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