Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

settings.c 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041
  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. #include <stdint.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <strings.h>
  23. #include <byteswap.h>
  24. #include <errno.h>
  25. #include <assert.h>
  26. #include <gpxe/in.h>
  27. #include <gpxe/vsprintf.h>
  28. #include <gpxe/dhcp.h>
  29. #include <gpxe/settings.h>
  30. /** @file
  31. *
  32. * Configuration settings
  33. *
  34. */
  35. /** Registered settings */
  36. static struct setting settings[0]
  37. __table_start ( struct setting, settings );
  38. static struct setting settings_end[0]
  39. __table_end ( struct setting, settings );
  40. /** Registered setting types */
  41. static struct setting_type setting_types[0]
  42. __table_start ( struct setting_type, setting_types );
  43. static struct setting_type setting_types_end[0]
  44. __table_end ( struct setting_type, setting_types );
  45. /** Registered settings applicators */
  46. static struct settings_applicator settings_applicators[0]
  47. __table_start ( struct settings_applicator, settings_applicators );
  48. static struct settings_applicator settings_applicators_end[0]
  49. __table_end ( struct settings_applicator, settings_applicators );
  50. /******************************************************************************
  51. *
  52. * Registered settings blocks
  53. *
  54. ******************************************************************************
  55. */
  56. /**
  57. * Store value of simple setting
  58. *
  59. * @v options DHCP option block
  60. * @v setting Setting to store
  61. * @v data Setting data, or NULL to clear setting
  62. * @v len Length of setting data
  63. * @ret rc Return status code
  64. */
  65. int simple_settings_store ( struct settings *settings, struct setting *setting,
  66. const void *data, size_t len ) {
  67. struct simple_settings *simple =
  68. container_of ( settings, struct simple_settings, settings );
  69. return dhcpopt_extensible_store ( &simple->dhcpopts, setting->tag,
  70. data, len );
  71. }
  72. /**
  73. * Fetch value of simple setting
  74. *
  75. * @v options DHCP option block
  76. * @v setting Setting to fetch
  77. * @v data Buffer to fill with setting data
  78. * @v len Length of buffer
  79. * @ret len Length of setting data, or negative error
  80. */
  81. int simple_settings_fetch ( struct settings *settings, struct setting *setting,
  82. void *data, size_t len ) {
  83. struct simple_settings *simple =
  84. container_of ( settings, struct simple_settings, settings );
  85. return dhcpopt_fetch ( &simple->dhcpopts, setting->tag, data, len );
  86. }
  87. /** Simple settings operations */
  88. struct settings_operations simple_settings_operations = {
  89. .store = simple_settings_store,
  90. .fetch = simple_settings_fetch,
  91. };
  92. /** Root simple settings block */
  93. struct simple_settings simple_settings_root = {
  94. .settings = {
  95. .refcnt = NULL,
  96. .name = "",
  97. .siblings =
  98. LIST_HEAD_INIT ( simple_settings_root.settings.siblings ),
  99. .children =
  100. LIST_HEAD_INIT ( simple_settings_root.settings.children ),
  101. .op = &simple_settings_operations,
  102. },
  103. };
  104. /** Root settings block */
  105. #define settings_root simple_settings_root.settings
  106. /**
  107. * Apply all settings
  108. *
  109. * @ret rc Return status code
  110. */
  111. static int apply_settings ( void ) {
  112. struct settings_applicator *applicator;
  113. int rc;
  114. /* Call all settings applicators */
  115. for ( applicator = settings_applicators ;
  116. applicator < settings_applicators_end ; applicator++ ) {
  117. if ( ( rc = applicator->apply() ) != 0 ) {
  118. DBG ( "Could not apply settings using applicator "
  119. "%p: %s\n", applicator, strerror ( rc ) );
  120. return rc;
  121. }
  122. }
  123. return 0;
  124. }
  125. /**
  126. * Reprioritise settings
  127. *
  128. * @v settings Settings block
  129. *
  130. * Reorders the settings block amongst its siblings according to its
  131. * priority.
  132. */
  133. static void reprioritise_settings ( struct settings *settings ) {
  134. struct settings *parent = settings->parent;
  135. long priority;
  136. struct settings *tmp;
  137. long tmp_priority;
  138. /* Stop when we reach the top of the tree */
  139. if ( ! parent )
  140. return;
  141. /* Read priority, if present */
  142. priority = fetch_intz_setting ( settings, &priority_setting );
  143. /* Remove from siblings list */
  144. list_del ( &settings->siblings );
  145. /* Reinsert after any existing blocks which have a higher priority */
  146. list_for_each_entry ( tmp, &parent->children, siblings ) {
  147. tmp_priority = fetch_intz_setting ( tmp, &priority_setting );
  148. if ( priority > tmp_priority )
  149. break;
  150. }
  151. list_add_tail ( &settings->siblings, &tmp->siblings );
  152. /* Recurse up the tree */
  153. reprioritise_settings ( parent );
  154. }
  155. /**
  156. * Register settings block
  157. *
  158. * @v settings Settings block
  159. * @v parent Parent settings block, or NULL
  160. * @ret rc Return status code
  161. */
  162. int register_settings ( struct settings *settings, struct settings *parent ) {
  163. /* NULL parent => add to settings root */
  164. assert ( settings != NULL );
  165. if ( parent == NULL )
  166. parent = &settings_root;
  167. /* Add to list of settings */
  168. ref_get ( settings->refcnt );
  169. ref_get ( parent->refcnt );
  170. settings->parent = parent;
  171. list_add_tail ( &settings->siblings, &parent->children );
  172. DBGC ( settings, "Settings %p registered\n", settings );
  173. /* Fix up settings priority */
  174. reprioritise_settings ( settings );
  175. /* Apply potentially-updated settings */
  176. apply_settings();
  177. return 0;
  178. }
  179. /**
  180. * Unregister settings block
  181. *
  182. * @v settings Settings block
  183. */
  184. void unregister_settings ( struct settings *settings ) {
  185. /* Remove from list of settings */
  186. ref_put ( settings->refcnt );
  187. ref_put ( settings->parent->refcnt );
  188. settings->parent = NULL;
  189. list_del ( &settings->siblings );
  190. DBGC ( settings, "Settings %p unregistered\n", settings );
  191. /* Apply potentially-updated settings */
  192. apply_settings();
  193. }
  194. /**
  195. * Find child named settings block
  196. *
  197. * @v parent Parent settings block
  198. * @v name Name within this parent
  199. * @ret settings Settings block, or NULL
  200. */
  201. struct settings * find_child_settings ( struct settings *parent,
  202. const char *name ) {
  203. struct settings *settings;
  204. size_t len;
  205. /* NULL parent => add to settings root */
  206. if ( parent == NULL )
  207. parent = &settings_root;
  208. /* Look for a child whose name matches the initial component */
  209. list_for_each_entry ( settings, &parent->children, siblings ) {
  210. len = strlen ( settings->name );
  211. if ( strncmp ( name, settings->name, len ) != 0 )
  212. continue;
  213. if ( name[len] == 0 )
  214. return settings;
  215. if ( name[len] == '.' )
  216. return find_child_settings ( settings,
  217. ( name + len + 1 ) );
  218. }
  219. return NULL;
  220. }
  221. /**
  222. * Find named settings block
  223. *
  224. * @v name Name
  225. * @ret settings Settings block, or NULL
  226. */
  227. struct settings * find_settings ( const char *name ) {
  228. /* If name is empty, use the root */
  229. if ( ! *name )
  230. return &settings_root;
  231. return find_child_settings ( &settings_root, name );
  232. }
  233. /******************************************************************************
  234. *
  235. * Core settings routines
  236. *
  237. ******************************************************************************
  238. */
  239. /**
  240. * Store value of setting
  241. *
  242. * @v settings Settings block
  243. * @v setting Setting to store
  244. * @v data Setting data, or NULL to clear setting
  245. * @v len Length of setting data
  246. * @ret rc Return status code
  247. */
  248. int store_setting ( struct settings *settings, struct setting *setting,
  249. const void *data, size_t len ) {
  250. int rc;
  251. /* Sanity check */
  252. if ( ! settings )
  253. return -ENODEV;
  254. /* Store setting */
  255. if ( ( rc = settings->op->store ( settings, setting,
  256. data, len ) ) != 0 )
  257. return rc;
  258. /* Reprioritise settings if necessary */
  259. if ( setting_cmp ( setting, &priority_setting ) == 0 )
  260. reprioritise_settings ( settings );
  261. /* If these settings are registered, apply potentially-updated
  262. * settings
  263. */
  264. for ( ; settings ; settings = settings->parent ) {
  265. if ( settings == &settings_root ) {
  266. if ( ( rc = apply_settings() ) != 0 )
  267. return rc;
  268. break;
  269. }
  270. }
  271. return 0;
  272. }
  273. /**
  274. * Fetch value of setting
  275. *
  276. * @v settings Settings block, or NULL to search all blocks
  277. * @v setting Setting to fetch
  278. * @v data Buffer to fill with setting data
  279. * @v len Length of buffer
  280. * @ret len Length of setting data, or negative error
  281. *
  282. * The actual length of the setting will be returned even if
  283. * the buffer was too small.
  284. */
  285. int fetch_setting ( struct settings *settings, struct setting *setting,
  286. void *data, size_t len ) {
  287. struct settings *child;
  288. int ret;
  289. /* NULL settings implies starting at the global settings root */
  290. if ( ! settings )
  291. settings = &settings_root;
  292. /* Try this block first */
  293. if ( ( ret = settings->op->fetch ( settings, setting,
  294. data, len ) ) >= 0 )
  295. return ret;
  296. /* Recurse into each child block in turn */
  297. list_for_each_entry ( child, &settings->children, siblings ) {
  298. if ( ( ret = fetch_setting ( child, setting,
  299. data, len ) ) >= 0 )
  300. return ret;
  301. }
  302. return -ENOENT;
  303. }
  304. /**
  305. * Fetch length of setting
  306. *
  307. * @v settings Settings block, or NULL to search all blocks
  308. * @v setting Setting to fetch
  309. * @ret len Length of setting data, or negative error
  310. *
  311. * This function can also be used as an existence check for the
  312. * setting.
  313. */
  314. int fetch_setting_len ( struct settings *settings, struct setting *setting ) {
  315. return fetch_setting ( settings, setting, NULL, 0 );
  316. }
  317. /**
  318. * Fetch value of string setting
  319. *
  320. * @v settings Settings block, or NULL to search all blocks
  321. * @v setting Setting to fetch
  322. * @v data Buffer to fill with setting string data
  323. * @v len Length of buffer
  324. * @ret len Length of string setting, or negative error
  325. *
  326. * The resulting string is guaranteed to be correctly NUL-terminated.
  327. * The returned length will be the length of the underlying setting
  328. * data.
  329. */
  330. int fetch_string_setting ( struct settings *settings, struct setting *setting,
  331. char *data, size_t len ) {
  332. memset ( data, 0, len );
  333. return fetch_setting ( settings, setting, data, ( len - 1 ) );
  334. }
  335. /**
  336. * Fetch value of IPv4 address setting
  337. *
  338. * @v settings Settings block, or NULL to search all blocks
  339. * @v setting Setting to fetch
  340. * @v inp IPv4 address to fill in
  341. * @ret len Length of setting, or negative error
  342. */
  343. int fetch_ipv4_setting ( struct settings *settings, struct setting *setting,
  344. struct in_addr *inp ) {
  345. int len;
  346. len = fetch_setting ( settings, setting, inp, sizeof ( *inp ) );
  347. if ( len < 0 )
  348. return len;
  349. if ( len < ( int ) sizeof ( *inp ) )
  350. return -ERANGE;
  351. return len;
  352. }
  353. /**
  354. * Fetch value of signed integer setting
  355. *
  356. * @v settings Settings block, or NULL to search all blocks
  357. * @v setting Setting to fetch
  358. * @v value Integer value to fill in
  359. * @ret len Length of setting, or negative error
  360. */
  361. int fetch_int_setting ( struct settings *settings, struct setting *setting,
  362. long *value ) {
  363. union {
  364. long value;
  365. uint8_t u8[ sizeof ( long ) ];
  366. int8_t s8[ sizeof ( long ) ];
  367. } buf;
  368. int len;
  369. int i;
  370. buf.value = 0;
  371. len = fetch_setting ( settings, setting, &buf, sizeof ( buf ) );
  372. if ( len < 0 )
  373. return len;
  374. if ( len > ( int ) sizeof ( buf ) )
  375. return -ERANGE;
  376. *value = ( ( buf.s8[0] >= 0 ) ? 0 : -1L );
  377. for ( i = 0 ; i < len ; i++ ) {
  378. *value = ( ( *value << 8 ) | buf.u8[i] );
  379. }
  380. return len;
  381. }
  382. /**
  383. * Fetch value of unsigned integer setting
  384. *
  385. * @v settings Settings block, or NULL to search all blocks
  386. * @v setting Setting to fetch
  387. * @v value Integer value to fill in
  388. * @ret len Length of setting, or negative error
  389. */
  390. int fetch_uint_setting ( struct settings *settings, struct setting *setting,
  391. unsigned long *value ) {
  392. long svalue;
  393. int len;
  394. len = fetch_int_setting ( settings, setting, &svalue );
  395. if ( len < 0 )
  396. return len;
  397. *value = ( svalue & ( -1UL >> ( sizeof ( long ) - len ) ) );
  398. return len;
  399. }
  400. /**
  401. * Fetch value of signed integer setting, or zero
  402. *
  403. * @v settings Settings block, or NULL to search all blocks
  404. * @v setting Setting to fetch
  405. * @ret value Setting value, or zero
  406. */
  407. long fetch_intz_setting ( struct settings *settings, struct setting *setting ){
  408. long value = 0;
  409. fetch_int_setting ( settings, setting, &value );
  410. return value;
  411. }
  412. /**
  413. * Fetch value of unsigned integer setting, or zero
  414. *
  415. * @v settings Settings block, or NULL to search all blocks
  416. * @v setting Setting to fetch
  417. * @ret value Setting value, or zero
  418. */
  419. unsigned long fetch_uintz_setting ( struct settings *settings,
  420. struct setting *setting ) {
  421. unsigned long value = 0;
  422. fetch_uint_setting ( settings, setting, &value );
  423. return value;
  424. }
  425. /**
  426. * Compare two settings
  427. *
  428. * @v a Setting to compare
  429. * @v b Setting to compare
  430. * @ret 0 Settings are the same
  431. * @ret non-zero Settings are not the same
  432. */
  433. int setting_cmp ( struct setting *a, struct setting *b ) {
  434. /* If the settings have tags, compare them */
  435. if ( a->tag && ( a->tag == b->tag ) )
  436. return 0;
  437. /* Otherwise, compare the names */
  438. return strcmp ( a->name, b->name );
  439. }
  440. /******************************************************************************
  441. *
  442. * Formatted setting routines
  443. *
  444. ******************************************************************************
  445. */
  446. /**
  447. * Store value of typed setting
  448. *
  449. * @v settings Settings block
  450. * @v setting Setting to store
  451. * @v type Settings type
  452. * @v value Formatted setting data, or NULL
  453. * @ret rc Return status code
  454. */
  455. int storef_setting ( struct settings *settings, struct setting *setting,
  456. const char *value ) {
  457. /* NULL value implies deletion. Avoid imposing the burden of
  458. * checking for NULL values on each typed setting's storef()
  459. * method.
  460. */
  461. if ( ! value )
  462. return delete_setting ( settings, setting );
  463. return setting->type->storef ( settings, setting, value );
  464. }
  465. /**
  466. * Find named setting
  467. *
  468. * @v name Name
  469. * @ret setting Named setting, or NULL
  470. */
  471. static struct setting * find_setting ( const char *name ) {
  472. struct setting *setting;
  473. for ( setting = settings ; setting < settings_end ; setting++ ) {
  474. if ( strcmp ( name, setting->name ) == 0 )
  475. return setting;
  476. }
  477. return NULL;
  478. }
  479. /**
  480. * Find setting type
  481. *
  482. * @v name Name
  483. * @ret type Setting type, or NULL
  484. */
  485. static struct setting_type * find_setting_type ( const char *name ) {
  486. struct setting_type *type;
  487. for ( type = setting_types ; type < setting_types_end ; type++ ) {
  488. if ( strcmp ( name, type->name ) == 0 )
  489. return type;
  490. }
  491. return NULL;
  492. }
  493. /**
  494. * Parse setting name
  495. *
  496. * @v name Name of setting
  497. * @v settings Settings block to fill in
  498. * @v setting Setting to fill in
  499. * @ret rc Return status code
  500. *
  501. * Interprets a name of the form
  502. * "[settings_name/]tag_name[:type_name]" and fills in the appropriate
  503. * fields.
  504. */
  505. static int parse_setting_name ( const char *name, struct settings **settings,
  506. struct setting *setting ) {
  507. char tmp_name[ strlen ( name ) + 1 ];
  508. char *settings_name;
  509. char *setting_name;
  510. char *type_name;
  511. struct setting *named_setting;
  512. char *tmp;
  513. /* Set defaults */
  514. *settings = &settings_root;
  515. memset ( setting, 0, sizeof ( *setting ) );
  516. setting->type = &setting_type_hex;
  517. /* Split name into "[settings_name/]setting_name[:type_name]" */
  518. memcpy ( tmp_name, name, sizeof ( tmp_name ) );
  519. if ( ( setting_name = strchr ( tmp_name, '/' ) ) != NULL ) {
  520. *(setting_name++) = 0;
  521. settings_name = tmp_name;
  522. } else {
  523. setting_name = tmp_name;
  524. settings_name = NULL;
  525. }
  526. if ( ( type_name = strchr ( setting_name, ':' ) ) != NULL )
  527. *(type_name++) = 0;
  528. /* Identify settings block, if specified */
  529. if ( settings_name ) {
  530. *settings = find_settings ( settings_name );
  531. if ( *settings == NULL ) {
  532. DBG ( "Unrecognised settings block \"%s\" in \"%s\"\n",
  533. settings_name, name );
  534. return -ENODEV;
  535. }
  536. }
  537. /* Identify tag number */
  538. if ( ( named_setting = find_setting ( setting_name ) ) != NULL ) {
  539. memcpy ( setting, named_setting, sizeof ( *setting ) );
  540. } else {
  541. /* Unrecognised name: try to interpret as a tag number */
  542. tmp = setting_name;
  543. while ( 1 ) {
  544. setting->tag = ( ( setting->tag << 8 ) |
  545. strtoul ( tmp, &tmp, 0 ) );
  546. if ( *tmp == 0 )
  547. break;
  548. if ( *tmp != '.' ) {
  549. DBG ( "Invalid setting \"%s\" in \"%s\"\n",
  550. setting_name, name );
  551. return -ENOENT;
  552. }
  553. tmp++;
  554. }
  555. }
  556. /* Identify setting type, if specified */
  557. if ( type_name ) {
  558. setting->type = find_setting_type ( type_name );
  559. if ( setting->type == NULL ) {
  560. DBG ( "Invalid setting type \"%s\" in \"%s\"\n",
  561. type_name, name );
  562. return -ENOTSUP;
  563. }
  564. }
  565. return 0;
  566. }
  567. /**
  568. * Parse and store value of named setting
  569. *
  570. * @v name Name of setting
  571. * @v value Formatted setting data, or NULL
  572. * @ret rc Return status code
  573. */
  574. int storef_named_setting ( const char *name, const char *value ) {
  575. struct settings *settings;
  576. struct setting setting;
  577. int rc;
  578. if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
  579. return rc;
  580. return storef_setting ( settings, &setting, value );
  581. }
  582. /**
  583. * Fetch and format value of named setting
  584. *
  585. * @v name Name of setting
  586. * @v buf Buffer to contain formatted value
  587. * @v len Length of buffer
  588. * @ret len Length of formatted value, or negative error
  589. */
  590. int fetchf_named_setting ( const char *name, char *buf, size_t len ) {
  591. struct settings *settings;
  592. struct setting setting;
  593. int rc;
  594. if ( ( rc = parse_setting_name ( name, &settings, &setting ) ) != 0 )
  595. return rc;
  596. return fetchf_setting ( settings, &setting, buf, len );
  597. }
  598. /******************************************************************************
  599. *
  600. * Setting types
  601. *
  602. ******************************************************************************
  603. */
  604. /**
  605. * Parse and store value of string setting
  606. *
  607. * @v settings Settings block
  608. * @v setting Setting to store
  609. * @v value Formatted setting data
  610. * @ret rc Return status code
  611. */
  612. static int storef_string ( struct settings *settings, struct setting *setting,
  613. const char *value ) {
  614. return store_setting ( settings, setting, value, strlen ( value ) );
  615. }
  616. /**
  617. * Fetch and format value of string setting
  618. *
  619. * @v settings Settings block, or NULL to search all blocks
  620. * @v setting Setting to fetch
  621. * @v buf Buffer to contain formatted value
  622. * @v len Length of buffer
  623. * @ret len Length of formatted value, or negative error
  624. */
  625. static int fetchf_string ( struct settings *settings, struct setting *setting,
  626. char *buf, size_t len ) {
  627. return fetch_string_setting ( settings, setting, buf, len );
  628. }
  629. /** A string setting type */
  630. struct setting_type setting_type_string __setting_type = {
  631. .name = "string",
  632. .storef = storef_string,
  633. .fetchf = fetchf_string,
  634. };
  635. /**
  636. * Parse and store value of IPv4 address setting
  637. *
  638. * @v settings Settings block
  639. * @v setting Setting to store
  640. * @v value Formatted setting data
  641. * @ret rc Return status code
  642. */
  643. static int storef_ipv4 ( struct settings *settings, struct setting *setting,
  644. const char *value ) {
  645. struct in_addr ipv4;
  646. if ( inet_aton ( value, &ipv4 ) == 0 )
  647. return -EINVAL;
  648. return store_setting ( settings, setting, &ipv4, sizeof ( ipv4 ) );
  649. }
  650. /**
  651. * Fetch and format value of IPv4 address setting
  652. *
  653. * @v settings Settings block, or NULL to search all blocks
  654. * @v setting Setting to fetch
  655. * @v buf Buffer to contain formatted value
  656. * @v len Length of buffer
  657. * @ret len Length of formatted value, or negative error
  658. */
  659. static int fetchf_ipv4 ( struct settings *settings, struct setting *setting,
  660. char *buf, size_t len ) {
  661. struct in_addr ipv4;
  662. int rc;
  663. if ( ( rc = fetch_ipv4_setting ( settings, setting, &ipv4 ) ) < 0 )
  664. return rc;
  665. return snprintf ( buf, len, inet_ntoa ( ipv4 ) );
  666. }
  667. /** An IPv4 address setting type */
  668. struct setting_type setting_type_ipv4 __setting_type = {
  669. .name = "ipv4",
  670. .storef = storef_ipv4,
  671. .fetchf = fetchf_ipv4,
  672. };
  673. /**
  674. * Parse and store value of integer setting
  675. *
  676. * @v settings Settings block
  677. * @v setting Setting to store
  678. * @v value Formatted setting data
  679. * @v size Integer size, in bytes
  680. * @ret rc Return status code
  681. */
  682. static int storef_int ( struct settings *settings, struct setting *setting,
  683. const char *value, unsigned int size ) {
  684. union {
  685. uint32_t num;
  686. uint8_t bytes[4];
  687. } u;
  688. char *endp;
  689. u.num = htonl ( strtoul ( value, &endp, 0 ) );
  690. if ( *endp )
  691. return -EINVAL;
  692. return store_setting ( settings, setting,
  693. &u.bytes[ sizeof ( u ) - size ], size );
  694. }
  695. /**
  696. * Parse and store value of 8-bit integer setting
  697. *
  698. * @v settings Settings block
  699. * @v setting Setting to store
  700. * @v value Formatted setting data
  701. * @v size Integer size, in bytes
  702. * @ret rc Return status code
  703. */
  704. static int storef_int8 ( struct settings *settings, struct setting *setting,
  705. const char *value ) {
  706. return storef_int ( settings, setting, value, 1 );
  707. }
  708. /**
  709. * Parse and store value of 16-bit integer setting
  710. *
  711. * @v settings Settings block
  712. * @v setting Setting to store
  713. * @v value Formatted setting data
  714. * @v size Integer size, in bytes
  715. * @ret rc Return status code
  716. */
  717. static int storef_int16 ( struct settings *settings, struct setting *setting,
  718. const char *value ) {
  719. return storef_int ( settings, setting, value, 2 );
  720. }
  721. /**
  722. * Parse and store value of 32-bit integer setting
  723. *
  724. * @v settings Settings block
  725. * @v setting Setting to store
  726. * @v value Formatted setting data
  727. * @v size Integer size, in bytes
  728. * @ret rc Return status code
  729. */
  730. static int storef_int32 ( struct settings *settings, struct setting *setting,
  731. const char *value ) {
  732. return storef_int ( settings, setting, value, 4 );
  733. }
  734. /**
  735. * Fetch and format value of signed integer setting
  736. *
  737. * @v settings Settings block, or NULL to search all blocks
  738. * @v setting Setting to fetch
  739. * @v buf Buffer to contain formatted value
  740. * @v len Length of buffer
  741. * @ret len Length of formatted value, or negative error
  742. */
  743. static int fetchf_int ( struct settings *settings, struct setting *setting,
  744. char *buf, size_t len ) {
  745. long value;
  746. int rc;
  747. if ( ( rc = fetch_int_setting ( settings, setting, &value ) ) < 0 )
  748. return rc;
  749. return snprintf ( buf, len, "%ld", value );
  750. }
  751. /**
  752. * Fetch and format value of unsigned integer setting
  753. *
  754. * @v settings Settings block, or NULL to search all blocks
  755. * @v setting Setting to fetch
  756. * @v buf Buffer to contain formatted value
  757. * @v len Length of buffer
  758. * @ret len Length of formatted value, or negative error
  759. */
  760. static int fetchf_uint ( struct settings *settings, struct setting *setting,
  761. char *buf, size_t len ) {
  762. unsigned long value;
  763. int rc;
  764. if ( ( rc = fetch_uint_setting ( settings, setting, &value ) ) < 0 )
  765. return rc;
  766. return snprintf ( buf, len, "%#lx", value );
  767. }
  768. /** A signed 8-bit integer setting type */
  769. struct setting_type setting_type_int8 __setting_type = {
  770. .name = "int8",
  771. .storef = storef_int8,
  772. .fetchf = fetchf_int,
  773. };
  774. /** A signed 16-bit integer setting type */
  775. struct setting_type setting_type_int16 __setting_type = {
  776. .name = "int16",
  777. .storef = storef_int16,
  778. .fetchf = fetchf_int,
  779. };
  780. /** A signed 32-bit integer setting type */
  781. struct setting_type setting_type_int32 __setting_type = {
  782. .name = "int32",
  783. .storef = storef_int32,
  784. .fetchf = fetchf_int,
  785. };
  786. /** An unsigned 8-bit integer setting type */
  787. struct setting_type setting_type_uint8 __setting_type = {
  788. .name = "uint8",
  789. .storef = storef_int8,
  790. .fetchf = fetchf_uint,
  791. };
  792. /** An unsigned 16-bit integer setting type */
  793. struct setting_type setting_type_uint16 __setting_type = {
  794. .name = "uint16",
  795. .storef = storef_int16,
  796. .fetchf = fetchf_uint,
  797. };
  798. /** An unsigned 32-bit integer setting type */
  799. struct setting_type setting_type_uint32 __setting_type = {
  800. .name = "uint32",
  801. .storef = storef_int32,
  802. .fetchf = fetchf_uint,
  803. };
  804. /**
  805. * Parse and store value of hex string setting
  806. *
  807. * @v settings Settings block
  808. * @v setting Setting to store
  809. * @v value Formatted setting data
  810. * @ret rc Return status code
  811. */
  812. static int storef_hex ( struct settings *settings, struct setting *setting,
  813. const char *value ) {
  814. char *ptr = ( char * ) value;
  815. uint8_t bytes[ strlen ( value ) ]; /* cannot exceed strlen(value) */
  816. unsigned int len = 0;
  817. while ( 1 ) {
  818. bytes[len++] = strtoul ( ptr, &ptr, 16 );
  819. switch ( *ptr ) {
  820. case '\0' :
  821. return store_setting ( settings, setting, bytes, len );
  822. case ':' :
  823. ptr++;
  824. break;
  825. default :
  826. return -EINVAL;
  827. }
  828. }
  829. }
  830. /**
  831. * Fetch and format value of hex string setting
  832. *
  833. * @v settings Settings block, or NULL to search all blocks
  834. * @v setting Setting to fetch
  835. * @v buf Buffer to contain formatted value
  836. * @v len Length of buffer
  837. * @ret len Length of formatted value, or negative error
  838. */
  839. static int fetchf_hex ( struct settings *settings, struct setting *setting,
  840. char *buf, size_t len ) {
  841. int raw_len;
  842. int check_len;
  843. int used = 0;
  844. int i;
  845. raw_len = fetch_setting_len ( settings, setting );
  846. if ( raw_len < 0 )
  847. return raw_len;
  848. {
  849. uint8_t raw[raw_len];
  850. check_len = fetch_setting ( settings, setting, raw,
  851. sizeof ( raw ) );
  852. assert ( check_len == raw_len );
  853. if ( len )
  854. buf[0] = 0; /* Ensure that a terminating NUL exists */
  855. for ( i = 0 ; i < raw_len ; i++ ) {
  856. used += ssnprintf ( ( buf + used ), ( len - used ),
  857. "%s%02x", ( used ? ":" : "" ),
  858. raw[i] );
  859. }
  860. return used;
  861. }
  862. }
  863. /** A hex-string setting */
  864. struct setting_type setting_type_hex __setting_type = {
  865. .name = "hex",
  866. .storef = storef_hex,
  867. .fetchf = fetchf_hex,
  868. };
  869. /******************************************************************************
  870. *
  871. * Settings
  872. *
  873. ******************************************************************************
  874. */
  875. /** Hostname setting */
  876. struct setting hostname_setting __setting = {
  877. .name = "hostname",
  878. .description = "Host name",
  879. .tag = DHCP_HOST_NAME,
  880. .type = &setting_type_string,
  881. };
  882. /** Filename setting */
  883. struct setting filename_setting __setting = {
  884. .name = "filename",
  885. .description = "Boot filename",
  886. .tag = DHCP_BOOTFILE_NAME,
  887. .type = &setting_type_string,
  888. };
  889. /** Root path setting */
  890. struct setting root_path_setting __setting = {
  891. .name = "root-path",
  892. .description = "NFS/iSCSI root path",
  893. .tag = DHCP_ROOT_PATH,
  894. .type = &setting_type_string,
  895. };
  896. /** Username setting */
  897. struct setting username_setting __setting = {
  898. .name = "username",
  899. .description = "User name",
  900. .tag = DHCP_EB_USERNAME,
  901. .type = &setting_type_string,
  902. };
  903. /** Password setting */
  904. struct setting password_setting __setting = {
  905. .name = "password",
  906. .description = "Password",
  907. .tag = DHCP_EB_PASSWORD,
  908. .type = &setting_type_string,
  909. };
  910. /** Priority setting */
  911. struct setting priority_setting __setting = {
  912. .name = "priority",
  913. .description = "Priority of these settings",
  914. .tag = DHCP_EB_PRIORITY,
  915. .type = &setting_type_int8,
  916. };