Procházet zdrojové kódy

[dhcp] Allow pseudo-DHCP servers to use pseudo-identifiers

Some ProxyDHCP servers and PXE boot servers do not specify a DHCP
server identifier via option 54.  We currently work around this in a
variety of ad-hoc ways:

 - if a ProxyDHCPACK has no server identifier then we treat it as
   having the correct server identifier,

 - if a boot server ACK has no server identifier then we use the
   packet's source IP address as the server identifier.

Introduce the concept of a DHCP server pseudo-identifier, defined as
being:

 - the server identifier (option 54), or

 - if there is no server identifier, then the next-server address
   (siaddr),

 - if there is no server identifier or next-server address, then the
   DHCP packet's source IP address.

Use the pseudo-identifier in place of the server identifier when
handling ProxyDHCP and PXE boot server responses.

Originally-fixed-by: Wissam Shoukair <wissams@mellanox.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown před 9 roky
rodič
revize
60e2b71471
1 změnil soubory, kde provedl 54 přidání a 27 odebrání
  1. 54
    27
      src/net/udp/dhcp.c

+ 54
- 27
src/net/udp/dhcp.c Zobrazit soubor

@@ -154,22 +154,23 @@ struct dhcp_session_state {
154 154
 	 * @v dhcppkt		DHCP packet
155 155
 	 * @v peer		Destination address
156 156
 	 */
157
-	int ( * tx ) ( struct dhcp_session *dhcp,
158
-		       struct dhcp_packet *dhcppkt,
157
+	int ( * tx ) ( struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt,
159 158
 		       struct sockaddr_in *peer );
160
-	/** Handle received packet
159
+	/**
160
+	 * Handle received packet
161 161
 	 *
162 162
 	 * @v dhcp		DHCP session
163 163
 	 * @v dhcppkt		DHCP packet
164 164
 	 * @v peer		DHCP server address
165 165
 	 * @v msgtype		DHCP message type
166 166
 	 * @v server_id		DHCP server ID
167
+	 * @v pseudo_id		DHCP server pseudo-ID
167 168
 	 */
168
-	void ( * rx ) ( struct dhcp_session *dhcp,
169
-			struct dhcp_packet *dhcppkt,
170
-			struct sockaddr_in *peer,
171
-			uint8_t msgtype, struct in_addr server_id );
172
-	/** Handle timer expiry
169
+	void ( * rx ) ( struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt,
170
+			struct sockaddr_in *peer, uint8_t msgtype,
171
+			struct in_addr server_id, struct in_addr pseudo_id );
172
+	/**
173
+	 * Handle timer expiry
173 174
 	 *
174 175
 	 * @v dhcp		DHCP session
175 176
 	 */
@@ -340,11 +341,13 @@ static int dhcp_discovery_tx ( struct dhcp_session *dhcp,
340 341
  * @v peer		DHCP server address
341 342
  * @v msgtype		DHCP message type
342 343
  * @v server_id		DHCP server ID
344
+ * @v pseudo_id		DHCP server pseudo-ID
343 345
  */
344 346
 static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
345 347
 				struct dhcp_packet *dhcppkt,
346 348
 				struct sockaddr_in *peer, uint8_t msgtype,
347
-				struct in_addr server_id ) {
349
+				struct in_addr server_id,
350
+				struct in_addr pseudo_id ) {
348 351
 	struct in_addr ip;
349 352
 	char vci[9]; /* "PXEClient" */
350 353
 	int vci_len;
@@ -356,8 +359,11 @@ static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
356 359
 	DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
357 360
 	       dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
358 361
 	       ntohs ( peer->sin_port ) );
359
-	if ( server_id.s_addr != peer->sin_addr.s_addr )
360
-		DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
362
+	if ( ( server_id.s_addr != peer->sin_addr.s_addr ) ||
363
+	     ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) {
364
+		DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) );
365
+		DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) );
366
+	}
361 367
 
362 368
 	/* Identify offered IP address */
363 369
 	ip = dhcppkt->dhcphdr->yiaddr;
