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  * Handle timer expiry during DHCP discovery
448  *
449  * @v dhcp DHCP session
450  */
451 static void dhcp_discovery_expired ( struct dhcp_session *dhcp ) {
452  unsigned long elapsed = ( currticks() - dhcp->start );
453 
454  /* If link is blocked, defer DHCP discovery (and reset timeout) */
455  if ( netdev_link_blocked ( dhcp->netdev ) &&
456  ( dhcp->count <= DHCP_DISC_MAX_DEFERRALS ) ) {
457  DBGC ( dhcp, "DHCP %p deferring discovery\n", dhcp );
458  dhcp->start = currticks();
459  start_timer_fixed ( &dhcp->timer,
461  TICKS_PER_SEC ) );
462  return;
463  }
464 
465  /* Give up waiting for ProxyDHCP before we reach the failure point */
466  if ( dhcp->offer.s_addr &&
467  ( elapsed > DHCP_DISC_PROXY_TIMEOUT_SEC * TICKS_PER_SEC ) ) {
469  return;
470  }
471 
472  /* Otherwise, retransmit current packet */
473  dhcp_tx ( dhcp );
474 }
475 
476 /** DHCP discovery state operations */
477 static struct dhcp_session_state dhcp_state_discover = {
478  .name = "discovery",
479  .tx = dhcp_discovery_tx,
480  .rx = dhcp_discovery_rx,
481  .expired = dhcp_discovery_expired,
482  .tx_msgtype = DHCPDISCOVER,
483  .min_timeout_sec = DHCP_DISC_START_TIMEOUT_SEC,
484  .max_timeout_sec = DHCP_DISC_END_TIMEOUT_SEC,
485 };
486 
487 /**
488  * Construct transmitted packet for DHCP request
489  *
490  * @v dhcp DHCP session
491  * @v dhcppkt DHCP packet
492  * @v peer Destination address
493  */
494 static int dhcp_request_tx ( struct dhcp_session *dhcp,
495  struct dhcp_packet *dhcppkt,
496  struct sockaddr_in *peer ) {
497  int rc;
498 
499  DBGC ( dhcp, "DHCP %p DHCPREQUEST to %s:%d",
500  dhcp, inet_ntoa ( dhcp->server ), BOOTPS_PORT );
501  DBGC ( dhcp, " for %s\n", inet_ntoa ( dhcp->offer ) );
502 
503  /* Set server ID */
504  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_SERVER_IDENTIFIER,
505  &dhcp->server,
506  sizeof ( dhcp->server ) ) ) != 0 )
507  return rc;
508 
509  /* Set requested IP address */
510  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_REQUESTED_ADDRESS,
511  &dhcp->offer,
512  sizeof ( dhcp->offer ) ) ) != 0 )
513  return rc;
514 
515  /* Set server address */
517  peer->sin_port = htons ( BOOTPS_PORT );
518 
519  return 0;
520 }
521 
522 /**
523  * Handle received packet during DHCP request
524  *
525  * @v dhcp DHCP session
526  * @v dhcppkt DHCP packet
527  * @v peer DHCP server address
528  * @v msgtype DHCP message type
529  * @v server_id DHCP server ID
530  * @v pseudo_id DHCP server pseudo-ID
531  */
532 static void dhcp_request_rx ( struct dhcp_session *dhcp,
533  struct dhcp_packet *dhcppkt,
534  struct sockaddr_in *peer, uint8_t msgtype,
535  struct in_addr server_id,
536  struct in_addr pseudo_id ) {
537  struct in_addr ip;
538  struct settings *parent;
539  struct settings *settings;
540  int rc;
541 
542  DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
543  dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
544  ntohs ( peer->sin_port ) );
545  if ( ( server_id.s_addr != peer->sin_addr.s_addr ) ||
546  ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) {
547  DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) );
548  DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) );
549  }
550 
551  /* Identify leased IP address */
552  ip = dhcppkt->dhcphdr->yiaddr;
553  if ( ip.s_addr )
554  DBGC ( dhcp, " for %s", inet_ntoa ( ip ) );
555  DBGC ( dhcp, "\n" );
556 
557  /* Filter out unacceptable responses */
558  if ( peer->sin_port != htons ( BOOTPS_PORT ) )
559  return;
560  if ( msgtype /* BOOTP */ && ( msgtype != DHCPACK ) )
561  return;
562  if ( server_id.s_addr != dhcp->server.s_addr )
563  return;
564  if ( ip.s_addr != dhcp->offer.s_addr )
565  return;
566 
567  /* Record assigned address */
568  dhcp->local.sin_addr = ip;
569 
570  /* Register settings */
571  parent = netdev_settings ( dhcp->netdev );
572  settings = &dhcppkt->settings;
573  if ( ( rc = register_settings ( settings, parent,
574  DHCP_SETTINGS_NAME ) ) != 0 ) {
575  DBGC ( dhcp, "DHCP %p could not register settings: %s\n",
576  dhcp, strerror ( rc ) );
577  dhcp_finished ( dhcp, rc );
578  return;
579  }
580 
581  /* Perform ProxyDHCP if applicable */
582  if ( dhcp->proxy_offer /* Have ProxyDHCP offer */ &&
583  ( ! dhcp->no_pxedhcp ) /* ProxyDHCP not disabled */ ) {
584  if ( dhcp_has_pxeopts ( dhcp->proxy_offer ) ) {
585  /* PXE options already present; register settings
586  * without performing a ProxyDHCPREQUEST
587  */
588  settings = &dhcp->proxy_offer->settings;
589  if ( ( rc = register_settings ( settings, NULL,
590  PROXYDHCP_SETTINGS_NAME ) ) != 0 ) {
591  DBGC ( dhcp, "DHCP %p could not register "
592  "proxy settings: %s\n",
593  dhcp, strerror ( rc ) );
594  dhcp_finished ( dhcp, rc );
595  return;
596  }
597  } else {
598  /* PXE options not present; use a ProxyDHCPREQUEST */
599  dhcp_set_state ( dhcp, &dhcp_state_proxy );
600  return;
601  }
602  }
603 
604  /* Terminate DHCP */
605  dhcp_finished ( dhcp, 0 );
606 }
607 
608 /**
609  * Handle timer expiry during DHCP discovery
610  *
611  * @v dhcp DHCP session
612  */
613 static void dhcp_request_expired ( struct dhcp_session *dhcp ) {
614 
615  /* Retransmit current packet */
616  dhcp_tx ( dhcp );
617 }
618 
619 /** DHCP request state operations */
620 static struct dhcp_session_state dhcp_state_request = {
621  .name = "request",
622  .tx = dhcp_request_tx,
623  .rx = dhcp_request_rx,
624  .expired = dhcp_request_expired,
625  .tx_msgtype = DHCPREQUEST,
626  .min_timeout_sec = DHCP_REQ_START_TIMEOUT_SEC,
627  .max_timeout_sec = DHCP_REQ_END_TIMEOUT_SEC,
628 };
629 
630 /**
631  * Construct transmitted packet for ProxyDHCP request
632  *
633  * @v dhcp DHCP session
634  * @v dhcppkt DHCP packet
635  * @v peer Destination address
636  */
637 static int dhcp_proxy_tx ( struct dhcp_session *dhcp,
638  struct dhcp_packet *dhcppkt,
639  struct sockaddr_in *peer ) {
640  int rc;
641 
642  DBGC ( dhcp, "DHCP %p ProxyDHCP REQUEST to %s\n", dhcp,
643  inet_ntoa ( dhcp->proxy_server ) );
644 
645  /* Set server ID */
646  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_SERVER_IDENTIFIER,
647  &dhcp->proxy_server,
648  sizeof ( dhcp->proxy_server ) ) ) != 0 )
649  return rc;
650 
651  /* Set server address */
652  peer->sin_addr = dhcp->proxy_server;
653  peer->sin_port = htons ( PXE_PORT );
654 
655  return 0;
656 }
657 
658 /**
659  * Handle received packet during ProxyDHCP request
660  *
661  * @v dhcp DHCP session
662  * @v dhcppkt DHCP packet
663  * @v peer DHCP server address
664  * @v msgtype DHCP message type
665  * @v server_id DHCP server ID
666  * @v pseudo_id DHCP server pseudo-ID
667  */
668 static void dhcp_proxy_rx ( struct dhcp_session *dhcp,
669  struct dhcp_packet *dhcppkt,
670  struct sockaddr_in *peer, uint8_t msgtype,
671  struct in_addr server_id,
672  struct in_addr pseudo_id ) {
673  struct settings *settings = &dhcppkt->settings;
674  int rc;
675 
676  DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
677  dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
678  ntohs ( peer->sin_port ) );
679  if ( ( server_id.s_addr != peer->sin_addr.s_addr ) ||
680  ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) {
681  DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) );
682  DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) );
683  }
684  if ( dhcp_has_pxeopts ( dhcppkt ) )
685  DBGC ( dhcp, " pxe" );
686  DBGC ( dhcp, "\n" );
687 
688  /* Filter out unacceptable responses */
689  if ( peer->sin_port != ntohs ( PXE_PORT ) )
690  return;
691  if ( ( msgtype != DHCPOFFER ) && ( msgtype != DHCPACK ) )
692  return;
693  if ( ( pseudo_id.s_addr != dhcp->proxy_server.s_addr ) )
694  return;
695  if ( ! dhcp_has_pxeopts ( dhcppkt ) )
696  return;
697 
698  /* Register settings */
699  if ( ( rc = register_settings ( settings, NULL,
700  PROXYDHCP_SETTINGS_NAME ) ) != 0 ) {
701  DBGC ( dhcp, "DHCP %p could not register proxy settings: %s\n",
702  dhcp, strerror ( rc ) );
703  dhcp_finished ( dhcp, rc );
704  return;
705  }
706 
707  /* Terminate DHCP */
708  dhcp_finished ( dhcp, 0 );
709 }
710 
711 /**
712  * Handle timer expiry during ProxyDHCP request
713  *
714  * @v dhcp DHCP session
715  */
716 static void dhcp_proxy_expired ( struct dhcp_session *dhcp ) {
717  unsigned long elapsed = ( currticks() - dhcp->start );
718 
719  /* Give up waiting for ProxyDHCP before we reach the failure point */
720  if ( elapsed > DHCP_REQ_PROXY_TIMEOUT_SEC * TICKS_PER_SEC ) {
721  dhcp_finished ( dhcp, 0 );
722  return;
723  }
724 
725  /* Retransmit current packet */
726  dhcp_tx ( dhcp );
727 }
728 
729 /** ProxyDHCP request state operations */
730 static struct dhcp_session_state dhcp_state_proxy = {
731  .name = "ProxyDHCP",
732  .tx = dhcp_proxy_tx,
733  .rx = dhcp_proxy_rx,
734  .expired = dhcp_proxy_expired,
735  .tx_msgtype = DHCPREQUEST,
736  .min_timeout_sec = DHCP_PROXY_START_TIMEOUT_SEC,
737  .max_timeout_sec = DHCP_PROXY_END_TIMEOUT_SEC,
738 };
739 
740 /**
741  * Construct transmitted packet for PXE Boot Server Discovery
742  *
743  * @v dhcp DHCP session
744  * @v dhcppkt DHCP packet
745  * @v peer Destination address
746  */
747 static int dhcp_pxebs_tx ( struct dhcp_session *dhcp,
748  struct dhcp_packet *dhcppkt,
749  struct sockaddr_in *peer ) {
750  struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 };
751  int rc;
752 
753  /* Set server address */
754  peer->sin_addr = *(dhcp->pxe_attempt);
755  peer->sin_port = ( ( peer->sin_addr.s_addr == INADDR_BROADCAST ) ?
756  htons ( BOOTPS_PORT ) : htons ( PXE_PORT ) );
757 
758  DBGC ( dhcp, "DHCP %p PXEBS REQUEST to %s:%d for type %d\n",
759  dhcp, inet_ntoa ( peer->sin_addr ), ntohs ( peer->sin_port ),
760  le16_to_cpu ( dhcp->pxe_type ) );
761 
762  /* Set boot menu item */
763  menu_item.type = dhcp->pxe_type;
764  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_PXE_BOOT_MENU_ITEM,
765  &menu_item, sizeof ( menu_item ) ) ) != 0 )
766  return rc;
767 
768  return 0;
769 }
770 
771 /**
772  * Check to see if PXE Boot Server address is acceptable
773  *
774  * @v dhcp DHCP session
775  * @v bs Boot Server address
776  * @ret accept Boot Server is acceptable
777  */
778 static int dhcp_pxebs_accept ( struct dhcp_session *dhcp,
779  struct in_addr bs ) {
780  struct in_addr *accept;
781 
782  /* Accept if we have no acceptance filter */
783  if ( ! dhcp->pxe_accept )
784  return 1;
785 
786  /* Scan through acceptance list */
787  for ( accept = dhcp->pxe_accept ; accept->s_addr ; accept++ ) {
788  if ( accept->s_addr == bs.s_addr )
789  return 1;
790  }
791 
792  DBGC ( dhcp, "DHCP %p rejecting server %s\n",
793  dhcp, inet_ntoa ( bs ) );
794  return 0;
795 }
796 
797 /**
798  * Handle received packet during PXE Boot Server Discovery
799  *
800  * @v dhcp DHCP session
801  * @v dhcppkt DHCP packet
802  * @v peer DHCP server address
803  * @v msgtype DHCP message type
804  * @v server_id DHCP server ID
805  * @v pseudo_id DHCP server pseudo-ID
806  */
807 static void dhcp_pxebs_rx ( struct dhcp_session *dhcp,
808  struct dhcp_packet *dhcppkt,
809  struct sockaddr_in *peer, uint8_t msgtype,
810  struct in_addr server_id,
811  struct in_addr pseudo_id ) {
812  struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 };
813  int rc;
814 
815  DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
816  dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
817  ntohs ( peer->sin_port ) );
818  if ( ( server_id.s_addr != peer->sin_addr.s_addr ) ||
819  ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) {
820  DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) );
821  DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) );
822  }
823 
824  /* Identify boot menu item */
826  &menu_item, sizeof ( menu_item ) );
827  if ( menu_item.type )
828  DBGC ( dhcp, " for type %d", ntohs ( menu_item.type ) );
829  DBGC ( dhcp, "\n" );
830 
831  /* Filter out unacceptable responses */
832  if ( ( peer->sin_port != htons ( BOOTPS_PORT ) ) &&
833  ( peer->sin_port != htons ( PXE_PORT ) ) )
834  return;
835  if ( msgtype != DHCPACK )
836  return;
837  if ( menu_item.type != dhcp->pxe_type )
838  return;
839  if ( ! dhcp_pxebs_accept ( dhcp, pseudo_id ) )
840  return;
841 
842  /* Register settings */
843  if ( ( rc = register_settings ( &dhcppkt->settings, NULL,
844  PXEBS_SETTINGS_NAME ) ) != 0 ) {
845  DBGC ( dhcp, "DHCP %p could not register settings: %s\n",
846  dhcp, strerror ( rc ) );
847  dhcp_finished ( dhcp, rc );
848  return;
849  }
850 
851  /* Terminate DHCP */
852  dhcp_finished ( dhcp, 0 );
853 }
854 
855 /**
856  * Handle timer expiry during PXE Boot Server Discovery
857  *
858  * @v dhcp DHCP session
859  */
860 static void dhcp_pxebs_expired ( struct dhcp_session *dhcp ) {
861  unsigned long elapsed = ( currticks() - dhcp->start );
862 
863  /* Give up waiting before we reach the failure point, and fail
864  * over to the next server in the attempt list
865  */
866  if ( elapsed > PXEBS_MAX_TIMEOUT_SEC * TICKS_PER_SEC ) {
867  dhcp->pxe_attempt++;
868  if ( dhcp->pxe_attempt->s_addr ) {
869  dhcp_set_state ( dhcp, &dhcp_state_pxebs );
870  return;
871  } else {
872  dhcp_finished ( dhcp, -ETIMEDOUT );
873  return;
874  }
875  }
876 
877  /* Retransmit current packet */
878  dhcp_tx ( dhcp );
879 }
880 
881 /** PXE Boot Server Discovery state operations */
882 static struct dhcp_session_state dhcp_state_pxebs = {
883  .name = "PXEBS",
884  .tx = dhcp_pxebs_tx,
885  .rx = dhcp_pxebs_rx,
886  .expired = dhcp_pxebs_expired,
887  .tx_msgtype = DHCPREQUEST,
888  .min_timeout_sec = PXEBS_START_TIMEOUT_SEC,
889  .max_timeout_sec = PXEBS_END_TIMEOUT_SEC,
890 };
891 
892 /****************************************************************************
893  *
894  * Packet construction
895  *
896  */
897 
898 /**
899  * Create a DHCP packet
900  *
901  * @v dhcppkt DHCP packet structure to fill in
902  * @v netdev Network device
903  * @v msgtype DHCP message type
904  * @v xid Transaction ID (in network-endian order)
905  * @v options Initial options to include (or NULL)
906  * @v options_len Length of initial options
907  * @v data Buffer for DHCP packet
908  * @v max_len Size of DHCP packet buffer
909  * @ret rc Return status code
910  *
911  * Creates a DHCP packet in the specified buffer, and initialise a
912  * DHCP packet structure.
913  */
914 int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
915  struct net_device *netdev, uint8_t msgtype,
916  uint32_t xid, const void *options, size_t options_len,
917  void *data, size_t max_len ) {
918  struct dhcphdr *dhcphdr = data;
919  int rc;
920 
921  /* Sanity check */
922  if ( max_len < ( sizeof ( *dhcphdr ) + options_len ) )
923  return -ENOSPC;
924 
925  /* Initialise DHCP packet content */
926  memset ( dhcphdr, 0, max_len );
927  dhcphdr->xid = xid;
930  dhcphdr->op = dhcp_op[msgtype];
934  memcpy ( dhcphdr->options, options, options_len );
935 
936  /* If the local link-layer address functions only as a name
937  * (i.e. cannot be used as a destination address), then
938  * request broadcast responses.
939  */
942 
943  /* If the network device already has an IPv4 address then
944  * unicast responses from the DHCP server may be rejected, so
945  * request broadcast responses.
946  */
947  if ( ipv4_has_any_addr ( netdev ) )
949 
950  /* Initialise DHCP packet structure */
951  memset ( dhcppkt, 0, sizeof ( *dhcppkt ) );
952  dhcppkt_init ( dhcppkt, data, max_len );
953 
954  /* Set DHCP_MESSAGE_TYPE option */
955  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_MESSAGE_TYPE,
956  &msgtype, sizeof ( msgtype ) ) ) != 0 )
957  return rc;
958 
959  return 0;
960 }
961 
962 /**
963  * Create DHCP request packet
964  *
965  * @v dhcppkt DHCP packet structure to fill in
966  * @v netdev Network device
967  * @v msgtype DHCP message type
968  * @v xid Transaction ID (in network-endian order)
969  * @v ciaddr Client IP address
970  * @v data Buffer for DHCP packet
971  * @v max_len Size of DHCP packet buffer
972  * @ret rc Return status code
973  *
974  * Creates a DHCP request packet in the specified buffer, and
975  * initialise a DHCP packet structure.
976  */
977 int dhcp_create_request ( struct dhcp_packet *dhcppkt,
978  struct net_device *netdev, unsigned int msgtype,
979  uint32_t xid, struct in_addr ciaddr,
980  void *data, size_t max_len ) {
981  struct dhcp_netdev_desc dhcp_desc;
982  struct dhcp_client_id client_id;
983  struct dhcp_client_uuid client_uuid;
984  const struct setting *setting;
985  uint8_t *dhcp_features;
986  size_t dhcp_features_len;
987  size_t ll_addr_len;
988  void *raw;
989  ssize_t len;
990  unsigned int i;
991  int rc;
992 
993  /* Create DHCP packet */
994  if ( ( rc = dhcp_create_packet ( dhcppkt, netdev, msgtype, xid,
996  sizeof ( dhcp_request_options_data ),
997  data, max_len ) ) != 0 ) {
998  DBG ( "DHCP could not create DHCP packet: %s\n",
999  strerror ( rc ) );
1000  goto err_create_packet;
1001  }
1002 
1003  /* Set client IP address */
1004  dhcppkt->dhcphdr->ciaddr = ciaddr;
1005 
1006  /* Add options to identify the feature list */
1007  dhcp_features = table_start ( DHCP_FEATURES );
1008  dhcp_features_len = table_num_entries ( DHCP_FEATURES );
1009  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_EB_ENCAP, dhcp_features,
1010  dhcp_features_len ) ) != 0 ) {
1011  DBG ( "DHCP could not set features list option: %s\n",
1012  strerror ( rc ) );
1013  goto err_store_features;
1014  }
1015 
1016  /* Add options to identify the network device */
1017  fetch_raw_setting ( netdev_settings ( netdev ), &busid_setting,
1018  &dhcp_desc, sizeof ( dhcp_desc ) );
1019  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_EB_BUS_ID, &dhcp_desc,
1020  sizeof ( dhcp_desc ) ) ) != 0 ) {
1021  DBG ( "DHCP could not set bus ID option: %s\n",
1022  strerror ( rc ) );
1023  goto err_store_busid;
1024  }
1025 
1026  /* Add DHCP client identifier. Required for Infiniband, and
1027  * doesn't hurt other link layers.
1028  */
1029  client_id.ll_proto = ntohs ( netdev->ll_protocol->ll_proto );
1030  ll_addr_len = netdev->ll_protocol->ll_addr_len;
1031  assert ( ll_addr_len <= sizeof ( client_id.ll_addr ) );
1032  memcpy ( client_id.ll_addr, netdev->ll_addr, ll_addr_len );
1033  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_CLIENT_ID, &client_id,
1034  ( ll_addr_len + 1 ) ) ) != 0 ) {
1035  DBG ( "DHCP could not set client ID: %s\n",
1036  strerror ( rc ) );
1037  goto err_store_client_id;
1038  }
1039 
1040  /* Add client UUID, if we have one. Required for PXE. The
1041  * PXE spec does not specify a byte ordering for UUIDs, but
1042  * RFC4578 suggests that it follows the EFI spec, in which the
1043  * first three fields are little-endian.
1044  */
1045  client_uuid.type = DHCP_CLIENT_UUID_TYPE;
1046  if ( ( len = fetch_uuid_setting ( NULL, &uuid_setting,
1047  &client_uuid.uuid ) ) >= 0 ) {
1048  uuid_mangle ( &client_uuid.uuid );
1049  if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_CLIENT_UUID,
1050  &client_uuid,
1051  sizeof ( client_uuid ) ) ) != 0 ) {
1052  DBG ( "DHCP could not set client UUID: %s\n",
1053  strerror ( rc ) );
1054  goto err_store_client_uuid;
1055  }
1056  }
1057 
1058  /* Add request settings, if applicable */
1059  for ( i = 0 ; i < ( sizeof ( dhcp_request_settings ) /
1060  sizeof ( dhcp_request_settings[0] ) ) ; i++ ) {
1062  if ( ( len = fetch_raw_setting_copy ( NULL, setting,
1063  &raw ) ) >= 0 ) {
1064  rc = dhcppkt_store ( dhcppkt, setting->tag, raw, len );
1065  free ( raw );
1066  if ( rc != 0 ) {
1067  DBG ( "DHCP could not set %s: %s\n",
1068  setting->name, strerror ( rc ) );
1069  goto err_store_raw;
1070  }
1071  }
1072  }
1073 
1074  err_store_raw:
1075  err_store_client_uuid:
1076  err_store_client_id:
1077  err_store_busid:
1078  err_store_features:
1079  err_create_packet:
1080  return rc;
1081 }
1082 
1083 /****************************************************************************
1084  *
1085  * Data transfer interface
1086  *
1087  */
1088 
1089 /**
1090  * Transmit DHCP request
1091  *
1092  * @v dhcp DHCP session
1093  * @ret rc Return status code
1094  */
1095 static int dhcp_tx ( struct dhcp_session *dhcp ) {
1096  static struct sockaddr_in peer = {
1097  .sin_family = AF_INET,
1098  };
1099  struct xfer_metadata meta = {
1100  .netdev = dhcp->netdev,
1101  .src = ( struct sockaddr * ) &dhcp->local,
1102  .dest = ( struct sockaddr * ) &peer,
1103  };
1104  struct io_buffer *iobuf;
1105  uint8_t msgtype = dhcp->state->tx_msgtype;
1106  struct dhcp_packet dhcppkt;
1107  int rc;
1108 
1109  /* Start retry timer. Do this first so that failures to
1110  * transmit will be retried.
1111  */
1112  start_timer ( &dhcp->timer );
1113 
1114  /* Allocate buffer for packet */
1115  iobuf = xfer_alloc_iob ( &dhcp->xfer, DHCP_MIN_LEN );
1116  if ( ! iobuf )
1117  return -ENOMEM;
1118 
1119  /* Create basic DHCP packet in temporary buffer */
1120  if ( ( rc = dhcp_create_request ( &dhcppkt, dhcp->netdev, msgtype,
1121  dhcp->xid, dhcp->local.sin_addr,
1122  iobuf->data,
1123  iob_tailroom ( iobuf ) ) ) != 0 ) {
1124  DBGC ( dhcp, "DHCP %p could not construct DHCP request: %s\n",
1125  dhcp, strerror ( rc ) );
1126  goto done;
1127  }
1128 
1129  /* (Ab)use the "secs" field to convey metadata about the DHCP
1130  * session state into packet traces. Useful for extracting
1131  * debug information from non-debug builds.
1132  */
1133  dhcppkt.dhcphdr->secs = htons ( ( dhcp->count << 2 ) |
1134  ( dhcp->offer.s_addr ? 0x02 : 0 ) |
1135  ( dhcp->proxy_offer ? 0x01 : 0 ) );
1136 
1137  /* Fill in packet based on current state */
1138  if ( ( rc = dhcp->state->tx ( dhcp, &dhcppkt, &peer ) ) != 0 ) {
1139  DBGC ( dhcp, "DHCP %p could not fill DHCP request: %s\n",
1140  dhcp, strerror ( rc ) );
1141  goto done;
1142  }
1143 
1144  /* Transmit the packet */
1145  iob_put ( iobuf, dhcppkt_len ( &dhcppkt ) );
1146  if ( ( rc = xfer_deliver ( &dhcp->xfer, iob_disown ( iobuf ),
1147  &meta ) ) != 0 ) {
1148  DBGC ( dhcp, "DHCP %p could not transmit UDP packet: %s\n",
1149  dhcp, strerror ( rc ) );
1150  goto done;
1151  }
1152 
1153  done:
1154  free_iob ( iobuf );
1155  return rc;
1156 }
1157 
1158 /**
1159  * Receive new data
1160  *
1161  * @v dhcp DHCP session
1162  * @v iobuf I/O buffer
1163  * @v meta Transfer metadata
1164  * @ret rc Return status code
1165  */
1166 static int dhcp_deliver ( struct dhcp_session *dhcp,
1167  struct io_buffer *iobuf,
1168  struct xfer_metadata *meta ) {
1169  struct net_device *netdev = dhcp->netdev;
1171  struct sockaddr_in *peer;
1172  size_t data_len;
1173  struct dhcp_packet *dhcppkt;
1174  struct dhcphdr *dhcphdr;
1175  uint8_t msgtype = 0;
1176  struct in_addr server_id = { 0 };
1177  struct in_addr pseudo_id;
1178  int rc = 0;
1179 
1180  /* Sanity checks */
1181  if ( ! meta->src ) {
1182  DBGC ( dhcp, "DHCP %p received packet without source port\n",
1183  dhcp );
1184  rc = -EINVAL;
1185  goto err_no_src;
1186  }
1187  peer = ( struct sockaddr_in * ) meta->src;
1188 
1189  /* Create a DHCP packet containing the I/O buffer contents.
1190  * Whilst we could just use the original buffer in situ, that
1191  * would waste the unused space in the packet buffer, and also
1192  * waste a relatively scarce fully-aligned I/O buffer.
1193  */
1194  data_len = iob_len ( iobuf );
1195  dhcppkt = zalloc ( sizeof ( *dhcppkt ) + data_len );
1196  if ( ! dhcppkt ) {
1197  rc = -ENOMEM;
1198  goto err_alloc_dhcppkt;
1199  }
1200  dhcphdr = ( ( ( void * ) dhcppkt ) + sizeof ( *dhcppkt ) );
1201  memcpy ( dhcphdr, iobuf->data, data_len );
1202  dhcppkt_init ( dhcppkt, dhcphdr, data_len );
1203 
1204  /* Identify message type */
1205  dhcppkt_fetch ( dhcppkt, DHCP_MESSAGE_TYPE, &msgtype,
1206  sizeof ( msgtype ) );
1207 
1208  /* Identify server ID */
1210  &server_id, sizeof ( server_id ) );
1211 
1212  /* Identify server pseudo-ID */
1213  pseudo_id = server_id;
1214  if ( ! pseudo_id.s_addr )
1215  pseudo_id = dhcppkt->dhcphdr->siaddr;
1216  if ( ! pseudo_id.s_addr )
1217  pseudo_id = peer->sin_addr;
1218 
1219  /* Check for matching transaction ID */
1220  if ( dhcphdr->xid != dhcp->xid ) {
1221  DBGC ( dhcp, "DHCP %p %s from %s:%d has bad transaction "
1222  "ID\n", dhcp, dhcp_msgtype_name ( msgtype ),
1223  inet_ntoa ( peer->sin_addr ),
1224  ntohs ( peer->sin_port ) );
1225  rc = -EINVAL;
1226  goto err_xid;
1227  };
1228 
1229  /* Check for matching client hardware address */
1230  if ( memcmp ( dhcphdr->chaddr, netdev->ll_addr,
1231  ll_protocol->ll_addr_len ) != 0 ) {
1232  DBGC ( dhcp, "DHCP %p %s from %s:%d has bad chaddr %s\n",
1233  dhcp, dhcp_msgtype_name ( msgtype ),
1234  inet_ntoa ( peer->sin_addr ), ntohs ( peer->sin_port ),
1235  ll_protocol->ntoa ( dhcphdr->chaddr ) );
1236  rc = -EINVAL;
1237  goto err_chaddr;
1238  }
1239 
1240  /* Handle packet based on current state */
1241  dhcp->state->rx ( dhcp, dhcppkt, peer, msgtype, server_id, pseudo_id );
1242 
1243  err_chaddr:
1244  err_xid:
1245  dhcppkt_put ( dhcppkt );
1246  err_alloc_dhcppkt:
1247  err_no_src:
1248  free_iob ( iobuf );
1249  return rc;
1250 }
1251 
1252 /** DHCP data transfer interface operations */
1255 };
1256 
1257 /** DHCP data transfer interface descriptor */
1259  INTF_DESC ( struct dhcp_session, xfer, dhcp_xfer_operations );
1260 
1261 /**
1262  * Handle DHCP retry timer expiry
1263  *
1264  * @v timer DHCP retry timer
1265  * @v fail Failure indicator
1266  */
1267 static void dhcp_timer_expired ( struct retry_timer *timer, int fail ) {
1268  struct dhcp_session *dhcp =
1269  container_of ( timer, struct dhcp_session, timer );
1270 
1271  /* If we have failed, terminate DHCP */
1272  if ( fail ) {
1273  dhcp_finished ( dhcp, -ETIMEDOUT );
1274  return;
1275  }
1276 
1277  /* Increment transmission counter */
1278  dhcp->count++;
1279 
1280  /* Handle timer expiry based on current state */
1281  dhcp->state->expired ( dhcp );
1282 }
1283 
1284 /****************************************************************************
1285  *
1286  * Job control interface
1287  *
1288  */
1289 
1290 /** DHCP job control interface operations */
1293 };
1294 
1295 /** DHCP job control interface descriptor */
1297  INTF_DESC ( struct dhcp_session, job, dhcp_job_op );
1298 
1299 /****************************************************************************
1300  *
1301  * Instantiators
1302  *
1303  */
1304 
1305 /**
1306  * DHCP peer address for socket opening
1307  *
1308  * This is a dummy address; the only useful portion is the socket
1309  * family (so that we get a UDP connection). The DHCP client will set
1310  * the IP address and source port explicitly on each transmission.
1311  */
1312 static struct sockaddr dhcp_peer = {
1313  .sa_family = AF_INET,
1314 };
1315 
1316 /**
1317  * Start DHCP state machine on a network device
1318  *
1319  * @v job Job control interface
1320  * @v netdev Network device
1321  * @ret rc Return status code
1322  *
1323  * Starts DHCP on the specified network device. If successful, the
1324  * DHCPACK (and ProxyDHCPACK, if applicable) will be registered as
1325  * option sources.
1326  */
1327 int start_dhcp ( struct interface *job, struct net_device *netdev ) {
1328  struct dhcp_session *dhcp;
1329  int rc;
1330 
1331  /* Allocate and initialise structure */
1332  dhcp = zalloc ( sizeof ( *dhcp ) );
1333  if ( ! dhcp )
1334  return -ENOMEM;
1335  ref_init ( &dhcp->refcnt, dhcp_free );
1336  intf_init ( &dhcp->job, &dhcp_job_desc, &dhcp->refcnt );
1337  intf_init ( &dhcp->xfer, &dhcp_xfer_desc, &dhcp->refcnt );
1338  timer_init ( &dhcp->timer, dhcp_timer_expired, &dhcp->refcnt );
1339  dhcp->netdev = netdev_get ( netdev );
1340  dhcp->local.sin_family = AF_INET;
1341  dhcp->local.sin_port = htons ( BOOTPC_PORT );
1342  dhcp->xid = random();
1343 
1344  /* Store DHCP transaction ID for fakedhcp code */
1345  dhcp_last_xid = dhcp->xid;
1346 
1347  /* Instantiate child objects and attach to our interfaces */
1348  if ( ( rc = xfer_open_socket ( &dhcp->xfer, SOCK_DGRAM, &dhcp_peer,
1349  ( struct sockaddr * ) &dhcp->local ) ) != 0 )
1350  goto err;
1351 
1352  /* Enter DHCPDISCOVER state */
1354 
1355  /* Attach parent interface, mortalise self, and return */
1356  intf_plug_plug ( &dhcp->job, job );
1357  ref_put ( &dhcp->refcnt );
1358  return 0;
1359 
1360  err:
1361  dhcp_finished ( dhcp, rc );
1362  ref_put ( &dhcp->refcnt );
1363  return rc;
1364 }
1365 
1366 /**
1367  * Retrieve list of PXE boot servers for a given server type
1368  *
1369  * @v dhcp DHCP session
1370  * @v raw DHCP PXE boot server list
1371  * @v raw_len Length of DHCP PXE boot server list
1372  * @v ip IP address list to fill in
1373  *
1374  * The caller must ensure that the IP address list has sufficient
1375  * space.
1376  */
1377 static void pxebs_list ( struct dhcp_session *dhcp, void *raw,
1378  size_t raw_len, struct in_addr *ip ) {
1379  struct dhcp_pxe_boot_server *server = raw;
1380  size_t server_len;
1381  unsigned int i;
1382 
1383  while ( raw_len ) {
1384  if ( raw_len < sizeof ( *server ) ) {
1385  DBGC ( dhcp, "DHCP %p malformed PXE server list\n",
1386  dhcp );
1387  break;
1388  }
1389  server_len = offsetof ( typeof ( *server ),
1390  ip[ server->num_ip ] );
1391  if ( raw_len < server_len ) {
1392  DBGC ( dhcp, "DHCP %p malformed PXE server list\n",
1393  dhcp );
1394  break;
1395  }
1396  if ( server->type == dhcp->pxe_type ) {
1397  for ( i = 0 ; i < server->num_ip ; i++ )
1398  *(ip++) = server->ip[i];
1399  }
1400  server = ( ( ( void * ) server ) + server_len );
1401  raw_len -= server_len;
1402  }
1403 }
1404 
1405 /**
1406  * Start PXE Boot Server Discovery on a network device
1407  *
1408  * @v job Job control interface
1409  * @v netdev Network device
1410  * @v pxe_type PXE server type
1411  * @ret rc Return status code
1412  *
1413  * Starts PXE Boot Server Discovery on the specified network device.
1414  * If successful, the Boot Server ACK will be registered as an option
1415  * source.
1416  */
1417 int start_pxebs ( struct interface *job, struct net_device *netdev,
1418  unsigned int pxe_type ) {
1419  struct setting pxe_discovery_control_setting =
1421  struct setting pxe_boot_servers_setting =
1422  { .tag = DHCP_PXE_BOOT_SERVERS };
1423  struct setting pxe_boot_server_mcast_setting =
1425  ssize_t pxebs_list_len;
1426  struct dhcp_session *dhcp;
1427  struct in_addr *ip;
1428  unsigned int pxe_discovery_control;
1429  int rc;
1430 
1431  /* Get upper bound for PXE boot server IP address list */
1432  pxebs_list_len = fetch_raw_setting ( NULL, &pxe_boot_servers_setting,
1433  NULL, 0 );
1434  if ( pxebs_list_len < 0 )
1435  pxebs_list_len = 0;
1436 
1437  /* Allocate and initialise structure */
1438  dhcp = zalloc ( sizeof ( *dhcp ) + sizeof ( *ip ) /* mcast */ +
1439  sizeof ( *ip ) /* bcast */ + pxebs_list_len +
1440  sizeof ( *ip ) /* terminator */ );
1441  if ( ! dhcp )
1442  return -ENOMEM;
1443  ref_init ( &dhcp->refcnt, dhcp_free );
1444  intf_init ( &dhcp->job, &dhcp_job_desc, &dhcp->refcnt );
1445  intf_init ( &dhcp->xfer, &dhcp_xfer_desc, &dhcp->refcnt );
1446  timer_init ( &dhcp->timer, dhcp_timer_expired, &dhcp->refcnt );
1447  dhcp->netdev = netdev_get ( netdev );
1448  dhcp->local.sin_family = AF_INET;
1449  fetch_ipv4_setting ( netdev_settings ( netdev ), &ip_setting,
1450  &dhcp->local.sin_addr );
1451  dhcp->local.sin_port = htons ( BOOTPC_PORT );
1452  dhcp->pxe_type = cpu_to_le16 ( pxe_type );
1453 
1454  /* Construct PXE boot server IP address lists */
1455  pxe_discovery_control =
1456  fetch_uintz_setting ( NULL, &pxe_discovery_control_setting );
1457  ip = ( ( ( void * ) dhcp ) + sizeof ( *dhcp ) );
1458  dhcp->pxe_attempt = ip;
1459  if ( ! ( pxe_discovery_control & PXEBS_NO_MULTICAST ) ) {
1460  fetch_ipv4_setting ( NULL, &pxe_boot_server_mcast_setting, ip);
1461  if ( ip->s_addr )
1462  ip++;
1463  }
1464  if ( ! ( pxe_discovery_control & PXEBS_NO_BROADCAST ) )
1465  (ip++)->s_addr = INADDR_BROADCAST;
1466  if ( pxe_discovery_control & PXEBS_NO_UNKNOWN_SERVERS )
1467  dhcp->pxe_accept = ip;
1468  if ( pxebs_list_len ) {
1469  uint8_t buf[pxebs_list_len];
1470 
1471  fetch_raw_setting ( NULL, &pxe_boot_servers_setting,
1472  buf, sizeof ( buf ) );
1473  pxebs_list ( dhcp, buf, sizeof ( buf ), ip );
1474  }
1475  if ( ! dhcp->pxe_attempt->s_addr ) {
1476  DBGC ( dhcp, "DHCP %p has no PXE boot servers for type %04x\n",
1477  dhcp, pxe_type );
1478  rc = -EINVAL;
1479  goto err;
1480  }
1481 
1482  /* Dump out PXE server lists */
1483  DBGC ( dhcp, "DHCP %p attempting", dhcp );
1484  for ( ip = dhcp->pxe_attempt ; ip->s_addr ; ip++ )
1485  DBGC ( dhcp, " %s", inet_ntoa ( *ip ) );
1486  DBGC ( dhcp, "\n" );
1487  if ( dhcp->pxe_accept ) {
1488  DBGC ( dhcp, "DHCP %p accepting", dhcp );
1489  for ( ip = dhcp->pxe_accept ; ip->s_addr ; ip++ )
1490  DBGC ( dhcp, " %s", inet_ntoa ( *ip ) );
1491  DBGC ( dhcp, "\n" );
1492  }
1493 
1494  /* Instantiate child objects and attach to our interfaces */
1495  if ( ( rc = xfer_open_socket ( &dhcp->xfer, SOCK_DGRAM, &dhcp_peer,
1496  ( struct sockaddr * ) &dhcp->local ) ) != 0 )
1497  goto err;
1498 
1499  /* Enter PXEBS state */
1500  dhcp_set_state ( dhcp, &dhcp_state_pxebs );
1501 
1502  /* Attach parent interface, mortalise self, and return */
1503  intf_plug_plug ( &dhcp->job, job );
1504  ref_put ( &dhcp->refcnt );
1505  return 0;
1506 
1507  err:
1508  dhcp_finished ( dhcp, rc );
1509  ref_put ( &dhcp->refcnt );
1510  return rc;
1511 }
1512 
1513 /** DHCP network device configurator */
1515  .name = "dhcp",
1516  .start = start_dhcp,
1517 };
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:311
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:244
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:116
static struct interface_operation dhcp_xfer_operations[]
DHCP data transfer interface operations.
Definition: dhcp.c:1253
#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:273
#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:1166
static void dhcp_timer_expired(struct retry_timer *timer, int fail)
Handle DHCP retry timer expiry.
Definition: dhcp.c:1267
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:451
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:1296
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:141
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:145
#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:1312
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition: interface.c:102
#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:778
int start_dhcp(struct interface *job, struct net_device *netdev)
Start DHCP state machine on a network device.
Definition: dhcp.c:1327
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:977
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:641
static void dhcp_proxy_expired(struct dhcp_session *dhcp)
Handle timer expiry during ProxyDHCP request.
Definition: dhcp.c:716
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:170
#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:1377
static struct settings * netdev_settings(struct net_device *netdev)
Get per-netdevice configuration settings block.
Definition: netdevice.h:577
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:668
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:914
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:1291
struct sockaddr_in local
Local socket address.
Definition: dhcp.c:210
#define ENOMEM
Not enough space.
Definition: errno.h:534
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition: iobuf.h:208
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:1258
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:555
#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:109
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:807
#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:860
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:1095
Generalized socket address structure.
Definition: socket.h:96
An object interface descriptor.
Definition: interface.h:40
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:151
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:348
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:171
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:544
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:65
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:494
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:637
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:747
void * data
Start of data.
Definition: iobuf.h:44
A network device configurator.
Definition: netdevice.h:309
#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
static int dhcppkt_len(struct dhcp_packet *dhcppkt)
Get used length of DHCP packet.
Definition: dhcppkt.h:59
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:1417
static void dhcp_request_expired(struct dhcp_session *dhcp)
Handle timer expiry during DHCP discovery.
Definition: dhcp.c:613
#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:381
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:173
#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:1514
#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:98
#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:532
#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:366
#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:32
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