summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arch/i386/image/nbi.c7
-rw-r--r--src/core/ibft.c27
-rw-r--r--src/core/nvo.c13
-rw-r--r--src/core/settings.c454
-rw-r--r--src/hci/commands/nvo_cmd.c6
-rw-r--r--src/hci/tui/settings_ui.c31
-rw-r--r--src/include/gpxe/dhcp.h29
-rw-r--r--src/include/gpxe/dhcpopts.h2
-rw-r--r--src/include/gpxe/dhcppkt.h9
-rw-r--r--src/include/gpxe/fakedhcp.h21
-rw-r--r--src/include/gpxe/settings.h148
-rw-r--r--src/interface/pxe/pxe_preboot.c8
-rw-r--r--src/net/dhcpopts.c16
-rw-r--r--src/net/dhcppkt.c30
-rw-r--r--src/net/fakedhcp.c205
-rw-r--r--src/net/ipv4.c143
-rw-r--r--src/net/netdev_settings.c39
-rw-r--r--src/net/tcp/iscsi.c30
-rw-r--r--src/net/udp/dhcp.c303
-rw-r--r--src/net/udp/dns.c17
-rw-r--r--src/net/udp/tftp.c17
-rw-r--r--src/usr/aoeboot.c2
-rw-r--r--src/usr/autoboot.c4
-rw-r--r--src/usr/iscsiboot.c2
24 files changed, 854 insertions, 709 deletions
diff --git a/src/arch/i386/image/nbi.c b/src/arch/i386/image/nbi.c
index 79dc8d1a..73791be9 100644
--- a/src/arch/i386/image/nbi.c
+++ b/src/arch/i386/image/nbi.c
@@ -8,8 +8,7 @@
#include <gpxe/segment.h>
#include <gpxe/init.h>
#include <gpxe/netdevice.h>
-#include <gpxe/dhcp.h>
-#include <gpxe/dhcppkt.h>
+#include <gpxe/fakedhcp.h>
#include <gpxe/image.h>
#include <gpxe/features.h>
@@ -400,8 +399,8 @@ static int nbi_prepare_dhcp ( struct image *image ) {
return -ENODEV;
}
- if ( ( rc = create_dhcpack ( boot_netdev, basemem_packet,
- sizeof ( basemem_packet ) ) ) != 0 ) {
+ if ( ( rc = create_fakedhcpack ( boot_netdev, basemem_packet,
+ sizeof ( basemem_packet ) ) ) != 0 ) {
DBGC ( image, "NBI %p failed to build DHCP packet\n", image );
return rc;
}
diff --git a/src/core/ibft.c b/src/core/ibft.c
index 61e00a8d..fda14704 100644
--- a/src/core/ibft.c
+++ b/src/core/ibft.c
@@ -123,15 +123,16 @@ static void ibft_set_ipaddr ( struct ibft_ipaddr *ipaddr, struct in_addr in ) {
}
/**
- * Fill in an IP address within iBFT from DHCP option
+ * Fill in an IP address within iBFT from configuration setting
*
* @v ipaddr IP address field
+ * @v setting Configuration setting
* @v tag DHCP option tag
*/
static void ibft_set_ipaddr_option ( struct ibft_ipaddr *ipaddr,
- unsigned int tag ) {
+ struct setting *setting ) {
struct in_addr in = { 0 };
- fetch_ipv4_setting ( NULL, tag, &in );
+ fetch_ipv4_setting ( NULL, setting, &in );
ibft_set_ipaddr ( ipaddr, in );
}
@@ -182,21 +183,21 @@ static int ibft_set_string ( struct ibft_string_block *strings,
}
/**
- * Fill in a string field within iBFT from DHCP option
+ * Fill in a string field within iBFT from configuration setting
*
* @v strings iBFT string block descriptor
* @v string String field
- * @v tag DHCP option tag
+ * @v setting Configuration setting
* @ret rc Return status code
*/
static int ibft_set_string_option ( struct ibft_string_block *strings,
struct ibft_string *string,
- unsigned int tag ) {
+ struct setting *setting ) {
int len;
char *dest;
int rc;
- len = fetch_setting_len ( NULL, tag );
+ len = fetch_setting_len ( NULL, setting );
if ( len < 0 ) {
string->offset = 0;
string->length = 0;
@@ -206,7 +207,7 @@ static int ibft_set_string_option ( struct ibft_string_block *strings,
if ( ( rc = ibft_alloc_string ( strings, string, len ) ) != 0 )
return rc;
dest = ( ( ( char * ) strings->table ) + string->offset );
- fetch_string_setting ( NULL, tag, dest, ( len + 1 ) );
+ fetch_string_setting ( NULL, setting, dest, ( len + 1 ) );
return 0;
}
@@ -226,15 +227,15 @@ static int ibft_fill_nic ( struct ibft_nic *nic,
int rc;
/* Extract values from DHCP configuration */
- ibft_set_ipaddr_option ( &nic->ip_address, DHCP_EB_YIADDR );
- ibft_set_ipaddr_option ( &nic->gateway, DHCP_ROUTERS );
- ibft_set_ipaddr_option ( &nic->dns[0], DHCP_DNS_SERVERS );
+ ibft_set_ipaddr_option ( &nic->ip_address, &ip_setting );
+ ibft_set_ipaddr_option ( &nic->gateway, &gateway_setting );
+ ibft_set_ipaddr_option ( &nic->dns[0], &dns_setting );
if ( ( rc = ibft_set_string_option ( strings, &nic->hostname,
- DHCP_HOST_NAME ) ) != 0 )
+ &hostname_setting ) ) != 0 )
return rc;
/* Derive subnet mask prefix from subnet mask */
- fetch_ipv4_setting ( NULL, DHCP_SUBNET_MASK, &netmask_addr );
+ fetch_ipv4_setting ( NULL, &netmask_setting, &netmask_addr );
while ( netmask_addr.s_addr ) {
if ( netmask_addr.s_addr & 0x1 )
netmask_count++;
diff --git a/src/core/nvo.c b/src/core/nvo.c
index 951539f1..13078022 100644
--- a/src/core/nvo.c
+++ b/src/core/nvo.c
@@ -138,19 +138,20 @@ static void nvo_init_dhcpopts ( struct nvo_block *nvo ) {
* Store value of NVO setting
*
* @v settings Settings block
- * @v tag Setting tag number
+ * @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 nvo_store ( struct settings *settings, unsigned int tag,
+static int nvo_store ( struct settings *settings, struct setting *setting,
const void *data, size_t len ) {
struct nvo_block *nvo =
container_of ( settings, struct nvo_block, settings );
int rc;
/* Update stored options */
- if ( ( rc = dhcpopt_store ( &nvo->dhcpopts, tag, data, len ) ) != 0 ) {
+ if ( ( rc = dhcpopt_store ( &nvo->dhcpopts, setting->tag,
+ data, len ) ) != 0 ) {
DBGC ( nvo, "NVO %p could not store %zd bytes: %s\n",
nvo, len, strerror ( rc ) );
return rc;
@@ -167,7 +168,7 @@ static int nvo_store ( struct settings *settings, unsigned int tag,
* Fetch value of NVO setting
*
* @v settings Settings block
- * @v tag Setting tag number
+ * @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
@@ -175,12 +176,12 @@ static int nvo_store ( struct settings *settings, unsigned int tag,
* The actual length of the setting will be returned even if
* the buffer was too small.
*/
-static int nvo_fetch ( struct settings *settings, unsigned int tag,
+static int nvo_fetch ( struct settings *settings, struct setting *setting,
void *data, size_t len ) {
struct nvo_block *nvo =
container_of ( settings, struct nvo_block, settings );
- return dhcpopt_fetch ( &nvo->dhcpopts, tag, data, len );
+ return dhcpopt_fetch ( &nvo->dhcpopts, setting->tag, data, len );
}
/** NVO settings operations */
diff --git a/src/core/settings.c b/src/core/settings.c
index 809779ae..b793ae68 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -35,43 +35,24 @@
*
*/
+/** Registered settings */
+static struct setting settings[0]
+ __table_start ( struct setting, settings );
+static struct setting settings_end[0]
+ __table_end ( struct setting, settings );
+
/** Registered setting types */
static struct setting_type setting_types[0]
__table_start ( struct setting_type, setting_types );
static struct setting_type setting_types_end[0]
__table_end ( struct setting_type, setting_types );
-/** Registered named settings */
-static struct named_setting named_settings[0]
- __table_start ( struct named_setting, named_settings );
-static struct named_setting named_settings_end[0]
- __table_end ( struct named_setting, named_settings );
-
/** Registered settings applicators */
static struct settings_applicator settings_applicators[0]
__table_start ( struct settings_applicator, settings_applicators );
static struct settings_applicator settings_applicators_end[0]
__table_end ( struct settings_applicator, settings_applicators );
-/**
- * Obtain printable version of a settings tag number
- *
- * @v tag Settings tag number
- * @ret name String representation of the tag
- */
-static inline char * setting_tag_name ( unsigned int tag ) {
- static char name[8];
-
- if ( DHCP_IS_ENCAP_OPT ( tag ) ) {
- snprintf ( name, sizeof ( name ), "%d.%d",
- DHCP_ENCAPSULATOR ( tag ),
- DHCP_ENCAPSULATED ( tag ) );
- } else {
- snprintf ( name, sizeof ( name ), "%d", tag );
- }
- return name;
-}
-
/******************************************************************************
*
* Registered settings blocks
@@ -83,32 +64,33 @@ static inline char * setting_tag_name ( unsigned int tag ) {
* Store value of simple setting
*
* @v options DHCP option block
- * @v tag Setting tag number
+ * @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
*/
-int simple_settings_store ( struct settings *settings, unsigned int tag,
+int simple_settings_store ( struct settings *settings, struct setting *setting,
const void *data, size_t len ) {
struct simple_settings *simple =
container_of ( settings, struct simple_settings, settings );
- return dhcpopt_extensible_store ( &simple->dhcpopts, tag, data, len );
+ return dhcpopt_extensible_store ( &simple->dhcpopts, setting->tag,
+ data, len );
}
/**
* Fetch value of simple setting
*
* @v options DHCP option block
- * @v tag Setting tag number
+ * @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
*/
-int simple_settings_fetch ( struct settings *settings, unsigned int tag,
+int simple_settings_fetch ( struct settings *settings, struct setting *setting,
void *data, size_t len ) {
struct simple_settings *simple =
container_of ( settings, struct simple_settings, settings );
- return dhcpopt_fetch ( &simple->dhcpopts, tag, data, len );
+ return dhcpopt_fetch ( &simple->dhcpopts, setting->tag, data, len );
}
/** Simple settings operations */
@@ -174,14 +156,14 @@ static void reprioritise_settings ( struct settings *settings ) {
return;
/* Read priority, if present */
- priority = fetch_intz_setting ( settings, DHCP_EB_PRIORITY );
+ priority = fetch_intz_setting ( settings, &priority_setting );
/* Remove from siblings list */
list_del ( &settings->siblings );
/* Reinsert after any existing blocks which have a higher priority */
list_for_each_entry ( tmp, &parent->children, siblings ) {
- tmp_priority = fetch_intz_setting ( tmp, DHCP_EB_PRIORITY );
+ tmp_priority = fetch_intz_setting ( tmp, &priority_setting );
if ( priority > tmp_priority )
break;
}
@@ -292,12 +274,12 @@ struct settings * find_settings ( const char *name ) {
* Store value of setting
*
* @v settings Settings block
- * @v tag Setting tag number
+ * @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
*/
-int store_setting ( struct settings *settings, unsigned int tag,
+int store_setting ( struct settings *settings, struct setting *setting,
const void *data, size_t len ) {
int rc;
@@ -306,11 +288,12 @@ int store_setting ( struct settings *settings, unsigned int tag,
return -ENODEV;
/* Store setting */
- if ( ( rc = settings->op->store ( settings, tag, data, len ) ) != 0 )
+ if ( ( rc = settings->op->store ( settings, setting,
+ data, len ) ) != 0 )
return rc;
/* Reprioritise settings if necessary */
- if ( tag == DHCP_EB_PRIORITY )
+ if ( setting_cmp ( setting, &priority_setting ) == 0 )
reprioritise_settings ( settings );
/* If these settings are registered, apply potentially-updated
@@ -331,7 +314,7 @@ int store_setting ( struct settings *settings, unsigned int tag,
* Fetch value of setting
*
* @v settings Settings block, or NULL to search all blocks
- * @v tag Setting tag number
+ * @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
@@ -339,7 +322,7 @@ int store_setting ( struct settings *settings, unsigned int tag,
* The actual length of the setting will be returned even if
* the buffer was too small.
*/
-int fetch_setting ( struct settings *settings, unsigned int tag,
+int fetch_setting ( struct settings *settings, struct setting *setting,
void *data, size_t len ) {
struct settings *child;
int ret;
@@ -349,12 +332,14 @@ int fetch_setting ( struct settings *settings, unsigned int tag,
settings = &settings_root;
/* Try this block first */
- if ( ( ret = settings->op->fetch ( settings, tag, data, len ) ) >= 0)
+ if ( ( ret = settings->op->fetch ( settings, setting,
+ data, len ) ) >= 0 )
return ret;
/* Recurse into each child block in turn */
list_for_each_entry ( child, &settings->children, siblings ) {
- if ( ( ret = fetch_setting ( child, tag, data, len ) ) >= 0)
+ if ( ( ret = fetch_setting ( child, setting,
+ data, len ) ) >= 0 )
return ret;
}
@@ -365,21 +350,21 @@ int fetch_setting ( struct settings *settings, unsigned int tag,
* Fetch length of setting
*
* @v settings Settings block, or NULL to search all blocks
- * @v tag Setting tag number
+ * @v setting Setting to fetch
* @ret len Length of setting data, or negative error
*
* This function can also be used as an existence check for the
* setting.
*/
-int fetch_setting_len ( struct settings *settings, unsigned int tag ) {
- return fetch_setting ( settings, tag, NULL, 0 );
+int fetch_setting_len ( struct settings *settings, struct setting *setting ) {
+ return fetch_setting ( settings, setting, NULL, 0 );
}
/**
* Fetch value of string setting
*
* @v settings Settings block, or NULL to search all blocks
- * @v tag Setting tag number
+ * @v setting Setting to fetch
* @v data Buffer to fill with setting string data
* @v len Length of buffer
* @ret len Length of string setting, or negative error
@@ -388,25 +373,25 @@ int fetch_setting_len ( struct settings *settings, unsigned int tag ) {
* The returned length will be the length of the underlying setting
* data.
*/
-int fetch_string_setting ( struct settings *settings, unsigned int tag,
+int fetch_string_setting ( struct settings *settings, struct setting *setting,
char *data, size_t len ) {
memset ( data, 0, len );
- return fetch_setting ( settings, tag, data, ( len - 1 ) );
+ return fetch_setting ( settings, setting, data, ( len - 1 ) );
}
/**
* Fetch value of IPv4 address setting
*
* @v settings Settings block, or NULL to search all blocks
- * @v tag Setting tag number
+ * @v setting Setting to fetch
* @v inp IPv4 address to fill in
* @ret len Length of setting, or negative error
*/
-int fetch_ipv4_setting ( struct settings *settings, unsigned int tag,
+int fetch_ipv4_setting ( struct settings *settings, struct setting *setting,
struct in_addr *inp ) {
int len;
- len = fetch_setting ( settings, tag, inp, sizeof ( *inp ) );
+ len = fetch_setting ( settings, setting, inp, sizeof ( *inp ) );
if ( len < 0 )
return len;
if ( len < ( int ) sizeof ( *inp ) )
@@ -418,11 +403,11 @@ int fetch_ipv4_setting ( struct settings *settings, unsigned int tag,
* Fetch value of signed integer setting
*
* @v settings Settings block, or NULL to search all blocks
- * @v tag Setting tag number
+ * @v setting Setting to fetch
* @v value Integer value to fill in
* @ret len Length of setting, or negative error
*/
-int fetch_int_setting ( struct settings *settings, unsigned int tag,
+int fetch_int_setting ( struct settings *settings, struct setting *setting,
long *value ) {
union {
long value;
@@ -433,7 +418,7 @@ int fetch_int_setting ( struct settings *settings, unsigned int tag,
int i;
buf.value = 0;
- len = fetch_setting ( settings, tag, &buf, sizeof ( buf ) );
+ len = fetch_setting ( settings, setting, &buf, sizeof ( buf ) );
if ( len < 0 )
return len;
if ( len > ( int ) sizeof ( buf ) )
@@ -451,16 +436,16 @@ int fetch_int_setting ( struct settings *settings, unsigned int tag,
* Fetch value of unsigned integer setting
*
* @v settings Settings block, or NULL to search all blocks
- * @v tag Setting tag number
+ * @v setting Setting to fetch
* @v value Integer value to fill in
* @ret len Length of setting, or negative error
*/
-int fetch_uint_setting ( struct settings *settings, unsigned int tag,
+int fetch_uint_setting ( struct settings *settings, struct setting *setting,
unsigned long *value ) {
long svalue;
int len;
- len = fetch_int_setting ( settings, tag, &svalue );
+ len = fetch_int_setting ( settings, setting, &svalue );
if ( len < 0 )
return len;
@@ -473,13 +458,13 @@ int fetch_uint_setting ( struct settings *settings, unsigned int tag,
* Fetch value of signed integer setting, or zero
*
* @v settings Settings block, or NULL to search all blocks
- * @v tag Setting tag number
+ * @v setting Setting to fetch
* @ret value Setting value, or zero
*/
-long fetch_intz_setting ( struct settings *settings, unsigned int tag ) {
+long fetch_intz_setting ( struct settings *settings, struct setting *setting ){
long value = 0;
- fetch_int_setting ( settings, tag, &value );
+ fetch_int_setting ( settings, setting, &value );
return value;
}
@@ -487,80 +472,38 @@ long fetch_intz_setting ( struct settings *settings, unsigned int tag ) {
* Fetch value of unsigned integer setting, or zero
*
* @v settings Settings block, or NULL to search all blocks
- * @v tag Setting tag number
+ * @v setting Setting to fetch
* @ret value Setting value, or zero
*/
unsigned long fetch_uintz_setting ( struct settings *settings,
- unsigned int tag ) {
+ struct setting *setting ) {
unsigned long value = 0;
- fetch_uint_setting ( settings, tag, &value );
+ fetch_uint_setting ( settings, setting, &value );
return value;
}
/**
- * Copy settings
+ * Compare two settings
*
- * @v dest Destination settings block
- * @v source Source settings block
- * @v encapsulator Encapsulating setting tag number, or zero
- * @ret rc Return status code
+ * @v a Setting to compare
+ * @v b Setting to compare
+ * @ret 0 Settings are the same
+ * @ret non-zero Settings are not the same
*/
-static int copy_encap_settings ( struct settings *dest,
- struct settings *source,
- unsigned int encapsulator ) {
- unsigned int subtag;
- unsigned int tag;
- int len;
- int check_len;
- int rc;
+int setting_cmp ( struct setting *a, struct setting *b ) {
- for ( subtag = DHCP_MIN_OPTION; subtag <= DHCP_MAX_OPTION; subtag++ ) {
- tag = DHCP_ENCAP_OPT ( encapsulator, subtag );
- switch ( tag ) {
- case DHCP_EB_ENCAP:
- case DHCP_VENDOR_ENCAP:
- /* Process encapsulated settings */
- if ( ( rc = copy_encap_settings ( dest, source,
- tag ) ) != 0 )
- return rc;
- break;
- default:
- /* Copy setting, if present */
- len = fetch_setting_len ( source, tag );
- if ( len < 0 )
- break;
- {
- char buf[len];
-
- check_len = fetch_setting ( source, tag, buf,
- sizeof ( buf ) );
- assert ( check_len == len );
- if ( ( rc = store_setting ( dest, tag, buf,
- sizeof(buf) )) !=0)
- return rc;
- }
- break;
- }
- }
+ /* If the settings have tags, compare them */
+ if ( a->tag && ( a->tag == b->tag ) )
+ return 0;
- return 0;
-}
-
-/**
- * Copy settings
- *
- * @v dest Destination settings block
- * @v source Source settings block
- * @ret rc Return status code
- */
-int copy_settings ( struct settings *dest, struct settings *source ) {
- return copy_encap_settings ( dest, source, 0 );
+ /* Otherwise, compare the names */
+ return strcmp ( a->name, b->name );
}
/******************************************************************************
*
- * Named and typed setting routines
+ * Formatted setting routines
*
******************************************************************************
*/
@@ -569,23 +512,22 @@ int copy_settings ( struct settings *dest, struct settings *source ) {
* Store value of typed setting
*
* @v settings Settings block
- * @v tag Setting tag number
+ * @v setting Setting to store
* @v type Settings type
* @v value Formatted setting data, or NULL
* @ret rc Return status code
*/
-int store_typed_setting ( struct settings *settings,
- unsigned int tag, struct setting_type *type,
- const char *value ) {
+int storef_setting ( struct settings *settings, struct setting *setting,
+ const char *value ) {
/* NULL value implies deletion. Avoid imposing the burden of
* checking for NULL values on each typed setting's storef()
* method.
*/
if ( ! value )
- return delete_setting ( settings, tag );
+ return delete_setting ( settings, setting );
- return type->storef ( settings, tag, value );
+ return setting->type->storef ( settings, setting, value );
}
/**
@@ -594,11 +536,10 @@ int store_typed_setting ( struct settings *settings,
* @v name Name
* @ret setting Named setting, or NULL
*/
-static struct named_setting * find_named_setting ( const char *name ) {
- struct named_setting *setting;
+static struct setting * find_setting ( const char *name ) {
+ struct setting *setting;
- for ( setting = named_settings ; setting < named_settings_end ;
- setting++ ) {
+ for ( setting = settings ; setting < settings_end ; setting++ ) {
if ( strcmp ( name, setting->name ) == 0 )
return setting;
}
@@ -625,9 +566,8 @@ static struct setting_type * find_setting_type ( const char *name ) {
* Parse setting name
*
* @v name Name of setting
- * @ret settings Settings block, or NULL
- * @ret tag Setting tag number
- * @ret type Setting type
+ * @v settings Settings block to fill in
+ * @v setting Setting to fill in
* @ret rc Return status code
*
* Interprets a name of the form
@@ -635,30 +575,29 @@ static struct setting_type * find_setting_type ( const char *name ) {
* fields.
*/
static int parse_setting_name ( const char *name, struct settings **settings,
- unsigned int *tag,
- struct setting_type **type ) {
+ struct setting *setting ) {
char tmp_name[ strlen ( name ) + 1 ];
char *settings_name;
- char *tag_name;
+ char *setting_name;
char *type_name;
- struct named_setting *named_setting;
+ struct setting *named_setting;
char *tmp;
/* Set defaults */
*settings = &settings_root;
- *tag = 0;
- *type = &setting_type_hex;
+ memset ( setting, 0, sizeof ( *setting ) );
+ setting->type = &setting_type_hex;
- /* Split name into "[settings_name/]tag_name[:type_name]" */
+ /* Split name into "[settings_name/]setting_name[:type_name]" */
memcpy ( tmp_name, name, sizeof ( tmp_name ) );
- if ( ( tag_name = strchr ( tmp_name, '/' ) ) != NULL ) {
- *(tag_name++) = 0;
+ if ( ( setting_name = strchr ( tmp_name, '/' ) ) != NULL ) {
+ *(setting_name++) = 0;
settings_name = tmp_name;
} else {
- tag_name = tmp_name;
+ setting_name = tmp_name;
settings_name = NULL;
}
- if ( ( type_name = strchr ( tag_name, ':' ) ) != NULL )
+ if ( ( type_name = strchr ( setting_name, ':' ) ) != NULL )
*(type_name++) = 0;
/* Identify settings block, if specified */
@@ -672,19 +611,19 @@ static int parse_setting_name ( const char *name, struct settings **settings,
}
/* Identify tag number */
- if ( ( named_setting = find_named_setting ( tag_name ) ) != NULL ) {
- *tag = named_setting->tag;
- *type = named_setting->type;
+ if ( ( named_setting = find_setting ( setting_name ) ) != NULL ) {
+ memcpy ( setting, named_setting, sizeof ( *setting ) );
} else {
/* Unrecognised name: try to interpret as a tag number */
- tmp = tag_name;
+ tmp = setting_name;
while ( 1 ) {
- *tag = ( ( *tag << 8 ) | strtoul ( tmp, &tmp, 0 ) );
+ setting->tag = ( ( setting->tag << 8 ) |
+ strtoul ( tmp, &tmp, 0 ) );
if ( *tmp == 0 )
break;
if ( *tmp != '.' ) {
- DBG ( "Invalid tag number \"%s\" in \"%s\"\n",
- tag_name, name );
+ DBG ( "Invalid setting \"%s\" in \"%s\"\n",
+ setting_name, name );
return -ENOENT;
}
tmp++;
@@ -693,8 +632,8 @@ static int parse_setting_name ( const char *name, struct settings **settings,
/* Identify setting type, if specified */
if ( type_name ) {
- *type = find_setting_type ( type_name );
- if ( *type == NULL ) {
+ setting->type = find_setting_type ( type_name );
+ if ( setting->type == NULL ) {
DBG ( "Invalid setting type \"%s\" in \"%s\"\n",
type_name, name );
return -ENOTSUP;
@@ -711,16 +650,14 @@ static int parse_setting_name ( const char *name, struct settings **settings,
* @v value Formatted setting data, or NULL
* @ret rc Return status code
*/
-int store_named_setting ( const char *name, const char *value ) {
+int storef_named_setting ( const char *name, const char *value ) {
struct settings *settings;
- unsigned int tag;
- struct setting_type *type;
+ struct setting setting;
int rc;
- if ( ( rc = parse_setting_name ( name, &settings, &tag,
- &type ) ) != 0 )
+ if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
return rc;
- return store_typed_setting ( settings, tag, type, value );
+ return storef_setting ( settings, &setting, value );
}
/**
@@ -731,16 +668,14 @@ int store_named_setting ( const char *name, const char *value ) {
* @v len Length of buffer
* @ret len Length of formatted value, or negative error
*/
-int fetch_named_setting ( const char *name, char *buf, size_t len ) {
+int fetchf_named_setting ( const char *name, char *buf, size_t len ) {
struct settings *settings;
- unsigned int tag;
- struct setting_type *type;
+ struct setting setting;
int rc;
- if ( ( rc = parse_setting_name ( name, &settings, &tag,
- &type ) ) != 0 )
+ if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
return rc;
- return fetch_typed_setting ( settings, tag, type, buf, len );
+ return fetchf_setting ( settings, &setting, buf, len );
}
/******************************************************************************
@@ -754,27 +689,27 @@ int fetch_named_setting ( const char *name, char *buf, size_t len ) {
* Parse and store value of string setting
*
* @v settings Settings block
- * @v tag Setting tag number
+ * @v setting Setting to store
* @v value Formatted setting data
* @ret rc Return status code
*/
-static int storef_string ( struct settings *settings, unsigned int tag,
+static int storef_string ( struct settings *settings, struct setting *setting,
const char *value ) {
- return store_setting ( settings, tag, value, strlen ( value ) );
+ return store_setting ( settings, setting, value, strlen ( value ) );
}
/**
* Fetch and format value of string setting
*
* @v settings Settings block, or NULL to search all blocks
- * @v tag Setting tag number
+ * @v setting Setting to fetch
* @v buf Buffer to contain formatted value
* @v len Length of buffer
* @ret len Length of formatted value, or negative error
*/
-static int fetchf_string ( struct settings *settings, unsigned int tag,
+static int fetchf_string ( struct settings *settings, struct setting *setting,
char *buf, size_t len ) {
- return fetch_string_setting ( settings, tag, buf, len );
+ return fetch_string_setting ( settings, setting, buf, len );
}
/** A string setting type */
@@ -788,34 +723,34 @@ struct setting_type setting_type_string __setting_type = {
* Parse and store value of IPv4 address setting
*
* @v settings Settings block
- * @v tag Setting tag number
+ * @v setting Setting to store
* @v value Formatted setting data
* @ret rc Return status code
*/
-static int storef_ipv4 ( struct settings *settings, unsigned int tag,
+static int storef_ipv4 ( struct settings *settings, struct setting *setting,
const char *value ) {
struct in_addr ipv4;
if ( inet_aton ( value, &ipv4 ) == 0 )
return -EINVAL;
- return store_setting ( settings, tag, &ipv4, sizeof ( ipv4 ) );
+ return store_setting ( settings, setting, &ipv4, sizeof ( ipv4 ) );
}
/**
* Fetch and format value of IPv4 address setting
*
* @v settings Settings block, or NULL to search all blocks
- * @v tag Setting tag number
+ * @v setting Setting to fetch
* @v buf Buffer to contain formatted value
* @v len Length of buffer
* @ret len Length of formatted value, or negative error
*/
-static int fetchf_ipv4 ( struct settings *settings, unsigned int tag,
+static int fetchf_ipv4 ( struct settings *settings, struct setting *setting,
char *buf, size_t len ) {
struct in_addr ipv4;
int rc;
- if ( ( rc = fetch_ipv4_setting ( settings, tag, &ipv4 ) ) < 0 )
+ if ( ( rc = fetch_ipv4_setting ( settings, setting, &ipv4 ) ) < 0 )
return rc;
return snprintf ( buf, len, inet_ntoa ( ipv4 ) );
}
@@ -831,12 +766,12 @@ struct setting_type setting_type_ipv4 __setting_type = {
* Parse and store value of integer setting
*
* @v settings Settings block
- * @v tag Setting tag number
+ * @v setting Setting to store
* @v value Formatted setting data
* @v size Integer size, in bytes
* @ret rc Return status code
*/
-static int storef_int ( struct settings *settings, unsigned int tag,
+static int storef_int ( struct settings *settings, struct setting *setting,
const char *value, unsigned int size ) {
union {
uint32_t num;
@@ -847,7 +782,7 @@ static int storef_int ( struct settings *settings, unsigned int tag,
u.num = htonl ( strtoul ( value, &endp, 0 ) );
if ( *endp )
return -EINVAL;
- return store_setting ( settings, tag,
+ return store_setting ( settings, setting,
&u.bytes[ sizeof ( u ) - size ], size );
}
@@ -855,59 +790,59 @@ static int storef_int ( struct settings *settings, unsigned int tag,
* Parse and store value of 8-bit integer setting
*
* @v settings Settings block
- * @v tag Setting tag number
+ * @v setting Setting to store
* @v value Formatted setting data
* @v size Integer size, in bytes
* @ret rc Return status code
*/
-static int storef_int8 ( struct settings *settings, unsigned int tag,
+static int storef_int8 ( struct settings *settings, struct setting *setting,
const char *value ) {
- return storef_int ( settings, tag, value, 1 );
+ return storef_int ( settings, setting, value, 1 );
}
/**
* Parse and store value of 16-bit integer setting
*
* @v settings Settings block
- * @v tag Setting tag number
+ * @v setting Setting to store
* @v value Formatted setting data
* @v size Integer size, in bytes
* @ret rc Return status code
*/
-static int storef_int16 ( struct settings *settings, unsigned int tag,
+static int storef_int16 ( struct settings *settings, struct setting *setting,
const char *value ) {
- return storef_int ( settings, tag, value, 2 );
+ return storef_int ( settings, setting, value, 2 );
}
/**
* Parse and store value of 32-bit integer setting
*
* @v settings Settings block
- * @v tag Setting tag number
+ * @v setting Setting to store
* @v value Formatted setting data
* @v size Integer size, in bytes
* @ret rc Return status code
*/
-static int storef_int32 ( struct settings *settings, unsigned int tag,
+static int storef_int32 ( struct settings *settings, struct setting *setting,
const char *value ) {
- return storef_int ( settings, tag, value, 4 );
+ return storef_int ( settings, setting, value, 4 );
}
/**
* Fetch and format value of signed integer setting
*
* @v settings Settings block, or NULL to search all blocks
- * @v tag Setting tag number
+ * @v setting Setting to fetch
* @v buf Buffer to contain formatted value
* @v len Length of buffer
* @ret len Length of formatted value, or negative error
*/
-static int fetchf_int ( struct settings *settings, unsigned int tag,
+static int fetchf_int ( struct settings *settings, struct setting *setting,
char *buf, size_t len ) {
long value;
int rc;
- if ( ( rc = fetch_int_setting ( settings, tag, &value ) ) < 0 )
+ if ( ( rc = fetch_int_setting ( settings, setting, &value ) ) < 0 )
return rc;
return snprintf ( buf, len, "%ld", value );
}
@@ -916,17 +851,17 @@ static int fetchf_int ( struct settings *settings, unsigned int tag,
* Fetch and format value of unsigned integer setting
*
* @v settings Settings block, or NULL to search all blocks
- * @v tag Setting tag number
+ * @v setting Setting to fetch
* @v buf Buffer to contain formatted value
* @v len Length of buffer
* @ret len Length of formatted value, or negative error
*/
-static int fetchf_uint ( struct settings *settings, unsigned int tag,
+static int fetchf_uint ( struct settings *settings, struct setting *setting,
char *buf, size_t len ) {
unsigned long value;
int rc;
- if ( ( rc = fetch_uint_setting ( settings, tag, &value ) ) < 0 )
+ if ( ( rc = fetch_uint_setting ( settings, setting, &value ) ) < 0 )
return rc;
return snprintf ( buf, len, "%#lx", value );
}
@@ -977,11 +912,11 @@ struct setting_type setting_type_uint32 __setting_type = {
* Parse and store value of hex string setting
*
* @v settings Settings block
- * @v tag Setting tag number
+ * @v setting Setting to store
* @v value Formatted setting data
* @ret rc Return status code
*/
-static int storef_hex ( struct settings *settings, unsigned int tag,
+static int storef_hex ( struct settings *settings, struct setting *setting,
const char *value ) {
char *ptr = ( char * ) value;
uint8_t bytes[ strlen ( value ) ]; /* cannot exceed strlen(value) */
@@ -991,7 +926,7 @@ static int storef_hex ( struct settings *settings, unsigned int tag,
bytes[len++] = strtoul ( ptr, &ptr, 16 );
switch ( *ptr ) {
case '\0' :
- return store_setting ( settings, tag, bytes, len );
+ return store_setting ( settings, setting, bytes, len );
case ':' :
ptr++;
break;
@@ -1005,26 +940,27 @@ static int storef_hex ( struct settings *settings, unsigned int tag,
* Fetch and format value of hex string setting
*
* @v settings Settings block, or NULL to search all blocks
- * @v tag Setting tag number
+ * @v setting Setting to fetch
* @v buf Buffer to contain formatted value
* @v len Length of buffer
* @ret len Length of formatted value, or negative error
*/
-static int fetchf_hex ( struct settings *settings, unsigned int tag,
+static int fetchf_hex ( struct settings *settings, struct setting *setting,
char *buf, size_t len ) {
int raw_len;
int check_len;
int used = 0;
int i;
- raw_len = fetch_setting_len ( settings, tag );
+ raw_len = fetch_setting_len ( settings, setting );
if ( raw_len < 0 )
return raw_len;
{
uint8_t raw[raw_len];
- check_len = fetch_setting ( settings, tag, raw, sizeof (raw) );
+ check_len = fetch_setting ( settings, setting, raw,
+ sizeof ( raw ) );
assert ( check_len == raw_len );
if ( len )
@@ -1047,83 +983,55 @@ struct setting_type setting_type_hex __setting_type = {
/******************************************************************************
*
- * Named settings
+ * Settings
*
******************************************************************************
*/
-/** Some basic setting definitions */
-struct named_setting basic_named_settings[] __named_setting = {
- {
- .name = "ip",
- .description = "IPv4 address",
- .tag = DHCP_EB_YIADDR,
- .type = &setting_type_ipv4,
- },
- {
- .name = "netmask",
- .description = "IPv4 subnet mask",
- .tag = DHCP_SUBNET_MASK,
- .type = &setting_type_ipv4,
- },
- {
- .name = "gateway",
- .description = "Default gateway",
- .tag = DHCP_ROUTERS,
- .type = &setting_type_ipv4,
- },
- {
- .name = "dns",
- .description = "DNS server",
- .tag = DHCP_DNS_SERVERS,
- .type = &setting_type_ipv4,
- },
- {
- .name = "hostname",
- .description = "Host name",
- .tag = DHCP_HOST_NAME,
- .type = &setting_type_string,
- },
- {
- .name = "next-server",
- .description = "TFTP server",
- .tag = DHCP_EB_SIADDR,
- .type = &setting_type_ipv4,
- },
- {
- .name = "filename",
- .description = "Boot filename",
- .tag = DHCP_BOOTFILE_NAME,
- .type = &setting_type_string,
- },
- {
- .name = "root-path",
- .description = "NFS/iSCSI root path",
- .tag = DHCP_ROOT_PATH,
- .type = &setting_type_string,
- },
- {
- .name = "username",
- .description = "User name",
- .tag = DHCP_EB_USERNAME,
- .type = &setting_type_string,
- },
- {
- .name = "password",
- .description = "Password",
- .tag = DHCP_EB_PASSWORD,
- .type = &setting_type_string,
- },
- {
- .name = "initiator-iqn",
- .description = "iSCSI initiator name",
- .tag = DHCP_ISCSI_INITIATOR_IQN,
- .type = &setting_type_string,
- },
- {
- .name = "priority",
- .description = "Priority of these settings",
- .tag = DHCP_EB_PRIORITY,
- .type = &setting_type_int8,
- },
+/** Hostname setting */
+struct setting hostname_setting __setting = {
+ .name = "hostname",
+ .description = "Host name",
+ .tag = DHCP_HOST_NAME,
+ .type = &setting_type_string,
+};
+
+/** Filename setting */
+struct setting filename_setting __setting = {
+ .name = "filename",
+ .description = "Boot filename",
+ .tag = DHCP_BOOTFILE_NAME,
+ .type = &setting_type_string,
+};
+
+/** Root path setting */
+struct setting root_path_setting __setting = {
+ .name = "root-path",
+ .description = "NFS/iSCSI root path",
+ .tag = DHCP_ROOT_PATH,
+ .type = &setting_type_string,
+};
+
+/** Username setting */
+struct setting username_setting __setting = {
+ .name = "username",
+ .description = "User name",
+ .tag = DHCP_EB_USERNAME,
+ .type = &setting_type_string,
+};
+
+/** Password setting */
+struct setting password_setting __setting = {
+ .name = "password",
+ .description = "Password",
+ .tag = DHCP_EB_PASSWORD,
+ .type = &setting_type_string,
+};
+
+/** Priority setting */
+struct setting priority_setting __setting = {
+ .name = "priority",
+ .description = "Priority of these settings",
+ .tag = DHCP_EB_PRIORITY,
+ .type = &setting_type_int8,
};
diff --git a/src/hci/commands/nvo_cmd.c b/src/hci/commands/nvo_cmd.c
index e2fdd8fb..c0c07280 100644
--- a/src/hci/commands/nvo_cmd.c
+++ b/src/hci/commands/nvo_cmd.c
@@ -16,8 +16,8 @@ static int show_exec ( int argc, char **argv ) {
return 1;
}
- if ( ( rc = fetch_named_setting ( argv[1], buf,
- sizeof ( buf ) ) ) < 0 ){
+ if ( ( rc = fetchf_named_setting ( argv[1], buf,
+ sizeof ( buf ) ) ) < 0 ){
printf ( "Could not find \"%s\": %s\n",
argv[1], strerror ( rc ) );
return 1;
@@ -35,7 +35,7 @@ static int set_exec ( int argc, char **argv ) {
return 1;
}
- if ( ( rc = store_named_setting ( argv[1], argv[2] ) ) != 0 ) {
+ if ( ( rc = storef_named_setting ( argv[1], argv[2] ) ) != 0 ) {
printf ( "Could not set \"%s\"=\"%s\": %s\n",
argv[1], argv[2], strerror ( rc ) );
return 1;
diff --git a/src/hci/tui/settings_ui.c b/src/hci/tui/settings_ui.c
index 83146b58..0907bfd3 100644
--- a/src/hci/tui/settings_ui.c
+++ b/src/hci/tui/settings_ui.c
@@ -64,7 +64,7 @@ struct setting_widget {
/** Settings block */
struct settings *settings;
/** Configuration setting */
- struct named_setting *setting;
+ struct setting *setting;
/** Screen row */
unsigned int row;
/** Screen column */
@@ -78,17 +78,17 @@ struct setting_widget {
};
/** Registered configuration settings */
-static struct named_setting named_settings[0]
- __table_start ( struct named_setting, named_settings );
-static struct named_setting named_settings_end[0]
- __table_end ( struct named_setting, named_settings );
-#define NUM_SETTINGS ( ( unsigned ) ( named_settings_end - named_settings ) )
+static struct setting all_settings[0]
+ __table_start ( struct setting, settings );
+static struct setting all_settings_end[0]
+ __table_end ( struct setting, settings );
+#define NUM_SETTINGS ( ( unsigned ) ( all_settings_end - all_settings ) )
static void load_setting ( struct setting_widget *widget ) __nonnull;
static int save_setting ( struct setting_widget *widget ) __nonnull;
static void init_setting ( struct setting_widget *widget,
struct settings *settings,
- struct named_setting *setting,
+ struct setting *setting,
unsigned int row, unsigned int col ) __nonnull;
static void draw_setting ( struct setting_widget *widget ) __nonnull;
static int edit_setting ( struct setting_widget *widget, int key ) __nonnull;
@@ -99,7 +99,7 @@ static void vmsg ( unsigned int row, const char *fmt, va_list args ) __nonnull;
static void msg ( unsigned int row, const char *fmt, ... ) __nonnull;
static void valert ( const char *fmt, va_list args ) __nonnull;
static void alert ( const char *fmt, ... ) __nonnull;
-static void draw_info_row ( struct named_setting *setting ) __nonnull;
+static void draw_info_row ( struct setting *setting ) __nonnull;
static int main_loop ( struct settings *settings ) __nonnull;
/**
@@ -114,9 +114,8 @@ static void load_setting ( struct setting_widget *widget ) {
widget->editing = 0;
/* Read current setting value */
- if ( fetch_typed_setting ( widget->settings, widget->setting->tag,
- widget->setting->type, widget->value,
- sizeof ( widget->value ) ) < 0 ) {
+ if ( fetchf_setting ( widget->settings, widget->setting,
+ widget->value, sizeof ( widget->value ) ) < 0 ) {
widget->value[0] = '\0';
}
@@ -133,8 +132,8 @@ static void load_setting ( struct setting_widget *widget ) {
* @v widget Setting widget
*/
static int save_setting ( struct setting_widget *widget ) {
- return store_typed_setting ( widget->settings, widget->setting->tag,
- widget->setting->type, widget->value );
+ return storef_setting ( widget->settings, widget->setting,
+ widget->value );
}
/**
@@ -148,7 +147,7 @@ static int save_setting ( struct setting_widget *widget ) {
*/
static void init_setting ( struct setting_widget *widget,
struct settings *settings,
- struct named_setting *setting,
+ struct setting *setting,
unsigned int row, unsigned int col ) {
/* Initialise widget structure */
@@ -224,7 +223,7 @@ static int edit_setting ( struct setting_widget *widget, int key ) {
static void init_setting_index ( struct setting_widget *widget,
struct settings *settings,
unsigned int index ) {
- init_setting ( widget, settings, &named_settings[index],
+ init_setting ( widget, settings, &all_settings[index],
( SETTINGS_LIST_ROW + index ), SETTINGS_LIST_COL );
}
@@ -311,7 +310,7 @@ static void draw_title_row ( void ) {
*
* @v setting Current configuration setting
*/
-static void draw_info_row ( struct named_setting *setting ) {
+static void draw_info_row ( struct setting *setting ) {
clearmsg ( INFO_ROW );
attron ( A_BOLD );
msg ( INFO_ROW, "%s - %s", setting->name, setting->description );
diff --git a/src/include/gpxe/dhcp.h b/src/include/gpxe/dhcp.h
index bc0e9a3b..94cc2010 100644
--- a/src/include/gpxe/dhcp.h
+++ b/src/include/gpxe/dhcp.h
@@ -15,8 +15,8 @@
struct net_device;
struct job_interface;
+struct dhcp_options;
struct dhcp_packet;
-struct settings;
/** BOOTP/DHCP server port */
#define BOOTPS_PORT 67
@@ -179,15 +179,6 @@ struct settings;
*/
#define DHCP_EB_SIADDR DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 3 )
-/** MAC address
- *
- * This option is used internally to contain the network device
- * hardware address, in order to provide a consistent approach to
- * storing and processing options. It should never be present in a
- * DHCP packet.
- */
-#define DHCP_EB_MAC DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 4 )
-
/*
* Tags in the range 0x10-0x7f are reserved for feature markers
*
@@ -445,11 +436,19 @@ struct dhcphdr {
/** Maximum time that we will wait for ProxyDHCP offers */
#define PROXYDHCP_WAIT_TIME ( TICKS_PER_SEC * 1 )
-extern int create_dhcpdiscover ( struct net_device *netdev,
- void *data, size_t max_len );
-extern int create_dhcpack ( struct net_device *netdev,
- void *data, size_t max_len );
-extern int create_proxydhcpack ( struct net_device *netdev,
+/** Settings block name used for DHCP responses */
+#define DHCP_SETTINGS_NAME "dhcp"
+
+/** Settings block name used for ProxyDHCP responses */
+#define PROXYDHCP_SETTINGS_NAME "proxydhcp"
+
+extern int create_dhcp_packet ( struct dhcp_packet *dhcppkt,
+ struct net_device *netdev, uint8_t msgtype,
+ struct dhcp_options *options,
+ void *data, size_t max_len );
+extern int create_dhcp_request ( struct dhcp_packet *dhcppkt,
+ struct net_device *netdev,
+ struct dhcp_packet *dhcpoffer,
void *data, size_t max_len );
extern int start_dhcp ( struct job_interface *job, struct net_device *netdev );
diff --git a/src/include/gpxe/dhcpopts.h b/src/include/gpxe/dhcpopts.h
index b16c5f22..8391a9d4 100644
--- a/src/include/gpxe/dhcpopts.h
+++ b/src/include/gpxe/dhcpopts.h
@@ -7,7 +7,7 @@
*
*/
-#include <gpxe/dhcp.h>
+#include <stdint.h>
/** A DHCP options block */
struct dhcp_options {
diff --git a/src/include/gpxe/dhcppkt.h b/src/include/gpxe/dhcppkt.h
index 98b8dad8..179be2f8 100644
--- a/src/include/gpxe/dhcppkt.h
+++ b/src/include/gpxe/dhcppkt.h
@@ -9,15 +9,12 @@
#include <gpxe/dhcp.h>
#include <gpxe/dhcpopts.h>
-#include <gpxe/settings.h>
/**
* A DHCP packet
*
*/
struct dhcp_packet {
- /** Settings block */
- struct settings settings;
/** The DHCP packet contents */
struct dhcphdr *dhcphdr;
/** Maximum length of the DHCP packet buffer */
@@ -28,7 +25,11 @@ struct dhcp_packet {
struct dhcp_options options;
};
-extern void dhcppkt_init ( struct dhcp_packet *dhcppkt, struct refcnt *refcnt,
+extern int dhcppkt_store ( struct dhcp_packet *dhcppkt, unsigned int tag,
+ const void *data, size_t len );
+extern int dhcppkt_fetch ( struct dhcp_packet *dhcppkt, unsigned int tag,
+ void *data, size_t len );
+extern void dhcppkt_init ( struct dhcp_packet *dhcppkt,
void *data, size_t len );
#endif /* _GPXE_DHCPPKT_H */
diff --git a/src/include/gpxe/fakedhcp.h b/src/include/gpxe/fakedhcp.h
new file mode 100644
index 00000000..990b56af
--- /dev/null
+++ b/src/include/gpxe/fakedhcp.h
@@ -0,0 +1,21 @@
+#ifndef _GPXE_FAKEDHCP_H
+#define _GPXE_FAKEDHCP_H
+
+/** @file
+ *
+ * Fake DHCP packets
+ *
+ */
+
+#include <stdint.h>
+
+struct net_device;
+
+extern int create_fakedhcpdiscover ( struct net_device *netdev,
+ void *data, size_t max_len );
+extern int create_fakedhcpack ( struct net_device *netdev,
+ void *data, size_t max_len );
+extern int create_fakeproxydhcpack ( struct net_device *netdev,
+ void *data, size_t max_len );
+
+#endif /* _GPXE_FAKEDHCP_H */
diff --git a/src/include/gpxe/settings.h b/src/include/gpxe/settings.h
index f32d3ec9..40825698 100644
--- a/src/include/gpxe/settings.h
+++ b/src/include/gpxe/settings.h
@@ -16,22 +16,44 @@
struct settings;
struct in_addr;
+/** A setting */
+struct setting {
+ /** Name
+ *
+ * This is the human-readable name for the setting.
+ */
+ const char *name;
+ /** Description */
+ const char *description;
+ /** Setting type
+ *
+ * This identifies the type of setting (e.g. string, IPv4
+ * address, etc.).
+ */
+ struct setting_type *type;
+ /** DHCP option number, if applicable */
+ unsigned int tag;
+};
+
+/** Declare a configuration setting */
+#define __setting __table ( struct setting, settings, 01 )
+
/** Settings block operations */
struct settings_operations {
/** Store value of setting
*
* @v settings Settings block
- * @v tag Setting tag number
+ * @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
*/
- int ( * store ) ( struct settings *settings, unsigned int tag,
+ int ( * store ) ( struct settings *settings, struct setting *setting,
const void *data, size_t len );
/** Fetch value of setting
*
* @v settings Settings block
- * @v tag Setting tag number
+ * @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
@@ -39,7 +61,7 @@ struct settings_operations {
* The actual length of the setting will be returned even if
* the buffer was too small.
*/
- int ( * fetch ) ( struct settings *settings, unsigned int tag,
+ int ( * fetch ) ( struct settings *settings, struct setting *setting,
void *data, size_t len );
};
@@ -74,21 +96,21 @@ struct setting_type {
/** Parse and set value of setting
*
* @v settings Settings block
- * @v tag Setting tag number
+ * @v setting Setting to store
* @v value Formatted setting data
* @ret rc Return status code
*/
- int ( * storef ) ( struct settings *settings, unsigned int tag,
+ int ( * storef ) ( struct settings *settings, struct setting *setting,
const char *value );
/** Fetch and format value of setting
*
- * @v settings Settings block, or NULL to search all blocks
- * @v tag Setting tag number
+ * @v settings Settings block
+ * @v setting Setting to fetch
* @v buf Buffer to contain formatted value
* @v len Length of buffer
* @ret len Length of formatted value, or negative error
*/
- int ( * fetchf ) ( struct settings *settings, unsigned int tag,
+ int ( * fetchf ) ( struct settings *settings, struct setting *setting,
char *buf, size_t len );
};
@@ -97,33 +119,6 @@ struct setting_type {
__table ( struct setting_type, setting_types, 01 )
/**
- * A named setting
- *
- * This represents a single setting (e.g. "hostname"), encapsulating
- * the information about the setting's tag number and type.
- */
-struct named_setting {
- /** Name
- *
- * This is the human-readable name for the setting.
- */
- const char *name;
- /** Description */
- const char *description;
- /** Setting tag number */
- unsigned int tag;
- /** Setting type
- *
- * This identifies the type of setting (e.g. string, IPv4
- * address, etc.).
- */
- struct setting_type *type;
-};
-
-/** Declare a configuration setting */
-#define __named_setting __table ( struct named_setting, named_settings, 01 )
-
-/**
* A settings applicator
*
*/
@@ -151,41 +146,49 @@ struct simple_settings {
};
extern struct settings_operations simple_settings_operations;
-
-extern int simple_settings_store ( struct settings *settings, unsigned int tag,
+extern int simple_settings_store ( struct settings *settings,
+ struct setting *setting,
const void *data, size_t len );
-extern int simple_settings_fetch ( struct settings *settings, unsigned int tag,
+extern int simple_settings_fetch ( struct settings *settings,
+ struct setting *setting,
void *data, size_t len );
+
extern int register_settings ( struct settings *settings,
struct settings *parent );
extern void unregister_settings ( struct settings *settings );
-extern int store_setting ( struct settings *settings, unsigned int tag,
+
+extern int store_setting ( struct settings *settings, struct setting *setting,
const void *data, size_t len );
-extern int fetch_setting ( struct settings *settings, unsigned int tag,
+extern int fetch_setting ( struct settings *settings, struct setting *setting,
void *data, size_t len );
-extern int copy_settings ( struct settings *dest, struct settings *source );
-extern int fetch_setting_len ( struct settings *settings, unsigned int tag );
-extern int fetch_string_setting ( struct settings *settings, unsigned int tag,
+extern int fetch_setting_len ( struct settings *settings,
+ struct setting *setting );
+extern int fetch_string_setting ( struct settings *settings,
+ struct setting *setting,
char *data, size_t len );
-extern int fetch_ipv4_setting ( struct settings *settings, unsigned int tag,
- struct in_addr *inp );
-extern int fetch_int_setting ( struct settings *settings, unsigned int tag,
- long *value );
-extern int fetch_uint_setting ( struct settings *settings, unsigned int tag,
+extern int fetch_ipv4_setting ( struct settings *settings,
+ struct setting *setting, struct in_addr *inp );
+extern int fetch_int_setting ( struct settings *settings,
+ struct setting *setting, long *value );
+extern int fetch_uint_setting ( struct settings *settings,
+ struct setting *setting,
unsigned long *value );
-extern long fetch_intz_setting ( struct settings *settings, unsigned int tag );
+extern long fetch_intz_setting ( struct settings *settings,
+ struct setting *setting );
extern unsigned long fetch_uintz_setting ( struct settings *settings,
- unsigned int tag );
+ struct setting *setting );
+extern int setting_cmp ( struct setting *a, struct setting *b );
+
extern struct settings * find_child_settings ( struct settings *parent,
const char *name );
extern struct settings * find_settings ( const char *name );
-extern int store_typed_setting ( struct settings *settings,
- unsigned int tag, struct setting_type *type,
- const char *value );
-extern int store_named_setting ( const char *name, const char *value );
-extern int fetch_named_setting ( const char *name, char *buf, size_t len );
-extern struct setting_type setting_type_ __setting_type;
+extern int storef_setting ( struct settings *settings,
+ struct setting *setting,
+ const char *value );
+extern int storef_named_setting ( const char *name, const char *value );
+extern int fetchf_named_setting ( const char *name, char *buf, size_t len );
+
extern struct setting_type setting_type_string __setting_type;
extern struct setting_type setting_type_ipv4 __setting_type;
extern struct setting_type setting_type_int8 __setting_type;
@@ -196,6 +199,18 @@ extern struct setting_type setting_type_uint16 __setting_type;
extern struct setting_type setting_type_uint32 __setting_type;
extern struct setting_type setting_type_hex __setting_type;
+extern struct setting ip_setting __setting;
+extern struct setting netmask_setting __setting;
+extern struct setting gateway_setting __setting;
+extern struct setting dns_setting __setting;
+extern struct setting hostname_setting __setting;
+extern struct setting filename_setting __setting;
+extern struct setting root_path_setting __setting;
+extern struct setting username_setting __setting;
+extern struct setting password_setting __setting;
+extern struct setting priority_setting __setting;
+extern struct setting bios_drive_setting __setting;
+
/**
* Initialise a settings block
*
@@ -233,29 +248,28 @@ static inline void simple_settings_init ( struct simple_settings *simple,
* Delete setting
*
* @v settings Settings block
- * @v tag Setting tag number
+ * @v setting Setting to delete
* @ret rc Return status code
*/
static inline int delete_setting ( struct settings *settings,
- unsigned int tag ) {
- return store_setting ( settings, tag, NULL, 0 );
+ struct setting *setting ) {
+ return store_setting ( settings, setting, NULL, 0 );
}
/**
* Fetch and format value of setting
*
* @v settings Settings block, or NULL to search all blocks
- * @v tag Setting tag number
+ * @v setting Setting to fetch
* @v type Settings type
* @v buf Buffer to contain formatted value
* @v len Length of buffer
* @ret len Length of formatted value, or negative error
*/
-static inline int fetch_typed_setting ( struct settings *settings,
- unsigned int tag,
- struct setting_type *type,
- char *buf, size_t len ) {
- return type->fetchf ( settings, tag, buf, len );
+static inline int fetchf_setting ( struct settings *settings,
+ struct setting *setting,
+ char *buf, size_t len ) {
+ return setting->type->fetchf ( settings, setting, buf, len );
}
/**
@@ -265,7 +279,7 @@ static inline int fetch_typed_setting ( struct settings *settings,
* @ret rc Return status code
*/
static inline int delete_named_setting ( const char *name ) {
- return store_named_setting ( name, NULL );
+ return storef_named_setting ( name, NULL );
}
#endif /* _GPXE_SETTINGS_H */
diff --git a/src/interface/pxe/pxe_preboot.c b/src/interface/pxe/pxe_preboot.c
index 2a10b1a5..302953eb 100644
--- a/src/interface/pxe/pxe_preboot.c
+++ b/src/interface/pxe/pxe_preboot.c
@@ -28,7 +28,7 @@
#include <stdlib.h>
#include <gpxe/uaccess.h>
#include <gpxe/dhcp.h>
-#include <gpxe/dhcppkt.h>
+#include <gpxe/fakedhcp.h>
#include <gpxe/device.h>
#include <gpxe/netdevice.h>
#include <gpxe/isapnp.h>
@@ -80,9 +80,9 @@ struct pxe_dhcp_packet_creator {
/** PXE DHCP packet creators */
static struct pxe_dhcp_packet_creator pxe_dhcp_packet_creators[] = {
- [CACHED_INFO_DHCPDISCOVER] = { create_dhcpdiscover },
- [CACHED_INFO_DHCPACK] = { create_dhcpack },
- [CACHED_INFO_BINL] = { create_proxydhcpack },
+ [CACHED_INFO_DHCPDISCOVER] = { create_fakedhcpdiscover },
+ [CACHED_INFO_DHCPACK] = { create_fakedhcpack },
+ [CACHED_INFO_BINL] = { create_fakeproxydhcpack },
};
/* The case in which the caller doesn't supply a buffer is really
diff --git a/src/net/dhcpopts.c b/src/net/dhcpopts.c
index 64b310d4..1898011a 100644
--- a/src/net/dhcpopts.c
+++ b/src/net/dhcpopts.c
@@ -118,6 +118,11 @@ static int find_dhcp_option_with_encap ( struct dhcp_options *options,
ssize_t remaining = options->len;
unsigned int option_len;
+ /* Sanity check */
+ if ( tag == DHCP_PAD )
+ return -ENOENT;
+
+ /* Search for option */
while ( remaining ) {
/* Calculate length of this option. Abort processing
* if the length is malformed (i.e. takes us beyond
@@ -128,6 +133,9 @@ static int find_dhcp_option_with_encap ( struct dhcp_options *options,
remaining -= option_len;
if ( remaining < 0 )
break;
+ /* Check for explicit end marker */
+ if ( option->tag == DHCP_END )
+ break;
/* Check for matching tag */
if ( option->tag == tag ) {
DBGC ( options, "DHCPOPT %p found %s (length %d)\n",
@@ -135,9 +143,6 @@ static int find_dhcp_option_with_encap ( struct dhcp_options *options,
option_len );
return offset;
}
- /* Check for explicit end marker */
- if ( option->tag == DHCP_END )
- break;
/* Check for start of matching encapsulation block */
if ( DHCP_IS_ENCAP_OPT ( tag ) &&
( option->tag == DHCP_ENCAPSULATOR ( tag ) ) ) {
@@ -151,6 +156,7 @@ static int find_dhcp_option_with_encap ( struct dhcp_options *options,
}
offset += option_len;
}
+
return -ENOENT;
}
@@ -255,6 +261,10 @@ static int set_dhcp_option ( struct dhcp_options *options, unsigned int tag,
size_t new_len = ( len ? ( len + DHCP_OPTION_HEADER_LEN ) : 0 );
int rc;
+ /* Sanity check */
+ if ( tag == DHCP_PAD )
+ return -ENOTTY;
+
/* Find old instance of this option, if any */
offset = find_dhcp_option_with_encap ( options, tag, &encap_offset );
if ( offset >= 0 ) {
diff --git a/src/net/dhcppkt.c b/src/net/dhcppkt.c
index 0a11520f..1cf99d8d 100644
--- a/src/net/dhcppkt.c
+++ b/src/net/dhcppkt.c
@@ -92,20 +92,18 @@ find_dhcp_packet_field ( unsigned int tag ) {
}
return NULL;
}
-
+
/**
* Store value of DHCP packet setting
*
- * @v settings Settings block
+ * @v dhcppkt DHCP packet
* @v tag Setting tag number
* @v data Setting data, or NULL to clear setting
* @v len Length of setting data
* @ret rc Return status code
*/
-static int dhcppkt_store ( struct settings *settings, unsigned int tag,
- const void *data, size_t len ) {
- struct dhcp_packet *dhcppkt =
- container_of ( settings, struct dhcp_packet, settings );
+int dhcppkt_store ( struct dhcp_packet *dhcppkt, unsigned int tag,
+ const void *data, size_t len ) {
struct dhcp_packet_field *field;
int rc;
@@ -131,16 +129,14 @@ static int dhcppkt_store ( struct settings *settings, unsigned int tag,
/**
* Fetch value of DHCP packet setting
*
- * @v settings Settings block
+ * @v dhcppkt DHCP packet
* @v tag Setting tag number
* @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_fetch ( struct settings *settings, unsigned int tag,
- void *data, size_t len ) {
- struct dhcp_packet *dhcppkt =
- container_of ( settings, struct dhcp_packet, settings );
+int dhcppkt_fetch ( struct dhcp_packet *dhcppkt, unsigned int tag,
+ void *data, size_t len ) {
struct dhcp_packet_field *field;
/* If this is a special field, return it */
@@ -156,31 +152,21 @@ static int dhcppkt_fetch ( struct settings *settings, unsigned int tag,
return dhcpopt_fetch ( &dhcppkt->options, tag, data, len );
}
-/** DHCP settings operations */
-static struct settings_operations dhcppkt_settings_operations = {
- .store = dhcppkt_store,
- .fetch = dhcppkt_fetch,
-};
-
/**
* Initialise prepopulated DHCP packet
*
* @v dhcppkt Uninitialised DHCP packet
- * @v refcnt Reference counter of containing object, or NULL
* @v data Memory for DHCP packet data
* @v max_len Length of memory for DHCP packet data
*
* 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, struct refcnt *refcnt,
- void *data, size_t len ) {
+void dhcppkt_init ( struct dhcp_packet *dhcppkt, void *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,
- refcnt, "dhcp" );
}
diff --git a/src/net/fakedhcp.c b/src/net/fakedhcp.c
new file mode 100644
index 00000000..c3054db1
--- /dev/null
+++ b/src/net/fakedhcp.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <gpxe/settings.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/dhcppkt.h>
+#include <gpxe/fakedhcp.h>
+
+/** @file
+ *
+ * Fake DHCP packets
+ *
+ */
+
+/**
+ * Copy settings to DHCP packet
+ *
+ * @v dest Destination DHCP packet
+ * @v source Source settings block
+ * @v encapsulator Encapsulating setting tag number, or zero
+ * @ret rc Return status code
+ */
+static int copy_encap_settings ( struct dhcp_packet *dest,
+ struct settings *source,
+ unsigned int encapsulator ) {
+ struct setting setting = { .name = "" };
+ unsigned int subtag;
+ unsigned int tag;
+ int len;
+ int check_len;
+ int rc;
+
+ for ( subtag = DHCP_MIN_OPTION; subtag <= DHCP_MAX_OPTION; subtag++ ) {
+ tag = DHCP_ENCAP_OPT ( encapsulator, subtag );
+ switch ( tag ) {
+ case DHCP_EB_ENCAP:
+ case DHCP_VENDOR_ENCAP:
+ /* Process encapsulated settings */
+ if ( ( rc = copy_encap_settings ( dest, source,
+ tag ) ) != 0 )
+ return rc;
+ break;
+ default:
+ /* Copy setting, if present */
+ setting.tag = tag;
+ len = fetch_setting_len ( source, &setting );
+ if ( len < 0 )
+ break;
+ {
+ char buf[len];
+
+ check_len = fetch_setting ( source, &setting,
+ buf, sizeof (buf));
+ assert ( check_len == len );
+ if ( ( rc = dhcppkt_store ( dest, tag, buf,
+ sizeof(buf) )) !=0)
+ return rc;
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Copy settings to DHCP packet
+ *
+ * @v dest Destination DHCP packet
+ * @v source Source settings block
+ * @ret rc Return status code
+ */
+static int copy_settings ( struct dhcp_packet *dest,
+ struct settings *source ) {
+ return copy_encap_settings ( dest, source, 0 );
+}
+
+/**
+ * Create fake DHCPDISCOVER packet
+ *
+ * @v netdev Network device
+ * @v data Buffer for DHCP packet
+ * @v max_len Size of DHCP packet buffer
+ * @ret rc Return status code
+ *
+ * Used by external code.
+ */
+int create_fakedhcpdiscover ( struct net_device *netdev,
+ void *data, size_t max_len ) {
+ struct dhcp_packet dhcppkt;
+ int rc;
+
+ if ( ( rc = create_dhcp_request ( &dhcppkt, netdev, NULL, data,
+ max_len ) ) != 0 ) {
+ DBG ( "Could not create DHCPDISCOVER: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Create fake DHCPACK packet
+ *
+ * @v netdev Network device
+ * @v data Buffer for DHCP packet
+ * @v max_len Size of DHCP packet buffer
+ * @ret rc Return status code
+ *
+ * Used by external code.
+ */
+int create_fakedhcpack ( struct net_device *netdev,
+ void *data, size_t max_len ) {
+ struct dhcp_packet dhcppkt;
+ int rc;
+
+ /* Create base DHCPACK packet */
+ if ( ( rc = create_dhcp_packet ( &dhcppkt, netdev, DHCPACK, NULL,
+ data, max_len ) ) != 0 ) {
+ DBG ( "Could not create DHCPACK: %s\n", strerror ( rc ) );
+ return rc;
+ }
+
+ /* Merge in globally-scoped settings, then netdev-specific
+ * settings. Do it in this order so that netdev-specific
+ * settings take precedence regardless of stated priorities.
+ */
+ if ( ( rc = copy_settings ( &dhcppkt, NULL ) ) != 0 ) {
+ DBG ( "Could not set DHCPACK global settings: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+ if ( ( rc = copy_settings ( &dhcppkt,
+ netdev_settings ( netdev ) ) ) != 0 ) {
+ DBG ( "Could not set DHCPACK netdev settings: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Create ProxyDHCPACK packet
+ *
+ * @v netdev Network device
+ * @v data Buffer for DHCP packet
+ * @v max_len Size of DHCP packet buffer
+ * @ret rc Return status code
+ *
+ * Used by external code.
+ */
+int create_fakeproxydhcpack ( struct net_device *netdev,
+ void *data, size_t max_len ) {
+ struct dhcp_packet dhcppkt;
+ struct settings *settings;
+ int rc;
+
+ /* Identify ProxyDHCP settings */
+ settings = find_settings ( PROXYDHCP_SETTINGS_NAME );
+
+ /* No ProxyDHCP settings => return empty block */
+ if ( ! settings ) {
+ memset ( data, 0, max_len );
+ return 0;
+ }
+
+ /* Create base DHCPACK packet */
+ if ( ( rc = create_dhcp_packet ( &dhcppkt, netdev, DHCPACK, NULL,
+ data, max_len ) ) != 0 ) {
+ DBG ( "Could not create ProxyDHCPACK: %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",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
diff --git a/src/net/ipv4.c b/src/net/ipv4.c
index 67bfc2d6..591293b7 100644
--- a/src/net/ipv4.c
+++ b/src/net/ipv4.c
@@ -96,62 +96,6 @@ static void del_ipv4_miniroute ( struct ipv4_miniroute *miniroute ) {
}
/**
- * Create IPv4 routing table
- *
- * @ret rc Return status code
- */
-static int ipv4_create_routes ( void ) {
- struct ipv4_miniroute *miniroute;
- struct ipv4_miniroute *tmp;
- struct net_device *netdev;
- struct settings *settings;
- struct in_addr address = { 0 };
- struct in_addr netmask = { 0 };
- struct in_addr gateway = { INADDR_NONE };
-
- /* Delete all existing routes */
- list_for_each_entry_safe ( miniroute, tmp, &ipv4_miniroutes, list )
- del_ipv4_miniroute ( miniroute );
-
- /* Create a route for each configured network device */
- for_each_netdev ( netdev ) {
- settings = netdev_settings ( netdev );
- /* Get IPv4 address */
- address.s_addr = 0;
- fetch_ipv4_setting ( settings, DHCP_EB_YIADDR, &address );
- if ( ! address.s_addr )
- continue;
- /* Calculate default netmask */
- if ( IN_CLASSA ( ntohl ( address.s_addr ) ) ) {
- netmask.s_addr = htonl ( IN_CLASSA_NET );
- } else if ( IN_CLASSB ( ntohl ( address.s_addr ) ) ) {
- netmask.s_addr = htonl ( IN_CLASSB_NET );
- } else if ( IN_CLASSC ( ntohl ( address.s_addr ) ) ) {
- netmask.s_addr = htonl ( IN_CLASSC_NET );
- } else {
- netmask.s_addr = 0;
- }
- /* Override with subnet mask, if present */
- fetch_ipv4_setting ( settings, DHCP_SUBNET_MASK, &netmask );
- /* Get default gateway, if present */
- gateway.s_addr = INADDR_NONE;
- fetch_ipv4_setting ( settings, DHCP_ROUTERS, &gateway );
- /* Configure route */
- miniroute = add_ipv4_miniroute ( netdev, address,
- netmask, gateway );
- if ( ! miniroute )
- return -ENOMEM;
- }
-
- return 0;
-}
-
-/** IPv4 settings applicator */
-struct settings_applicator ipv4_settings_applicator __settings_applicator = {
- .apply = ipv4_create_routes,
-};
-
-/**
* Perform IPv4 routing
*
* @v dest Final destination address
@@ -600,3 +544,90 @@ struct arp_net_protocol ipv4_arp_protocol __arp_net_protocol = {
.net_protocol = &ipv4_protocol,
.check = ipv4_arp_check,
};
+
+/******************************************************************************
+ *
+ * Settings
+ *
+ ******************************************************************************
+ */
+
+/** IPv4 address setting */
+struct setting ip_setting __setting = {
+ .name = "ip",
+ .description = "IPv4 address",
+ .tag = DHCP_EB_YIADDR,
+ .type = &setting_type_ipv4,
+};
+
+/** IPv4 subnet mask setting */
+struct setting netmask_setting __setting = {
+ .name = "netmask",
+ .description = "IPv4 subnet mask",
+ .tag = DHCP_SUBNET_MASK,
+ .type = &setting_type_ipv4,
+};
+
+/** Default gateway setting */
+struct setting gateway_setting __setting = {
+ .name = "gateway",
+ .description = "Default gateway",
+ .tag = DHCP_ROUTERS,
+ .type = &setting_type_ipv4,
+};
+
+/**
+ * Create IPv4 routing table based on configured settings
+ *
+ * @ret rc Return status code
+ */
+static int ipv4_create_routes ( void ) {
+ struct ipv4_miniroute *miniroute;
+ struct ipv4_miniroute *tmp;
+ struct net_device *netdev;
+ struct settings *settings;
+ struct in_addr address = { 0 };
+ struct in_addr netmask = { 0 };
+ struct in_addr gateway = { INADDR_NONE };
+
+ /* Delete all existing routes */
+ list_for_each_entry_safe ( miniroute, tmp, &ipv4_miniroutes, list )
+ del_ipv4_miniroute ( miniroute );
+
+ /* Create a route for each configured network device */
+ for_each_netdev ( netdev ) {
+ settings = netdev_settings ( netdev );
+ /* Get IPv4 address */
+ address.s_addr = 0;
+ fetch_ipv4_setting ( settings, &ip_setting, &address );
+ if ( ! address.s_addr )
+ continue;
+ /* Calculate default netmask */
+ if ( IN_CLASSA ( ntohl ( address.s_addr ) ) ) {
+ netmask.s_addr = htonl ( IN_CLASSA_NET );
+ } else if ( IN_CLASSB ( ntohl ( address.s_addr ) ) ) {
+ netmask.s_addr = htonl ( IN_CLASSB_NET );
+ } else if ( IN_CLASSC ( ntohl ( address.s_addr ) ) ) {
+ netmask.s_addr = htonl ( IN_CLASSC_NET );
+ } else {
+ netmask.s_addr = 0;
+ }
+ /* Override with subnet mask, if present */
+ fetch_ipv4_setting ( settings, &netmask_setting, &netmask );
+ /* Get default gateway, if present */
+ gateway.s_addr = INADDR_NONE;
+ fetch_ipv4_setting ( settings, &gateway_setting, &gateway );
+ /* Configure route */
+ miniroute = add_ipv4_miniroute ( netdev, address,
+ netmask, gateway );
+ if ( ! miniroute )
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+/** IPv4 settings applicator */
+struct settings_applicator ipv4_settings_applicator __settings_applicator = {
+ .apply = ipv4_create_routes,
+};
diff --git a/src/net/netdev_settings.c b/src/net/netdev_settings.c
index c8e630a9..44aca7d8 100644
--- a/src/net/netdev_settings.c
+++ b/src/net/netdev_settings.c
@@ -28,28 +28,34 @@
*
*/
+/** Network device named settings */
+struct setting mac_setting __setting = {
+ .name = "mac",
+ .description = "MAC address",
+ .type = &setting_type_hex,
+};
+
/**
* Store value of network device setting
*
* @v settings Settings block
- * @v tag Setting tag number
+ * @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 netdev_store ( struct settings *settings, unsigned int tag,
+static int netdev_store ( struct settings *settings, struct setting *setting,
const void *data, size_t len ) {
struct net_device *netdev = container_of ( settings, struct net_device,
settings.settings );
- switch ( tag ) {
- case DHCP_EB_MAC:
+ if ( setting_cmp ( setting, &mac_setting ) == 0 ) {
if ( len != netdev->ll_protocol->ll_addr_len )
return -EINVAL;
memcpy ( netdev->ll_addr, data, len );
return 0;
- default :
- return simple_settings_store ( settings, tag, data, len );
+ } else {
+ return simple_settings_store ( settings, setting, data, len );
}
}
@@ -57,24 +63,23 @@ static int netdev_store ( struct settings *settings, unsigned int tag,
* Fetch value of network device setting
*
* @v settings Settings block
- * @v tag Setting tag number
+ * @v setting Setting to fetch
* @v data Setting data, or NULL to clear setting
* @v len Length of setting data
* @ret rc Return status code
*/
-static int netdev_fetch ( struct settings *settings, unsigned int tag,
+static int netdev_fetch ( struct settings *settings, struct setting *setting,
void *data, size_t len ) {
struct net_device *netdev = container_of ( settings, struct net_device,
settings.settings );
- switch ( tag ) {
- case DHCP_EB_MAC:
+ if ( setting_cmp ( setting, &mac_setting ) == 0 ) {
if ( len > netdev->ll_protocol->ll_addr_len )
len = netdev->ll_protocol->ll_addr_len;
memcpy ( data, netdev->ll_addr, len );
return netdev->ll_protocol->ll_addr_len;
- default :
- return simple_settings_fetch ( settings, tag, data, len );
+ } else {
+ return simple_settings_fetch ( settings, setting, data, len );
}
}
@@ -83,13 +88,3 @@ struct settings_operations netdev_settings_operations = {
.store = netdev_store,
.fetch = netdev_fetch,
};
-
-/** Network device named settings */
-struct named_setting netdev_named_settings[] __named_setting = {
- {
- .name = "mac",
- .description = "MAC address",
- .tag = DHCP_EB_MAC,
- .type = &setting_type_hex,
- },
-};
diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c
index f071b04a..c01ca44b 100644
--- a/src/net/tcp/iscsi.c
+++ b/src/net/tcp/iscsi.c
@@ -1591,14 +1591,22 @@ int iscsi_attach ( struct scsi_device *scsi, const char *root_path ) {
/****************************************************************************
*
- * Settings applicators
+ * Settings
*
*/
+/** iSCSI initiator IQN setting */
+struct setting initiator_iqn_setting __setting = {
+ .name = "initiator-iqn",
+ .description = "iSCSI initiator name",
+ .tag = DHCP_ISCSI_INITIATOR_IQN,
+ .type = &setting_type_string,
+};
+
/** An iSCSI string setting */
struct iscsi_string_setting {
- /** Setting tag number */
- unsigned int tag;
+ /** Setting */
+ struct setting *setting;
/** String to update */
char **string;
/** String prefix */
@@ -1608,22 +1616,22 @@ struct iscsi_string_setting {
/** iSCSI string settings */
static struct iscsi_string_setting iscsi_string_settings[] = {
{
- .tag = DHCP_ISCSI_INITIATOR_IQN,
+ .setting = &initiator_iqn_setting,
.string = &iscsi_explicit_initiator_iqn,
.prefix = "",
},
{
- .tag = DHCP_EB_USERNAME,
+ .setting = &username_setting,
.string = &iscsi_username,
.prefix = "",
},
{
- .tag = DHCP_EB_PASSWORD,
+ .setting = &password_setting,
.string = &iscsi_password,
.prefix = "",
},
{
- .tag = DHCP_HOST_NAME,
+ .setting = &hostname_setting,
.string = &iscsi_default_initiator_iqn,
.prefix = "iqn.2000-09.org.etherboot:",
},
@@ -1648,7 +1656,7 @@ static int apply_iscsi_string_setting ( struct iscsi_string_setting *setting ){
/* Allocate new string */
prefix_len = strlen ( setting->prefix );
- setting_len = fetch_setting_len ( NULL, setting->tag );
+ setting_len = fetch_setting_len ( NULL, setting->setting );
if ( setting_len < 0 ) {
/* Missing settings are not errors; leave strings as NULL */
return 0;
@@ -1660,7 +1668,7 @@ static int apply_iscsi_string_setting ( struct iscsi_string_setting *setting ){
/* Fill new string */
strcpy ( p, setting->prefix );
- check_len = fetch_string_setting ( NULL, setting->tag,
+ check_len = fetch_string_setting ( NULL, setting->setting,
( p + prefix_len ),
( len - prefix_len ) );
assert ( check_len == setting_len );
@@ -1682,8 +1690,8 @@ static int apply_iscsi_settings ( void ) {
sizeof ( iscsi_string_settings[0] ) ) ; i++ ) {
setting = &iscsi_string_settings[i];
if ( ( rc = apply_iscsi_string_setting ( setting ) ) != 0 ) {
- DBG ( "iSCSI could not apply setting %d\n",
- setting->tag );
+ DBG ( "iSCSI could not apply setting %s\n",
+ setting->setting->name );
return rc;
}
}
diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c
index 8789f925..98b8af0b 100644
--- a/src/net/udp/dhcp.c
+++ b/src/net/udp/dhcp.c
@@ -130,9 +130,6 @@ static uint32_t dhcp_xid ( struct net_device *netdev ) {
return xid;
}
-/** Settings block name used for ProxyDHCP responses */
-#define PROXYDHCP_SETTINGS_NAME "proxydhcp"
-
/**
* Create a DHCP packet
*
@@ -180,12 +177,12 @@ int create_dhcp_packet ( struct dhcp_packet *dhcppkt,
memcpy ( dhcphdr->chaddr, netdev->ll_addr, hlen );
memcpy ( dhcphdr->options, options->data, options_len );
- /* Initialise DHCP packet structure and settings interface */
+ /* Initialise DHCP packet structure */
memset ( dhcppkt, 0, sizeof ( *dhcppkt ) );
- dhcppkt_init ( dhcppkt, NULL, data, max_len );
+ dhcppkt_init ( dhcppkt, data, max_len );
/* Set DHCP_MESSAGE_TYPE option */
- if ( ( rc = store_setting ( &dhcppkt->settings, DHCP_MESSAGE_TYPE,
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_MESSAGE_TYPE,
&msgtype, sizeof ( msgtype ) ) ) != 0 )
return rc;
@@ -230,10 +227,10 @@ struct dhcp_client_uuid {
* @v max_len Size of DHCP packet buffer
* @ret rc Return status code
*/
-static int create_dhcp_request ( struct dhcp_packet *dhcppkt,
- struct net_device *netdev,
- struct dhcp_packet *dhcpoffer,
- void *data, size_t max_len ) {
+int create_dhcp_request ( struct dhcp_packet *dhcppkt,
+ struct net_device *netdev,
+ struct dhcp_packet *dhcpoffer,
+ void *data, size_t max_len ) {
struct device_description *desc = &netdev->dev->desc;
struct dhcp_netdev_desc dhcp_desc;
struct dhcp_client_id client_id;
@@ -258,27 +255,26 @@ static int create_dhcp_request ( struct dhcp_packet *dhcppkt,
struct in_addr server_id;
struct in_addr requested_ip;
- if ( ( rc = fetch_ipv4_setting ( &dhcpoffer->settings,
- DHCP_SERVER_IDENTIFIER,
- &server_id ) ) < 0 ) {
+ if ( dhcppkt_fetch ( dhcpoffer, DHCP_SERVER_IDENTIFIER,
+ &server_id, sizeof ( server_id ) )
+ != sizeof ( server_id ) ) {
DBG ( "DHCP offer missing server identifier\n" );
return -EINVAL;
}
- if ( ( rc = fetch_ipv4_setting ( &dhcpoffer->settings,
- DHCP_EB_YIADDR,
- &requested_ip ) ) < 0 ) {
+ if ( dhcppkt_fetch ( dhcpoffer, DHCP_EB_YIADDR,
+ &requested_ip, sizeof ( requested_ip ) )
+ != sizeof ( requested_ip ) ) {
DBG ( "DHCP offer missing IP address\n" );
return -EINVAL;
}
- if ( ( rc = store_setting ( &dhcppkt->settings,
- DHCP_SERVER_IDENTIFIER, &server_id,
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_SERVER_IDENTIFIER,
+ &server_id,
sizeof ( server_id ) ) ) != 0 ) {
DBG ( "DHCP could not set server identifier: %s\n ",
strerror ( rc ) );
return rc;
}
- if ( ( rc = store_setting ( &dhcppkt->settings,
- DHCP_REQUESTED_ADDRESS,
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_REQUESTED_ADDRESS,
&requested_ip,
sizeof ( requested_ip ) ) ) != 0 ){
DBG ( "DHCP could not set requested address: %s\n",
@@ -289,8 +285,8 @@ static int create_dhcp_request ( struct dhcp_packet *dhcppkt,
/* Add options to identify the feature list */
dhcp_features_len = ( dhcp_features_end - dhcp_features );
- if ( ( rc = store_setting ( &dhcppkt->settings, DHCP_EB_ENCAP,
- dhcp_features, dhcp_features_len ) ) !=0 ){
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_EB_ENCAP, dhcp_features,
+ dhcp_features_len ) ) != 0 ) {
DBG ( "DHCP could not set features list option: %s\n",
strerror ( rc ) );
return rc;
@@ -300,8 +296,8 @@ static int create_dhcp_request ( struct dhcp_packet *dhcppkt,
dhcp_desc.type = desc->bus_type;
dhcp_desc.vendor = htons ( desc->vendor );
dhcp_desc.device = htons ( desc->device );
- if ( ( rc = store_setting ( &dhcppkt->settings, DHCP_EB_BUS_ID,
- &dhcp_desc, sizeof ( dhcp_desc ) ) ) !=0 ){
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_EB_BUS_ID, &dhcp_desc,
+ sizeof ( dhcp_desc ) ) ) != 0 ) {
DBG ( "DHCP could not set bus ID option: %s\n",
strerror ( rc ) );
return rc;
@@ -314,8 +310,8 @@ static int create_dhcp_request ( struct dhcp_packet *dhcppkt,
ll_addr_len = netdev->ll_protocol->ll_addr_len;
assert ( ll_addr_len <= sizeof ( client_id.ll_addr ) );
memcpy ( client_id.ll_addr, netdev->ll_addr, ll_addr_len );
- if ( ( rc = store_setting ( &dhcppkt->settings, DHCP_CLIENT_ID,
- &client_id, ( ll_addr_len + 1 ) ) ) != 0 ){
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_CLIENT_ID, &client_id,
+ ( ll_addr_len + 1 ) ) ) != 0 ) {
DBG ( "DHCP could not set client ID: %s\n",
strerror ( rc ) );
return rc;
@@ -324,8 +320,8 @@ static int create_dhcp_request ( struct dhcp_packet *dhcppkt,
/* Add client UUID, if we have one. Required for PXE. */
client_uuid.type = DHCP_CLIENT_UUID_TYPE;
if ( ( rc = get_uuid ( &client_uuid.uuid ) ) == 0 ) {
- if ( ( rc = store_setting ( &dhcppkt->settings,
- DHCP_CLIENT_UUID, &client_uuid,
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_CLIENT_UUID,
+ &client_uuid,
sizeof ( client_uuid ) ) ) != 0 ) {
DBG ( "DHCP could not set client UUID: %s\n",
strerror ( rc ) );
@@ -336,169 +332,109 @@ static int create_dhcp_request ( struct dhcp_packet *dhcppkt,
return 0;
}
-/**
- * Create DHCPDISCOVER packet
+/****************************************************************************
*
- * @v netdev Network device
- * @v data Buffer for DHCP packet
- * @v max_len Size of DHCP packet buffer
- * @ret rc Return status code
+ * DHCP settings
*
- * Used by external code.
*/
-int create_dhcpdiscover ( struct net_device *netdev,
- void *data, size_t max_len ) {
- struct dhcp_packet dhcppkt;
- int rc;
- if ( ( rc = create_dhcp_request ( &dhcppkt, netdev, NULL, data,
- max_len ) ) != 0 ) {
- DBG ( "Could not create DHCPDISCOVER: %s\n",
- strerror ( rc ) );
- return rc;
- }
-
- return 0;
-}
+/** A DHCP settings block */
+struct dhcp_settings {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** Containing I/O buffer */
+ struct io_buffer *iobuf;
+ /** DHCP packet */
+ struct dhcp_packet dhcppkt;
+ /** Setting interface */
+ struct settings settings;
+};
/**
- * Create DHCPACK packet
+ * Free DHCP settings block
*
- * @v netdev Network device
- * @v data Buffer for DHCP packet
- * @v max_len Size of DHCP packet buffer
- * @ret rc Return status code
- *
- * Used by external code.
+ * @v refcnt Reference counter
*/
-int create_dhcpack ( struct net_device *netdev,
- void *data, size_t max_len ) {
- struct dhcp_packet dhcppkt;
- int rc;
-
- /* Create base DHCPACK packet */
- if ( ( rc = create_dhcp_packet ( &dhcppkt, netdev, DHCPACK, NULL,
- data, max_len ) ) != 0 ) {
- DBG ( "Could not create DHCPACK: %s\n", strerror ( rc ) );
- return rc;
- }
-
- /* Merge in globally-scoped settings, then netdev-specific
- * settings. Do it in this order so that netdev-specific
- * settings take precedence regardless of stated priorities.
- */
- if ( ( rc = copy_settings ( &dhcppkt.settings, NULL ) ) != 0 ) {
- DBG ( "Could not set DHCPACK global settings: %s\n",
- strerror ( rc ) );
- return rc;
- }
- if ( ( rc = copy_settings ( &dhcppkt.settings,
- netdev_settings ( netdev ) ) ) != 0 ) {
- DBG ( "Could not set DHCPACK netdev settings: %s\n",
- strerror ( rc ) );
- return rc;
- }
+static void dhcpset_free ( struct refcnt *refcnt ) {
+ struct dhcp_settings *dhcpset =
+ container_of ( refcnt, struct dhcp_settings, refcnt );
- return 0;
+ free_iob ( dhcpset->iobuf );
+ free ( dhcpset );
}
/**
- * Create ProxyDHCPACK packet
- *
- * @v netdev Network device
- * @v data Buffer for DHCP packet
- * @v max_len Size of DHCP packet buffer
- * @ret rc Return status code
+ * Decrement reference count on DHCP settings block
*
- * Used by external code.
+ * @v dhcpset DHCP settings block
*/
-int create_proxydhcpack ( struct net_device *netdev,
- void *data, size_t max_len ) {
- struct dhcp_packet dhcppkt;
- struct settings *settings;
- int rc;
-
- /* Identify ProxyDHCP settings */
- settings = find_settings ( PROXYDHCP_SETTINGS_NAME );
-
- /* No ProxyDHCP settings => return empty block */
- if ( ! settings ) {
- memset ( data, 0, max_len );
- return 0;
- }
-
- /* Create base DHCPACK packet */
- if ( ( rc = create_dhcp_packet ( &dhcppkt, netdev, DHCPACK, NULL,
- data, max_len ) ) != 0 ) {
- DBG ( "Could not create ProxyDHCPACK: %s\n",
- strerror ( rc ) );
- return rc;
- }
-
- /* Merge in ProxyDHCP options */
- if ( ( rc = copy_settings ( &dhcppkt.settings, settings ) ) != 0 ) {
- DBG ( "Could not set ProxyDHCPACK settings: %s\n",
- strerror ( rc ) );
- return rc;
- }
-
- return 0;
+static inline void dhcpset_put ( struct dhcp_settings *dhcpset ) {
+ ref_put ( &dhcpset->refcnt );
}
-/****************************************************************************
- *
- * DHCP packets contained in I/O buffers
+/**
+ * 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 dhcpset_store ( struct settings *settings, struct setting *setting,
+ const void *data, size_t len ) {
+ struct dhcp_settings *dhcpset =
+ container_of ( settings, struct dhcp_settings, settings );
-/** A DHCP packet contained in an I/O buffer */
-struct dhcp_iobuf_packet {
- /** DHCP packet */
- struct dhcp_packet dhcppkt;
- /** Reference counter */
- struct refcnt refcnt;
- /** Containing I/O buffer */
- struct io_buffer *iobuf;
-};
+ return dhcppkt_store ( &dhcpset->dhcppkt, setting->tag, data, len );
+}
/**
- * Free DHCP packet contained in an I/O buffer
+ * Fetch value of setting
*
- * @v refcnt Reference counter
+ * @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 void dhcpiob_free ( struct refcnt *refcnt ) {
- struct dhcp_iobuf_packet *dhcpiob =
- container_of ( refcnt, struct dhcp_iobuf_packet, refcnt );
+static int dhcpset_fetch ( struct settings *settings, struct setting *setting,
+ void *data, size_t len ) {
+ struct dhcp_settings *dhcpset =
+ container_of ( settings, struct dhcp_settings, settings );
- free_iob ( dhcpiob->iobuf );
- free ( dhcpiob );
+ return dhcppkt_fetch ( &dhcpset->dhcppkt, setting->tag, data, len );
}
+/** DHCP settings operations */
+static struct settings_operations dhcpset_settings_operations = {
+ .store = dhcpset_store,
+ .fetch = dhcpset_fetch,
+};
+
/**
- * Create DHCP packet from I/O buffer
+ * Create DHCP setting block from I/O buffer
*
* @v iobuf I/O buffer
- * @ret dhcpiob DHCP packet contained in I/O buffer
+ * @ret dhcpset DHCP settings block
*
* This function takes ownership of the I/O buffer. Future accesses
- * must be via the @c dhcpiob data structure.
+ * must be via the @c dhcpset data structure.
*/
-static struct dhcp_iobuf_packet * dhcpiob_create ( struct io_buffer *iobuf ) {
- struct dhcp_iobuf_packet *dhcpiob;
-
- dhcpiob = zalloc ( sizeof ( *dhcpiob ) );
- if ( dhcpiob ) {
- dhcpiob->refcnt.free = dhcpiob_free;
- dhcpiob->iobuf = iobuf;
- dhcppkt_init ( &dhcpiob->dhcppkt, &dhcpiob->refcnt,
+static struct dhcp_settings * dhcpset_create_iob ( struct io_buffer *iobuf ) {
+ struct dhcp_settings *dhcpset;
+
+ dhcpset = zalloc ( sizeof ( *dhcpset ) );
+ if ( dhcpset ) {
+ dhcpset->refcnt.free = dhcpset_free;
+ dhcpset->iobuf = iobuf;
+ dhcppkt_init ( &dhcpset->dhcppkt,
iobuf->data, iob_len ( iobuf ) );
+ settings_init ( &dhcpset->settings,
+ &dhcpset_settings_operations, &dhcpset->refcnt,
+ DHCP_SETTINGS_NAME );
}
- return dhcpiob;
-}
-
-static void dhcpiob_put ( struct dhcp_iobuf_packet *dhcpiob ) {
- if ( dhcpiob )
- ref_put ( &dhcpiob->refcnt );
+ return dhcpset;
}
/****************************************************************************
@@ -526,9 +462,9 @@ struct dhcp_session {
*/
int state;
/** Response obtained from DHCP server */
- struct dhcp_iobuf_packet *response;
+ struct dhcp_settings *response;
/** Response obtained from ProxyDHCP server */
- struct dhcp_iobuf_packet *proxy_response;
+ struct dhcp_settings *proxy_response;
/** Retransmission timer */
struct retry_timer timer;
/** Session start time (in ticks) */
@@ -545,8 +481,8 @@ static void dhcp_free ( struct refcnt *refcnt ) {
container_of ( refcnt, struct dhcp_session, refcnt );
netdev_put ( dhcp->netdev );
- dhcpiob_put ( dhcp->response );
- dhcpiob_put ( dhcp->proxy_response );
+ dhcpset_put ( dhcp->response );
+ dhcpset_put ( dhcp->proxy_response );
free ( dhcp );
}
@@ -584,7 +520,7 @@ static int dhcp_register_settings ( struct dhcp_session *dhcp ) {
/* Register ProxyDHCP settings, if present */
if ( dhcp->proxy_response ) {
- settings = &dhcp->proxy_response->dhcppkt.settings;
+ settings = &dhcp->proxy_response->settings;
settings->name = PROXYDHCP_SETTINGS_NAME;
old_settings = find_settings ( settings->name );
if ( old_settings )
@@ -595,7 +531,7 @@ static int dhcp_register_settings ( struct dhcp_session *dhcp ) {
/* Register DHCP settings */
parent = netdev_settings ( dhcp->netdev );
- settings = &dhcp->response->dhcppkt.settings;
+ settings = &dhcp->response->settings;
old_settings = find_child_settings ( parent, settings->name );
if ( old_settings )
unregister_settings ( old_settings );
@@ -701,24 +637,24 @@ static int dhcp_deliver_iob ( struct xfer_interface *xfer,
struct xfer_metadata *meta __unused ) {
struct dhcp_session *dhcp =
container_of ( xfer, struct dhcp_session, xfer );
- struct dhcp_iobuf_packet *response;
- struct dhcp_iobuf_packet **store_response;
+ struct dhcp_settings *response;
+ struct dhcp_settings **store_response;
struct dhcphdr *dhcphdr;
- struct settings *settings;
- unsigned int msgtype;
+ uint8_t msgtype = 0;
+ uint8_t priority = 0;
+ uint8_t existing_priority = 0;
unsigned long elapsed;
int is_proxy;
- int ignore_proxy;
+ uint8_t ignore_proxy = 0;
int rc;
/* Convert packet into a DHCP-packet-in-iobuf */
- response = dhcpiob_create ( iobuf );
+ response = dhcpset_create_iob ( iobuf );
if ( ! response ) {
DBGC ( dhcp, "DHCP %p could not store DHCP packet\n", dhcp );
return -ENOMEM;
}
dhcphdr = response->dhcppkt.dhcphdr;
- settings = &response->dhcppkt.settings;
/* Check for matching transaction ID */
if ( dhcphdr->xid != dhcp_xid ( dhcp->netdev ) ) {
@@ -730,7 +666,8 @@ static int dhcp_deliver_iob ( struct xfer_interface *xfer,
/* Determine and verify message type */
is_proxy = ( dhcphdr->yiaddr.s_addr == 0 );
- msgtype = fetch_uintz_setting ( settings, DHCP_MESSAGE_TYPE );
+ dhcppkt_fetch ( &response->dhcppkt, DHCP_MESSAGE_TYPE, &msgtype,
+ sizeof ( msgtype ) );
DBGC ( dhcp, "DHCP %p received %s%s\n", dhcp,
( is_proxy ? "Proxy" : "" ), dhcp_msgtype_name ( msgtype ) );
if ( ( ( dhcp->state != DHCPDISCOVER ) || ( msgtype != DHCPOFFER ) ) &&
@@ -746,14 +683,18 @@ static int dhcp_deliver_iob ( struct xfer_interface *xfer,
* currently-stored options.
*/
store_response = ( is_proxy ? &dhcp->proxy_response : &dhcp->response);
- if ( ( ! *store_response ) ||
- ( fetch_uintz_setting ( settings, DHCP_EB_PRIORITY ) >=
- fetch_uintz_setting ( &(*store_response)->dhcppkt.settings,
- DHCP_EB_PRIORITY ) ) ) {
- dhcpiob_put ( *store_response );
+ if ( *store_response ) {
+ dhcppkt_fetch ( &(*store_response)->dhcppkt, DHCP_EB_PRIORITY,
+ &existing_priority,
+ sizeof ( existing_priority ) );
+ }
+ dhcppkt_fetch ( &response->dhcppkt, DHCP_EB_PRIORITY, &priority,
+ sizeof ( priority ) );
+ if ( priority >= existing_priority ) {
+ dhcpset_put ( *store_response );
*store_response = response;
} else {
- dhcpiob_put ( response );
+ dhcpset_put ( response );
}
/* If we don't yet have a standard DHCP response (i.e. one
@@ -763,8 +704,8 @@ static int dhcp_deliver_iob ( struct xfer_interface *xfer,
goto out;
/* Handle DHCP response */
- ignore_proxy = fetch_uintz_setting ( &dhcp->response->dhcppkt.settings,
- DHCP_EB_NO_PROXYDHCP );
+ dhcppkt_fetch ( &dhcp->response->dhcppkt, DHCP_EB_NO_PROXYDHCP,
+ &ignore_proxy, sizeof ( ignore_proxy ) );
switch ( dhcp->state ) {
case DHCPDISCOVER:
/* If we have allowed sufficient time for ProxyDHCP
@@ -780,7 +721,7 @@ static int dhcp_deliver_iob ( struct xfer_interface *xfer,
case DHCPREQUEST:
/* DHCP finished; register options and exit */
if ( ignore_proxy && dhcp->proxy_response ) {
- dhcpiob_put ( dhcp->proxy_response );
+ dhcpset_put ( dhcp->proxy_response );
dhcp->proxy_response = NULL;
}
if ( ( rc = dhcp_register_settings ( dhcp ) ) != 0 ) {
@@ -797,7 +738,7 @@ static int dhcp_deliver_iob ( struct xfer_interface *xfer,
return 0;
out_discard:
- dhcpiob_put ( response );
+ dhcpset_put ( response );
return 0;
}
diff --git a/src/net/udp/dns.c b/src/net/udp/dns.c
index 5e632d18..1bcdbc7e 100644
--- a/src/net/udp/dns.c
+++ b/src/net/udp/dns.c
@@ -506,6 +506,21 @@ struct resolver dns_resolver __resolver ( RESOLV_NORMAL ) = {
.resolv = dns_resolv,
};
+/******************************************************************************
+ *
+ * Settings
+ *
+ ******************************************************************************
+ */
+
+/** DNS server setting */
+struct setting dns_setting __setting = {
+ .name = "dns",
+ .description = "DNS server",
+ .tag = DHCP_DNS_SERVERS,
+ .type = &setting_type_ipv4,
+};
+
/**
* Apply nameserver setting
*
@@ -516,7 +531,7 @@ static int apply_nameserver_setting ( void ) {
( struct sockaddr_in * ) &nameserver;
int len;
- if ( ( len = fetch_ipv4_setting ( NULL, DHCP_DNS_SERVERS,
+ if ( ( len = fetch_ipv4_setting ( NULL, &dns_setting,
&sin_nameserver->sin_addr ) ) >= 0 ){
sin_nameserver->sin_family = AF_INET;
DBG ( "DNS using nameserver %s\n",
diff --git a/src/net/udp/tftp.c b/src/net/udp/tftp.c
index 8bd2b80b..e49bcf9f 100644
--- a/src/net/udp/tftp.c
+++ b/src/net/udp/tftp.c
@@ -1093,6 +1093,21 @@ struct uri_opener mtftp_uri_opener __uri_opener = {
.open = mtftp_open,
};
+/******************************************************************************
+ *
+ * Settings
+ *
+ ******************************************************************************
+ */
+
+/** TFTP server setting */
+struct setting next_server_setting __setting = {
+ .name = "next-server",
+ .description = "TFTP server",
+ .tag = DHCP_EB_SIADDR,
+ .type = &setting_type_ipv4,
+};
+
/**
* Apply TFTP configuration settings
*
@@ -1106,7 +1121,7 @@ static int tftp_apply_settings ( void ) {
/* Retrieve TFTP server setting */
last_tftp_server = tftp_server;
- fetch_ipv4_setting ( NULL, DHCP_EB_SIADDR, &tftp_server );
+ fetch_ipv4_setting ( NULL, &next_server_setting, &tftp_server );
/* If TFTP server setting has changed, set the current working
* URI to match. Do it only when the TFTP server has changed
diff --git a/src/usr/aoeboot.c b/src/usr/aoeboot.c
index 6bf56a87..f0e481bd 100644
--- a/src/usr/aoeboot.c
+++ b/src/usr/aoeboot.c
@@ -5,7 +5,6 @@
#include <gpxe/aoe.h>
#include <gpxe/ata.h>
#include <gpxe/netdevice.h>
-#include <gpxe/dhcp.h>
#include <gpxe/settings.h>
#include <gpxe/abft.h>
#include <int13.h>
@@ -56,7 +55,6 @@ int aoeboot ( const char *root_path ) {
container_of ( ata.backend, struct aoe_session, refcnt );
abft_fill_data ( aoe );
- drive.drive = fetch_uintz_setting ( NULL, DHCP_EB_BIOS_DRIVE );
drive.blockdev = &ata.blockdev;
register_int13_drive ( &drive );
diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c
index bc86d05e..c1a61ec0 100644
--- a/src/usr/autoboot.c
+++ b/src/usr/autoboot.c
@@ -147,14 +147,14 @@ static int netboot ( struct net_device *netdev ) {
return rc;
/* Try to download and boot whatever we are given as a filename */
- fetch_string_setting ( NULL, DHCP_BOOTFILE_NAME, buf, sizeof ( buf ) );
+ fetch_string_setting ( NULL, &filename_setting, buf, sizeof ( buf ) );
if ( buf[0] ) {
printf ( "Booting from filename \"%s\"\n", buf );
return boot_filename ( buf );
}
/* No filename; try the root path */
- fetch_string_setting ( NULL, DHCP_ROOT_PATH, buf, sizeof ( buf ) );
+ fetch_string_setting ( NULL, &root_path_setting, buf, sizeof ( buf ) );
if ( buf[0] ) {
printf ( "Booting from root path \"%s\"\n", buf );
return boot_root_path ( buf );
diff --git a/src/usr/iscsiboot.c b/src/usr/iscsiboot.c
index c3a477c4..99edc879 100644
--- a/src/usr/iscsiboot.c
+++ b/src/usr/iscsiboot.c
@@ -2,7 +2,6 @@
#include <string.h>
#include <stdio.h>
#include <gpxe/iscsi.h>
-#include <gpxe/dhcp.h>
#include <gpxe/settings.h>
#include <gpxe/netdevice.h>
#include <gpxe/ibft.h>
@@ -46,7 +45,6 @@ int iscsiboot ( const char *root_path ) {
goto error_init;
}
- drive.drive = fetch_uintz_setting ( NULL, DHCP_EB_BIOS_DRIVE );
drive.blockdev = &scsi.blockdev;
/* FIXME: ugly, ugly hack */