Browse Source

Update DHCP to use data-xfer interface (not yet tested).

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
07dc294de8
8 changed files with 245 additions and 143 deletions
  1. 2
    2
      src/core/nvo.c
  2. 35
    28
      src/include/gpxe/dhcp.h
  3. 2
    0
      src/include/gpxe/xfer.h
  4. 2
    9
      src/net/dhcpopts.c
  5. 6
    5
      src/net/udp.c
  6. 187
    97
      src/net/udp/dhcp.c
  7. 1
    1
      src/tests/dhcptest.c
  8. 10
    1
      src/usr/dhcpmgmt.c

+ 2
- 2
src/core/nvo.c View File

194
 	return 0;
194
 	return 0;
195
 	
195
 	
196
  err:
196
  err:
197
-	free_dhcp_options ( nvo->options );
197
+	dhcpopt_put ( nvo->options );
198
 	nvo->options = NULL;
198
 	nvo->options = NULL;
199
 	return rc;
199
 	return rc;
200
 }
200
 }
208
 
208
 
209
 	if ( nvo->options ) {
209
 	if ( nvo->options ) {
210
 		unregister_dhcp_options ( nvo->options );
210
 		unregister_dhcp_options ( nvo->options );
211
-		free_dhcp_options ( nvo->options );
211
+		dhcpopt_put ( nvo->options );
212
 		nvo->options = NULL;
212
 		nvo->options = NULL;
213
 	}
213
 	}
214
 
214
 

+ 35
- 28
src/include/gpxe/dhcp.h View File

10
 #include <stdint.h>
10
 #include <stdint.h>
11
 #include <gpxe/list.h>
11
 #include <gpxe/list.h>
12
 #include <gpxe/in.h>
12
 #include <gpxe/in.h>
13
-#include <gpxe/udp.h>
14
-#include <gpxe/async.h>
15
-#include <gpxe/retry.h>
13
+#include <gpxe/refcnt.h>
14
+
15
+struct net_device;
16
+struct job_interface;
16
 
17
 
17
 /** BOOTP/DHCP server port */
18
 /** BOOTP/DHCP server port */
18
 #define BOOTPS_PORT 67
19
 #define BOOTPS_PORT 67
312
 
313
 
313
 /** A DHCP options block */
314
 /** A DHCP options block */
