iPXE
dhcp.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <string.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <ctype.h>
30 #include <errno.h>
31 #include <assert.h>
32 #include <byteswap.h>
33 #include <ipxe/if_ether.h>
34 #include <ipxe/iobuf.h>
35 #include <ipxe/netdevice.h>
36 #include <ipxe/device.h>
37 #include <ipxe/xfer.h>
38 #include <ipxe/open.h>
39 #include <ipxe/job.h>
40 #include <ipxe/retry.h>
41 #include <ipxe/tcpip.h>
42 #include <ipxe/ip.h>
43 #include <ipxe/uuid.h>
44 #include <ipxe/timer.h>
45 #include <ipxe/settings.h>
46 #include <ipxe/dhcp.h>
47 #include <ipxe/dhcpopts.h>
48 #include <ipxe/dhcppkt.h>
49 #include <ipxe/dhcparch.h>
50 #include <ipxe/features.h>
51 #include <config/dhcp.h>
52 
53 /** @file
54  *
55  * Dynamic Host Configuration Protocol
56  *
57  */
58 
59 struct dhcp_session;
60 static int dhcp_tx ( struct dhcp_session *dhcp );
61 
62 /**
63  * DHCP operation types
64  *
65  * This table maps from DHCP message types (i.e. values of the @c
66  * DHCP_MESSAGE_TYPE option) to values of the "op" field within a DHCP
67  * packet.
68  */
69 static const uint8_t dhcp_op[] = {
74  [DHCPACK] = BOOTP_REPLY,
75  [DHCPNAK] = BOOTP_REPLY,
78 };
79 
80 /** Raw option data for options common to all DHCP requests */
84  DHCP_WORD ( ETH_MAX_MTU - 20 /* IP header */ - 8 /* UDP header */ ),
90  DHCP_USER_CLASS_ID, DHCP_STRING ( 'i', 'P', 'X', 'E' ),
98  128, 129, 130, 131, 132, 133, 134, 135, /* for PXE */
100  DHCP_END
101 };
102 
103 /** Settings copied in to all DHCP requests */
104 static const struct setting * dhcp_request_settings[] = {
105  &user_class_setting,
106  &vendor_class_setting,
107 };
108 
109 /** DHCP server address setting */
110 const struct setting dhcp_server_setting __setting ( SETTING_MISC,
111  dhcp-server ) = {
112  .name = "dhcp-server",
113  .description = "DHCP server",
114  .tag = DHCP_SERVER_IDENTIFIER,
115  .type = &setting_type_ipv4,
116 };
117 
118 /**
119  * Most recent DHCP transaction ID
120  *
121  * This is exposed for use by the fakedhcp code when reconstructing
122  * DHCP packets for PXE NBPs.
123  */
125 
126 /**
127  * Name a DHCP packet type
128  *
129  * @v msgtype DHCP message type
130  * @ret string DHCP mesasge type name
131  */
132 static inline const char * dhcp_msgtype_name ( unsigned int msgtype ) {
133  switch ( msgtype ) {
134  case DHCPNONE: return "BOOTP"; /* Non-DHCP packet */
135  case DHCPDISCOVER: return "DHCPDISCOVER";
136  case DHCPOFFER: return "DHCPOFFER";
137  case DHCPREQUEST: return "DHCPREQUEST";
138  case DHCPDECLINE: return "DHCPDECLINE";
139  case DHCPACK: return "DHCPACK";
140  case DHCPNAK: return "DHCPNAK";
141  case DHCPRELEASE: return "DHCPRELEASE";
142  case DHCPINFORM: return "DHCPINFORM";
143  default: return "DHCP<invalid>";
144  }
145 }
146 
147 /****************************************************************************
148  *
149  * DHCP session
150  *
151  */
152 
153 struct dhcp_session;
154 
155 /** DHCP session state operations */
157  /** State name */
158  const char *name;
159  /**
160  * Construct transmitted packet
161  *
162  * @v dhcp DHCP session
163  * @v dhcppkt DHCP packet
164  * @v peer Destination address
165  */
166  int ( * tx ) ( struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt,
167  struct sockaddr_in *peer );
168  /**
169  * Handle received packet
170  *
171  * @v dhcp DHCP session
172  * @v dhcppkt DHCP packet
173  * @v peer DHCP server address
174  * @v msgtype DHCP message type
175  * @v server_id DHCP server ID
176  * @v pseudo_id DHCP server pseudo-ID
177  */
178  void ( * rx ) ( struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt,
179  struct sockaddr_in *peer, uint8_t msgtype,
180  struct in_addr server_id, struct in_addr pseudo_id );
181  /**
182  * Handle timer expiry
183  *
184  * @v dhcp DHCP session
185  */
186  void ( * expired ) ( struct dhcp_session *dhcp );
187  /** Transmitted message type */
189  /** Timeout parameters */
192 };
193 
198 
199 /** A DHCP session */
200 struct dhcp_session {
201  /** Reference counter */
202  struct refcnt refcnt;
203  /** Job control interface */
204  struct interface job;
205  /** Data transfer interface */
206  struct interface xfer;
207 
208  /** Network device being configured */
210  /** Local socket address */
212  /** State of the session */
214  /** Transaction ID (in network-endian order) */
216 
217  /** Offered IP address */
218  struct in_addr offer;
219  /** DHCP server */
220  struct in_addr server;
221  /** DHCP offer priority */
222  int priority;
223 
224  /** ProxyDHCP protocol extensions should be ignored */
226  /** ProxyDHCP server */
228  /** ProxyDHCP offer */
230  /** ProxyDHCP offer priority */
232 
233  /** PXE Boot Server type */
235  /** List of PXE Boot Servers to attempt */
237  /** List of PXE Boot Servers to accept */
239 
240  /** Retransmission timer */
242  /** Transmission counter */
243  unsigned int count;
244  /** Start time of the current state (in ticks) */
245  unsigned long start;
246 };
247 
248 /**
249  * Free DHCP session
250  *
251  * @v refcnt Reference counter
252  */
253 static void dhcp_free ( struct refcnt *refcnt ) {
254  struct dhcp_session *dhcp =
255  container_of ( refcnt, struct dhcp_session, refcnt );
256 
257  netdev_put ( dhcp->netdev );
258  dhcppkt_put ( dhcp->proxy_offer );
259  free ( dhcp );
260 }
261 
262 /**
263  * Mark DHCP session as complete
264  *
265  * @v dhcp DHCP session
266  * @v rc Return status code
267  */
268 static void dhcp_finished ( struct dhcp_session *dhcp, int rc ) {
269 
270  /* Stop retry timer */
271  stop_timer ( &dhcp->timer );
272 
273  /* Shut down interfaces */
274  intf_shutdown ( &dhcp->xfer, rc );
275  intf_shutdown ( &dhcp->job, rc );
276 }
277 
278 /**
279  * Transition to new DHCP session state
280  *
281  * @v dhcp DHCP session
282  * @v state New session state
283  */
284 static void dhcp_set_state ( struct dhcp_session *dhcp,
285  struct dhcp_session_state *state ) {
286 
287  DBGC ( dhcp, "DHCP %p entering %s state\n", dhcp, state->name );
288  dhcp->state = state;
289  dhcp->start = currticks();
290  stop_timer ( &dhcp->timer );
291  set_timer_limits ( &dhcp->timer,
292  ( state->min_timeout_sec * TICKS_PER_SEC ),
293  ( state->max_timeout_sec * TICKS_PER_SEC ) );
294  start_timer_nodelay ( &dhcp->timer );
295 }
296 
297 /**
298  * Check if DHCP packet contains PXE options
299  *
300  * @v dhcppkt DHCP packet
301  * @ret has_pxeopts DHCP packet contains PXE options
302  *
303  * It is assumed that the packet is already known to contain option 60
304  * set to "PXEClient".
305  */
306 static int dhcp_has_pxeopts ( struct dhcp_packet *dhcppkt ) {
307 
308  /* Check for a next-server and boot filename */
309  if ( dhcppkt->dhcphdr->siaddr.s_addr &&
310  ( dhcppkt_fetch ( dhcppkt, DHCP_BOOTFILE_NAME, NULL, 0 ) > 0 ) )
311  return 1;
312 
313  /* Check for a PXE boot menu */
314  if ( dhcppkt_fetch ( dhcppkt, DHCP_PXE_BOOT_MENU, NULL, 0 ) > 0 )
315  return 1;
316 
317  return 0;
318 }
319 
320 /****************************************************************************
321  *
322  * DHCP state machine
323  *
324  */
325 
326 /**
327  * Construct transmitted packet for DHCP discovery
328  *
329  * @v dhcp DHCP session
330  * @v dhcppkt DHCP packet
331  * @v peer Destination address
332  */
333 static int dhcp_discovery_tx ( struct dhcp_session *dhcp,
334  struct dhcp_packet *dhcppkt __unused,
335  struct sockaddr_in *peer ) {
336 
337  DBGC ( dhcp, "DHCP %p DHCPDISCOVER\n", dhcp );
338 
339  /* Set server address */
340  peer->sin_addr.s_addr = INADDR_BROADCAST;
341  peer->sin_port = htons ( BOOTPS_PORT );
342 
343  return 0;
344 }
345 
346 /**
347  * Handle received packet during DHCP discovery
348  *
349  * @v dhcp DHCP session
350  * @v dhcppkt DHCP packet
351  * @v peer DHCP server address
352  * @v msgtype DHCP message type
353  * @v server_id DHCP server ID
354  * @v pseudo_id DHCP server pseudo-ID
355  */
356 static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
357  struct dhcp_packet *dhcppkt,
358  struct sockaddr_in *peer, uint8_t msgtype,
359  struct in_addr server_id,
360  struct in_addr pseudo_id ) {
361  struct in_addr ip;
362  char vci[9]; /* "PXEClient" */
363  int vci_len;
364  int has_pxeclient;
365  int8_t priority = 0;
366  uint8_t no_pxedhcp = 0;
367  unsigned long elapsed;
368 
369  DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
370  dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
371  ntohs ( peer->sin_port ) );
372  if ( ( server_id.s_addr != peer->sin_addr.s_addr ) ||
373  ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) {
374  DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) );
375  DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) );
376  }
377 
378  /* Identify offered IP address */
379  ip = dhcppkt->dhcphdr->yiaddr;
380  if ( ip.s_addr )
381  DBGC ( dhcp, " for %s", inet_ntoa ( ip ) );
382 
383  /* Identify "PXEClient" vendor class */
384  vci_len = dhcppkt_fetch ( dhcppkt, DHCP_VENDOR_CLASS_ID,
385  vci, sizeof ( vci ) );
386  has_pxeclient = ( ( vci_len >= ( int ) sizeof ( vci ) ) &&
387  ( strncmp ( "PXEClient", vci, sizeof (vci) ) == 0 ));
388  if ( has_pxeclient ) {
389  DBGC ( dhcp, "%s",
390  ( dhcp_has_pxeopts ( dhcppkt ) ? " pxe" : " proxy" ) );
391  }
392 
393  /* Identify priority */
395  sizeof ( priority ) );
396  if ( priority )
397  DBGC ( dhcp, " pri %d", priority );
398 
399  /* Identify ignore-PXE flag */
400  dhcppkt_fetch ( dhcppkt, DHCP_EB_NO_PXEDHCP, &no_pxedhcp,
401  sizeof ( no_pxedhcp ) );
402  if ( no_pxedhcp )
403  DBGC ( dhcp, " nopxe" );
404  DBGC ( dhcp, "\n" );
405 
406  /* Select as DHCP offer, if applicable */
407  if ( ip.s_addr && ( peer->sin_port == htons ( BOOTPS_PORT ) ) &&
408  ( ( msgtype == DHCPOFFER ) || ( ! msgtype /* BOOTP */ ) ) &&
409  ( priority >= dhcp->priority ) ) {
410  dhcp->offer = ip;
411  dhcp->server = server_id;
412  dhcp->priority = priority;
413  dhcp->no_pxedhcp = no_pxedhcp;
414  }
415 
416  /* Select as ProxyDHCP offer, if applicable */
417  if ( pseudo_id.s_addr && has_pxeclient &&
418  ( priority >= dhcp->proxy_priority ) ) {
419  dhcppkt_put ( dhcp->proxy_offer );
420  dhcp->proxy_server = pseudo_id;
421  dhcp->proxy_offer = dhcppkt_get ( dhcppkt );
422  dhcp->proxy_priority = priority;
423  }
424 
425  /* We can exit the discovery state when we have a valid
426  * DHCPOFFER, and either:
427  *
428  * o The DHCPOFFER instructs us to ignore ProxyDHCPOFFERs, or
429  * o We have a valid ProxyDHCPOFFER, or
430  * o We have allowed sufficient time for ProxyDHCPOFFERs.
431  */
432 
433  /* If we don't yet have a DHCPOFFER, do nothing */
434  if ( ! dhcp->offer.s_addr )
435  return;
436 
437  /* If we can't yet transition to DHCPREQUEST, do nothing */
438  elapsed = ( currticks() - dhcp->start );
439  if ( ! ( dhcp->no_pxedhcp || dhcp->proxy_offer ||
440  ( elapsed > DHCP_DISC_PROXY_TIMEOUT_SEC * TICKS_PER_SEC ) ) )
441  return;
442 
443  /* Transition to DHCPREQUEST */
445 }
446 
447 /**
448  * Defer DHCP discovery
449  *
450  * @v dhcp DHCP session
451  */
452 static void dhcp_defer ( struct dhcp_session *dhcp ) {
453 
454  /* Do nothing if we have reached the deferral limit */
455  if ( dhcp->count > DHCP_DISC_MAX_DEFERRALS )
456  return;
457 
458  /* Return to discovery state */
459  DBGC ( dhcp, "DHCP %p deferring discovery\n", dhcp );
461 
462  /* Delay first DHCPDISCOVER */
463  start_timer_fixed ( &dhcp->timer,
465 }
466 
467 /**
468  * Handle timer expiry during DHCP discovery
469  *
470  * @v dhcp DHCP session
471  */
472 static void dhcp_discovery_expired ( struct dhcp_session *dhcp ) {
473  unsigned long elapsed = ( currticks() - dhcp->start );
474 
475  /* Give up waiting for ProxyDHCP before we reach the failure point */
476  if ( dhcp->offer.s_addr &&
477  ( elapsed > DHCP_DISC_PROXY_TIMEOUT_SEC * TICKS_PER_SEC ) ) {
479  return;
480  }
481 
482  /* Retransmit current packet */
483  dhcp_tx ( dhcp );
484 
485  /* If link is blocked, defer DHCP discovery timeout */
486  if ( netdev_link_blocked ( dhcp->netdev ) )
487  dhcp_defer ( dhcp );
488 }
489 
490 /** DHCP discovery state operations */
491 static struct dhcp_session_state dhcp_state_discover = {
492  .name = "discovery",
493  .tx = dhcp_discovery_tx,
494  .rx = dhcp_discovery_rx,
495  .expired = dhcp_discovery_expired,
496  .tx_msgtype = DHCPDISCOVER,
497  .min_timeout_sec = DHCP_DISC_START_TIMEOUT_SEC,
498  .max_timeout_sec = DHCP_DISC_END_TIMEOUT_SEC,
499 };
500 
501 /**
502  * Construct transmitted packet for DHCP request
503  *
504  * @v dhcp DHCP session
505  * @v dhcppkt DHCP packet
506  * @v peer Destination address
507  */
508 static int dhcp_request_tx ( struct dhcp_session *dhcp,
509  struct dhcp_packet *dhcppkt,
510  struct sockaddr_in *peer ) {
511  int rc;
512 
513  DBGC ( dhcp, "DHCP %p DHCPREQUEST to %s:%d",
514  dhcp, inet_ntoa ( dhcp->server ), BOOTPS_PORT );
515  DBGC ( dhcp, " for %s\n", inet_ntoa ( dhcp->offer ) );
516 
517  /* Set server ID */
518  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_SERVER_IDENTIFIER,
519  &dhcp->server,
520  sizeof ( dhcp->server ) ) ) != 0 )
521  return rc;
522 
523  /* Set requested IP address */
524  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_REQUESTED_ADDRESS,
525  &dhcp->offer,
526  sizeof ( dhcp->offer ) ) ) != 0 )
527  return rc;
528 
529  /* Set server address */
530  peer->sin_addr.s_addr = INADDR_BROADCAST;
531  peer->sin_port = htons ( BOOTPS_PORT );
532 
533  return 0;
534 }
535 
536 /**
537  * Handle received packet during DHCP request
538  *
539  * @v dhcp DHCP session
540  * @v dhcppkt DHCP packet
541  * @v peer DHCP server address
542  * @v msgtype DHCP message type
543  * @v server_id DHCP server ID
544  * @v pseudo_id DHCP server pseudo-ID
545  */
546 static void dhcp_request_rx ( struct dhcp_session *dhcp,
547  struct dhcp_packet *dhcppkt,
548  struct sockaddr_in *peer, uint8_t msgtype,
549  struct in_addr server_id,
550  struct in_addr pseudo_id ) {
551  struct in_addr ip;
552  struct settings *parent;
553  struct settings *settings;
554  int rc;
555 
556  DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
557  dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
558  ntohs ( peer->sin_port ) );
559  if ( ( server_id.s_addr != peer->sin_addr.s_addr ) ||
560  ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) {
561  DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) );
562  DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) );
563  }
564 
565  /* Identify leased IP address */
566  ip = dhcppkt->dhcphdr->yiaddr;
567  if ( ip.s_addr )
568  DBGC ( dhcp, " for %s", inet_ntoa ( ip ) );
569  DBGC ( dhcp, "\n" );
570 
571  /* Filter out invalid port */
572  if ( peer->sin_port != htons ( BOOTPS_PORT ) )
573  return;
574 
575  /* Filter out non-selected servers */
576  if ( server_id.s_addr != dhcp->server.s_addr )
577  return;
578 
579  /* Handle DHCPNAK */
580  if ( msgtype == DHCPNAK ) {
581  dhcp_defer ( dhcp );
582  return;
583  }
584 
585  /* Filter out unacceptable responses */
586  if ( msgtype /* BOOTP */ && ( msgtype != DHCPACK ) )
587  return;
588  if ( ip.s_addr != dhcp->offer.s_addr )
589  return;
590 
591  /* Record assigned address */
592  dhcp->local.sin_addr = ip;
593 
594  /* Register settings */
595  parent = netdev_settings ( dhcp->netdev );
596  settings = &dhcppkt->settings;
597  if ( ( rc = register_settings ( settings, parent,
598  DHCP_SETTINGS_NAME ) ) != 0 ) {
599  DBGC ( dhcp, "DHCP %p could not register settings: %s\n",
600  dhcp, strerror ( rc ) );
601  dhcp_finished ( dhcp, rc );
602  return;
603  }
604 
605  /* Unregister any existing ProxyDHCP or PXEBS settings */
608  if ( ( settings = find_settings ( PXEBS_SETTINGS_NAME ) ) != NULL )
610 
611  /* Perform ProxyDHCP if applicable */
612  if ( dhcp->proxy_offer /* Have ProxyDHCP offer */ &&
613  ( ! dhcp->no_pxedhcp ) /* ProxyDHCP not disabled */ ) {
614  if ( dhcp_has_pxeopts ( dhcp->proxy_offer ) ) {
615  /* PXE options already present; register settings
616  * without performing a ProxyDHCPREQUEST
617  */
618  settings = &dhcp->proxy_offer->settings;
619  if ( ( rc = register_settings ( settings, NULL,
620  PROXYDHCP_SETTINGS_NAME ) ) != 0 ) {
621  DBGC ( dhcp, "DHCP %p could not register "
622  "proxy settings: %s\n",
623  dhcp, strerror ( rc ) );
624  dhcp_finished ( dhcp, rc );
625  return;
626  }
627  } else {
628  /* PXE options not present; use a ProxyDHCPREQUEST */
629  dhcp_set_state ( dhcp, &dhcp_state_proxy );
630  return;
631  }
632  }
633 
634  /* Terminate DHCP */
635  dhcp_finished ( dhcp, 0 );
636 }
637 
638 /**
639  * Handle timer expiry during DHCP discovery
640  *
641  * @v dhcp DHCP session
642  */
643 static void dhcp_request_expired ( struct dhcp_session *dhcp ) {
644 
645  /* Retransmit current packet */
646  dhcp_tx ( dhcp );
647 }
648 
649 /** DHCP request state operations */
650 static struct dhcp_session_state dhcp_state_request = {
651  .name = "request",
652  .tx = dhcp_request_tx,
653  .rx = dhcp_request_rx,
654  .expired = dhcp_request_expired,
655  .tx_msgtype = DHCPREQUEST,
656  .min_timeout_sec = DHCP_REQ_START_TIMEOUT_SEC,
657  .max_timeout_sec = DHCP_REQ_END_TIMEOUT_SEC,
658 };
659 
660 /**
661  * Construct transmitted packet for ProxyDHCP request
662  *
663  * @v dhcp DHCP session
664  * @v dhcppkt DHCP packet
665  * @v peer Destination address
666  */
667 static int dhcp_proxy_tx ( struct dhcp_session *dhcp,
668  struct dhcp_packet *dhcppkt,
669  struct sockaddr_in *peer ) {
670  int rc;
671 
672  DBGC ( dhcp, "DHCP %p ProxyDHCP REQUEST to %s\n", dhcp,
673  inet_ntoa ( dhcp->proxy_server ) );
674 
675  /* Set server ID */
676  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_SERVER_IDENTIFIER,
677  &dhcp->proxy_server,
678  sizeof ( dhcp->proxy_server ) ) ) != 0 )
679  return rc;
680 
681  /* Set server address */
682  peer->sin_addr = dhcp->proxy_server;
683  peer->sin_port = htons ( PXE_PORT );
684 
685  return 0;
686 }
687 
688 /**
689  * Handle received packet during ProxyDHCP request
690  *
691  * @v dhcp DHCP session
692  * @v dhcppkt DHCP packet
693  * @v peer DHCP server address
694  * @v msgtype DHCP message type
695  * @v server_id DHCP server ID
696  * @v pseudo_id DHCP server pseudo-ID
697  */
698 static void dhcp_proxy_rx ( struct dhcp_session *dhcp,
699  struct dhcp_packet *dhcppkt,
700  struct sockaddr_in *peer, uint8_t msgtype,
701  struct in_addr server_id,
702  struct in_addr pseudo_id ) {
703  struct settings *settings = &dhcppkt->settings;
704  int rc;
705 
706  DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
707  dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
708  ntohs ( peer->sin_port ) );
709  if ( ( server_id.s_addr != peer->sin_addr.s_addr ) ||
710  ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) {
711  DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) );
712  DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) );
713  }
714  if ( dhcp_has_pxeopts ( dhcppkt ) )
715  DBGC ( dhcp, " pxe" );
716  DBGC ( dhcp, "\n" );
717 
718  /* Filter out unacceptable responses */
719  if ( peer->sin_port != ntohs ( PXE_PORT ) )
720  return;
721  if ( ( msgtype != DHCPOFFER ) && ( msgtype != DHCPACK ) )
722  return;
723  if ( ( pseudo_id.s_addr != dhcp->proxy_server.s_addr ) )
724  return;
725  if ( ! dhcp_has_pxeopts ( dhcppkt ) )
726  return;
727 
728  /* Register settings */
729  if ( ( rc = register_settings ( settings, NULL,
730  PROXYDHCP_SETTINGS_NAME ) ) != 0 ) {
731  DBGC ( dhcp, "DHCP %p could not register proxy settings: %s\n",
732  dhcp, strerror ( rc ) );
733  dhcp_finished ( dhcp, rc );
734  return;
735  }
736 
737  /* Terminate DHCP */
738  dhcp_finished ( dhcp, 0 );
739 }
740 
741 /**
742  * Handle timer expiry during ProxyDHCP request
743  *
744  * @v dhcp DHCP session
745  */
746 static void dhcp_proxy_expired ( struct dhcp_session *dhcp ) {
747  unsigned long elapsed = ( currticks() - dhcp->start );
748 
749  /* Give up waiting for ProxyDHCP before we reach the failure point */
750  if ( elapsed > DHCP_REQ_PROXY_TIMEOUT_SEC * TICKS_PER_SEC ) {
751  dhcp_finished ( dhcp, 0 );
752  return;
753  }
754 
755  /* Retransmit current packet */
756  dhcp_tx ( dhcp );
757 }
758 
759 /** ProxyDHCP request state operations */
760 static struct dhcp_session_state dhcp_state_proxy = {
761  .name = "ProxyDHCP",
762  .tx = dhcp_proxy_tx,
763  .rx = dhcp_proxy_rx,
764  .expired = dhcp_proxy_expired,
765  .tx_msgtype = DHCPREQUEST,
766  .min_timeout_sec = DHCP_PROXY_START_TIMEOUT_SEC,
767  .max_timeout_sec = DHCP_PROXY_END_TIMEOUT_SEC,
768 };
769 
770 /**
771  * Construct transmitted packet for PXE Boot Server Discovery
772  *
773  * @v dhcp DHCP session
774  * @v dhcppkt DHCP packet
775  * @v peer Destination address
776  */
777 static int dhcp_pxebs_tx ( struct dhcp_session *dhcp,
778  struct dhcp_packet *dhcppkt,
779  struct sockaddr_in *peer ) {
780  struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 };
781  int rc;
782 
783  /* Set server address */
784  peer->sin_addr = *(dhcp->pxe_attempt);
785  peer->sin_port = ( ( peer->sin_addr.s_addr == INADDR_BROADCAST ) ?
786  htons ( BOOTPS_PORT ) : htons ( PXE_PORT ) );
787 
788  DBGC ( dhcp, "DHCP %p PXEBS REQUEST to %s:%d for type %d\n",
789  dhcp, inet_ntoa ( peer->sin_addr ), ntohs ( peer->sin_port ),
790  le16_to_cpu ( dhcp->pxe_type ) );
791 
792  /* Set boot menu item */
793  menu_item.type = dhcp->pxe_type;
794  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_PXE_BOOT_MENU_ITEM,
795  &menu_item, sizeof ( menu_item ) ) ) != 0 )
796  return rc;
797 
798  return 0;
799 }
800 
801 /**
802  * Check to see if PXE Boot Server address is acceptable
803  *
804  * @v dhcp DHCP session
805  * @v bs Boot Server address
806  * @ret accept Boot Server is acceptable
807  */
808 static int dhcp_pxebs_accept ( struct dhcp_session *dhcp,
809  struct in_addr bs ) {
810  struct in_addr *accept;
811 
812  /* Accept if we have no acceptance filter */
813  if ( ! dhcp->pxe_accept )
814  return 1;
815 
816  /* Scan through acceptance list */
817  for ( accept = dhcp->pxe_accept ; accept->s_addr ; accept++ ) {
818  if ( accept->s_addr == bs.s_addr )
819  return 1;
820  }
821 
822  DBGC ( dhcp, "DHCP %p rejecting server %s\n",
823  dhcp, inet_ntoa ( bs ) );
824  return 0;
825 }
826 
827 /**
828  * Handle received packet during PXE Boot Server Discovery
829  *
830  * @v dhcp DHCP session
831  * @v dhcppkt DHCP packet
832  * @v peer DHCP server address
833  * @v msgtype DHCP message type
834  * @v server_id DHCP server ID
835  * @v pseudo_id DHCP server pseudo-ID
836  */
837 static void dhcp_pxebs_rx ( struct dhcp_session *dhcp,
838  struct dhcp_packet *dhcppkt,
839  struct sockaddr_in *peer, uint8_t msgtype,
840  struct in_addr server_id,
841  struct in_addr pseudo_id ) {
842  struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 };
843  int rc;
844 
845  DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
846  dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
847  ntohs ( peer->sin_port ) );
848  if ( ( server_id.s_addr != peer->sin_addr.s_addr ) ||
849  ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) {
850  DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) );
851  DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) );
852  }
853 
854  /* Identify boot menu item */
856  &menu_item, sizeof ( menu_item ) );
857  if ( menu_item.type )
858  DBGC ( dhcp, " for type %d", ntohs ( menu_item.type ) );
859  DBGC ( dhcp, "\n" );
860 
861  /* Filter out unacceptable responses */
862  if ( ( peer->sin_port != htons ( BOOTPS_PORT ) ) &&
863  ( peer->sin_port != htons ( PXE_PORT ) ) )
864  return;
865  if ( msgtype != DHCPACK )
866  return;
867  if ( menu_item.type != dhcp->pxe_type )
868  return;
869  if ( ! dhcp_pxebs_accept ( dhcp, pseudo_id ) )
870  return;
871 
872  /* Register settings */
873  if ( ( rc = register_settings ( &dhcppkt->settings, NULL,
874  PXEBS_SETTINGS_NAME ) ) != 0 ) {
875  DBGC ( dhcp, "DHCP %p could not register settings: %s\n",
876  dhcp, strerror ( rc ) );
877  dhcp_finished ( dhcp, rc );
878  return;
879  }
880 
881  /* Terminate DHCP */
882  dhcp_finished ( dhcp, 0 );
883 }
884 
885 /**
886  * Handle timer expiry during PXE Boot Server Discovery
887  *
888  * @v dhcp DHCP session
889  */
890 static void dhcp_pxebs_expired ( struct dhcp_session *dhcp ) {
891  unsigned long elapsed = ( currticks() - dhcp->start );
892 
893  /* Give up waiting before we reach the failure point, and fail
894  * over to the next server in the attempt list
895  */
896  if ( elapsed > PXEBS_MAX_TIMEOUT_SEC * TICKS_PER_SEC ) {
897  dhcp->pxe_attempt++;
898  if ( dhcp->pxe_attempt->s_addr ) {
899  dhcp_set_state ( dhcp, &dhcp_state_pxebs );
900  return;
901  } else {
902  dhcp_finished ( dhcp, -ETIMEDOUT );
903  return;
904  }
905  }
906 
907  /* Retransmit current packet */
908  dhcp_tx ( dhcp );
909 }
910 
911 /** PXE Boot Server Discovery state operations */
912 static struct dhcp_session_state dhcp_state_pxebs = {
913  .name = "PXEBS",
914  .tx = dhcp_pxebs_tx,
915  .rx = dhcp_pxebs_rx,
916  .expired = dhcp_pxebs_expired,
917  .tx_msgtype = DHCPREQUEST,
918  .min_timeout_sec = PXEBS_START_TIMEOUT_SEC,
919  .max_timeout_sec = PXEBS_END_TIMEOUT_SEC,
920 };
921 
922 /****************************************************************************
923  *
924  * Packet construction
925  *
926  */
927 
928 /**
929  * Create a DHCP packet
930  *
931  * @v dhcppkt DHCP packet structure to fill in
932  * @v netdev Network device
933  * @v msgtype DHCP message type
934  * @v xid Transaction ID (in network-endian order)
935  * @v options Initial options to include (or NULL)
936  * @v options_len Length of initial options
937  * @v data Buffer for DHCP packet
938  * @v max_len Size of DHCP packet buffer
939  * @ret rc Return status code
940  *
941  * Creates a DHCP packet in the specified buffer, and initialise a
942  * DHCP packet structure.
943  */
944 int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
945  struct net_device *netdev, uint8_t msgtype,
946  uint32_t xid, const void *options, size_t options_len,
947  void *data, size_t max_len ) {
948  struct dhcphdr *dhcphdr = data;
949  int rc;
950 
951  /* Sanity check */
952  if ( max_len < ( sizeof ( *dhcphdr ) + options_len ) )
953  return -ENOSPC;
954 
955  /* Initialise DHCP packet content */
956  memset ( dhcphdr, 0, max_len );
957  dhcphdr->xid = xid;
960  dhcphdr->op = dhcp_op[msgtype];
964  memcpy ( dhcphdr->options, options, options_len );
965 
966  /* If the local link-layer address functions only as a name
967  * (i.e. cannot be used as a destination address), then
968  * request broadcast responses.
969  */
972 
973  /* If the network device already has an IPv4 address then
974  * unicast responses from the DHCP server may be rejected, so
975  * request broadcast responses.
976  */
977  if ( ipv4_has_any_addr ( netdev ) )
979 
980  /* Initialise DHCP packet structure */
981  memset ( dhcppkt, 0, sizeof ( *dhcppkt ) );
982  dhcppkt_init ( dhcppkt, data, max_len );
983 
984  /* Set DHCP_MESSAGE_TYPE option */
985  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_MESSAGE_TYPE,
986  &msgtype, sizeof ( msgtype ) ) ) != 0 )
987  return rc;
988 
989  return 0;
990 }
991 
992 /**
993  * Create DHCP request packet
994  *
995  * @v dhcppkt DHCP packet structure to fill in
996  * @v netdev Network device
997  * @v msgtype DHCP message type
998  * @v xid Transaction ID (in network-endian order)
999  * @v ciaddr Client IP address
1000  * @v data Buffer for DHCP packet
1001  * @v max_len Size of DHCP packet buffer
1002  * @ret rc Return status code
1003  *
1004  * Creates a DHCP request packet in the specified buffer, and
1005  * initialise a DHCP packet structure.
1006  */
1007 int dhcp_create_request ( struct dhcp_packet *dhcppkt,
1008  struct net_device *netdev, unsigned int msgtype,
1009  uint32_t xid, struct in_addr ciaddr,
1010  void *data, size_t max_len ) {
1011  struct dhcp_netdev_desc dhcp_desc;
1012  struct dhcp_client_id client_id;
1013  struct dhcp_client_uuid client_uuid;
1014  const struct setting *setting;
1015  uint8_t *dhcp_features;
1016  size_t dhcp_features_len;
1017  size_t ll_addr_len;
1018  void *raw;
1019  ssize_t len;
1020  unsigned int i;
1021  int rc;
1022 
1023  /* Create DHCP packet */
1024  if ( ( rc = dhcp_create_packet ( dhcppkt, netdev, msgtype, xid,
1026  sizeof ( dhcp_request_options_data ),
1027  data, max_len ) ) != 0 ) {
1028  DBG ( "DHCP could not create DHCP packet: %s\n",
1029  strerror ( rc ) );
1030  goto err_create_packet;
1031  }
1032 
1033  /* Set client IP address */
1034  dhcppkt->dhcphdr->ciaddr = ciaddr;
1035 
1036  /* Add options to identify the feature list */
1037  dhcp_features = table_start ( DHCP_FEATURES );
1038  dhcp_features_len = table_num_entries ( DHCP_FEATURES );
1039  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_EB_ENCAP, dhcp_features,
1040  dhcp_features_len ) ) != 0 ) {
1041  DBG ( "DHCP could not set features list option: %s\n",
1042  strerror ( rc ) );
1043  goto err_store_features;
1044  }
1045 
1046  /* Add options to identify the network device */
1047  fetch_raw_setting ( netdev_settings ( netdev ), &busid_setting,
1048  &dhcp_desc, sizeof ( dhcp_desc ) );
1049  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_EB_BUS_ID, &dhcp_desc,
1050  sizeof ( dhcp_desc ) ) ) != 0 ) {
1051  DBG ( "DHCP could not set bus ID option: %s\n",
1052  strerror ( rc ) );
1053  goto err_store_busid;
1054  }
1055 
1056  /* Add DHCP client identifier. Required for Infiniband, and
1057  * doesn't hurt other link layers.
1058  */
1059  client_id.ll_proto = ntohs ( netdev->ll_protocol->ll_proto );
1060  ll_addr_len = netdev->ll_protocol->ll_addr_len;
1061  assert ( ll_addr_len <= sizeof ( client_id.ll_addr ) );
1062  memcpy ( client_id.ll_addr, netdev->ll_addr, ll_addr_len );
1063  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_CLIENT_ID, &client_id,
1064  ( ll_addr_len + 1 ) ) ) != 0 ) {
1065  DBG ( "DHCP could not set client ID: %s\n",
1066  strerror ( rc ) );
1067  goto err_store_client_id;
1068  }
1069 
1070  /* Add client UUID, if we have one. Required for PXE. The
1071  * PXE spec does not specify a byte ordering for UUIDs, but
1072  * RFC4578 suggests that it follows the EFI spec, in which the
1073  * first three fields are little-endian.
1074  */
1075  client_uuid.type = DHCP_CLIENT_UUID_TYPE;
1076  if ( ( len = fetch_uuid_setting ( NULL, &uuid_setting,
1077  &client_uuid.uuid ) ) >= 0 ) {
1078  uuid_mangle ( &client_uuid.uuid );
1079  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_CLIENT_UUID,
1080  &client_uuid,
1081  sizeof ( client_uuid ) ) ) != 0 ) {
1082  DBG ( "DHCP could not set client UUID: %s\n",
1083  strerror ( rc ) );
1084  goto err_store_client_uuid;
1085  }
1086  }
1087 
1088  /* Add request settings, if applicable */
1089  for ( i = 0 ; i < ( sizeof ( dhcp_request_settings ) /
1090  sizeof ( dhcp_request_settings[0] ) ) ; i++ ) {
1092  if ( ( len = fetch_raw_setting_copy ( NULL, setting,
1093  &raw ) ) >= 0 ) {
1094  rc = dhcppkt_store ( dhcppkt, setting->tag, raw, len );
1095  free ( raw );
1096  if ( rc != 0 ) {
1097  DBG ( "DHCP could not set %s: %s\n",
1098  setting->name, strerror ( rc ) );
1099  goto err_store_raw;
1100  }
1101  }
1102  }
1103 
1104  err_store_raw:
1105  err_store_client_uuid:
1106  err_store_client_id:
1107  err_store_busid:
1108  err_store_features:
1109  err_create_packet:
1110  return rc;
1111 }
1112 
1113 /****************************************************************************
1114  *
1115  * Data transfer interface
1116  *
1117  */
1118 
1119 /**
1120  * Transmit DHCP request
1121  *
1122  * @v dhcp DHCP session
1123  * @ret rc Return status code
1124  */
1125 static int dhcp_tx ( struct dhcp_session *dhcp ) {
1126  static struct sockaddr_in peer = {
1127  .sin_family = AF_INET,
1128  };
1129  struct xfer_metadata meta = {
1130  .netdev = dhcp->netdev,
1131  .src = ( struct sockaddr * ) &dhcp->local,
1132  .dest = ( struct sockaddr * ) &peer,
1133  };
1134  struct io_buffer *iobuf;
1135  uint8_t msgtype = dhcp->state->tx_msgtype;
1136  struct dhcp_packet dhcppkt;
1137  int rc;
1138 
1139  /* Start retry timer. Do this first so that failures to
1140  * transmit will be retried.
1141  */
1142  start_timer ( &dhcp->timer );
1143 
1144  /* Allocate buffer for packet */
1145  iobuf = xfer_alloc_iob ( &dhcp->xfer, DHCP_MIN_LEN );
1146  if ( ! iobuf )
1147  return -ENOMEM;
1148 
1149  /* Create basic DHCP packet in temporary buffer */
1150  if ( ( rc = dhcp_create_request ( &dhcppkt, dhcp->netdev, msgtype,
1151  dhcp->xid, dhcp->local.sin_addr,
1152  iobuf->data,
1153  iob_tailroom ( iobuf ) ) ) != 0 ) {
1154  DBGC ( dhcp, "DHCP %p could not construct DHCP request: %s\n",
1155  dhcp, strerror ( rc ) );
1156  goto done;
1157  }
1158 
1159  /* (Ab)use the "secs" field to convey metadata about the DHCP
1160  * session state into packet traces. Useful for extracting
1161  * debug information from non-debug builds.
1162  */
1163  dhcppkt.dhcphdr->secs = htons ( ( dhcp->count << 2 ) |
1164  ( dhcp->offer.s_addr ? 0x02 : 0 ) |
1165  ( dhcp->proxy_offer ? 0x01 : 0 ) );
1166 
1167  /* Fill in packet based on current state */
1168  if ( ( rc = dhcp->state->tx ( dhcp, &dhcppkt, &peer ) ) != 0 ) {
1169  DBGC ( dhcp, "DHCP %p could not fill DHCP request: %s\n",
1170  dhcp, strerror ( rc ) );
1171  goto done;
1172  }
1173 
1174  /* Transmit the packet */
1175  iob_put ( iobuf, dhcppkt_len ( &dhcppkt ) );
1176  if ( ( rc = xfer_deliver ( &dhcp->xfer, iob_disown ( iobuf ),
1177  &meta ) ) != 0 ) {
1178  DBGC ( dhcp, "DHCP %p could not transmit UDP packet: %s\n",
1179  dhcp, strerror ( rc ) );
1180  goto done;
1181  }
1182 
1183  done:
1184  free_iob ( iobuf );
1185  return rc;
1186 }
1187 
1188 /**
1189  * Receive new data
1190  *
1191  * @v dhcp DHCP session
1192  * @v iobuf I/O buffer
1193  * @v meta Transfer metadata
1194  * @ret rc Return status code
1195  */
1196 static int dhcp_deliver ( struct dhcp_session *dhcp,
1197  struct io_buffer *iobuf,
1198  struct xfer_metadata *meta ) {
1199  struct net_device *netdev = dhcp->netdev;
1201  struct sockaddr_in *peer;
1202  size_t data_len;
1203  struct dhcp_packet *dhcppkt;
1204  struct dhcphdr *dhcphdr;
1205  uint8_t msgtype = 0;
1206  struct in_addr server_id = { 0 };
1207  struct in_addr pseudo_id;
1208  int rc = 0;
1209 
1210  /* Sanity checks */
1211  if ( ! meta->src ) {
1212  DBGC ( dhcp, "DHCP %p received packet without source port\n",
1213  dhcp );
1214  rc = -EINVAL;
1215  goto err_no_src;
1216  }
1217  peer = ( struct sockaddr_in * ) meta->src;
1218 
1219  /* Create a DHCP packet containing the I/O buffer contents.
1220  * Whilst we could just use the original buffer in situ, that
1221  * would waste the unused space in the packet buffer, and also
1222  * waste a relatively scarce fully-aligned I/O buffer.
1223  */
1224  data_len = iob_len ( iobuf );
1225  dhcppkt = zalloc ( sizeof ( *dhcppkt ) + data_len );
1226  if ( ! dhcppkt ) {
1227  rc = -ENOMEM;
1228  goto err_alloc_dhcppkt;
1229  }
1230  dhcphdr = ( ( ( void * ) dhcppkt ) + sizeof ( *dhcppkt ) );
1231  memcpy ( dhcphdr, iobuf->data, data_len );
1232  dhcppkt_init ( dhcppkt, dhcphdr, data_len );
1233 
1234  /* Identify message type */
1235  dhcppkt_fetch ( dhcppkt, DHCP_MESSAGE_TYPE, &msgtype,
1236  sizeof ( msgtype ) );
1237 
1238  /* Identify server ID */
1240  &server_id, sizeof ( server_id ) );
1241 
1242  /* Identify server pseudo-ID */
1243  pseudo_id = server_id;
1244  if ( ! pseudo_id.s_addr )
1245  pseudo_id = dhcppkt->dhcphdr->siaddr;
1246  if ( ! pseudo_id.s_addr )
1247  pseudo_id = peer->sin_addr;
1248 
1249  /* Check for matching transaction ID */
1250  if ( dhcphdr->xid != dhcp->xid ) {
1251  DBGC ( dhcp, "DHCP %p %s from %s:%d has bad transaction "
1252  "ID\n", dhcp, dhcp_msgtype_name ( msgtype ),
1253  inet_ntoa ( peer->sin_addr ),
1254  ntohs ( peer->sin_port ) );
1255  rc = -EINVAL;
1256  goto err_xid;
1257  };
1258 
1259  /* Check for matching client hardware address */
1260  if ( memcmp ( dhcphdr->chaddr, netdev->ll_addr,
1261  ll_protocol->ll_addr_len ) != 0 ) {
1262  DBGC ( dhcp, "DHCP %p %s from %s:%d has bad chaddr %s\n",
1263  dhcp, dhcp_msgtype_name ( msgtype ),
1264  inet_ntoa ( peer->sin_addr ), ntohs ( peer->sin_port ),
1265  ll_protocol->ntoa ( dhcphdr->chaddr ) );
1266  rc = -EINVAL;
1267  goto err_chaddr;
1268  }
1269 
1270  /* Handle packet based on current state */
1271  dhcp->state->rx ( dhcp, dhcppkt, peer, msgtype, server_id, pseudo_id );
1272 
1273  err_chaddr:
1274  err_xid:
1275  dhcppkt_put ( dhcppkt );
1276  err_alloc_dhcppkt:
1277  err_no_src:
1278  free_iob ( iobuf );
1279  return rc;
1280 }
1281 
1282 /** DHCP data transfer interface operations */
1285 };
1286 
1287 /** DHCP data transfer interface descriptor */
1289  INTF_DESC ( struct dhcp_session, xfer, dhcp_xfer_operations );
1290 
1291 /**
1292  * Handle DHCP retry timer expiry
1293  *
1294  * @v timer DHCP retry timer
1295  * @v fail Failure indicator
1296  */
1297 static void dhcp_timer_expired ( struct retry_timer *timer, int fail ) {
1298  struct dhcp_session *dhcp =
1299  container_of ( timer, struct dhcp_session, timer );
1300 
1301  /* If we have failed, terminate DHCP */
1302  if ( fail ) {
1303  dhcp_finished ( dhcp, -ETIMEDOUT );
1304  return;
1305  }
1306 
1307  /* Increment transmission counter */
1308  dhcp->count++;
1309 
1310  /* Handle timer expiry based on current state */
1311  dhcp->state->expired ( dhcp );
1312 }
1313 
1314 /****************************************************************************
1315  *
1316  * Job control interface
1317  *
1318  */
1319 
1320 /** DHCP job control interface operations */
1323 };
1324 
1325 /** DHCP job control interface descriptor */
1327  INTF_DESC ( struct dhcp_session, job, dhcp_job_op );
1328 
1329 /****************************************************************************
1330  *
1331  * Instantiators
1332  *
1333  */
1334 
1335 /**
1336  * DHCP peer address for socket opening
1337  *
1338  * This is a dummy address; the only useful portion is the socket
1339  * family (so that we get a UDP connection). The DHCP client will set
1340  * the IP address and source port explicitly on each transmission.
1341  */
1342 static struct sockaddr dhcp_peer = {
1343  .sa_family = AF_INET,
1344 };
1345 
1346 /**
1347  * Start DHCP state machine on a network device
1348  *
1349  * @v job Job control interface
1350  * @v netdev Network device
1351  * @ret rc Return status code
1352  *
1353  * Starts DHCP on the specified network device. If successful, the
1354  * DHCPACK (and ProxyDHCPACK, if applicable) will be registered as
1355  * option sources.
1356  */
1357 int start_dhcp ( struct interface *job, struct net_device *netdev ) {
1358  struct dhcp_session *dhcp;
1359  int rc;
1360 
1361  /* Allocate and initialise structure */
1362  dhcp = zalloc ( sizeof ( *dhcp ) );
1363  if ( ! dhcp )
1364  return -ENOMEM;
1365  ref_init ( &dhcp->refcnt, dhcp_free );
1366  intf_init ( &dhcp->job, &dhcp_job_desc, &dhcp->refcnt );
1367  intf_init ( &dhcp->xfer, &dhcp_xfer_desc, &dhcp->refcnt );
1368  timer_init ( &dhcp->timer, dhcp_timer_expired, &dhcp->refcnt );
1369  dhcp->netdev = netdev_get ( netdev );
1370  dhcp->local.sin_family = AF_INET;
1371  dhcp->local.sin_port = htons ( BOOTPC_PORT );
1372  dhcp->xid = random();
1373 
1374  /* Store DHCP transaction ID for fakedhcp code */
1375  dhcp_last_xid = dhcp->xid;
1376 
1377  /* Instantiate child objects and attach to our interfaces */
1378  if ( ( rc = xfer_open_socket ( &dhcp->xfer, SOCK_DGRAM, &dhcp_peer,
1379  ( struct sockaddr * ) &dhcp->local ) ) != 0 )
1380  goto err;
1381 
1382  /* Enter DHCPDISCOVER state */
1384 
1385  /* Attach parent interface, mortalise self, and return */
1386  intf_plug_plug ( &dhcp->job, job );
1387  ref_put ( &dhcp->refcnt );
1388  return 0;
1389 
1390  err:
1391  dhcp_finished ( dhcp, rc );
1392  ref_put ( &dhcp->refcnt );
1393  return rc;
1394 }
1395 
1396 /**
1397  * Retrieve list of PXE boot servers for a given server type
1398  *
1399  * @v dhcp DHCP session
1400  * @v raw DHCP PXE boot server list
1401  * @v raw_len Length of DHCP PXE boot server list
1402  * @v ip IP address list to fill in
1403  *
1404  * The caller must ensure that the IP address list has sufficient
1405  * space.
1406  */
1407 static void pxebs_list ( struct dhcp_session *dhcp, void *raw,
1408  size_t raw_len, struct in_addr *ip ) {
1409  struct dhcp_pxe_boot_server *server = raw;
1410  size_t server_len;
1411  unsigned int i;
1412 
1413  while ( raw_len ) {
1414  if ( raw_len < sizeof ( *server ) ) {
1415  DBGC ( dhcp, "DHCP %p malformed PXE server list\n",
1416  dhcp );
1417  break;
1418  }
1419  server_len = offsetof ( typeof ( *server ),
1420  ip[ server->num_ip ] );
1421  if ( raw_len < server_len ) {
1422  DBGC ( dhcp, "DHCP %p malformed PXE server list\n",
1423  dhcp );
1424  break;
1425  }
1426  if ( server->type == dhcp->pxe_type ) {
1427  for ( i = 0 ; i < server->num_ip ; i++ )
1428  *(ip++) = server->ip[i];
1429  }
1430  server = ( ( ( void * ) server ) + server_len );
1431  raw_len -= server_len;
1432  }
1433 }
1434 
1435 /**
1436  * Start PXE Boot Server Discovery on a network device
1437  *
1438  * @v job Job control interface
1439  * @v netdev Network device
1440  * @v pxe_type PXE server type
1441  * @ret rc Return status code
1442  *
1443  * Starts PXE Boot Server Discovery on the specified network device.
1444  * If successful, the Boot Server ACK will be registered as an option
1445  * source.
1446  */
1447 int start_pxebs ( struct interface *job, struct net_device *netdev,
1448  unsigned int pxe_type ) {
1449  struct setting pxe_discovery_control_setting =
1451  struct setting pxe_boot_servers_setting =
1452  { .tag = DHCP_PXE_BOOT_SERVERS };
1453  struct setting pxe_boot_server_mcast_setting =
1455  ssize_t pxebs_list_len;
1456  struct dhcp_session *dhcp;
1457  struct in_addr *ip;
1458  unsigned int pxe_discovery_control;
1459  int rc;
1460 
1461  /* Get upper bound for PXE boot server IP address list */
1462  pxebs_list_len = fetch_raw_setting ( NULL, &pxe_boot_servers_setting,
1463  NULL, 0 );
1464  if ( pxebs_list_len < 0 )
1465  pxebs_list_len = 0;
1466 
1467  /* Allocate and initialise structure */
1468  dhcp = zalloc ( sizeof ( *dhcp ) + sizeof ( *ip ) /* mcast */ +
1469  sizeof ( *ip ) /* bcast */ + pxebs_list_len +
1470  sizeof ( *ip ) /* terminator */ );
1471  if ( ! dhcp )
1472  return -ENOMEM;
1473  ref_init ( &dhcp->refcnt, dhcp_free );
1474  intf_init ( &dhcp->job, &dhcp_job_desc, &dhcp->refcnt );
1475  intf_init ( &dhcp->xfer, &dhcp_xfer_desc, &dhcp->refcnt );
1476  timer_init ( &dhcp->timer, dhcp_timer_expired, &dhcp->refcnt );
1477  dhcp->netdev = netdev_get ( netdev );
1478  dhcp->local.sin_family = AF_INET;
1479  fetch_ipv4_setting ( netdev_settings ( netdev ), &ip_setting,
1480  &dhcp->local.sin_addr );
1481  dhcp->local.sin_port = htons ( BOOTPC_PORT );
1482  dhcp->pxe_type = cpu_to_le16 ( pxe_type );
1483 
1484  /* Construct PXE boot server IP address lists */
1485  pxe_discovery_control =
1486  fetch_uintz_setting ( NULL, &pxe_discovery_control_setting );
1487  ip = ( ( ( void * ) dhcp ) + sizeof ( *dhcp ) );
1488  dhcp->pxe_attempt = ip;
1489  if ( ! ( pxe_discovery_control & PXEBS_NO_MULTICAST ) ) {
1490  fetch_ipv4_setting ( NULL, &pxe_boot_server_mcast_setting, ip);
1491  if ( ip->s_addr )
1492  ip++;
1493  }
1494  if ( ! ( pxe_discovery_control & PXEBS_NO_BROADCAST ) )
1495  (ip++)->s_addr = INADDR_BROADCAST;
1496  if ( pxe_discovery_control & PXEBS_NO_UNKNOWN_SERVERS )
1497  dhcp->pxe_accept = ip;
1498  if ( pxebs_list_len ) {
1499  uint8_t buf[pxebs_list_len];
1500 
1501  fetch_raw_setting ( NULL, &pxe_boot_servers_setting,
1502  buf, sizeof ( buf ) );
1503  pxebs_list ( dhcp, buf, sizeof ( buf ), ip );
1504  }
1505  if ( ! dhcp->pxe_attempt->s_addr ) {
1506  DBGC ( dhcp, "DHCP %p has no PXE boot servers for type %04x\n",
1507  dhcp, pxe_type );
1508  rc = -EINVAL;
1509  goto err;
1510  }
1511 
1512  /* Dump out PXE server lists */
1513  DBGC ( dhcp, "DHCP %p attempting", dhcp );
1514  for ( ip = dhcp->pxe_attempt ; ip->s_addr ; ip++ )
1515  DBGC ( dhcp, " %s", inet_ntoa ( *ip ) );
1516  DBGC ( dhcp, "\n" );
1517  if ( dhcp->pxe_accept ) {
1518  DBGC ( dhcp, "DHCP %p accepting", dhcp );
1519  for ( ip = dhcp->pxe_accept ; ip->s_addr ; ip++ )
1520  DBGC ( dhcp, " %s", inet_ntoa ( *ip ) );
1521  DBGC ( dhcp, "\n" );
1522  }
1523 
1524  /* Instantiate child objects and attach to our interfaces */
1525  if ( ( rc = xfer_open_socket ( &dhcp->xfer, SOCK_DGRAM, &dhcp_peer,
1526  ( struct sockaddr * ) &dhcp->local ) ) != 0 )
1527  goto err;
1528 
1529  /* Enter PXEBS state */
1530  dhcp_set_state ( dhcp, &dhcp_state_pxebs );
1531 
1532  /* Attach parent interface, mortalise self, and return */
1533  intf_plug_plug ( &dhcp->job, job );
1534  ref_put ( &dhcp->refcnt );
1535  return 0;
1536 
1537  err:
1538  dhcp_finished ( dhcp, rc );
1539  ref_put ( &dhcp->refcnt );
1540  return rc;
1541 }
1542 
1543 /** DHCP network device configurator */
1545  .name = "dhcp",
1546  .start = start_dhcp,
1547 };
#define DHCP_FEATURES
DHCP feature table.
Definition: features.h:62
#define DHCP_REQUESTED_ADDRESS
Requested IP address.
Definition: dhcp.h:177
#define EINVAL
Invalid argument.
Definition: errno.h:428
#define DHCP_CLIENT_UUID
UUID client identifier.
Definition: dhcp.h:333
An object interface operation.
Definition: interface.h:17
#define DHCP_NTP_SERVERS
NTP servers.
Definition: dhcp.h:90
#define PXE_PORT
PXE server port.
Definition: dhcp.h:33
static void dhcp_set_state(struct dhcp_session *dhcp, struct dhcp_session_state *state)
Transition to new DHCP session state.
Definition: dhcp.c:284
static void dhcp_free(struct refcnt *refcnt)
Free DHCP session.
Definition: dhcp.c:253
#define DHCPOFFER
Definition: dhcp.h:199
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct dhcp_packet * proxy_offer
ProxyDHCP offer.
Definition: dhcp.c:229
void(* rx)(struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, struct sockaddr_in *peer, uint8_t msgtype, struct in_addr server_id, struct in_addr pseudo_id)
Handle received packet.
Definition: dhcp.c:178
unsigned short uint16_t
Definition: stdint.h:11
const char * name
Name.
Definition: netdevice.h:315
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:249
A DHCP packet.
Definition: dhcppkt.h:20
int proxy_priority
ProxyDHCP offer priority.
Definition: dhcp.c:231
Dynamic Host Configuration Protocol.
#define iob_put(iobuf, len)
Definition: iobuf.h:120
static struct interface_operation dhcp_xfer_operations[]
DHCP data transfer interface operations.
Definition: dhcp.c:1283
#define TICKS_PER_SEC
Number of ticks per second.
Definition: timer.h:15
Data transfer metadata.
Definition: xfer.h:22
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:278
#define DHCP_HOST_NAME
Host name.
Definition: dhcp.h:78
static int dhcp_deliver(struct dhcp_session *dhcp, struct io_buffer *iobuf, struct xfer_metadata *meta)
Receive new data.
Definition: dhcp.c:1196
static void dhcp_timer_expired(struct retry_timer *timer, int fail)
Handle DHCP retry timer expiry.
Definition: dhcp.c:1297
uint8_t num_ip
Number of IPv4 addresses.
Definition: dhcp.h:121
static void dhcp_discovery_expired(struct dhcp_session *dhcp)
Handle timer expiry during DHCP discovery.
Definition: dhcp.c:472
struct in_addr offer
Offered IP address.
Definition: dhcp.c:218
#define DHCP_LOG_SERVERS
Syslog servers.
Definition: dhcp.h:75
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
Definition: retry.h:99
uint8_t ll_addr_len
Link-layer address length.
Definition: netdevice.h:198
static void dhcp_finished(struct dhcp_session *dhcp, int rc)
Mark DHCP session as complete.
Definition: dhcp.c:268
static int dhcp_has_pxeopts(struct dhcp_packet *dhcppkt)
Check if DHCP packet contains PXE options.
Definition: dhcp.c:306
uint16_t type
"Type"
Definition: dhcp.h:119
uint8_t state
State.
Definition: eth_slow.h:47
#define table_start(table)
Get start of linker table.
Definition: tables.h:282
void unregister_settings(struct settings *settings)
Unregister settings block.
Definition: settings.c:514
struct retry_timer timer
Retransmission timer.
Definition: dhcp.c:241
#define DHCP_EB_ENCAP
Etherboot-specific encapsulated options.
Definition: dhcp.h:354
static const struct setting * dhcp_request_settings[]
Settings copied in to all DHCP requests.
Definition: dhcp.c:104
static struct interface_descriptor dhcp_job_desc
DHCP job control interface descriptor.
Definition: dhcp.c:1326
uint8_t tx_msgtype
Transmitted message type.
Definition: dhcp.c:188
int fetch_raw_setting_copy(struct settings *settings, const struct setting *setting, void **data)
Fetch value of setting.
Definition: settings.c:821
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:64
Error codes.
int xfer_open_socket(struct interface *intf, int semantics, struct sockaddr *peer, struct sockaddr *local)
Open socket.
Definition: open.c:142
struct settings * parent
Parent settings block.
Definition: settings.h:138
#define DHCP_ROUTERS
Routers.
Definition: dhcp.h:69
int fetch_ipv4_setting(struct settings *settings, const struct setting *setting, struct in_addr *inp)
Fetch value of IPv4 address setting.
Definition: settings.c:912
#define DHCP_ISCSI_INITIATOR_IQN
iSCSI initiator IQN
Definition: dhcp.h:536
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
#define DHCP_DOMAIN_NAME
Domain name.
Definition: dhcp.h:81
#define BOOTP_REPLY
Opcode for a reply from server to client.
Definition: dhcp.h:688
#define SOCK_DGRAM
Definition: socket.h:29
Retry timers.
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
unsigned int count
Transmission counter.
Definition: dhcp.c:243
uint8_t htype
Hardware address type.
Definition: dhcp.h:625
sa_family_t sa_family
Socket address family.
Definition: socket.h:101
#define DBGC(...)
Definition: compiler.h:505
#define DHCP_DISC_MAX_DEFERRALS
Definition: dhcp.h:31
#define LL_NAME_ONLY
Local link-layer address functions only as a name.
Definition: netdevice.h:210
#define BOOTP_FL_BROADCAST
BOOTP reply must be broadcast.
Definition: dhcp.h:695
A retry timer.
Definition: retry.h:21
static struct sockaddr dhcp_peer
DHCP peer address for socket opening.
Definition: dhcp.c:1342
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition: interface.c:107
#define DHCP_MESSAGE_TYPE
DHCP message type.
Definition: dhcp.h:196
unsigned long start
Start time of the current state (in ticks)
Definition: dhcp.c:245
void(* expired)(struct dhcp_session *dhcp)
Handle timer expiry.
Definition: dhcp.c:186
Universally unique IDs.
static int dhcp_pxebs_accept(struct dhcp_session *dhcp, struct in_addr bs)
Check to see if PXE Boot Server address is acceptable.
Definition: dhcp.c:808
int start_dhcp(struct interface *job, struct net_device *netdev)
Start DHCP state machine on a network device.
Definition: dhcp.c:1357
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition: xfer.c:158
int fetch_raw_setting(struct settings *settings, const struct setting *setting, void *data, size_t len)
Fetch value of setting.
Definition: settings.c:803
uint8_t options[0]
DHCP options.
Definition: dhcp.h:681
uint32_t xid
Transaction ID.
Definition: dhcp.h:631
IP protocol.
#define DHCP_PROXY_END_TIMEOUT_SEC
Definition: dhcp.h:60
int dhcp_create_request(struct dhcp_packet *dhcppkt, struct net_device *netdev, unsigned int msgtype, uint32_t xid, struct in_addr ciaddr, void *data, size_t max_len)
Create DHCP request packet.
Definition: dhcp.c:1007
A DHCP session.
Definition: dhcp.c:200
#define ETH_MAX_MTU
Definition: if_ether.h:14
uint32_t data_len
Microcode data size (or 0 to indicate 2000 bytes)
Definition: ucode.h:26
static void dhcp_discovery_rx(struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, struct sockaddr_in *peer, uint8_t msgtype, struct in_addr server_id, struct in_addr pseudo_id)
Handle received packet during DHCP discovery.
Definition: dhcp.c:356
struct refcnt refcnt
Reference counter.
Definition: dhcp.c:202
iPXE timers
#define SETTING_MISC
Miscellaneous settings.
Definition: settings.h:80
IPv4 socket address.
Definition: in.h:84
static uint8_t dhcp_request_options_data[]
Raw option data for options common to all DHCP requests.
Definition: dhcp.c:81
struct interface job
Job control interface.
Definition: dhcp.c:204
#define ntohs(value)
Definition: byteswap.h:136
#define BOOTPS_PORT
BOOTP/DHCP server port.
Definition: dhcp.h:27
DHCP configuration.
DHCP session state operations.
Definition: dhcp.c:156
#define offsetof(type, field)
Get offset of a field within a structure.
Definition: stddef.h:24
Character types.
uint16_t secs
Seconds since start of acquisition.
Definition: dhcp.h:633
#define DHCP_EB_NO_PXEDHCP
Skip PXE DHCP protocol extensions such as ProxyDHCP.
Definition: dhcp.h:430
static int netdev_link_blocked(struct net_device *netdev)
Check link block state of network device.
Definition: netdevice.h:647
static void dhcp_proxy_expired(struct dhcp_session *dhcp)
Handle timer expiry during ProxyDHCP request.
Definition: dhcp.c:746
sa_family_t sin_family
Socket address family (part of struct sockaddr)
Definition: in.h:89
static const uint8_t dhcp_op[]
DHCP operation types.
Definition: dhcp.c:69
#define DHCP_PROXY_START_TIMEOUT_SEC
Definition: dhcp.h:59
int no_pxedhcp
ProxyDHCP protocol extensions should be ignored.
Definition: dhcp.c:225
int strncmp(const char *first, const char *second, size_t max)
Compare strings.
Definition: string.c:186
#define htonl(value)
Definition: byteswap.h:133
#define DHCP_REQ_END_TIMEOUT_SEC
Definition: dhcp.h:52
static void pxebs_list(struct dhcp_session *dhcp, void *raw, size_t raw_len, struct in_addr *ip)
Retrieve list of PXE boot servers for a given server type.
Definition: dhcp.c:1407
static struct settings * netdev_settings(struct net_device *netdev)
Get per-netdevice configuration settings block.
Definition: netdevice.h:583
A link-layer protocol.
Definition: netdevice.h:114
struct in_addr proxy_server
ProxyDHCP server.
Definition: dhcp.c:227
uint32_t xid
Transaction ID (in network-endian order)
Definition: dhcp.c:215
Data transfer interfaces.
static void dhcp_proxy_rx(struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, struct sockaddr_in *peer, uint8_t msgtype, struct in_addr server_id, struct in_addr pseudo_id)
Handle received packet during ProxyDHCP request.
Definition: dhcp.c:698
A reference counter.
Definition: refcnt.h:26
A timer.
Definition: timer.h:28
const char * name
Name.
Definition: settings.h:28
int dhcp_create_packet(struct dhcp_packet *dhcppkt, struct net_device *netdev, uint8_t msgtype, uint32_t xid, const void *options, size_t options_len, void *data, size_t max_len)
Create a DHCP packet.
Definition: dhcp.c:944
static int dhcp_discovery_tx(struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt __unused, struct sockaddr_in *peer)
Construct transmitted packet for DHCP discovery.
Definition: dhcp.c:333
struct dhcp_session_state * state
State of the session.
Definition: dhcp.c:213
static void uuid_mangle(union uuid *uuid)
Change UUID endianness.
Definition: uuid.h:43
uint64_t tag
Setting tag, if applicable.
Definition: settings.h:43
static struct interface_operation dhcp_job_op[]
DHCP job control interface operations.
Definition: dhcp.c:1321
struct sockaddr_in local
Local socket address.
Definition: dhcp.c:211
uint16_t type
"Type"
Definition: dhcp.h:168
static void dhcp_defer(struct dhcp_session *dhcp)
Defer DHCP discovery.
Definition: dhcp.c:452
#define ENOMEM
Not enough space.
Definition: errno.h:534
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition: iobuf.h:212
const char * name
State name.
Definition: dhcp.c:158
void * memcpy(void *dest, const void *src, size_t len) __nonnull
DHCP client architecture definitions.
uint16_t flags
Flags.
Definition: dhcp.h:635
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
static struct interface_descriptor dhcp_xfer_desc
DHCP data transfer interface descriptor.
Definition: dhcp.c:1288
static struct dhcp_session_state dhcp_state_request
DHCP request state operations.
Definition: dhcp.c:195
int ipv4_has_any_addr(struct net_device *netdev)
Check if network device has any IPv4 address.
Definition: ipv4.c:443
#define DHCP_ROOT_PATH
Root path.
Definition: dhcp.h:84
#define BOOTP_REQUEST
Opcode for a request from client to server.
Definition: dhcp.h:685
uint8_t op
Operation.
Definition: dhcp.h:618
Assertions.
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition: netdevice.h:572
#define PROXYDHCP_SETTINGS_NAME
Settings block name used for ProxyDHCP responses.
Definition: dhcp.h:711
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
An object interface.
Definition: interface.h:124
static void dhcp_pxebs_rx(struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, struct sockaddr_in *peer, uint8_t msgtype, struct in_addr server_id, struct in_addr pseudo_id)
Handle received packet during PXE Boot Server Discovery.
Definition: dhcp.c:837
#define DHCP_MAX_MESSAGE_SIZE
Maximum DHCP message size.
Definition: dhcp.h:214
static void dhcp_pxebs_expired(struct dhcp_session *dhcp)
Handle timer expiry during PXE Boot Server Discovery.
Definition: dhcp.c:890
const struct setting dhcp_server_setting __setting(SETTING_MISC, dhcp-server)
DHCP server address setting.
#define DHCP_SERVER_IDENTIFIER
DHCP server identifier.
Definition: dhcp.h:208
static int options
Definition: 3c515.c:286
#define DHCP_MAGIC_COOKIE
DHCP magic cookie.
Definition: dhcp.h:698
#define DHCP_MIN_LEN
DHCP minimum packet length.
Definition: dhcp.h:705
static struct dhcp_session_state dhcp_state_proxy
ProxyDHCP request state operations.
Definition: dhcp.c:196
#define DHCP_SETTINGS_NAME
Settings block name used for DHCP responses.
Definition: dhcp.h:708
uint8_t min_timeout_sec
Timeout parameters.
Definition: dhcp.c:190
int(* tx)(struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, struct sockaddr_in *peer)
Construct transmitted packet.
Definition: dhcp.c:166
uint16_t pxe_type
PXE Boot Server type.
Definition: dhcp.c:234
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
Definition: dhcp.h:250
static struct net_device * netdev
Definition: gdbudp.c:52
#define DHCPINFORM
Definition: dhcp.h:205
Transport-network layer interface.
#define DHCP_CLIENT_NDI
Client network device interface.
Definition: dhcp.h:330
Feature list.
#define INADDR_BROADCAST
Definition: in.h:21
signed char int8_t
Definition: stdint.h:15
#define DHCP_ARCH_CLIENT_ARCHITECTURE
DHCP client architecture.
Definition: dhcparch.h:15
struct in_addr ciaddr
"Client" IP address
Definition: dhcp.h:641
#define DHCP_CLIENT_ARCHITECTURE
Client system architecture.
Definition: dhcp.h:271
#define DHCP_DOMAIN_SEARCH
DNS domain search list.
Definition: dhcp.h:346
#define DHCP_CLIENT_UUID_TYPE
Definition: dhcp.h:343
#define DHCPNAK
Definition: dhcp.h:203
#define PXEBS_SETTINGS_NAME
Setting block name used for BootServerDHCP responses.
Definition: dhcp.h:714
struct in_addr siaddr
"Server" IP address
Definition: dhcp.h:652
#define DHCP_MTU
Maximum transmission unit.
Definition: dhcp.h:87
#define DHCP_WORD(value)
Construct a word-valued DHCP option.
Definition: dhcp.h:560
int meta(WINDOW *, bool)
#define DHCP_SUBNET_MASK
Subnet mask.
Definition: dhcp.h:66
Configuration settings.
static size_t raw_len
Definition: base16.h:53
static int dhcp_tx(struct dhcp_session *dhcp)
Transmit DHCP request.
Definition: dhcp.c:1125
Generalized socket address structure.
Definition: socket.h:96
An object interface descriptor.
Definition: interface.h:55
struct interface xfer
Data transfer interface.
Definition: dhcp.c:206
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
#define DHCPRELEASE
Definition: dhcp.h:204
#define DHCPDISCOVER
Definition: dhcp.h:198
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
struct in_addr ip[0]
IPv4 addresses.
Definition: dhcp.h:123
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
IP address structure.
Definition: in.h:41
Client identifier.
Definition: dhcp.h:246
uint16_t sin_port
TCP/IP port (part of struct sockaddr_tcpip)
Definition: in.h:93
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:155
int dhcppkt_fetch(struct dhcp_packet *dhcppkt, unsigned int tag, void *data, size_t len)
Fetch value of DHCP packet setting.
Definition: dhcppkt.c:195
uint8_t chaddr[16]
Client hardware address.
Definition: dhcp.h:659
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:32
#define DHCP_REQ_PROXY_TIMEOUT_SEC
Definition: dhcp.h:69
int priority
DHCP offer priority.
Definition: dhcp.c:222
A network device.
Definition: netdevice.h:352
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition: random.c:31
static size_t iob_tailroom(struct io_buffer *iobuf)
Calculate available space at end of an I/O buffer.
Definition: iobuf.h:175
Network device descriptor.
Definition: dhcp.h:446
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:194
int dhcppkt_store(struct dhcp_packet *dhcppkt, unsigned int tag, const void *data, size_t len)
Store value of DHCP packet setting.
Definition: dhcppkt.c:164
char * inet_ntoa(struct in_addr in)
Convert IPv4 address to dotted-quad notation.
Definition: ipv4.c:668
IP4_t ip
Destination IP address.
Definition: pxe_api.h:58
A settings block.
Definition: settings.h:132
unsigned char uint8_t
Definition: stdint.h:10
#define DHCP_BYTE(value)
Construct a byte-valued DHCP option.
Definition: dhcp.h:557
Data transfer interface opening.
unsigned long fetch_uintz_setting(struct settings *settings, const struct setting *setting)
Fetch value of unsigned integer setting, or zero.
Definition: settings.c:1068
unsigned int flags
Flags.
Definition: netdevice.h:202
static struct net_device * netdev_get(struct net_device *netdev)
Get reference to network device.
Definition: netdevice.h:561
struct in_addr server
DHCP server.
Definition: dhcp.c:220
#define DHCP_PXE_BOOT_MENU
PXE boot menu.
Definition: dhcp.h:127
struct in_addr yiaddr
"Your" IP address
Definition: dhcp.h:646
#define DHCPACK
Definition: dhcp.h:202
#define DHCP_DISC_PROXY_TIMEOUT_SEC
Definition: dhcp.h:39
uint16_t ll_proto
Link-layer protocol.
Definition: netdevice.h:194
#define DHCP_PXE_BOOT_MENU_ITEM
PXE boot menu item.
Definition: dhcp.h:159
#define le16_to_cpu(value)
Definition: byteswap.h:112
unsigned int uint32_t
Definition: stdint.h:12
Accept only servers in DHCP_PXE_BOOT_SERVERS list.
Definition: dhcp.h:105
DHCP options.
Inhibit broadcast discovery.
Definition: dhcp.h:101
static const char * dhcp_msgtype_name(unsigned int msgtype)
Name a DHCP packet type.
Definition: dhcp.c:132
uint8_t max_timeout_sec
Definition: dhcp.c:191
A setting.
Definition: settings.h:23
Job control interfaces.
struct settings settings
Settings interface.
Definition: dhcppkt.h:28
UUID client identifier.
Definition: dhcp.h:336
void start_timer(struct retry_timer *timer)
Start timer.
Definition: retry.c:93
uint32_t s_addr
Definition: in.h:42
A DHCP header.
Definition: dhcp.h:613
Network device management.
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition: retry.c:64
#define DHCP_VENDOR_CLASS_ID
Vendor class identifier.
Definition: dhcp.h:217
PXE boot menu item.
Definition: dhcp.h:162
struct in_addr sin_addr
IPv4 address.
Definition: in.h:100
uint8_t type
Identifier type.
Definition: dhcp.h:338
void dhcppkt_init(struct dhcp_packet *dhcppkt, struct dhcphdr *data, size_t len)
Initialise DHCP packet.
Definition: dhcppkt.c:300
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:80
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition: retry.c:117
#define DHCPNONE
Definition: dhcp.h:197
#define ENOSPC
No space left on device.
Definition: errno.h:549
uint32_t dhcp_last_xid
Most recent DHCP transaction ID.
Definition: dhcp.c:124
#define DHCP_CLIENT_ID
Client identifier.
Definition: dhcp.h:243
#define DHCP_STRING(...)
Construct a DHCP option from a list of characters.
Definition: dhcp.h:554
struct dhcphdr * dhcphdr
The DHCP packet contents.
Definition: dhcppkt.h:24
#define DHCPREQUEST
Definition: dhcp.h:200
static int dhcp_request_tx(struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, struct sockaddr_in *peer)
Construct transmitted packet for DHCP request.
Definition: dhcp.c:508
static void dhcppkt_put(struct dhcp_packet *dhcppkt)
Decrement reference count on DHCP packet.
Definition: dhcppkt.h:49
#define DHCP_EB_PRIORITY
Priority of this options block.
Definition: dhcp.h:363
union uuid uuid
UUID.
Definition: dhcp.h:340
#define DHCP_ARCH_CLIENT_NDI
DHCP client network device interface.
Definition: dhcparch.h:18
uint16_t priority
Priotity.
Definition: stp.h:12
static struct dhcp_session_state dhcp_state_discover
DHCP discovery state operations.
Definition: dhcp.c:194
static int dhcp_proxy_tx(struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, struct sockaddr_in *peer)
Construct transmitted packet for ProxyDHCP request.
Definition: dhcp.c:667
static int dhcp_pxebs_tx(struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, struct sockaddr_in *peer)
Construct transmitted packet for PXE Boot Server Discovery.
Definition: dhcp.c:777
void * data
Start of data.
Definition: iobuf.h:48
static size_t dhcppkt_len(struct dhcp_packet *dhcppkt)
Get used length of DHCP packet.
Definition: dhcppkt.h:59
A network device configurator.
Definition: netdevice.h:313
#define BOOTPC_PORT
BOOTP/DHCP client port.
Definition: dhcp.h:30
struct in_addr * pxe_attempt
List of PXE Boot Servers to attempt.
Definition: dhcp.c:236
static struct dhcp_session_state dhcp_state_pxebs
PXE Boot Server Discovery state operations.
Definition: dhcp.c:197
struct settings * find_settings(const char *name)
Find settings block.
Definition: settings.c:406
#define cpu_to_le16(value)
Definition: byteswap.h:106
uint8_t data[48]
Additional event data.
Definition: ena.h:22
#define DHCP_BOOTFILE_NAME
Bootfile name.
Definition: dhcp.h:265
uint32_t magic
DHCP magic cookie.
Definition: dhcp.h:674
static struct dhcp_packet * dhcppkt_get(struct dhcp_packet *dhcppkt)
Increment reference count on DHCP packet.
Definition: dhcppkt.h:38
const char *(* ntoa)(const void *ll_addr)
Transcribe link-layer address.
Definition: netdevice.h:163
#define DHCP_DNS_SERVERS
DNS servers.
Definition: dhcp.h:72
#define DHCP_REQ_START_TIMEOUT_SEC
Definition: dhcp.h:51
__be32 raw[7]
Definition: CIB_PRM.h:28
DHCP packets.
Device model.
#define PXEBS_END_TIMEOUT_SEC
Definition: dhcp.h:80
int register_settings(struct settings *settings, struct settings *parent, const char *name)
Register settings block.
Definition: settings.c:475
#define DHCP_END
End of options.
Definition: dhcp.h:546
int fetch_uuid_setting(struct settings *settings, const struct setting *setting, union uuid *uuid)
Fetch value of UUID setting.
Definition: settings.c:1084
#define DHCP_VENDOR_ENCAP
Vendor encapsulated options.
Definition: dhcp.h:93
struct in_addr * pxe_accept
List of PXE Boot Servers to accept.
Definition: dhcp.c:238
struct mschapv2_challenge peer
Peer challenge.
Definition: mschapv2.h:12
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition: acpi.c:45
signed long ssize_t
Definition: stdint.h:7
#define DHCP_USER_CLASS_ID
User class identifier.
Definition: dhcp.h:268
#define DHCP_VENDOR_PXECLIENT(arch, ndi)
Vendor class identifier for PXE clients.
Definition: dhcp.h:220
int start_pxebs(struct interface *job, struct net_device *netdev, unsigned int pxe_type)
Start PXE Boot Server Discovery on a network device.
Definition: dhcp.c:1447
static void dhcp_request_expired(struct dhcp_session *dhcp)
Handle timer expiry during DHCP discovery.
Definition: dhcp.c:643
#define DHCP_PXE_DISCOVERY_CONTROL
PXE boot server discovery control.
Definition: dhcp.h:96
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
Definition: netdevice.h:387
unsigned long currticks(void)
Get current system time in ticks.
Definition: timer.c:42
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
uint8_t hlen
Hardware address length.
Definition: dhcp.h:627
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition: interface.h:203
#define DHCP_TFTP_SERVER_NAME
TFTP server name.
Definition: dhcp.h:258
#define DHCP_EB_BUS_ID
Network device descriptor.
Definition: dhcp.h:443
struct net_device_configurator dhcp_configurator __net_device_configurator
DHCP network device configurator.
Definition: dhcp.c:1544
#define PXEBS_START_TIMEOUT_SEC
Definition: dhcp.h:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:114
uint32_t len
Length.
Definition: ena.h:14
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
#define DHCPDECLINE
Definition: dhcp.h:201
#define DHCP_PXE_BOOT_SERVER_MCAST
PXE boot server multicast address.
Definition: dhcp.h:111
#define ETIMEDOUT
Connection timed out.
Definition: errno.h:669
#define DHCP_PARAMETER_REQUEST_LIST
Parameter request list.
Definition: dhcp.h:211
String functions.
#define DHCP_PXE_BOOT_SERVERS
PXE boot servers.
Definition: dhcp.h:114
PXE boot server.
Definition: dhcp.h:117
#define htons(value)
Definition: byteswap.h:135
struct bofm_section_header done
Definition: bofm_test.c:46
Inhibit multicast discovery.
Definition: dhcp.h:103
uint8_t ll_proto
Link-layer protocol.
Definition: dhcp.h:248
#define AF_INET
IPv4 Internet addresses.
Definition: socket.h:63
#define DHCP_DISC_START_TIMEOUT_SEC
Definition: dhcp.h:22
static void dhcp_request_rx(struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, struct sockaddr_in *peer, uint8_t msgtype, struct in_addr server_id, struct in_addr pseudo_id)
Handle received packet during DHCP request.
Definition: dhcp.c:546
#define DHCP_OPTION(...)
Construct a DHCP option from a list of bytes.
Definition: dhcp.h:551
#define PXEBS_MAX_TIMEOUT_SEC
Definition: dhcp.h:88
struct ll_protocol * ll_protocol
Link-layer protocol.
Definition: netdevice.h:372
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106
#define DHCP_DISC_END_TIMEOUT_SEC
Definition: dhcp.h:23
void * memset(void *dest, int character, size_t len) __nonnull
A persistent I/O buffer.
Definition: iobuf.h:33
struct net_device * netdev
Network device being configured.
Definition: dhcp.c:209
#define table_num_entries(table)
Get number of entries in linker table.
Definition: tables.h:335