@@ -398,10 +404,10 @@ static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
398 404
 	}
399 405
 
400 406
 	/* Select as ProxyDHCP offer, if applicable */
401
-	if ( server_id.s_addr && has_pxeclient &&
407
+	if ( pseudo_id.s_addr && has_pxeclient &&
402 408
 	     ( priority >= dhcp->proxy_priority ) ) {
403 409
 		dhcppkt_put ( dhcp->proxy_offer );
404
-		dhcp->proxy_server = server_id;
410
+		dhcp->proxy_server = pseudo_id;
405 411
 		dhcp->proxy_offer = dhcppkt_get ( dhcppkt );
406 412
 		dhcp->proxy_priority = priority;
407 413
 	}
@@ -510,11 +516,13 @@ static int dhcp_request_tx ( struct dhcp_session *dhcp,
510 516
  * @v peer		DHCP server address
511 517
  * @v msgtype		DHCP message type
512 518
  * @v server_id		DHCP server ID
519
+ * @v pseudo_id		DHCP server pseudo-ID
513 520
  */
514 521
 static void dhcp_request_rx ( struct dhcp_session *dhcp,
515 522
 			      struct dhcp_packet *dhcppkt,
516 523
 			      struct sockaddr_in *peer, uint8_t msgtype,
517
-			      struct in_addr server_id ) {
524
+			      struct in_addr server_id,
525
+			      struct in_addr pseudo_id ) {
518 526
 	struct in_addr ip;
519 527
 	struct settings *parent;
520 528
 	struct settings *settings;
@@ -523,8 +531,11 @@ static void dhcp_request_rx ( struct dhcp_session *dhcp,
523 531
 	DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
524 532
 	       dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
525 533
 	       ntohs ( peer->sin_port ) );
526
-	if ( server_id.s_addr != peer->sin_addr.s_addr )
527
-		DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
534
+	if ( ( server_id.s_addr != peer->sin_addr.s_addr ) ||
535
+	     ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) {
536
+		DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) );
537
+		DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) );
538
+	}
528 539
 
529 540
 	/* Identify leased IP address */
530 541
 	ip = dhcppkt->dhcphdr->yiaddr;
@@ -641,19 +652,24 @@ static int dhcp_proxy_tx ( struct dhcp_session *dhcp,
641 652
  * @v peer		DHCP server address
642 653
  * @v msgtype		DHCP message type
643 654
  * @v server_id		DHCP server ID
655
+ * @v pseudo_id		DHCP server pseudo-ID
644 656
  */
645 657
 static void dhcp_proxy_rx ( struct dhcp_session *dhcp,
646 658
 			    struct dhcp_packet *dhcppkt,
647 659
 			    struct sockaddr_in *peer, uint8_t msgtype,
648
-			    struct in_addr server_id ) {
660
+			    struct in_addr server_id,
661
+			    struct in_addr pseudo_id ) {
649 662
 	struct settings *settings = &dhcppkt->settings;
650 663
 	int rc;
651 664
 
652 665
 	DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
653 666
 	       dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
654 667
 	       ntohs ( peer->sin_port ) );
655
-	if ( server_id.s_addr != peer->sin_addr.s_addr )
656
-		DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
668
+	if ( ( server_id.s_addr != peer->sin_addr.s_addr ) ||
669
+	     ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) {
670
+		DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) );
671
+		DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) );
672
+	}
657 673
 	DBGC ( dhcp, "\n" );
658 674
 
659 675
 	/* Filter out unacceptable responses */