314
 struct dhcp_option_block {
315
 struct dhcp_option_block {
316
+	/** Reference counter */
317
+	struct refcnt refcnt;
315
 	/** List of option blocks */
318
 	/** List of option blocks */
316
 	struct list_head list;
319
 	struct list_head list;
317
 	/** Option block raw data */
320
 	/** Option block raw data */
413
 /** DHCP magic cookie */
416
 /** DHCP magic cookie */
414
 #define DHCP_MAGIC_COOKIE 0x63825363UL
417
 #define DHCP_MAGIC_COOKIE 0x63825363UL
415
 
418
 
419
+/** DHCP minimum packet length
420
+ *
421
+ * This is the mandated minimum packet length that a DHCP participant
422
+ * must be prepared to receive.
423
+ */
424
+#define DHCP_MIN_LEN 552
425
+
416
 /** DHCP packet option block fill order
426
 /** DHCP packet option block fill order
417
  *
427
  *
418
  * This is the order in which option blocks are filled when
428
  * This is the order in which option blocks are filled when
448
 	struct dhcp_option_block options[NUM_OPT_BLOCKS];
458
 	struct dhcp_option_block options[NUM_OPT_BLOCKS];
449
 };
459
 };
450
 
460
 
451
-struct udp_connection {};
452
-
453
-/** A DHCP session */
454
-struct dhcp_session {
455
-	/** UDP connection for this session */
456
-	struct udp_connection udp;
457
-
458
-	/** Network device being configured */
459
-	struct net_device *netdev;
460
-
461
-	/** Options obtained from server */
462
-	struct dhcp_option_block *options;
461
+/**
462
+ * Get reference to DHCP options block
463
+ *
464
+ * @v options		DHCP options block
465
+ * @ret options		DHCP options block
466
+ */
467
+static inline __attribute__ (( always_inline )) struct dhcp_option_block *
468
+dhcpopt_get ( struct dhcp_option_block *options ) {
469
+	ref_get ( &options->refcnt );
470
+	return options;
471
+}
463
 
472
 
464
-	/** State of the session
465
-	 *
466
-	 * This is a value for the @c DHCP_MESSAGE_TYPE option
467
-	 * (e.g. @c DHCPDISCOVER).
468
-	 */
469
-	int state;
470
-	/** Asynchronous operation for this DHCP session */
471
-	struct async async;
472
-	/** Retransmission timer */
473
-	struct retry_timer timer;
474
-};
473
+/**
474
+ * Drop reference to DHCP options block
475
+ *
476
+ * @v options		DHCP options block
477
+ */
478
+static inline __attribute__ (( always_inline )) void
479
+dhcpopt_put ( struct dhcp_option_block *options ) {
480
+	ref_put ( &options->refcnt );
481
+}
475
 
482
 
476
 extern unsigned long dhcp_num_option ( struct dhcp_option *option );
483
 extern unsigned long dhcp_num_option ( struct dhcp_option *option );
477
 extern void dhcp_ipv4_option ( struct dhcp_option *option,
484
 extern void dhcp_ipv4_option ( struct dhcp_option *option,
485
 extern void init_dhcp_options ( struct dhcp_option_block *options,
492
 extern void init_dhcp_options ( struct dhcp_option_block *options,
486
 				void *data, size_t max_len );
493
 				void *data, size_t max_len );
487
 extern struct dhcp_option_block * alloc_dhcp_options ( size_t max_len );
494
 extern struct dhcp_option_block * alloc_dhcp_options ( size_t max_len );
488
-extern void free_dhcp_options ( struct dhcp_option_block *options );
489
 extern struct dhcp_option *
495
 extern struct dhcp_option *
490
 set_dhcp_option ( struct dhcp_option_block *options, unsigned int tag,
496
 set_dhcp_option ( struct dhcp_option_block *options, unsigned int tag,
491
 		  const void *data, size_t len );
497
 		  const void *data, size_t len );
506
 				struct dhcp_packet *dhcppkt );
512
 				struct dhcp_packet *dhcppkt );
507
 extern int copy_dhcp_packet_options ( struct dhcp_packet *dhcppkt,
513
 extern int copy_dhcp_packet_options ( struct dhcp_packet *dhcppkt,
508
 				      struct dhcp_option_block *options );
514
 				      struct dhcp_option_block *options );
509
-extern int start_dhcp ( struct dhcp_session *dhcp, struct async *parent );
515
+extern int start_dhcp ( struct job_interface *job, struct net_device *netdev,
516
+			int (*register_options) ( struct dhcp_option_block * ));
510
 
517
 
511
 #endif /* _GPXE_DHCP_H */
518
 #endif /* _GPXE_DHCP_H */

+ 2
- 0
src/include/gpxe/xfer.h View File

115
 	struct sockaddr *src;
115
 	struct sockaddr *src;
116
 	/** Destination socket address, or NULL */
116
 	/** Destination socket address, or NULL */
117
 	struct sockaddr *dest;
117
 	struct sockaddr *dest;
118
+	/** Network device, or NULL */
119
+	struct net_device *netdev;
118
 };
120
 };
119
 
121
 
120
 /** Basis positions for seek() events */
122
 /** Basis positions for seek() events */

+ 2
- 9
src/net/dhcpopts.c View File

280
 		if ( options->priority > existing->priority )
280
 		if ( options->priority > existing->priority )
281
 			break;
281
 			break;
282
 	}
282
 	}
283
+	dhcpopt_get ( options );
283
 	list_add_tail ( &options->list, &existing->list );
284
 	list_add_tail ( &options->list, &existing->list );
284
 }
285
 }
285
 
286
 
290
  */
291
  */
291
 void unregister_dhcp_options ( struct dhcp_option_block *options ) {
292
 void unregister_dhcp_options ( struct dhcp_option_block *options ) {
292
 	list_del ( &options->list );
293
 	list_del ( &options->list );
294
+	dhcpopt_put ( options );
293
 }
295
 }
294
 
296
 
295
 /**
297
 /**
337
 	return options;
339
 	return options;
338
 }
340
 }
339
 
341
 
340
-/**
341
- * Free DHCP options block
342
- *
343
- * @v options		DHCP option block
344
- */
345
-void free_dhcp_options ( struct dhcp_option_block *options ) {
346
-	free ( options );
347
-}
348
-
349
 /**
342
 /**
350
  * Resize a DHCP option
343
  * Resize a DHCP option
351
  *
344
  *

+ 6
- 5
src/net/udp.c View File

183
  * @v iobuf		I/O buffer
183
  * @v iobuf		I/O buffer
184
  * @v src_port		Source port, or 0 to use default
184
  * @v src_port		Source port, or 0 to use default
185
  * @v dest		Destination address, or NULL to use default
185
  * @v dest		Destination address, or NULL to use default
186
+ * @v netdev		Network device, or NULL to use default
186
  * @ret rc		Return status code
187
  * @ret rc		Return status code
187
  */
