2 * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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.
19 FILE_LICENCE ( GPL2_OR_LATER
);
30 #include <gpxe/vsprintf.h>
31 #include <gpxe/dhcp.h>
32 #include <gpxe/uuid.h>
34 #include <gpxe/settings.h>
38 * Configuration settings
42 /******************************************************************************
44 * Generic settings blocks
46 ******************************************************************************
53 struct generic_setting
{
54 /** List of generic settings */
55 struct list_head list
;
57 struct setting setting
;
58 /** Size of setting name */
60 /** Size of setting data */
65 * Get generic setting name
67 * @v generic Generic setting
68 * @ret name Generic setting name
70 static inline void * generic_setting_name ( struct generic_setting
*generic
) {
71 return ( ( ( void * ) generic
) + sizeof ( *generic
) );
75 * Get generic setting data
77 * @v generic Generic setting
78 * @ret data Generic setting data
80 static inline void * generic_setting_data ( struct generic_setting
*generic
) {
81 return ( ( ( void * ) generic
) + sizeof ( *generic
) +
86 * Find generic setting
88 * @v generics Generic settings block
89 * @v setting Setting to find
90 * @ret generic Generic setting, or NULL
92 static struct generic_setting
*
93 find_generic_setting ( struct generic_settings
*generics
,
94 struct setting
*setting
) {
95 struct generic_setting
*generic
;
97 list_for_each_entry ( generic
, &generics
->list
, list
) {
98 if ( setting_cmp ( &generic
->setting
, setting
) == 0 )
105 * Store value of generic setting
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
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
;
122 /* Identify existing generic setting, if any */
123 old
= find_generic_setting ( generics
, setting
);
125 /* Create new generic setting, if required */
127 /* Allocate new generic setting */
128 name_len
= ( strlen ( setting
->name
) + 1 );
129 new = zalloc ( sizeof ( *new ) + name_len
+ len
);
133 /* Populate new generic setting */
134 new->name_len
= name_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
);
143 /* Delete existing generic setting, if any */
145 list_del ( &old
->list
);
149 /* Add new setting to list, if any */
151 list_add ( &new->list
, &generics
->list
);
157 * Fetch value of generic setting
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
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
;
172 /* Find generic setting */
173 generic
= find_generic_setting ( generics
, setting
);
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
;
185 * Clear generic settings block
187 * @v settings Settings block
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
;
195 list_for_each_entry_safe ( generic
, tmp
, &generics
->list
, list
) {
196 list_del ( &generic
->list
);
199 assert ( list_empty ( &generics
->list
) );
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
,
209 /******************************************************************************
211 * Registered settings blocks
213 ******************************************************************************
216 /** Root generic settings block */
217 struct generic_settings generic_settings_root
= {
222 LIST_HEAD_INIT ( generic_settings_root
.settings
.siblings
),
224 LIST_HEAD_INIT ( generic_settings_root
.settings
.children
),
225 .op
= &generic_settings_operations
,
227 .list
= LIST_HEAD_INIT ( generic_settings_root
.list
),
230 /** Root settings block */
231 #define settings_root generic_settings_root.settings
234 * Find child named settings block
236 * @v parent Parent settings block
237 * @v name Name within this parent
238 * @ret settings Settings block, or NULL
240 static struct settings
* find_child_settings ( struct settings
*parent
,
242 struct settings
*settings
;
244 /* Treat empty name as meaning "this block" */
248 /* Look for child with matching name */
249 list_for_each_entry ( settings
, &parent
->children
, siblings
) {
250 if ( strcmp ( settings
->name
, name
) == 0 )
258 * Find or create child named settings block
260 * @v parent Parent settings block
261 * @v name Name within this parent
262 * @ret settings Settings block, or NULL
264 static struct settings
* autovivify_child_settings ( struct settings
*parent
,
267 struct generic_settings generic
;
268 char name
[ strlen ( name
) + 1 /* NUL */ ];
270 struct settings
*settings
;
272 /* Return existing settings, if existent */
273 if ( ( settings
= find_child_settings ( parent
, name
) ) != NULL
)
276 /* Create new generic settings block */
277 new_child
= zalloc ( sizeof ( *new_child
) );
279 DBGC ( parent
, "Settings %p could not create child %s\n",
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
);
291 * Return settings block name (for debug only)
293 * @v settings Settings block
294 * @ret name Settings block name
296 static const char * settings_name ( struct settings
*settings
) {
298 char tmp
[ sizeof ( buf
) ];
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
);
310 * Parse settings block name
313 * @v get_child Function to find or create child settings block
314 * @ret settings Settings block, or NULL
316 static struct settings
*
317 parse_settings_name ( const char *name
,
318 struct settings
* ( * get_child
) ( struct settings
*,
320 struct settings
*settings
= &settings_root
;
321 char name_copy
[ strlen ( name
) + 1 ];
325 /* Create modifiable copy of name */
326 memcpy ( name_copy
, name
, sizeof ( name_copy
) );
327 remainder
= name_copy
;
329 /* Parse each name component in turn */
330 while ( remainder
) {
331 struct net_device
*netdev
;
334 remainder
= strchr ( subname
, '.' );
336 *(remainder
++) = '\0';
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
);
343 settings
= get_child ( settings
, subname
);
353 * Find named settings block
356 * @ret settings Settings block, or NULL
358 struct settings
* find_settings ( const char *name
) {
360 return parse_settings_name ( name
, find_child_settings
);
366 * @ret rc Return status code
368 static int apply_settings ( void ) {
369 struct settings_applicator
*applicator
;
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
) );
385 * Reprioritise settings
387 * @v settings Settings block
389 * Reorders the settings block amongst its siblings according to its
392 static void reprioritise_settings ( struct settings
*settings
) {
393 struct settings
*parent
= settings
->parent
;
395 struct settings
*tmp
;
398 /* Stop when we reach the top of the tree */
402 /* Read priority, if present */
403 priority
= fetch_intz_setting ( settings
, &priority_setting
);
405 /* Remove from siblings list */
406 list_del ( &settings
->siblings
);
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
)
414 list_add_tail ( &settings
->siblings
, &tmp
->siblings
);
416 /* Recurse up the tree */
417 reprioritise_settings ( parent
);
421 * Register settings block
423 * @v settings Settings block
424 * @v parent Parent settings block, or NULL
425 * @ret rc Return status code
427 int register_settings ( struct settings
*settings
, struct settings
*parent
) {
428 struct settings
*old_settings
;
430 /* NULL parent => add to settings root */
431 assert ( settings
!= NULL
);
432 if ( parent
== NULL
)
433 parent
= &settings_root
;
435 /* Remove any existing settings with the same name */
436 if ( ( old_settings
= find_child_settings ( parent
, settings
->name
) ))
437 unregister_settings ( old_settings
);
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
) );
447 /* Fix up settings priority */
448 reprioritise_settings ( settings
);
450 /* Apply potentially-updated settings */
457 * Unregister settings block
459 * @v settings Settings block
461 void unregister_settings ( struct settings
*settings
) {
463 DBGC ( settings
, "Settings %p (\"%s\") unregistered\n",
464 settings
, settings_name ( settings
) );
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
);
472 /* Apply potentially-updated settings */
476 /******************************************************************************
478 * Core settings routines
480 ******************************************************************************
484 * Store value of setting
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
492 int store_setting ( struct settings
*settings
, struct setting
*setting
,
493 const void *data
, size_t len
) {
496 /* NULL settings implies storing into the global settings root */
498 settings
= &settings_root
;
501 if ( ! settings
->op
->store
)
505 if ( ( rc
= settings
->op
->store ( settings
, setting
,
509 /* Reprioritise settings if necessary */
510 if ( setting_cmp ( setting
, &priority_setting
) == 0 )
511 reprioritise_settings ( settings
);
513 /* If these settings are registered, apply potentially-updated
516 for ( ; settings
; settings
= settings
->parent
) {
517 if ( settings
== &settings_root
) {
518 if ( ( rc
= apply_settings() ) != 0 )
528 * Fetch value of setting
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
536 * The actual length of the setting will be returned even if
537 * the buffer was too small.
539 int fetch_setting ( struct settings
*settings
, struct setting
*setting
,
540 void *data
, size_t len
) {
541 struct settings
*child
;
544 /* Avoid returning uninitialised data on error */
545 memset ( data
, 0, len
);
547 /* NULL settings implies starting at the global settings root */
549 settings
= &settings_root
;
552 if ( ! settings
->op
->fetch
)
555 /* Try this block first */
556 if ( ( ret
= settings
->op
->fetch ( settings
, setting
,
560 /* Recurse into each child block in turn */
561 list_for_each_entry ( child
, &settings
->children
, siblings
) {
562 if ( ( ret
= fetch_setting ( child
, setting
,
571 * Fetch length of setting
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
577 * This function can also be used as an existence check for the
580 int fetch_setting_len ( struct settings
*settings
, struct setting
*setting
) {
581 return fetch_setting ( settings
, setting
, NULL
, 0 );
585 * Fetch value of string setting
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
593 * The resulting string is guaranteed to be correctly NUL-terminated.
594 * The returned length will be the length of the underlying setting
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 ) );
605 * Fetch value of string setting
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
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
617 int fetch_string_setting_copy ( struct settings
*settings
,
618 struct setting
*setting
,
623 len
= fetch_setting_len ( settings
, setting
);
627 *data
= malloc ( len
+ 1 );
631 check_len
= fetch_string_setting ( settings
, setting
, *data
,
633 assert ( check_len
== len
);
638 * Fetch value of IPv4 address setting
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
645 int fetch_ipv4_setting ( struct settings
*settings
, struct setting
*setting
,
646 struct in_addr
*inp
) {
649 len
= fetch_setting ( settings
, setting
, inp
, sizeof ( *inp
) );
652 if ( len
< ( int ) sizeof ( *inp
) )
658 * Fetch value of signed integer setting
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
665 int fetch_int_setting ( struct settings
*settings
, struct setting
*setting
,
668 uint8_t u8
[ sizeof ( long ) ];
669 int8_t s8
[ sizeof ( long ) ];
674 /* Avoid returning uninitialised data on error */
677 /* Fetch raw (network-ordered, variable-length) setting */
678 len
= fetch_setting ( settings
, setting
, &buf
, sizeof ( buf
) );
681 if ( len
> ( int ) sizeof ( buf
) )
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
] );
694 * Fetch value of unsigned integer setting
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
701 int fetch_uint_setting ( struct settings
*settings
, struct setting
*setting
,
702 unsigned long *value
) {
706 /* Avoid returning uninitialised data on error */
709 /* Fetch as a signed long */
710 len
= fetch_int_setting ( settings
, setting
, &svalue
);
714 /* Mask off sign-extended bits */
715 assert ( len
<= ( int ) sizeof ( long ) );
716 *value
= ( svalue
& ( -1UL >> ( 8 * ( sizeof ( long ) - len
) ) ) );
722 * Fetch value of signed integer setting, or zero
724 * @v settings Settings block, or NULL to search all blocks
725 * @v setting Setting to fetch
726 * @ret value Setting value, or zero
728 long fetch_intz_setting ( struct settings
*settings
, struct setting
*setting
){
731 fetch_int_setting ( settings
, setting
, &value
);
736 * Fetch value of unsigned integer setting, or zero
738 * @v settings Settings block, or NULL to search all blocks
739 * @v setting Setting to fetch
740 * @ret value Setting value, or zero
742 unsigned long fetch_uintz_setting ( struct settings
*settings
,
743 struct setting
*setting
) {
746 fetch_uint_setting ( settings
, setting
, &value
);
751 * Fetch value of UUID setting
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
758 int fetch_uuid_setting ( struct settings
*settings
, struct setting
*setting
,
762 len
= fetch_setting ( settings
, setting
, uuid
, sizeof ( *uuid
) );
765 if ( len
!= sizeof ( *uuid
) )
771 * Clear settings block
773 * @v settings Settings block
775 void clear_settings ( struct settings
*settings
) {
776 if ( settings
->op
->clear
)
777 settings
->op
->clear ( settings
);
781 * Compare two settings
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
788 int setting_cmp ( struct setting
*a
, struct setting
*b
) {
790 /* If the settings have tags, compare them */
791 if ( a
->tag
&& ( a
->tag
== b
->tag
) )
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
);
798 /* Otherwise, return a non-match */
802 /******************************************************************************
804 * Formatted setting routines
806 ******************************************************************************
810 * Store value of typed setting
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
818 int storef_setting ( struct settings
*settings
, struct setting
*setting
,
819 const char *value
) {
821 /* NULL value implies deletion. Avoid imposing the burden of
822 * checking for NULL values on each typed setting's storef()
826 return delete_setting ( settings
, setting
);
828 return setting
->type
->storef ( settings
, setting
, value
);
835 * @ret setting Named setting, or NULL
837 static struct setting
* find_setting ( const char *name
) {
838 struct setting
*setting
;
840 for_each_table_entry ( setting
, SETTINGS
) {
841 if ( strcmp ( name
, setting
->name
) == 0 )
848 * Parse setting name as tag number
851 * @ret tag Tag number, or 0 if not a valid number
853 static unsigned int parse_setting_tag ( const char *name
) {
854 char *tmp
= ( ( char * ) name
);
855 unsigned int tag
= 0;
858 tag
= ( ( tag
<< 8 ) | strtoul ( tmp
, &tmp
, 0 ) );
871 * @ret type Setting type, or NULL
873 static struct setting_type
* find_setting_type ( const char *name
) {
874 struct setting_type
*type
;
876 for_each_table_entry ( type
, SETTING_TYPES
) {
877 if ( strcmp ( name
, type
->name
) == 0 )
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
893 * Interprets a name of the form
894 * "[settings_name/]tag_name[:type_name]" and fills in the appropriate
897 * The @c tmp_name buffer must be large enough to hold a copy of the
901 parse_setting_name ( const char *name
,
902 struct settings
* ( * get_child
) ( struct settings
*,
904 struct settings
**settings
, struct setting
*setting
,
909 struct setting
*named_setting
;
912 *settings
= &settings_root
;
913 memset ( setting
, 0, sizeof ( *setting
) );
915 setting
->type
= &setting_type_string
;
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
;
923 setting_name
= tmp_name
;
924 settings_name
= NULL
;
926 if ( ( type_name
= strchr ( setting_name
, ':' ) ) != NULL
)
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
);
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
;
947 /* Use the arbitrary name */
948 setting
->name
= setting_name
;
951 /* Identify setting type, if specified */
953 setting
->type
= find_setting_type ( type_name
);
954 if ( setting
->type
== NULL
) {
955 DBG ( "Invalid setting type \"%s\" in \"%s\"\n",
965 * Parse and store value of named setting
967 * @v name Name of setting
968 * @v value Formatted setting data, or NULL
969 * @ret rc Return status code
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 ];
977 if ( ( rc
= parse_setting_name ( name
, autovivify_child_settings
,
978 &settings
, &setting
, tmp_name
)) != 0)
980 return storef_setting ( settings
, &setting
, value
);
984 * Fetch and format value of named setting
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
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 ];
997 if ( ( rc
= parse_setting_name ( name
, find_child_settings
,
998 &settings
, &setting
, tmp_name
)) != 0)
1000 return fetchf_setting ( settings
, &setting
, buf
, len
);
1003 /******************************************************************************
1007 ******************************************************************************
1011 * Parse and store value of string setting
1013 * @v settings Settings block
1014 * @v setting Setting to store
1015 * @v value Formatted setting data
1016 * @ret rc Return status code
1018 static int storef_string ( struct settings
*settings
, struct setting
*setting
,
1019 const char *value
) {
1020 return store_setting ( settings
, setting
, value
, strlen ( value
) );
1024 * Fetch and format value of string setting
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
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
);
1037 /** A string setting type */
1038 struct setting_type setting_type_string __setting_type
= {
1040 .storef
= storef_string
,
1041 .fetchf
= fetchf_string
,
1045 * Parse and store value of URI-encoded string setting
1047 * @v settings Settings block
1048 * @v setting Setting to store
1049 * @v value Formatted setting data
1050 * @ret rc Return status code
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 */
1058 len
= uri_decode ( value
, buf
, sizeof ( buf
) );
1059 return store_setting ( settings
, setting
, buf
, len
);
1063 * Fetch and format value of URI-encoded string setting
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
1071 static int fetchf_uristring ( struct settings
*settings
,
1072 struct setting
*setting
,
1073 char *buf
, size_t len
) {
1076 /* We need to always retrieve the full raw string to know the
1077 * length of the encoded string.
1079 raw_len
= fetch_setting ( settings
, setting
, NULL
, 0 );
1084 char raw_buf
[ raw_len
+ 1 ];
1086 fetch_string_setting ( settings
, setting
, raw_buf
,
1087 sizeof ( raw_buf
) );
1088 return uri_encode ( raw_buf
, buf
, len
, URI_FRAGMENT
);
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
,
1100 * Parse and store value of IPv4 address setting
1102 * @v settings Settings block
1103 * @v setting Setting to store
1104 * @v value Formatted setting data
1105 * @ret rc Return status code
1107 static int storef_ipv4 ( struct settings
*settings
, struct setting
*setting
,
1108 const char *value
) {
1109 struct in_addr ipv4
;
1111 if ( inet_aton ( value
, &ipv4
) == 0 )
1113 return store_setting ( settings
, setting
, &ipv4
, sizeof ( ipv4
) );
1117 * Fetch and format value of IPv4 address setting
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
1125 static int fetchf_ipv4 ( struct settings
*settings
, struct setting
*setting
,
1126 char *buf
, size_t len
) {
1127 struct in_addr ipv4
;
1130 if ( ( raw_len
= fetch_ipv4_setting ( settings
, setting
, &ipv4
) ) < 0)
1132 return snprintf ( buf
, len
, "%s", inet_ntoa ( ipv4
) );
1135 /** An IPv4 address setting type */
1136 struct setting_type setting_type_ipv4 __setting_type
= {
1138 .storef
= storef_ipv4
,
1139 .fetchf
= fetchf_ipv4
,
1143 * Parse and store value of integer setting
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
1151 static int storef_int ( struct settings
*settings
, struct setting
*setting
,
1152 const char *value
, unsigned int size
) {
1159 u
.num
= htonl ( strtoul ( value
, &endp
, 0 ) );
1162 return store_setting ( settings
, setting
,
1163 &u
.bytes
[ sizeof ( u
) - size
], size
);
1167 * Parse and store value of 8-bit integer setting
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
1175 static int storef_int8 ( struct settings
*settings
, struct setting
*setting
,
1176 const char *value
) {
1177 return storef_int ( settings
, setting
, value
, 1 );
1181 * Parse and store value of 16-bit integer setting
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
1189 static int storef_int16 ( struct settings
*settings
, struct setting
*setting
,
1190 const char *value
) {
1191 return storef_int ( settings
, setting
, value
, 2 );
1195 * Parse and store value of 32-bit integer setting
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
1203 static int storef_int32 ( struct settings
*settings
, struct setting
*setting
,
1204 const char *value
) {
1205 return storef_int ( settings
, setting
, value
, 4 );
1209 * Fetch and format value of signed integer setting
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
1217 static int fetchf_int ( struct settings
*settings
, struct setting
*setting
,
1218 char *buf
, size_t len
) {
1222 if ( ( rc
= fetch_int_setting ( settings
, setting
, &value
) ) < 0 )
1224 return snprintf ( buf
, len
, "%ld", value
);
1228 * Fetch and format value of unsigned integer setting
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
1236 static int fetchf_uint ( struct settings
*settings
, struct setting
*setting
,
1237 char *buf
, size_t len
) {
1238 unsigned long value
;
1241 if ( ( rc
= fetch_uint_setting ( settings
, setting
, &value
) ) < 0 )
1243 return snprintf ( buf
, len
, "%#lx", value
);
1246 /** A signed 8-bit integer setting type */
1247 struct setting_type setting_type_int8 __setting_type
= {
1249 .storef
= storef_int8
,
1250 .fetchf
= fetchf_int
,
1253 /** A signed 16-bit integer setting type */
1254 struct setting_type setting_type_int16 __setting_type
= {
1256 .storef
= storef_int16
,
1257 .fetchf
= fetchf_int
,
1260 /** A signed 32-bit integer setting type */
1261 struct setting_type setting_type_int32 __setting_type
= {
1263 .storef
= storef_int32
,
1264 .fetchf
= fetchf_int
,
1267 /** An unsigned 8-bit integer setting type */
1268 struct setting_type setting_type_uint8 __setting_type
= {
1270 .storef
= storef_int8
,
1271 .fetchf
= fetchf_uint
,
1274 /** An unsigned 16-bit integer setting type */
1275 struct setting_type setting_type_uint16 __setting_type
= {
1277 .storef
= storef_int16
,
1278 .fetchf
= fetchf_uint
,
1281 /** An unsigned 32-bit integer setting type */
1282 struct setting_type setting_type_uint32 __setting_type
= {
1284 .storef
= storef_int32
,
1285 .fetchf
= fetchf_uint
,
1289 * Parse and store value of hex string setting
1291 * @v settings Settings block
1292 * @v setting Setting to store
1293 * @v value Formatted setting data
1294 * @ret rc Return status code
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;
1303 bytes
[len
++] = strtoul ( ptr
, &ptr
, 16 );
1306 return store_setting ( settings
, setting
, bytes
, len
);
1317 * Fetch and format value of hex string setting
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
1325 static int fetchf_hex ( struct settings
*settings
, struct setting
*setting
,
1326 char *buf
, size_t len
) {
1332 raw_len
= fetch_setting_len ( settings
, setting
);
1337 uint8_t raw
[raw_len
];
1339 check_len
= fetch_setting ( settings
, setting
, raw
,
1341 if ( check_len
< 0 )
1343 assert ( check_len
== raw_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
? ":" : "" ),
1356 /** A hex-string setting */
1357 struct setting_type setting_type_hex __setting_type
= {
1359 .storef
= storef_hex
,
1360 .fetchf
= fetchf_hex
,
1364 * Parse and store value of UUID setting
1366 * @v settings Settings block
1367 * @v setting Setting to store
1368 * @v value Formatted setting data
1369 * @ret rc Return status code
1371 static int storef_uuid ( struct settings
*settings __unused
,
1372 struct setting
*setting __unused
,
1373 const char *value __unused
) {
1378 * Fetch and format value of UUID setting
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
1386 static int fetchf_uuid ( struct settings
*settings
, struct setting
*setting
,
1387 char *buf
, size_t len
) {
1391 if ( ( raw_len
= fetch_uuid_setting ( settings
, setting
, &uuid
) ) < 0)
1393 return snprintf ( buf
, len
, "%s", uuid_ntoa ( &uuid
) );
1396 /** UUID setting type */
1397 struct setting_type setting_type_uuid __setting_type
= {
1399 .storef
= storef_uuid
,
1400 .fetchf
= fetchf_uuid
,
1403 /******************************************************************************
1407 ******************************************************************************
1410 /** Hostname setting */
1411 struct setting hostname_setting __setting
= {
1413 .description
= "Host name",
1414 .tag
= DHCP_HOST_NAME
,
1415 .type
= &setting_type_string
,
1418 /** Filename setting */
1419 struct setting filename_setting __setting
= {
1421 .description
= "Boot filename",
1422 .tag
= DHCP_BOOTFILE_NAME
,
1423 .type
= &setting_type_string
,
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
,
1434 /** Username setting */
1435 struct setting username_setting __setting
= {
1437 .description
= "User name",
1438 .tag
= DHCP_EB_USERNAME
,
1439 .type
= &setting_type_string
,
1442 /** Password setting */
1443 struct setting password_setting __setting
= {
1445 .description
= "Password",
1446 .tag
= DHCP_EB_PASSWORD
,
1447 .type
= &setting_type_string
,
1450 /** Priority setting */
1451 struct setting priority_setting __setting
= {
1453 .description
= "Priority of these settings",
1454 .tag
= DHCP_EB_PRIORITY
,
1455 .type
= &setting_type_int8
,