[Settings] Introduce settings applicators.
authorMichael Brown <mcb30@etherboot.org>
Thu, 20 Mar 2008 23:15:48 +0000 (23:15 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 20 Mar 2008 23:15:48 +0000 (23:15 +0000)
Convert DHCP option applicators in dns.c and iscsi.c to settings
applicators.

Kill off DHCP option applicators.

src/core/settings.c
src/include/gpxe/dhcp.h
src/include/gpxe/settings.h
src/net/dhcpopts.c
src/net/tcp/iscsi.c
src/net/udp/dns.c

index 49a7410..458ba11 100644 (file)
 
 /** Registered setting types */
 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]
-__table_end ( struct setting_type, setting_types );
+       __table_end ( struct setting_type, setting_types );
 
 /** Registered named settings */
 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]
-__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
@@ -94,10 +100,6 @@ int simple_settings_fetch ( struct settings *settings, unsigned int tag,
        return ( len ? len : 8 );
 }
 
-// Dummy routine just for testing
-static void apply_settings ( void ) {
-}
-
 /** Simple settings operations */
 struct settings_operations simple_settings_operations = {
        .store = simple_settings_store,
@@ -113,6 +115,66 @@ struct settings settings_root = {
        .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
  *
@@ -134,6 +196,9 @@ int register_settings ( struct settings *settings, struct settings *parent ) {
        list_add_tail ( &settings->siblings, &parent->children );
        DBGC ( settings, "Settings %p registered\n", settings );
 
+       /* Fix up settings priority */
+       reprioritise_settings ( settings );
+
        /* Apply potentially-updated 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
  *
@@ -288,7 +381,7 @@ int fetch_ipv4_setting ( struct settings *settings, unsigned int tag,
        len = fetch_setting ( settings, tag, inp, sizeof ( *inp ) );
        if ( len < 0 )
                return len;
-       if ( len != sizeof ( *inp ) )
+       if ( len < ( int ) sizeof ( *inp ) )
                return -ERANGE;
        return len;
 }
index 3da9652..a8fa811 100644 (file)
@@ -489,23 +489,6 @@ struct dhcp_packet {
        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
  *
index 5333c4f..94ca9e0 100644 (file)
@@ -122,6 +122,22 @@ struct named_setting {
 /** Declare a configuration setting */
 #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,
                                   const void *data, size_t len );
 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,
                               struct settings *parent );
 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,
                           void *data, size_t len );
 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;
 }
 
-/**
- * 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
  *
index ed53916..75a9f2a 100644 (file)
 /** List of registered 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
  *
@@ -578,13 +572,9 @@ void delete_dhcp_option ( struct dhcp_option_block *options,
  * @ret rc             Return status code
  */
 int apply_dhcp_options ( struct dhcp_option_block *options ) {
-       struct dhcp_option_applicator *applicator;
-       struct dhcp_option *option;
        struct in_addr tftp_server;
        struct uri *uri;
        char uri_string[32];
-       unsigned int tag;
-       int rc;
 
        /* Set current working URI based on 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 );
        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;
 }
 
index cf6c7f5..0e7b258 100644 (file)
@@ -31,7 +31,7 @@
 #include <gpxe/process.h>
 #include <gpxe/uaccess.h>
 #include <gpxe/tcpip.h>
-#include <gpxe/dhcp.h>
+#include <gpxe/settings.h>
 #include <gpxe/features.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
  *
  */
 
-/**
- * Apply DHCP iSCSI option
- *
- * @v tag              DHCP option tag
- * @v option           DHCP option
- * @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;
+/** An iSCSI string setting */
+struct iscsi_string_setting {
+       /** Setting tag number */
+       unsigned int tag;
+       /** String to update */
        char **string;
-       char *p;
-
-       /* Identify string and prefix */
-       switch ( tag ) {
-       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;
-}
+       /** String prefix */
+       const char *prefix;
+};
 
-/** DHCP iSCSI option applicators */
-struct dhcp_option_applicator dhcp_iscsi_applicators[] __dhcp_applicator = {
+/** iSCSI string settings */
+static struct iscsi_string_setting iscsi_string_settings[] = {
        {
                .tag = DHCP_ISCSI_INITIATOR_IQN,
-               .apply = apply_dhcp_iscsi_string,
+               .string = &iscsi_explicit_initiator_iqn,
+               .prefix = "",
        },
        {
                .tag = DHCP_EB_USERNAME,
-               .apply = apply_dhcp_iscsi_string,
+               .string = &iscsi_username,
+               .prefix = "",
        },
        {
                .tag = DHCP_EB_PASSWORD,
-               .apply = apply_dhcp_iscsi_string,
+               .string = &iscsi_password,
+               .prefix = "",
        },
        {
                .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
index d82d124..5e632d1 100644 (file)
@@ -30,7 +30,7 @@
 #include <gpxe/resolv.h>
 #include <gpxe/retry.h>
 #include <gpxe/tcpip.h>
-#include <gpxe/dhcp.h>
+#include <gpxe/settings.h>
 #include <gpxe/features.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
- * @v option           DHCP option
+ * @ret rc             Return status code
  */
-static int apply_dhcp_nameserver ( unsigned int tag __unused,
-                                  struct dhcp_option *option ) {
-       struct sockaddr_in *sin_nameserver;
-
-       sin_nameserver = ( struct sockaddr_in * ) &nameserver;
-       sin_nameserver->sin_family = AF_INET;
-       dhcp_ipv4_option ( option, &sin_nameserver->sin_addr );
-
-       DBG ( "DNS using nameserver %s\n",
-             inet_ntoa ( sin_nameserver->sin_addr ) );
+static int apply_nameserver_setting ( void ) {
+       struct sockaddr_in *sin_nameserver =
+               ( struct sockaddr_in * ) &nameserver;
+       int len;
+
+       if ( ( len = fetch_ipv4_setting ( NULL, DHCP_DNS_SERVERS,
+                                         &sin_nameserver->sin_addr ) ) >= 0 ){
+               sin_nameserver->sin_family = AF_INET;
+               DBG ( "DNS using nameserver %s\n",
+                     inet_ntoa ( sin_nameserver->sin_addr ) );
+       }
 
        return 0;
 }
 
-/** DHCP nameserver applicator */
-struct dhcp_option_applicator dhcp_nameserver_applicator __dhcp_applicator = {
-       .tag = DHCP_DNS_SERVERS,
-       .apply = apply_dhcp_nameserver,
+/** Nameserver setting applicator */
+struct settings_applicator nameserver_applicator __settings_applicator = {
+       .apply = apply_nameserver_setting,
 };