188
  */
188
 static int udp_tx ( struct udp_connection *udp, struct io_buffer *iobuf,
189
 static int udp_tx ( struct udp_connection *udp, struct io_buffer *iobuf,
189
-		    unsigned int src_port, struct sockaddr_tcpip *dest ) {
190
+		    unsigned int src_port, struct sockaddr_tcpip *dest,
191
+		    struct net_device *netdev ) {
190
        	struct udp_header *udphdr;
192
        	struct udp_header *udphdr;
191
-	struct net_device *netdev = NULL;
192
 	size_t len;
193
 	size_t len;
193
 	int rc;
194
 	int rc;
194
 
195
 
195
-#warning "netdev?"
196
-
197
 	/* Check we can accommodate the header */
196
 	/* Check we can accommodate the header */
198
 	if ( ( rc = iob_ensure_headroom ( iobuf, UDP_MAX_HLEN ) ) != 0 ) {
197
 	if ( ( rc = iob_ensure_headroom ( iobuf, UDP_MAX_HLEN ) ) != 0 ) {
199
 		free_iob ( iobuf );
198
 		free_iob ( iobuf );
394
 		container_of ( xfer, struct udp_connection, xfer );
393
 		container_of ( xfer, struct udp_connection, xfer );
395
 	struct sockaddr_tcpip *src;
394
 	struct sockaddr_tcpip *src;
396
 	struct sockaddr_tcpip *dest = NULL;
395
 	struct sockaddr_tcpip *dest = NULL;
396
+	struct net_device *netdev = NULL;
397
 	unsigned int src_port = 0;
397
 	unsigned int src_port = 0;
398
 
398
 
399
 	/* Apply xfer metadata */
399
 	/* Apply xfer metadata */
402
 		if ( src )
402
 		if ( src )
403
 			src_port = src->st_port;
403
 			src_port = src->st_port;
404
 		dest = ( struct sockaddr_tcpip * ) meta->dest;
404
 		dest = ( struct sockaddr_tcpip * ) meta->dest;
405
+		netdev = meta->netdev;
405
 	}
406
 	}
406
 
407
 
407
 	/* Transmit data, if possible */
408
 	/* Transmit data, if possible */
408
-	udp_tx ( udp, iobuf, src_port, dest );
409
+	udp_tx ( udp, iobuf, src_port, dest, netdev );
409
 
410
 
410
 	return 0;
411
 	return 0;
411
 }
412
 }

+ 187
- 97
src/net/udp/dhcp.c View File

17
  */
17
  */
18
 
18
 
19
 #include <string.h>
19
 #include <string.h>
20
+#include <stdlib.h>
20
 #include <errno.h>
21
 #include <errno.h>
21
 #include <assert.h>
22
 #include <assert.h>
22
 #include <byteswap.h>
23
 #include <byteswap.h>
23
 #include <gpxe/if_ether.h>
24
 #include <gpxe/if_ether.h>
24
 #include <gpxe/netdevice.h>
25
 #include <gpxe/netdevice.h>
25
-#include <gpxe/udp.h>
26
+#include <gpxe/xfer.h>
27
+#include <gpxe/open.h>
28
+#include <gpxe/job.h>
29
+#include <gpxe/retry.h>
26
 #include <gpxe/dhcp.h>
30
 #include <gpxe/dhcp.h>
27
 
31
 
28
 /** @file
32
 /** @file
387
 /**
391
 /**
388
  * Parse DHCP packet and construct DHCP options block
392
  * Parse DHCP packet and construct DHCP options block
389
  *
393
  *
390
- * @v dhcp		DHCP session
391
  * @v dhcphdr		DHCP packet
394
  * @v dhcphdr		DHCP packet
392
  * @v len		Length of DHCP packet
395
  * @v len		Length of DHCP packet
393
  * @ret options		DHCP options block, or NULL
396
  * @ret options		DHCP options block, or NULL
407
  * options block; it is the responsibility of the caller to eventually
410
  * options block; it is the responsibility of the caller to eventually
408
  * free this memory.
411
  * free this memory.
409
  */
412
  */
