Ver código fonte

Add ProxyDHCP support.

tags/v0.9.3
Michael Brown 17 anos atrás
pai
commit
0becbf5fba
2 arquivos alterados com 59 adições e 26 exclusões
  1. 5
    1
      src/include/gpxe/dhcp.h
  2. 54
    25
      src/net/udp/dhcp.c

+ 5
- 1
src/include/gpxe/dhcp.h Ver arquivo

@@ -12,6 +12,7 @@
12 12
 #include <gpxe/in.h>
13 13
 #include <gpxe/refcnt.h>
14 14
 #include <gpxe/tables.h>
15
+#include <latch.h>
15 16
 
16 17
 struct net_device;
17 18
 struct job_interface;
@@ -505,13 +506,16 @@ dhcpopt_get ( struct dhcp_option_block *options ) {
505 506
 /**
506 507
  * Drop reference to DHCP options block
507 508
  *
508
- * @v options		DHCP options block
509
+ * @v options		DHCP options block, or NULL
509 510
  */
510 511
 static inline __attribute__ (( always_inline )) void
511 512
 dhcpopt_put ( struct dhcp_option_block *options ) {
512 513
 	ref_put ( &options->refcnt );
513 514
 }
514 515
 
516
+/** Maximum time that we will wait for ProxyDHCP offers */
517
+#define PROXYDHCP_WAIT_TIME ( TICKS_PER_SEC * 2 )
518
+
515 519
 extern struct list_head dhcp_option_blocks;
516 520
 
517 521
 extern unsigned long dhcp_num_option ( struct dhcp_option *option );

+ 54
- 25
src/net/udp/dhcp.c Ver arquivo

@@ -693,10 +693,14 @@ struct dhcp_session {
693 693
 	 * (e.g. @c DHCPDISCOVER).
694 694
 	 */
695 695
 	int state;
696
-	/** Options obtained from server */
696
+	/** Options obtained from DHCP server */
697 697
 	struct dhcp_option_block *options;
698
+	/** Options obtained from ProxyDHCP server */
699
+	struct dhcp_option_block *proxy_options;
698 700
 	/** Retransmission timer */
699 701
 	struct retry_timer timer;
702
+	/** Session start time (in ticks) */
703
+	unsigned long start;
700 704
 };
701 705
 
702 706
 /**
@@ -710,6 +714,7 @@ static void dhcp_free ( struct refcnt *refcnt ) {
710 714
 
711 715
 	netdev_put ( dhcp->netdev );
712 716
 	dhcpopt_put ( dhcp->options );
717
+	dhcpopt_put ( dhcp->proxy_options );
713 718
 	free ( dhcp );
714 719
 }
715 720
 
@@ -826,7 +831,10 @@ static int dhcp_deliver_raw ( struct xfer_interface *xfer,
826 831
 		container_of ( xfer, struct dhcp_session, xfer );
827 832
 	const struct dhcphdr *dhcphdr = data;
828 833
 	struct dhcp_option_block *options;
834
+	struct dhcp_option_block **store_options;
835
+	int is_proxy;
829 836
 	unsigned int msgtype;
837
+	unsigned long elapsed;
830 838
 
831 839
 	/* Check for matching transaction ID */
832 840
 	if ( dhcphdr->xid != dhcp_xid ( dhcp->netdev ) ) {
@@ -843,41 +851,61 @@ static int dhcp_deliver_raw ( struct xfer_interface *xfer,
843 851
 		return -EINVAL;
844 852
 	}
845 853
 
846
-	/* Determine message type */
854
+	/* Determine and verify message type */
855
+	is_proxy = ( dhcphdr->yiaddr.s_addr == 0 );
847 856
 	msgtype = find_dhcp_num_option ( options, DHCP_MESSAGE_TYPE );
848
-	DBGC ( dhcp, "DHCP %p received %s\n",
849
-	       dhcp, dhcp_msgtype_name ( msgtype ) );
857
+	DBGC ( dhcp, "DHCP %p received %s%s\n", dhcp,
858
+	       ( is_proxy ? "Proxy" : "" ), dhcp_msgtype_name ( msgtype ) );
859
+	if ( ( ( dhcp->state != DHCPDISCOVER ) || ( msgtype != DHCPOFFER ) ) &&
860
+	     ( ( dhcp->state != DHCPREQUEST ) || ( msgtype != DHCPACK ) ) ) {
861
+		DBGC ( dhcp, "DHCP %p discarding %s while in %s state\n",
862
+		       dhcp, dhcp_msgtype_name ( msgtype ),
863
+		       dhcp_msgtype_name ( dhcp->state ) );
864
+		goto out_discard;
865
+	}
850 866
 
851
-	/* Handle DHCP reply */
867
+	/* Update stored standard/ProxyDHCP options, if the new
868
+	 * options have equal or higher priority than the
869
+	 * currently-stored options.
870
+	 */
871
+	store_options = ( is_proxy ? &dhcp->proxy_options : &dhcp->options );
872
+	if ( ( ! *store_options ) || 
873
+	     ( find_dhcp_num_option ( options, DHCP_EB_PRIORITY ) >=
874
+	       find_dhcp_num_option ( *store_options, DHCP_EB_PRIORITY ) ) ) {
875
+		dhcpopt_put ( *store_options );
876
+		*store_options = options;
877
+	} else {
878
+		dhcpopt_put ( options );
879
+	}
880
+
881
+	/* Handle DHCP response */
852 882
 	switch ( dhcp->state ) {
853 883
 	case DHCPDISCOVER:
854
-		if ( msgtype != DHCPOFFER )
855
-			goto out_discard;
856
-		dhcp->state = DHCPREQUEST;
884
+		/* If we have received a valid standard DHCP response
885
+		 * (i.e. one with an IP address), and we have allowed
886
+		 * sufficient time for ProxyDHCP reponses, then
887
+		 * transition to making the DHCPREQUEST.
888
+		 */
889
+		elapsed = ( currticks() - dhcp->start );
890
+		if ( dhcp->options &&
891
+		     ( elapsed > PROXYDHCP_WAIT_TIME ) ) {
892
+			stop_timer ( &dhcp->timer );
893
+			dhcp->state = DHCPREQUEST;
894
+			dhcp_send_request ( dhcp );
895
+		}
857 896
 		break;
858 897
 	case DHCPREQUEST:
859
-		if ( msgtype != DHCPACK )
860
-			goto out_discard;
861
-		dhcp->state = DHCPACK;
898
+		/* DHCP finished; register options and exit */
899
+		if ( dhcp->proxy_options )
900
+			dhcp->register_options ( dhcp->netdev,
901
+						 dhcp->proxy_options );
902
+		dhcp->register_options ( dhcp->netdev, dhcp->options );
903
+		dhcp_finished ( dhcp, 0 );
862 904
 		break;
863 905
 	default:
864 906
 		assert ( 0 );
865
-		goto out_discard;
866 907
 	}
867 908
 
868
-	/* Stop timer and update stored options */
869
-	stop_timer ( &dhcp->timer );
870
-	if ( dhcp->options )
871
-		dhcpopt_put ( dhcp->options );
872
-	dhcp->options = options;
873
-
874
-	/* Transmit next packet, or terminate session */
875
-	if ( dhcp->state < DHCPACK ) {
876
-		dhcp_send_request ( dhcp );
877
-	} else {
878
-		dhcp->register_options ( dhcp->netdev, dhcp->options );
879
-		dhcp_finished ( dhcp, 0 );
880
-	}
881 909
 	return 0;
882 910
 
883 911
  out_discard:
@@ -965,6 +993,7 @@ int start_dhcp ( struct job_interface *job, struct net_device *netdev,
965 993
 	dhcp->register_options = register_options;
966 994
 	dhcp->timer.expired = dhcp_timer_expired;
967 995
 	dhcp->state = DHCPDISCOVER;
996
+	dhcp->start = currticks();
968 997
 
969 998
 	/* Instantiate child objects and attach to our interfaces */
970 999
 	if ( ( rc = xfer_open_socket ( &dhcp->xfer, SOCK_DGRAM,

Carregando…
Cancelar
Salvar