Browse Source

[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 9 years ago
parent
commit
60e2b71471
1 changed files with 54 additions and 27 deletions
  1. 54
    27
      src/net/udp/dhcp.c

+ 54
- 27
src/net/udp/dhcp.c View File

154
 	 * @v dhcppkt		DHCP packet
154
 	 * @v dhcppkt		DHCP packet
155
 	 * @v peer		Destination address
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
 		       struct sockaddr_in *peer );
158
 		       struct sockaddr_in *peer );
160
-	/** Handle received packet
159
+	/**
160
+	 * Handle received packet
161
 	 *
161
 	 *
162
 	 * @v dhcp		DHCP session
162
 	 * @v dhcp		DHCP session
163
 	 * @v dhcppkt		DHCP packet
163
 	 * @v dhcppkt		DHCP packet
164
 	 * @v peer		DHCP server address
164
 	 * @v peer		DHCP server address
165
 	 * @v msgtype		DHCP message type
165
 	 * @v msgtype		DHCP message type
166
 	 * @v server_id		DHCP server ID
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
 	 * @v dhcp		DHCP session
175
 	 * @v dhcp		DHCP session
175
 	 */
176
 	 */
340
  * @v peer		DHCP server address
341
  * @v peer		DHCP server address
341
  * @v msgtype		DHCP message type
342
  * @v msgtype		DHCP message type
342
  * @v server_id		DHCP server ID
343
  * @v server_id		DHCP server ID
344
+ * @v pseudo_id		DHCP server pseudo-ID
343
  */
345
  */
344
 static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
346
 static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
345
 				struct dhcp_packet *dhcppkt,
347
 				struct dhcp_packet *dhcppkt,
346
 				struct sockaddr_in *peer, uint8_t msgtype,
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
 	struct in_addr ip;
351
 	struct in_addr ip;
349
 	char vci[9]; /* "PXEClient" */
352
 	char vci[9]; /* "PXEClient" */
350
 	int vci_len;
353
 	int vci_len;
356
 	DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
359
 	DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
357
 	       dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
360
 	       dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
358
 	       ntohs ( peer->sin_port ) );
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
 	/* Identify offered IP address */
368
 	/* Identify offered IP address */
363
 	ip = dhcppkt->dhcphdr->yiaddr;
369
 	ip = dhcppkt->dhcphdr->yiaddr;
398
 	}
404
 	}
399
 
405
 
400
 	/* Select as ProxyDHCP offer, if applicable */
406
 	/* Select as ProxyDHCP offer, if applicable */
401
-	if ( server_id.s_addr && has_pxeclient &&
407
+	if ( pseudo_id.s_addr && has_pxeclient &&
402
 	     ( priority >= dhcp->proxy_priority ) ) {
408
 	     ( priority >= dhcp->proxy_priority ) ) {
403
 		dhcppkt_put ( dhcp->proxy_offer );
409
 		dhcppkt_put ( dhcp->proxy_offer );
404
-		dhcp->proxy_server = server_id;
410
+		dhcp->proxy_server = pseudo_id;
405
 		dhcp->proxy_offer = dhcppkt_get ( dhcppkt );
411
 		dhcp->proxy_offer = dhcppkt_get ( dhcppkt );
406
 		dhcp->proxy_priority = priority;
412
 		dhcp->proxy_priority = priority;
407
 	}
413
 	}
510
  * @v peer		DHCP server address
516
  * @v peer		DHCP server address
511
  * @v msgtype		DHCP message type
517
  * @v msgtype		DHCP message type
512
  * @v server_id		DHCP server ID
518
  * @v server_id		DHCP server ID
519
+ * @v pseudo_id		DHCP server pseudo-ID
513
  */
520
  */