410
-static struct dhcp_option_block * dhcp_parse ( struct dhcp_session *dhcp,
411
-					       struct dhcphdr *dhcphdr,
413
+static struct dhcp_option_block * dhcp_parse ( const struct dhcphdr *dhcphdr,
412
 					       size_t len ) {
414
 					       size_t len ) {
413
 	struct dhcp_option_block *options;
415
 	struct dhcp_option_block *options;
414
 	size_t options_len;
416
 	size_t options_len;
443
 	/* Allocate empty options block of required size */
445
 	/* Allocate empty options block of required size */
444
 	options = alloc_dhcp_options ( options_len );
446
 	options = alloc_dhcp_options ( options_len );
445
 	if ( ! options ) {
447
 	if ( ! options ) {
446
-		DBGC ( dhcp, "DHCP %p could not allocate %d-byte option "
447
-		       "block\n", dhcp, options_len );
448
+		DBG ( "DHCP could not allocate %d-byte option block\n",
449
+		      options_len );
448
 		return NULL;
450
 		return NULL;
449
 	}
451
 	}
450
 	
452
 	
488
  *
490
  *
489
  */
491
  */
490
 
492
 
491
-static inline struct dhcp_session *
492
-udp_to_dhcp ( struct udp_connection *conn ) {
493
-	return container_of ( conn, struct dhcp_session, udp );
494
-}
493
+/** A DHCP session */
494
+struct dhcp_session {
495
+	/** Reference counter */
496
+	struct refcnt refcnt;
497
+	/** Job control interface */
498
+	struct job_interface job;
499
+	/** Data transfer interface */
500
+	struct xfer_interface xfer;
501
+
502
+	/** Network device being configured */
503
+	struct net_device *netdev;
504
+	/** Option block registration routine */
505
+	int ( * register_options ) ( struct dhcp_option_block *options );
506
+
507
+	/** State of the session
508
+	 *
509
+	 * This is a value for the @c DHCP_MESSAGE_TYPE option
510
+	 * (e.g. @c DHCPDISCOVER).
511
+	 */
512
+	int state;
513
+	/** Options obtained from server */
514
+	struct dhcp_option_block *options;
515
+	/** Retransmission timer */
516
+	struct retry_timer timer;
517
+};
518
+
519
+/**
520
+ * Free DHCP session
521
+ *
522
+ * @v refcnt		Reference counter
523
+ */
524
+static void dhcp_free ( struct refcnt *refcnt ) {
525
+	struct dhcp_session *dhcp =
526
+		container_of ( refcnt, struct dhcp_session, refcnt );
495
 
527
 
496
-#if 0
528
+	netdev_put ( dhcp->netdev );
529
+	dhcpopt_put ( dhcp->options );
530
+	free ( dhcp );
531
+}
497
 
532
 
498
 /**
533
 /**
499
  * Mark DHCP session as complete
534
  * Mark DHCP session as complete
501
  * @v dhcp		DHCP session
536
  * @v dhcp		DHCP session
502
  * @v rc		Return status code
537
  * @v rc		Return status code
503
  */
538
  */
504
-static void dhcp_done ( struct dhcp_session *dhcp, int rc ) {
539
+static void dhcp_finished ( struct dhcp_session *dhcp, int rc ) {
505
 
540
 
506
-	/* Free up options if we failed */
507
-	if ( rc != 0 ) {
508
-		if ( dhcp->options ) {
509
-			free_dhcp_options ( dhcp->options );
510
-			dhcp->options = NULL;
511
-		}
512
-	}
541
+	/* Block futher incoming messages */
542
+	job_nullify ( &dhcp->job );
543
+	xfer_nullify ( &dhcp->xfer );
513
 
544
 
514
 	/* Stop retry timer */
545
 	/* Stop retry timer */
515
 	stop_timer ( &dhcp->timer );
546
 	stop_timer ( &dhcp->timer );
516
 
547
 
517
-	/* Close UDP connection */
518
-	udp_close ( &dhcp->udp );
519
-
520
-	/* Mark async operation as complete */
521
-	async_done ( &dhcp->async, rc );
548
+	/* Free resources and close interfaces */
549
+	xfer_close ( &dhcp->xfer, rc );
550
+	job_done ( &dhcp->job, rc );
522
 }
551
 }
523
 
552
 
524
-/** Address for transmitting DHCP requests */
525
-static union {
526
-	struct sockaddr_tcpip st;
527
-	struct sockaddr_in sin;
528
-} sa_dhcp_server = {
529
-	.sin = {
530
-		.sin_family = AF_INET,
531
-		.sin_addr.s_addr = INADDR_BROADCAST,
532
-		.sin_port = htons ( BOOTPS_PORT ),
533
-	},
534
-};
553
+/****************************************************************************
554
+ *
555
+ * Data transfer interface
556
+ *
557
+ */
535
 
558
 
536
 /**
559
 /**
537
  * Transmit DHCP request
560
  * Transmit DHCP request
538
  *
561
  *
539
- * @v conn		UDP connection
540
- * @v buf		Temporary data buffer
541
- * @v len		Length of temporary data buffer
562
+ * @v dhcp		DHCP session
542
  * @ret rc		Return status code
563
  * @ret rc		Return status code
543
  */
564
  */
544
-static int dhcp_senddata ( struct udp_connection *conn,
545
-			   void *buf, size_t len ) {
546
-	struct dhcp_session *dhcp = udp_to_dhcp ( conn );
565
+static int dhcp_send_request ( struct dhcp_session *dhcp ) {
566
+	struct xfer_metadata meta = {
567
+		.netdev = dhcp->netdev,
568
+	};
547
 	struct dhcp_packet dhcppkt;
569
 	struct dhcp_packet dhcppkt;
570
+	struct io_buffer *iobuf;
548
 	int rc;
571
 	int rc;
549
 	
572
 	
550
 	DBGC ( dhcp, "DHCP %p transmitting %s\n",
573
 	DBGC ( dhcp, "DHCP %p transmitting %s\n",
553
 	assert ( ( dhcp->state == DHCPDISCOVER ) ||
576
 	assert ( ( dhcp->state == DHCPDISCOVER ) ||
554
 		 ( dhcp->state == DHCPREQUEST ) );
577
 		 ( dhcp->state == DHCPREQUEST ) );
555
 
578
 
579
+	/* Start retry timer.  Do this first so that failures to
580
+	 * transmit will be retried.
581
+	 */
582
+	start_timer ( &dhcp->timer );
583
+
584
+	/* Allocate buffer for packet */
585
+	iobuf = xfer_alloc_iob ( &dhcp->xfer, DHCP_MIN_LEN );
586
+	if ( ! iobuf )
587
+		return -ENOMEM;
588
+
556
 	/* Create DHCP packet in temporary buffer */
589
 	/* Create DHCP packet in temporary buffer */
557
-	if ( ( rc = create_dhcp_packet ( dhcp->netdev, dhcp->state, buf, len,
590
+	if ( ( rc = create_dhcp_packet ( dhcp->netdev, dhcp->state,
591
+					 iobuf->data, iob_tailroom ( iobuf ),
558
 					 &dhcppkt ) ) != 0 ) {
592
 					 &dhcppkt ) ) != 0 ) {
559
 		DBGC ( dhcp, "DHCP %p could not create DHCP packet: %s\n",
593
 		DBGC ( dhcp, "DHCP %p could not create DHCP packet: %s\n",
560
 		       dhcp, strerror ( rc ) );
594
 		       dhcp, strerror ( rc ) );
561
-		return rc;
595
+		goto done;
562
 	}
596
 	}
563
 
597
 
564
 	/* Copy in options common to all requests */
598
 	/* Copy in options common to all requests */
566
 					       &dhcp_request_options ) ) != 0){
600
 					       &dhcp_request_options ) ) != 0){
567
 		DBGC ( dhcp, "DHCP %p could not set common DHCP options: %s\n",
601
 		DBGC ( dhcp, "DHCP %p could not set common DHCP options: %s\n",
568
 		       dhcp, strerror ( rc ) );
602
 		       dhcp, strerror ( rc ) );
569
-		return rc;
603
+		goto done;
570
 	}
604
 	}
