Parcourir la source

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

tags/v0.9.3
Michael Brown il y a 17 ans
Parent
révision
07dc294de8
8 fichiers modifiés avec 245 ajouts et 143 suppressions
  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 Voir le fichier

@@ -194,7 +194,7 @@ int nvo_register ( struct nvo_block *nvo ) {
194 194
 	return 0;
195 195
 	
196 196
  err:
197
-	free_dhcp_options ( nvo->options );
197
+	dhcpopt_put ( nvo->options );
198 198
 	nvo->options = NULL;
199 199
 	return rc;
200 200
 }
@@ -208,7 +208,7 @@ void nvo_unregister ( struct nvo_block *nvo ) {
208 208
 
209 209
 	if ( nvo->options ) {
210 210
 		unregister_dhcp_options ( nvo->options );
211
-		free_dhcp_options ( nvo->options );
211
+		dhcpopt_put ( nvo->options );
212 212
 		nvo->options = NULL;
213 213
 	}
214 214
 

+ 35
- 28
src/include/gpxe/dhcp.h Voir le fichier

@@ -10,9 +10,10 @@
10 10
 #include <stdint.h>
11 11
 #include <gpxe/list.h>
12 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 18
 /** BOOTP/DHCP server port */
18 19
 #define BOOTPS_PORT 67
@@ -312,6 +313,8 @@ struct dhcp_option {
312 313
 
313 314
 /** A DHCP options block */
314 315
 struct dhcp_option_block {
316
+	/** Reference counter */
317
+	struct refcnt refcnt;
315 318
 	/** List of option blocks */
316 319
 	struct list_head list;
317 320
 	/** Option block raw data */
@@ -413,6 +416,13 @@ struct dhcphdr {
413 416
 /** DHCP magic cookie */
414 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 426
 /** DHCP packet option block fill order
417 427
  *
418 428
  * This is the order in which option blocks are filled when
@@ -448,30 +458,27 @@ struct dhcp_packet {
448 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 483
 extern unsigned long dhcp_num_option ( struct dhcp_option *option );
477 484
 extern void dhcp_ipv4_option ( struct dhcp_option *option,
@@ -485,7 +492,6 @@ extern void unregister_dhcp_options ( struct dhcp_option_block *options );
485 492
 extern void init_dhcp_options ( struct dhcp_option_block *options,
486 493
 				void *data, size_t max_len );
487 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 495
 extern struct dhcp_option *
490 496
 set_dhcp_option ( struct dhcp_option_block *options, unsigned int tag,
491 497
 		  const void *data, size_t len );
@@ -506,6 +512,7 @@ extern int create_dhcp_packet ( struct net_device *netdev, uint8_t msgtype,
506 512
 				struct dhcp_packet *dhcppkt );
507 513
 extern int copy_dhcp_packet_options ( struct dhcp_packet *dhcppkt,
508 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 518
 #endif /* _GPXE_DHCP_H */

+ 2
- 0
src/include/gpxe/xfer.h Voir le fichier

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

+ 2
- 9
src/net/dhcpopts.c Voir le fichier

@@ -280,6 +280,7 @@ void register_dhcp_options ( struct dhcp_option_block *options ) {
280 280
 		if ( options->priority > existing->priority )
281 281
 			break;
282 282
 	}
283
+	dhcpopt_get ( options );
283 284
 	list_add_tail ( &options->list, &existing->list );
284 285
 }
285 286
 
@@ -290,6 +291,7 @@ void register_dhcp_options ( struct dhcp_option_block *options ) {
290 291
  */
291 292
 void unregister_dhcp_options ( struct dhcp_option_block *options ) {
292 293
 	list_del ( &options->list );
294
+	dhcpopt_put ( options );
293 295
 }
294 296
 
295 297
 /**
@@ -337,15 +339,6 @@ struct dhcp_option_block * alloc_dhcp_options ( size_t max_len ) {
337 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 343
  * Resize a DHCP option
351 344
  *

+ 6
- 5
src/net/udp.c Voir le fichier

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

+ 187
- 97
src/net/udp/dhcp.c Voir le fichier

@@ -17,12 +17,16 @@
17 17
  */
18 18
 
19 19
 #include <string.h>
20
+#include <stdlib.h>
20 21
 #include <errno.h>
21 22
 #include <assert.h>
22 23
 #include <byteswap.h>
23 24
 #include <gpxe/if_ether.h>
24 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 30
 #include <gpxe/dhcp.h>
27 31
 
28 32
 /** @file
@@ -387,7 +391,6 @@ static void merge_dhcp_field ( struct dhcp_option_block *options,
387 391
 /**
388 392
  * Parse DHCP packet and construct DHCP options block
389 393
  *
390
- * @v dhcp		DHCP session
391 394
  * @v dhcphdr		DHCP packet
392 395
  * @v len		Length of DHCP packet
393 396
  * @ret options		DHCP options block, or NULL
@@ -407,8 +410,7 @@ static void merge_dhcp_field ( struct dhcp_option_block *options,
407 410
  * options block; it is the responsibility of the caller to eventually
408 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 414
 					       size_t len ) {
413 415
 	struct dhcp_option_block *options;
414 416
 	size_t options_len;
@@ -443,8 +445,8 @@ static struct dhcp_option_block * dhcp_parse ( struct dhcp_session *dhcp,
443 445
 	/* Allocate empty options block of required size */
444 446
 	options = alloc_dhcp_options ( options_len );
445 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 450
 		return NULL;
449 451
 	}
450 452
 	
@@ -488,12 +490,45 @@ static struct dhcp_option_block * dhcp_parse ( struct dhcp_session *dhcp,
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 534
  * Mark DHCP session as complete
@@ -501,50 +536,38 @@ udp_to_dhcp ( struct udp_connection *conn ) {
501 536
  * @v dhcp		DHCP session
502 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 545
 	/* Stop retry timer */
515 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 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 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 569
 	struct dhcp_packet dhcppkt;
570
+	struct io_buffer *iobuf;
548 571
 	int rc;
549 572
 	
550 573
 	DBGC ( dhcp, "DHCP %p transmitting %s\n",
@@ -553,12 +576,23 @@ static int dhcp_senddata ( struct udp_connection *conn,
553 576
 	assert ( ( dhcp->state == DHCPDISCOVER ) ||
554 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 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 592
 					 &dhcppkt ) ) != 0 ) {
559 593
 		DBGC ( dhcp, "DHCP %p could not create DHCP packet: %s\n",
560 594
 		       dhcp, strerror ( rc ) );
561
-		return rc;
595
+		goto done;
562 596
 	}
563 597
 
564 598
 	/* Copy in options common to all requests */
@@ -566,7 +600,7 @@ static int dhcp_senddata ( struct udp_connection *conn,
566 600
 					       &dhcp_request_options ) ) != 0){
567 601
 		DBGC ( dhcp, "DHCP %p could not set common DHCP options: %s\n",
568 602
 		       dhcp, strerror ( rc ) );
569
-		return rc;
603
+		goto done;
570 604
 	}
571 605
 
572 606
 	/* Copy any required options from previous server repsonse */
@@ -576,36 +610,30 @@ static int dhcp_senddata ( struct udp_connection *conn,
576 610
 					    DHCP_SERVER_IDENTIFIER ) ) != 0 ) {
577 611
 			DBGC ( dhcp, "DHCP %p could not set server identifier "
578 612
 			       "option: %s\n", dhcp, strerror ( rc ) );
579
-			return rc;
613
+			goto done;
580 614
 		}
581 615
 		if ( ( rc = copy_dhcp_packet_option ( &dhcppkt, dhcp->options,
582 616
 					    DHCP_EB_YIADDR,
583 617
 					    DHCP_REQUESTED_ADDRESS ) ) != 0 ) {
584 618
 			DBGC ( dhcp, "DHCP %p could not set requested address "
585 619
 			       "option: %s\n", dhcp, strerror ( rc ) );
586
-			return rc;
620
+			goto done;
587 621
 		}
588 622
 	}
