#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <assert.h>
#include <byteswap.h>
#include <gpxe/if_ether.h>
#include <gpxe/netdevice.h>
#include <gpxe/device.h>
#include <gpxe/xfer.h>
#include <gpxe/open.h>
#include <gpxe/job.h>
#include <gpxe/retry.h>
#include <gpxe/tcpip.h>
#include <gpxe/ip.h>
#include <gpxe/uuid.h>
#include <gpxe/timer.h>
#include <gpxe/settings.h>
#include <gpxe/dhcp.h>
#include <gpxe/dhcpopts.h>
#include <gpxe/dhcppkt.h>
#include <gpxe/features.h>
Go to the source code of this file.
Data Structures | |
| struct | dhcp_session_state |
| DHCP session state operations. More... | |
| struct | dhcp_offer |
| A DHCP offer. More... | |
| struct | dhcp_session |
| A DHCP session. More... | |
Defines | |
| #define | DHCP_OFFER_IP 1 |
| DHCP offer is valid for IP lease. | |
| #define | DHCP_OFFER_PXE 2 |
| DHCP offer is valid for PXE options. | |
| #define | DHCP_MAX_OFFERS 6 |
| Maximum number of DHCP offers to queue. | |
Functions | |
| FILE_LICENCE (GPL2_OR_LATER) | |
| static int | dhcp_tx (struct dhcp_session *dhcp) |
| Transmit DHCP request. | |
| FEATURE_VERSION (VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH) | |
| Version number feature. | |
| static const char * | dhcp_msgtype_name (unsigned int msgtype) |
| Name a DHCP packet type. | |
| static uint32_t | dhcp_xid (struct net_device *netdev) |
| Calculate DHCP transaction ID for a network device. | |
| static void | dhcp_free (struct refcnt *refcnt) |
| Free DHCP session. | |
| static void | dhcp_finished (struct dhcp_session *dhcp, int rc) |
| Mark DHCP session as complete. | |
| static void | dhcp_set_state (struct dhcp_session *dhcp, struct dhcp_session_state *state) |
| Transition to new DHCP session state. | |
| static struct dhcp_offer * | dhcp_next_offer (struct dhcp_session *dhcp, uint8_t type) |
| Determine next DHCP offer to try. | |
| static int | dhcp_discovery_tx (struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt __unused, struct sockaddr_in *peer) |
| Construct transmitted packet for DHCP discovery. | |
| static void | dhcp_rx_offer (struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, struct sockaddr_in *peer, uint8_t msgtype, struct in_addr server_id) |
| Handle received DHCPOFFER during any state. | |
| 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) |
| Handle received packet during DHCP discovery. | |
| static void | dhcp_discovery_expired (struct dhcp_session *dhcp) |
| Handle timer expiry during DHCP discovery. | |
| static int | dhcp_request_tx (struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, struct sockaddr_in *peer) |
| Construct transmitted packet for DHCP request. | |
| 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) |
| Handle received packet during DHCP request. | |
| static void | dhcp_request_expired (struct dhcp_session *dhcp) |
| Handle timer expiry during DHCP discovery. | |
| static int | dhcp_proxy_tx (struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, struct sockaddr_in *peer) |
| Construct transmitted packet for ProxyDHCP request. | |
| 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) |
| Handle received packet during ProxyDHCP request. | |
| static void | dhcp_proxy_expired (struct dhcp_session *dhcp) |
| Handle timer expiry during ProxyDHCP request. | |
| 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. | |
| static int | dhcp_pxebs_accept (struct dhcp_session *dhcp, struct in_addr bs) |
| Check to see if PXE Boot Server address is acceptable. | |
| 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) |
| Handle received packet during PXE Boot Server Discovery. | |
| static void | dhcp_pxebs_expired (struct dhcp_session *dhcp) |
| Handle timer expiry during PXE Boot Server Discovery. | |
| void * | dhcp_chaddr (struct net_device *netdev, uint8_t *hlen, uint16_t *flags) |
| Construct DHCP client hardware address field and broadcast flag. | |
| int | dhcp_create_packet (struct dhcp_packet *dhcppkt, struct net_device *netdev, uint8_t msgtype, const void *options, size_t options_len, void *data, size_t max_len) |
| Create a DHCP packet. | |
| int | dhcp_create_request (struct dhcp_packet *dhcppkt, struct net_device *netdev, unsigned int msgtype, struct in_addr ciaddr, void *data, size_t max_len) |
| Create DHCP request packet. | |
| static int | dhcp_deliver_iob (struct xfer_interface *xfer, struct io_buffer *iobuf, struct xfer_metadata *meta) |
| Receive new data. | |
| static void | dhcp_timer_expired (struct retry_timer *timer, int fail) |
| Handle DHCP retry timer expiry. | |
| static void | dhcp_job_kill (struct job_interface *job) |
| Handle kill() event received via job control interface. | |
| int | start_dhcp (struct job_interface *job, struct net_device *netdev) |
| Start DHCP state machine on a network device. | |
| 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. | |
| int | start_pxebs (struct job_interface *job, struct net_device *netdev, unsigned int pxe_type) |
| Start PXE Boot Server Discovery on a network device. | |
Variables | |
| static const uint8_t | dhcp_op [] |
| DHCP operation types. | |
| static uint8_t | dhcp_request_options_data [] |
| Raw option data for options common to all DHCP requests. | |
| struct setting dhcp_server_setting | __setting |
| DHCP server address setting. | |
| static struct dhcp_session_state | dhcp_state_discover |
| DHCP discovery state operations. | |
| static struct dhcp_session_state | dhcp_state_request |
| DHCP request state operations. | |
| static struct dhcp_session_state | dhcp_state_proxy |
| ProxyDHCP request state operations. | |
| static struct dhcp_session_state | dhcp_state_pxebs |
| PXE Boot Server Discovery state operations. | |
| static struct xfer_interface_operations | dhcp_xfer_operations |
| DHCP data transfer interface operations. | |
| static struct job_interface_operations | dhcp_job_operations |
| DHCP job control interface operations. | |
| static struct sockaddr | dhcp_peer |
| DHCP peer address for socket opening. | |
Definition in file dhcp.c.
| #define DHCP_OFFER_IP 1 |
DHCP offer is valid for IP lease.
Definition at line 210 of file dhcp.c.
Referenced by dhcp_discovery_expired(), dhcp_discovery_rx(), dhcp_request_rx(), dhcp_request_tx(), and dhcp_rx_offer().
| #define DHCP_OFFER_PXE 2 |
DHCP offer is valid for PXE options.
Definition at line 213 of file dhcp.c.
Referenced by dhcp_discovery_rx(), dhcp_proxy_expired(), dhcp_proxy_tx(), dhcp_request_rx(), and dhcp_rx_offer().
| #define DHCP_MAX_OFFERS 6 |
Maximum number of DHCP offers to queue.
Definition at line 237 of file dhcp.c.
Referenced by dhcp_free(), dhcp_next_offer(), and dhcp_rx_offer().
| FILE_LICENCE | ( | GPL2_OR_LATER | ) |
| static int dhcp_tx | ( | struct dhcp_session * | dhcp | ) | [static] |
Transmit DHCP request.
| dhcp | DHCP session |
| rc | Return status code |
Definition at line 1184 of file dhcp.c.
References AF_INET, io_buffer::data, DBGC, dhcp_create_request(), DHCP_MIN_LEN, ENOMEM, free_iob(), iob_disown, iob_put, iob_tailroom(), dhcp_packet::len, dhcp_session::local, dhcp_session::netdev, xfer_metadata::netdev, sockaddr_in::sin_addr, sockaddr_in::sin_family, start_timer(), dhcp_session::state, strerror(), dhcp_session::timer, dhcp_session_state::tx, dhcp_session_state::tx_msgtype, dhcp_session::xfer, xfer_alloc_iob(), and xfer_deliver_iob_meta().
Referenced by dhcp_discovery_expired(), dhcp_proxy_expired(), dhcp_pxebs_expired(), and dhcp_request_expired().
01184 { 01185 static struct sockaddr_in peer = { 01186 .sin_family = AF_INET, 01187 }; 01188 struct xfer_metadata meta = { 01189 .netdev = dhcp->netdev, 01190 .src = ( struct sockaddr * ) &dhcp->local, 01191 .dest = ( struct sockaddr * ) &peer, 01192 }; 01193 struct io_buffer *iobuf; 01194 uint8_t msgtype = dhcp->state->tx_msgtype; 01195 struct dhcp_packet dhcppkt; 01196 int rc; 01197 01198 /* Start retry timer. Do this first so that failures to 01199 * transmit will be retried. 01200 */ 01201 start_timer ( &dhcp->timer ); 01202 01203 /* Allocate buffer for packet */ 01204 iobuf = xfer_alloc_iob ( &dhcp->xfer, DHCP_MIN_LEN ); 01205 if ( ! iobuf ) 01206 return -ENOMEM; 01207 01208 /* Create basic DHCP packet in temporary buffer */ 01209 if ( ( rc = dhcp_create_request ( &dhcppkt, dhcp->netdev, msgtype, 01210 dhcp->local.sin_addr, iobuf->data, 01211 iob_tailroom ( iobuf ) ) ) != 0 ) { 01212 DBGC ( dhcp, "DHCP %p could not construct DHCP request: %s\n", 01213 dhcp, strerror ( rc ) ); 01214 goto done; 01215 } 01216 01217 /* Fill in packet based on current state */ 01218 if ( ( rc = dhcp->state->tx ( dhcp, &dhcppkt, &peer ) ) != 0 ) { 01219 DBGC ( dhcp, "DHCP %p could not fill DHCP request: %s\n", 01220 dhcp, strerror ( rc ) ); 01221 goto done; 01222 } 01223 01224 /* Transmit the packet */ 01225 iob_put ( iobuf, dhcppkt.len ); 01226 if ( ( rc = xfer_deliver_iob_meta ( &dhcp->xfer, iob_disown ( iobuf ), 01227 &meta ) ) != 0 ) { 01228 DBGC ( dhcp, "DHCP %p could not transmit UDP packet: %s\n", 01229 dhcp, strerror ( rc ) ); 01230 goto done; 01231 } 01232 01233 done: 01234 free_iob ( iobuf ); 01235 return rc; 01236 }
| FEATURE_VERSION | ( | VERSION_MAJOR | , | |
| VERSION_MINOR | , | |||
| VERSION_PATCH | ||||
| ) |
Version number feature.
| static const char* dhcp_msgtype_name | ( | unsigned int | msgtype | ) | [inline, static] |
Name a DHCP packet type.
| msgtype | DHCP message type |
| string | DHCP mesasge type name |
Definition at line 127 of file dhcp.c.
References DHCPACK, DHCPDECLINE, DHCPDISCOVER, DHCPINFORM, DHCPNAK, DHCPNONE, DHCPOFFER, DHCPRELEASE, and DHCPREQUEST.
Referenced by dhcp_deliver_iob(), dhcp_proxy_rx(), dhcp_pxebs_rx(), dhcp_request_rx(), and dhcp_rx_offer().
00127 { 00128 switch ( msgtype ) { 00129 case DHCPNONE: return "BOOTP"; /* Non-DHCP packet */ 00130 case DHCPDISCOVER: return "DHCPDISCOVER"; 00131 case DHCPOFFER: return "DHCPOFFER"; 00132 case DHCPREQUEST: return "DHCPREQUEST"; 00133 case DHCPDECLINE: return "DHCPDECLINE"; 00134 case DHCPACK: return "DHCPACK"; 00135 case DHCPNAK: return "DHCPNAK"; 00136 case DHCPRELEASE: return "DHCPRELEASE"; 00137 case DHCPINFORM: return "DHCPINFORM"; 00138 default: return "DHCP<invalid>"; 00139 } 00140 }
| static uint32_t dhcp_xid | ( | struct net_device * | netdev | ) | [static] |
Calculate DHCP transaction ID for a network device.
| netdev | Network device |
| xid | DHCP XID |
Definition at line 151 of file dhcp.c.
References net_device::ll_addr, ll_protocol::ll_addr_len, net_device::ll_protocol, and memcpy.
Referenced by dhcp_create_packet(), and dhcp_deliver_iob().
00151 { 00152 uint32_t xid; 00153 00154 memcpy ( &xid, ( netdev->ll_addr + netdev->ll_protocol->ll_addr_len 00155 - sizeof ( xid ) ), sizeof ( xid ) ); 00156 return xid; 00157 }
| static void dhcp_free | ( | struct refcnt * | refcnt | ) | [static] |
Free DHCP session.
| refcnt | Reference counter |
Definition at line 278 of file dhcp.c.
References container_of, dhcp(), DHCP_MAX_OFFERS, dhcppkt_put(), free(), dhcp_session::netdev, netdev_put(), dhcp_session::offers, and dhcp_offer::pxe.
Referenced by start_dhcp(), and start_pxebs().
00278 { 00279 struct dhcp_session *dhcp = 00280 container_of ( refcnt, struct dhcp_session, refcnt ); 00281 int i; 00282 00283 for ( i = 0 ; i < DHCP_MAX_OFFERS ; i++ ) { 00284 if ( dhcp->offers[i].pxe ) 00285 dhcppkt_put ( dhcp->offers[i].pxe ); 00286 } 00287 00288 netdev_put ( dhcp->netdev ); 00289 free ( dhcp ); 00290 }
| static void dhcp_finished | ( | struct dhcp_session * | dhcp, | |
| int | rc | |||
| ) | [static] |
Mark DHCP session as complete.
| dhcp | DHCP session | |
| rc | Return status code |
Definition at line 298 of file dhcp.c.
References dhcp_session::job, job_done(), job_nullify(), stop_timer(), dhcp_session::timer, dhcp_session::xfer, and xfer_close().
Referenced by dhcp_job_kill(), dhcp_proxy_expired(), dhcp_proxy_rx(), dhcp_pxebs_expired(), dhcp_pxebs_rx(), dhcp_request_rx(), dhcp_timer_expired(), start_dhcp(), and start_pxebs().
00298 { 00299 00300 /* Block futher incoming messages */ 00301 job_nullify ( &dhcp->job ); 00302 xfer_nullify ( &dhcp->xfer ); 00303 00304 /* Stop retry timer */ 00305 stop_timer ( &dhcp->timer ); 00306 00307 /* Free resources and close interfaces */ 00308 xfer_close ( &dhcp->xfer, rc ); 00309 job_done ( &dhcp->job, rc ); 00310 }
| static void dhcp_set_state | ( | struct dhcp_session * | dhcp, | |
| struct dhcp_session_state * | state | |||
| ) | [static] |
Transition to new DHCP session state.
| dhcp | DHCP session | |
| state | New session state |
Definition at line 318 of file dhcp.c.
References dhcp_session_state::apply_min_timeout, currticks(), DBGC, DHCP_MAX_TIMEOUT, DHCP_MIN_TIMEOUT, retry_timer::max_timeout, retry_timer::min_timeout, dhcp_session_state::name, dhcp_session::start, start_timer_nodelay(), dhcp_session::state, stop_timer(), and dhcp_session::timer.
Referenced by dhcp_discovery_expired(), dhcp_discovery_rx(), dhcp_proxy_expired(), dhcp_pxebs_expired(), dhcp_request_rx(), start_dhcp(), and start_pxebs().
00319 { 00320 00321 DBGC ( dhcp, "DHCP %p entering %s state\n", dhcp, state->name ); 00322 dhcp->state = state; 00323 dhcp->start = currticks(); 00324 stop_timer ( &dhcp->timer ); 00325 dhcp->timer.min_timeout = 00326 ( state->apply_min_timeout ? DHCP_MIN_TIMEOUT : 0 ); 00327 dhcp->timer.max_timeout = DHCP_MAX_TIMEOUT; 00328 start_timer_nodelay ( &dhcp->timer ); 00329 }
| static struct dhcp_offer* dhcp_next_offer | ( | struct dhcp_session * | dhcp, | |
| uint8_t | type | |||
| ) | [static, read] |
Determine next DHCP offer to try.
| dhcp | DHCP session | |
| type | DHCP offer type |
| offer | Next DHCP offer to try |
Definition at line 341 of file dhcp.c.
References DHCP_MAX_OFFERS, NULL, dhcp_session::offers, dhcp_offer::priority, and dhcp_offer::valid.
Referenced by dhcp_discovery_expired(), dhcp_discovery_rx(), dhcp_proxy_expired(), dhcp_proxy_tx(), dhcp_request_rx(), and dhcp_request_tx().
00342 { 00343 00344 struct dhcp_offer *offer; 00345 struct dhcp_offer *best = NULL; 00346 00347 for ( offer = dhcp->offers ; offer < dhcp->offers + DHCP_MAX_OFFERS ; 00348 offer++ ) { 00349 if ( ( offer->valid & type ) && 00350 ( ( best == NULL ) || 00351 ( offer->priority > best->priority ) || 00352 ( ( offer->priority == best->priority ) && 00353 ( offer->valid & ~best->valid ) ) ) ) 00354 best = offer; 00355 } 00356 00357 return best; 00358 }
| static int dhcp_discovery_tx | ( | struct dhcp_session * | dhcp, | |
| struct dhcp_packet *dhcppkt | __unused, | |||
| struct sockaddr_in * | peer | |||
| ) | [static] |
Construct transmitted packet for DHCP discovery.
| dhcp | DHCP session | |
| dhcppkt | DHCP packet | |
| peer | Destination address |
Definition at line 373 of file dhcp.c.
References BOOTPS_PORT, DBGC, htons, INADDR_BROADCAST, in_addr::s_addr, sockaddr_in::sin_addr, and sockaddr_in::sin_port.
00375 { 00376 00377 DBGC ( dhcp, "DHCP %p DHCPDISCOVER\n", dhcp ); 00378 00379 /* Set server address */ 00380 peer->sin_addr.s_addr = INADDR_BROADCAST; 00381 peer->sin_port = htons ( BOOTPS_PORT ); 00382 00383 return 0; 00384 }
| static void dhcp_rx_offer | ( | struct dhcp_session * | dhcp, | |
| struct dhcp_packet * | dhcppkt, | |||
| struct sockaddr_in * | peer, | |||
| uint8_t | msgtype, | |||
| struct in_addr | server_id | |||
| ) | [static] |
Handle received DHCPOFFER during any state.
| dhcp | DHCP session | |
| dhcppkt | DHCP packet | |
| peer | DHCP server address | |
| msgtype | DHCP message type | |
| server_id | DHCP server ID |
Definition at line 395 of file dhcp.c.
References BOOTPS_PORT, DBGC, DHCP_EB_NO_PXEDHCP, DHCP_EB_PRIORITY, DHCP_MAX_OFFERS, dhcp_msgtype_name(), DHCP_OFFER_IP, DHCP_OFFER_PXE, DHCP_PXE_BOOT_MENU, DHCP_VENDOR_CLASS_ID, dhcp_packet::dhcphdr, DHCPOFFER, dhcppkt_fetch(), dhcppkt_get(), dhcppkt_put(), htons, inet_ntoa(), dhcp_offer::ip, dhcp_offer::no_pxedhcp, ntohs, NULL, dhcp_session::offers, dhcp_offer::priority, dhcp_offer::pxe, in_addr::s_addr, dhcp_offer::server, sockaddr_in::sin_addr, sockaddr_in::sin_port, strncmp(), dhcp_offer::valid, and dhcphdr::yiaddr.
Referenced by dhcp_discovery_rx(), dhcp_proxy_rx(), and dhcp_request_rx().
00398 { 00399 char vci[9]; /* "PXEClient" */ 00400 int vci_len; 00401 int has_pxeclient; 00402 int pxeopts_len; 00403 int has_pxeopts; 00404 struct dhcp_offer *offer; 00405 int i; 00406 00407 DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp, 00408 dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ), 00409 ntohs ( peer->sin_port ) ); 00410 if ( server_id.s_addr != peer->sin_addr.s_addr ) 00411 DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) ); 00412 00413 /* Identify offered IP address */ 00414 if ( dhcppkt->dhcphdr->yiaddr.s_addr ) 00415 DBGC ( dhcp, " for %s", inet_ntoa ( dhcppkt->dhcphdr->yiaddr )); 00416 00417 /* Enqueue an offer to be filled in */ 00418 for ( i = 0 ; i < DHCP_MAX_OFFERS ; i++ ) { 00419 if ( dhcp->offers[i].server.s_addr == server_id.s_addr ) { 00420 DBGC ( dhcp, " dup\n" ); 00421 return; 00422 } 00423 00424 if ( ! dhcp->offers[i].valid ) 00425 break; 00426 } 00427 if ( i == DHCP_MAX_OFFERS ) { 00428 DBGC ( dhcp, " dropped\n" ); 00429 return; 00430 } 00431 00432 offer = &dhcp->offers[i]; 00433 offer->server = server_id; 00434 offer->ip = dhcppkt->dhcphdr->yiaddr; 00435 00436 /* Identify "PXEClient" vendor class */ 00437 vci_len = dhcppkt_fetch ( dhcppkt, DHCP_VENDOR_CLASS_ID, 00438 vci, sizeof ( vci ) ); 00439 has_pxeclient = ( ( vci_len >= ( int ) sizeof ( vci ) ) && 00440 ( strncmp ( "PXEClient", vci, sizeof (vci) ) == 0 )); 00441 00442 /* Identify presence of PXE-specific options */ 00443 pxeopts_len = dhcppkt_fetch ( dhcppkt, DHCP_PXE_BOOT_MENU, NULL, 0 ); 00444 has_pxeopts = ( pxeopts_len >= 0 ); 00445 if ( has_pxeclient ) 00446 DBGC ( dhcp, "%s", ( has_pxeopts ? " pxe" : " proxy" ) ); 00447 00448 if ( has_pxeclient && has_pxeopts ) { 00449 /* Save reference to packet for future use */ 00450 if ( offer->pxe ) 00451 dhcppkt_put ( offer->pxe ); 00452 offer->pxe = dhcppkt_get ( dhcppkt ); 00453 } 00454 00455 /* Identify priority */ 00456 dhcppkt_fetch ( dhcppkt, DHCP_EB_PRIORITY, &offer->priority, 00457 sizeof ( offer->priority ) ); 00458 if ( offer->priority ) 00459 DBGC ( dhcp, " pri %d", offer->priority ); 00460 00461 /* Identify ignore-PXE flag */ 00462 dhcppkt_fetch ( dhcppkt, DHCP_EB_NO_PXEDHCP, &offer->no_pxedhcp, 00463 sizeof ( offer->no_pxedhcp ) ); 00464 if ( offer->no_pxedhcp ) 00465 DBGC ( dhcp, " nopxe" ); 00466 DBGC ( dhcp, "\n" ); 00467 00468 /* Determine roles this offer can fill */ 00469 if ( offer->ip.s_addr && 00470 ( peer->sin_port == htons ( BOOTPS_PORT ) ) && 00471 ( ( msgtype == DHCPOFFER ) || ( ! msgtype /* BOOTP */ ) ) ) 00472 offer->valid |= DHCP_OFFER_IP; 00473 00474 if ( has_pxeclient && ( msgtype == DHCPOFFER ) ) 00475 offer->valid |= DHCP_OFFER_PXE; 00476 }
| 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 | |||
| ) | [static] |
Handle received packet during DHCP discovery.
| dhcp | DHCP session | |
| dhcppkt | DHCP packet | |
| peer | DHCP server address | |
| msgtype | DHCP message type | |
| server_id | DHCP server ID |
Definition at line 487 of file dhcp.c.
References currticks(), dhcp_next_offer(), DHCP_OFFER_IP, DHCP_OFFER_PXE, dhcp_rx_offer(), dhcp_set_state(), dhcp_state_request, dhcp_offer::no_pxedhcp, PROXYDHCP_MAX_TIMEOUT, and dhcp_session::start.
00490 { 00491 unsigned long elapsed; 00492 struct dhcp_offer *ip_offer; 00493 00494 dhcp_rx_offer ( dhcp, dhcppkt, peer, msgtype, server_id ); 00495 00496 /* We can exit the discovery state when we have a valid 00497 * DHCPOFFER, and either: 00498 * 00499 * o The DHCPOFFER instructs us to ignore ProxyDHCPOFFERs, or 00500 * o We have a valid ProxyDHCPOFFER, or 00501 * o We have allowed sufficient time for ProxyDHCPOFFERs. 00502 */ 00503 00504 /* If we don't yet have a DHCPOFFER, do nothing */ 00505 ip_offer = dhcp_next_offer ( dhcp, DHCP_OFFER_IP ); 00506 if ( ! ip_offer ) 00507 return; 00508 00509 /* If we can't yet transition to DHCPREQUEST, do nothing */ 00510 elapsed = ( currticks() - dhcp->start ); 00511 if ( ! ( ip_offer->no_pxedhcp || 00512 dhcp_next_offer ( dhcp, DHCP_OFFER_PXE ) || 00513 ( elapsed > PROXYDHCP_MAX_TIMEOUT ) ) ) 00514 return; 00515 00516 /* Transition to DHCPREQUEST */ 00517 dhcp_set_state ( dhcp, &dhcp_state_request ); 00518 }
| static void dhcp_discovery_expired | ( | struct dhcp_session * | dhcp | ) | [static] |
Handle timer expiry during DHCP discovery.
| dhcp | DHCP session |
Definition at line 525 of file dhcp.c.
References currticks(), dhcp_next_offer(), DHCP_OFFER_IP, dhcp_set_state(), dhcp_state_request, dhcp_tx(), PROXYDHCP_MAX_TIMEOUT, and dhcp_session::start.
00525 { 00526 unsigned long elapsed = ( currticks() - dhcp->start ); 00527 00528 /* Give up waiting for ProxyDHCP before we reach the failure point */ 00529 if ( dhcp_next_offer ( dhcp, DHCP_OFFER_IP ) && 00530 ( elapsed > PROXYDHCP_MAX_TIMEOUT ) ) { 00531 dhcp_set_state ( dhcp, &dhcp_state_request ); 00532 return; 00533 } 00534 00535 /* Otherwise, retransmit current packet */ 00536 dhcp_tx ( dhcp ); 00537 }
| static int dhcp_request_tx | ( | struct dhcp_session * | dhcp, | |
| struct dhcp_packet * | dhcppkt, | |||
| struct sockaddr_in * | peer | |||
| ) | [static] |
Construct transmitted packet for DHCP request.
| dhcp | DHCP session | |
| dhcppkt | DHCP packet | |
| peer | Destination address |
Definition at line 556 of file dhcp.c.
References BOOTPS_PORT, dhcp_session::current_offer, DBGC, dhcp_next_offer(), DHCP_OFFER_IP, DHCP_REQUESTED_ADDRESS, DHCP_SERVER_IDENTIFIER, dhcppkt_store(), htons, INADDR_BROADCAST, inet_ntoa(), dhcp_offer::ip, in_addr::s_addr, dhcp_offer::server, sockaddr_in::sin_addr, and sockaddr_in::sin_port.
00558 { 00559 int rc; 00560 struct dhcp_offer *offer; 00561 00562 offer = dhcp->current_offer = dhcp_next_offer ( dhcp, DHCP_OFFER_IP ); 00563 00564 DBGC ( dhcp, "DHCP %p DHCPREQUEST to %s:%d", 00565 dhcp, inet_ntoa ( offer->server ), BOOTPS_PORT ); 00566 DBGC ( dhcp, " for %s\n", inet_ntoa ( offer->ip ) ); 00567 00568 /* Set server ID */ 00569 if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_SERVER_IDENTIFIER, 00570 &offer->server, 00571 sizeof ( offer->server ) ) ) != 0 ) 00572 return rc; 00573 00574 /* Set requested IP address */ 00575 if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_REQUESTED_ADDRESS, 00576 &offer->ip, sizeof ( offer->ip ) ) ) != 0 ) 00577 return rc; 00578 00579 /* Set server address */ 00580 peer->sin_addr.s_addr = INADDR_BROADCAST; 00581 peer->sin_port = htons ( BOOTPS_PORT ); 00582 00583 return 0; 00584 }
| 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 | |||
| ) | [static] |
Handle received packet during DHCP request.
| dhcp | DHCP session | |
| dhcppkt | DHCP packet | |
| peer | DHCP server address | |
| msgtype | DHCP message type | |
| server_id | DHCP server ID |
Definition at line 595 of file dhcp.c.
References BOOTPS_PORT, dhcp_session::current_offer, DBGC, dhcp_finished(), dhcp_msgtype_name(), dhcp_next_offer(), DHCP_OFFER_IP, DHCP_OFFER_PXE, dhcp_rx_offer(), dhcp_set_state(), dhcp_state_proxy, dhcp_state_request, DHCPACK, dhcp_packet::dhcphdr, DHCPOFFER, htons, inet_ntoa(), dhcp_session::local, settings::name, dhcp_session::netdev, netdev_settings(), dhcp_offer::no_pxedhcp, ntohs, NULL, settings::parent, PROXYDHCP_SETTINGS_NAME, dhcp_offer::pxe, register_settings(), in_addr::s_addr, dhcp_offer::server, dhcp_packet::settings, sockaddr_in::sin_addr, sockaddr_in::sin_port, strerror(), and dhcphdr::yiaddr.
00598 { 00599 struct in_addr ip; 00600 struct settings *parent; 00601 int rc; 00602 struct dhcp_offer *pxe_offer; 00603 00604 if ( msgtype == DHCPOFFER ) { 00605 dhcp_rx_offer ( dhcp, dhcppkt, peer, msgtype, server_id ); 00606 if ( dhcp_next_offer ( dhcp, DHCP_OFFER_IP ) != 00607 dhcp->current_offer ) { 00608 /* Restart due to higher-priority offer received */ 00609 DBGC ( dhcp, "DHCP %p re-requesting\n", dhcp ); 00610 dhcp_set_state ( dhcp, &dhcp_state_request ); 00611 } 00612 return; 00613 } 00614 00615 DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp, 00616 dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ), 00617 ntohs ( peer->sin_port ) ); 00618 if ( server_id.s_addr != peer->sin_addr.s_addr ) 00619 DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) ); 00620 00621 /* Identify leased IP address */ 00622 ip = dhcppkt->dhcphdr->yiaddr; 00623 if ( ip.s_addr ) 00624 DBGC ( dhcp, " for %s", inet_ntoa ( ip ) ); 00625 DBGC ( dhcp, "\n" ); 00626 00627 /* Filter out unacceptable responses */ 00628 if ( peer->sin_port != htons ( BOOTPS_PORT ) ) 00629 return; 00630 if ( msgtype /* BOOTP */ && ( msgtype != DHCPACK ) ) 00631 return; 00632 if ( server_id.s_addr != dhcp->current_offer->server.s_addr ) 00633 return; 00634 00635 /* Record assigned address */ 00636 dhcp->local.sin_addr = ip; 00637 00638 /* Register settings */ 00639 parent = netdev_settings ( dhcp->netdev ); 00640 if ( ( rc = register_settings ( &dhcppkt->settings, parent ) ) != 0 ){ 00641 DBGC ( dhcp, "DHCP %p could not register settings: %s\n", 00642 dhcp, strerror ( rc ) ); 00643 dhcp_finished ( dhcp, rc ); 00644 return; 00645 } 00646 00647 /* Locate best source of PXE settings */ 00648 pxe_offer = dhcp_next_offer ( dhcp, DHCP_OFFER_PXE ); 00649 00650 if ( ( ! pxe_offer ) || /* No PXE available */ 00651 /* IP offer instructs us to ignore PXE */ 00652 dhcp->current_offer->no_pxedhcp || 00653 /* PXE settings already registered with IP offer */ 00654 ( ( dhcp->current_offer == pxe_offer ) && ( pxe_offer->pxe ) ) ) { 00655 00656 /* Terminate DHCP */ 00657 dhcp_finished ( dhcp, 0 ); 00658 00659 } else if ( pxe_offer->pxe ) { 00660 /* Register PXE settings and terminate DHCP */ 00661 pxe_offer->pxe->settings.name = PROXYDHCP_SETTINGS_NAME; 00662 if ( ( rc = register_settings ( &pxe_offer->pxe->settings, 00663 NULL ) ) != 0 ) { 00664 DBGC ( dhcp, "DHCP %p could not register settings: " 00665 "%s\n", dhcp, strerror ( rc ) ); 00666 } 00667 dhcp_finished ( dhcp, rc ); 00668 } else { 00669 /* Start ProxyDHCP */ 00670 dhcp_set_state ( dhcp, &dhcp_state_proxy ); 00671 } 00672 }
| static void dhcp_request_expired | ( | struct dhcp_session * | dhcp | ) | [static] |
| static int dhcp_proxy_tx | ( | struct dhcp_session * | dhcp, | |
| struct dhcp_packet * | dhcppkt, | |||
| struct sockaddr_in * | peer | |||
| ) | [static] |
Construct transmitted packet for ProxyDHCP request.
| dhcp | DHCP session | |
| dhcppkt | DHCP packet | |
| peer | Destination address |
Definition at line 702 of file dhcp.c.
References dhcp_session::current_offer, DBGC, dhcp_next_offer(), DHCP_OFFER_PXE, DHCP_SERVER_IDENTIFIER, dhcppkt_store(), htons, inet_ntoa(), PXE_PORT, dhcp_offer::server, sockaddr_in::sin_addr, and sockaddr_in::sin_port.
00704 { 00705 int rc; 00706 struct dhcp_offer *offer; 00707 00708 offer = dhcp->current_offer = dhcp_next_offer ( dhcp, DHCP_OFFER_PXE ); 00709 00710 DBGC ( dhcp, "DHCP %p ProxyDHCP REQUEST to %s:%d\n", dhcp, 00711 inet_ntoa ( offer->server ), PXE_PORT ); 00712 00713 /* Set server ID */ 00714 if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_SERVER_IDENTIFIER, 00715 &offer->server, 00716 sizeof ( offer->server ) ) ) != 0 ) 00717 return rc; 00718 00719 /* Set server address */ 00720 peer->sin_addr = offer->server; 00721 peer->sin_port = htons ( PXE_PORT ); 00722 00723 return 0; 00724 }
| 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 | |||
| ) | [static] |
Handle received packet during ProxyDHCP request.
| dhcp | DHCP session | |
| dhcppkt | DHCP packet | |
| peer | DHCP server address | |
| msgtype | DHCP message type | |
| server_id | DHCP server ID |
Definition at line 735 of file dhcp.c.
References BOOTPS_PORT, dhcp_session::current_offer, DBGC, dhcp_finished(), dhcp_msgtype_name(), dhcp_rx_offer(), DHCPACK, DHCPOFFER, htons, inet_ntoa(), settings::name, ntohs, NULL, PROXYDHCP_SETTINGS_NAME, PXE_PORT, register_settings(), in_addr::s_addr, dhcp_offer::server, dhcp_packet::settings, sockaddr_in::sin_addr, sockaddr_in::sin_port, and strerror().
00738 { 00739 int rc; 00740 00741 /* Enqueue last-minute DHCPOFFERs for use in case of failure */ 00742 if ( peer->sin_port == htons ( BOOTPS_PORT ) && 00743 msgtype == DHCPOFFER ) { 00744 dhcp_rx_offer ( dhcp, dhcppkt, peer, msgtype, server_id ); 00745 return; 00746 } 00747 00748 DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp, 00749 dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ), 00750 ntohs ( peer->sin_port ) ); 00751 if ( server_id.s_addr != peer->sin_addr.s_addr ) 00752 DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) ); 00753 DBGC ( dhcp, "\n" ); 00754 00755 /* Filter out unacceptable responses */ 00756 if ( peer->sin_port != htons ( PXE_PORT ) ) 00757 return; 00758 if ( msgtype != DHCPACK && msgtype != DHCPOFFER ) 00759 return; 00760 if ( server_id.s_addr /* Linux PXE server omits server ID */ && 00761 ( server_id.s_addr != dhcp->current_offer->server.s_addr ) ) 00762 return; 00763 00764 /* Register settings */ 00765 dhcppkt->settings.name = PROXYDHCP_SETTINGS_NAME; 00766 if ( ( rc = register_settings ( &dhcppkt->settings, NULL ) ) != 0 ) { 00767 DBGC ( dhcp, "DHCP %p could not register settings: %s\n", 00768 dhcp, strerror ( rc ) ); 00769 dhcp_finished ( dhcp, rc ); 00770 return; 00771 } 00772 00773 /* Terminate DHCP */ 00774 dhcp_finished ( dhcp, 0 ); 00775 }
| static void dhcp_proxy_expired | ( | struct dhcp_session * | dhcp | ) | [static] |
Handle timer expiry during ProxyDHCP request.
| dhcp | DHCP session |
Definition at line 782 of file dhcp.c.
References dhcp_session::current_offer, currticks(), dhcp_finished(), dhcp_next_offer(), DHCP_OFFER_PXE, dhcp_set_state(), dhcp_tx(), dhcp_session::local, dhcp_offer::priority, PROXYDHCP_MAX_TIMEOUT, in_addr::s_addr, sockaddr_in::sin_addr, dhcp_session::start, and dhcp_offer::valid.
00782 { 00783 unsigned long elapsed = ( currticks() - dhcp->start ); 00784 00785 /* Give up waiting for ProxyDHCP before we reach the failure point */ 00786 if ( elapsed > PROXYDHCP_MAX_TIMEOUT ) { 00787 00788 /* Mark failed offer as unsuitable for ProxyDHCP */ 00789 dhcp->current_offer->valid &= ~DHCP_OFFER_PXE; 00790 00791 /* Prefer not to use only half of a PXE+IP offer if we 00792 * have other offers available 00793 */ 00794 dhcp->current_offer->priority = -1; 00795 00796 /* If we have any other PXE offers we can try, go back 00797 * to DHCPREQUEST (since they might not be proxied 00798 * offers, or might be coupled to a new IP address). 00799 * We should probably DHCPRELEASE our old IP, but the 00800 * standard does not require it. 00801 */ 00802 if ( dhcp_next_offer ( dhcp, DHCP_OFFER_PXE ) ) { 00803 dhcp->local.sin_addr.s_addr = 0; 00804 dhcp_set_state ( dhcp, &dhcp_state_request ); 00805 return; 00806 } 00807 00808 /* No possibilities left; finish without PXE options */ 00809 dhcp_finished ( dhcp, 0 ); 00810 return; 00811 } 00812 00813 /* Retransmit current packet */ 00814 dhcp_tx ( dhcp ); 00815 }
| static int dhcp_pxebs_tx | ( | struct dhcp_session * | dhcp, | |
| struct dhcp_packet * | dhcppkt, | |||
| struct sockaddr_in * | peer | |||
| ) | [static] |
Construct transmitted packet for PXE Boot Server Discovery.
| dhcp | DHCP session | |
| dhcppkt | DHCP packet | |
| peer | Destination address |
Definition at line 834 of file dhcp.c.
References BOOTPS_PORT, DBGC, DHCP_PXE_BOOT_MENU_ITEM, dhcppkt_store(), htons, INADDR_BROADCAST, inet_ntoa(), le16_to_cpu, ntohs, dhcp_session::pxe_attempt, PXE_PORT, dhcp_session::pxe_type, in_addr::s_addr, sockaddr_in::sin_addr, sockaddr_in::sin_port, and dhcp_pxe_boot_menu_item::type.
00836 { 00837 struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 }; 00838 int rc; 00839 00840 /* Set server address */ 00841 peer->sin_addr = *(dhcp->pxe_attempt); 00842 peer->sin_port = ( ( peer->sin_addr.s_addr == INADDR_BROADCAST ) ? 00843 htons ( BOOTPS_PORT ) : htons ( PXE_PORT ) ); 00844 00845 DBGC ( dhcp, "DHCP %p PXEBS REQUEST to %s:%d for type %d\n", 00846 dhcp, inet_ntoa ( peer->sin_addr ), ntohs ( peer->sin_port ), 00847 le16_to_cpu ( dhcp->pxe_type ) ); 00848 00849 /* Set boot menu item */ 00850 menu_item.type = dhcp->pxe_type; 00851 if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_PXE_BOOT_MENU_ITEM, 00852 &menu_item, sizeof ( menu_item ) ) ) != 0 ) 00853 return rc; 00854 00855 return 0; 00856 }
| static int dhcp_pxebs_accept | ( | struct dhcp_session * | dhcp, | |
| struct in_addr | bs | |||
| ) | [static] |
Check to see if PXE Boot Server address is acceptable.
| dhcp | DHCP session | |
| bs | Boot Server address |
| accept | Boot Server is acceptable |
Definition at line 865 of file dhcp.c.
References DBGC, inet_ntoa(), dhcp_session::pxe_accept, and in_addr::s_addr.
Referenced by dhcp_pxebs_rx().
00866 { 00867 struct in_addr *accept; 00868 00869 /* Accept if we have no acceptance filter */ 00870 if ( ! dhcp->pxe_accept ) 00871 return 1; 00872 00873 /* Scan through acceptance list */ 00874 for ( accept = dhcp->pxe_accept ; accept->s_addr ; accept++ ) { 00875 if ( accept->s_addr == bs.s_addr ) 00876 return 1; 00877 } 00878 00879 DBGC ( dhcp, "DHCP %p rejecting server %s\n", 00880 dhcp, inet_ntoa ( bs ) ); 00881 return 0; 00882 }
| 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 | |||
| ) | [static] |
Handle received packet during PXE Boot Server Discovery.
| dhcp | DHCP session | |
| dhcppkt | DHCP packet | |
| peer | DHCP server address | |
| msgtype | DHCP message type | |
| server_id | DHCP server ID |
Definition at line 893 of file dhcp.c.
References BOOTPS_PORT, DBGC, dhcp_finished(), dhcp_msgtype_name(), DHCP_PXE_BOOT_MENU_ITEM, dhcp_pxebs_accept(), DHCPACK, dhcppkt_fetch(), htons, inet_ntoa(), settings::name, ntohs, NULL, PXE_PORT, dhcp_session::pxe_type, PXEBS_SETTINGS_NAME, register_settings(), in_addr::s_addr, dhcp_packet::settings, sockaddr_in::sin_addr, sockaddr_in::sin_port, strerror(), and dhcp_pxe_boot_menu_item::type.
00896 { 00897 struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 }; 00898 int rc; 00899 00900 DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp, 00901 dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ), 00902 ntohs ( peer->sin_port ) ); 00903 if ( server_id.s_addr != peer->sin_addr.s_addr ) 00904 DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) ); 00905 00906 /* Identify boot menu item */ 00907 dhcppkt_fetch ( dhcppkt, DHCP_PXE_BOOT_MENU_ITEM, 00908 &menu_item, sizeof ( menu_item ) ); 00909 if ( menu_item.type ) 00910 DBGC ( dhcp, " for type %d", ntohs ( menu_item.type ) ); 00911 DBGC ( dhcp, "\n" ); 00912 00913 /* Filter out unacceptable responses */ 00914 if ( ( peer->sin_port != htons ( BOOTPS_PORT ) ) && 00915 ( peer->sin_port != htons ( PXE_PORT ) ) ) 00916 return; 00917 if ( msgtype != DHCPACK ) 00918 return; 00919 if ( menu_item.type != dhcp->pxe_type ) 00920 return; 00921 if ( ! dhcp_pxebs_accept ( dhcp, ( server_id.s_addr ? 00922 server_id : peer->sin_addr ) ) ) 00923 return; 00924 00925 /* Register settings */ 00926 dhcppkt->settings.name = PXEBS_SETTINGS_NAME; 00927 if ( ( rc = register_settings ( &dhcppkt->settings, NULL ) ) != 0 ) { 00928 DBGC ( dhcp, "DHCP %p could not register settings: %s\n", 00929 dhcp, strerror ( rc ) ); 00930 dhcp_finished ( dhcp, rc ); 00931 return; 00932 } 00933 00934 /* Terminate DHCP */ 00935 dhcp_finished ( dhcp, 0 ); 00936 }
| static void dhcp_pxebs_expired | ( | struct dhcp_session * | dhcp | ) | [static] |
Handle timer expiry during PXE Boot Server Discovery.
| dhcp | DHCP session |
Definition at line 943 of file dhcp.c.
References currticks(), dhcp_finished(), dhcp_set_state(), dhcp_state_pxebs, dhcp_tx(), ETIMEDOUT, dhcp_session::pxe_attempt, PXEBS_MAX_TIMEOUT, in_addr::s_addr, and dhcp_session::start.
00943 { 00944 unsigned long elapsed = ( currticks() - dhcp->start ); 00945 00946 /* Give up waiting before we reach the failure point, and fail 00947 * over to the next server in the attempt list 00948 */ 00949 if ( elapsed > PXEBS_MAX_TIMEOUT ) { 00950 dhcp->pxe_attempt++; 00951 if ( dhcp->pxe_attempt->s_addr ) { 00952 dhcp_set_state ( dhcp, &dhcp_state_pxebs ); 00953 return; 00954 } else { 00955 dhcp_finished ( dhcp, -ETIMEDOUT ); 00956 return; 00957 } 00958 } 00959 00960 /* Retransmit current packet */ 00961 dhcp_tx ( dhcp ); 00962 }
| void* dhcp_chaddr | ( | struct net_device * | netdev, | |
| uint8_t * | hlen, | |||
| uint16_t * | flags | |||
| ) |
Construct DHCP client hardware address field and broadcast flag.
| netdev | Network device | |
| hlen | DHCP hardware address length to fill in | |
| flags | DHCP flags to fill in |
| chaddr | DHCP client hardware address |
Definition at line 988 of file dhcp.c.
References BOOTP_FL_BROADCAST, htons, net_device::hw_addr, ll_protocol::hw_addr_len, net_device::ll_addr, ll_protocol::ll_addr_len, net_device::ll_protocol, and NULL.
Referenced by dhcp(), and dhcp_create_packet().
00989 { 00990 struct ll_protocol *ll_protocol = netdev->ll_protocol; 00991 typeof ( ( ( struct dhcphdr * ) NULL )->chaddr ) chaddr; 00992 00993 /* If the link-layer address cannot fit into the chaddr field 00994 * (as is the case for IPoIB) then try using the hardware 00995 * address instead. If we do this, set the broadcast flag, 00996 * since chaddr then does not represent a valid link-layer 00997 * address for the return path. 00998 * 00999 * If even the hardware address is too large, use an empty 01000 * chaddr field and set the broadcast flag. 01001 * 01002 * This goes against RFC4390, but RFC4390 mandates that we use 01003 * a DHCP client identifier that conforms with RFC4361, which 01004 * we cannot do without either persistent (NIC-independent) 01005 * storage, or by eliminating the hardware address completely 01006 * from the DHCP packet, which seems unfriendly to users. 01007 */ 01008 if ( ( *hlen = ll_protocol->ll_addr_len ) <= sizeof ( chaddr ) ) { 01009 return netdev->ll_addr; 01010 } 01011 *flags = htons ( BOOTP_FL_BROADCAST ); 01012 if ( ( *hlen = ll_protocol->hw_addr_len ) <= sizeof ( chaddr ) ) { 01013 return netdev->hw_addr; 01014 } else { 01015 *hlen = 0; 01016 return NULL; 01017 } 01018 }
| int dhcp_create_packet | ( | struct dhcp_packet * | dhcppkt, | |
| struct net_device * | netdev, | |||
| uint8_t | msgtype, | |||
| const void * | options, | |||
| size_t | options_len, | |||
| void * | data, | |||
| size_t | max_len | |||
| ) |
Create a DHCP packet.
| dhcppkt | DHCP packet structure to fill in | |
| netdev | Network device | |
| msgtype | DHCP message type | |
| options | Initial options to include (or NULL) | |
| options_len | Length of initial options | |
| data | Buffer for DHCP packet | |
| max_len | Size of DHCP packet buffer |
| rc | Return status code |
Definition at line 1035 of file dhcp.c.
References dhcphdr::chaddr, dhcp_chaddr(), DHCP_MAGIC_COOKIE, DHCP_MESSAGE_TYPE, dhcp_op, dhcp_xid(), dhcppkt_init(), dhcppkt_store(), ENOSPC, dhcphdr::flags, dhcphdr::hlen, htonl, dhcphdr::htype, ll_protocol::ll_proto, net_device::ll_protocol, dhcphdr::magic, memcpy, memset(), ntohs, dhcphdr::op, dhcphdr::options, and dhcphdr::xid.
Referenced by create_fakedhcpack(), create_fakepxebsack(), and dhcp_create_request().
01038 { 01039 struct dhcphdr *dhcphdr = data; 01040 void *chaddr; 01041 int rc; 01042 01043 /* Sanity check */ 01044 if ( max_len < ( sizeof ( *dhcphdr ) + options_len ) ) 01045 return -ENOSPC; 01046 01047 /* Initialise DHCP packet content */ 01048 memset ( dhcphdr, 0, max_len ); 01049 dhcphdr->xid = dhcp_xid ( netdev ); 01050 dhcphdr->magic = htonl ( DHCP_MAGIC_COOKIE ); 01051 dhcphdr->htype = ntohs ( netdev->ll_protocol->ll_proto ); 01052 dhcphdr->op = dhcp_op[msgtype]; 01053 chaddr = dhcp_chaddr ( netdev, &dhcphdr->hlen, &dhcphdr->flags ); 01054 memcpy ( dhcphdr->chaddr, chaddr, dhcphdr->hlen ); 01055 memcpy ( dhcphdr->options, options, options_len ); 01056 01057 /* Initialise DHCP packet structure */ 01058 memset ( dhcppkt, 0, sizeof ( *dhcppkt ) ); 01059 dhcppkt_init ( dhcppkt, data, max_len ); 01060 01061 /* Set DHCP_MESSAGE_TYPE option */ 01062 if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_MESSAGE_TYPE, 01063 &msgtype, sizeof ( msgtype ) ) ) != 0 ) 01064 return rc; 01065 01066 return 0; 01067 }
| int dhcp_create_request | ( | struct dhcp_packet * | dhcppkt, | |
| struct net_device * | netdev, | |||
| unsigned int | msgtype, | |||
| struct in_addr | ciaddr, | |||
| void * | data, | |||
| size_t | max_len | |||
| ) |
Create DHCP request packet.
| dhcppkt | DHCP packet structure to fill in | |
| netdev | Network device | |
| msgtype | DHCP message type | |
| ciaddr | Client IP address | |
| data | Buffer for DHCP packet | |
| max_len | Size of DHCP packet buffer |
| rc | Return status code |
Definition at line 1083 of file dhcp.c.
References assert, dhcphdr::ciaddr, DBG, DHCP_CLIENT_ID, DHCP_CLIENT_UUID, DHCP_CLIENT_UUID_TYPE, dhcp_create_packet(), DHCP_EB_BUS_ID, DHCP_EB_ENCAP, DHCP_FEATURES, dhcp_request_options_data, DHCP_USER_CLASS_ID, dhcp_packet::dhcphdr, dhcppkt_store(), fetch_setting(), fetch_setting_len(), fetch_uuid_setting(), net_device::ll_addr, dhcp_client_id::ll_addr, ll_protocol::ll_addr_len, ll_protocol::ll_proto, dhcp_client_id::ll_proto, net_device::ll_protocol, memcpy, ntohs, NULL, generic_settings::settings, net_device::settings, strerror(), table_num_entries, table_start, dhcp_client_uuid::type, and dhcp_client_uuid::uuid.
Referenced by create_fakedhcpdiscover(), and dhcp_tx().
01085 { 01086 struct dhcp_netdev_desc dhcp_desc; 01087 struct dhcp_client_id client_id; 01088 struct dhcp_client_uuid client_uuid; 01089 uint8_t *dhcp_features; 01090 size_t dhcp_features_len; 01091 size_t ll_addr_len; 01092 ssize_t len; 01093 int rc; 01094 01095 /* Create DHCP packet */ 01096 if ( ( rc = dhcp_create_packet ( dhcppkt, netdev, msgtype, 01097 dhcp_request_options_data, 01098 sizeof ( dhcp_request_options_data ), 01099 data, max_len ) ) != 0 ) { 01100 DBG ( "DHCP could not create DHCP packet: %s\n", 01101 strerror ( rc ) ); 01102 return rc; 01103 } 01104 01105 /* Set client IP address */ 01106 dhcppkt->dhcphdr->ciaddr = ciaddr; 01107 01108 /* Add options to identify the feature list */ 01109 dhcp_features = table_start ( DHCP_FEATURES ); 01110 dhcp_features_len = table_num_entries ( DHCP_FEATURES ); 01111 if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_EB_ENCAP, dhcp_features, 01112 dhcp_features_len ) ) != 0 ) { 01113 DBG ( "DHCP could not set features list option: %s\n", 01114 strerror ( rc ) ); 01115 return rc; 01116 } 01117 01118 /* Add options to identify the network device */ 01119 fetch_setting ( &netdev->settings.settings, &busid_setting, &dhcp_desc, 01120 sizeof ( dhcp_desc ) ); 01121 if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_EB_BUS_ID, &dhcp_desc, 01122 sizeof ( dhcp_desc ) ) ) != 0 ) { 01123 DBG ( "DHCP could not set bus ID option: %s\n", 01124 strerror ( rc ) ); 01125 return rc; 01126 } 01127 01128 /* Add DHCP client identifier. Required for Infiniband, and 01129 * doesn't hurt other link layers. 01130 */ 01131 client_id.ll_proto = ntohs ( netdev->ll_protocol->ll_proto ); 01132 ll_addr_len = netdev->ll_protocol->ll_addr_len; 01133 assert ( ll_addr_len <= sizeof ( client_id.ll_addr ) ); 01134 memcpy ( client_id.ll_addr, netdev->ll_addr, ll_addr_len ); 01135 if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_CLIENT_ID, &client_id, 01136 ( ll_addr_len + 1 ) ) ) != 0 ) { 01137 DBG ( "DHCP could not set client ID: %s\n", 01138 strerror ( rc ) ); 01139 return rc; 01140 } 01141 01142 /* Add client UUID, if we have one. Required for PXE. */ 01143 client_uuid.type = DHCP_CLIENT_UUID_TYPE; 01144 if ( ( len = fetch_uuid_setting ( NULL, &uuid_setting, 01145 &client_uuid.uuid ) ) >= 0 ) { 01146 if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_CLIENT_UUID, 01147 &client_uuid, 01148 sizeof ( client_uuid ) ) ) != 0 ) { 01149 DBG ( "DHCP could not set client UUID: %s\n", 01150 strerror ( rc ) ); 01151 return rc; 01152 } 01153 } 01154 01155 /* Add user class, if we have one. */ 01156 if ( ( len = fetch_setting_len ( NULL, &user_class_setting ) ) >= 0 ) { 01157 char user_class[len]; 01158 fetch_setting ( NULL, &user_class_setting, user_class, 01159 sizeof ( user_class ) ); 01160 if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_USER_CLASS_ID, 01161 &user_class, 01162 sizeof ( user_class ) ) ) != 0 ) { 01163 DBG ( "DHCP could not set user class: %s\n", 01164 strerror ( rc ) ); 01165 return rc; 01166 } 01167 } 01168 01169 return 0; 01170 }
| static int dhcp_deliver_iob | ( | struct xfer_interface * | xfer, | |
| struct io_buffer * | iobuf, | |||
| struct xfer_metadata * | meta | |||
| ) | [static] |
Receive new data.
| xfer | Data transfer interface | |
| iobuf | I/O buffer | |
| meta | Transfer metadata |
| rc | Return status code |
Definition at line 1246 of file dhcp.c.
References container_of, io_buffer::data, DBGC, dhcp(), DHCP_MESSAGE_TYPE, dhcp_msgtype_name(), DHCP_SERVER_IDENTIFIER, dhcp_xid(), dhcppkt_fetch(), dhcppkt_init(), dhcppkt_put(), EINVAL, ENOMEM, free_iob(), inet_ntoa(), iob_len(), memcpy, dhcp_session::netdev, ntohs, dhcp_session_state::rx, sockaddr_in::sin_addr, sockaddr_in::sin_port, xfer_metadata::src, dhcp_session::state, dhcphdr::xid, and zalloc().
01248 { 01249 struct dhcp_session *dhcp = 01250 container_of ( xfer, struct dhcp_session, xfer ); 01251 struct sockaddr_in *peer; 01252 size_t data_len; 01253 struct dhcp_packet *dhcppkt; 01254 struct dhcphdr *dhcphdr; 01255 uint8_t msgtype = 0; 01256 struct in_addr server_id = { 0 }; 01257 int rc = 0; 01258 01259 /* Sanity checks */ 01260 if ( ! meta->src ) { 01261 DBGC ( dhcp, "DHCP %p received packet without source port\n", 01262 dhcp ); 01263 rc = -EINVAL; 01264 goto err_no_src; 01265 } 01266 peer = ( struct sockaddr_in * ) meta->src; 01267 01268 /* Create a DHCP packet containing the I/O buffer contents. 01269 * Whilst we could just use the original buffer in situ, that 01270 * would waste the unused space in the packet buffer, and also 01271 * waste a relatively scarce fully-aligned I/O buffer. 01272 */ 01273 data_len = iob_len ( iobuf ); 01274 dhcppkt = zalloc ( sizeof ( *dhcppkt ) + data_len ); 01275 if ( ! dhcppkt ) { 01276 rc = -ENOMEM; 01277 goto err_alloc_dhcppkt; 01278 } 01279 dhcphdr = ( ( ( void * ) dhcppkt ) + sizeof ( *dhcppkt ) ); 01280 memcpy ( dhcphdr, iobuf->data, data_len ); 01281 dhcppkt_init ( dhcppkt, dhcphdr, data_len ); 01282 01283 /* Identify message type */ 01284 dhcppkt_fetch ( dhcppkt, DHCP_MESSAGE_TYPE, &msgtype, 01285 sizeof ( msgtype ) ); 01286 01287 /* Identify server ID */ 01288 dhcppkt_fetch ( dhcppkt, DHCP_SERVER_IDENTIFIER, 01289 &server_id, sizeof ( server_id ) ); 01290 01291 /* Check for matching transaction ID */ 01292 if ( dhcphdr->xid != dhcp_xid ( dhcp->netdev ) ) { 01293 DBGC ( dhcp, "DHCP %p %s from %s:%d has bad transaction " 01294 "ID\n", dhcp, dhcp_msgtype_name ( msgtype ), 01295 inet_ntoa ( peer->sin_addr ), 01296 ntohs ( peer->sin_port ) ); 01297 rc = -EINVAL; 01298 goto err_xid; 01299 }; 01300 01301 /* Handle packet based on current state */ 01302 dhcp->state->rx ( dhcp, dhcppkt, peer, msgtype, server_id ); 01303 01304 err_xid: 01305 dhcppkt_put ( dhcppkt ); 01306 err_alloc_dhcppkt: 01307 err_no_src: 01308 free_iob ( iobuf ); 01309 return rc; 01310 }
| static void dhcp_timer_expired | ( | struct retry_timer * | timer, | |
| int | fail | |||
| ) | [static] |
Handle DHCP retry timer expiry.
| timer | DHCP retry timer | |
| fail | Failure indicator |
Definition at line 1328 of file dhcp.c.
References container_of, dhcp(), dhcp_finished(), ETIMEDOUT, dhcp_session_state::expired, and dhcp_session::state.
Referenced by start_dhcp(), and start_pxebs().
01328 { 01329 struct dhcp_session *dhcp = 01330 container_of ( timer, struct dhcp_session, timer ); 01331 01332 /* If we have failed, terminate DHCP */ 01333 if ( fail ) { 01334 dhcp_finished ( dhcp, -ETIMEDOUT ); 01335 return; 01336 } 01337 01338 /* Handle timer expiry based on current state */ 01339 dhcp->state->expired ( dhcp ); 01340 }
| static void dhcp_job_kill | ( | struct job_interface * | job | ) | [static] |
Handle kill() event received via job control interface.
| job | DHCP job control interface |
Definition at line 1353 of file dhcp.c.
References container_of, dhcp(), dhcp_finished(), and ECANCELED.
01353 { 01354 struct dhcp_session *dhcp = 01355 container_of ( job, struct dhcp_session, job ); 01356 01357 /* Terminate DHCP session */ 01358 dhcp_finished ( dhcp, -ECANCELED ); 01359 }
| int start_dhcp | ( | struct job_interface * | job, | |
| struct net_device * | netdev | |||
| ) |
Start DHCP state machine on a network device.
| rc | Return status code, or positive if cached |
On a return of 0, a background job has been started to perform the DHCP request. Any nonzero return means the job has not been started; a positive return value indicates the success condition of having fetched the appropriate data from cached information.
Definition at line 1401 of file dhcp.c.
References AF_INET, BOOTPC_PORT, DBG, dhcp(), dhcp_finished(), dhcp_free(), dhcp_set_state(), dhcp_timer_expired(), ENOMEM, retry_timer::expired, fetch_uintz_setting(), refcnt::free, get_cached_dhcpack(), htons, dhcp_session::job, job_init(), job_plug_plug(), dhcp_session::local, dhcp_session::netdev, netdev_get(), NULL, ref_put(), dhcp_session::refcnt, sockaddr_in::sin_family, sockaddr_in::sin_port, SOCK_DGRAM, dhcp_session::timer, dhcp_session::xfer, xfer_init(), xfer_open_socket(), and zalloc().
Referenced by dhcp().
01401 { 01402 struct dhcp_session *dhcp; 01403 int rc; 01404 01405 /* Check for cached DHCP information */ 01406 get_cached_dhcpack(); 01407 if ( fetch_uintz_setting ( NULL, &use_cached_setting ) ) { 01408 DBG ( "DHCP using cached network settings\n" ); 01409 return 1; 01410 } 01411 01412 /* Allocate and initialise structure */ 01413 dhcp = zalloc ( sizeof ( *dhcp ) ); 01414 if ( ! dhcp ) 01415 return -ENOMEM; 01416 dhcp->refcnt.free = dhcp_free; 01417 job_init ( &dhcp->job, &dhcp_job_operations, &dhcp->refcnt ); 01418 xfer_init ( &dhcp->xfer, &dhcp_xfer_operations, &dhcp->refcnt ); 01419 dhcp->netdev = netdev_get ( netdev ); 01420 dhcp->local.sin_family = AF_INET; 01421 dhcp->local.sin_port = htons ( BOOTPC_PORT ); 01422 dhcp->timer.expired = dhcp_timer_expired; 01423 01424 /* Instantiate child objects and attach to our interfaces */ 01425 if ( ( rc = xfer_open_socket ( &dhcp->xfer, SOCK_DGRAM, &dhcp_peer, 01426 ( struct sockaddr * ) &dhcp->local ) ) != 0 ) 01427 goto err; 01428 01429 /* Enter DHCPDISCOVER state */ 01430 dhcp_set_state ( dhcp, &dhcp_state_discover ); 01431 01432 /* Attach parent interface, mortalise self, and return */ 01433 job_plug_plug ( &dhcp->job, job ); 01434 ref_put ( &dhcp->refcnt ); 01435 return 0; 01436 01437 err: 01438 dhcp_finished ( dhcp, rc ); 01439 ref_put ( &dhcp->refcnt ); 01440 return rc; 01441 }
| static void pxebs_list | ( | struct dhcp_session * | dhcp, | |
| void * | raw, | |||
| size_t | raw_len, | |||
| struct in_addr * | ip | |||
| ) | [static] |
Retrieve list of PXE boot servers for a given server type.
| dhcp | DHCP session | |
| raw | DHCP PXE boot server list | |
| raw_len | Length of DHCP PXE boot server list | |
| ip | IP address list to fill in |
Definition at line 1454 of file dhcp.c.
References DBGC, dhcp_pxe_boot_server::ip, dhcp_pxe_boot_server::num_ip, offsetof, dhcp_session::pxe_type, and dhcp_pxe_boot_server::type.
Referenced by start_pxebs().
01455 { 01456 struct dhcp_pxe_boot_server *server = raw; 01457 size_t server_len; 01458 unsigned int i; 01459 01460 while ( raw_len ) { 01461 if ( raw_len < sizeof ( *server ) ) { 01462 DBGC ( dhcp, "DHCP %p malformed PXE server list\n", 01463 dhcp ); 01464 break; 01465 } 01466 server_len = offsetof ( typeof ( *server ), 01467 ip[ server->num_ip ] ); 01468 if ( raw_len < server_len ) { 01469 DBGC ( dhcp, "DHCP %p malformed PXE server list\n", 01470 dhcp ); 01471 break; 01472 } 01473 if ( server->type == dhcp->pxe_type ) { 01474 for ( i = 0 ; i < server->num_ip ; i++ ) 01475 *(ip++) = server->ip[i]; 01476 } 01477 server = ( ( ( void * ) server ) + server_len ); 01478 raw_len -= server_len; 01479 } 01480 }
| int start_pxebs | ( | struct job_interface * | job, | |
| struct net_device * | netdev, | |||
| unsigned int | pxe_type | |||
| ) |
Start PXE Boot Server Discovery on a network device.
| rc | Return status code |
Definition at line 1494 of file dhcp.c.
References AF_INET, BOOTPC_PORT, cpu_to_le16, DBGC, dhcp(), dhcp_finished(), dhcp_free(), DHCP_PXE_BOOT_SERVER_MCAST, DHCP_PXE_BOOT_SERVERS, DHCP_PXE_DISCOVERY_CONTROL, dhcp_set_state(), dhcp_timer_expired(), EINVAL, ENOMEM, retry_timer::expired, fetch_ipv4_setting(), fetch_setting(), fetch_setting_len(), fetch_uintz_setting(), refcnt::free, htons, INADDR_BROADCAST, inet_ntoa(), dhcp_session::job, job_init(), job_plug_plug(), dhcp_session::local, dhcp_session::netdev, netdev_get(), netdev_settings(), NULL, dhcp_session::pxe_accept, dhcp_session::pxe_attempt, dhcp_session::pxe_type, pxebs_list(), PXEBS_NO_BROADCAST, PXEBS_NO_MULTICAST, PXEBS_NO_UNKNOWN_SERVERS, ref_put(), dhcp_session::refcnt, in_addr::s_addr, sockaddr_in::sin_addr, sockaddr_in::sin_family, sockaddr_in::sin_port, SOCK_DGRAM, setting::tag, dhcp_session::timer, dhcp_session::xfer, xfer_init(), xfer_open_socket(), and zalloc().
Referenced by pxebs().
01495 { 01496 struct setting pxe_discovery_control_setting = 01497 { .tag = DHCP_PXE_DISCOVERY_CONTROL }; 01498 struct setting pxe_boot_servers_setting = 01499 { .tag = DHCP_PXE_BOOT_SERVERS }; 01500 struct setting pxe_boot_server_mcast_setting = 01501 { .tag = DHCP_PXE_BOOT_SERVER_MCAST }; 01502 ssize_t pxebs_list_len; 01503 struct dhcp_session *dhcp; 01504 struct in_addr *ip; 01505 unsigned int pxe_discovery_control; 01506 int rc; 01507 01508 /* Get upper bound for PXE boot server IP address list */ 01509 pxebs_list_len = fetch_setting_len ( NULL, &pxe_boot_servers_setting ); 01510 if ( pxebs_list_len < 0 ) 01511 pxebs_list_len = 0; 01512 01513 /* Allocate and initialise structure */ 01514 dhcp = zalloc ( sizeof ( *dhcp ) + sizeof ( *ip ) /* mcast */ + 01515 sizeof ( *ip ) /* bcast */ + pxebs_list_len + 01516 sizeof ( *ip ) /* terminator */ ); 01517 if ( ! dhcp ) 01518 return -ENOMEM; 01519 dhcp->refcnt.free = dhcp_free; 01520 job_init ( &dhcp->job, &dhcp_job_operations, &dhcp->refcnt ); 01521 xfer_init ( &dhcp->xfer, &dhcp_xfer_operations, &dhcp->refcnt ); 01522 dhcp->netdev = netdev_get ( netdev ); 01523 dhcp->local.sin_family = AF_INET; 01524 fetch_ipv4_setting ( netdev_settings ( netdev ), &ip_setting, 01525 &dhcp->local.sin_addr ); 01526 dhcp->local.sin_port = htons ( BOOTPC_PORT ); 01527 dhcp->pxe_type = cpu_to_le16 ( pxe_type ); 01528 dhcp->timer.expired = dhcp_timer_expired; 01529 01530 /* Construct PXE boot server IP address lists */ 01531 pxe_discovery_control = 01532 fetch_uintz_setting ( NULL, &pxe_discovery_control_setting ); 01533 ip = ( ( ( void * ) dhcp ) + sizeof ( *dhcp ) ); 01534 dhcp->pxe_attempt = ip; 01535 if ( ! ( pxe_discovery_control & PXEBS_NO_MULTICAST ) ) { 01536 fetch_ipv4_setting ( NULL, &pxe_boot_server_mcast_setting, ip); 01537 if ( ip->s_addr ) 01538 ip++; 01539 } 01540 if ( ! ( pxe_discovery_control & PXEBS_NO_BROADCAST ) ) 01541 (ip++)->s_addr = INADDR_BROADCAST; 01542 if ( pxe_discovery_control & PXEBS_NO_UNKNOWN_SERVERS ) 01543 dhcp->pxe_accept = ip; 01544 if ( pxebs_list_len ) { 01545 uint8_t buf[pxebs_list_len]; 01546 01547 fetch_setting ( NULL, &pxe_boot_servers_setting, 01548 buf, sizeof ( buf ) ); 01549 pxebs_list ( dhcp, buf, sizeof ( buf ), ip ); 01550 } 01551 if ( ! dhcp->pxe_attempt->s_addr ) { 01552 DBGC ( dhcp, "DHCP %p has no PXE boot servers for type %04x\n", 01553 dhcp, pxe_type ); 01554 rc = -EINVAL; 01555 goto err; 01556 } 01557 01558 /* Dump out PXE server lists */ 01559 DBGC ( dhcp, "DHCP %p attempting", dhcp ); 01560 for ( ip = dhcp->pxe_attempt ; ip->s_addr ; ip++ ) 01561 DBGC ( dhcp, " %s", inet_ntoa ( *ip ) ); 01562 DBGC ( dhcp, "\n" ); 01563 if ( dhcp->pxe_accept ) { 01564 DBGC ( dhcp, "DHCP %p accepting", dhcp ); 01565 for ( ip = dhcp->pxe_accept ; ip->s_addr ; ip++ ) 01566 DBGC ( dhcp, " %s", inet_ntoa ( *ip ) ); 01567 DBGC ( dhcp, "\n" ); 01568 } 01569 01570 /* Instantiate child objects and attach to our interfaces */ 01571 if ( ( rc = xfer_open_socket ( &dhcp->xfer, SOCK_DGRAM, &dhcp_peer, 01572 ( struct sockaddr * ) &dhcp->local ) ) != 0 ) 01573 goto err; 01574 01575 /* Enter PXEBS state */ 01576 dhcp_set_state ( dhcp, &dhcp_state_pxebs ); 01577 01578 /* Attach parent interface, mortalise self, and return */ 01579 job_plug_plug ( &dhcp->job, job ); 01580 ref_put ( &dhcp->refcnt ); 01581 return 0; 01582 01583 err: 01584 dhcp_finished ( dhcp, rc ); 01585 ref_put ( &dhcp->refcnt ); 01586 return rc; 01587 }
Initial value:
{
[DHCPDISCOVER] = BOOTP_REQUEST,
[DHCPOFFER] = BOOTP_REPLY,
[DHCPREQUEST] = BOOTP_REQUEST,
[DHCPDECLINE] = BOOTP_REQUEST,
[DHCPACK] = BOOTP_REPLY,
[DHCPNAK] = BOOTP_REPLY,
[DHCPRELEASE] = BOOTP_REQUEST,
[DHCPINFORM] = BOOTP_REQUEST,
}
This table maps from DHCP message types (i.e. values of the DHCP_MESSAGE_TYPE option) to values of the "op" field within a DHCP packet.
Definition at line 61 of file dhcp.c.
Referenced by dhcp_create_packet().
uint8_t dhcp_request_options_data[] [static] |
Initial value:
{
DHCP_MESSAGE_TYPE, DHCP_BYTE ( 0 ),
DHCP_MAX_MESSAGE_SIZE,
DHCP_WORD ( ETH_MAX_MTU - 20 - 8 ),
DHCP_CLIENT_ARCHITECTURE, DHCP_WORD ( 0 ),
DHCP_CLIENT_NDI, DHCP_OPTION ( 1 , 2, 1 ),
DHCP_VENDOR_CLASS_ID,
DHCP_STRING ( 'P', 'X', 'E', 'C', 'l', 'i', 'e', 'n', 't', ':',
'A', 'r', 'c', 'h', ':', '0', '0', '0', '0', '0', ':',
'U', 'N', 'D', 'I', ':', '0', '0', '2', '0', '0', '1' ),
DHCP_USER_CLASS_ID,
DHCP_STRING ( 'g', 'P', 'X', 'E' ),
DHCP_PARAMETER_REQUEST_LIST,
DHCP_OPTION ( DHCP_SUBNET_MASK, DHCP_ROUTERS, DHCP_DNS_SERVERS,
DHCP_LOG_SERVERS, DHCP_HOST_NAME, DHCP_DOMAIN_NAME,
DHCP_ROOT_PATH, DHCP_VENDOR_ENCAP, DHCP_VENDOR_CLASS_ID,
DHCP_TFTP_SERVER_NAME, DHCP_BOOTFILE_NAME,
DHCP_EB_ENCAP, DHCP_ISCSI_INITIATOR_IQN ),
DHCP_END
}
Definition at line 73 of file dhcp.c.
Referenced by dhcp_create_request().
static struct dhcp_session_state dhcp_state_discover [static, read] |
Initial value:
{
.name = "discovery",
.tx = dhcp_discovery_tx,
.rx = dhcp_discovery_rx,
.expired = dhcp_discovery_expired,
.tx_msgtype = DHCPDISCOVER,
.apply_min_timeout = 1,
}
static struct dhcp_session_state dhcp_state_request [static, read] |
Initial value:
{
.name = "request",
.tx = dhcp_request_tx,
.rx = dhcp_request_rx,
.expired = dhcp_request_expired,
.tx_msgtype = DHCPREQUEST,
.apply_min_timeout = 0,
}
Definition at line 205 of file dhcp.c.
Referenced by dhcp_discovery_expired(), dhcp_discovery_rx(), and dhcp_request_rx().
static struct dhcp_session_state dhcp_state_proxy [static, read] |
Initial value:
{
.name = "ProxyDHCP",
.tx = dhcp_proxy_tx,
.rx = dhcp_proxy_rx,
.expired = dhcp_proxy_expired,
.tx_msgtype = DHCPREQUEST,
.apply_min_timeout = 0,
}
Definition at line 206 of file dhcp.c.
Referenced by dhcp_request_rx().
static struct dhcp_session_state dhcp_state_pxebs [static, read] |
Initial value:
{
.name = "PXEBS",
.tx = dhcp_pxebs_tx,
.rx = dhcp_pxebs_rx,
.expired = dhcp_pxebs_expired,
.tx_msgtype = DHCPREQUEST,
.apply_min_timeout = 1,
}
Definition at line 207 of file dhcp.c.
Referenced by dhcp_pxebs_expired().
struct xfer_interface_operations dhcp_xfer_operations [static] |
Initial value:
{
.close = ignore_xfer_close,
.vredirect = xfer_vreopen,
.window = unlimited_xfer_window,
.alloc_iob = default_xfer_alloc_iob,
.deliver_iob = dhcp_deliver_iob,
.deliver_raw = xfer_deliver_as_iob,
}
struct job_interface_operations dhcp_job_operations [static] |
Initial value:
{
.done = ignore_job_done,
.kill = dhcp_job_kill,
.progress = ignore_job_progress,
}
Initial value:
{
.sa_family = AF_INET,
}
This is a dummy address; the only useful portion is the socket family (so that we get a UDP connection). The DHCP client will set the IP address and source port explicitly on each transmission.
1.5.7.1