571
 
605
 
572
 	/* Copy any required options from previous server repsonse */
606
 	/* Copy any required options from previous server repsonse */
576
 					    DHCP_SERVER_IDENTIFIER ) ) != 0 ) {
610
 					    DHCP_SERVER_IDENTIFIER ) ) != 0 ) {
577
 			DBGC ( dhcp, "DHCP %p could not set server identifier "
611
 			DBGC ( dhcp, "DHCP %p could not set server identifier "
578
 			       "option: %s\n", dhcp, strerror ( rc ) );
612
 			       "option: %s\n", dhcp, strerror ( rc ) );
579
-			return rc;
613
+			goto done;
580
 		}
614
 		}
581
 		if ( ( rc = copy_dhcp_packet_option ( &dhcppkt, dhcp->options,
615
 		if ( ( rc = copy_dhcp_packet_option ( &dhcppkt, dhcp->options,
582
 					    DHCP_EB_YIADDR,
616
 					    DHCP_EB_YIADDR,
583
 					    DHCP_REQUESTED_ADDRESS ) ) != 0 ) {
617
 					    DHCP_REQUESTED_ADDRESS ) ) != 0 ) {
584
 			DBGC ( dhcp, "DHCP %p could not set requested address "
618
 			DBGC ( dhcp, "DHCP %p could not set requested address "
585
 			       "option: %s\n", dhcp, strerror ( rc ) );
619
 			       "option: %s\n", dhcp, strerror ( rc ) );
586
-			return rc;
620
+			goto done;
587
 		}
621
 		}
