type_defs.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. /* Copyright (c) 2001 Matej Pfajfar.
  2. * Copyright (c) 2001-2004, Roger Dingledine.
  3. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  4. * Copyright (c) 2007-2019, The Tor Project, Inc. */
  5. /* See LICENSE for licensing information */
  6. /**
  7. * @file type_defs.c
  8. * @brief Definitions for various low-level configuration types.
  9. *
  10. * This module creates a number of var_type_def_t objects, to be used by
  11. * typedvar.c in manipulating variables.
  12. *
  13. * The types here are common types that can be implemented with Tor's
  14. * low-level functionality. To define new types, see var_type_def_st.h.
  15. **/
  16. #include "orconfig.h"
  17. #include "lib/conf/conftypes.h"
  18. #include "lib/confmgt/typedvar.h"
  19. #include "lib/confmgt/type_defs.h"
  20. #include "lib/confmgt/unitparse.h"
  21. #include "lib/cc/compat_compiler.h"
  22. #include "lib/conf/conftypes.h"
  23. #include "lib/container/smartlist.h"
  24. #include "lib/encoding/confline.h"
  25. #include "lib/encoding/time_fmt.h"
  26. #include "lib/log/escape.h"
  27. #include "lib/log/log.h"
  28. #include "lib/log/util_bug.h"
  29. #include "lib/malloc/malloc.h"
  30. #include "lib/string/parse_int.h"
  31. #include "lib/string/printf.h"
  32. #include "lib/confmgt/var_type_def_st.h"
  33. #include <stddef.h>
  34. #include <string.h>
  35. #include <errno.h>
  36. //////
  37. // CONFIG_TYPE_STRING
  38. // CONFIG_TYPE_FILENAME
  39. //
  40. // These two types are the same for now, but they have different names.
  41. //
  42. // Warning: For this type, the default value (NULL) and "" are considered
  43. // different values. That is generally risky, and best avoided for other
  44. // types in the future.
  45. //////
  46. static int
  47. string_parse(void *target, const char *value, char **errmsg,
  48. const void *params, const char *key)
  49. {
  50. (void)params;
  51. (void)errmsg;
  52. (void)key;
  53. char **p = (char**)target;
  54. *p = tor_strdup(value);
  55. return 0;
  56. }
  57. static char *
  58. string_encode(const void *value, const void *params)
  59. {
  60. (void)params;
  61. const char **p = (const char**)value;
  62. return *p ? tor_strdup(*p) : NULL;
  63. }
  64. static void
  65. string_clear(void *value, const void *params)
  66. {
  67. (void)params;
  68. char **p = (char**)value;
  69. tor_free(*p); // sets *p to NULL.
  70. }
  71. static const var_type_fns_t string_fns = {
  72. .parse = string_parse,
  73. .encode = string_encode,
  74. .clear = string_clear,
  75. };
  76. /////
  77. // CONFIG_TYPE_INT
  78. // CONFIG_TYPE_POSINT
  79. //
  80. // These types are implemented as int, possibly with a restricted range.
  81. /////
  82. typedef struct int_type_params_t {
  83. int minval;
  84. int maxval;
  85. } int_parse_params_t;
  86. static const int_parse_params_t INT_PARSE_UNRESTRICTED = {
  87. .minval = INT_MIN,
  88. .maxval = INT_MAX,
  89. };
  90. static const int_parse_params_t INT_PARSE_POSINT = {
  91. .minval = 0,
  92. .maxval = INT_MAX,
  93. };
  94. static int
  95. int_parse(void *target, const char *value, char **errmsg, const void *params,
  96. const char *key)
  97. {
  98. (void)key;
  99. const int_parse_params_t *pp;
  100. if (params) {
  101. pp = params;
  102. } else {
  103. pp = &INT_PARSE_UNRESTRICTED;
  104. }
  105. int *p = target;
  106. int ok=0;
  107. *p = (int)tor_parse_long(value, 10, pp->minval, pp->maxval, &ok, NULL);
  108. if (!ok) {
  109. tor_asprintf(errmsg, "Integer %s is malformed or out of bounds.",
  110. value);
  111. return -1;
  112. }
  113. return 0;
  114. }
  115. static char *
  116. int_encode(const void *value, const void *params)
  117. {
  118. (void)params;
  119. int v = *(int*)value;
  120. char *result;
  121. tor_asprintf(&result, "%d", v);
  122. return result;
  123. }
  124. static void
  125. int_clear(void *value, const void *params)
  126. {
  127. (void)params;
  128. *(int*)value = 0;
  129. }
  130. static bool
  131. int_ok(const void *value, const void *params)
  132. {
  133. const int_parse_params_t *pp = params;
  134. if (pp) {
  135. int v = *(int*)value;
  136. return pp->minval <= v && v <= pp->maxval;
  137. } else {
  138. return true;
  139. }
  140. }
  141. static const var_type_fns_t int_fns = {
  142. .parse = int_parse,
  143. .encode = int_encode,
  144. .clear = int_clear,
  145. .ok = int_ok,
  146. };
  147. /////
  148. // CONFIG_TYPE_UINT64
  149. //
  150. // This type is an unrestricted u64.
  151. /////
  152. static int
  153. uint64_parse(void *target, const char *value, char **errmsg,
  154. const void *params, const char *key)
  155. {
  156. (void)params;
  157. (void)errmsg;
  158. (void)key;
  159. uint64_t *p = target;
  160. int ok=0;
  161. *p = tor_parse_uint64(value, 10, 0, UINT64_MAX, &ok, NULL);
  162. if (!ok) {
  163. tor_asprintf(errmsg, "Integer %s is malformed or out of bounds.",
  164. value);
  165. return -1;
  166. }
  167. return 0;
  168. }
  169. static char *
  170. uint64_encode(const void *value, const void *params)
  171. {
  172. (void)params;
  173. uint64_t v = *(uint64_t*)value;
  174. char *result;
  175. tor_asprintf(&result, "%"PRIu64, v);
  176. return result;
  177. }
  178. static void
  179. uint64_clear(void *value, const void *params)
  180. {
  181. (void)params;
  182. *(uint64_t*)value = 0;
  183. }
  184. static const var_type_fns_t uint64_fns = {
  185. .parse = uint64_parse,
  186. .encode = uint64_encode,
  187. .clear = uint64_clear,
  188. };
  189. /////
  190. // CONFIG_TYPE_INTERVAL
  191. // CONFIG_TYPE_MSEC_INTERVAL
  192. // CONFIG_TYPE_MEMUNIT
  193. //
  194. // These types are implemented using the config_parse_units() function.
  195. // The intervals are stored as ints, whereas memory units are stored as
  196. // uint64_ts.
  197. /////
  198. static int
  199. units_parse_u64(void *target, const char *value, char **errmsg,
  200. const void *params, const char *key)
  201. {
  202. (void)key;
  203. const unit_table_t *table = params;
  204. tor_assert(table);
  205. uint64_t *v = (uint64_t*)target;
  206. int ok=1;
  207. *v = config_parse_units(value, table, &ok);
  208. if (!ok) {
  209. *errmsg = tor_strdup("Provided value is malformed or out of bounds.");
  210. return -1;
  211. }
  212. return 0;
  213. }
  214. static int
  215. units_parse_int(void *target, const char *value, char **errmsg,
  216. const void *params, const char *key)
  217. {
  218. (void)key;
  219. const unit_table_t *table = params;
  220. tor_assert(table);
  221. int *v = (int*)target;
  222. int ok=1;
  223. uint64_t u64 = config_parse_units(value, table, &ok);
  224. if (!ok) {
  225. *errmsg = tor_strdup("Provided value is malformed or out of bounds.");
  226. return -1;
  227. }
  228. if (u64 > INT_MAX) {
  229. tor_asprintf(errmsg, "Provided value %s is too large", value);
  230. return -1;
  231. }
  232. *v = (int) u64;
  233. return 0;
  234. }
  235. static bool
  236. units_ok_int(const void *value, const void *params)
  237. {
  238. (void)params;
  239. int v = *(int*)value;
  240. return v >= 0;
  241. }
  242. static const var_type_fns_t memunit_fns = {
  243. .parse = units_parse_u64,
  244. .encode = uint64_encode, // doesn't use params
  245. .clear = uint64_clear, // doesn't use params
  246. };
  247. static const var_type_fns_t interval_fns = {
  248. .parse = units_parse_int,
  249. .encode = int_encode, // doesn't use params
  250. .clear = int_clear, // doesn't use params,
  251. .ok = units_ok_int // can't use int_ok, since that expects int params.
  252. };
  253. /////
  254. // CONFIG_TYPE_DOUBLE
  255. //
  256. // This is a nice simple double.
  257. /////
  258. static int
  259. double_parse(void *target, const char *value, char **errmsg,
  260. const void *params, const char *key)
  261. {
  262. (void)params;
  263. (void)errmsg;
  264. (void)key;
  265. double *v = (double*)target;
  266. char *endptr=NULL;
  267. errno = 0;
  268. *v = strtod(value, &endptr);
  269. if (endptr == value || *endptr != '\0') {
  270. // Either there are no converted characters, or there were some characters
  271. // that didn't get converted.
  272. tor_asprintf(errmsg, "Could not convert %s to a number.", escaped(value));
  273. return -1;
  274. }
  275. if (errno == ERANGE) {
  276. // strtod will set errno to ERANGE on underflow or overflow.
  277. bool underflow = -.00001 < *v && *v < .00001;
  278. tor_asprintf(errmsg,
  279. "%s is too %s to express as a floating-point number.",
  280. escaped(value), underflow ? "small" : "large");
  281. return -1;
  282. }
  283. return 0;
  284. }
  285. static char *
  286. double_encode(const void *value, const void *params)
  287. {
  288. (void)params;
  289. double v = *(double*)value;
  290. char *result;
  291. tor_asprintf(&result, "%f", v);
  292. return result;
  293. }
  294. static void
  295. double_clear(void *value, const void *params)
  296. {
  297. (void)params;
  298. double *v = (double *)value;
  299. *v = 0.0;
  300. }
  301. static const var_type_fns_t double_fns = {
  302. .parse = double_parse,
  303. .encode = double_encode,
  304. .clear = double_clear,
  305. };
  306. /////
  307. // CONFIG_TYPE_BOOL
  308. // CONFIG_TYPE_AUTOBOOL
  309. //
  310. // These types are implemented as a case-insensitive string-to-integer
  311. // mapping.
  312. /////
  313. typedef struct enumeration_table_t {
  314. const char *name;
  315. int value;
  316. } enumeration_table_t;
  317. static int
  318. enum_parse(void *target, const char *value, char **errmsg,
  319. const void *params, const char *key)
  320. {
  321. (void)key;
  322. const enumeration_table_t *table = params;
  323. int *p = (int *)target;
  324. for (; table->name; ++table) {
  325. if (!strcasecmp(value, table->name)) {
  326. *p = table->value;
  327. return 0;
  328. }
  329. }
  330. tor_asprintf(errmsg, "Unrecognized value %s.", value);
  331. return -1;
  332. }
  333. static char *
  334. enum_encode(const void *value, const void *params)
  335. {
  336. int v = *(const int*)value;
  337. const enumeration_table_t *table = params;
  338. for (; table->name; ++table) {
  339. if (v == table->value)
  340. return tor_strdup(table->name);
  341. }
  342. return NULL; // error.
  343. }
  344. static void
  345. enum_clear(void *value, const void *params)
  346. {
  347. int *p = (int*)value;
  348. const enumeration_table_t *table = params;
  349. tor_assert(table->name);
  350. *p = table->value;
  351. }
  352. static bool
  353. enum_ok(const void *value, const void *params)
  354. {
  355. int v = *(const int*)value;
  356. const enumeration_table_t *table = params;
  357. for (; table->name; ++table) {
  358. if (v == table->value)
  359. return true;
  360. }
  361. return false;
  362. }
  363. static const enumeration_table_t enum_table_bool[] = {
  364. { "0", 0 },
  365. { "1", 1 },
  366. { NULL, 0 },
  367. };
  368. static const enumeration_table_t enum_table_autobool[] = {
  369. { "0", 0 },
  370. { "1", 1 },
  371. { "auto", -1 },
  372. { NULL, 0 },
  373. };
  374. static const var_type_fns_t enum_fns = {
  375. .parse = enum_parse,
  376. .encode = enum_encode,
  377. .clear = enum_clear,
  378. .ok = enum_ok,
  379. };
  380. /////
  381. // CONFIG_TYPE_ISOTIME
  382. //
  383. // This is a time_t, encoded in ISO8601 format.
  384. /////
  385. static int
  386. time_parse(void *target, const char *value, char **errmsg,
  387. const void *params, const char *key)
  388. {
  389. (void) params;
  390. (void) key;
  391. time_t *p = target;
  392. if (parse_iso_time(value, p) < 0) {
  393. tor_asprintf(errmsg, "Invalid time %s", escaped(value));
  394. return -1;
  395. }
  396. return 0;
  397. }
  398. static char *
  399. time_encode(const void *value, const void *params)
  400. {
  401. (void)params;
  402. time_t v = *(const time_t *)value;
  403. char *result = tor_malloc(ISO_TIME_LEN+1);
  404. format_iso_time(result, v);
  405. return result;
  406. }
  407. static void
  408. time_clear(void *value, const void *params)
  409. {
  410. (void)params;
  411. time_t *t = value;
  412. *t = 0;
  413. }
  414. static const var_type_fns_t time_fns = {
  415. .parse = time_parse,
  416. .encode = time_encode,
  417. .clear = time_clear,
  418. };
  419. /////
  420. // CONFIG_TYPE_CSV
  421. //
  422. // This type is a comma-separated list of strings, stored in a smartlist_t.
  423. // An empty list may be encoded either as an empty smartlist, or as NULL.
  424. /////
  425. static int
  426. csv_parse(void *target, const char *value, char **errmsg,
  427. const void *params, const char *key)
  428. {
  429. (void)params;
  430. (void)errmsg;
  431. (void)key;
  432. smartlist_t **sl = (smartlist_t**)target;
  433. *sl = smartlist_new();
  434. smartlist_split_string(*sl, value, ",",
  435. SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  436. return 0;
  437. }
  438. static char *
  439. csv_encode(const void *value, const void *params)
  440. {
  441. (void)params;
  442. const smartlist_t *sl = *(const smartlist_t **)value;
  443. if (! sl)
  444. return tor_strdup("");
  445. return smartlist_join_strings(*(smartlist_t**)value, ",", 0, NULL);
  446. }
  447. static void
  448. csv_clear(void *value, const void *params)
  449. {
  450. (void)params;
  451. smartlist_t **sl = (smartlist_t**)value;
  452. if (!*sl)
  453. return;
  454. SMARTLIST_FOREACH(*sl, char *, cp, tor_free(cp));
  455. smartlist_free(*sl); // clears pointer.
  456. }
  457. static const var_type_fns_t csv_fns = {
  458. .parse = csv_parse,
  459. .encode = csv_encode,
  460. .clear = csv_clear,
  461. };
  462. /////
  463. // CONFIG_TYPE_CSV_INTERVAL
  464. //
  465. // This type used to be a list of time intervals, used to determine a download
  466. // schedule. Now, only the first interval counts: everything after the first
  467. // comma is discarded.
  468. /////
  469. static int
  470. legacy_csv_interval_parse(void *target, const char *value, char **errmsg,
  471. const void *params, const char *key)
  472. {
  473. (void)params;
  474. /* We used to have entire smartlists here. But now that all of our
  475. * download schedules use exponential backoff, only the first part
  476. * matters. */
  477. const char *comma = strchr(value, ',');
  478. const char *val = value;
  479. char *tmp = NULL;
  480. if (comma) {
  481. tmp = tor_strndup(val, comma - val);
  482. val = tmp;
  483. }
  484. int rv = units_parse_int(target, val, errmsg, &time_units, key);
  485. tor_free(tmp);
  486. return rv;
  487. }
  488. static const var_type_fns_t legacy_csv_interval_fns = {
  489. .parse = legacy_csv_interval_parse,
  490. .encode = int_encode,
  491. .clear = int_clear,
  492. };
  493. /////
  494. // CONFIG_TYPE_LINELIST
  495. // CONFIG_TYPE_LINELIST_S
  496. // CONFIG_TYPE_LINELIST_V
  497. //
  498. // A linelist is a raw config_line_t list. Order is preserved.
  499. //
  500. // The LINELIST type is used for homogeneous lists, where all the lines
  501. // have the same key.
  502. //
  503. // The LINELIST_S and LINELIST_V types are used for the case where multiple
  504. // lines of different keys are kept in a single list, to preserve their
  505. // relative order. The unified list is stored as a "virtual" variable whose
  506. // type is LINELIST_V; the individual sublists are treated as variables of
  507. // type LINELIST_S.
  508. //
  509. // A linelist may be fragile or non-fragile. Assigning a line to a fragile
  510. // linelist replaces the list with the line. If the line has the "APPEND"
  511. // command set on it, or if the list is non-fragile, the line is appended.
  512. // Either way, the new list is non-fragile.
  513. /////
  514. static int
  515. linelist_kv_parse(void *target, const struct config_line_t *line,
  516. char **errmsg, const void *params)
  517. {
  518. (void)params;
  519. (void)errmsg;
  520. config_line_t **lines = target;
  521. if (*lines && (*lines)->fragile) {
  522. if (line->command == CONFIG_LINE_APPEND) {
  523. (*lines)->fragile = 0;
  524. } else {
  525. config_free_lines(*lines); // sets it to NULL
  526. }
  527. }
  528. config_line_append(lines, line->key, line->value);
  529. return 0;
  530. }
  531. static int
  532. linelist_kv_virt_noparse(void *target, const struct config_line_t *line,
  533. char **errmsg, const void *params)
  534. {
  535. (void)target;
  536. (void)line;
  537. (void)params;
  538. *errmsg = tor_strdup("Cannot assign directly to virtual option.");
  539. return -1;
  540. }
  541. static struct config_line_t *
  542. linelist_kv_encode(const char *key, const void *value,
  543. const void *params)
  544. {
  545. (void)key;
  546. (void)params;
  547. config_line_t *lines = *(config_line_t **)value;
  548. return config_lines_dup(lines);
  549. }
  550. static struct config_line_t *
  551. linelist_s_kv_encode(const char *key, const void *value,
  552. const void *params)
  553. {
  554. (void)params;
  555. config_line_t *lines = *(config_line_t **)value;
  556. return config_lines_dup_and_filter(lines, key);
  557. }
  558. static void
  559. linelist_clear(void *target, const void *params)
  560. {
  561. (void)params;
  562. config_line_t **lines = target;
  563. config_free_lines(*lines); // sets it to NULL
  564. }
  565. static bool
  566. linelist_eq(const void *a, const void *b, const void *params)
  567. {
  568. (void)params;
  569. const config_line_t *lines_a = *(const config_line_t **)a;
  570. const config_line_t *lines_b = *(const config_line_t **)b;
  571. return config_lines_eq(lines_a, lines_b);
  572. }
  573. static int
  574. linelist_copy(void *target, const void *value, const void *params)
  575. {
  576. (void)params;
  577. config_line_t **ptr = (config_line_t **)target;
  578. const config_line_t *val = *(const config_line_t **)value;
  579. config_free_lines(*ptr);
  580. *ptr = config_lines_dup(val);
  581. return 0;
  582. }
  583. static void
  584. linelist_mark_fragile(void *target, const void *params)
  585. {
  586. (void)params;
  587. config_line_t **ptr = (config_line_t **)target;
  588. if (*ptr)
  589. (*ptr)->fragile = 1;
  590. }
  591. static const var_type_fns_t linelist_fns = {
  592. .kv_parse = linelist_kv_parse,
  593. .kv_encode = linelist_kv_encode,
  594. .clear = linelist_clear,
  595. .eq = linelist_eq,
  596. .copy = linelist_copy,
  597. .mark_fragile = linelist_mark_fragile,
  598. };
  599. static const var_type_fns_t linelist_v_fns = {
  600. .kv_parse = linelist_kv_virt_noparse,
  601. .kv_encode = linelist_kv_encode,
  602. .clear = linelist_clear,
  603. .eq = linelist_eq,
  604. .copy = linelist_copy,
  605. .mark_fragile = linelist_mark_fragile,
  606. };
  607. static const var_type_fns_t linelist_s_fns = {
  608. .kv_parse = linelist_kv_parse,
  609. .kv_encode = linelist_s_kv_encode,
  610. .clear = linelist_clear,
  611. .eq = linelist_eq,
  612. .copy = linelist_copy,
  613. };
  614. /////
  615. // CONFIG_TYPE_ROUTERSET
  616. //
  617. // XXXX This type is not implemented here, since routerset_t is not available
  618. // XXXX to this module.
  619. /////
  620. /////
  621. // CONFIG_TYPE_OBSOLETE
  622. //
  623. // Used to indicate an obsolete option.
  624. //
  625. // XXXX This is not a type, and should be handled at a higher level of
  626. // XXXX abstraction.
  627. /////
  628. static int
  629. ignore_parse(void *target, const char *value, char **errmsg,
  630. const void *params, const char *key)
  631. {
  632. (void)target;
  633. (void)value;
  634. (void)errmsg;
  635. (void)params;
  636. // XXXX move this to a higher level, once such a level exists.
  637. log_warn(LD_GENERAL, "Skipping obsolete configuration option%s%s%s",
  638. key && *key ? " \"" : "",
  639. key && *key ? key : "",
  640. key && *key ? "\"." : ".");
  641. return 0;
  642. }
  643. static char *
  644. ignore_encode(const void *value, const void *params)
  645. {
  646. (void)value;
  647. (void)params;
  648. return NULL;
  649. }
  650. static const var_type_fns_t ignore_fns = {
  651. .parse = ignore_parse,
  652. .encode = ignore_encode,
  653. };
  654. /**
  655. * Table mapping conf_type_t values to var_type_def_t objects.
  656. **/
  657. static const var_type_def_t type_definitions_table[] = {
  658. [CONFIG_TYPE_STRING] = { .name="String", .fns=&string_fns },
  659. [CONFIG_TYPE_FILENAME] = { .name="Filename", .fns=&string_fns },
  660. [CONFIG_TYPE_INT] = { .name="SignedInteger", .fns=&int_fns,
  661. .params=&INT_PARSE_UNRESTRICTED },
  662. [CONFIG_TYPE_POSINT] = { .name="Integer", .fns=&int_fns,
  663. .params=&INT_PARSE_POSINT },
  664. [CONFIG_TYPE_UINT64] = { .name="Integer", .fns=&uint64_fns, },
  665. [CONFIG_TYPE_MEMUNIT] = { .name="DataSize", .fns=&memunit_fns,
  666. .params=&memory_units },
  667. [CONFIG_TYPE_INTERVAL] = { .name="TimeInterval", .fns=&interval_fns,
  668. .params=&time_units },
  669. [CONFIG_TYPE_MSEC_INTERVAL] = { .name="TimeMsecInterval",
  670. .fns=&interval_fns,
  671. .params=&time_msec_units },
  672. [CONFIG_TYPE_DOUBLE] = { .name="Float", .fns=&double_fns, },
  673. [CONFIG_TYPE_BOOL] = { .name="Boolean", .fns=&enum_fns,
  674. .params=&enum_table_bool },
  675. [CONFIG_TYPE_AUTOBOOL] = { .name="Boolean+Auto", .fns=&enum_fns,
  676. .params=&enum_table_autobool },
  677. [CONFIG_TYPE_ISOTIME] = { .name="Time", .fns=&time_fns, },
  678. [CONFIG_TYPE_CSV] = { .name="CommaList", .fns=&csv_fns, },
  679. [CONFIG_TYPE_CSV_INTERVAL] = { .name="TimeInterval",
  680. .fns=&legacy_csv_interval_fns, },
  681. [CONFIG_TYPE_LINELIST] = { .name="LineList", .fns=&linelist_fns,
  682. .flags=CFLG_NOREPLACE },
  683. /*
  684. * A "linelist_s" is a derived view of a linelist_v: inspecting
  685. * it gets part of a linelist_v, and setting it adds to the linelist_v.
  686. */
  687. [CONFIG_TYPE_LINELIST_S] = { .name="Dependent", .fns=&linelist_s_fns,
  688. .flags=CFLG_NOREPLACE|
  689. /* The operations we disable here are
  690. * handled by the linelist_v. */
  691. CFLG_NOCOPY|CFLG_NOCMP|CFLG_NODUMP },
  692. [CONFIG_TYPE_LINELIST_V] = { .name="Virtual", .fns=&linelist_v_fns,
  693. .flags=CFLG_NOREPLACE|CFLG_NOSET },
  694. [CONFIG_TYPE_OBSOLETE] = {
  695. .name="Obsolete", .fns=&ignore_fns,
  696. .flags=CFLG_GROUP_OBSOLETE,
  697. }
  698. };
  699. /**
  700. * Return a pointer to the var_type_def_t object for the given
  701. * config_type_t value, or NULL if no such type definition exists.
  702. **/
  703. const var_type_def_t *
  704. lookup_type_def(config_type_t type)
  705. {
  706. int t = type;
  707. tor_assert(t >= 0);
  708. if (t >= (int)ARRAY_LENGTH(type_definitions_table))
  709. return NULL;
  710. return &type_definitions_table[t];
  711. }