david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[Settings] Introduce settings applicators.

Convert DHCP option applicators in dns.c and iscsi.c to settings
applicators.

Kill off DHCP option applicators.
This commit is contained in:
Michael Brown 2008-03-20 23:15:48 +00:00
parent acfa14423e
commit cf03304620
6 changed files with 221 additions and 137 deletions

View File

@ -37,15 +37,21 @@
/** Registered setting types */ /** Registered setting types */
static struct setting_type setting_types[0] static struct setting_type setting_types[0]
__table_start ( struct setting_type, setting_types ); __table_start ( struct setting_type, setting_types );
static struct setting_type setting_types_end[0] static struct setting_type setting_types_end[0]
__table_end ( struct setting_type, setting_types ); __table_end ( struct setting_type, setting_types );
/** Registered named settings */ /** Registered named settings */
static struct named_setting named_settings[0] static struct named_setting named_settings[0]
__table_start ( struct named_setting, named_settings ); __table_start ( struct named_setting, named_settings );
static struct named_setting named_settings_end[0] static struct named_setting named_settings_end[0]
__table_end ( struct named_setting, named_settings ); __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 * Obtain printable version of a settings tag number
@ -94,10 +100,6 @@ int simple_settings_fetch ( struct settings *settings, unsigned int tag,
return ( len ? len : 8 ); return ( len ? len : 8 );
} }
// Dummy routine just for testing
static void apply_settings ( void ) {
}
/** Simple settings operations */ /** Simple settings operations */
struct settings_operations simple_settings_operations = { struct settings_operations simple_settings_operations = {
.store = simple_settings_store, .store = simple_settings_store,
@ -113,6 +115,66 @@ struct settings settings_root = {
.op = &simple_settings_operations, .op = &simple_settings_operations,
}; };
/**
* Apply all settings
*
* @ret rc Return status code
*/
static int apply_settings ( void ) {
struct settings_applicator *applicator;
int rc;
/* Call all settings applicators */
for ( applicator = settings_applicators ;
applicator < settings_applicators_end ; applicator++ ) {
if ( ( rc = applicator->apply() ) != 0 ) {
DBG ( "Could not apply settings using applicator "
"%p: %s\n", applicator, strerror ( rc ) );
return rc;
}
}
return 0;
}
/**
* Reprioritise settings
*
* @v settings Settings block
*
* Reorders the settings block amongst its siblings according to its
* priority.
*/
static void reprioritise_settings ( struct settings *settings ) {
struct settings *parent = settings->parent;
long priority;
struct settings *tmp;
long tmp_priority;
/* Stop when we reach the top of the tree */
if ( ! parent )
return;
/* Read priority, if present */
priority = 0;
fetch_int_setting ( settings, DHCP_EB_PRIORITY, &priority );
/* 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 = 0;
fetch_int_setting ( tmp, DHCP_EB_PRIORITY, &tmp_priority );
if ( priority > tmp_priority )
break;
}
list_add_tail ( &settings->siblings, &tmp->siblings );
/* Recurse up the tree */
reprioritise_settings ( parent );
}
/** /**
* Register settings block * Register settings block
* *
@ -134,6 +196,9 @@ int register_settings ( struct settings *settings, struct settings *parent ) {
list_add_tail ( &settings->siblings, &parent->children ); list_add_tail ( &settings->siblings, &parent->children );
DBGC ( settings, "Settings %p registered\n", settings ); DBGC ( settings, "Settings %p registered\n", settings );
/* Fix up settings priority */
reprioritise_settings ( settings );
/* Apply potentially-updated settings */ /* Apply potentially-updated settings */
apply_settings(); apply_settings();
@ -206,6 +271,34 @@ struct settings * find_settings ( const char *name ) {
****************************************************************************** ******************************************************************************
*/ */
/**
* Store value of setting
*
* @v settings Settings block
* @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
*/
int store_setting ( struct settings *settings, unsigned int tag,
const void *data, size_t len ) {
int rc;
/* Store setting */
if ( ( rc = settings->op->store ( settings, tag, data, len ) ) != 0 )
return rc;
/* Reprioritise settings if necessary */
if ( tag == DHCP_EB_PRIORITY )
reprioritise_settings ( settings );
/* Apply potentially-updated setting */
if ( ( rc = apply_settings() ) != 0 )
return rc;
return 0;
}
/** /**
* Fetch value of setting * Fetch value of setting
* *
@ -288,7 +381,7 @@ int fetch_ipv4_setting ( struct settings *settings, unsigned int tag,
len = fetch_setting ( settings, tag, inp, sizeof ( *inp ) ); len = fetch_setting ( settings, tag, inp, sizeof ( *inp ) );
if ( len < 0 ) if ( len < 0 )
return len; return len;
if ( len != sizeof ( *inp ) ) if ( len < ( int ) sizeof ( *inp ) )
return -ERANGE; return -ERANGE;
return len; return len;
} }

View File

@ -489,23 +489,6 @@ struct dhcp_packet {
struct dhcp_option_block options; struct dhcp_option_block options;
}; };
/** A DHCP option applicator */
struct dhcp_option_applicator {
/** DHCP option tag */
unsigned int tag;
/** Applicator
*
* @v tag DHCP option tag
* @v option DHCP option
* @ret rc Return status code
*/
int ( * apply ) ( unsigned int tag, struct dhcp_option *option );
};
/** Declare a DHCP option applicator */
#define __dhcp_applicator \
__table ( struct dhcp_option_applicator, dhcp_applicators, 01 )
/** /**
* Get reference to DHCP options block * Get reference to DHCP options block
* *

View File

@ -122,6 +122,22 @@ struct named_setting {
/** Declare a configuration setting */ /** Declare a configuration setting */
#define __named_setting __table ( struct named_setting, named_settings, 01 ) #define __named_setting __table ( struct named_setting, named_settings, 01 )
/**
* A settings applicator
*
*/
struct settings_applicator {
/** Apply updated settings
*
* @ret rc Return status code
*/
int ( * apply ) ( void );
};
/** Declare a settings applicator */
#define __settings_applicator \
__table ( struct settings_applicator, settings_applicators, 01 )
extern int simple_settings_store ( struct settings *settings, unsigned int tag, extern int simple_settings_store ( struct settings *settings, unsigned int tag,
const void *data, size_t len ); 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, unsigned int tag,
@ -131,6 +147,8 @@ extern struct settings_operations simple_settings_operations;
extern int register_settings ( struct settings *settings, extern int register_settings ( struct settings *settings,
struct settings *parent ); struct settings *parent );
extern void unregister_settings ( struct settings *settings ); extern void unregister_settings ( struct settings *settings );
extern int store_setting ( struct settings *settings, unsigned int tag,
const void *data, size_t len );
extern int fetch_setting ( struct settings *settings, unsigned int tag, extern int fetch_setting ( struct settings *settings, unsigned int tag,
void *data, size_t len ); void *data, size_t len );
extern int fetch_setting_len ( struct settings *settings, unsigned int tag ); extern int fetch_setting_len ( struct settings *settings, unsigned int tag );
@ -179,20 +197,6 @@ static inline void settings_init ( struct settings *settings,
settings->name = name; settings->name = name;
} }
/**
* Store value of setting
*
* @v settings Settings block
* @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 inline int store_setting ( struct settings *settings, unsigned int tag,
const void *data, size_t len ) {
return settings->op->store ( settings, tag, data, len );
}
/** /**
* Delete setting * Delete setting
* *

View File

@ -37,12 +37,6 @@
/** List of registered DHCP option blocks */ /** List of registered DHCP option blocks */
LIST_HEAD ( dhcp_option_blocks ); LIST_HEAD ( dhcp_option_blocks );
/** Registered DHCP option applicators */
static struct dhcp_option_applicator dhcp_option_applicators[0]
__table_start ( struct dhcp_option_applicator, dhcp_applicators );
static struct dhcp_option_applicator dhcp_option_applicators_end[0]
__table_end ( struct dhcp_option_applicator, dhcp_applicators );
/** /**
* Obtain printable version of a DHCP option tag * Obtain printable version of a DHCP option tag
* *
@ -578,13 +572,9 @@ void delete_dhcp_option ( struct dhcp_option_block *options,
* @ret rc Return status code * @ret rc Return status code
*/ */
int apply_dhcp_options ( struct dhcp_option_block *options ) { int apply_dhcp_options ( struct dhcp_option_block *options ) {
struct dhcp_option_applicator *applicator;
struct dhcp_option *option;
struct in_addr tftp_server; struct in_addr tftp_server;
struct uri *uri; struct uri *uri;
char uri_string[32]; char uri_string[32];
unsigned int tag;
int rc;
/* Set current working URI based on TFTP server */ /* Set current working URI based on TFTP server */
find_dhcp_ipv4_option ( options, DHCP_EB_SIADDR, &tftp_server ); find_dhcp_ipv4_option ( options, DHCP_EB_SIADDR, &tftp_server );
@ -596,20 +586,6 @@ int apply_dhcp_options ( struct dhcp_option_block *options ) {
churi ( uri ); churi ( uri );
uri_put ( uri ); uri_put ( uri );
/* Call all registered DHCP option applicators */
for ( applicator = dhcp_option_applicators ;
applicator < dhcp_option_applicators_end ; applicator++ ) {
tag = applicator->tag;
option = find_dhcp_option ( options, tag );
if ( ! option )
continue;
if ( ( rc = applicator->apply ( tag, option ) ) != 0 ) {
DBG ( "Could not apply DHCP option %s: %s\n",
dhcp_tag_name ( tag ), strerror ( rc ) );
return rc;
}
}
return 0; return 0;
} }

View File

@ -31,7 +31,7 @@
#include <gpxe/process.h> #include <gpxe/process.h>
#include <gpxe/uaccess.h> #include <gpxe/uaccess.h>
#include <gpxe/tcpip.h> #include <gpxe/tcpip.h>
#include <gpxe/dhcp.h> #include <gpxe/settings.h>
#include <gpxe/features.h> #include <gpxe/features.h>
#include <gpxe/iscsi.h> #include <gpxe/iscsi.h>
@ -1591,80 +1591,109 @@ int iscsi_attach ( struct scsi_device *scsi, const char *root_path ) {
/**************************************************************************** /****************************************************************************
* *
* DHCP option applicators * Settings applicators
* *
*/ */
/** /** An iSCSI string setting */
* Apply DHCP iSCSI option struct iscsi_string_setting {
* /** Setting tag number */
* @v tag DHCP option tag unsigned int tag;
* @v option DHCP option /** String to update */
* @ret rc Return status code
*/
static int apply_dhcp_iscsi_string ( unsigned int tag,
struct dhcp_option *option ) {
char *prefix = "";
size_t prefix_len;
size_t len;
char **string; char **string;
char *p; /** String prefix */
const char *prefix;
};
/* Identify string and prefix */ /** iSCSI string settings */
switch ( tag ) { static struct iscsi_string_setting iscsi_string_settings[] = {
case DHCP_ISCSI_INITIATOR_IQN:
string = &iscsi_explicit_initiator_iqn;
break;
case DHCP_EB_USERNAME:
string = &iscsi_username;
break;
case DHCP_EB_PASSWORD:
string = &iscsi_password;
break;
case DHCP_HOST_NAME:
string = &iscsi_default_initiator_iqn;
prefix = "iqn.2000-09.org.etherboot:";
break;
default:
assert ( 0 );
return -EINVAL;
}
/* Free old string */
free ( *string );
*string = NULL;
/* Allocate and fill new string */
prefix_len = strlen ( prefix );
len = ( prefix_len + option->len + 1 );
p = *string = malloc ( len );
if ( ! p )
return -ENOMEM;
strcpy ( p, prefix );
dhcp_snprintf ( ( p + prefix_len ), ( len - prefix_len ), option );
return 0;
}
/** DHCP iSCSI option applicators */
struct dhcp_option_applicator dhcp_iscsi_applicators[] __dhcp_applicator = {
{ {
.tag = DHCP_ISCSI_INITIATOR_IQN, .tag = DHCP_ISCSI_INITIATOR_IQN,
.apply = apply_dhcp_iscsi_string, .string = &iscsi_explicit_initiator_iqn,
.prefix = "",
}, },
{ {
.tag = DHCP_EB_USERNAME, .tag = DHCP_EB_USERNAME,
.apply = apply_dhcp_iscsi_string, .string = &iscsi_username,
.prefix = "",
}, },
{ {
.tag = DHCP_EB_PASSWORD, .tag = DHCP_EB_PASSWORD,
.apply = apply_dhcp_iscsi_string, .string = &iscsi_password,
.prefix = "",
}, },
{ {
.tag = DHCP_HOST_NAME, .tag = DHCP_HOST_NAME,
.apply = apply_dhcp_iscsi_string, .string = &iscsi_default_initiator_iqn,
.prefix = "iqn.2000-09.org.etherboot:",
}, },
}; };
/**
* Apply iSCSI setting
*
* @v setting iSCSI string setting
* @ret rc Return status code
*/
static int apply_iscsi_string_setting ( struct iscsi_string_setting *setting ){
size_t prefix_len;
int setting_len;
size_t len;
int check_len;
char *p;
/* Free old string */
free ( *setting->string );
*setting->string = NULL;
/* Allocate new string */
prefix_len = strlen ( setting->prefix );
setting_len = fetch_setting_len ( NULL, setting->tag );
if ( setting_len < 0 )
return setting_len;
len = ( prefix_len + setting_len + 1 );
p = *setting->string = malloc ( len );
if ( ! p )
return -ENOMEM;
/* Fill new string */
strcpy ( p, setting->prefix );
check_len = fetch_string_setting ( NULL, setting->tag,
( p + prefix_len ),
( len - prefix_len ) );
assert ( check_len == setting_len );
return 0;
}
/**
* Apply iSCSI settings
*
* @ret rc Return status code
*/
static int apply_iscsi_settings ( void ) {
struct iscsi_string_setting *setting;
unsigned int i;
int rc;
for ( i = 0 ; i < ( sizeof ( iscsi_string_settings ) /
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 );
return rc;
}
}
return 0;
}
/** iSCSI settings applicator */
struct settings_applicator iscsi_settings_applicator __settings_applicator = {
.apply = apply_iscsi_settings,
};
/**************************************************************************** /****************************************************************************
* *
* Initiator name * Initiator name

View File

@ -30,7 +30,7 @@
#include <gpxe/resolv.h> #include <gpxe/resolv.h>
#include <gpxe/retry.h> #include <gpxe/retry.h>
#include <gpxe/tcpip.h> #include <gpxe/tcpip.h>
#include <gpxe/dhcp.h> #include <gpxe/settings.h>
#include <gpxe/features.h> #include <gpxe/features.h>
#include <gpxe/dns.h> #include <gpxe/dns.h>
@ -507,27 +507,26 @@ struct resolver dns_resolver __resolver ( RESOLV_NORMAL ) = {
}; };
/** /**
* Apply DHCP nameserver option * Apply nameserver setting
* *
* @v tag DHCP option tag * @ret rc Return status code
* @v option DHCP option
*/ */
static int apply_dhcp_nameserver ( unsigned int tag __unused, static int apply_nameserver_setting ( void ) {
struct dhcp_option *option ) { struct sockaddr_in *sin_nameserver =
struct sockaddr_in *sin_nameserver; ( struct sockaddr_in * ) &nameserver;
int len;
sin_nameserver = ( struct sockaddr_in * ) &nameserver; if ( ( len = fetch_ipv4_setting ( NULL, DHCP_DNS_SERVERS,
sin_nameserver->sin_family = AF_INET; &sin_nameserver->sin_addr ) ) >= 0 ){
dhcp_ipv4_option ( option, &sin_nameserver->sin_addr ); sin_nameserver->sin_family = AF_INET;
DBG ( "DNS using nameserver %s\n",
DBG ( "DNS using nameserver %s\n", inet_ntoa ( sin_nameserver->sin_addr ) );
inet_ntoa ( sin_nameserver->sin_addr ) ); }
return 0; return 0;
} }
/** DHCP nameserver applicator */ /** Nameserver setting applicator */
struct dhcp_option_applicator dhcp_nameserver_applicator __dhcp_applicator = { struct settings_applicator nameserver_applicator __settings_applicator = {
.tag = DHCP_DNS_SERVERS, .apply = apply_nameserver_setting,
.apply = apply_dhcp_nameserver,
}; };