588
 	}
622
 	}
589
 
623
 
590
 	/* Transmit the packet */
624
 	/* Transmit the packet */
591
-	if ( ( rc = udp_sendto_via ( conn, &sa_dhcp_server.st, dhcp->netdev,
592
-				     dhcppkt.dhcphdr, dhcppkt.len ) ) != 0 ) {
625
+	iob_put ( iobuf, dhcppkt.len );
626
+	rc = xfer_deliver_iob_meta ( &dhcp->xfer, iobuf, &meta );
627
+	iobuf = NULL;
628
+	if ( rc != 0 ) {
593
 		DBGC ( dhcp, "DHCP %p could not transmit UDP packet: %s\n",
629
 		DBGC ( dhcp, "DHCP %p could not transmit UDP packet: %s\n",
594
 		       dhcp, strerror ( rc ) );
630
 		       dhcp, strerror ( rc ) );
595
-		return rc;
631
+		goto done;
596
 	}
632
 	}
597
 
633
 
598
-	return 0;
599
-}
600
-
601
-/**
602
- * Transmit DHCP request
603
- *
604
- * @v dhcp		DHCP session
605
- */
606
-static void dhcp_send_request ( struct dhcp_session *dhcp ) {
607
-	start_timer ( &dhcp->timer );
608
-	udp_senddata ( &dhcp->udp );
634
+ done:
635
+	free_iob ( iobuf );
636
+	return rc;
609
 }
637
 }
610
 
638
 
611
 /**
639
 /**
619
 		container_of ( timer, struct dhcp_session, timer );
647
 		container_of ( timer, struct dhcp_session, timer );
620
 
648
 
621
 	if ( fail ) {
649
 	if ( fail ) {
622
-		dhcp_done ( dhcp, -ETIMEDOUT );
650
+		dhcp_finished ( dhcp, -ETIMEDOUT );
623
 	} else {
651
 	} else {
624
 		dhcp_send_request ( dhcp );
652
 		dhcp_send_request ( dhcp );
625
 	}
653
 	}
628
 /**
656
 /**
629
  * Receive new data
657
  * Receive new data
630
  *
658
  *
631
- * @v udp		UDP connection
659
+ * @v xfer 		Data transfer interface
660
+ * @v iobuf		I/O buffer
632
  * @v data		Received data
661
  * @v data		Received data
633
  * @v len		Length of received data
662
  * @v len		Length of received data
634
- * @v st_src		Partially-filled source address
635
- * @v st_dest		Partially-filled destination address
663
+ * @ret rc		Return status code
636
  */
664
  */
637
-static int dhcp_newdata ( struct udp_connection *conn, void *data, size_t len,
638
-			  struct sockaddr_tcpip *st_src __unused,
639
-			  struct sockaddr_tcpip *st_dest __unused ) {
640
-	struct dhcp_session *dhcp = udp_to_dhcp ( conn );
641
-	struct dhcphdr *dhcphdr = data;
665
+static int dhcp_deliver_raw ( struct xfer_interface *xfer,
666
+			      const void *data, size_t len ) {
667
+	struct dhcp_session *dhcp =
668
+		container_of ( xfer, struct dhcp_session, xfer );
669
+	const struct dhcphdr *dhcphdr = data;
642
 	struct dhcp_option_block *options;
670
 	struct dhcp_option_block *options;
643
 	unsigned int msgtype;
671
 	unsigned int msgtype;
644
 
672
 
651
 	};
679
 	};
652
 
680
 
653
 	/* Parse packet and create options structure */
681
 	/* Parse packet and create options structure */
