Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2008 Michael Brown <mbrown (at) fensystems.co.uk>.
      3  *
      4  * This program is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU General Public License as
      6  * published by the Free Software Foundation; either version 2 of the
      7  * License, or any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful, but
     10  * WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program; if not, write to the Free Software
     16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     17  */
     18 
     19 FILE_LICENCE ( GPL2_OR_LATER );
     20 
     21 #include <stdint.h>
     22 #include <stdlib.h>
     23 #include <stdio.h>
     24 #include <string.h>
     25 #include <strings.h>
     26 #include <byteswap.h>
     27 #include <errno.h>
     28 #include <assert.h>
     29 #include <gpxe/in.h>
     30 #include <gpxe/vsprintf.h>
     31 #include <gpxe/dhcp.h>
     32 #include <gpxe/uuid.h>
     33 #include <gpxe/uri.h>
     34 #include <gpxe/settings.h>
     35 
     36 /** @file
     37  *
     38  * Configuration settings
     39  *
     40  */
     41 
     42 /******************************************************************************
     43  *
     44  * Generic settings blocks
     45  *
     46  ******************************************************************************
     47  */
     48 
     49 /**
     50  * A generic setting
     51  *
     52  */
     53 struct generic_setting {
     54 	/** List of generic settings */
     55 	struct list_head list;
     56 	/** Setting */
     57 	struct setting setting;
     58 	/** Size of setting name */
     59 	size_t name_len;
     60 	/** Size of setting data */
     61 	size_t data_len;
     62 };
     63 
     64 /**
     65  * Get generic setting name
     66  *
     67  * @v generic		Generic setting
     68  * @ret name		Generic setting name
     69  */
     70 static inline void * generic_setting_name ( struct generic_setting *generic ) {
     71 	return ( ( ( void * ) generic ) + sizeof ( *generic ) );
     72 }
     73 
     74 /**
     75  * Get generic setting data
     76  *
     77  * @v generic		Generic setting
     78  * @ret data		Generic setting data
     79  */
     80 static inline void * generic_setting_data ( struct generic_setting *generic ) {
     81 	return ( ( ( void * ) generic ) + sizeof ( *generic ) +
     82 		 generic->name_len );
     83 }
     84 
     85 /**
     86  * Find generic setting
     87  *
     88  * @v generics		Generic settings block
     89  * @v setting		Setting to find
     90  * @ret generic		Generic setting, or NULL
     91  */
     92 static struct generic_setting *
     93 find_generic_setting ( struct generic_settings *generics,
     94 		       struct setting *setting ) {
     95 	struct generic_setting *generic;
     96 
     97 	list_for_each_entry ( generic, &generics->list, list ) {
     98 		if ( setting_cmp ( &generic->setting, setting ) == 0 )
     99 			return generic;
    100 	}
    101 	return NULL;
    102 }
    103 
    104 /**
    105  * Store value of generic setting
    106  *
    107  * @v settings		Settings block
    108  * @v setting		Setting to store
    109  * @v data		Setting data, or NULL to clear setting
    110  * @v len		Length of setting data
    111  * @ret rc		Return status code
    112  */
    113 int generic_settings_store ( struct settings *settings,
    114 			     struct setting *setting,
    115 			     const void *data, size_t len ) {
    116 	struct generic_settings *generics =
    117 		container_of ( settings, struct generic_settings, settings );
    118 	struct generic_setting *old;
    119 	struct generic_setting *new = NULL;
    120 	size_t name_len;
    121 
    122 	/* Identify existing generic setting, if any */
    123 	old = find_generic_setting ( generics, setting );
    124 
    125 	/* Create new generic setting, if required */
    126 	if ( len ) {
    127 		/* Allocate new generic setting */
    128 		name_len = ( strlen ( setting->name ) + 1 );
    129 		new = zalloc ( sizeof ( *new ) + name_len + len );
    130 		if ( ! new )
    131 			return -ENOMEM;
    132 
    133 		/* Populate new generic setting */
    134 		new->name_len = name_len;
    135 		new->data_len = len;
    136 		memcpy ( &new->setting, setting, sizeof ( new->setting ) );
    137 		new->setting.name = generic_setting_name ( new );
    138 		memcpy ( generic_setting_name ( new ),
    139 			 setting->name, name_len );
    140 		memcpy ( generic_setting_data ( new ), data, len );
    141 	}
    142 
    143 	/* Delete existing generic setting, if any */
    144 	if ( old ) {
    145 		list_del ( &old->list );
    146 		free ( old );
    147 	}
    148 
    149 	/* Add new setting to list, if any */
    150 	if ( new )
    151 		list_add ( &new->list, &generics->list );
    152 
    153 	return 0;
    154 }
    155 
    156 /**
    157  * Fetch value of generic setting
    158  *
    159  * @v settings		Settings block
    160  * @v setting		Setting to fetch
    161  * @v data		Buffer to fill with setting data
    162  * @v len		Length of buffer
    163  * @ret len		Length of setting data, or negative error
    164  */
    165 int generic_settings_fetch ( struct settings *settings,
    166 			     struct setting *setting,
    167 			     void *data, size_t len ) {
    168 	struct generic_settings *generics =
    169 		container_of ( settings, struct generic_settings, settings );
    170 	struct generic_setting *generic;
    171 
    172 	/* Find generic setting */
    173 	generic = find_generic_setting ( generics, setting );
    174 	if ( ! generic )
    175 		return -ENOENT;
    176 
    177 	/* Copy out generic setting data */
    178 	if ( len > generic->data_len )
    179 		len = generic->data_len;
    180 	memcpy ( data, generic_setting_data ( generic ), len );
    181 	return generic->data_len;
    182 }
    183 
    184 /**
    185  * Clear generic settings block
    186  *
    187  * @v settings		Settings block
    188  */
    189 void generic_settings_clear ( struct settings *settings ) {
    190 	struct generic_settings *generics =
    191 		container_of ( settings, struct generic_settings, settings );
    192 	struct generic_setting *generic;
    193 	struct generic_setting *tmp;
    194 
    195 	list_for_each_entry_safe ( generic, tmp, &generics->list, list ) {
    196 		list_del ( &generic->list );
    197 		free ( generic );
    198 	}
    199 	assert ( list_empty ( &generics->list ) );
    200 }
    201 
    202 /** Generic settings operations */
    203 struct settings_operations generic_settings_operations = {
    204 	.store = generic_settings_store,
    205 	.fetch = generic_settings_fetch,
    206 	.clear = generic_settings_clear,
    207 };
    208 
    209 /******************************************************************************
    210  *
    211  * Registered settings blocks
    212  *
    213  ******************************************************************************
    214  */
    215 
    216 /** Root generic settings block */
    217 struct generic_settings generic_settings_root = {
    218 	.settings = {
    219 		.refcnt = NULL,
    220 		.name = "",
    221 		.siblings =
    222 		    LIST_HEAD_INIT ( generic_settings_root.settings.siblings ),
    223 		.children =
    224 		    LIST_HEAD_INIT ( generic_settings_root.settings.children ),
    225 		.op = &generic_settings_operations,
    226 	},
    227 	.list = LIST_HEAD_INIT ( generic_settings_root.list ),
    228 };
    229 
    230 /** Root settings block */
    231 #define settings_root generic_settings_root.settings
    232 
    233 /**
    234  * Find child named settings block
    235  *
    236  * @v parent		Parent settings block
    237  * @v name		Name within this parent
    238  * @ret settings	Settings block, or NULL
    239  */
    240 static struct settings * find_child_settings ( struct settings *parent,
    241 					       const char *name ) {
    242 	struct settings *settings;
    243 
    244 	/* Treat empty name as meaning "this block" */
    245 	if ( ! *name )
    246 		return parent;
    247 
    248 	/* Look for child with matching name */
    249 	list_for_each_entry ( settings, &parent->children, siblings ) {
    250 		if ( strcmp ( settings->name, name ) == 0 )
    251 			return settings;
    252 	}
    253 
    254 	return NULL;
    255 }
    256 
    257 /**
    258  * Find or create child named settings block
    259  *
    260  * @v parent		Parent settings block
    261  * @v name		Name within this parent
    262  * @ret settings	Settings block, or NULL
    263  */
    264 static struct settings * autovivify_child_settings ( struct settings *parent,
    265 						     const char *name ) {
    266 	struct {
    267 		struct generic_settings generic;
    268 		char name[ strlen ( name ) + 1 /* NUL */ ];
    269 	} *new_child;
    270 	struct settings *settings;
    271 
    272 	/* Return existing settings, if existent */
    273 	if ( ( settings = find_child_settings ( parent, name ) ) != NULL )
    274 		return settings;
    275 
    276 	/* Create new generic settings block */
    277 	new_child = zalloc ( sizeof ( *new_child ) );
    278 	if ( ! new_child ) {
    279 		DBGC ( parent, "Settings %p could not create child %s\n",
    280 		       parent, name );
    281 		return NULL;
    282 	}
    283 	memcpy ( new_child->name, name, sizeof ( new_child->name ) );
    284 	generic_settings_init ( &new_child->generic, NULL, new_child->name );
    285 	settings = &new_child->generic.settings;
    286 	register_settings ( settings, parent );
    287 	return settings;
    288 }
    289 
    290 /**
    291  * Return settings block name (for debug only)
    292  *
    293  * @v settings		Settings block
    294  * @ret name		Settings block name
    295  */
    296 static const char * settings_name ( struct settings *settings ) {
    297 	static char buf[64];
    298 	char tmp[ sizeof ( buf ) ];
    299 	int count;
    300 
    301 	for ( count = 0 ; settings ; settings = settings->parent ) {
    302 		memcpy ( tmp, buf, sizeof ( tmp ) );
    303 		snprintf ( buf, sizeof ( buf ), "%s%c%s", settings->name,
    304 			   ( count++ ? '.' : '\0' ), tmp );
    305 	}
    306 	return ( buf + 1 );
    307 }
    308 
    309 /**
    310  * Parse settings block name
    311  *
    312  * @v name		Name
    313  * @v get_child		Function to find or create child settings block
    314  * @ret settings	Settings block, or NULL
    315  */
    316 static struct settings *
    317 parse_settings_name ( const char *name,
    318 		      struct settings * ( * get_child ) ( struct settings *,
    319 							  const char * ) ) {
    320 	struct settings *settings = &settings_root;
    321 	char name_copy[ strlen ( name ) + 1 ];
    322 	char *subname;
    323 	char *remainder;
    324 
    325 	/* Create modifiable copy of name */
    326 	memcpy ( name_copy, name, sizeof ( name_copy ) );
    327 	remainder = name_copy;
    328 
    329 	/* Parse each name component in turn */
    330 	while ( remainder ) {
    331 		struct net_device *netdev;
    332 
    333 		subname = remainder;
    334 		remainder = strchr ( subname, '.' );
    335 		if ( remainder )
    336 			*(remainder++) = '\0';
    337 
    338 		/* Special case "netX" root settings block */
    339 		if ( ( subname == name_copy ) && ! strcmp ( subname, "netX" ) &&
    340 		     ( ( netdev = last_opened_netdev() ) != NULL ) )
    341 			settings = get_child ( settings, netdev->name );
    342 		else
    343 			settings = get_child ( settings, subname );
    344 
    345 		if ( ! settings )
    346 			break;
    347 	}
    348 
    349 	return settings;
    350 }
    351 
    352 /**
    353  * Find named settings block
    354  *
    355  * @v name		Name
    356  * @ret settings	Settings block, or NULL
    357  */
    358 struct settings * find_settings ( const char *name ) {
    359 
    360 	return parse_settings_name ( name, find_child_settings );
    361 }
    362 
    363 /**
    364  * Apply all settings
    365  *
    366  * @ret rc		Return status code
    367  */
    368 static int apply_settings ( void ) {
    369 	struct settings_applicator *applicator;
    370 	int rc;
    371 
    372 	/* Call all settings applicators */
    373 	for_each_table_entry ( applicator, SETTINGS_APPLICATORS ) {
    374 		if ( ( rc = applicator->apply() ) != 0 ) {
    375 			DBG ( "Could not apply settings using applicator "
    376 			      "%p: %s\n", applicator, strerror ( rc ) );
    377 			return rc;
    378 		}
    379 	}
    380 
    381 	return 0;
    382 }
    383 
    384 /**
    385  * Reprioritise settings
    386  *
    387  * @v settings		Settings block
    388  *
    389  * Reorders the settings block amongst its siblings according to its
    390  * priority.
    391  */
    392 static void reprioritise_settings ( struct settings *settings ) {
    393 	struct settings *parent = settings->parent;
    394 	long priority;
    395 	struct settings *tmp;
    396 	long tmp_priority;
    397 
    398 	/* Stop when we reach the top of the tree */
    399 	if ( ! parent )
    400 		return;
    401 
    402 	/* Read priority, if present */
    403 	priority = fetch_intz_setting ( settings, &priority_setting );
    404 
    405 	/* Remove from siblings list */
    406 	list_del ( &settings->siblings );
    407 
    408 	/* Reinsert after any existing blocks which have a higher priority */
    409 	list_for_each_entry ( tmp, &parent->children, siblings ) {
    410 		tmp_priority = fetch_intz_setting ( tmp, &priority_setting );
    411 		if ( priority > tmp_priority )
    412 			break;
    413 	}
    414 	list_add_tail ( &settings->siblings, &tmp->siblings );
    415 
    416 	/* Recurse up the tree */
    417 	reprioritise_settings ( parent );
    418 }
    419 
    420 /**
    421  * Register settings block
    422  *
    423  * @v settings		Settings block
    424  * @v parent		Parent settings block, or NULL
    425  * @ret rc		Return status code
    426  */
    427 int register_settings ( struct settings *settings, struct settings *parent ) {
    428 	struct settings *old_settings;
    429 
    430 	/* NULL parent => add to settings root */
    431 	assert ( settings != NULL );
    432 	if ( parent == NULL )
    433 		parent = &settings_root;
    434 
    435 	/* Remove any existing settings with the same name */
    436 	if ( ( old_settings = find_child_settings ( parent, settings->name ) ))
    437 		unregister_settings ( old_settings );
    438 
    439 	/* Add to list of settings */
    440 	ref_get ( settings->refcnt );
    441 	ref_get ( parent->refcnt );
    442 	settings->parent = parent;
    443 	list_add_tail ( &settings->siblings, &parent->children );
    444 	DBGC ( settings, "Settings %p (\"%s\") registered\n",
    445 	       settings, settings_name ( settings ) );
    446 
    447 	/* Fix up settings priority */
    448 	reprioritise_settings ( settings );
    449 
    450 	/* Apply potentially-updated settings */
    451 	apply_settings();
    452 
    453 	return 0;
    454 }
    455 
    456 /**
    457  * Unregister settings block
    458  *
    459  * @v settings		Settings block
    460  */
    461 void unregister_settings ( struct settings *settings ) {
    462 
    463 	DBGC ( settings, "Settings %p (\"%s\") unregistered\n",
    464 	       settings, settings_name ( settings ) );
    465 
    466 	/* Remove from list of settings */
    467 	ref_put ( settings->refcnt );
    468 	ref_put ( settings->parent->refcnt );
    469 	settings->parent = NULL;
    470 	list_del ( &settings->siblings );
    471 
    472 	/* Apply potentially-updated settings */
    473 	apply_settings();
    474 }
    475 
    476 /******************************************************************************
    477  *
    478  * Core settings routines
    479  *
    480  ******************************************************************************
    481  */
    482 
    483 /**
    484  * Store value of setting
    485  *
    486  * @v settings		Settings block, or NULL
    487  * @v setting		Setting to store
    488  * @v data		Setting data, or NULL to clear setting
    489  * @v len		Length of setting data
    490  * @ret rc		Return status code
    491  */
    492 int store_setting ( struct settings *settings, struct setting *setting,
    493 		    const void *data, size_t len ) {
    494 	int rc;
    495 
    496 	/* NULL settings implies storing into the global settings root */
    497 	if ( ! settings )
    498 		settings = &settings_root;
    499 
    500 	/* Sanity check */
    501 	if ( ! settings->op->store )
    502 		return -ENOTSUP;
    503 
    504 	/* Store setting */
    505 	if ( ( rc = settings->op->store ( settings, setting,
    506 					  data, len ) ) != 0 )
    507 		return rc;
    508 
    509 	/* Reprioritise settings if necessary */
    510 	if ( setting_cmp ( setting, &priority_setting ) == 0 )
    511 		reprioritise_settings ( settings );
    512 
    513 	/* If these settings are registered, apply potentially-updated
    514 	 * settings
    515 	 */
    516 	for ( ; settings ; settings = settings->parent ) {
    517 		if ( settings == &settings_root ) {
    518 			if ( ( rc = apply_settings() ) != 0 )
    519 				return rc;
    520 			break;
    521 		}
    522 	}
    523 
    524 	return 0;
    525 }
    526 
    527 /**
    528  * Fetch value of setting
    529  *
    530  * @v settings		Settings block, or NULL to search all blocks
    531  * @v setting		Setting to fetch
    532  * @v data		Buffer to fill with setting data
    533  * @v len		Length of buffer
    534  * @ret len		Length of setting data, or negative error
    535  *
    536  * The actual length of the setting will be returned even if
    537  * the buffer was too small.
    538  */
    539 int fetch_setting ( struct settings *settings, struct setting *setting,
    540 		    void *data, size_t len ) {
    541 	struct settings *child;
    542 	int ret;
    543 
    544 	/* Avoid returning uninitialised data on error */
    545 	memset ( data, 0, len );
    546 
    547 	/* NULL settings implies starting at the global settings root */
    548 	if ( ! settings )
    549 		settings = &settings_root;
    550 
    551 	/* Sanity check */
    552 	if ( ! settings->op->fetch )
    553 		return -ENOTSUP;
    554 
    555 	/* Try this block first */
    556 	if ( ( ret = settings->op->fetch ( settings, setting,
    557 					   data, len ) ) >= 0 )
    558 		return ret;
    559 
    560 	/* Recurse into each child block in turn */
    561 	list_for_each_entry ( child, &settings->children, siblings ) {
    562 		if ( ( ret = fetch_setting ( child, setting,
    563 					     data, len ) ) >= 0 )
    564 			return ret;
    565 	}
    566 
    567 	return -ENOENT;
    568 }
    569 
    570 /**
    571  * Fetch length of setting
    572  *
    573  * @v settings		Settings block, or NULL to search all blocks
    574  * @v setting		Setting to fetch
    575  * @ret len		Length of setting data, or negative error
    576  *
    577  * This function can also be used as an existence check for the
    578  * setting.
    579  */
    580 int fetch_setting_len ( struct settings *settings, struct setting *setting ) {
    581 	return fetch_setting ( settings, setting, NULL, 0 );
    582 }
    583 
    584 /**
    585  * Fetch value of string setting
    586  *
    587  * @v settings		Settings block, or NULL to search all blocks
    588  * @v setting		Setting to fetch
    589  * @v data		Buffer to fill with setting string data
    590  * @v len		Length of buffer
    591  * @ret len		Length of string setting, or negative error
    592  *
    593  * The resulting string is guaranteed to be correctly NUL-terminated.
    594  * The returned length will be the length of the underlying setting
    595  * data.
    596  */
    597 int fetch_string_setting ( struct settings *settings, struct setting *setting,
    598 			   char *data, size_t len ) {
    599 	memset ( data, 0, len );
    600 	return fetch_setting ( settings, setting, data,
    601 			       ( ( len > 0 ) ? ( len - 1 ) : 0 ) );
    602 }
    603 
    604 /**
    605  * Fetch value of string setting
    606  *
    607  * @v settings		Settings block, or NULL to search all blocks
    608  * @v setting		Setting to fetch
    609  * @v data		Buffer to allocate and fill with setting string data
    610  * @ret len		Length of string setting, or negative error
    611  *
    612  * The resulting string is guaranteed to be correctly NUL-terminated.
    613  * The returned length will be the length of the underlying setting
    614  * data.  The caller is responsible for eventually freeing the
    615  * allocated buffer.
    616  */
    617 int fetch_string_setting_copy ( struct settings *settings,
    618 				struct setting *setting,
    619 				char **data ) {
    620 	int len;
    621 	int check_len = 0;
    622 
    623 	len = fetch_setting_len ( settings, setting );
    624 	if ( len < 0 )
    625 		return len;
    626 
    627 	*data = malloc ( len + 1 );
    628 	if ( ! *data )
    629 		return -ENOMEM;
    630 
    631 	check_len = fetch_string_setting ( settings, setting, *data,
    632 					   ( len + 1 ) );
    633 	assert ( check_len == len );
    634 	return len;
    635 }
    636 
    637 /**
    638  * Fetch value of IPv4 address setting
    639  *
    640  * @v settings		Settings block, or NULL to search all blocks
    641  * @v setting		Setting to fetch
    642  * @v inp		IPv4 address to fill in
    643  * @ret len		Length of setting, or negative error
    644  */
    645 int fetch_ipv4_setting ( struct settings *settings, struct setting *setting,
    646 			 struct in_addr *inp ) {
    647 	int len;
    648 
    649 	len = fetch_setting ( settings, setting, inp, sizeof ( *inp ) );
    650 	if ( len < 0 )
    651 		return len;
    652 	if ( len < ( int ) sizeof ( *inp ) )
    653 		return -ERANGE;
    654 	return len;
    655 }
    656 
    657 /**
    658  * Fetch value of signed integer setting
    659  *
    660  * @v settings		Settings block, or NULL to search all blocks
    661  * @v setting		Setting to fetch
    662  * @v value		Integer value to fill in
    663  * @ret len		Length of setting, or negative error
    664  */
    665 int fetch_int_setting ( struct settings *settings, struct setting *setting,
    666 			long *value ) {
    667 	union {
    668 		uint8_t u8[ sizeof ( long ) ];
    669 		int8_t s8[ sizeof ( long ) ];
    670 	} buf;
    671 	int len;
    672 	int i;
    673 
    674 	/* Avoid returning uninitialised data on error */
    675 	*value = 0;
    676 
    677 	/* Fetch raw (network-ordered, variable-length) setting */
    678 	len = fetch_setting ( settings, setting, &buf, sizeof ( buf ) );
    679 	if ( len < 0 )
    680 		return len;
    681 	if ( len > ( int ) sizeof ( buf ) )
    682 		return -ERANGE;
    683 
    684 	/* Convert to host-ordered signed long */
    685 	*value = ( ( buf.s8[0] >= 0 ) ? 0 : -1L );
    686 	for ( i = 0 ; i < len ; i++ ) {
    687 		*value = ( ( *value << 8 ) | buf.u8[i] );
    688 	}
    689 
    690 	return len;
    691 }
    692 
    693 /**
    694  * Fetch value of unsigned integer setting
    695  *
    696  * @v settings		Settings block, or NULL to search all blocks
    697  * @v setting		Setting to fetch
    698  * @v value		Integer value to fill in
    699  * @ret len		Length of setting, or negative error
    700  */
    701 int fetch_uint_setting ( struct settings *settings, struct setting *setting,
    702 			 unsigned long *value ) {
    703 	long svalue;
    704 	int len;
    705 
    706 	/* Avoid returning uninitialised data on error */
    707 	*value = 0;
    708 
    709 	/* Fetch as a signed long */
    710 	len = fetch_int_setting ( settings, setting, &svalue );
    711 	if ( len < 0 )
    712 		return len;
    713 
    714 	/* Mask off sign-extended bits */
    715 	assert ( len <= ( int ) sizeof ( long ) );
    716 	*value = ( svalue & ( -1UL >> ( 8 * ( sizeof ( long ) - len ) ) ) );
    717 
    718 	return len;
    719 }
    720 
    721 /**
    722  * Fetch value of signed integer setting, or zero
    723  *
    724  * @v settings		Settings block, or NULL to search all blocks
    725  * @v setting		Setting to fetch
    726  * @ret value		Setting value, or zero
    727  */
    728 long fetch_intz_setting ( struct settings *settings, struct setting *setting ){
    729 	long value;
    730 
    731 	fetch_int_setting ( settings, setting, &value );
    732 	return value;
    733 }
    734 
    735 /**
    736  * Fetch value of unsigned integer setting, or zero
    737  *
    738  * @v settings		Settings block, or NULL to search all blocks
    739  * @v setting		Setting to fetch
    740  * @ret value		Setting value, or zero
    741  */
    742 unsigned long fetch_uintz_setting ( struct settings *settings,
    743 				    struct setting *setting ) {
    744 	unsigned long value;
    745 
    746 	fetch_uint_setting ( settings, setting, &value );
    747 	return value;
    748 }
    749 
    750 /**
    751  * Fetch value of UUID setting
    752  *
    753  * @v settings		Settings block, or NULL to search all blocks
    754  * @v setting		Setting to fetch
    755  * @v uuid		UUID to fill in
    756  * @ret len		Length of setting, or negative error
    757  */
    758 int fetch_uuid_setting ( struct settings *settings, struct setting *setting,
    759 			 union uuid *uuid ) {
    760 	int len;
    761 
    762 	len = fetch_setting ( settings, setting, uuid, sizeof ( *uuid ) );
    763 	if ( len < 0 )
    764 		return len;
    765 	if ( len != sizeof ( *uuid ) )
    766 		return -ERANGE;
    767 	return len;
    768 }
    769 
    770 /**
    771  * Clear settings block
    772  *
    773  * @v settings		Settings block
    774  */
    775 void clear_settings ( struct settings *settings ) {
    776 	if ( settings->op->clear )
    777 		settings->op->clear ( settings );
    778 }
    779 
    780 /**
    781  * Compare two settings
    782  *
    783  * @v a			Setting to compare
    784  * @v b			Setting to compare
    785  * @ret 0		Settings are the same
    786  * @ret non-zero	Settings are not the same
    787  */
    788 int setting_cmp ( struct setting *a, struct setting *b ) {
    789 
    790 	/* If the settings have tags, compare them */
    791 	if ( a->tag && ( a->tag == b->tag ) )
    792 		return 0;
    793 
    794 	/* Otherwise, if the settings have names, compare them */
    795 	if ( a->name && b->name && a->name[0] )
    796 		return strcmp ( a->name, b->name );
    797 
    798 	/* Otherwise, return a non-match */
    799 	return ( ! 0 );
    800 }
    801 
    802 /******************************************************************************
    803  *
    804  * Formatted setting routines
    805  *
    806  ******************************************************************************
    807  */
    808 
    809 /**
    810  * Store value of typed setting
    811  *
    812  * @v settings		Settings block
    813  * @v setting		Setting to store
    814  * @v type		Settings type
    815  * @v value		Formatted setting data, or NULL
    816  * @ret rc		Return status code
    817  */
    818 int storef_setting ( struct settings *settings, struct setting *setting,
    819 		     const char *value ) {
    820 
    821 	/* NULL value implies deletion.  Avoid imposing the burden of
    822 	 * checking for NULL values on each typed setting's storef()
    823 	 * method.
    824 	 */
    825 	if ( ! value )
    826 		return delete_setting ( settings, setting );
    827 
    828 	return setting->type->storef ( settings, setting, value );
    829 }
    830 
    831 /**
    832  * Find named setting
    833  *
    834  * @v name		Name
    835  * @ret setting		Named setting, or NULL
    836  */
    837 static struct setting * find_setting ( const char *name ) {
    838 	struct setting *setting;
    839 
    840 	for_each_table_entry ( setting, SETTINGS ) {
    841 		if ( strcmp ( name, setting->name ) == 0 )
    842 			return setting;
    843 	}
    844 	return NULL;
    845 }
    846 
    847 /**
    848  * Parse setting name as tag number
    849  *
    850  * @v name		Name
    851  * @ret tag		Tag number, or 0 if not a valid number
    852  */
    853 static unsigned int parse_setting_tag ( const char *name ) {
    854 	char *tmp = ( ( char * ) name );
    855 	unsigned int tag = 0;
    856 
    857 	while ( 1 ) {
    858 		tag = ( ( tag << 8 ) | strtoul ( tmp, &tmp, 0 ) );
    859 		if ( *tmp == 0 )
    860 			return tag;
    861 		if ( *tmp != '.' )
    862 			return 0;
    863 		tmp++;
    864 	}
    865 }
    866 
    867 /**
    868  * Find setting type
    869  *
    870  * @v name		Name
    871  * @ret type		Setting type, or NULL
    872  */
    873 static struct setting_type * find_setting_type ( const char *name ) {
    874 	struct setting_type *type;
    875 
    876 	for_each_table_entry ( type, SETTING_TYPES ) {
    877 		if ( strcmp ( name, type->name ) == 0 )
    878 			return type;
    879 	}
    880 	return NULL;
    881 }
    882 
    883 /**
    884  * Parse setting name
    885  *
    886  * @v name		Name of setting
    887  * @v get_child		Function to find or create child settings block
    888  * @v settings		Settings block to fill in
    889  * @v setting		Setting to fill in
    890  * @v tmp_name		Buffer for copy of setting name
    891  * @ret rc		Return status code
    892  *
    893  * Interprets a name of the form
    894  * "[settings_name/]tag_name[:type_name]" and fills in the appropriate
    895  * fields.
    896  *
    897  * The @c tmp_name buffer must be large enough to hold a copy of the
    898  * setting name.
    899  */
    900 static int
    901 parse_setting_name ( const char *name,
    902 		     struct settings * ( * get_child ) ( struct settings *,
    903 							 const char * ),
    904 		     struct settings **settings, struct setting *setting,
    905 		     char *tmp_name ) {
    906 	char *settings_name;
    907 	char *setting_name;
    908 	char *type_name;
    909 	struct setting *named_setting;
    910 
    911 	/* Set defaults */
    912 	*settings = &settings_root;
    913 	memset ( setting, 0, sizeof ( *setting ) );
    914 	setting->name = "";
    915 	setting->type = &setting_type_string;
    916 
    917 	/* Split name into "[settings_name/]setting_name[:type_name]" */
    918 	strcpy ( tmp_name, name );
    919 	if ( ( setting_name = strchr ( tmp_name, '/' ) ) != NULL ) {
    920 		*(setting_name++) = 0;
    921 		settings_name = tmp_name;
    922 	} else {
    923 		setting_name = tmp_name;
    924 		settings_name = NULL;
    925 	}
    926 	if ( ( type_name = strchr ( setting_name, ':' ) ) != NULL )
    927 		*(type_name++) = 0;
    928 
    929 	/* Identify settings block, if specified */
    930 	if ( settings_name ) {
    931 		*settings = parse_settings_name ( settings_name, get_child );
    932 		if ( *settings == NULL ) {
    933 			DBG ( "Unrecognised settings block \"%s\" in \"%s\"\n",
    934 			      settings_name, name );
    935 			return -ENODEV;
    936 		}
    937 	}
    938 
    939 	/* Identify setting */
    940 	if ( ( named_setting = find_setting ( setting_name ) ) != NULL ) {
    941 		/* Matches a defined named setting; use that setting */
    942 		memcpy ( setting, named_setting, sizeof ( *setting ) );
    943 	} else if ( ( setting->tag = parse_setting_tag ( setting_name ) ) !=0){
    944 		/* Is a valid numeric tag; use the tag */
    945 		setting->tag |= (*settings)->tag_magic;
    946 	} else {
    947 		/* Use the arbitrary name */
    948 		setting->name = setting_name;
    949 	}
    950 
    951 	/* Identify setting type, if specified */
    952 	if ( type_name ) {
    953 		setting->type = find_setting_type ( type_name );
    954 		if ( setting->type == NULL ) {
    955 			DBG ( "Invalid setting type \"%s\" in \"%s\"\n",
    956 			      type_name, name );
    957 			return -ENOTSUP;
    958 		}
    959 	}
    960 
    961 	return 0;
    962 }
    963 
    964 /**
    965  * Parse and store value of named setting
    966  *
    967  * @v name		Name of setting
    968  * @v value		Formatted setting data, or NULL
    969  * @ret rc		Return status code
    970  */
    971 int storef_named_setting ( const char *name, const char *value ) {
    972 	struct settings *settings;
    973 	struct setting setting;
    974 	char tmp_name[ strlen ( name ) + 1 ];
    975 	int rc;
    976 
    977 	if ( ( rc = parse_setting_name ( name, autovivify_child_settings,
    978 					 &settings, &setting, tmp_name )) != 0)
    979 		return rc;
    980 	return storef_setting ( settings, &setting, value );
    981 }
    982 
    983 /**
    984  * Fetch and format value of named setting
    985  *
    986  * @v name		Name of setting
    987  * @v buf		Buffer to contain formatted value
    988  * @v len		Length of buffer
    989  * @ret len		Length of formatted value, or negative error
    990  */
    991 int fetchf_named_setting ( const char *name, char *buf, size_t len ) {
    992 	struct settings *settings;
    993 	struct setting setting;
    994 	char tmp_name[ strlen ( name ) + 1 ];
    995 	int rc;
    996 
    997 	if ( ( rc = parse_setting_name ( name, find_child_settings,
    998 					 &settings, &setting, tmp_name )) != 0)
    999 		return rc;
   1000 	return fetchf_setting ( settings, &setting, buf, len );
   1001 }
   1002 
   1003 /******************************************************************************
   1004  *
   1005  * Setting types
   1006  *
   1007  ******************************************************************************
   1008  */
   1009 
   1010 /**
   1011  * Parse and store value of string setting
   1012  *
   1013  * @v settings		Settings block
   1014  * @v setting		Setting to store
   1015  * @v value		Formatted setting data
   1016  * @ret rc		Return status code
   1017  */
   1018 static int storef_string ( struct settings *settings, struct setting *setting,
   1019 			   const char *value ) {
   1020 	return store_setting ( settings, setting, value, strlen ( value ) );
   1021 }
   1022 
   1023 /**
   1024  * Fetch and format value of string setting
   1025  *
   1026  * @v settings		Settings block, or NULL to search all blocks
   1027  * @v setting		Setting to fetch
   1028  * @v buf		Buffer to contain formatted value
   1029  * @v len		Length of buffer
   1030  * @ret len		Length of formatted value, or negative error
   1031  */
   1032 static int fetchf_string ( struct settings *settings, struct setting *setting,
   1033 			   char *buf, size_t len ) {
   1034 	return fetch_string_setting ( settings, setting, buf, len );
   1035 }
   1036 
   1037 /** A string setting type */
   1038 struct setting_type setting_type_string __setting_type = {
   1039 	.name = "string",
   1040 	.storef = storef_string,
   1041 	.fetchf = fetchf_string,
   1042 };
   1043 
   1044 /**
   1045  * Parse and store value of URI-encoded string setting
   1046  *
   1047  * @v settings		Settings block
   1048  * @v setting		Setting to store
   1049  * @v value		Formatted setting data
   1050  * @ret rc		Return status code
   1051  */
   1052 static int storef_uristring ( struct settings *settings,
   1053 			      struct setting *setting,
   1054 			      const char *value ) {
   1055 	char buf[ strlen ( value ) + 1 ]; /* Decoding never expands string */
   1056 	size_t len;
   1057 
   1058 	len = uri_decode ( value, buf, sizeof ( buf ) );
   1059 	return store_setting ( settings, setting, buf, len );
   1060 }
   1061 
   1062 /**
   1063  * Fetch and format value of URI-encoded string setting
   1064  *
   1065  * @v settings		Settings block, or NULL to search all blocks
   1066  * @v setting		Setting to fetch
   1067  * @v buf		Buffer to contain formatted value
   1068  * @v len		Length of buffer
   1069  * @ret len		Length of formatted value, or negative error
   1070  */
   1071 static int fetchf_uristring ( struct settings *settings,
   1072 			      struct setting *setting,
   1073 			      char *buf, size_t len ) {
   1074 	ssize_t raw_len;
   1075 
   1076 	/* We need to always retrieve the full raw string to know the
   1077 	 * length of the encoded string.
   1078 	 */
   1079 	raw_len = fetch_setting ( settings, setting, NULL, 0 );
   1080 	if ( raw_len < 0 )
   1081 		return raw_len;
   1082 
   1083 	{
   1084 		char raw_buf[ raw_len + 1 ];
   1085 
   1086 		fetch_string_setting ( settings, setting, raw_buf,
   1087 				       sizeof ( raw_buf ) );
   1088 		return uri_encode ( raw_buf, buf, len, URI_FRAGMENT );
   1089 	}
   1090 }
   1091 
   1092 /** A URI-encoded string setting type */
   1093 struct setting_type setting_type_uristring __setting_type = {
   1094 	.name = "uristring",
   1095 	.storef = storef_uristring,
   1096 	.fetchf = fetchf_uristring,
   1097 };
   1098 
   1099 /**
   1100  * Parse and store value of IPv4 address setting
   1101  *
   1102  * @v settings		Settings block
   1103  * @v setting		Setting to store
   1104  * @v value		Formatted setting data
   1105  * @ret rc		Return status code
   1106  */
   1107 static int storef_ipv4 ( struct settings *settings, struct setting *setting,
   1108 			 const char *value ) {
   1109 	struct in_addr ipv4;
   1110 
   1111 	if ( inet_aton ( value, &ipv4 ) == 0 )
   1112 		return -EINVAL;
   1113 	return store_setting ( settings, setting, &ipv4, sizeof ( ipv4 ) );
   1114 }
   1115 
   1116 /**
   1117  * Fetch and format value of IPv4 address setting
   1118  *
   1119  * @v settings		Settings block, or NULL to search all blocks
   1120  * @v setting		Setting to fetch
   1121  * @v buf		Buffer to contain formatted value
   1122  * @v len		Length of buffer
   1123  * @ret len		Length of formatted value, or negative error
   1124  */
   1125 static int fetchf_ipv4 ( struct settings *settings, struct setting *setting,
   1126 			 char *buf, size_t len ) {
   1127 	struct in_addr ipv4;
   1128 	int raw_len;
   1129 
   1130 	if ( ( raw_len = fetch_ipv4_setting ( settings, setting, &ipv4 ) ) < 0)
   1131 		return raw_len;
   1132 	return snprintf ( buf, len, "%s", inet_ntoa ( ipv4 ) );
   1133 }
   1134 
   1135 /** An IPv4 address setting type */
   1136 struct setting_type setting_type_ipv4 __setting_type = {
   1137 	.name = "ipv4",
   1138 	.storef = storef_ipv4,
   1139 	.fetchf = fetchf_ipv4,
   1140 };
   1141 
   1142 /**
   1143  * Parse and store value of integer setting
   1144  *
   1145  * @v settings		Settings block
   1146  * @v setting		Setting to store
   1147  * @v value		Formatted setting data
   1148  * @v size		Integer size, in bytes
   1149  * @ret rc		Return status code
   1150  */
   1151 static int storef_int ( struct settings *settings, struct setting *setting,
   1152 			const char *value, unsigned int size ) {
   1153 	union {
   1154 		uint32_t num;
   1155 		uint8_t bytes[4];
   1156 	} u;
   1157 	char *endp;
   1158 
   1159 	u.num = htonl ( strtoul ( value, &endp, 0 ) );
   1160 	if ( *endp )
   1161 		return -EINVAL;
   1162 	return store_setting ( settings, setting,
   1163 			       &u.bytes[ sizeof ( u ) - size ], size );
   1164 }
   1165 
   1166 /**
   1167  * Parse and store value of 8-bit integer setting
   1168  *
   1169  * @v settings		Settings block
   1170  * @v setting		Setting to store
   1171  * @v value		Formatted setting data
   1172  * @v size		Integer size, in bytes
   1173  * @ret rc		Return status code
   1174  */
   1175 static int storef_int8 ( struct settings *settings, struct setting *setting,
   1176 			 const char *value ) {
   1177 	return storef_int ( settings, setting, value, 1 );
   1178 }
   1179 
   1180 /**
   1181  * Parse and store value of 16-bit integer setting
   1182  *
   1183  * @v settings		Settings block
   1184  * @v setting		Setting to store
   1185  * @v value		Formatted setting data
   1186  * @v size		Integer size, in bytes
   1187  * @ret rc		Return status code
   1188  */
   1189 static int storef_int16 ( struct settings *settings, struct setting *setting,
   1190 			  const char *value ) {
   1191 	return storef_int ( settings, setting, value, 2 );
   1192 }
   1193 
   1194 /**
   1195  * Parse and store value of 32-bit integer setting
   1196  *
   1197  * @v settings		Settings block
   1198  * @v setting		Setting to store
   1199  * @v value		Formatted setting data
   1200  * @v size		Integer size, in bytes
   1201  * @ret rc		Return status code
   1202  */
   1203 static int storef_int32 ( struct settings *settings, struct setting *setting,
   1204 			  const char *value ) {
   1205 	return storef_int ( settings, setting, value, 4 );
   1206 }
   1207 
   1208 /**
   1209  * Fetch and format value of signed integer setting
   1210  *
   1211  * @v settings		Settings block, or NULL to search all blocks
   1212  * @v setting		Setting to fetch
   1213  * @v buf		Buffer to contain formatted value
   1214  * @v len		Length of buffer
   1215  * @ret len		Length of formatted value, or negative error
   1216  */
   1217 static int fetchf_int ( struct settings *settings, struct setting *setting,
   1218 			char *buf, size_t len ) {
   1219 	long value;
   1220 	int rc;
   1221 
   1222 	if ( ( rc = fetch_int_setting ( settings, setting, &value ) ) < 0 )
   1223 		return rc;
   1224 	return snprintf ( buf, len, "%ld", value );
   1225 }
   1226 
   1227 /**
   1228  * Fetch and format value of unsigned integer setting
   1229  *
   1230  * @v settings		Settings block, or NULL to search all blocks
   1231  * @v setting		Setting to fetch
   1232  * @v buf		Buffer to contain formatted value
   1233  * @v len		Length of buffer
   1234  * @ret len		Length of formatted value, or negative error
   1235  */
   1236 static int fetchf_uint ( struct settings *settings, struct setting *setting,
   1237 			 char *buf, size_t len ) {
   1238 	unsigned long value;
   1239 	int rc;
   1240 
   1241 	if ( ( rc = fetch_uint_setting ( settings, setting, &value ) ) < 0 )
   1242 		return rc;
   1243 	return snprintf ( buf, len, "%#lx", value );
   1244 }
   1245 
   1246 /** A signed 8-bit integer setting type */
   1247 struct setting_type setting_type_int8 __setting_type = {
   1248 	.name = "int8",
   1249 	.storef = storef_int8,
   1250 	.fetchf = fetchf_int,
   1251 };
   1252 
   1253 /** A signed 16-bit integer setting type */
   1254 struct setting_type setting_type_int16 __setting_type = {
   1255 	.name = "int16",
   1256 	.storef = storef_int16,
   1257 	.fetchf = fetchf_int,
   1258 };
   1259 
   1260 /** A signed 32-bit integer setting type */
   1261 struct setting_type setting_type_int32 __setting_type = {
   1262 	.name = "int32",
   1263 	.storef = storef_int32,
   1264 	.fetchf = fetchf_int,
   1265 };
   1266 
   1267 /** An unsigned 8-bit integer setting type */
   1268 struct setting_type setting_type_uint8 __setting_type = {
   1269 	.name = "uint8",
   1270 	.storef = storef_int8,
   1271 	.fetchf = fetchf_uint,
   1272 };
   1273 
   1274 /** An unsigned 16-bit integer setting type */
   1275 struct setting_type setting_type_uint16 __setting_type = {
   1276 	.name = "uint16",
   1277 	.storef = storef_int16,
   1278 	.fetchf = fetchf_uint,
   1279 };
   1280 
   1281 /** An unsigned 32-bit integer setting type */
   1282 struct setting_type setting_type_uint32 __setting_type = {
   1283 	.name = "uint32",
   1284 	.storef = storef_int32,
   1285 	.fetchf = fetchf_uint,
   1286 };
   1287 
   1288 /**
   1289  * Parse and store value of hex string setting
   1290  *
   1291  * @v settings		Settings block
   1292  * @v setting		Setting to store
   1293  * @v value		Formatted setting data
   1294  * @ret rc		Return status code
   1295  */
   1296 static int storef_hex ( struct settings *settings, struct setting *setting,
   1297 			const char *value ) {
   1298 	char *ptr = ( char * ) value;
   1299 	uint8_t bytes[ strlen ( value ) ]; /* cannot exceed strlen(value) */
   1300 	unsigned int len = 0;
   1301 
   1302 	while ( 1 ) {
   1303 		bytes[len++] = strtoul ( ptr, &ptr, 16 );
   1304 		switch ( *ptr ) {
   1305 		case '\0' :
   1306 			return store_setting ( settings, setting, bytes, len );
   1307 		case ':' :
   1308 			ptr++;
   1309 			break;
   1310 		default :
   1311 			return -EINVAL;
   1312 		}
   1313 	}
   1314 }
   1315 
   1316 /**
   1317  * Fetch and format value of hex string setting
   1318  *
   1319  * @v settings		Settings block, or NULL to search all blocks
   1320  * @v setting		Setting to fetch
   1321  * @v buf		Buffer to contain formatted value
   1322  * @v len		Length of buffer
   1323  * @ret len		Length of formatted value, or negative error
   1324  */
   1325 static int fetchf_hex ( struct settings *settings, struct setting *setting,
   1326 			char *buf, size_t len ) {
   1327 	int raw_len;
   1328 	int check_len;
   1329 	int used = 0;
   1330 	int i;
   1331 
   1332 	raw_len = fetch_setting_len ( settings, setting );
   1333 	if ( raw_len < 0 )
   1334 		return raw_len;
   1335 
   1336 	{
   1337 		uint8_t raw[raw_len];
   1338 
   1339 		check_len = fetch_setting ( settings, setting, raw,
   1340 					    sizeof ( raw ) );
   1341 		if ( check_len < 0 )
   1342 			return check_len;
   1343 		assert ( check_len == raw_len );
   1344 
   1345 		if ( len )
   1346 			buf[0] = 0; /* Ensure that a terminating NUL exists */
   1347 		for ( i = 0 ; i < raw_len ; i++ ) {
   1348 			used += ssnprintf ( ( buf + used ), ( len - used ),
   1349 					    "%s%02x", ( used ? ":" : "" ),
   1350 					    raw[i] );
   1351 		}
   1352 		return used;
   1353 	}
   1354 }
   1355 
   1356 /** A hex-string setting */
   1357 struct setting_type setting_type_hex __setting_type = {
   1358 	.name = "hex",
   1359 	.storef = storef_hex,
   1360 	.fetchf = fetchf_hex,
   1361 };
   1362 
   1363 /**
   1364  * Parse and store value of UUID setting
   1365  *
   1366  * @v settings		Settings block
   1367  * @v setting		Setting to store
   1368  * @v value		Formatted setting data
   1369  * @ret rc		Return status code
   1370  */
   1371 static int storef_uuid ( struct settings *settings __unused,
   1372 			 struct setting *setting __unused,
   1373 			 const char *value __unused ) {
   1374 	return -ENOTSUP;
   1375 }
   1376 
   1377 /**
   1378  * Fetch and format value of UUID setting
   1379  *
   1380  * @v settings		Settings block, or NULL to search all blocks
   1381  * @v setting		Setting to fetch
   1382  * @v buf		Buffer to contain formatted value
   1383  * @v len		Length of buffer
   1384  * @ret len		Length of formatted value, or negative error
   1385  */
   1386 static int fetchf_uuid ( struct settings *settings, struct setting *setting,
   1387 			 char *buf, size_t len ) {
   1388 	union uuid uuid;
   1389 	int raw_len;
   1390 
   1391 	if ( ( raw_len = fetch_uuid_setting ( settings, setting, &uuid ) ) < 0)
   1392 		return raw_len;
   1393 	return snprintf ( buf, len, "%s", uuid_ntoa ( &uuid ) );
   1394 }
   1395 
   1396 /** UUID setting type */
   1397 struct setting_type setting_type_uuid __setting_type = {
   1398 	.name = "uuid",
   1399 	.storef = storef_uuid,
   1400 	.fetchf = fetchf_uuid,
   1401 };
   1402 
   1403 /******************************************************************************
   1404  *
   1405  * Settings
   1406  *
   1407  ******************************************************************************
   1408  */
   1409 
   1410 /** Hostname setting */
   1411 struct setting hostname_setting __setting = {
   1412 	.name = "hostname",
   1413 	.description = "Host name",
   1414 	.tag = DHCP_HOST_NAME,
   1415 	.type = &setting_type_string,
   1416 };
   1417 
   1418 /** Filename setting */
   1419 struct setting filename_setting __setting = {
   1420 	.name = "filename",
   1421 	.description = "Boot filename",
   1422 	.tag = DHCP_BOOTFILE_NAME,
   1423 	.type = &setting_type_string,
   1424 };
   1425 
   1426 /** Root path setting */
   1427 struct setting root_path_setting __setting = {
   1428 	.name = "root-path",
   1429 	.description = "iSCSI root path",
   1430 	.tag = DHCP_ROOT_PATH,
   1431 	.type = &setting_type_string,
   1432 };
   1433 
   1434 /** Username setting */
   1435 struct setting username_setting __setting = {
   1436 	.name = "username",
   1437 	.description = "User name",
   1438 	.tag = DHCP_EB_USERNAME,
   1439 	.type = &setting_type_string,
   1440 };
   1441 
   1442 /** Password setting */
   1443 struct setting password_setting __setting = {
   1444 	.name = "password",
   1445 	.description = "Password",
   1446 	.tag = DHCP_EB_PASSWORD,
   1447 	.type = &setting_type_string,
   1448 };
   1449 
   1450 /** Priority setting */
   1451 struct setting priority_setting __setting = {
   1452 	.name = "priority",
   1453 	.description = "Priority of these settings",
   1454 	.tag = DHCP_EB_PRIORITY,
   1455 	.type = &setting_type_int8,
   1456 };
   1457