514
 static void dhcp_request_rx ( struct dhcp_session *dhcp,
521
 static void dhcp_request_rx ( struct dhcp_session *dhcp,
515
 			      struct dhcp_packet *dhcppkt,
522
 			      struct dhcp_packet *dhcppkt,
516
 			      struct sockaddr_in *peer, uint8_t msgtype,
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
 	struct in_addr ip;
526
 	struct in_addr ip;
519
 	struct settings *parent;
527
 	struct settings *parent;
520
 	struct settings *settings;
528
 	struct settings *settings;
523
 	DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
531
 	DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
524
 	       dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
532
 	       dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
525
 	       ntohs ( peer->sin_port ) );
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
 	/* Identify leased IP address */
540
 	/* Identify leased IP address */
530
 	ip = dhcppkt->dhcphdr->yiaddr;
541
 	ip = dhcppkt->dhcphdr->yiaddr;
641
  * @v peer		DHCP server address
652
  * @v peer		DHCP server address
642
  * @v msgtype		DHCP message type
653
  * @v msgtype		DHCP message type
643
  * @v server_id		DHCP server ID
654
  * @v server_id		DHCP server ID
655
+ * @v pseudo_id		DHCP server pseudo-ID
644
  */
656
  */
645
 static void dhcp_proxy_rx ( struct dhcp_session *dhcp,
657
 static void dhcp_proxy_rx ( struct dhcp_session *dhcp,
646
 			    struct dhcp_packet *dhcppkt,
658
 			    struct dhcp_packet *dhcppkt,
647
 			    struct sockaddr_in *peer, uint8_t msgtype,
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
 	struct settings *settings = &dhcppkt->settings;
662
 	struct settings *settings = &dhcppkt->settings;
650
 	int rc;
663
 	int rc;
651
 
664
 
652
 	DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
665
 	DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
653
 	       dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
666
 	       dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
654
 	       ntohs ( peer->sin_port ) );
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
 	DBGC ( dhcp, "\n" );
673
 	DBGC ( dhcp, "\n" );
658
 
674
 
659
 	/* Filter out unacceptable responses */
675
 	/* Filter out unacceptable responses */
661
 		return;
677
 		return;
662
 	if ( ( msgtype != DHCPOFFER ) && ( msgtype != DHCPACK ) )
678
 	if ( ( msgtype != DHCPOFFER ) && ( msgtype != DHCPACK ) )
663
 		return;
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
 		return;
681
 		return;
667
 
682
 
668
 	/* Register settings */
683
 	/* Register settings */
772
  * @v peer		DHCP server address
787
  * @v peer		DHCP server address
773
  * @v msgtype		DHCP message type
788
  * @v msgtype		DHCP message type
774
  * @v server_id		DHCP server ID
789
  * @v server_id		DHCP server ID
790
+ * @v pseudo_id		DHCP server pseudo-ID
775
  */
791
  */
776
 static void dhcp_pxebs_rx ( struct dhcp_session *dhcp,
792
 static void dhcp_pxebs_rx ( struct dhcp_session *dhcp,
777
 			    struct dhcp_packet *dhcppkt,
793
 			    struct dhcp_packet *dhcppkt,
778
 			    struct sockaddr_in *peer, uint8_t msgtype,
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
 	struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 };
797
 	struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 };
781
 	int rc;
798
 	int rc;
782
 
799
 
783
 	DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
800
 	DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
784
 	       dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
801
 	       dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
785
 	       ntohs ( peer->sin_port ) );
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
 	/* Identify boot menu item */
809
 	/* Identify boot menu item */
790
 	dhcppkt_fetch ( dhcppkt, DHCP_PXE_BOOT_MENU_ITEM,
810
 	dhcppkt_fetch ( dhcppkt, DHCP_PXE_BOOT_MENU_ITEM,
801
 		return;
821
 		return;
802
 	if ( menu_item.type != dhcp->pxe_type )
822
 	if ( menu_item.type != dhcp->pxe_type )
803
 		return;
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
 		return;
825
 		return;
807
 
826
 
808
 	/* Register settings */
827
 	/* Register settings */
1134
 	struct dhcphdr *dhcphdr;
1153
 	struct dhcphdr *dhcphdr;
1135
 	uint8_t msgtype = 0;
1154
 	uint8_t msgtype = 0;
1136
 	struct in_addr server_id = { 0 };
1155
 	struct in_addr server_id = { 0 };
1156
+	struct in_addr pseudo_id;
1137
 	int rc = 0;
1157
 	int rc = 0;
1138
 
1158
 
1139
 	/* Sanity checks */
1159
 	/* Sanity checks */
1168
 	dhcppkt_fetch ( dhcppkt, DHCP_SERVER_IDENTIFIER,
1188
 	dhcppkt_fetch ( dhcppkt, DHCP_SERVER_IDENTIFIER,
1169
 			&server_id, sizeof ( server_id ) );
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
 	/* Check for matching transaction ID */
1198
 	/* Check for matching transaction ID */
1172
 	if ( dhcphdr->xid != dhcp->xid ) {
1199
 	if ( dhcphdr->xid != dhcp->xid ) {
1173
 		DBGC ( dhcp, "DHCP %p %s from %s:%d has bad transaction "
1200
 		DBGC ( dhcp, "DHCP %p %s from %s:%d has bad transaction "
1190
 	}
1217
 	}
1191
 
1218
 
1192
 	/* Handle packet based on current state */
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
  err_chaddr:
1222
  err_chaddr:
1196
  err_xid:
1223
  err_xid:

Loading…
Cancel
Save