654
-	options = dhcp_parse ( dhcp, dhcphdr, len );
682
+	options = dhcp_parse ( dhcphdr, len );
655
 	if ( ! options ) {
683
 	if ( ! options ) {
656
 		DBGC ( dhcp, "DHCP %p could not parse DHCP packet\n", dhcp );
684
 		DBGC ( dhcp, "DHCP %p could not parse DHCP packet\n", dhcp );
657
 		return -EINVAL;
685
 		return -EINVAL;
682
 	/* Stop timer and update stored options */
710
 	/* Stop timer and update stored options */
683
 	stop_timer ( &dhcp->timer );
711
 	stop_timer ( &dhcp->timer );
684
 	if ( dhcp->options )
712
 	if ( dhcp->options )
685
-		free_dhcp_options ( dhcp->options );
713
+		dhcpopt_put ( dhcp->options );
686
 	dhcp->options = options;
714
 	dhcp->options = options;
687
 
715
 
688
 	/* Transmit next packet, or terminate session */
716
 	/* Transmit next packet, or terminate session */
689
 	if ( dhcp->state < DHCPACK ) {
717
 	if ( dhcp->state < DHCPACK ) {
690
 		dhcp_send_request ( dhcp );
718
 		dhcp_send_request ( dhcp );
691
 	} else {
719
 	} else {
692
-		dhcp_done ( dhcp, 0 );
720
+		dhcp->register_options ( dhcp->options );
721
+		dhcp_finished ( dhcp, 0 );
693
 	}
722
 	}
694
 	return 0;
723
 	return 0;
695
 
724
 
696
  out_discard:
725
  out_discard:
697
-	free_dhcp_options ( options );
726
+	dhcpopt_put ( options );
698
 	return 0;
727
 	return 0;
699
 }
728
 }
700
 
729
 
701
-/** DHCP UDP operations */
702
-static struct udp_operations dhcp_udp_operations = {
703
-	.senddata	= dhcp_senddata,
704
-	.newdata	= dhcp_newdata,
730
+/** DHCP data transfer interface operations */
731
+static struct xfer_interface_operations dhcp_xfer_operations = {
732
+	.close		= ignore_xfer_close,
733
+	.vredirect	= xfer_vopen,
734
+	.request	= ignore_xfer_request,
735
+	.seek		= ignore_xfer_seek,
736
+	.deliver_iob	= xfer_deliver_as_raw,
737
+	.deliver_raw	= dhcp_deliver_raw,
705
 };
738
 };
706
 
739
 
740
+/****************************************************************************
741
+ *
742
+ * Job control interface
743
+ *
744
+ */
745
+
707
 /**
746
 /**
708
- * Initiate DHCP on a network interface
747
+ * Handle kill() event received via job control interface
709
  *
748
  *
710
- * @v dhcp		DHCP session
711
- * @v parent		Parent asynchronous operation
749
+ * @v job		DHCP job control interface
750
+ */
751
+static void dhcp_job_kill ( struct job_interface *job ) {
752
+	struct dhcp_session *dhcp =
753
+		container_of ( job, struct dhcp_session, job );
754
+
755
+	/* Terminate DHCP session */
756
+	dhcp_finished ( dhcp, -ECANCELED );
757
+}
758
+
759
+/** DHCP job control interface operations */
760
+static struct job_interface_operations dhcp_job_operations = {
761
+	.start		= ignore_job_start,
762
+	.done		= ignore_job_done,
763
+	.kill		= dhcp_job_kill,
764
+	.progress	= ignore_job_progress,
765
+};
766
+
767
+/****************************************************************************
768
+ *
769
+ * Instantiator
770
+ *
771
+ */
772
+
773
+/**
774
+ * Start DHCP on a network device
775
+ *
776
+ * @v job		Job control interface
777
+ * @v netdev		Network device
778
+ * @v register_options	DHCP option block registration routine
712
  * @ret rc		Return status code
779
  * @ret rc		Return status code
713
  *
780
  *
714
- * If the DHCP operation completes successfully, the
715
- * dhcp_session::options field will be filled in with the resulting
716
- * options block.  The caller takes responsibility for eventually
717
- * calling free_dhcp_options().
781
+ * Starts DHCP on the specified network device.  If successful, the @c
782
+ * register_options() routine will be called with the acquired
783
+ * options.
718
  */
784
  */
