type_defs.c 19 KB

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