settings.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020 
00021 #include <stdint.h>
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <strings.h>
00026 #include <byteswap.h>
00027 #include <errno.h>
00028 #include <assert.h>
00029 #include <gpxe/in.h>
00030 #include <gpxe/vsprintf.h>
00031 #include <gpxe/dhcp.h>
00032 #include <gpxe/uuid.h>
00033 #include <gpxe/uri.h>
00034 #include <gpxe/settings.h>
00035 
00036 /** @file
00037  *
00038  * Configuration settings
00039  *
00040  */
00041 
00042 /******************************************************************************
00043  *
00044  * Generic settings blocks
00045  *
00046  ******************************************************************************
00047  */
00048 
00049 /**
00050  * A generic setting
00051  *
00052  */
00053 struct generic_setting {
00054         /** List of generic settings */
00055         struct list_head list;
00056         /** Setting */
00057         struct setting setting;
00058         /** Size of setting name */
00059         size_t name_len;
00060         /** Size of setting data */
00061         size_t data_len;
00062 };
00063 
00064 /**
00065  * Get generic setting name
00066  *
00067  * @v generic           Generic setting
00068  * @ret name            Generic setting name
00069  */
00070 static inline void * generic_setting_name ( struct generic_setting *generic ) {
00071         return ( ( ( void * ) generic ) + sizeof ( *generic ) );
00072 }
00073 
00074 /**
00075  * Get generic setting data
00076  *
00077  * @v generic           Generic setting
00078  * @ret data            Generic setting data
00079  */
00080 static inline void * generic_setting_data ( struct generic_setting *generic ) {
00081         return ( ( ( void * ) generic ) + sizeof ( *generic ) +
00082                  generic->name_len );
00083 }
00084 
00085 /**
00086  * Find generic setting
00087  *
00088  * @v generics          Generic settings block
00089  * @v setting           Setting to find
00090  * @ret generic         Generic setting, or NULL
00091  */
00092 static struct generic_setting *
00093 find_generic_setting ( struct generic_settings *generics,
00094                        struct setting *setting ) {
00095         struct generic_setting *generic;
00096 
00097         list_for_each_entry ( generic, &generics->list, list ) {
00098                 if ( setting_cmp ( &generic->setting, setting ) == 0 )
00099                         return generic;
00100         }
00101         return NULL;
00102 }
00103 
00104 /**
00105  * Store value of generic setting
00106  *
00107  * @v settings          Settings block
00108  * @v setting           Setting to store
00109  * @v data              Setting data, or NULL to clear setting
00110  * @v len               Length of setting data
00111  * @ret rc              Return status code
00112  */
00113 int generic_settings_store ( struct settings *settings,
00114                              struct setting *setting,
00115                              const void *data, size_t len ) {
00116         struct generic_settings *generics =
00117                 container_of ( settings, struct generic_settings, settings );
00118         struct generic_setting *old;
00119         struct generic_setting *new = NULL;
00120         size_t name_len;
00121 
00122         /* Identify existing generic setting, if any */
00123         old = find_generic_setting ( generics, setting );
00124 
00125         /* Create new generic setting, if required */
00126         if ( len ) {
00127                 /* Allocate new generic setting */
00128                 name_len = ( strlen ( setting->name ) + 1 );
00129                 new = zalloc ( sizeof ( *new ) + name_len + len );
00130                 if ( ! new )
00131                         return -ENOMEM;
00132 
00133                 /* Populate new generic setting */
00134                 new->name_len = name_len;
00135                 new->data_len = len;
00136                 memcpy ( &new->setting, setting, sizeof ( new->setting ) );
00137                 new->setting.name = generic_setting_name ( new );
00138                 memcpy ( generic_setting_name ( new ),
00139                          setting->name, name_len );
00140                 memcpy ( generic_setting_data ( new ), data, len );
00141         }
00142 
00143         /* Delete existing generic setting, if any */
00144         if ( old ) {
00145                 list_del ( &old->list );
00146                 free ( old );
00147         }
00148 
00149         /* Add new setting to list, if any */
00150         if ( new )
00151                 list_add ( &new->list, &generics->list );
00152 
00153         return 0;
00154 }
00155 
00156 /**
00157  * Fetch value of generic setting
00158  *
00159  * @v settings          Settings block
00160  * @v setting           Setting to fetch
00161  * @v data              Buffer to fill with setting data
00162  * @v len               Length of buffer
00163  * @ret len             Length of setting data, or negative error
00164  */
00165 int generic_settings_fetch ( struct settings *settings,
00166                              struct setting *setting,
00167                              void *data, size_t len ) {
00168         struct generic_settings *generics =
00169                 container_of ( settings, struct generic_settings, settings );
00170         struct generic_setting *generic;
00171 
00172         /* Find generic setting */
00173         generic = find_generic_setting ( generics, setting );
00174         if ( ! generic )
00175                 return -ENOENT;
00176 
00177         /* Copy out generic setting data */
00178         if ( len > generic->data_len )
00179                 len = generic->data_len;
00180         memcpy ( data, generic_setting_data ( generic ), len );
00181         return generic->data_len;
00182 }
00183 
00184 /**
00185  * Clear generic settings block
00186  *
00187  * @v settings          Settings block
00188  */
00189 void generic_settings_clear ( struct settings *settings ) {
00190         struct generic_settings *generics =
00191                 container_of ( settings, struct generic_settings, settings );
00192         struct generic_setting *generic;
00193         struct generic_setting *tmp;
00194 
00195         list_for_each_entry_safe ( generic, tmp, &generics->list, list ) {
00196                 list_del ( &generic->list );
00197                 free ( generic );
00198         }
00199         assert ( list_empty ( &generics->list ) );
00200 }
00201 
00202 /** Generic settings operations */
00203 struct settings_operations generic_settings_operations = {
00204         .store = generic_settings_store,
00205         .fetch = generic_settings_fetch,
00206         .clear = generic_settings_clear,
00207 };
00208 
00209 /******************************************************************************
00210  *
00211  * Registered settings blocks
00212  *
00213  ******************************************************************************
00214  */
00215 
00216 /** Root generic settings block */
00217 struct generic_settings generic_settings_root = {
00218         .settings = {
00219                 .refcnt = NULL,
00220                 .name = "",
00221                 .siblings =
00222                     LIST_HEAD_INIT ( generic_settings_root.settings.siblings ),
00223                 .children =
00224                     LIST_HEAD_INIT ( generic_settings_root.settings.children ),
00225                 .op = &generic_settings_operations,
00226         },
00227         .list = LIST_HEAD_INIT ( generic_settings_root.list ),
00228 };
00229 
00230 /** Root settings block */
00231 #define settings_root generic_settings_root.settings
00232 
00233 /**
00234  * Find child named settings block
00235  *
00236  * @v parent            Parent settings block
00237  * @v name              Name within this parent
00238  * @ret settings        Settings block, or NULL
00239  */
00240 static struct settings * find_child_settings ( struct settings *parent,
00241                                                const char *name ) {
00242         struct settings *settings;
00243 
00244         /* Treat empty name as meaning "this block" */
00245         if ( ! *name )
00246                 return parent;
00247 
00248         /* Look for child with matching name */
00249         list_for_each_entry ( settings, &parent->children, siblings ) {
00250                 if ( strcmp ( settings->name, name ) == 0 )
00251                         return settings;
00252         }
00253 
00254         return NULL;
00255 }
00256 
00257 /**
00258  * Find or create child named settings block
00259  *
00260  * @v parent            Parent settings block
00261  * @v name              Name within this parent
00262  * @ret settings        Settings block, or NULL
00263  */
00264 static struct settings * autovivify_child_settings ( struct settings *parent,
00265                                                      const char *name ) {
00266         struct {
00267                 struct generic_settings generic;
00268                 char name[ strlen ( name ) + 1 /* NUL */ ];
00269         } *new_child;
00270         struct settings *settings;
00271 
00272         /* Return existing settings, if existent */
00273         if ( ( settings = find_child_settings ( parent, name ) ) != NULL )
00274                 return settings;
00275 
00276         /* Create new generic settings block */
00277         new_child = zalloc ( sizeof ( *new_child ) );
00278         if ( ! new_child ) {
00279                 DBGC ( parent, "Settings %p could not create child %s\n",
00280                        parent, name );
00281                 return NULL;
00282         }
00283         memcpy ( new_child->name, name, sizeof ( new_child->name ) );
00284         generic_settings_init ( &new_child->generic, NULL, new_child->name );
00285         settings = &new_child->generic.settings;
00286         register_settings ( settings, parent );
00287         return settings;
00288 }
00289 
00290 /**
00291  * Return settings block name (for debug only)
00292  *
00293  * @v settings          Settings block
00294  * @ret name            Settings block name
00295  */
00296 static const char * settings_name ( struct settings *settings ) {
00297         static char buf[64];
00298         char tmp[ sizeof ( buf ) ];
00299         int count;
00300 
00301         for ( count = 0 ; settings ; settings = settings->parent ) {
00302                 memcpy ( tmp, buf, sizeof ( tmp ) );
00303                 snprintf ( buf, sizeof ( buf ), "%s%c%s", settings->name,
00304                            ( count++ ? '.' : '\0' ), tmp );
00305         }
00306         return ( buf + 1 );
00307 }
00308 
00309 /**
00310  * Parse settings block name
00311  *
00312  * @v name              Name
00313  * @v get_child         Function to find or create child settings block
00314  * @ret settings        Settings block, or NULL
00315  */
00316 static struct settings *
00317 parse_settings_name ( const char *name,
00318                       struct settings * ( * get_child ) ( struct settings *,
00319                                                           const char * ) ) {
00320         struct settings *settings = &settings_root;
00321         char name_copy[ strlen ( name ) + 1 ];
00322         char *subname;
00323         char *remainder;
00324 
00325         /* Create modifiable copy of name */
00326         memcpy ( name_copy, name, sizeof ( name_copy ) );
00327         remainder = name_copy;
00328 
00329         /* Parse each name component in turn */
00330         while ( remainder ) {
00331                 struct net_device *netdev;
00332 
00333                 subname = remainder;
00334                 remainder = strchr ( subname, '.' );
00335                 if ( remainder )
00336                         *(remainder++) = '\0';
00337 
00338                 /* Special case "netX" root settings block */
00339                 if ( ( subname == name_copy ) && ! strcmp ( subname, "netX" ) &&
00340                      ( ( netdev = last_opened_netdev() ) != NULL ) )
00341                         settings = get_child ( settings, netdev->name );
00342                 else
00343                         settings = get_child ( settings, subname );
00344 
00345                 if ( ! settings )
00346                         break;
00347         }
00348 
00349         return settings;
00350 }
00351 
00352 /**
00353  * Find named settings block
00354  *
00355  * @v name              Name
00356  * @ret settings        Settings block, or NULL
00357  */
00358 struct settings * find_settings ( const char *name ) {
00359 
00360         return parse_settings_name ( name, find_child_settings );
00361 }
00362 
00363 /**
00364  * Apply all settings
00365  *
00366  * @ret rc              Return status code
00367  */
00368 static int apply_settings ( void ) {
00369         struct settings_applicator *applicator;
00370         int rc;
00371 
00372         /* Call all settings applicators */
00373         for_each_table_entry ( applicator, SETTINGS_APPLICATORS ) {
00374                 if ( ( rc = applicator->apply() ) != 0 ) {
00375                         DBG ( "Could not apply settings using applicator "
00376                               "%p: %s\n", applicator, strerror ( rc ) );
00377                         return rc;
00378                 }
00379         }
00380 
00381         return 0;
00382 }
00383 
00384 /**
00385  * Reprioritise settings
00386  *
00387  * @v settings          Settings block
00388  *
00389  * Reorders the settings block amongst its siblings according to its
00390  * priority.
00391  */
00392 static void reprioritise_settings ( struct settings *settings ) {
00393         struct settings *parent = settings->parent;
00394         long priority;
00395         struct settings *tmp;
00396         long tmp_priority;
00397 
00398         /* Stop when we reach the top of the tree */
00399         if ( ! parent )
00400                 return;
00401 
00402         /* Read priority, if present */
00403         priority = fetch_intz_setting ( settings, &priority_setting );
00404 
00405         /* Remove from siblings list */
00406         list_del ( &settings->siblings );
00407 
00408         /* Reinsert after any existing blocks which have a higher priority */
00409         list_for_each_entry ( tmp, &parent->children, siblings ) {
00410                 tmp_priority = fetch_intz_setting ( tmp, &priority_setting );
00411                 if ( priority > tmp_priority )
00412                         break;
00413         }
00414         list_add_tail ( &settings->siblings, &tmp->siblings );
00415 
00416         /* Recurse up the tree */
00417         reprioritise_settings ( parent );
00418 }
00419 
00420 /**
00421  * Register settings block
00422  *
00423  * @v settings          Settings block
00424  * @v parent            Parent settings block, or NULL
00425  * @ret rc              Return status code
00426  */
00427 int register_settings ( struct settings *settings, struct settings *parent ) {
00428         struct settings *old_settings;
00429 
00430         /* NULL parent => add to settings root */
00431         assert ( settings != NULL );
00432         if ( parent == NULL )
00433                 parent = &settings_root;
00434 
00435         /* Remove any existing settings with the same name */
00436         if ( ( old_settings = find_child_settings ( parent, settings->name ) ))
00437                 unregister_settings ( old_settings );
00438 
00439         /* Add to list of settings */
00440         ref_get ( settings->refcnt );
00441         ref_get ( parent->refcnt );
00442         settings->parent = parent;
00443         list_add_tail ( &settings->siblings, &parent->children );
00444         DBGC ( settings, "Settings %p (\"%s\") registered\n",
00445                settings, settings_name ( settings ) );
00446 
00447         /* Fix up settings priority */
00448         reprioritise_settings ( settings );
00449 
00450         /* Apply potentially-updated settings */
00451         apply_settings();
00452 
00453         return 0;
00454 }
00455 
00456 /**
00457  * Unregister settings block
00458  *
00459  * @v settings          Settings block
00460  */
00461 void unregister_settings ( struct settings *settings ) {
00462 
00463         DBGC ( settings, "Settings %p (\"%s\") unregistered\n",
00464                settings, settings_name ( settings ) );
00465 
00466         /* Remove from list of settings */
00467         ref_put ( settings->refcnt );
00468         ref_put ( settings->parent->refcnt );
00469         settings->parent = NULL;
00470         list_del ( &settings->siblings );
00471 
00472         /* Apply potentially-updated settings */
00473         apply_settings();
00474 }
00475 
00476 /******************************************************************************
00477  *
00478  * Core settings routines
00479  *
00480  ******************************************************************************
00481  */
00482 
00483 /**
00484  * Store value of setting
00485  *
00486  * @v settings          Settings block, or NULL
00487  * @v setting           Setting to store
00488  * @v data              Setting data, or NULL to clear setting
00489  * @v len               Length of setting data
00490  * @ret rc              Return status code
00491  */
00492 int store_setting ( struct settings *settings, struct setting *setting,
00493                     const void *data, size_t len ) {
00494         int rc;
00495 
00496         /* NULL settings implies storing into the global settings root */
00497         if ( ! settings )
00498                 settings = &settings_root;
00499 
00500         /* Sanity check */
00501         if ( ! settings->op->store )
00502                 return -ENOTSUP;
00503 
00504         /* Store setting */
00505         if ( ( rc = settings->op->store ( settings, setting,
00506                                           data, len ) ) != 0 )
00507                 return rc;
00508 
00509         /* Reprioritise settings if necessary */
00510         if ( setting_cmp ( setting, &priority_setting ) == 0 )
00511                 reprioritise_settings ( settings );
00512 
00513         /* If these settings are registered, apply potentially-updated
00514          * settings
00515          */
00516         for ( ; settings ; settings = settings->parent ) {
00517                 if ( settings == &settings_root ) {
00518                         if ( ( rc = apply_settings() ) != 0 )
00519                                 return rc;
00520                         break;
00521                 }
00522         }
00523 
00524         return 0;
00525 }
00526 
00527 /**
00528  * Fetch value of setting
00529  *
00530  * @v settings          Settings block, or NULL to search all blocks
00531  * @v setting           Setting to fetch
00532  * @v data              Buffer to fill with setting data
00533  * @v len               Length of buffer
00534  * @ret len             Length of setting data, or negative error
00535  *
00536  * The actual length of the setting will be returned even if
00537  * the buffer was too small.
00538  */
00539 int fetch_setting ( struct settings *settings, struct setting *setting,
00540                     void *data, size_t len ) {
00541         struct settings *child;
00542         int ret;
00543 
00544         /* Avoid returning uninitialised data on error */
00545         memset ( data, 0, len );
00546 
00547         /* NULL settings implies starting at the global settings root */
00548         if ( ! settings )
00549                 settings = &settings_root;
00550 
00551         /* Sanity check */
00552         if ( ! settings->op->fetch )
00553                 return -ENOTSUP;
00554 
00555         /* Try this block first */
00556         if ( ( ret = settings->op->fetch ( settings, setting,
00557                                            data, len ) ) >= 0 )
00558                 return ret;
00559 
00560         /* Recurse into each child block in turn */
00561         list_for_each_entry ( child, &settings->children, siblings ) {
00562                 if ( ( ret = fetch_setting ( child, setting,
00563                                              data, len ) ) >= 0 )
00564                         return ret;
00565         }
00566 
00567         return -ENOENT;
00568 }
00569 
00570 /**
00571  * Fetch length of setting
00572  *
00573  * @v settings          Settings block, or NULL to search all blocks
00574  * @v setting           Setting to fetch
00575  * @ret len             Length of setting data, or negative error
00576  *
00577  * This function can also be used as an existence check for the
00578  * setting.
00579  */
00580 int fetch_setting_len ( struct settings *settings, struct setting *setting ) {
00581         return fetch_setting ( settings, setting, NULL, 0 );
00582 }
00583 
00584 /**
00585  * Fetch value of string setting
00586  *
00587  * @v settings          Settings block, or NULL to search all blocks
00588  * @v setting           Setting to fetch
00589  * @v data              Buffer to fill with setting string data
00590  * @v len               Length of buffer
00591  * @ret len             Length of string setting, or negative error
00592  *
00593  * The resulting string is guaranteed to be correctly NUL-terminated.
00594  * The returned length will be the length of the underlying setting
00595  * data.
00596  */
00597 int fetch_string_setting ( struct settings *settings, struct setting *setting,
00598                            char *data, size_t len ) {
00599         memset ( data, 0, len );
00600         return fetch_setting ( settings, setting, data,
00601                                ( ( len > 0 ) ? ( len - 1 ) : 0 ) );
00602 }
00603 
00604 /**
00605  * Fetch value of string setting
00606  *
00607  * @v settings          Settings block, or NULL to search all blocks
00608  * @v setting           Setting to fetch
00609  * @v data              Buffer to allocate and fill with setting string data
00610  * @ret len             Length of string setting, or negative error
00611  *
00612  * The resulting string is guaranteed to be correctly NUL-terminated.
00613  * The returned length will be the length of the underlying setting
00614  * data.  The caller is responsible for eventually freeing the
00615  * allocated buffer.
00616  */
00617 int fetch_string_setting_copy ( struct settings *settings,
00618                                 struct setting *setting,
00619                                 char **data ) {
00620         int len;
00621         int check_len = 0;
00622 
00623         len = fetch_setting_len ( settings, setting );
00624         if ( len < 0 )
00625                 return len;
00626 
00627         *data = malloc ( len + 1 );
00628         if ( ! *data )
00629                 return -ENOMEM;
00630 
00631         check_len = fetch_string_setting ( settings, setting, *data,
00632                                            ( len + 1 ) );
00633         assert ( check_len == len );
00634         return len;
00635 }
00636 
00637 /**
00638  * Fetch value of IPv4 address setting
00639  *
00640  * @v settings          Settings block, or NULL to search all blocks
00641  * @v setting           Setting to fetch
00642  * @v inp               IPv4 address to fill in
00643  * @ret len             Length of setting, or negative error
00644  */
00645 int fetch_ipv4_setting ( struct settings *settings, struct setting *setting,
00646                          struct in_addr *inp ) {
00647         int len;
00648 
00649         len = fetch_setting ( settings, setting, inp, sizeof ( *inp ) );
00650         if ( len < 0 )
00651                 return len;
00652         if ( len < ( int ) sizeof ( *inp ) )
00653                 return -ERANGE;
00654         return len;
00655 }
00656 
00657 /**
00658  * Fetch value of signed integer setting
00659  *
00660  * @v settings          Settings block, or NULL to search all blocks
00661  * @v setting           Setting to fetch
00662  * @v value             Integer value to fill in
00663  * @ret len             Length of setting, or negative error
00664  */
00665 int fetch_int_setting ( struct settings *settings, struct setting *setting,
00666                         long *value ) {
00667         union {
00668                 uint8_t u8[ sizeof ( long ) ];
00669                 int8_t s8[ sizeof ( long ) ];
00670         } buf;
00671         int len;
00672         int i;
00673 
00674         /* Avoid returning uninitialised data on error */
00675         *value = 0;
00676 
00677         /* Fetch raw (network-ordered, variable-length) setting */
00678         len = fetch_setting ( settings, setting, &buf, sizeof ( buf ) );
00679         if ( len < 0 )
00680                 return len;
00681         if ( len > ( int ) sizeof ( buf ) )
00682                 return -ERANGE;
00683 
00684         /* Convert to host-ordered signed long */
00685         *value = ( ( buf.s8[0] >= 0 ) ? 0 : -1L );
00686         for ( i = 0 ; i < len ; i++ ) {
00687                 *value = ( ( *value << 8 ) | buf.u8[i] );
00688         }
00689 
00690         return len;
00691 }
00692 
00693 /**
00694  * Fetch value of unsigned integer setting
00695  *
00696  * @v settings          Settings block, or NULL to search all blocks
00697  * @v setting           Setting to fetch
00698  * @v value             Integer value to fill in
00699  * @ret len             Length of setting, or negative error
00700  */
00701 int fetch_uint_setting ( struct settings *settings, struct setting *setting,
00702                          unsigned long *value ) {
00703         long svalue;
00704         int len;
00705 
00706         /* Avoid returning uninitialised data on error */
00707         *value = 0;
00708 
00709         /* Fetch as a signed long */
00710         len = fetch_int_setting ( settings, setting, &svalue );
00711         if ( len < 0 )
00712                 return len;
00713 
00714         /* Mask off sign-extended bits */
00715         assert ( len <= ( int ) sizeof ( long ) );
00716         *value = ( svalue & ( -1UL >> ( 8 * ( sizeof ( long ) - len ) ) ) );
00717 
00718         return len;
00719 }
00720 
00721 /**
00722  * Fetch value of signed integer setting, or zero
00723  *
00724  * @v settings          Settings block, or NULL to search all blocks
00725  * @v setting           Setting to fetch
00726  * @ret value           Setting value, or zero
00727  */
00728 long fetch_intz_setting ( struct settings *settings, struct setting *setting ){
00729         long value;
00730 
00731         fetch_int_setting ( settings, setting, &value );
00732         return value;
00733 }
00734 
00735 /**
00736  * Fetch value of unsigned integer setting, or zero
00737  *
00738  * @v settings          Settings block, or NULL to search all blocks
00739  * @v setting           Setting to fetch
00740  * @ret value           Setting value, or zero
00741  */
00742 unsigned long fetch_uintz_setting ( struct settings *settings,
00743                                     struct setting *setting ) {
00744         unsigned long value;
00745 
00746         fetch_uint_setting ( settings, setting, &value );
00747         return value;
00748 }
00749 
00750 /**
00751  * Fetch value of UUID setting
00752  *
00753  * @v settings          Settings block, or NULL to search all blocks
00754  * @v setting           Setting to fetch
00755  * @v uuid              UUID to fill in
00756  * @ret len             Length of setting, or negative error
00757  */
00758 int fetch_uuid_setting ( struct settings *settings, struct setting *setting,
00759                          union uuid *uuid ) {
00760         int len;
00761 
00762         len = fetch_setting ( settings, setting, uuid, sizeof ( *uuid ) );
00763         if ( len < 0 )
00764                 return len;
00765         if ( len != sizeof ( *uuid ) )
00766                 return -ERANGE;
00767         return len;
00768 }
00769 
00770 /**
00771  * Clear settings block
00772  *
00773  * @v settings          Settings block
00774  */
00775 void clear_settings ( struct settings *settings ) {
00776         if ( settings->op->clear )
00777                 settings->op->clear ( settings );
00778 }
00779 
00780 /**
00781  * Compare two settings
00782  *
00783  * @v a                 Setting to compare
00784  * @v b                 Setting to compare
00785  * @ret 0               Settings are the same
00786  * @ret non-zero        Settings are not the same
00787  */
00788 int setting_cmp ( struct setting *a, struct setting *b ) {
00789 
00790         /* If the settings have tags, compare them */
00791         if ( a->tag && ( a->tag == b->tag ) )
00792                 return 0;
00793 
00794         /* Otherwise, if the settings have names, compare them */
00795         if ( a->name && b->name && a->name[0] )
00796                 return strcmp ( a->name, b->name );
00797 
00798         /* Otherwise, return a non-match */
00799         return ( ! 0 );
00800 }
00801 
00802 /******************************************************************************
00803  *
00804  * Formatted setting routines
00805  *
00806  ******************************************************************************
00807  */
00808 
00809 /**
00810  * Store value of typed setting
00811  *
00812  * @v settings          Settings block
00813  * @v setting           Setting to store
00814  * @v type              Settings type
00815  * @v value             Formatted setting data, or NULL
00816  * @ret rc              Return status code
00817  */
00818 int storef_setting ( struct settings *settings, struct setting *setting,
00819                      const char *value ) {
00820 
00821         /* NULL value implies deletion.  Avoid imposing the burden of
00822          * checking for NULL values on each typed setting's storef()
00823          * method.
00824          */
00825         if ( ! value )
00826                 return delete_setting ( settings, setting );
00827                 
00828         return setting->type->storef ( settings, setting, value );
00829 }
00830 
00831 /**
00832  * Find named setting
00833  *
00834  * @v name              Name
00835  * @ret setting         Named setting, or NULL
00836  */
00837 static struct setting * find_setting ( const char *name ) {
00838         struct setting *setting;
00839 
00840         for_each_table_entry ( setting, SETTINGS ) {
00841                 if ( strcmp ( name, setting->name ) == 0 )
00842                         return setting;
00843         }
00844         return NULL;
00845 }
00846 
00847 /**
00848  * Parse setting name as tag number
00849  *
00850  * @v name              Name
00851  * @ret tag             Tag number, or 0 if not a valid number
00852  */
00853 static unsigned int parse_setting_tag ( const char *name ) {
00854         char *tmp = ( ( char * ) name );
00855         unsigned int tag = 0;
00856 
00857         while ( 1 ) {
00858                 tag = ( ( tag << 8 ) | strtoul ( tmp, &tmp, 0 ) );
00859                 if ( *tmp == 0 )
00860                         return tag;
00861                 if ( *tmp != '.' )
00862                         return 0;
00863                 tmp++;
00864         }
00865 }
00866 
00867 /**
00868  * Find setting type
00869  *
00870  * @v name              Name
00871  * @ret type            Setting type, or NULL
00872  */
00873 static struct setting_type * find_setting_type ( const char *name ) {
00874         struct setting_type *type;
00875 
00876         for_each_table_entry ( type, SETTING_TYPES ) {
00877                 if ( strcmp ( name, type->name ) == 0 )
00878                         return type;
00879         }
00880         return NULL;
00881 }
00882 
00883 /**
00884  * Parse setting name
00885  *
00886  * @v name              Name of setting
00887  * @v get_child         Function to find or create child settings block
00888  * @v settings          Settings block to fill in
00889  * @v setting           Setting to fill in
00890  * @v tmp_name          Buffer for copy of setting name
00891  * @ret rc              Return status code
00892  *
00893  * Interprets a name of the form
00894  * "[settings_name/]tag_name[:type_name]" and fills in the appropriate
00895  * fields.
00896  *
00897  * The @c tmp_name buffer must be large enough to hold a copy of the
00898  * setting name.
00899  */
00900 static int
00901 parse_setting_name ( const char *name,
00902                      struct settings * ( * get_child ) ( struct settings *,
00903                                                          const char * ),
00904                      struct settings **settings, struct setting *setting,
00905                      char *tmp_name ) {
00906         char *settings_name;
00907         char *setting_name;
00908         char *type_name;
00909         struct setting *named_setting;
00910 
00911         /* Set defaults */
00912         *settings = &settings_root;
00913         memset ( setting, 0, sizeof ( *setting ) );
00914         setting->name = "";
00915         setting->type = &setting_type_string;
00916 
00917         /* Split name into "[settings_name/]setting_name[:type_name]" */
00918         strcpy ( tmp_name, name );
00919         if ( ( setting_name = strchr ( tmp_name, '/' ) ) != NULL ) {
00920                 *(setting_name++) = 0;
00921                 settings_name = tmp_name;
00922         } else {
00923                 setting_name = tmp_name;
00924                 settings_name = NULL;
00925         }
00926         if ( ( type_name = strchr ( setting_name, ':' ) ) != NULL )
00927                 *(type_name++) = 0;
00928 
00929         /* Identify settings block, if specified */
00930         if ( settings_name ) {
00931                 *settings = parse_settings_name ( settings_name, get_child );
00932                 if ( *settings == NULL ) {
00933                         DBG ( "Unrecognised settings block \"%s\" in \"%s\"\n",
00934                               settings_name, name );
00935                         return -ENODEV;
00936                 }
00937         }
00938 
00939         /* Identify setting */
00940         if ( ( named_setting = find_setting ( setting_name ) ) != NULL ) {
00941                 /* Matches a defined named setting; use that setting */
00942                 memcpy ( setting, named_setting, sizeof ( *setting ) );
00943         } else if ( ( setting->tag = parse_setting_tag ( setting_name ) ) !=0){
00944                 /* Is a valid numeric tag; use the tag */
00945                 setting->tag |= (*settings)->tag_magic;
00946         } else {
00947                 /* Use the arbitrary name */
00948                 setting->name = setting_name;
00949         }
00950 
00951         /* Identify setting type, if specified */
00952         if ( type_name ) {
00953                 setting->type = find_setting_type ( type_name );
00954                 if ( setting->type == NULL ) {
00955                         DBG ( "Invalid setting type \"%s\" in \"%s\"\n",
00956                               type_name, name );
00957                         return -ENOTSUP;
00958                 }
00959         }
00960 
00961         return 0;
00962 }
00963 
00964 /**
00965  * Parse and store value of named setting
00966  *
00967  * @v name              Name of setting
00968  * @v value             Formatted setting data, or NULL
00969  * @ret rc              Return status code
00970  */
00971 int storef_named_setting ( const char *name, const char *value ) {
00972         struct settings *settings;
00973         struct setting setting;
00974         char tmp_name[ strlen ( name ) + 1 ];
00975         int rc;
00976 
00977         if ( ( rc = parse_setting_name ( name, autovivify_child_settings,
00978                                          &settings, &setting, tmp_name )) != 0)
00979                 return rc;
00980         return storef_setting ( settings, &setting, value );
00981 }
00982 
00983 /**
00984  * Fetch and format value of named setting
00985  *
00986  * @v name              Name of setting
00987  * @v buf               Buffer to contain formatted value
00988  * @v len               Length of buffer
00989  * @ret len             Length of formatted value, or negative error
00990  */
00991 int fetchf_named_setting ( const char *name, char *buf, size_t len ) {
00992         struct settings *settings;
00993         struct setting setting;
00994         char tmp_name[ strlen ( name ) + 1 ];
00995         int rc;
00996 
00997         if ( ( rc = parse_setting_name ( name, find_child_settings,
00998                                          &settings, &setting, tmp_name )) != 0)
00999                 return rc;
01000         return fetchf_setting ( settings, &setting, buf, len );
01001 }
01002 
01003 /******************************************************************************
01004  *
01005  * Setting types
01006  *
01007  ******************************************************************************
01008  */
01009 
01010 /**
01011  * Parse and store value of string setting
01012  *
01013  * @v settings          Settings block
01014  * @v setting           Setting to store
01015  * @v value             Formatted setting data
01016  * @ret rc              Return status code
01017  */
01018 static int storef_string ( struct settings *settings, struct setting *setting,
01019                            const char *value ) {
01020         return store_setting ( settings, setting, value, strlen ( value ) );
01021 }
01022 
01023 /**
01024  * Fetch and format value of string setting
01025  *
01026  * @v settings          Settings block, or NULL to search all blocks
01027  * @v setting           Setting to fetch
01028  * @v buf               Buffer to contain formatted value
01029  * @v len               Length of buffer
01030  * @ret len             Length of formatted value, or negative error
01031  */
01032 static int fetchf_string ( struct settings *settings, struct setting *setting,
01033                            char *buf, size_t len ) {
01034         return fetch_string_setting ( settings, setting, buf, len );
01035 }
01036 
01037 /** A string setting type */
01038 struct setting_type setting_type_string __setting_type = {
01039         .name = "string",
01040         .storef = storef_string,
01041         .fetchf = fetchf_string,
01042 };
01043 
01044 /**
01045  * Parse and store value of URI-encoded string setting
01046  *
01047  * @v settings          Settings block
01048  * @v setting           Setting to store
01049  * @v value             Formatted setting data
01050  * @ret rc              Return status code
01051  */
01052 static int storef_uristring ( struct settings *settings,
01053                               struct setting *setting,
01054                               const char *value ) {
01055         char buf[ strlen ( value ) + 1 ]; /* Decoding never expands string */
01056         size_t len;
01057 
01058         len = uri_decode ( value, buf, sizeof ( buf ) );
01059         return store_setting ( settings, setting, buf, len );
01060 }
01061 
01062 /**
01063  * Fetch and format value of URI-encoded string setting
01064  *
01065  * @v settings          Settings block, or NULL to search all blocks
01066  * @v setting           Setting to fetch
01067  * @v buf               Buffer to contain formatted value
01068  * @v len               Length of buffer
01069  * @ret len             Length of formatted value, or negative error
01070  */
01071 static int fetchf_uristring ( struct settings *settings,
01072                               struct setting *setting,
01073                               char *buf, size_t len ) {
01074         ssize_t raw_len;
01075 
01076         /* We need to always retrieve the full raw string to know the
01077          * length of the encoded string.
01078          */
01079         raw_len = fetch_setting ( settings, setting, NULL, 0 );
01080         if ( raw_len < 0 )
01081                 return raw_len;
01082 
01083         {
01084                 char raw_buf[ raw_len + 1 ];
01085        
01086                 fetch_string_setting ( settings, setting, raw_buf,
01087                                        sizeof ( raw_buf ) );
01088                 return uri_encode ( raw_buf, buf, len, URI_FRAGMENT );
01089         }
01090 }
01091 
01092 /** A URI-encoded string setting type */
01093 struct setting_type setting_type_uristring __setting_type = {
01094         .name = "uristring",
01095         .storef = storef_uristring,
01096         .fetchf = fetchf_uristring,
01097 };
01098 
01099 /**
01100  * Parse and store value of IPv4 address setting
01101  *
01102  * @v settings          Settings block
01103  * @v setting           Setting to store
01104  * @v value             Formatted setting data
01105  * @ret rc              Return status code
01106  */
01107 static int storef_ipv4 ( struct settings *settings, struct setting *setting,
01108                          const char *value ) {
01109         struct in_addr ipv4;
01110 
01111         if ( inet_aton ( value, &ipv4 ) == 0 )
01112                 return -EINVAL;
01113         return store_setting ( settings, setting, &ipv4, sizeof ( ipv4 ) );
01114 }
01115 
01116 /**
01117  * Fetch and format value of IPv4 address setting
01118  *
01119  * @v settings          Settings block, or NULL to search all blocks
01120  * @v setting           Setting to fetch
01121  * @v buf               Buffer to contain formatted value
01122  * @v len               Length of buffer
01123  * @ret len             Length of formatted value, or negative error
01124  */
01125 static int fetchf_ipv4 ( struct settings *settings, struct setting *setting,
01126                          char *buf, size_t len ) {
01127         struct in_addr ipv4;
01128         int raw_len;
01129 
01130         if ( ( raw_len = fetch_ipv4_setting ( settings, setting, &ipv4 ) ) < 0)
01131                 return raw_len;
01132         return snprintf ( buf, len, "%s", inet_ntoa ( ipv4 ) );
01133 }
01134 
01135 /** An IPv4 address setting type */
01136 struct setting_type setting_type_ipv4 __setting_type = {
01137         .name = "ipv4",
01138         .storef = storef_ipv4,
01139         .fetchf = fetchf_ipv4,
01140 };
01141 
01142 /**
01143  * Parse and store value of integer setting
01144  *
01145  * @v settings          Settings block
01146  * @v setting           Setting to store
01147  * @v value             Formatted setting data
01148  * @v size              Integer size, in bytes
01149  * @ret rc              Return status code
01150  */
01151 static int storef_int ( struct settings *settings, struct setting *setting,
01152                         const char *value, unsigned int size ) {
01153         union {
01154                 uint32_t num;
01155                 uint8_t bytes[4];
01156         } u;
01157         char *endp;
01158 
01159         u.num = htonl ( strtoul ( value, &endp, 0 ) );
01160         if ( *endp )
01161                 return -EINVAL;
01162         return store_setting ( settings, setting, 
01163                                &u.bytes[ sizeof ( u ) - size ], size );
01164 }
01165 
01166 /**
01167  * Parse and store value of 8-bit integer setting
01168  *
01169  * @v settings          Settings block
01170  * @v setting           Setting to store
01171  * @v value             Formatted setting data
01172  * @v size              Integer size, in bytes
01173  * @ret rc              Return status code
01174  */
01175 static int storef_int8 ( struct settings *settings, struct setting *setting,
01176                          const char *value ) {
01177         return storef_int ( settings, setting, value, 1 );
01178 }
01179 
01180 /**
01181  * Parse and store value of 16-bit integer setting
01182  *
01183  * @v settings          Settings block
01184  * @v setting           Setting to store
01185  * @v value             Formatted setting data
01186  * @v size              Integer size, in bytes
01187  * @ret rc              Return status code
01188  */
01189 static int storef_int16 ( struct settings *settings, struct setting *setting,
01190                           const char *value ) {
01191         return storef_int ( settings, setting, value, 2 );
01192 }
01193 
01194 /**
01195  * Parse and store value of 32-bit integer setting
01196  *
01197  * @v settings          Settings block
01198  * @v setting           Setting to store
01199  * @v value             Formatted setting data
01200  * @v size              Integer size, in bytes
01201  * @ret rc              Return status code
01202  */
01203 static int storef_int32 ( struct settings *settings, struct setting *setting,
01204                           const char *value ) {
01205         return storef_int ( settings, setting, value, 4 );
01206 }
01207 
01208 /**
01209  * Fetch and format value of signed integer setting
01210  *
01211  * @v settings          Settings block, or NULL to search all blocks
01212  * @v setting           Setting to fetch
01213  * @v buf               Buffer to contain formatted value
01214  * @v len               Length of buffer
01215  * @ret len             Length of formatted value, or negative error
01216  */
01217 static int fetchf_int ( struct settings *settings, struct setting *setting,
01218                         char *buf, size_t len ) {
01219         long value;
01220         int rc;
01221 
01222         if ( ( rc = fetch_int_setting ( settings, setting, &value ) ) < 0 )
01223                 return rc;
01224         return snprintf ( buf, len, "%ld", value );
01225 }
01226 
01227 /**
01228  * Fetch and format value of unsigned integer setting
01229  *
01230  * @v settings          Settings block, or NULL to search all blocks
01231  * @v setting           Setting to fetch
01232  * @v buf               Buffer to contain formatted value
01233  * @v len               Length of buffer
01234  * @ret len             Length of formatted value, or negative error
01235  */
01236 static int fetchf_uint ( struct settings *settings, struct setting *setting,
01237                          char *buf, size_t len ) {
01238         unsigned long value;
01239         int rc;
01240 
01241         if ( ( rc = fetch_uint_setting ( settings, setting, &value ) ) < 0 )
01242                 return rc;
01243         return snprintf ( buf, len, "%#lx", value );
01244 }
01245 
01246 /** A signed 8-bit integer setting type */
01247 struct setting_type setting_type_int8 __setting_type = {
01248         .name = "int8",
01249         .storef = storef_int8,
01250         .fetchf = fetchf_int,
01251 };
01252 
01253 /** A signed 16-bit integer setting type */
01254 struct setting_type setting_type_int16 __setting_type = {
01255         .name = "int16",
01256         .storef = storef_int16,
01257         .fetchf = fetchf_int,
01258 };
01259 
01260 /** A signed 32-bit integer setting type */
01261 struct setting_type setting_type_int32 __setting_type = {
01262         .name = "int32",
01263         .storef = storef_int32,
01264         .fetchf = fetchf_int,
01265 };
01266 
01267 /** An unsigned 8-bit integer setting type */
01268 struct setting_type setting_type_uint8 __setting_type = {
01269         .name = "uint8",
01270         .storef = storef_int8,
01271         .fetchf = fetchf_uint,
01272 };
01273 
01274 /** An unsigned 16-bit integer setting type */
01275 struct setting_type setting_type_uint16 __setting_type = {
01276         .name = "uint16",
01277         .storef = storef_int16,
01278         .fetchf = fetchf_uint,
01279 };
01280 
01281 /** An unsigned 32-bit integer setting type */
01282 struct setting_type setting_type_uint32 __setting_type = {
01283         .name = "uint32",
01284         .storef = storef_int32,
01285         .fetchf = fetchf_uint,
01286 };
01287 
01288 /**
01289  * Parse and store value of hex string setting
01290  *
01291  * @v settings          Settings block
01292  * @v setting           Setting to store
01293  * @v value             Formatted setting data
01294  * @ret rc              Return status code
01295  */
01296 static int storef_hex ( struct settings *settings, struct setting *setting,
01297                         const char *value ) {
01298         char *ptr = ( char * ) value;
01299         uint8_t bytes[ strlen ( value ) ]; /* cannot exceed strlen(value) */
01300         unsigned int len = 0;
01301 
01302         while ( 1 ) {
01303                 bytes[len++] = strtoul ( ptr, &ptr, 16 );
01304                 switch ( *ptr ) {
01305                 case '\0' :
01306                         return store_setting ( settings, setting, bytes, len );
01307                 case ':' :
01308                         ptr++;
01309                         break;
01310                 default :
01311                         return -EINVAL;
01312                 }
01313         }
01314 }
01315 
01316 /**
01317  * Fetch and format value of hex string setting
01318  *
01319  * @v settings          Settings block, or NULL to search all blocks
01320  * @v setting           Setting to fetch
01321  * @v buf               Buffer to contain formatted value
01322  * @v len               Length of buffer
01323  * @ret len             Length of formatted value, or negative error
01324  */
01325 static int fetchf_hex ( struct settings *settings, struct setting *setting,
01326                         char *buf, size_t len ) {
01327         int raw_len;
01328         int check_len;
01329         int used = 0;
01330         int i;
01331 
01332         raw_len = fetch_setting_len ( settings, setting );
01333         if ( raw_len < 0 )
01334                 return raw_len;
01335 
01336         {
01337                 uint8_t raw[raw_len];
01338 
01339                 check_len = fetch_setting ( settings, setting, raw,
01340                                             sizeof ( raw ) );
01341                 if ( check_len < 0 )
01342                         return check_len;
01343                 assert ( check_len == raw_len );
01344                 
01345                 if ( len )
01346                         buf[0] = 0; /* Ensure that a terminating NUL exists */
01347                 for ( i = 0 ; i < raw_len ; i++ ) {
01348                         used += ssnprintf ( ( buf + used ), ( len - used ),
01349                                             "%s%02x", ( used ? ":" : "" ),
01350                                             raw[i] );
01351                 }
01352                 return used;
01353         }
01354 }
01355 
01356 /** A hex-string setting */
01357 struct setting_type setting_type_hex __setting_type = {
01358         .name = "hex",
01359         .storef = storef_hex,
01360         .fetchf = fetchf_hex,
01361 };
01362 
01363 /**
01364  * Parse and store value of UUID setting
01365  *
01366  * @v settings          Settings block
01367  * @v setting           Setting to store
01368  * @v value             Formatted setting data
01369  * @ret rc              Return status code
01370  */
01371 static int storef_uuid ( struct settings *settings __unused,
01372                          struct setting *setting __unused,
01373                          const char *value __unused ) {
01374         return -ENOTSUP;
01375 }
01376 
01377 /**
01378  * Fetch and format value of UUID setting
01379  *
01380  * @v settings          Settings block, or NULL to search all blocks
01381  * @v setting           Setting to fetch
01382  * @v buf               Buffer to contain formatted value
01383  * @v len               Length of buffer
01384  * @ret len             Length of formatted value, or negative error
01385  */
01386 static int fetchf_uuid ( struct settings *settings, struct setting *setting,
01387                          char *buf, size_t len ) {
01388         union uuid uuid;
01389         int raw_len;
01390 
01391         if ( ( raw_len = fetch_uuid_setting ( settings, setting, &uuid ) ) < 0)
01392                 return raw_len;
01393         return snprintf ( buf, len, "%s", uuid_ntoa ( &uuid ) );
01394 }
01395 
01396 /** UUID setting type */
01397 struct setting_type setting_type_uuid __setting_type = {
01398         .name = "uuid",
01399         .storef = storef_uuid,
01400         .fetchf = fetchf_uuid,
01401 };
01402 
01403 /******************************************************************************
01404  *
01405  * Settings
01406  *
01407  ******************************************************************************
01408  */
01409 
01410 /** Hostname setting */
01411 struct setting hostname_setting __setting = {
01412         .name = "hostname",
01413         .description = "Host name",
01414         .tag = DHCP_HOST_NAME,
01415         .type = &setting_type_string,
01416 };
01417 
01418 /** Filename setting */
01419 struct setting filename_setting __setting = {
01420         .name = "filename",
01421         .description = "Boot filename",
01422         .tag = DHCP_BOOTFILE_NAME,
01423         .type = &setting_type_string,
01424 };
01425 
01426 /** Root path setting */
01427 struct setting root_path_setting __setting = {
01428         .name = "root-path",
01429         .description = "iSCSI root path",
01430         .tag = DHCP_ROOT_PATH,
01431         .type = &setting_type_string,
01432 };
01433 
01434 /** Username setting */
01435 struct setting username_setting __setting = {
01436         .name = "username",
01437         .description = "User name",
01438         .tag = DHCP_EB_USERNAME,
01439         .type = &setting_type_string,
01440 };
01441 
01442 /** Password setting */
01443 struct setting password_setting __setting = {
01444         .name = "password",
01445         .description = "Password",
01446         .tag = DHCP_EB_PASSWORD,
01447         .type = &setting_type_string,
01448 };
01449 
01450 /** Priority setting */
01451 struct setting priority_setting __setting = {
01452         .name = "priority",
01453         .description = "Priority of these settings",
01454         .tag = DHCP_EB_PRIORITY,
01455         .type = &setting_type_int8,
01456 };

Generated on Tue Apr 6 20:00:52 2010 for gPXE by  doxygen 1.5.7.1