719
-int start_dhcp ( struct dhcp_session *dhcp, struct async *parent ) {
785
+int start_dhcp ( struct job_interface *job, struct net_device *netdev,
786
+		 int ( * register_options ) ( struct dhcp_option_block * ) ) {
787
+	static struct sockaddr_in server = {
788
+		.sin_family = AF_INET,
789
+		.sin_addr.s_addr = INADDR_BROADCAST,
790
+		.sin_port = htons ( BOOTPS_PORT ),
791
+	};
792
+	static struct sockaddr_in client = {
793
+		.sin_family = AF_INET,
794
+		.sin_port = htons ( BOOTPC_PORT ),
795
+	};
796
+	struct dhcp_session *dhcp;
720
 	int rc;
797
 	int rc;
721
 
798
 
722
-	/* Initialise DHCP session */
723
-	dhcp->udp.udp_op = &dhcp_udp_operations;
799
+	/* Allocate and initialise structure */
800
+	dhcp = malloc ( sizeof ( *dhcp ) );
801
+	if ( ! dhcp )
802
+		return -ENOMEM;
803
+	memset ( dhcp, 0, sizeof ( *dhcp ) );
804
+	dhcp->refcnt.free = dhcp_free;
805
+	job_init ( &dhcp->job, &dhcp_job_operations, &dhcp->refcnt );
806
+	xfer_init ( &dhcp->xfer, &dhcp_xfer_operations, &dhcp->refcnt );
807
+	dhcp->netdev = netdev_get ( netdev );
808
+	dhcp->register_options = register_options;
724
 	dhcp->timer.expired = dhcp_timer_expired;
809
 	dhcp->timer.expired = dhcp_timer_expired;
725
-	dhcp->state = DHCPDISCOVER;
726
 
810
 
727
-	/* Bind to local port */
728
-	if ( ( rc = udp_open ( &dhcp->udp, htons ( BOOTPC_PORT ) ) ) != 0 )
729
-		return rc;
811
+	/* Instantiate child objects and attach to our interfaces */
812
+	if ( ( rc = xfer_open_socket ( &dhcp->xfer, SOCK_DGRAM,
813
+				       ( struct sockaddr * ) &server,
814
+				       ( struct sockaddr * ) &client ) ) != 0 )
815
+		goto err;
730
 
816
 
731
-	/* Proof of concept: just send a single DHCPDISCOVER */
732
-	dhcp_send_request ( dhcp );
817
+	/* Start timer to initiate initial DHCPREQUEST */
818
+	start_timer ( &dhcp->timer );
733
 
819
 
734
-	async_init ( &dhcp->async, &default_async_operations, parent );
820
+	/* Attach parent interface, mortalise self, and return */
821
+	job_plug_plug ( &dhcp->job, job );
822
+	ref_put ( &dhcp->refcnt );
735
 	return 0;
823
 	return 0;
736
-}
737
 
824
 
738
-
739
-#endif
825
+ err:
826
+	dhcp_finished ( dhcp, rc );
827
+	ref_put ( &dhcp->refcnt );
828
+	return rc;
829
+}

+ 1
- 1
src/tests/dhcptest.c View File

261
  out:
261
  out:
262
 	/* Unregister and free DHCP options */
262
 	/* Unregister and free DHCP options */
263
 	unregister_dhcp_options ( dhcp.options );
263
 	unregister_dhcp_options ( dhcp.options );
264
-	free_dhcp_options ( dhcp.options );
264
+	dhcpopt_put ( dhcp.options );
265
  out_no_options:
265
  out_no_options:
266
  out_no_del_ipv4:
266
  out_no_del_ipv4:
267
 	return rc;
267
 	return rc;

+ 10
- 1
src/usr/dhcpmgmt.c View File

18
 
18
 
19
 #include <string.h>
19
 #include <string.h>
20
 #include <stdio.h>
20
 #include <stdio.h>
21
+#include <errno.h>
21
 #include <byteswap.h>
22
 #include <byteswap.h>
22
 #include <gpxe/in.h>
23
 #include <gpxe/in.h>
23
 #include <gpxe/ip.h>
24
 #include <gpxe/ip.h>
34
  *
35
  *
35
  */
36
  */
36
 
37
 
38
+int dhcp ( struct net_device *netdev ) {
39
+	return -ENOTSUP;
40
+}
41
+
42
+#if 0
43
+
37
 /* Avoid dragging in dns.o */
44
 /* Avoid dragging in dns.o */
38
 struct sockaddr_tcpip nameserver;
45
 struct sockaddr_tcpip nameserver;
39
 
46
 
63
 	/* Free up any previously-acquired options */
70
 	/* Free up any previously-acquired options */
64
 	if ( dhcp_options ) {
71
 	if ( dhcp_options ) {
65
 		unregister_dhcp_options ( dhcp_options );
72
 		unregister_dhcp_options ( dhcp_options );
66
-		free_dhcp_options ( dhcp_options );
73
+		dhcpopt_put ( dhcp_options );
67
 		dhcp_options = NULL;
74
 		dhcp_options = NULL;
68
 	}
75
 	}
69
 
76
 
108
 
115
 
109
 	return 0;
116
 	return 0;
110
 }
117
 }
118
+
119
+#endif

Loading…
Cancel
Save