type_defs.c 19 KB

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