589 623
 
590 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 629
 		DBGC ( dhcp, "DHCP %p could not transmit UDP packet: %s\n",
594 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,7 +647,7 @@ static void dhcp_timer_expired ( struct retry_timer *timer, int fail ) {
619 647
 		container_of ( timer, struct dhcp_session, timer );
620 648
 
621 649
 	if ( fail ) {
622
-		dhcp_done ( dhcp, -ETIMEDOUT );
650
+		dhcp_finished ( dhcp, -ETIMEDOUT );
623 651
 	} else {
624 652
 		dhcp_send_request ( dhcp );
625 653
 	}
@@ -628,17 +656,17 @@ static void dhcp_timer_expired ( struct retry_timer *timer, int fail ) {
628 656
 /**
629 657
  * Receive new data
630 658
  *
631
- * @v udp		UDP connection
659
+ * @v xfer 		Data transfer interface
660
+ * @v iobuf		I/O buffer
632 661
  * @v data		Received data
633 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 670
 	struct dhcp_option_block *options;
643 671
 	unsigned int msgtype;
644 672
 
@@ -651,7 +679,7 @@ static int dhcp_newdata ( struct udp_connection *conn, void *data, size_t len,
651 679
 	};
652 680
 
653 681
 	/* Parse packet and create options structure */
654
-	options = dhcp_parse ( dhcp, dhcphdr, len );
682
+	options = dhcp_parse ( dhcphdr, len );
655 683
 	if ( ! options ) {
656 684
 		DBGC ( dhcp, "DHCP %p could not parse DHCP packet\n", dhcp );
657 685
 		return -EINVAL;
@@ -682,58 +710,120 @@ static int dhcp_newdata ( struct udp_connection *conn, void *data, size_t len,
682 710
 	/* Stop timer and update stored options */
683 711
 	stop_timer ( &dhcp->timer );
684 712
 	if ( dhcp->options )
685
-		free_dhcp_options ( dhcp->options );
713
+		dhcpopt_put ( dhcp->options );
686 714
 	dhcp->options = options;
687 715
 
688 716
 	/* Transmit next packet, or terminate session */
689 717
 	if ( dhcp->state < DHCPACK ) {
690 718
 		dhcp_send_request ( dhcp );
691 719
 	} else {
692
-		dhcp_done ( dhcp, 0 );
720
+		dhcp->register_options ( dhcp->options );
721
+		dhcp_finished ( dhcp, 0 );
693 722
 	}
694 723
 	return 0;
695 724
 
696 725
  out_discard:
697
-	free_dhcp_options ( options );
726
+	dhcpopt_put ( options );
698 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 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 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 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 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 Voir le fichier

@@ -261,7 +261,7 @@ int test_dhcp ( struct net_device *netdev ) {
261 261
  out:
262 262
 	/* Unregister and free DHCP options */
263 263
 	unregister_dhcp_options ( dhcp.options );
264
-	free_dhcp_options ( dhcp.options );
264
+	dhcpopt_put ( dhcp.options );
265 265
  out_no_options:
266 266
  out_no_del_ipv4:
267 267
 	return rc;

+ 10
- 1
src/usr/dhcpmgmt.c Voir le fichier

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

Chargement…
Annuler
Enregistrer