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