dhcp.c File Reference

Dynamic Host Configuration Protocol. More...

#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_offerdhcp_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.


Detailed Description

Dynamic Host Configuration Protocol.

Definition in file dhcp.c.


Define Documentation

#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().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER   ) 

static int dhcp_tx ( struct dhcp_session dhcp  )  [static]

Transmit DHCP request.

Parameters:
dhcp DHCP session
Return values:
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.

Parameters:
msgtype DHCP message type
Return values:
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.

Parameters:
netdev Network device
Return values:
xid DHCP XID
Extract the least significant bits of the hardware address for use as the transaction ID.

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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
dhcp DHCP session
type DHCP offer type
Return values:
offer Next DHCP offer to try
Offers are ranked by priority, then by completeness (combined IP+PXE are tried before type alone), then by order of receipt.

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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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]

Handle timer expiry during DHCP discovery.

Parameters:
dhcp DHCP session

Definition at line 679 of file dhcp.c.

References dhcp_tx().

00679                                                                {
00680 
00681         /* Retransmit current packet */
00682         dhcp_tx ( dhcp );
00683 }

static int dhcp_proxy_tx ( struct dhcp_session dhcp,
struct dhcp_packet dhcppkt,
struct sockaddr_in peer 
) [static]

Construct transmitted packet for ProxyDHCP request.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
dhcp DHCP session
bs Boot Server address
Return values:
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.

Parameters:
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.

Parameters:
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.

Parameters:
netdev Network device
hlen DHCP hardware address length to fill in
flags DHCP flags to fill in
Return values:
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.

Parameters:
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
Return values:
rc Return status code
Creates a DHCP packet in the specified buffer, and initialise a DHCP packet structure.

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.

Parameters:
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
Return values:
rc Return status code
Creates a DHCP request packet in the specified buffer, and initialise a DHCP packet structure.

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.

Parameters:
xfer Data transfer interface
iobuf I/O buffer
meta Transfer metadata
Return values:
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.

Parameters:
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.

Parameters:
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.

Parameters:
job Job control interface
netdev Network device
Return values:
rc Return status code, or positive if cached
Starts DHCP on the specified network device. If successful, the DHCPACK (and ProxyDHCPACK, if applicable) will be registered as option sources.

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.

Parameters:
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
The caller must ensure that the IP address list has sufficient space.

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.

Parameters:
job Job control interface
netdev Network device
pxe_type PXE server type
Return values:
rc Return status code
Starts PXE Boot Server Discovery on the specified network device. If successful, the Boot Server ACK will be registered as an option source.

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 }


Variable Documentation

const uint8_t dhcp_op[] [static]

Initial value:

DHCP operation types.

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().

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
}
Raw option data for options common to all DHCP requests.

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,
}
DHCP discovery state operations.

Definition at line 204 of file dhcp.c.

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,
}
DHCP request state operations.

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,
}
ProxyDHCP request state operations.

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,
}
PXE Boot Server Discovery state operations.

Definition at line 207 of file dhcp.c.

Referenced by dhcp_pxebs_expired().

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,
}
DHCP data transfer interface operations.

Definition at line 1313 of file dhcp.c.

Initial value:

 {
        .done           = ignore_job_done,
        .kill           = dhcp_job_kill,
        .progress       = ignore_job_progress,
}
DHCP job control interface operations.

Definition at line 1362 of file dhcp.c.

struct sockaddr dhcp_peer [static]

Initial value:

 {
        .sa_family = AF_INET,
}
DHCP peer address for socket opening.

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.

Definition at line 1381 of file dhcp.c.


Generated on Tue Apr 6 20:01:57 2010 for gPXE by  doxygen 1.5.7.1