[settings] Allow store_setting() to access the root settings block
[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, or NULL
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         /* NULL settings implies storing into the global settings root */
298         if ( ! settings )
299                 settings = &settings_root;
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         ssize_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         if ( raw_len < 0 )
835                 return raw_len;
836
837         {
838                 char raw_buf[ raw_len + 1 ];
839        
840                 fetch_string_setting ( settings, setting, raw_buf,
841                                        sizeof ( raw_buf ) );
842                 return uri_encode ( raw_buf, buf, len );
843         }
844 }
845
846 /** A URI-encoded string setting type */
847 struct setting_type setting_type_uristring __setting_type = {
848         .name = "uristring",
849         .storef = storef_uristring,
850         .fetchf = fetchf_uristring,
851 };
852
853 /**
854  * Parse and store value of IPv4 address setting
855  *
856  * @v settings          Settings block
857  * @v setting           Setting to store
858  * @v value             Formatted setting data
859  * @ret rc              Return status code
860  */
861 static int storef_ipv4 ( struct settings *settings, struct setting *setting,
862                          const char *value ) {
863         struct in_addr ipv4;
864
865         if ( inet_aton ( value, &ipv4 ) == 0 )
866                 return -EINVAL;
867         return store_setting ( settings, setting, &ipv4, sizeof ( ipv4 ) );
868 }
869
870 /**
871  * Fetch and format value of IPv4 address setting
872  *
873  * @v settings          Settings block, or NULL to search all blocks
874  * @v setting           Setting to fetch
875  * @v buf               Buffer to contain formatted value
876  * @v len               Length of buffer
877  * @ret len             Length of formatted value, or negative error
878  */
879 static int fetchf_ipv4 ( struct settings *settings, struct setting *setting,
880                          char *buf, size_t len ) {
881         struct in_addr ipv4;
882         int raw_len;
883
884         if ( ( raw_len = fetch_ipv4_setting ( settings, setting, &ipv4 ) ) < 0)
885                 return raw_len;
886         return snprintf ( buf, len, "%s", inet_ntoa ( ipv4 ) );
887 }
888
889 /** An IPv4 address setting type */
890 struct setting_type setting_type_ipv4 __setting_type = {
891         .name = "ipv4",
892         .storef = storef_ipv4,
893         .fetchf = fetchf_ipv4,
894 };
895
896 /**
897  * Parse and store value of integer setting
898  *
899  * @v settings          Settings block
900  * @v setting           Setting to store
901  * @v value             Formatted setting data
902  * @v size              Integer size, in bytes
903  * @ret rc              Return status code
904  */
905 static int storef_int ( struct settings *settings, struct setting *setting,
906                         const char *value, unsigned int size ) {
907         union {
908                 uint32_t num;
909                 uint8_t bytes[4];
910         } u;
911         char *endp;
912
913         u.num = htonl ( strtoul ( value, &endp, 0 ) );
914         if ( *endp )
915                 return -EINVAL;
916         return store_setting ( settings, setting, 
917                                &u.bytes[ sizeof ( u ) - size ], size );
918 }
919
920 /**
921  * Parse and store value of 8-bit integer setting
922  *
923  * @v settings          Settings block
924  * @v setting           Setting to store
925  * @v value             Formatted setting data
926  * @v size              Integer size, in bytes
927  * @ret rc              Return status code
928  */
929 static int storef_int8 ( struct settings *settings, struct setting *setting,
930                          const char *value ) {
931         return storef_int ( settings, setting, value, 1 );
932 }
933
934 /**
935  * Parse and store value of 16-bit integer setting
936  *
937  * @v settings          Settings block
938  * @v setting           Setting to store
939  * @v value             Formatted setting data
940  * @v size              Integer size, in bytes
941  * @ret rc              Return status code
942  */
943 static int storef_int16 ( struct settings *settings, struct setting *setting,
944                           const char *value ) {
945         return storef_int ( settings, setting, value, 2 );
946 }
947
948 /**
949  * Parse and store value of 32-bit integer setting
950  *
951  * @v settings          Settings block
952  * @v setting           Setting to store
953  * @v value             Formatted setting data
954  * @v size              Integer size, in bytes
955  * @ret rc              Return status code
956  */
957 static int storef_int32 ( struct settings *settings, struct setting *setting,
958                           const char *value ) {
959         return storef_int ( settings, setting, value, 4 );
960 }
961
962 /**
963  * Fetch and format value of signed integer setting
964  *
965  * @v settings          Settings block, or NULL to search all blocks
966  * @v setting           Setting to fetch
967  * @v buf               Buffer to contain formatted value
968  * @v len               Length of buffer
969  * @ret len             Length of formatted value, or negative error
970  */
971 static int fetchf_int ( struct settings *settings, struct setting *setting,
972                         char *buf, size_t len ) {
973         long value;
974         int rc;
975
976         if ( ( rc = fetch_int_setting ( settings, setting, &value ) ) < 0 )
977                 return rc;
978         return snprintf ( buf, len, "%ld", value );
979 }
980
981 /**
982  * Fetch and format value of unsigned integer setting
983  *
984  * @v settings          Settings block, or NULL to search all blocks
985  * @v setting           Setting to fetch
986  * @v buf               Buffer to contain formatted value
987  * @v len               Length of buffer
988  * @ret len             Length of formatted value, or negative error
989  */
990 static int fetchf_uint ( struct settings *settings, struct setting *setting,
991                          char *buf, size_t len ) {
992         unsigned long value;
993         int rc;
994
995         if ( ( rc = fetch_uint_setting ( settings, setting, &value ) ) < 0 )
996                 return rc;
997         return snprintf ( buf, len, "%#lx", value );
998 }
999
1000 /** A signed 8-bit integer setting type */
1001 struct setting_type setting_type_int8 __setting_type = {
1002         .name = "int8",
1003         .storef = storef_int8,
1004         .fetchf = fetchf_int,
1005 };
1006
1007 /** A signed 16-bit integer setting type */
1008 struct setting_type setting_type_int16 __setting_type = {
1009         .name = "int16",
1010         .storef = storef_int16,
1011         .fetchf = fetchf_int,
1012 };
1013
1014 /** A signed 32-bit integer setting type */
1015 struct setting_type setting_type_int32 __setting_type = {
1016         .name = "int32",
1017         .storef = storef_int32,
1018         .fetchf = fetchf_int,
1019 };
1020
1021 /** An unsigned 8-bit integer setting type */
1022 struct setting_type setting_type_uint8 __setting_type = {
1023         .name = "uint8",
1024         .storef = storef_int8,
1025         .fetchf = fetchf_uint,
1026 };
1027
1028 /** An unsigned 16-bit integer setting type */
1029 struct setting_type setting_type_uint16 __setting_type = {
1030         .name = "uint16",
1031         .storef = storef_int16,
1032         .fetchf = fetchf_uint,
1033 };
1034
1035 /** An unsigned 32-bit integer setting type */
1036 struct setting_type setting_type_uint32 __setting_type = {
1037         .name = "uint32",
1038         .storef = storef_int32,
1039         .fetchf = fetchf_uint,
1040 };
1041
1042 /**
1043  * Parse and store value of hex string setting
1044  *
1045  * @v settings          Settings block
1046  * @v setting           Setting to store
1047  * @v value             Formatted setting data
1048  * @ret rc              Return status code
1049  */
1050 static int storef_hex ( struct settings *settings, struct setting *setting,
1051                         const char *value ) {
1052         char *ptr = ( char * ) value;
1053         uint8_t bytes[ strlen ( value ) ]; /* cannot exceed strlen(value) */
1054         unsigned int len = 0;
1055
1056         while ( 1 ) {
1057                 bytes[len++] = strtoul ( ptr, &ptr, 16 );
1058                 switch ( *ptr ) {
1059                 case '\0' :
1060                         return store_setting ( settings, setting, bytes, len );
1061                 case ':' :
1062                         ptr++;
1063                         break;
1064                 default :
1065                         return -EINVAL;
1066                 }
1067         }
1068 }
1069
1070 /**
1071  * Fetch and format value of hex string setting
1072  *
1073  * @v settings          Settings block, or NULL to search all blocks
1074  * @v setting           Setting to fetch
1075  * @v buf               Buffer to contain formatted value
1076  * @v len               Length of buffer
1077  * @ret len             Length of formatted value, or negative error
1078  */
1079 static int fetchf_hex ( struct settings *settings, struct setting *setting,
1080                         char *buf, size_t len ) {
1081         int raw_len;
1082         int check_len;
1083         int used = 0;
1084         int i;
1085
1086         raw_len = fetch_setting_len ( settings, setting );
1087         if ( raw_len < 0 )
1088                 return raw_len;
1089
1090         {
1091                 uint8_t raw[raw_len];
1092
1093                 check_len = fetch_setting ( settings, setting, raw,
1094                                             sizeof ( raw ) );
1095                 if ( check_len < 0 )
1096                         return check_len;
1097                 assert ( check_len == raw_len );
1098                 
1099                 if ( len )
1100                         buf[0] = 0; /* Ensure that a terminating NUL exists */
1101                 for ( i = 0 ; i < raw_len ; i++ ) {
1102                         used += ssnprintf ( ( buf + used ), ( len - used ),
1103                                             "%s%02x", ( used ? ":" : "" ),
1104                                             raw[i] );
1105                 }
1106                 return used;
1107         }
1108 }
1109
1110 /** A hex-string setting */
1111 struct setting_type setting_type_hex __setting_type = {
1112         .name = "hex",
1113         .storef = storef_hex,
1114         .fetchf = fetchf_hex,
1115 };
1116
1117 /**
1118  * Parse and store value of UUID setting
1119  *
1120  * @v settings          Settings block
1121  * @v setting           Setting to store
1122  * @v value             Formatted setting data
1123  * @ret rc              Return status code
1124  */
1125 static int storef_uuid ( struct settings *settings __unused,
1126                          struct setting *setting __unused,
1127                          const char *value __unused ) {
1128         return -ENOTSUP;
1129 }
1130
1131 /**
1132  * Fetch and format value of UUID setting
1133  *
1134  * @v settings          Settings block, or NULL to search all blocks
1135  * @v setting           Setting to fetch
1136  * @v buf               Buffer to contain formatted value
1137  * @v len               Length of buffer
1138  * @ret len             Length of formatted value, or negative error
1139  */
1140 static int fetchf_uuid ( struct settings *settings, struct setting *setting,
1141                          char *buf, size_t len ) {
1142         union uuid uuid;
1143         int raw_len;
1144
1145         if ( ( raw_len = fetch_uuid_setting ( settings, setting, &uuid ) ) < 0)
1146                 return raw_len;
1147         return snprintf ( buf, len, "%s", uuid_ntoa ( &uuid ) );
1148 }
1149
1150 /** UUID setting type */
1151 struct setting_type setting_type_uuid __setting_type = {
1152         .name = "uuid",
1153         .storef = storef_uuid,
1154         .fetchf = fetchf_uuid,
1155 };
1156
1157 /******************************************************************************
1158  *
1159  * Settings
1160  *
1161  ******************************************************************************
1162  */
1163
1164 /** Hostname setting */
1165 struct setting hostname_setting __setting = {
1166         .name = "hostname",
1167         .description = "Host name",
1168         .tag = DHCP_HOST_NAME,
1169         .type = &setting_type_string,
1170 };
1171
1172 /** Filename setting */
1173 struct setting filename_setting __setting = {
1174         .name = "filename",
1175         .description = "Boot filename",
1176         .tag = DHCP_BOOTFILE_NAME,
1177         .type = &setting_type_string,
1178 };
1179
1180 /** Root path setting */
1181 struct setting root_path_setting __setting = {
1182         .name = "root-path",
1183         .description = "NFS/iSCSI root path",
1184         .tag = DHCP_ROOT_PATH,
1185         .type = &setting_type_string,
1186 };
1187
1188 /** Username setting */
1189 struct setting username_setting __setting = {
1190         .name = "username",
1191         .description = "User name",
1192         .tag = DHCP_EB_USERNAME,
1193         .type = &setting_type_string,
1194 };
1195
1196 /** Password setting */
1197 struct setting password_setting __setting = {
1198         .name = "password",
1199         .description = "Password",
1200         .tag = DHCP_EB_PASSWORD,
1201         .type = &setting_type_string,
1202 };
1203
1204 /** Priority setting */
1205 struct setting priority_setting __setting = {
1206         .name = "priority",
1207         .description = "Priority of these settings",
1208         .tag = DHCP_EB_PRIORITY,
1209         .type = &setting_type_int8,
1210 };