mirror of
https://github.com/ipxe/ipxe
synced 2025-12-20 12:00:19 +03:00
[dhcp] Split PXE menuing code out of dhcp.c
The DHCP client code now implements only the mechanism of the DHCP and PXE Boot Server protocols. Boot Server Discovery can be initiated manually using the "pxebs" command. The menuing code is separated out into a user-level function on a par with boot_root_path(), and is entered in preference to a normal filename boot if the DHCP vendor class is "PXEClient" and the PXE boot menu option exists.
This commit is contained in:
@@ -32,6 +32,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* DHCP packet raw interface
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Calculate used length of an IPv4 field within a DHCP packet
|
||||
*
|
||||
@@ -193,21 +199,79 @@ int dhcppkt_fetch ( struct dhcp_packet *dhcppkt, unsigned int tag,
|
||||
return dhcpopt_fetch ( &dhcppkt->options, tag, data, len );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise prepopulated DHCP packet
|
||||
/****************************************************************************
|
||||
*
|
||||
* @v dhcppkt Uninitialised DHCP packet
|
||||
* @v data Memory for DHCP packet data
|
||||
* @v max_len Length of memory for DHCP packet data
|
||||
* DHCP packet settings interface
|
||||
*
|
||||
* The memory content must already be filled with valid DHCP options.
|
||||
* A zeroed block counts as a block of valid DHCP options.
|
||||
*/
|
||||
void dhcppkt_init ( struct dhcp_packet *dhcppkt, void *data, size_t len ) {
|
||||
|
||||
/**
|
||||
* Store value of DHCP setting
|
||||
*
|
||||
* @v settings Settings block
|
||||
* @v setting Setting to store
|
||||
* @v data Setting data, or NULL to clear setting
|
||||
* @v len Length of setting data
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int dhcppkt_settings_store ( struct settings *settings,
|
||||
struct setting *setting,
|
||||
const void *data, size_t len ) {
|
||||
struct dhcp_packet *dhcppkt =
|
||||
container_of ( settings, struct dhcp_packet, settings );
|
||||
|
||||
return dhcppkt_store ( dhcppkt, setting->tag, data, len );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch value of DHCP setting
|
||||
*
|
||||
* @v settings Settings block, or NULL to search all blocks
|
||||
* @v setting Setting to fetch
|
||||
* @v data Buffer to fill with setting data
|
||||
* @v len Length of buffer
|
||||
* @ret len Length of setting data, or negative error
|
||||
*/
|
||||
static int dhcppkt_settings_fetch ( struct settings *settings,
|
||||
struct setting *setting,
|
||||
void *data, size_t len ) {
|
||||
struct dhcp_packet *dhcppkt =
|
||||
container_of ( settings, struct dhcp_packet, settings );
|
||||
|
||||
return dhcppkt_fetch ( dhcppkt, setting->tag, data, len );
|
||||
}
|
||||
|
||||
/** DHCP settings operations */
|
||||
static struct settings_operations dhcppkt_settings_operations = {
|
||||
.store = dhcppkt_settings_store,
|
||||
.fetch = dhcppkt_settings_fetch,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Constructor
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialise DHCP packet
|
||||
*
|
||||
* @v dhcppkt DHCP packet structure to fill in
|
||||
* @v data DHCP packet raw data
|
||||
* @v max_len Length of raw data buffer
|
||||
*
|
||||
* Initialise a DHCP packet structure from a data buffer containing a
|
||||
* DHCP packet.
|
||||
*/
|
||||
void dhcppkt_init ( struct dhcp_packet *dhcppkt, struct dhcphdr *data,
|
||||
size_t len ) {
|
||||
dhcppkt->dhcphdr = data;
|
||||
dhcppkt->max_len = len;
|
||||
dhcpopt_init ( &dhcppkt->options, &dhcppkt->dhcphdr->options,
|
||||
( len - offsetof ( struct dhcphdr, options ) ) );
|
||||
dhcppkt->len = ( offsetof ( struct dhcphdr, options ) +
|
||||
dhcppkt->options.len );
|
||||
settings_init ( &dhcppkt->settings,
|
||||
&dhcppkt_settings_operations, &dhcppkt->refcnt,
|
||||
DHCP_SETTINGS_NAME, 0 );
|
||||
}
|
||||
|
||||
@@ -108,12 +108,11 @@ static int copy_settings ( struct dhcp_packet *dest,
|
||||
int create_fakedhcpdiscover ( struct net_device *netdev,
|
||||
void *data, size_t max_len ) {
|
||||
struct dhcp_packet dhcppkt;
|
||||
struct in_addr dummy_addr = { 0 };
|
||||
struct in_addr ciaddr = { 0 };
|
||||
int rc;
|
||||
|
||||
if ( ( rc = dhcp_create_request ( &dhcppkt, netdev, DHCPDISCOVER,
|
||||
dummy_addr, dummy_addr, dummy_addr,
|
||||
NULL, data, max_len ) ) != 0 ) {
|
||||
ciaddr, data, max_len ) ) != 0 ) {
|
||||
DBG ( "Could not create DHCPDISCOVER: %s\n",
|
||||
strerror ( rc ) );
|
||||
return rc;
|
||||
@@ -138,7 +137,7 @@ int create_fakedhcpack ( struct net_device *netdev,
|
||||
int rc;
|
||||
|
||||
/* Create base DHCPACK packet */
|
||||
if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL,
|
||||
if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL, 0,
|
||||
data, max_len ) ) != 0 ) {
|
||||
DBG ( "Could not create DHCPACK: %s\n", strerror ( rc ) );
|
||||
return rc;
|
||||
@@ -164,7 +163,7 @@ int create_fakedhcpack ( struct net_device *netdev,
|
||||
}
|
||||
|
||||
/**
|
||||
* Create ProxyDHCPACK packet
|
||||
* Create fake PXE Boot Server ACK packet
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @v data Buffer for DHCP packet
|
||||
@@ -173,43 +172,43 @@ int create_fakedhcpack ( struct net_device *netdev,
|
||||
*
|
||||
* Used by external code.
|
||||
*/
|
||||
int create_fakeproxydhcpack ( struct net_device *netdev,
|
||||
void *data, size_t max_len ) {
|
||||
int create_fakepxebsack ( struct net_device *netdev,
|
||||
void *data, size_t max_len ) {
|
||||
struct dhcp_packet dhcppkt;
|
||||
struct settings *settings;
|
||||
struct settings *bs_settings;
|
||||
struct settings *proxy_settings;
|
||||
struct settings *pxebs_settings;
|
||||
int rc;
|
||||
|
||||
/* Identify ProxyDHCP settings */
|
||||
settings = find_settings ( PROXYDHCP_SETTINGS_NAME );
|
||||
|
||||
/* No ProxyDHCP settings => use normal DHCPACK */
|
||||
if ( ! settings )
|
||||
/* Identify available settings */
|
||||
proxy_settings = find_settings ( PROXYDHCP_SETTINGS_NAME );
|
||||
pxebs_settings = find_settings ( PXEBS_SETTINGS_NAME );
|
||||
if ( ( ! proxy_settings ) && ( ! pxebs_settings ) ) {
|
||||
/* No PXE boot server; return the regular DHCPACK */
|
||||
return create_fakedhcpack ( netdev, data, max_len );
|
||||
}
|
||||
|
||||
/* Create base DHCPACK packet */
|
||||
if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL,
|
||||
if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL, 0,
|
||||
data, max_len ) ) != 0 ) {
|
||||
DBG ( "Could not create ProxyDHCPACK: %s\n",
|
||||
DBG ( "Could not create PXE BS ACK: %s\n",
|
||||
strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Merge in ProxyDHCP options */
|
||||
if ( ( rc = copy_settings ( &dhcppkt, settings ) ) != 0 ) {
|
||||
DBG ( "Could not set ProxyDHCPACK settings: %s\n",
|
||||
if ( proxy_settings &&
|
||||
( ( rc = copy_settings ( &dhcppkt, proxy_settings ) ) != 0 ) ) {
|
||||
DBG ( "Could not copy ProxyDHCP settings: %s\n",
|
||||
strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Merge in BootServerDHCP options, if present */
|
||||
bs_settings = find_settings ( BSDHCP_SETTINGS_NAME );
|
||||
if ( bs_settings ) {
|
||||
if ( ( rc = copy_settings ( &dhcppkt, bs_settings ) ) != 0 ) {
|
||||
DBG ( "Could not set BootServerDHCPACK settings: "
|
||||
"%s\n", strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
if ( pxebs_settings &&
|
||||
( ( rc = copy_settings ( &dhcppkt, pxebs_settings ) ) != 0 ) ) {
|
||||
DBG ( "Could not copy PXE BS settings: %s\n",
|
||||
strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
1603
src/net/udp/dhcp.c
1603
src/net/udp/dhcp.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user