|
@@ -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:
|