[settings] Avoid duplicate settings block names
[people/mcb30/gpxe.git] / src / core / settings.c
1 /*
2  * Copyright (C) 2008 Michael Brown <mbrown@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 #include <stdint.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <strings.h>
24 #include <byteswap.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <gpxe/in.h>
28 #include <gpxe/vsprintf.h>
29 #include <gpxe/dhcp.h>
30 #include <gpxe/uuid.h>
31 #include <gpxe/uri.h>
32 #include <gpxe/settings.h>
33
34 /** @file
35  *
36  * Configuration settings
37  *
38  */
39
40 /** Registered settings */
41 static struct setting settings[0]
42         __table_start ( struct setting, settings );
43 static struct setting settings_end[0]
44         __table_end ( struct setting, settings );
45
46 /** Registered setting types */
47 static struct setting_type setting_types[0]
48         __table_start ( struct setting_type, setting_types );
49 static struct setting_type setting_types_end[0]
50         __table_end ( struct setting_type, setting_types );
51
52 /** Registered settings applicators */
53 static struct settings_applicator settings_applicators[0]
54         __table_start ( struct settings_applicator, settings_applicators );
55 static struct settings_applicator settings_applicators_end[0]
56         __table_end ( struct settings_applicator, settings_applicators );
57
58 /******************************************************************************
59  *
60  * Registered settings blocks
61  *
62  ******************************************************************************
63  */
64
65 /**
66  * Store value of simple setting
67  *
68  * @v options           DHCP option block
69  * @v setting           Setting to store
70  * @v data              Setting data, or NULL to clear setting
71  * @v len               Length of setting data
72  * @ret rc              Return status code
73  */
74 int simple_settings_store ( struct settings *settings, struct setting *setting,
75                             const void *data, size_t len ) {
76         struct simple_settings *simple =
77                 container_of ( settings, struct simple_settings, settings );
78         return dhcpopt_extensible_store ( &simple->dhcpopts, setting->tag,
79                                           data, len );
80 }
81
82 /**
83  * Fetch value of simple setting
84  *
85  * @v options           DHCP option block
86  * @v setting           Setting to fetch
87  * @v data              Buffer to fill with setting data
88  * @v len               Length of buffer
89  * @ret len             Length of setting data, or negative error
90  */
91 int simple_settings_fetch ( struct settings *settings, struct setting *setting,
92                             void *data, size_t len ) {
93         struct simple_settings *simple =
94                 container_of ( settings, struct simple_settings, settings );
95         return dhcpopt_fetch ( &simple->dhcpopts, setting->tag, data, len );
96 }
97
98 /** Simple settings operations */
99 struct settings_operations simple_settings_operations = {
100         .store = simple_settings_store,
101         .fetch = simple_settings_fetch,
102 };
103
104 /** Root simple settings block */
105 struct simple_settings simple_settings_root = {
106         .settings = {
107                 .refcnt = NULL,
108                 .name = "",
109                 .siblings =
110                      LIST_HEAD_INIT ( simple_settings_root.settings.siblings ),
111                 .children =
112                      LIST_HEAD_INIT ( simple_settings_root.settings.children ),
113                 .op = &simple_settings_operations,
114         },
115 };
116
117 /** Root settings block */
118 #define settings_root simple_settings_root.settings
119
120 /**
121  * Apply all settings
122  *
123  * @ret rc              Return status code
124  */
125 static int apply_settings ( void ) {
126         struct settings_applicator *applicator;
127         int rc;
128
129         /* Call all settings applicators */
130         for ( applicator = settings_applicators ;
131               applicator < settings_applicators_end ; applicator++ ) {
132                 if ( ( rc = applicator->apply() ) != 0 ) {
133                         DBG ( "Could not apply settings using applicator "
134                               "%p: %s\n", applicator, strerror ( rc ) );
135                         return rc;
136                 }
137         }
138
139         return 0;
140 }
141
142 /**
143  * Reprioritise settings
144  *
145  * @v settings          Settings block
146  *
147  * Reorders the settings block amongst its siblings according to its
148  * priority.
149  */
150 static void reprioritise_settings ( struct settings *settings ) {
151         struct settings *parent = settings->parent;
152         long priority;
153         struct settings *tmp;
154         long tmp_priority;
155
156         /* Stop when we reach the top of the tree */
157         if ( ! parent )
158                 return;
159
160         /* Read priority, if present */
161         priority = fetch_intz_setting ( settings, &priority_setting );
162
163         /* Remove from siblings list */
164         list_del ( &settings->siblings );
165
166         /* Reinsert after any existing blocks which have a higher priority */
167         list_for_each_entry ( tmp, &parent->children, siblings ) {
168                 tmp_priority = fetch_intz_setting ( tmp, &priority_setting );
169                 if ( priority > tmp_priority )
170                         break;
171         }
172         list_add_tail ( &settings->siblings, &tmp->siblings );
173
174         /* Recurse up the tree */
175         reprioritise_settings ( parent );
176 }
177
178 /**
179  * Register settings block
180  *
181  * @v settings          Settings block
182  * @v parent            Parent settings block, or NULL
183  * @ret rc              Return status code
184  */
185 int register_settings ( struct settings *settings, struct settings *parent ) {
186         struct settings *old_settings;
187
188         /* NULL parent => add to settings root */
189         assert ( settings != NULL );
190         if ( parent == NULL )
191                 parent = &settings_root;
192
193         /* Remove any existing settings with the same name */
194         if ( ( old_settings = find_child_settings ( parent, settings->name ) ))
195                 unregister_settings ( old_settings );
196
197         /* Add to list of settings */
198         ref_get ( settings->refcnt );
199         ref_get ( parent->refcnt );
200         settings->parent = parent;
201         list_add_tail ( &settings->siblings, &parent->children );
202         DBGC ( settings, "Settings %p registered\n", settings );
203
204         /* Fix up settings priority */
205         reprioritise_settings ( settings );
206
207         /* Apply potentially-updated settings */
208         apply_settings();
209
210         return 0;
211 }
212
213 /**
214  * Unregister settings block
215  *
216  * @v settings          Settings block
217  */
218 void unregister_settings ( struct settings *settings ) {
219
220         /* Remove from list of settings */
221         ref_put ( settings->refcnt );
222         ref_put ( settings->parent->refcnt );
223         settings->parent = NULL;
224         list_del ( &settings->siblings );
225         DBGC ( settings, "Settings %p unregistered\n", settings );
226
227         /* Apply potentially-updated settings */
228         apply_settings();
229 }
230
231 /**
232  * Find child named settings block
233  *
234  * @v parent            Parent settings block
235  * @v name              Name within this parent
236  * @ret settings        Settings block, or NULL
237  */
238 struct settings * find_child_settings ( struct settings *parent,
239                                         const char *name ) {
240         struct settings *settings;
241         size_t len;
242
243         /* NULL parent => add to settings root */
244         if ( parent == NULL )
245                 parent = &settings_root;
246
247         /* Look for a child whose name matches the initial component */
248         list_for_each_entry ( settings, &parent->children, siblings ) {
249                 len = strlen ( settings->name );
250                 if ( strncmp ( name, settings->name, len ) != 0 )
251                         continue;
252                 if ( name[len] == 0 )
253                         return settings;
254                 if ( name[len] == '.' )
255                         return find_child_settings ( settings,
256                                                      ( name + len + 1 ) );
257         }
258
259         return NULL;
260 }
261
262 /**
263  * Find named settings block
264  *
265  * @v name              Name
266  * @ret settings        Settings block, or NULL
267  */
268 struct settings * find_settings ( const char *name ) {
269
270         /* If name is empty, use the root */
271         if ( ! *name )
272                 return &settings_root;
273
274         return find_child_settings ( &settings_root, name );
275 }
276
277 /******************************************************************************
278  *
279  * Core settings routines
280  *
281  ******************************************************************************
282  */
283
284 /**
285  * Store value of setting
286  *
287  * @v settings          Settings block
288  * @v setting           Setting to store
289  * @v data              Setting data, or NULL to clear setting
290  * @v len               Length of setting data
291  * @ret rc              Return status code
292  */
293 int store_setting ( struct settings *settings, struct setting *setting,
294                     const void *data, size_t len ) {
295         int rc;
296
297         /* Sanity check */
298         if ( ! settings )
299                 return -ENODEV;
300
301         /* Store setting */
302         if ( ( rc = settings->op->store ( settings, setting,
303                                           data, len ) ) != 0 )
304                 return rc;
305
306         /* Reprioritise settings if necessary */
307         if ( setting_cmp ( setting, &priority_setting ) == 0 )
308                 reprioritise_settings ( settings );
309
310         /* If these settings are registered, apply potentially-updated
311          * settings
312          */
313         for ( ; settings ; settings = settings->parent ) {
314                 if ( settings == &settings_root ) {
315                         if ( ( rc = apply_settings() ) != 0 )
316                                 return rc;
317                         break;
318                 }
319         }
320
321         return 0;
322 }
323
324 /**
325  * Fetch value of setting
326  *
327  * @v settings          Settings block, or NULL to search all blocks
328  * @v setting           Setting to fetch
329  * @v data              Buffer to fill with setting data
330  * @v len               Length of buffer
331  * @ret len             Length of setting data, or negative error
332  *
333  * The actual length of the setting will be returned even if
334  * the buffer was too small.
335  */
336 int fetch_setting ( struct settings *settings, struct setting *setting,
337                     void *data, size_t len ) {
338         struct settings *child;
339         int ret;
340
341         /* Avoid returning uninitialised data on error */
342         memset ( data, 0, len );
343
344         /* NULL settings implies starting at the global settings root */
345         if ( ! settings )
346                 settings = &settings_root;
347
348         /* Try this block first */
349         if ( ( ret = settings->op->fetch ( settings, setting,
350                                            data, len ) ) >= 0 )
351                 return ret;
352
353         /* Recurse into each child block in turn */
354         list_for_each_entry ( child, &settings->children, siblings ) {
355                 if ( ( ret = fetch_setting ( child, setting,
356                                              data, len ) ) >= 0 )
357                         return ret;
358         }
359
360         return -ENOENT;
361 }
362
363 /**
364  * Fetch length of setting
365  *
366  * @v settings          Settings block, or NULL to search all blocks
367  * @v setting           Setting to fetch
368  * @ret len             Length of setting data, or negative error
369  *
370  * This function can also be used as an existence check for the
371  * setting.
372  */
373 int fetch_setting_len ( struct settings *settings, struct setting *setting ) {
374         return fetch_setting ( settings, setting, NULL, 0 );
375 }
376
377 /**
378  * Fetch value of string setting
379  *
380  * @v settings          Settings block, or NULL to search all blocks
381  * @v setting           Setting to fetch
382  * @v data              Buffer to fill with setting string data
383  * @v len               Length of buffer
384  * @ret len             Length of string setting, or negative error
385  *
386  * The resulting string is guaranteed to be correctly NUL-terminated.
387  * The returned length will be the length of the underlying setting
388  * data.
389  */
390 int fetch_string_setting ( struct settings *settings, struct setting *setting,
391                            char *data, size_t len ) {
392         memset ( data, 0, len );
393         return fetch_setting ( settings, setting, data,
394                                ( ( len > 0 ) ? ( len - 1 ) : 0 ) );
395 }
396
397 /**
398  * Fetch value of string setting
399  *
400  * @v settings          Settings block, or NULL to search all blocks
401  * @v setting           Setting to fetch
402  * @v data              Buffer to allocate and fill with setting string data
403  * @ret len             Length of string setting, or negative error
404  *
405  * The resulting string is guaranteed to be correctly NUL-terminated.
406  * The returned length will be the length of the underlying setting
407  * data.  The caller is responsible for eventually freeing the
408  * allocated buffer.
409  */
410 int fetch_string_setting_copy ( struct settings *settings,
411                                 struct setting *setting,
412                                 char **data ) {
413         int len;
414         int check_len;
415
416         len = fetch_setting_len ( settings, setting );
417         if ( len < 0 )
418                 return len;
419
420         *data = malloc ( len + 1 );
421         if ( ! *data )
422                 return -ENOMEM;
423
424         fetch_string_setting ( settings, setting, *data, ( len + 1 ) );
425         assert ( check_len == len );
426         return len;
427 }
428
429 /**
430  * Fetch value of IPv4 address setting
431  *
432  * @v settings          Settings block, or NULL to search all blocks
433  * @v setting           Setting to fetch
434  * @v inp               IPv4 address to fill in
435  * @ret len             Length of setting, or negative error
436  */
437 int fetch_ipv4_setting ( struct settings *settings, struct setting *setting,
438                          struct in_addr *inp ) {
439         int len;
440
441         len = fetch_setting ( settings, setting, inp, sizeof ( *inp ) );
442         if ( len < 0 )
443                 return len;
444         if ( len < ( int ) sizeof ( *inp ) )
445                 return -ERANGE;
446         return len;
447 }
448
449 /**
450  * Fetch value of signed integer setting
451  *
452  * @v settings          Settings block, or NULL to search all blocks
453  * @v setting           Setting to fetch
454  * @v value             Integer value to fill in
455  * @ret len             Length of setting, or negative error
456  */
457 int fetch_int_setting ( struct settings *settings, struct setting *setting,
458                         long *value ) {
459         union {
460                 uint8_t u8[ sizeof ( long ) ];
461                 int8_t s8[ sizeof ( long ) ];
462         } buf;
463         int len;
464         int i;
465
466         /* Avoid returning uninitialised data on error */
467         *value = 0;
468
469         /* Fetch raw (network-ordered, variable-length) setting */
470         len = fetch_setting ( settings, setting, &buf, sizeof ( buf ) );
471         if ( len < 0 )
472                 return len;
473         if ( len > ( int ) sizeof ( buf ) )
474                 return -ERANGE;
475
476         /* Convert to host-ordered signed long */
477         *value = ( ( buf.s8[0] >= 0 ) ? 0 : -1L );
478         for ( i = 0 ; i < len ; i++ ) {
479                 *value = ( ( *value << 8 ) | buf.u8[i] );
480         }
481
482         return len;
483 }
484
485 /**
486  * Fetch value of unsigned integer setting
487  *
488  * @v settings          Settings block, or NULL to search all blocks
489  * @v setting           Setting to fetch
490  * @v value             Integer value to fill in
491  * @ret len             Length of setting, or negative error
492  */
493 int fetch_uint_setting ( struct settings *settings, struct setting *setting,
494                          unsigned long *value ) {
495         long svalue;
496         int len;
497
498         /* Avoid returning uninitialised data on error */
499         *value = 0;
500
501         /* Fetch as a signed long */
502         len = fetch_int_setting ( settings, setting, &svalue );
503         if ( len < 0 )
504                 return len;
505
506         /* Mask off sign-extended bits */
507         *value = ( svalue & ( -1UL >> ( sizeof ( long ) - len ) ) );
508
509         return len;
510 }
511
512 /**
513  * Fetch value of signed integer setting, or zero
514  *
515  * @v settings          Settings block, or NULL to search all blocks
516  * @v setting           Setting to fetch
517  * @ret value           Setting value, or zero
518  */
519 long fetch_intz_setting ( struct settings *settings, struct setting *setting ){
520         long value;
521
522         fetch_int_setting ( settings, setting, &value );
523         return value;
524 }
525
526 /**
527  * Fetch value of unsigned integer setting, or zero
528  *
529  * @v settings          Settings block, or NULL to search all blocks
530  * @v setting           Setting to fetch
531  * @ret value           Setting value, or zero
532  */
533 unsigned long fetch_uintz_setting ( struct settings *settings,
534                                     struct setting *setting ) {
535         unsigned long value;
536
537         fetch_uint_setting ( settings, setting, &value );
538         return value;
539 }
540
541 /**
542  * Fetch value of UUID setting
543  *
544  * @v settings          Settings block, or NULL to search all blocks
545  * @v setting           Setting to fetch
546  * @v uuid              UUID to fill in
547  * @ret len             Length of setting, or negative error
548  */
549 int fetch_uuid_setting ( struct settings *settings, struct setting *setting,
550                          union uuid *uuid ) {
551         int len;
552
553         len = fetch_setting ( settings, setting, uuid, sizeof ( *uuid ) );
554         if ( len < 0 )
555                 return len;
556         if ( len != sizeof ( *uuid ) )
557                 return -ERANGE;
558         return len;
559 }
560
561 /**
562  * Compare two settings
563  *
564  * @v a                 Setting to compare
565  * @v b                 Setting to compare
566  * @ret 0               Settings are the same
567  * @ret non-zero        Settings are not the same
568  */
569 int setting_cmp ( struct setting *a, struct setting *b ) {
570
571         /* If the settings have tags, compare them */
572         if ( a->tag && ( a->tag == b->tag ) )
573                 return 0;
574
575         /* Otherwise, compare the names */
576         return strcmp ( a->name, b->name );
577 }
578
579 /******************************************************************************
580  *
581  * Formatted setting routines
582  *
583  ******************************************************************************
584  */
585
586 /**
587  * Store value of typed setting
588  *
589  * @v settings          Settings block
590  * @v setting           Setting to store
591  * @v type              Settings type
592  * @v value             Formatted setting data, or NULL
593  * @ret rc              Return status code
594  */
595 int storef_setting ( struct settings *settings, struct setting *setting,
596                      const char *value ) {
597
598         /* NULL value implies deletion.  Avoid imposing the burden of
599          * checking for NULL values on each typed setting's storef()
600          * method.
601          */
602         if ( ! value )
603                 return delete_setting ( settings, setting );
604                 
605         return setting->type->storef ( settings, setting, value );
606 }
607
608 /**
609  * Find named setting
610  *
611  * @v name              Name
612  * @ret setting         Named setting, or NULL
613  */
614 static struct setting * find_setting ( const char *name ) {
615         struct setting *setting;
616
617         for ( setting = settings ; setting < settings_end ; setting++ ) {
618                 if ( strcmp ( name, setting->name ) == 0 )
619                         return setting;
620         }
621         return NULL;
622 }
623
624 /**
625  * Find setting type
626  *
627  * @v name              Name
628  * @ret type            Setting type, or NULL
629  */
630 static struct setting_type * find_setting_type ( const char *name ) {
631         struct setting_type *type;
632
633         for ( type = setting_types ; type < setting_types_end ; type++ ) {
634                 if ( strcmp ( name, type->name ) == 0 )
635                         return type;
636         }
637         return NULL;
638 }
639
640 /**
641  * Parse setting name
642  *
643  * @v name              Name of setting
644  * @v settings          Settings block to fill in
645  * @v setting           Setting to fill in
646  * @ret rc              Return status code
647  *
648  * Interprets a name of the form
649  * "[settings_name/]tag_name[:type_name]" and fills in the appropriate
650  * fields.
651  */
652 static int parse_setting_name ( const char *name, struct settings **settings,
653                                 struct setting *setting ) {
654         char tmp_name[ strlen ( name ) + 1 ];
655         char *settings_name;
656         char *setting_name;
657         char *type_name;
658         struct setting *named_setting;
659         char *tmp;
660
661         /* Set defaults */
662         *settings = &settings_root;
663         memset ( setting, 0, sizeof ( *setting ) );
664         setting->type = &setting_type_hex;
665
666         /* Split name into "[settings_name/]setting_name[:type_name]" */
667         memcpy ( tmp_name, name, sizeof ( tmp_name ) );
668         if ( ( setting_name = strchr ( tmp_name, '/' ) ) != NULL ) {
669                 *(setting_name++) = 0;
670                 settings_name = tmp_name;
671         } else {
672                 setting_name = tmp_name;
673                 settings_name = NULL;
674         }
675         if ( ( type_name = strchr ( setting_name, ':' ) ) != NULL )
676                 *(type_name++) = 0;
677
678         /* Identify settings block, if specified */
679         if ( settings_name ) {
680                 *settings = find_settings ( settings_name );
681                 if ( *settings == NULL ) {
682                         DBG ( "Unrecognised settings block \"%s\" in \"%s\"\n",
683                               settings_name, name );
684                         return -ENODEV;
685                 }
686         }
687
688         /* Identify tag number */
689         if ( ( named_setting = find_setting ( setting_name ) ) != NULL ) {
690                 memcpy ( setting, named_setting, sizeof ( *setting ) );
691         } else {
692                 /* Unrecognised name: try to interpret as a tag number */
693                 tmp = setting_name;
694                 while ( 1 ) {
695                         setting->tag = ( ( setting->tag << 8 ) |
696                                          strtoul ( tmp, &tmp, 0 ) );
697                         if ( *tmp == 0 )
698                                 break;
699                         if ( *tmp != '.' ) {
700                                 DBG ( "Invalid setting \"%s\" in \"%s\"\n",
701                                       setting_name, name );
702                                 return -ENOENT;
703                         }
704                         tmp++;
705                 }
706                 setting->tag |= (*settings)->tag_magic;
707         }
708
709         /* Identify setting type, if specified */
710         if ( type_name ) {
711                 setting->type = find_setting_type ( type_name );
712                 if ( setting->type == NULL ) {
713                         DBG ( "Invalid setting type \"%s\" in \"%s\"\n",
714                               type_name, name );
715                         return -ENOTSUP;
716                 }
717         }
718
719         return 0;
720 }
721
722 /**
723  * Parse and store value of named setting
724  *
725  * @v name              Name of setting
726  * @v value             Formatted setting data, or NULL
727  * @ret rc              Return status code
728  */
729 int storef_named_setting ( const char *name, const char *value ) {
730         struct settings *settings;
731         struct setting setting;
732         int rc;
733
734         if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
735                 return rc;
736         return storef_setting ( settings, &setting, value );
737 }
738
739 /**
740  * Fetch and format value of named setting
741  *
742  * @v name              Name of setting
743  * @v buf               Buffer to contain formatted value
744  * @v len               Length of buffer
745  * @ret len             Length of formatted value, or negative error
746  */
747 int fetchf_named_setting ( const char *name, char *buf, size_t len ) {
748         struct settings *settings;
749         struct setting setting;
750         int rc;
751
752         if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
753                 return rc;
754         return fetchf_setting ( settings, &setting, buf, len );
755 }
756
757 /******************************************************************************
758  *
759  * Setting types
760  *
761  ******************************************************************************
762  */
763
764 /**
765  * Parse and store value of string setting
766  *
767  * @v settings          Settings block
768  * @v setting           Setting to store
769  * @v value             Formatted setting data
770  * @ret rc              Return status code
771  */
772 static int storef_string ( struct settings *settings, struct setting *setting,
773                            const char *value ) {
774         return store_setting ( settings, setting, value, strlen ( value ) );
775 }
776
777 /**
778  * Fetch and format value of string setting
779  *
780  * @v settings          Settings block, or NULL to search all blocks
781  * @v setting           Setting to fetch
782  * @v buf               Buffer to contain formatted value
783  * @v len               Length of buffer
784  * @ret len             Length of formatted value, or negative error
785  */
786 static int fetchf_string ( struct settings *settings, struct setting *setting,
787                            char *buf, size_t len ) {
788         return fetch_string_setting ( settings, setting, buf, len );
789 }
790
791 /** A string setting type */
792 struct setting_type setting_type_string __setting_type = {
793         .name = "string",
794         .storef = storef_string,
795         .fetchf = fetchf_string,
796 };
797
798 /**
799  * Parse and store value of URI-encoded string setting
800  *
801  * @v settings          Settings block
802  * @v setting           Setting to store
803  * @v value             Formatted setting data
804  * @ret rc              Return status code
805  */
806 static int storef_uristring ( struct settings *settings,
807                               struct setting *setting,
808                               const char *value ) {
809         char buf[ strlen ( value ) + 1 ]; /* Decoding never expands string */
810         size_t len;
811
812         len = uri_decode ( value, buf, sizeof ( buf ) );
813         return store_setting ( settings, setting, buf, len );
814 }
815
816 /**
817  * Fetch and format value of URI-encoded string setting
818  *
819  * @v settings          Settings block, or NULL to search all blocks
820  * @v setting           Setting to fetch
821  * @v buf               Buffer to contain formatted value
822  * @v len               Length of buffer
823  * @ret len             Length of formatted value, or negative error
824  */
825 static int fetchf_uristring ( struct settings *settings,
826                               struct setting *setting,
827                               char *buf, size_t len ) {
828         size_t raw_len;
829
830         /* We need to always retrieve the full raw string to know the
831          * length of the encoded string.
832          */
833         raw_len = fetch_setting ( settings, setting, NULL, 0 );
834         {
835                 char raw_buf[ raw_len + 1 ];
836        
837                 fetch_string_setting ( settings, setting, raw_buf,
838                                        sizeof ( raw_buf ) );
839                 return uri_encode ( raw_buf, buf, len );
840         }
841 }
842
843 /** A URI-encoded string setting type */
844 struct setting_type setting_type_uristring __setting_type = {
845         .name = "uristring",
846         .storef = storef_uristring,
847         .fetchf = fetchf_uristring,
848 };
849
850 /**
851  * Parse and store value of IPv4 address setting
852  *
853  * @v settings          Settings block
854  * @v setting           Setting to store
855  * @v value             Formatted setting data
856  * @ret rc              Return status code
857  */
858 static int storef_ipv4 ( struct settings *settings, struct setting *setting,
859                          const char *value ) {
860         struct in_addr ipv4;
861
862         if ( inet_aton ( value, &ipv4 ) == 0 )
863                 return -EINVAL;
864         return store_setting ( settings, setting, &ipv4, sizeof ( ipv4 ) );
865 }
866
867 /**
868  * Fetch and format value of IPv4 address setting
869  *
870  * @v settings          Settings block, or NULL to search all blocks
871  * @v setting           Setting to fetch
872  * @v buf               Buffer to contain formatted value
873  * @v len               Length of buffer
874  * @ret len             Length of formatted value, or negative error
875  */
876 static int fetchf_ipv4 ( struct settings *settings, struct setting *setting,
877                          char *buf, size_t len ) {
878         struct in_addr ipv4;
879         int raw_len;
880
881         if ( ( raw_len = fetch_ipv4_setting ( settings, setting, &ipv4 ) ) < 0)
882                 return raw_len;
883         return snprintf ( buf, len, "%s", inet_ntoa ( ipv4 ) );
884 }
885
886 /** An IPv4 address setting type */
887 struct setting_type setting_type_ipv4 __setting_type = {
888         .name = "ipv4",
889         .storef = storef_ipv4,
890         .fetchf = fetchf_ipv4,
891 };
892
893 /**
894  * Parse and store value of integer setting
895  *
896  * @v settings          Settings block
897  * @v setting           Setting to store
898  * @v value             Formatted setting data
899  * @v size              Integer size, in bytes
900  * @ret rc              Return status code
901  */
902 static int storef_int ( struct settings *settings, struct setting *setting,
903                         const char *value, unsigned int size ) {
904         union {
905                 uint32_t num;
906                 uint8_t bytes[4];
907         } u;
908         char *endp;
909
910         u.num = htonl ( strtoul ( value, &endp, 0 ) );
911         if ( *endp )
912                 return -EINVAL;
913         return store_setting ( settings, setting, 
914                                &u.bytes[ sizeof ( u ) - size ], size );
915 }
916
917 /**
918  * Parse and store value of 8-bit integer setting
919  *
920  * @v settings          Settings block
921  * @v setting           Setting to store
922  * @v value             Formatted setting data
923  * @v size              Integer size, in bytes
924  * @ret rc              Return status code
925  */
926 static int storef_int8 ( struct settings *settings, struct setting *setting,
927                          const char *value ) {
928         return storef_int ( settings, setting, value, 1 );
929 }
930
931 /**
932  * Parse and store value of 16-bit integer setting
933  *
934  * @v settings          Settings block
935  * @v setting           Setting to store
936  * @v value             Formatted setting data
937  * @v size              Integer size, in bytes
938  * @ret rc              Return status code
939  */
940 static int storef_int16 ( struct settings *settings, struct setting *setting,
941                           const char *value ) {
942         return storef_int ( settings, setting, value, 2 );
943 }
944
945 /**
946  * Parse and store value of 32-bit integer setting
947  *
948  * @v settings          Settings block
949  * @v setting           Setting to store
950  * @v value             Formatted setting data
951  * @v size              Integer size, in bytes
952  * @ret rc              Return status code
953  */
954 static int storef_int32 ( struct settings *settings, struct setting *setting,
955                           const char *value ) {
956         return storef_int ( settings, setting, value, 4 );
957 }
958
959 /**
960  * Fetch and format value of signed integer setting
961  *
962  * @v settings          Settings block, or NULL to search all blocks
963  * @v setting           Setting to fetch
964  * @v buf               Buffer to contain formatted value
965  * @v len               Length of buffer
966  * @ret len             Length of formatted value, or negative error
967  */
968 static int fetchf_int ( struct settings *settings, struct setting *setting,
969                         char *buf, size_t len ) {
970         long value;
971         int rc;
972
973         if ( ( rc = fetch_int_setting ( settings, setting, &value ) ) < 0 )
974                 return rc;
975         return snprintf ( buf, len, "%ld", value );
976 }
977
978 /**
979  * Fetch and format value of unsigned integer setting
980  *
981  * @v settings          Settings block, or NULL to search all blocks
982  * @v setting           Setting to fetch
983  * @v buf               Buffer to contain formatted value
984  * @v len               Length of buffer
985  * @ret len             Length of formatted value, or negative error
986  */
987 static int fetchf_uint ( struct settings *settings, struct setting *setting,
988                          char *buf, size_t len ) {
989         unsigned long value;
990         int rc;
991
992         if ( ( rc = fetch_uint_setting ( settings, setting, &value ) ) < 0 )
993                 return rc;
994         return snprintf ( buf, len, "%#lx", value );
995 }
996
997 /** A signed 8-bit integer setting type */
998 struct setting_type setting_type_int8 __setting_type = {
999         .name = "int8",
1000         .storef = storef_int8,
1001         .fetchf = fetchf_int,
1002 };
1003
1004 /** A signed 16-bit integer setting type */
1005 struct setting_type setting_type_int16 __setting_type = {
1006         .name = "int16",
1007         .storef = storef_int16,
1008         .fetchf = fetchf_int,
1009 };
1010
1011 /** A signed 32-bit integer setting type */
1012 struct setting_type setting_type_int32 __setting_type = {
1013         .name = "int32",
1014         .storef = storef_int32,
1015         .fetchf = fetchf_int,
1016 };
1017
1018 /** An unsigned 8-bit integer setting type */
1019 struct setting_type setting_type_uint8 __setting_type = {
1020         .name = "uint8",
1021         .storef = storef_int8,
1022         .fetchf = fetchf_uint,
1023 };
1024
1025 /** An unsigned 16-bit integer setting type */
1026 struct setting_type setting_type_uint16 __setting_type = {
1027         .name = "uint16",
1028         .storef = storef_int16,
1029         .fetchf = fetchf_uint,
1030 };
1031
1032 /** An unsigned 32-bit integer setting type */
1033 struct setting_type setting_type_uint32 __setting_type = {
1034         .name = "uint32",
1035         .storef = storef_int32,
1036         .fetchf = fetchf_uint,
1037 };
1038
1039 /**
1040  * Parse and store value of hex string setting
1041  *
1042  * @v settings          Settings block
1043  * @v setting           Setting to store
1044  * @v value             Formatted setting data
1045  * @ret rc              Return status code
1046  */
1047 static int storef_hex ( struct settings *settings, struct setting *setting,
1048                         const char *value ) {
1049         char *ptr = ( char * ) value;
1050         uint8_t bytes[ strlen ( value ) ]; /* cannot exceed strlen(value) */
1051         unsigned int len = 0;
1052
1053         while ( 1 ) {
1054                 bytes[len++] = strtoul ( ptr, &ptr, 16 );
1055                 switch ( *ptr ) {
1056                 case '\0' :
1057                         return store_setting ( settings, setting, bytes, len );
1058                 case ':' :
1059                         ptr++;
1060                         break;
1061                 default :
1062                         return -EINVAL;
1063                 }
1064         }
1065 }
1066
1067 /**
1068  * Fetch and format value of hex string setting
1069  *
1070  * @v settings          Settings block, or NULL to search all blocks
1071  * @v setting           Setting to fetch
1072  * @v buf               Buffer to contain formatted value
1073  * @v len               Length of buffer
1074  * @ret len             Length of formatted value, or negative error
1075  */
1076 static int fetchf_hex ( struct settings *settings, struct setting *setting,
1077                         char *buf, size_t len ) {
1078         int raw_len;
1079         int check_len;
1080         int used = 0;
1081         int i;
1082
1083         raw_len = fetch_setting_len ( settings, setting );
1084         if ( raw_len < 0 )
1085                 return raw_len;
1086
1087         {
1088                 uint8_t raw[raw_len];
1089
1090                 check_len = fetch_setting ( settings, setting, raw,
1091                                             sizeof ( raw ) );
1092                 if ( check_len < 0 )
1093                         return check_len;
1094                 assert ( check_len == raw_len );
1095                 
1096                 if ( len )
1097                         buf[0] = 0; /* Ensure that a terminating NUL exists */
1098                 for ( i = 0 ; i < raw_len ; i++ ) {
1099                         used += ssnprintf ( ( buf + used ), ( len - used ),
1100                                             "%s%02x", ( used ? ":" : "" ),
1101                                             raw[i] );
1102                 }
1103                 return used;
1104         }
1105 }
1106
1107 /** A hex-string setting */
1108 struct setting_type setting_type_hex __setting_type = {
1109         .name = "hex",
1110         .storef = storef_hex,
1111         .fetchf = fetchf_hex,
1112 };
1113
1114 /**
1115  * Parse and store value of UUID setting
1116  *
1117  * @v settings          Settings block
1118  * @v setting           Setting to store
1119  * @v value             Formatted setting data
1120  * @ret rc              Return status code
1121  */
1122 static int storef_uuid ( struct settings *settings __unused,
1123                          struct setting *setting __unused,
1124                          const char *value __unused ) {
1125         return -ENOTSUP;
1126 }
1127
1128 /**
1129  * Fetch and format value of UUID setting
1130  *
1131  * @v settings          Settings block, or NULL to search all blocks
1132  * @v setting           Setting to fetch
1133  * @v buf               Buffer to contain formatted value
1134  * @v len               Length of buffer
1135  * @ret len             Length of formatted value, or negative error
1136  */
1137 static int fetchf_uuid ( struct settings *settings, struct setting *setting,
1138                          char *buf, size_t len ) {
1139         union uuid uuid;
1140         int raw_len;
1141
1142         if ( ( raw_len = fetch_uuid_setting ( settings, setting, &uuid ) ) < 0)
1143                 return raw_len;
1144         return snprintf ( buf, len, "%s", uuid_ntoa ( &uuid ) );
1145 }
1146
1147 /** UUID setting type */
1148 struct setting_type setting_type_uuid __setting_type = {
1149         .name = "uuid",
1150         .storef = storef_uuid,
1151         .fetchf = fetchf_uuid,
1152 };
1153
1154 /******************************************************************************
1155  *
1156  * Settings
1157  *
1158  ******************************************************************************
1159  */
1160
1161 /** Hostname setting */
1162 struct setting hostname_setting __setting = {
1163         .name = "hostname",
1164         .description = "Host name",
1165         .tag = DHCP_HOST_NAME,
1166         .type = &setting_type_string,
1167 };
1168
1169 /** Filename setting */
1170 struct setting filename_setting __setting = {
1171         .name = "filename",
1172         .description = "Boot filename",
1173         .tag = DHCP_BOOTFILE_NAME,
1174         .type = &setting_type_string,
1175 };
1176
1177 /** Root path setting */
1178 struct setting root_path_setting __setting = {
1179         .name = "root-path",
1180         .description = "NFS/iSCSI root path",
1181         .tag = DHCP_ROOT_PATH,
1182         .type = &setting_type_string,
1183 };
1184
1185 /** Username setting */
1186 struct setting username_setting __setting = {
1187         .name = "username",
1188         .description = "User name",
1189         .tag = DHCP_EB_USERNAME,
1190         .type = &setting_type_string,
1191 };
1192
1193 /** Password setting */
1194 struct setting password_setting __setting = {
1195         .name = "password",
1196         .description = "Password",
1197         .tag = DHCP_EB_PASSWORD,
1198         .type = &setting_type_string,
1199 };
1200
1201 /** Priority setting */
1202 struct setting priority_setting __setting = {
1203         .name = "priority",
1204         .description = "Priority of these settings",
1205         .tag = DHCP_EB_PRIORITY,
1206         .type = &setting_type_int8,
1207 };