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