a5c7f8169ab16c8d835aed118fb3bef5f6ad568d
[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/settings.h>
31
32 /** @file
33  *
34  * Configuration settings
35  *
36  */
37
38 /** Registered setting types */
39 static struct setting_type setting_types[0]
40         __table_start ( struct setting_type, setting_types );
41 static struct setting_type setting_types_end[0]
42         __table_end ( struct setting_type, setting_types );
43
44 /** Registered named settings */
45 static struct named_setting named_settings[0]
46         __table_start ( struct named_setting, named_settings );
47 static struct named_setting named_settings_end[0]
48         __table_end ( struct named_setting, named_settings );
49
50 struct setting_type setting_type_hex __setting_type;
51
52 /**
53  * Obtain printable version of a settings tag number
54  *
55  * @v tag               Settings tag number
56  * @ret name            String representation of the tag
57  */
58 static inline char * setting_tag_name ( unsigned int tag ) {
59         static char name[8];
60
61         if ( DHCP_IS_ENCAP_OPT ( tag ) ) {
62                 snprintf ( name, sizeof ( name ), "%d.%d",
63                            DHCP_ENCAPSULATOR ( tag ),
64                            DHCP_ENCAPSULATED ( tag ) );
65         } else {
66                 snprintf ( name, sizeof ( name ), "%d", tag );
67         }
68         return name;
69 }
70
71 /******************************************************************************
72  *
73  * Registered settings blocks
74  *
75  ******************************************************************************
76  */
77
78 /** List of all registered settings */
79 static struct list_head all_settings = {
80         &interactive_settings.list, &interactive_settings.list
81 };
82
83 // Dummy routine just for testing
84 static int dummy_set ( struct settings *settings, unsigned int tag,
85                        const void *data, size_t len ) {
86         DBGC ( settings, "Settings %p: set %s to:\n",
87                settings, setting_tag_name ( tag ) );
88         DBGC_HD ( settings, data, len );
89         return 0;
90 }
91
92 // Dummy routine just for testing
93 static int dummy_get ( struct settings *settings, unsigned int tag,
94                        void *data, size_t len ) {
95         unsigned int i;
96
97         DBGC ( settings, "Settings %p: get %s\n",
98                settings, setting_tag_name ( tag ) );
99         for ( i = 0 ; i < len ; i++ )
100                 *( ( ( uint8_t * ) data ) + i ) = i;
101         return ( len ? len : 8 );
102 }
103
104 struct settings_operations dummy_settings_operations = {
105         .set = dummy_set,
106         .get = dummy_get,
107 };
108
109 /** Interactively-edited settings */
110 struct settings interactive_settings = {
111         .refcnt = NULL,
112         .name = "",
113         .list = { &all_settings, &all_settings },
114         .op = &dummy_settings_operations,
115 };
116
117 /**
118  * Find named settings block
119  *
120  * @v name              Name
121  * @ret settings        Settings block, or NULL
122  */
123 struct settings * find_settings ( const char *name ) {
124         struct settings *settings;
125
126         list_for_each_entry ( settings, &all_settings, list ) {
127                 if ( strcasecmp ( name, settings->name ) == 0 )
128                         return settings;
129         }
130         return NULL;
131 }
132
133 /******************************************************************************
134  *
135  * Core settings routines
136  *
137  ******************************************************************************
138  */
139
140 /**
141  * Get value of setting
142  *
143  * @v settings          Settings block, or NULL to search all blocks
144  * @v tag               Setting tag number
145  * @v data              Buffer to fill with setting data
146  * @v len               Length of buffer
147  * @ret len             Length of setting data, or negative error
148  *
149  * The actual length of the setting will be returned even if
150  * the buffer was too small.
151  */
152 int get_setting ( struct settings *settings, unsigned int tag,
153                   void *data, size_t len ) {
154         int ret;
155
156         if ( settings ) {
157                 return settings->op->get ( settings, tag, data, len );
158         } else {
159                 list_for_each_entry ( settings, &all_settings, list ) {
160                         if ( ( ret = settings->op->get ( settings, tag,
161                                                          data, len ) ) >= 0 )
162                                 return ret;
163                 }
164                 return -ENOENT;
165         }
166 }
167
168 /**
169  * Get length of setting
170  *
171  * @v settings          Settings block, or NULL to search all blocks
172  * @v tag               Setting tag number
173  * @ret len             Length of setting data, or negative error
174  *
175  * This function can also be used as an existence check for the
176  * setting.
177  */
178 int get_setting_len ( struct settings *settings, unsigned int tag ) {
179         return get_setting ( settings, tag, NULL, 0 );
180 }
181
182 /**
183  * Get value of string setting
184  *
185  * @v settings          Settings block, or NULL to search all blocks
186  * @v tag               Setting tag number
187  * @v data              Buffer to fill with setting string data
188  * @v len               Length of buffer
189  * @ret len             Length of string setting, or negative error
190  *
191  * The resulting string is guaranteed to be correctly NUL-terminated.
192  * The returned length will be the length of the underlying setting
193  * data.
194  */
195 int get_string_setting ( struct settings *settings, unsigned int tag,
196                          char *data, size_t len ) {
197         memset ( data, 0, len );
198         return get_setting ( settings, tag, data, ( len - 1 ) );
199 }
200
201 /**
202  * Get value of IPv4 address setting
203  *
204  * @v settings          Settings block, or NULL to search all blocks
205  * @v tag               Setting tag number
206  * @v inp               IPv4 address to fill in
207  * @ret len             Length of setting, or negative error
208  */
209 int get_ipv4_setting ( struct settings *settings, unsigned int tag,
210                        struct in_addr *inp ) {
211         int len;
212
213         len = get_setting ( settings, tag, inp, sizeof ( *inp ) );
214         if ( len < 0 )
215                 return len;
216         if ( len != sizeof ( *inp ) )
217                 return -ERANGE;
218         return len;
219 }
220
221 /**
222  * Get value of signed integer setting
223  *
224  * @v settings          Settings block, or NULL to search all blocks
225  * @v tag               Setting tag number
226  * @v value             Integer value to fill in
227  * @ret len             Length of setting, or negative error
228  */
229 int get_int_setting ( struct settings *settings, unsigned int tag,
230                       long *value ) {
231         union {
232                 long value;
233                 uint8_t u8[ sizeof ( long ) ];
234                 int8_t s8[ sizeof ( long ) ];
235         } buf;
236         int len;
237         int i;
238
239         buf.value = 0;
240         len = get_setting ( settings, tag, &buf, sizeof ( buf ) );
241         if ( len < 0 )
242                 return len;
243         if ( len > ( int ) sizeof ( buf ) )
244                 return -ERANGE;
245
246         *value = ( ( buf.s8[0] >= 0 ) ? 0 : -1L );
247         for ( i = 0 ; i < len ; i++ ) {
248                 *value = ( ( *value << 8 ) | buf.u8[i] );
249         }
250
251         return len;
252 }
253
254 /**
255  * Get value of unsigned integer setting
256  *
257  * @v settings          Settings block, or NULL to search all blocks
258  * @v tag               Setting tag number
259  * @v value             Integer value to fill in
260  * @ret len             Length of setting, or negative error
261  */
262 int get_uint_setting ( struct settings *settings, unsigned int tag,
263                        unsigned long *value ) {
264         long svalue;
265         int len;
266
267         len = get_int_setting ( settings, tag, &svalue );
268         if ( len < 0 )
269                 return len;
270
271         *value = ( svalue & ( -1UL >> ( sizeof ( long ) - len ) ) );
272
273         return len;
274 }
275
276 /******************************************************************************
277  *
278  * Named and typed setting routines
279  *
280  ******************************************************************************
281  */
282
283 /**
284  * Set value of typed setting
285  *
286  * @v settings          Settings block
287  * @v tag               Setting tag number
288  * @v type              Settings type
289  * @v value             Formatted setting data, or NULL
290  * @ret rc              Return status code
291  */
292 int set_typed_setting ( struct settings *settings,
293                         unsigned int tag, struct setting_type *type,
294                         const char *value ) {
295
296         /* NULL value implies deletion.  Avoid imposing the burden of
297          * checking for NULL values on each typed setting's setf()
298          * method.
299          */
300         if ( ! value )
301                 return delete_setting ( settings, tag );
302                 
303         return type->setf ( settings, tag, value );
304 }
305
306 /**
307  * Find named setting
308  *
309  * @v name              Name
310  * @ret setting         Named setting, or NULL
311  */
312 static struct named_setting * find_named_setting ( const char *name ) {
313         struct named_setting *setting;
314
315         for ( setting = named_settings ; setting < named_settings_end ;
316               setting++ ) {
317                 if ( strcasecmp ( name, setting->name ) == 0 )
318                         return setting;
319         }
320         return NULL;
321 }
322
323 /**
324  * Find setting type
325  *
326  * @v name              Name
327  * @ret type            Setting type, or NULL
328  */
329 static struct setting_type * find_setting_type ( const char *name ) {
330         struct setting_type *type;
331
332         for ( type = setting_types ; type < setting_types_end ; type++ ) {
333                 if ( strcasecmp ( name, type->name ) == 0 )
334                         return type;
335         }
336         return NULL;
337 }
338
339 /**
340  * Parse setting name
341  *
342  * @v name              Name of setting
343  * @ret settings        Settings block, or NULL
344  * @ret tag             Setting tag number
345  * @ret type            Setting type
346  * @ret rc              Return status code
347  *
348  * Interprets a name of the form
349  * "[settings_name/]tag_name[:type_name]" and fills in the appropriate
350  * fields.
351  */
352 static int parse_setting_name ( const char *name, struct settings **settings,
353                                 unsigned int *tag,
354                                 struct setting_type **type ) {
355         char tmp_name[ strlen ( name ) + 1 ];
356         char *settings_name;
357         char *tag_name;
358         char *type_name;
359         struct named_setting *named_setting;
360         char *tmp;
361
362         /* Set defaults */
363         *settings = NULL;
364         *tag = 0;
365         *type = &setting_type_hex;
366
367         /* Split name into "[settings_name/]tag_name[:type_name]" */
368         memcpy ( tmp_name, name, sizeof ( tmp_name ) );
369         if ( ( tag_name = strchr ( tmp_name, '/' ) ) != NULL ) {
370                 *(tag_name++) = 0;
371                 settings_name = tmp_name;
372         } else {
373                 tag_name = tmp_name;
374                 settings_name = NULL;
375         }
376         if ( ( type_name = strchr ( tag_name, ':' ) ) != NULL )
377                 *(type_name++) = 0;
378
379         /* Identify settings block, if specified */
380         if ( settings_name ) {
381                 *settings = find_settings ( settings_name );
382                 if ( *settings == NULL ) {
383                         DBG ( "Unrecognised settings block \"%s\" in \"%s\"\n",
384                               settings_name, name );
385                         return -ENODEV;
386                 }
387         }
388
389         /* Identify tag number */
390         if ( ( named_setting = find_named_setting ( tag_name ) ) != NULL ) {
391                 *tag = named_setting->tag;
392                 *type = named_setting->type;
393         } else {
394                 /* Unrecognised name: try to interpret as a tag number */
395                 tmp = tag_name;
396                 while ( 1 ) {
397                         *tag = ( ( *tag << 8 ) | strtoul ( tmp, &tmp, 0 ) );
398                         if ( *tmp == 0 )
399                                 break;
400                         if ( *tmp != '.' ) {
401                                 DBG ( "Invalid tag number \"%s\" in \"%s\"\n",
402                                       tag_name, name );
403                                 return -ENOENT;
404                         }
405                         tmp++;
406                 }
407         }
408
409         /* Identify setting type, if specified */
410         if ( type_name ) {
411                 *type = find_setting_type ( type_name );
412                 if ( *type == NULL ) {
413                         DBG ( "Invalid setting type \"%s\" in \"%s\"\n",
414                               type_name, name );
415                         return -ENOTSUP;
416                 }
417         }
418
419         return 0;
420 }
421
422 /**
423  * Parse and set value of named setting
424  *
425  * @v name              Name of setting
426  * @v value             Formatted setting data, or NULL
427  * @ret rc              Return status code
428  */
429 int set_named_setting ( const char *name, const char *value ) {
430         struct settings *settings;
431         unsigned int tag;
432         struct setting_type *type;
433         int rc;
434
435         if ( ( rc = parse_setting_name ( name, &settings, &tag,
436                                          &type ) ) != 0 )
437                 return rc;
438         if ( settings == NULL )
439                 return -ENODEV;
440         return set_typed_setting ( settings, tag, type, value );
441 }
442
443 /**
444  * Get and format value of named setting
445  *
446  * @v name              Name of setting
447  * @v buf               Buffer to contain formatted value
448  * @v len               Length of buffer
449  * @ret len             Length of formatted value, or negative error
450  */
451 int get_named_setting ( const char *name, char *buf, size_t len ) {
452         struct settings *settings;
453         unsigned int tag;
454         struct setting_type *type;
455         int rc;
456
457         if ( ( rc = parse_setting_name ( name, &settings, &tag,
458                                          &type ) ) != 0 )
459                 return rc;
460         return get_typed_setting ( settings, tag, type, buf, len );
461 }
462
463 /******************************************************************************
464  *
465  * Setting types
466  *
467  ******************************************************************************
468  */
469
470 /**
471  * Parse and set value of string setting
472  *
473  * @v settings          Settings block
474  * @v tag               Setting tag number
475  * @v value             Formatted setting data
476  * @ret rc              Return status code
477  */
478 static int setf_string ( struct settings *settings, unsigned int tag,
479                          const char *value ) {
480         return set_setting ( settings, tag, value, strlen ( value ) );
481 }
482
483 /**
484  * Get and format value of string setting
485  *
486  * @v settings          Settings block, or NULL to search all blocks
487  * @v tag               Setting tag number
488  * @v buf               Buffer to contain formatted value
489  * @v len               Length of buffer
490  * @ret len             Length of formatted value, or negative error
491  */
492 static int getf_string ( struct settings *settings, unsigned int tag,
493                          char *buf, size_t len ) {
494         return get_string_setting ( settings, tag, buf, len );
495 }
496
497 /** A string setting type */
498 struct setting_type setting_type_string __setting_type = {
499         .name = "string",
500         .setf = setf_string,
501         .getf = getf_string,
502 };
503
504 /**
505  * Parse and set value of IPv4 address setting
506  *
507  * @v settings          Settings block
508  * @v tag               Setting tag number
509  * @v value             Formatted setting data
510  * @ret rc              Return status code
511  */
512 static int setf_ipv4 ( struct settings *settings, unsigned int tag,
513                        const char *value ) {
514         struct in_addr ipv4;
515
516         if ( inet_aton ( value, &ipv4 ) == 0 )
517                 return -EINVAL;
518         return set_setting ( settings, tag, &ipv4, sizeof ( ipv4 ) );
519 }
520
521 /**
522  * Get and format value of IPv4 address setting
523  *
524  * @v settings          Settings block, or NULL to search all blocks
525  * @v tag               Setting tag number
526  * @v buf               Buffer to contain formatted value
527  * @v len               Length of buffer
528  * @ret len             Length of formatted value, or negative error
529  */
530 static int getf_ipv4 ( struct settings *settings, unsigned int tag,
531                        char *buf, size_t len ) {
532         struct in_addr ipv4;
533         int rc;
534
535         if ( ( rc = get_ipv4_setting ( settings, tag, &ipv4 ) ) < 0 )
536                 return rc;
537         return snprintf ( buf, len, inet_ntoa ( ipv4 ) );
538 }
539
540 /** An IPv4 address setting type */
541 struct setting_type setting_type_ipv4 __setting_type = {
542         .name = "ipv4",
543         .setf = setf_ipv4,
544         .getf = getf_ipv4,
545 };
546
547 /**
548  * Parse and set value of integer setting
549  *
550  * @v settings          Settings block
551  * @v tag               Setting tag number
552  * @v value             Formatted setting data
553  * @v size              Integer size, in bytes
554  * @ret rc              Return status code
555  */
556 static int setf_int ( struct settings *settings, unsigned int tag,
557                       const char *value, unsigned int size ) {
558         union {
559                 uint32_t num;
560                 uint8_t bytes[4];
561         } u;
562         char *endp;
563
564         u.num = htonl ( strtoul ( value, &endp, 0 ) );
565         if ( *endp )
566                 return -EINVAL;
567         return set_setting ( settings, tag, 
568                              &u.bytes[ sizeof ( u ) - size ], size );
569 }
570
571 /**
572  * Parse and set value of 8-bit integer setting
573  *
574  * @v settings          Settings block
575  * @v tag               Setting tag number
576  * @v value             Formatted setting data
577  * @v size              Integer size, in bytes
578  * @ret rc              Return status code
579  */
580 static int setf_int8 ( struct settings *settings, unsigned int tag,
581                        const char *value ) {
582         return setf_int ( settings, tag, value, 1 );
583 }
584
585 /**
586  * Parse and set value of 16-bit integer setting
587  *
588  * @v settings          Settings block
589  * @v tag               Setting tag number
590  * @v value             Formatted setting data
591  * @v size              Integer size, in bytes
592  * @ret rc              Return status code
593  */
594 static int setf_int16 ( struct settings *settings, unsigned int tag,
595                        const char *value ) {
596         return setf_int ( settings, tag, value, 2 );
597 }
598
599 /**
600  * Parse and set value of 32-bit integer setting
601  *
602  * @v settings          Settings block
603  * @v tag               Setting tag number
604  * @v value             Formatted setting data
605  * @v size              Integer size, in bytes
606  * @ret rc              Return status code
607  */
608 static int setf_int32 ( struct settings *settings, unsigned int tag,
609                        const char *value ) {
610         return setf_int ( settings, tag, value, 4 );
611 }
612
613 /**
614  * Get and format value of signed integer setting
615  *
616  * @v settings          Settings block, or NULL to search all blocks
617  * @v tag               Setting tag number
618  * @v buf               Buffer to contain formatted value
619  * @v len               Length of buffer
620  * @ret len             Length of formatted value, or negative error
621  */
622 static int getf_int ( struct settings *settings, unsigned int tag,
623                       char *buf, size_t len ) {
624         long value;
625         int rc;
626
627         if ( ( rc = get_int_setting ( settings, tag, &value ) ) < 0 )
628                 return rc;
629         return snprintf ( buf, len, "%ld", value );
630 }
631
632 /**
633  * Get and format value of unsigned integer setting
634  *
635  * @v settings          Settings block, or NULL to search all blocks
636  * @v tag               Setting tag number
637  * @v buf               Buffer to contain formatted value
638  * @v len               Length of buffer
639  * @ret len             Length of formatted value, or negative error
640  */
641 static int getf_uint ( struct settings *settings, unsigned int tag,
642                        char *buf, size_t len ) {
643         unsigned long value;
644         int rc;
645
646         if ( ( rc = get_uint_setting ( settings, tag, &value ) ) < 0 )
647                 return rc;
648         return snprintf ( buf, len, "%#lx", value );
649 }
650
651 /** A signed 8-bit integer setting type */
652 struct setting_type setting_type_int8 __setting_type = {
653         .name = "int8",
654         .setf = setf_int8,
655         .getf = getf_int,
656 };
657
658 /** A signed 16-bit integer setting type */
659 struct setting_type setting_type_int16 __setting_type = {
660         .name = "int16",
661         .setf = setf_int16,
662         .getf = getf_int,
663 };
664
665 /** A signed 32-bit integer setting type */
666 struct setting_type setting_type_int32 __setting_type = {
667         .name = "int32",
668         .setf = setf_int32,
669         .getf = getf_int,
670 };
671
672 /** An unsigned 8-bit integer setting type */
673 struct setting_type setting_type_uint8 __setting_type = {
674         .name = "uint8",
675         .setf = setf_int8,
676         .getf = getf_uint,
677 };
678
679 /** An unsigned 16-bit integer setting type */
680 struct setting_type setting_type_uint16 __setting_type = {
681         .name = "uint16",
682         .setf = setf_int16,
683         .getf = getf_uint,
684 };
685
686 /** An unsigned 32-bit integer setting type */
687 struct setting_type setting_type_uint32 __setting_type = {
688         .name = "uint32",
689         .setf = setf_int32,
690         .getf = getf_uint,
691 };
692
693 /**
694  * Parse and set value of hex string setting
695  *
696  * @v settings          Settings block
697  * @v tag               Setting tag number
698  * @v value             Formatted setting data
699  * @ret rc              Return status code
700  */
701 static int setf_hex ( struct settings *settings, unsigned int tag,
702                       const char *value ) {
703         char *ptr = ( char * ) value;
704         uint8_t bytes[ strlen ( value ) ]; /* cannot exceed strlen(value) */
705         unsigned int len = 0;
706
707         while ( 1 ) {
708                 bytes[len++] = strtoul ( ptr, &ptr, 16 );
709                 switch ( *ptr ) {
710                 case '\0' :
711                         return set_setting ( settings, tag, bytes, len );
712                 case ':' :
713                         ptr++;
714                         break;
715                 default :
716                         return -EINVAL;
717                 }
718         }
719 }
720
721 /**
722  * Get and format value of hex string setting
723  *
724  * @v settings          Settings block, or NULL to search all blocks
725  * @v tag               Setting tag number
726  * @v buf               Buffer to contain formatted value
727  * @v len               Length of buffer
728  * @ret len             Length of formatted value, or negative error
729  */
730 static int getf_hex ( struct settings *settings, unsigned int tag,
731                       char *buf, size_t len ) {
732         int raw_len;
733         int check_len;
734         int used = 0;
735         int i;
736
737         raw_len = get_setting_len ( settings, tag );
738         if ( raw_len < 0 )
739                 return raw_len;
740
741         {
742                 uint8_t raw[raw_len];
743
744                 check_len = get_setting ( settings, tag, raw, sizeof ( raw ) );
745                 assert ( check_len == raw_len );
746                 
747                 if ( len )
748                         buf[0] = 0; /* Ensure that a terminating NUL exists */
749                 for ( i = 0 ; i < raw_len ; i++ ) {
750                         used += ssnprintf ( ( buf + used ), ( len - used ),
751                                             "%s%02x", ( used ? ":" : "" ),
752                                             raw[i] );
753                 }
754                 return used;
755         }
756 }
757
758 /** A hex-string setting */
759 struct setting_type setting_type_hex __setting_type = {
760         .name = "hex",
761         .setf = setf_hex,
762         .getf = getf_hex,
763 };
764
765 /******************************************************************************
766  *
767  * Named settings
768  *
769  ******************************************************************************
770  */
771
772 /** Some basic setting definitions */
773 struct named_setting basic_named_settings[] __named_setting = {
774         {
775                 .name = "ip",
776                 .description = "IPv4 address of this interface",
777                 .tag = DHCP_EB_YIADDR,
778                 .type = &setting_type_ipv4,
779         },
780         {
781                 .name = "subnet-mask",
782                 .description = "IPv4 subnet mask",
783                 .tag = DHCP_SUBNET_MASK,
784                 .type = &setting_type_ipv4,
785         },
786         {
787                 .name = "routers",
788                 .description = "Default gateway",
789                 .tag = DHCP_ROUTERS,
790                 .type = &setting_type_ipv4,
791         },
792         {
793                 .name = "domain-name-servers",
794                 .description = "DNS server",
795                 .tag = DHCP_DNS_SERVERS,
796                 .type = &setting_type_ipv4,
797         },
798         {
799                 .name = "hostname",
800                 .description = "Host name of this machine",
801                 .tag = DHCP_HOST_NAME,
802                 .type = &setting_type_string,
803         },
804         {
805                 .name = "filename",
806                 .description = "Boot filename",
807                 .tag = DHCP_BOOTFILE_NAME,
808                 .type = &setting_type_string,
809         },
810         {
811                 .name = "root-path",
812                 .description = "NFS/iSCSI root path",
813                 .tag = DHCP_ROOT_PATH,
814                 .type = &setting_type_string,
815         },
816         {
817                 .name = "username",
818                 .description = "User name for authentication",
819                 .tag = DHCP_EB_USERNAME,
820                 .type = &setting_type_string,
821         },
822         {
823                 .name = "password",
824                 .description = "Password for authentication",
825                 .tag = DHCP_EB_PASSWORD,
826                 .type = &setting_type_string,
827         },
828         {
829                 .name = "initiator-iqn",
830                 .description = "iSCSI initiator name",
831                 .tag = DHCP_ISCSI_INITIATOR_IQN,
832                 .type = &setting_type_string,
833         },
834         {
835                 .name = "priority",
836                 .description = "Priority of these options",
837                 .tag = DHCP_EB_PRIORITY,
838                 .type = &setting_type_int8,
839         },
840 };