@@ -661,8 +677,7 @@ static void dhcp_proxy_rx ( struct dhcp_session *dhcp,
661 677
 		return;
662 678
 	if ( ( msgtype != DHCPOFFER ) && ( msgtype != DHCPACK ) )
663 679
 		return;
664
-	if ( server_id.s_addr /* Linux PXE server omits server ID */ &&
665
-	     ( server_id.s_addr != dhcp->proxy_server.s_addr ) )
680
+	if ( ( pseudo_id.s_addr != dhcp->proxy_server.s_addr ) )
666 681
 		return;
667 682
 
668 683
 	/* Register settings */
@@ -772,19 +787,24 @@ static int dhcp_pxebs_accept ( struct dhcp_session *dhcp,
772 787
  * @v peer		DHCP server address
773 788
  * @v msgtype		DHCP message type
774 789
  * @v server_id		DHCP server ID
790
+ * @v pseudo_id		DHCP server pseudo-ID
775 791
  */
776 792
 static void dhcp_pxebs_rx ( struct dhcp_session *dhcp,
777 793
 			    struct dhcp_packet *dhcppkt,
778 794
 			    struct sockaddr_in *peer, uint8_t msgtype,
779
-			    struct in_addr server_id ) {
795
+			    struct in_addr server_id,
796
+			    struct in_addr pseudo_id ) {
780 797
 	struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 };
781 798
 	int rc;
782 799
 
783 800
 	DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
784 801
 	       dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
785 802
 	       ntohs ( peer->sin_port ) );
786
-	if ( server_id.s_addr != peer->sin_addr.s_addr )
787
-		DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
803
+	if ( ( server_id.s_addr != peer->sin_addr.s_addr ) ||
804
+	     ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) {
805
+		DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) );
806
+		DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) );
807
+	}
788 808
 
789 809
 	/* Identify boot menu item */
790 810
 	dhcppkt_fetch ( dhcppkt, DHCP_PXE_BOOT_MENU_ITEM,
@@ -801,8 +821,7 @@ static void dhcp_pxebs_rx ( struct dhcp_session *dhcp,
801 821
 		return;
802 822
 	if ( menu_item.type != dhcp->pxe_type )
803 823
 		return;
804
-	if ( ! dhcp_pxebs_accept ( dhcp, ( server_id.s_addr ?
805
-					   server_id : peer->sin_addr ) ) )
824
+	if ( ! dhcp_pxebs_accept ( dhcp, pseudo_id ) )
806 825
 		return;
807 826
 
808 827
 	/* Register settings */
@@ -1134,6 +1153,7 @@ static int dhcp_deliver ( struct dhcp_session *dhcp,
1134 1153
 	struct dhcphdr *dhcphdr;
1135 1154
 	uint8_t msgtype = 0;
1136 1155
 	struct in_addr server_id = { 0 };
1156
+	struct in_addr pseudo_id;
1137 1157
 	int rc = 0;
1138 1158
 
1139 1159
 	/* Sanity checks */
@@ -1168,6 +1188,13 @@ static int dhcp_deliver ( struct dhcp_session *dhcp,
1168 1188
 	dhcppkt_fetch ( dhcppkt, DHCP_SERVER_IDENTIFIER,
1169 1189
 			&server_id, sizeof ( server_id ) );
1170 1190
 
1191
+	/* Identify server pseudo-ID */
1192
+	pseudo_id = server_id;
1193
+	if ( ! pseudo_id.s_addr )
1194
+		pseudo_id = dhcppkt->dhcphdr->siaddr;
1195
+	if ( ! pseudo_id.s_addr )
1196
+		pseudo_id = peer->sin_addr;
1197
+
1171 1198
 	/* Check for matching transaction ID */
1172 1199
 	if ( dhcphdr->xid != dhcp->xid ) {
1173 1200
 		DBGC ( dhcp, "DHCP %p %s from %s:%d has bad transaction "
@@ -1190,7 +1217,7 @@ static int dhcp_deliver ( struct dhcp_session *dhcp,
1190 1217
 	}
1191 1218
 
1192 1219
 	/* Handle packet based on current state */
1193
-	dhcp->state->rx ( dhcp, dhcppkt, peer, msgtype, server_id );
1220
+	dhcp->state->rx ( dhcp, dhcppkt, peer, msgtype, server_id, pseudo_id );
1194 1221
 
1195 1222
  err_chaddr:
1196 1223
  err_xid:

Načítá se…
Zrušit
Uložit