|
@@ -204,36 +204,6 @@ static struct dhcp_session_state dhcp_state_request;
|
204
|
204
|
static struct dhcp_session_state dhcp_state_proxy;
|
205
|
205
|
static struct dhcp_session_state dhcp_state_pxebs;
|
206
|
206
|
|
207
|
|
-/** DHCP offer is valid for IP lease */
|
208
|
|
-#define DHCP_OFFER_IP 1
|
209
|
|
-
|
210
|
|
-/** DHCP offer is valid for PXE options */
|
211
|
|
-#define DHCP_OFFER_PXE 2
|
212
|
|
-
|
213
|
|
-/** A DHCP offer */
|
214
|
|
-struct dhcp_offer {
|
215
|
|
- /** IP address of server granting offer */
|
216
|
|
- struct in_addr server;
|
217
|
|
-
|
218
|
|
- /** IP address being offered, or 0.0.0.0 for a pure proxy */
|
219
|
|
- struct in_addr ip;
|
220
|
|
-
|
221
|
|
- /** DHCP packet containing PXE options; NULL if missing or proxied */
|
222
|
|
- struct dhcp_packet *pxe;
|
223
|
|
-
|
224
|
|
- /** Valid uses for this offer, a combination of DHCP_OFFER bits */
|
225
|
|
- uint8_t valid;
|
226
|
|
-
|
227
|
|
- /** Priority of this offer */
|
228
|
|
- int8_t priority;
|
229
|
|
-
|
230
|
|
- /** Whether to ignore PXE DHCP extensions */
|
231
|
|
- uint8_t no_pxedhcp;
|
232
|
|
-};
|
233
|
|
-
|
234
|
|
-/** Maximum number of DHCP offers to queue */
|
235
|
|
-#define DHCP_MAX_OFFERS 6
|
236
|
|
-
|
237
|
207
|
/** A DHCP session */
|
238
|
208
|
struct dhcp_session {
|
239
|
209
|
/** Reference counter */
|
|
@@ -250,6 +220,22 @@ struct dhcp_session {
|
250
|
220
|
/** State of the session */
|
251
|
221
|
struct dhcp_session_state *state;
|
252
|
222
|
|
|
223
|
+ /** Offered IP address */
|
|
224
|
+ struct in_addr offer;
|
|
225
|
+ /** DHCP server */
|
|
226
|
+ struct in_addr server;
|
|
227
|
+ /** DHCP offer priority */
|
|
228
|
+ int priority;
|
|
229
|
+
|
|
230
|
+ /** ProxyDHCP protocol extensions should be ignored */
|
|
231
|
+ int no_pxedhcp;
|
|
232
|
+ /** ProxyDHCP server */
|
|
233
|
+ struct in_addr proxy_server;
|
|
234
|
+ /** ProxyDHCP port */
|
|
235
|
+ uint16_t proxy_port;
|
|
236
|
+ /** ProxyDHCP server priority */
|
|
237
|
+ int proxy_priority;
|
|
238
|
+
|
253
|
239
|
/** PXE Boot Server type */
|
254
|
240
|
uint16_t pxe_type;
|
255
|
241
|
/** List of PXE Boot Servers to attempt */
|
|
@@ -261,11 +247,6 @@ struct dhcp_session {
|
261
|
247
|
struct retry_timer timer;
|
262
|
248
|
/** Start time of the current state (in ticks) */
|
263
|
249
|
unsigned long start;
|
264
|
|
-
|
265
|
|
- /** DHCP offer just requested */
|
266
|
|
- struct dhcp_offer *current_offer;
|
267
|
|
- /** List of DHCP offers received */
|
268
|
|
- struct dhcp_offer offers[DHCP_MAX_OFFERS];
|
269
|
250
|
};
|
270
|
251
|
|
271
|
252
|
/**
|
|
@@ -276,12 +257,6 @@ struct dhcp_session {
|
276
|
257
|
static void dhcp_free ( struct refcnt *refcnt ) {
|
277
|
258
|
struct dhcp_session *dhcp =
|
278
|
259
|
container_of ( refcnt, struct dhcp_session, refcnt );
|
279
|
|
- int i;
|
280
|
|
-
|
281
|
|
- for ( i = 0 ; i < DHCP_MAX_OFFERS ; i++ ) {
|
282
|
|
- if ( dhcp->offers[i].pxe )
|
283
|
|
- dhcppkt_put ( dhcp->offers[i].pxe );
|
284
|
|
- }
|
285
|
260
|
|
286
|
261
|
netdev_put ( dhcp->netdev );
|
287
|
262
|
free ( dhcp );
|
|
@@ -322,35 +297,6 @@ static void dhcp_set_state ( struct dhcp_session *dhcp,
|
322
|
297
|
start_timer_nodelay ( &dhcp->timer );
|
323
|
298
|
}
|
324
|
299
|
|
325
|
|
-/**
|
326
|
|
- * Determine next DHCP offer to try
|
327
|
|
- *
|
328
|
|
- * @v dhcp DHCP session
|
329
|
|
- * @v type DHCP offer type
|
330
|
|
- * @ret offer Next DHCP offer to try
|
331
|
|
- *
|
332
|
|
- * Offers are ranked by priority, then by completeness (combined
|
333
|
|
- * IP+PXE are tried before @a type alone), then by order of receipt.
|
334
|
|
- */
|
335
|
|
-static struct dhcp_offer * dhcp_next_offer ( struct dhcp_session *dhcp,
|
336
|
|
- uint8_t type ) {
|
337
|
|
-
|
338
|
|
- struct dhcp_offer *offer;
|
339
|
|
- struct dhcp_offer *best = NULL;
|
340
|
|
-
|
341
|
|
- for ( offer = dhcp->offers ; offer < dhcp->offers + DHCP_MAX_OFFERS ;
|
342
|
|
- offer++ ) {
|
343
|
|
- if ( ( offer->valid & type ) &&
|
344
|
|
- ( ( best == NULL ) ||
|
345
|
|
- ( offer->priority > best->priority ) ||
|
346
|
|
- ( ( offer->priority == best->priority ) &&
|
347
|
|
- ( offer->valid & ~best->valid ) ) ) )
|
348
|
|
- best = offer;
|
349
|
|
- }
|
350
|
|
-
|
351
|
|
- return best;
|
352
|
|
-}
|
353
|
|
-
|
354
|
300
|
/****************************************************************************
|
355
|
301
|
*
|
356
|
302
|
* DHCP state machine
|
|
@@ -378,7 +324,7 @@ static int dhcp_discovery_tx ( struct dhcp_session *dhcp,
|
378
|
324
|
}
|
379
|
325
|
|
380
|
326
|
/**
|
381
|
|
- * Handle received DHCPOFFER during any state
|
|
327
|
+ * Handle received packet during DHCP discovery
|
382
|
328
|
*
|
383
|
329
|
* @v dhcp DHCP session
|
384
|
330
|
* @v dhcppkt DHCP packet
|
|
@@ -386,18 +332,19 @@ static int dhcp_discovery_tx ( struct dhcp_session *dhcp,
|
386
|
332
|
* @v msgtype DHCP message type
|
387
|
333
|
* @v server_id DHCP server ID
|
388
|
334
|
*/
|
389
|
|
-static void dhcp_rx_offer ( struct dhcp_session *dhcp,
|
390
|
|
- struct dhcp_packet *dhcppkt,
|
391
|
|
- struct sockaddr_in *peer, uint8_t msgtype,
|
392
|
|
- struct in_addr server_id ) {
|
|
335
|
+static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
|
|
336
|
+ struct dhcp_packet *dhcppkt,
|
|
337
|
+ struct sockaddr_in *peer, uint8_t msgtype,
|
|
338
|
+ struct in_addr server_id ) {
|
|
339
|
+ struct in_addr ip;
|
393
|
340
|
char vci[9]; /* "PXEClient" */
|
394
|
341
|
int vci_len;
|
395
|
342
|
int has_pxeclient;
|
396
|
343
|
int pxeopts_len;
|
397
|
344
|
int has_pxeopts;
|
398
|
|
- uint8_t discovery_control = 0;
|
399
|
|
- struct dhcp_offer *offer;
|
400
|
|
- int i;
|
|
345
|
+ int8_t priority = 0;
|
|
346
|
+ uint8_t no_pxedhcp = 0;
|
|
347
|
+ unsigned long elapsed;
|
401
|
348
|
|
402
|
349
|
DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
|
403
|
350
|
dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
|
|
@@ -406,27 +353,9 @@ static void dhcp_rx_offer ( struct dhcp_session *dhcp,
|
406
|
353
|
DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
|
407
|
354
|
|
408
|
355
|
/* Identify offered IP address */
|
409
|
|
- if ( dhcppkt->dhcphdr->yiaddr.s_addr )
|
410
|
|
- DBGC ( dhcp, " for %s", inet_ntoa ( dhcppkt->dhcphdr->yiaddr ));
|
411
|
|
-
|
412
|
|
- /* Enqueue an offer to be filled in */
|
413
|
|
- for ( i = 0 ; i < DHCP_MAX_OFFERS ; i++ ) {
|
414
|
|
- if ( ! dhcp->offers[i].valid )
|
415
|
|
- break;
|
416
|
|
-
|
417
|
|
- if ( dhcp->offers[i].server.s_addr == server_id.s_addr ) {
|
418
|
|
- DBGC ( dhcp, " dup\n" );
|
419
|
|
- return;
|
420
|
|
- }
|
421
|
|
- }
|
422
|
|
- if ( i == DHCP_MAX_OFFERS ) {
|
423
|
|
- DBGC ( dhcp, " dropped\n" );
|
424
|
|
- return;
|
425
|
|
- }
|
426
|
|
-
|
427
|
|
- offer = &dhcp->offers[i];
|
428
|
|
- offer->server = server_id;
|
429
|
|
- offer->ip = dhcppkt->dhcphdr->yiaddr;
|
|
356
|
+ ip = dhcppkt->dhcphdr->yiaddr;
|
|
357
|
+ if ( ip.s_addr )
|
|
358
|
+ DBGC ( dhcp, " for %s", inet_ntoa ( ip ) );
|
430
|
359
|
|
431
|
360
|
/* Identify "PXEClient" vendor class */
|
432
|
361
|
vci_len = dhcppkt_fetch ( dhcppkt, DHCP_VENDOR_CLASS_ID,
|
|
@@ -434,82 +363,49 @@ static void dhcp_rx_offer ( struct dhcp_session *dhcp,
|
434
|
363
|
has_pxeclient = ( ( vci_len >= ( int ) sizeof ( vci ) ) &&
|
435
|
364
|
( strncmp ( "PXEClient", vci, sizeof (vci) ) == 0 ));
|
436
|
365
|
|
437
|
|
- /*
|
438
|
|
- * Identify presence of PXE-specific options
|
439
|
|
- *
|
440
|
|
- * The Intel firmware appears to check for:
|
441
|
|
- * - PXE_DISCOVERY_CONTROL exists and has bit 3 set, or
|
442
|
|
- * - both PXE_BOOT_MENU and PXE_BOOT_MENU_PROMPT exist
|
443
|
|
- *
|
444
|
|
- * If DISCOVERY_CONTROL bit 3 is set, the firmware treats this
|
445
|
|
- * packet like a "normal" non-PXE DHCP packet with respect to
|
446
|
|
- * boot filename, except that it can come from ProxyDHCP. This
|
447
|
|
- * is the scheme that dnsmasq uses in the simple case.
|
448
|
|
- *
|
449
|
|
- * Otherwise, if one of the boot menu / boot menu prompt
|
450
|
|
- * options exists but not both, the firmware signals an
|
451
|
|
- * error. If neither exists, the packet is not considered to
|
452
|
|
- * contain DHCP options.
|
453
|
|
- *
|
454
|
|
- * In an effort to preserve semantics but be more flexible, we
|
455
|
|
- * check only for bit 3 of DISCOVERY_CONTROL or the presence
|
456
|
|
- * of BOOT_MENU. We don't care (yet) about the menu prompt.
|
457
|
|
- */
|
|
366
|
+ /* Identify presence of PXE-specific options */
|
458
|
367
|
pxeopts_len = dhcppkt_fetch ( dhcppkt, DHCP_PXE_BOOT_MENU, NULL, 0 );
|
459
|
|
- dhcppkt_fetch ( dhcppkt, DHCP_PXE_DISCOVERY_CONTROL,
|
460
|
|
- &discovery_control, sizeof ( discovery_control ) );
|
461
|
|
- has_pxeopts = ( ( pxeopts_len >= 0 ) ||
|
462
|
|
- ( discovery_control & PXEBS_SKIP ) );
|
|
368
|
+ has_pxeopts = ( pxeopts_len >= 0 );
|
463
|
369
|
if ( has_pxeclient )
|
464
|
370
|
DBGC ( dhcp, "%s", ( has_pxeopts ? " pxe" : " proxy" ) );
|
465
|
371
|
|
466
|
|
- if ( has_pxeclient && has_pxeopts ) {
|
467
|
|
- /* Save reference to packet for future use */
|
468
|
|
- if ( offer->pxe )
|
469
|
|
- dhcppkt_put ( offer->pxe );
|
470
|
|
- offer->pxe = dhcppkt_get ( dhcppkt );
|
471
|
|
- }
|
472
|
|
-
|
473
|
372
|
/* Identify priority */
|
474
|
|
- dhcppkt_fetch ( dhcppkt, DHCP_EB_PRIORITY, &offer->priority,
|
475
|
|
- sizeof ( offer->priority ) );
|
476
|
|
- if ( offer->priority )
|
477
|
|
- DBGC ( dhcp, " pri %d", offer->priority );
|
|
373
|
+ dhcppkt_fetch ( dhcppkt, DHCP_EB_PRIORITY, &priority,
|
|
374
|
+ sizeof ( priority ) );
|
|
375
|
+ if ( priority )
|
|
376
|
+ DBGC ( dhcp, " pri %d", priority );
|
478
|
377
|
|
479
|
378
|
/* Identify ignore-PXE flag */
|
480
|
|
- dhcppkt_fetch ( dhcppkt, DHCP_EB_NO_PXEDHCP, &offer->no_pxedhcp,
|
481
|
|
- sizeof ( offer->no_pxedhcp ) );
|
482
|
|
- if ( offer->no_pxedhcp )
|
|
379
|
+ dhcppkt_fetch ( dhcppkt, DHCP_EB_NO_PXEDHCP, &no_pxedhcp,
|
|
380
|
+ sizeof ( no_pxedhcp ) );
|
|
381
|
+ if ( no_pxedhcp )
|
483
|
382
|
DBGC ( dhcp, " nopxe" );
|
484
|
383
|
DBGC ( dhcp, "\n" );
|
485
|
384
|
|
486
|
|
- /* Determine roles this offer can fill */
|
487
|
|
- if ( offer->ip.s_addr &&
|
488
|
|
- ( peer->sin_port == htons ( BOOTPS_PORT ) ) &&
|
489
|
|
- ( ( msgtype == DHCPOFFER ) || ( ! msgtype /* BOOTP */ ) ) )
|
490
|
|
- offer->valid |= DHCP_OFFER_IP;
|
491
|
|
-
|
492
|
|
- if ( has_pxeclient && ( msgtype == DHCPOFFER ) )
|
493
|
|
- offer->valid |= DHCP_OFFER_PXE;
|
494
|
|
-}
|
495
|
|
-
|
496
|
|
-/**
|
497
|
|
- * Handle received packet during DHCP discovery
|
498
|
|
- *
|
499
|
|
- * @v dhcp DHCP session
|
500
|
|
- * @v dhcppkt DHCP packet
|
501
|
|
- * @v peer DHCP server address
|
502
|
|
- * @v msgtype DHCP message type
|
503
|
|
- * @v server_id DHCP server ID
|
504
|
|
- */
|
505
|
|
-static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
|
506
|
|
- struct dhcp_packet *dhcppkt,
|
507
|
|
- struct sockaddr_in *peer, uint8_t msgtype,
|
508
|
|
- struct in_addr server_id ) {
|
509
|
|
- unsigned long elapsed;
|
510
|
|
- struct dhcp_offer *ip_offer;
|
|
385
|
+ /* Select as DHCP offer, if applicable */
|
|
386
|
+ if ( ip.s_addr && ( peer->sin_port == htons ( BOOTPS_PORT ) ) &&
|
|
387
|
+ ( ( msgtype == DHCPOFFER ) || ( ! msgtype /* BOOTP */ ) ) &&
|
|
388
|
+ ( priority >= dhcp->priority ) ) {
|
|
389
|
+ dhcp->offer = ip;
|
|
390
|
+ dhcp->server = server_id;
|
|
391
|
+ dhcp->priority = priority;
|
|
392
|
+ dhcp->no_pxedhcp = no_pxedhcp;
|
|
393
|
+ }
|
511
|
394
|
|
512
|
|
- dhcp_rx_offer ( dhcp, dhcppkt, peer, msgtype, server_id );
|
|
395
|
+ /* Select as ProxyDHCP offer, if applicable */
|
|
396
|
+ if ( has_pxeclient && ( msgtype == DHCPOFFER ) &&
|
|
397
|
+ ( priority >= dhcp->proxy_priority ) ) {
|
|
398
|
+ /* If the offer already includes the PXE options, then
|
|
399
|
+ * assume that we can send the ProxyDHCPREQUEST to
|
|
400
|
+ * port 67 (since the DHCPDISCOVER that triggered this
|
|
401
|
+ * ProxyDHCPOFFER was sent to port 67). Otherwise,
|
|
402
|
+ * send the ProxyDHCPREQUEST to port 4011.
|
|
403
|
+ */
|
|
404
|
+ dhcp->proxy_server = server_id;
|
|
405
|
+ dhcp->proxy_port = ( has_pxeopts ? htons ( BOOTPS_PORT )
|
|
406
|
+ : htons ( PXE_PORT ) );
|
|
407
|
+ dhcp->proxy_priority = priority;
|
|
408
|
+ }
|
513
|
409
|
|
514
|
410
|
/* We can exit the discovery state when we have a valid
|
515
|
411
|
* DHCPOFFER, and either:
|
|
@@ -520,14 +416,12 @@ static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
|
520
|
416
|
*/
|
521
|
417
|
|
522
|
418
|
/* If we don't yet have a DHCPOFFER, do nothing */
|
523
|
|
- ip_offer = dhcp_next_offer ( dhcp, DHCP_OFFER_IP );
|
524
|
|
- if ( ! ip_offer )
|
|
419
|
+ if ( ! dhcp->offer.s_addr )
|
525
|
420
|
return;
|
526
|
421
|
|
527
|
422
|
/* If we can't yet transition to DHCPREQUEST, do nothing */
|
528
|
423
|
elapsed = ( currticks() - dhcp->start );
|
529
|
|
- if ( ! ( ip_offer->no_pxedhcp ||
|
530
|
|
- dhcp_next_offer ( dhcp, DHCP_OFFER_PXE ) ||
|
|
424
|
+ if ( ! ( dhcp->no_pxedhcp || dhcp->proxy_server.s_addr ||
|
531
|
425
|
( elapsed > PROXYDHCP_MAX_TIMEOUT ) ) )
|
532
|
426
|
return;
|
533
|
427
|
|
|
@@ -544,8 +438,7 @@ static void dhcp_discovery_expired ( struct dhcp_session *dhcp ) {
|
544
|
438
|
unsigned long elapsed = ( currticks() - dhcp->start );
|
545
|
439
|
|
546
|
440
|
/* Give up waiting for ProxyDHCP before we reach the failure point */
|
547
|
|
- if ( dhcp_next_offer ( dhcp, DHCP_OFFER_IP ) &&
|
548
|
|
- ( elapsed > PROXYDHCP_MAX_TIMEOUT ) ) {
|
|
441
|
+ if ( dhcp->offer.s_addr && ( elapsed > PROXYDHCP_MAX_TIMEOUT ) ) {
|
549
|
442
|
dhcp_set_state ( dhcp, &dhcp_state_request );
|
550
|
443
|
return;
|
551
|
444
|
}
|
|
@@ -575,23 +468,21 @@ static int dhcp_request_tx ( struct dhcp_session *dhcp,
|
575
|
468
|
struct dhcp_packet *dhcppkt,
|
576
|
469
|
struct sockaddr_in *peer ) {
|
577
|
470
|
int rc;
|
578
|
|
- struct dhcp_offer *offer;
|
579
|
|
-
|
580
|
|
- offer = dhcp->current_offer = dhcp_next_offer ( dhcp, DHCP_OFFER_IP );
|
581
|
471
|
|
582
|
472
|
DBGC ( dhcp, "DHCP %p DHCPREQUEST to %s:%d",
|
583
|
|
- dhcp, inet_ntoa ( offer->server ), BOOTPS_PORT );
|
584
|
|
- DBGC ( dhcp, " for %s\n", inet_ntoa ( offer->ip ) );
|
|
473
|
+ dhcp, inet_ntoa ( dhcp->server ), BOOTPS_PORT );
|
|
474
|
+ DBGC ( dhcp, " for %s\n", inet_ntoa ( dhcp->offer ) );
|
585
|
475
|
|
586
|
476
|
/* Set server ID */
|
587
|
477
|
if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_SERVER_IDENTIFIER,
|
588
|
|
- &offer->server,
|
589
|
|
- sizeof ( offer->server ) ) ) != 0 )
|
|
478
|
+ &dhcp->server,
|
|
479
|
+ sizeof ( dhcp->server ) ) ) != 0 )
|
590
|
480
|
return rc;
|
591
|
481
|
|
592
|
482
|
/* Set requested IP address */
|
593
|
483
|
if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_REQUESTED_ADDRESS,
|
594
|
|
- &offer->ip, sizeof ( offer->ip ) ) ) != 0 )
|
|
484
|
+ &dhcp->offer,
|
|
485
|
+ sizeof ( dhcp->offer ) ) ) != 0 )
|
595
|
486
|
return rc;
|
596
|
487
|
|
597
|
488
|
/* Set server address */
|
|
@@ -617,18 +508,6 @@ static void dhcp_request_rx ( struct dhcp_session *dhcp,
|
617
|
508
|
struct in_addr ip;
|
618
|
509
|
struct settings *parent;
|
619
|
510
|
int rc;
|
620
|
|
- struct dhcp_offer *pxe_offer;
|
621
|
|
-
|
622
|
|
- if ( msgtype == DHCPOFFER ) {
|
623
|
|
- dhcp_rx_offer ( dhcp, dhcppkt, peer, msgtype, server_id );
|
624
|
|
- if ( dhcp_next_offer ( dhcp, DHCP_OFFER_IP ) !=
|
625
|
|
- dhcp->current_offer ) {
|
626
|
|
- /* Restart due to higher-priority offer received */
|
627
|
|
- DBGC ( dhcp, "DHCP %p re-requesting\n", dhcp );
|
628
|
|
- dhcp_set_state ( dhcp, &dhcp_state_request );
|
629
|
|
- }
|
630
|
|
- return;
|
631
|
|
- }
|
632
|
511
|
|
633
|
512
|
DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
|
634
|
513
|
dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
|
|
@@ -647,7 +526,7 @@ static void dhcp_request_rx ( struct dhcp_session *dhcp,
|
647
|
526
|
return;
|
648
|
527
|
if ( msgtype /* BOOTP */ && ( msgtype != DHCPACK ) )
|
649
|
528
|
return;
|
650
|
|
- if ( server_id.s_addr != dhcp->current_offer->server.s_addr )
|
|
529
|
+ if ( server_id.s_addr != dhcp->server.s_addr )
|
651
|
530
|
return;
|
652
|
531
|
|
653
|
532
|
/* Record assigned address */
|
|
@@ -662,31 +541,18 @@ static void dhcp_request_rx ( struct dhcp_session *dhcp,
|
662
|
541
|
return;
|
663
|
542
|
}
|
664
|
543
|
|
665
|
|
- /* Locate best source of PXE settings */
|
666
|
|
- pxe_offer = dhcp_next_offer ( dhcp, DHCP_OFFER_PXE );
|
667
|
|
-
|
668
|
|
- if ( ( ! pxe_offer ) || /* No PXE available */
|
669
|
|
- /* IP offer instructs us to ignore PXE */
|
670
|
|
- dhcp->current_offer->no_pxedhcp ||
|
671
|
|
- /* PXE settings already registered with IP offer */
|
672
|
|
- ( ( dhcp->current_offer == pxe_offer ) && ( pxe_offer->pxe ) ) ) {
|
673
|
|
-
|
674
|
|
- /* Terminate DHCP */
|
675
|
|
- dhcp_finished ( dhcp, 0 );
|
676
|
|
-
|
677
|
|
- } else if ( pxe_offer->pxe ) {
|
678
|
|
- /* Register PXE settings and terminate DHCP */
|
679
|
|
- pxe_offer->pxe->settings.name = PROXYDHCP_SETTINGS_NAME;
|
680
|
|
- if ( ( rc = register_settings ( &pxe_offer->pxe->settings,
|
681
|
|
- NULL ) ) != 0 ) {
|
682
|
|
- DBGC ( dhcp, "DHCP %p could not register settings: "
|
683
|
|
- "%s\n", dhcp, strerror ( rc ) );
|
684
|
|
- }
|
685
|
|
- dhcp_finished ( dhcp, rc );
|
686
|
|
- } else {
|
687
|
|
- /* Start ProxyDHCP */
|
|
544
|
+ /* Start ProxyDHCPREQUEST if applicable */
|
|
545
|
+ if ( dhcp->proxy_server.s_addr /* Have ProxyDHCP server */ &&
|
|
546
|
+ ( ! dhcp->no_pxedhcp ) /* ProxyDHCP not disabled */ &&
|
|
547
|
+ ( /* ProxyDHCP server is not just the DHCP server itself */
|
|
548
|
+ ( dhcp->proxy_server.s_addr != dhcp->server.s_addr ) ||
|
|
549
|
+ ( dhcp->proxy_port != htons ( BOOTPS_PORT ) ) ) ) {
|
688
|
550
|
dhcp_set_state ( dhcp, &dhcp_state_proxy );
|
|
551
|
+ return;
|
689
|
552
|
}
|
|
553
|
+
|
|
554
|
+ /* Terminate DHCP */
|
|
555
|
+ dhcp_finished ( dhcp, 0 );
|
690
|
556
|
}
|
691
|
557
|
|
692
|
558
|
/**
|
|
@@ -721,22 +587,19 @@ static int dhcp_proxy_tx ( struct dhcp_session *dhcp,
|
721
|
587
|
struct dhcp_packet *dhcppkt,
|
722
|
588
|
struct sockaddr_in *peer ) {
|
723
|
589
|
int rc;
|
724
|
|
- struct dhcp_offer *offer;
|
725
|
|
-
|
726
|
|
- offer = dhcp->current_offer = dhcp_next_offer ( dhcp, DHCP_OFFER_PXE );
|
727
|
590
|
|
728
|
591
|
DBGC ( dhcp, "DHCP %p ProxyDHCP REQUEST to %s:%d\n", dhcp,
|
729
|
|
- inet_ntoa ( offer->server ), PXE_PORT );
|
|
592
|
+ inet_ntoa ( dhcp->proxy_server ), ntohs ( dhcp->proxy_port ) );
|
730
|
593
|
|
731
|
594
|
/* Set server ID */
|
732
|
595
|
if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_SERVER_IDENTIFIER,
|
733
|
|
- &offer->server,
|
734
|
|
- sizeof ( offer->server ) ) ) != 0 )
|
|
596
|
+ &dhcp->proxy_server,
|
|
597
|
+ sizeof ( dhcp->proxy_server ) ) ) != 0 )
|
735
|
598
|
return rc;
|
736
|
599
|
|
737
|
600
|
/* Set server address */
|
738
|
|
- peer->sin_addr = offer->server;
|
739
|
|
- peer->sin_port = htons ( PXE_PORT );
|
|
601
|
+ peer->sin_addr = dhcp->proxy_server;
|
|
602
|
+ peer->sin_port = dhcp->proxy_port;
|
740
|
603
|
|
741
|
604
|
return 0;
|
742
|
605
|
}
|
|
@@ -756,13 +619,6 @@ static void dhcp_proxy_rx ( struct dhcp_session *dhcp,
|
756
|
619
|
struct in_addr server_id ) {
|
757
|
620
|
int rc;
|
758
|
621
|
|
759
|
|
- /* Enqueue last-minute DHCPOFFERs for use in case of failure */
|
760
|
|
- if ( peer->sin_port == htons ( BOOTPS_PORT ) &&
|
761
|
|
- msgtype == DHCPOFFER ) {
|
762
|
|
- dhcp_rx_offer ( dhcp, dhcppkt, peer, msgtype, server_id );
|
763
|
|
- return;
|
764
|
|
- }
|
765
|
|
-
|
766
|
622
|
DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
|
767
|
623
|
dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
|
768
|
624
|
ntohs ( peer->sin_port ) );
|
|
@@ -771,12 +627,12 @@ static void dhcp_proxy_rx ( struct dhcp_session *dhcp,
|
771
|
627
|
DBGC ( dhcp, "\n" );
|
772
|
628
|
|
773
|
629
|
/* Filter out unacceptable responses */
|
774
|
|
- if ( peer->sin_port != htons ( PXE_PORT ) )
|
|
630
|
+ if ( peer->sin_port != dhcp->proxy_port )
|
775
|
631
|
return;
|
776
|
|
- if ( msgtype != DHCPACK && msgtype != DHCPOFFER )
|
|
632
|
+ if ( ( msgtype != DHCPOFFER ) && ( msgtype != DHCPACK ) )
|
777
|
633
|
return;
|
778
|
634
|
if ( server_id.s_addr /* Linux PXE server omits server ID */ &&
|
779
|
|
- ( server_id.s_addr != dhcp->current_offer->server.s_addr ) )
|
|
635
|
+ ( server_id.s_addr != dhcp->proxy_server.s_addr ) )
|
780
|
636
|
return;
|
781
|
637
|
|
782
|
638
|
/* Register settings */
|
|
@@ -802,28 +658,6 @@ static void dhcp_proxy_expired ( struct dhcp_session *dhcp ) {
|
802
|
658
|
|
803
|
659
|
/* Give up waiting for ProxyDHCP before we reach the failure point */
|
804
|
660
|
if ( elapsed > PROXYDHCP_MAX_TIMEOUT ) {
|
805
|
|
-
|
806
|
|
- /* Mark failed offer as unsuitable for ProxyDHCP */
|
807
|
|
- dhcp->current_offer->valid &= ~DHCP_OFFER_PXE;
|
808
|
|
-
|
809
|
|
- /* Prefer not to use only half of a PXE+IP offer if we
|
810
|
|
- * have other offers available
|
811
|
|
- */
|
812
|
|
- dhcp->current_offer->priority = -1;
|
813
|
|
-
|
814
|
|
- /* If we have any other PXE offers we can try, go back
|
815
|
|
- * to DHCPREQUEST (since they might not be proxied
|
816
|
|
- * offers, or might be coupled to a new IP address).
|
817
|
|
- * We should probably DHCPRELEASE our old IP, but the
|
818
|
|
- * standard does not require it.
|
819
|
|
- */
|
820
|
|
- if ( dhcp_next_offer ( dhcp, DHCP_OFFER_PXE ) ) {
|
821
|
|
- dhcp->local.sin_addr.s_addr = 0;
|
822
|
|
- dhcp_set_state ( dhcp, &dhcp_state_request );
|
823
|
|
- return;
|
824
|
|
- }
|
825
|
|
-
|
826
|
|
- /* No possibilities left; finish without PXE options */
|
827
|
661
|
dhcp_finished ( dhcp, 0 );
|
828
|
662
|
return;
|
829
|
663
|
}
|