You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cfg_rcl.h 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /*
  2. * Copyright 2023 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef CFG_RCL_H_
  17. #define CFG_RCL_H_
  18. #include "config.h"
  19. #include "cfg_file.h"
  20. #include "ucl.h"
  21. #include "mem_pool.h"
  22. #define CFG_RCL_ERROR cfg_rcl_error_quark()
  23. static inline GQuark
  24. cfg_rcl_error_quark(void)
  25. {
  26. return g_quark_from_static_string("cfg-rcl-error-quark");
  27. }
  28. #ifdef __cplusplus
  29. extern "C" {
  30. #endif
  31. struct rspamd_rcl_section;
  32. struct rspamd_rcl_sections_map;
  33. struct rspamd_config;
  34. struct rspamd_rcl_default_handler_data;
  35. enum rspamd_rcl_flag {
  36. RSPAMD_CL_FLAG_TIME_FLOAT = 0x1 << 0,
  37. RSPAMD_CL_FLAG_TIME_TIMEVAL = 0x1 << 1,
  38. RSPAMD_CL_FLAG_TIME_TIMESPEC = 0x1 << 2,
  39. RSPAMD_CL_FLAG_TIME_INTEGER = 0x1 << 3,
  40. RSPAMD_CL_FLAG_TIME_UINT_32 = 0x1 << 4,
  41. RSPAMD_CL_FLAG_INT_16 = 0x1 << 5,
  42. RSPAMD_CL_FLAG_INT_32 = 0x1 << 6,
  43. RSPAMD_CL_FLAG_INT_64 = 0x1 << 7,
  44. RSPAMD_CL_FLAG_UINT = 0x1 << 8,
  45. RSPAMD_CL_FLAG_INT_SIZE = 0x1 << 9,
  46. RSPAMD_CL_FLAG_STRING_PATH = 0x1 << 10,
  47. RSPAMD_CL_FLAG_BOOLEAN_INVERSE = 0x1 << 11,
  48. RSPAMD_CL_FLAG_STRING_LIST_HASH = 0x1 << 12,
  49. RSPAMD_CL_FLAG_MULTIPLE = 0x1 << 13,
  50. RSPAMD_CL_FLAG_SIGNKEY = 0x1 << 14,
  51. RSPAMD_CL_FLAG_NISTKEY = 0x1 << 15,
  52. };
  53. struct rspamd_rcl_struct_parser {
  54. struct rspamd_config *cfg;
  55. gpointer user_struct;
  56. goffset offset;
  57. int flags; /* enum rspamd_rcl_flag */
  58. };
  59. /**
  60. * Common handler type
  61. * @param cfg configuration
  62. * @param obj object to parse
  63. * @param ud user data (depends on section)
  64. * @param err error object
  65. * @return TRUE if a section has been parsed
  66. */
  67. typedef gboolean (*rspamd_rcl_handler_t)(rspamd_mempool_t *pool,
  68. const ucl_object_t *obj,
  69. const char *key,
  70. gpointer ud,
  71. struct rspamd_rcl_section *section,
  72. GError **err);
  73. typedef gboolean (*rspamd_rcl_default_handler_t)(rspamd_mempool_t *pool,
  74. const ucl_object_t *obj,
  75. gpointer ud,
  76. struct rspamd_rcl_section *section,
  77. GError **err);
  78. /**
  79. * A handler type that is called at the end of section parsing
  80. * @param cfg configuration
  81. * @param ud user data
  82. */
  83. typedef void (*rspamd_rcl_section_fin_t)(rspamd_mempool_t *pool, gpointer ud);
  84. /**
  85. * Add a default handler for a section
  86. * @param section section pointer
  87. * @param name name of param
  88. * @param handler handler of param
  89. * @param offset offset in a structure
  90. * @param flags flags for the parser
  91. * @return newly created structure
  92. */
  93. struct rspamd_rcl_default_handler_data *rspamd_rcl_add_default_handler(
  94. struct rspamd_rcl_section *section,
  95. const char *name,
  96. rspamd_rcl_default_handler_t handler,
  97. goffset offset,
  98. int flags,
  99. const char *doc_string);
  100. /**
  101. * Add new section to the configuration
  102. * @param top top section
  103. * @param name the name of the section
  104. * @param key_attr name of the attribute that should be used as key attribute
  105. * @param handler handler function for all attributes
  106. * @param type type of object handled by a handler
  107. * @param required whether at least one of these sections is required
  108. * @param strict_type turn on strict check for types for this section
  109. * @return newly created structure
  110. */
  111. struct rspamd_rcl_section *rspamd_rcl_add_section(
  112. struct rspamd_rcl_sections_map **top,
  113. struct rspamd_rcl_section *parent_section,
  114. const char *name,
  115. const char *key_attr,
  116. rspamd_rcl_handler_t handler,
  117. enum ucl_type type,
  118. gboolean required,
  119. gboolean strict_type);
  120. struct rspamd_rcl_section *rspamd_rcl_add_section_doc(
  121. struct rspamd_rcl_sections_map **top,
  122. struct rspamd_rcl_section *parent_section,
  123. const char *name, const char *key_attr,
  124. rspamd_rcl_handler_t handler,
  125. enum ucl_type type, gboolean required,
  126. gboolean strict_type,
  127. ucl_object_t *doc_target,
  128. const char *doc_string);
  129. /**
  130. * Init common sections known to rspamd
  131. * @return top section
  132. */
  133. struct rspamd_rcl_sections_map *rspamd_rcl_config_init(struct rspamd_config *cfg,
  134. GHashTable *skip_sections);
  135. /**
  136. * Parse configuration
  137. * @param top top section
  138. * @param cfg rspamd configuration
  139. * @param ptr pointer to the target
  140. * @param pool pool object
  141. * @param obj ucl object to parse
  142. * @param err error pointer
  143. * @return
  144. */
  145. gboolean rspamd_rcl_parse(struct rspamd_rcl_sections_map *top,
  146. struct rspamd_config *cfg,
  147. gpointer ptr, rspamd_mempool_t *pool,
  148. const ucl_object_t *obj, GError **err);
  149. /**
  150. * Here is a section of common handlers that accepts rcl_struct_parser
  151. * which itself contains a struct pointer and the offset of a member in a
  152. * specific structure
  153. */
  154. /**
  155. * Parse a string field of a structure
  156. * @param cfg config pointer
  157. * @param obj object to parse
  158. * @param ud struct_parser structure
  159. * @param section the current section
  160. * @param err error pointer
  161. * @return TRUE if a string value has been successfully parsed
  162. */
  163. gboolean rspamd_rcl_parse_struct_string(rspamd_mempool_t *pool,
  164. const ucl_object_t *obj,
  165. gpointer ud,
  166. struct rspamd_rcl_section *section,
  167. GError **err);
  168. /**
  169. * Parse an integer field of a structure
  170. * @param cfg config pointer
  171. * @param obj object to parse
  172. * @param ud struct_parser structure
  173. * @param section the current section
  174. * @param err error pointer
  175. * @return TRUE if a value has been successfully parsed
  176. */
  177. gboolean rspamd_rcl_parse_struct_integer(rspamd_mempool_t *pool,
  178. const ucl_object_t *obj,
  179. gpointer ud,
  180. struct rspamd_rcl_section *section,
  181. GError **err);
  182. /**
  183. * Parse a float field of a structure
  184. * @param cfg config pointer
  185. * @param obj object to parse
  186. * @param ud struct_parser structure
  187. * @param section the current section
  188. * @param err error pointer
  189. * @return TRUE if a value has been successfully parsed
  190. */
  191. gboolean rspamd_rcl_parse_struct_double(rspamd_mempool_t *pool,
  192. const ucl_object_t *obj,
  193. gpointer ud,
  194. struct rspamd_rcl_section *section,
  195. GError **err);
  196. /**
  197. * Parse a time field of a structure
  198. * @param cfg config pointer
  199. * @param obj object to parse
  200. * @param ud struct_parser structure (flags mean the exact structure used)
  201. * @param section the current section
  202. * @param err error pointer
  203. * @return TRUE if a value has been successfully parsed
  204. */
  205. gboolean rspamd_rcl_parse_struct_time(rspamd_mempool_t *pool,
  206. const ucl_object_t *obj,
  207. gpointer ud,
  208. struct rspamd_rcl_section *section,
  209. GError **err);
  210. /**
  211. * Parse a string list field of a structure presented by a GList* object
  212. * @param cfg config pointer
  213. * @param obj object to parse
  214. * @param ud struct_parser structure (flags mean the exact structure used)
  215. * @param section the current section
  216. * @param err error pointer
  217. * @return TRUE if a value has been successfully parsed
  218. */
  219. gboolean rspamd_rcl_parse_struct_string_list(rspamd_mempool_t *pool,
  220. const ucl_object_t *obj,
  221. gpointer ud,
  222. struct rspamd_rcl_section *section,
  223. GError **err);
  224. /**
  225. * Parse a boolean field of a structure
  226. * @param cfg config pointer
  227. * @param obj object to parse
  228. * @param ud struct_parser structure (flags mean the exact structure used)
  229. * @param section the current section
  230. * @param err error pointer
  231. * @return TRUE if a value has been successfully parsed
  232. */
  233. gboolean rspamd_rcl_parse_struct_boolean(rspamd_mempool_t *pool,
  234. const ucl_object_t *obj,
  235. gpointer ud,
  236. struct rspamd_rcl_section *section,
  237. GError **err);
  238. /**
  239. * Parse a keypair field of a structure
  240. * @param cfg config pointer
  241. * @param obj object to parse
  242. * @param ud struct_parser structure (flags mean the exact structure used)
  243. * @param section the current section
  244. * @param err error pointer
  245. * @return TRUE if a value has been successfully parsed
  246. */
  247. gboolean rspamd_rcl_parse_struct_keypair(rspamd_mempool_t *pool,
  248. const ucl_object_t *obj,
  249. gpointer ud,
  250. struct rspamd_rcl_section *section,
  251. GError **err);
  252. /**
  253. * Parse a pubkey field of a structure
  254. * @param cfg config pointer
  255. * @param obj object to parse
  256. * @param ud struct_parser structure (flags mean the exact structure used)
  257. * @param section the current section
  258. * @param err error pointer
  259. * @return TRUE if a value has been successfully parsed
  260. */
  261. gboolean rspamd_rcl_parse_struct_pubkey(rspamd_mempool_t *pool,
  262. const ucl_object_t *obj,
  263. gpointer ud,
  264. struct rspamd_rcl_section *section,
  265. GError **err);
  266. /**
  267. * Parse a inet addr field of a structure
  268. * @param cfg config pointer
  269. * @param obj object to parse
  270. * @param ud struct_parser structure (flags mean the exact structure used)
  271. * @param section the current section
  272. * @param err error pointer
  273. * @return TRUE if a value has been successfully parsed
  274. */
  275. gboolean rspamd_rcl_parse_struct_addr(rspamd_mempool_t *pool,
  276. const ucl_object_t *obj,
  277. gpointer ud,
  278. struct rspamd_rcl_section *section,
  279. GError **err);
  280. /**
  281. * Parse a gmime inet address field of a structure
  282. * @param cfg config pointer
  283. * @param obj object to parse
  284. * @param ud struct_parser structure (flags mean the exact structure used)
  285. * @param section the current section
  286. * @param err error pointer
  287. * @return TRUE if a value has been successfully parsed
  288. */
  289. gboolean rspamd_rcl_parse_struct_mime_addr(rspamd_mempool_t *pool,
  290. const ucl_object_t *obj,
  291. gpointer ud,
  292. struct rspamd_rcl_section *section,
  293. GError **err);
  294. /**
  295. * Parse a raw ucl object
  296. * @param cfg config pointer
  297. * @param obj object to parse
  298. * @param ud struct_parser structure (flags mean the exact structure used)
  299. * @param section the current section
  300. * @param err error pointer
  301. * @return TRUE if a value has been successfully parsed
  302. */
  303. gboolean rspamd_rcl_parse_struct_ucl(rspamd_mempool_t *pool,
  304. const ucl_object_t *obj,
  305. gpointer ud,
  306. struct rspamd_rcl_section *section,
  307. GError **err);
  308. /**
  309. * Utility functions
  310. */
  311. /**
  312. * Register new parser for a worker type of an option with the specified name
  313. * @param cfg config structure
  314. * @param type type of worker (GQuark)
  315. * @param name name of option
  316. * @param handler handler of option
  317. * @param target opaque target structure, note it **MUST** be worker ctx due to some reasons I don't really remember
  318. * @param offset offset inside a structure
  319. */
  320. void rspamd_rcl_register_worker_option(struct rspamd_config *cfg,
  321. GQuark type,
  322. const char *name,
  323. rspamd_rcl_default_handler_t handler,
  324. gpointer target,
  325. glong offset,
  326. int flags,
  327. const char *doc_string);
  328. /**
  329. * Adds new documentation object to the configuration
  330. * @param doc_target target object where to insert documentation (top object is used if this is NULL)
  331. * @param doc_object documentation object to insert
  332. */
  333. ucl_object_t *rspamd_rcl_add_doc_obj(ucl_object_t *doc_target,
  334. const char *doc_string,
  335. const char *doc_name,
  336. ucl_type_t type,
  337. rspamd_rcl_default_handler_t handler,
  338. int flags,
  339. const char *default_value,
  340. gboolean required);
  341. /**
  342. * Adds new documentation option specified by path `doc_path` that should be
  343. * split by dots
  344. */
  345. ucl_object_t *rspamd_rcl_add_doc_by_path(struct rspamd_config *cfg,
  346. const char *doc_path,
  347. const char *doc_string,
  348. const char *doc_name,
  349. ucl_type_t type,
  350. rspamd_rcl_default_handler_t handler,
  351. int flags,
  352. const char *default_value,
  353. gboolean required);
  354. /**
  355. * Parses example and adds documentation according to the example:
  356. *
  357. * ```
  358. * section {
  359. * param1 = value; # explanation
  360. * param2 = value; # explanation
  361. * }
  362. * ```
  363. *
  364. * will produce the following documentation strings:
  365. * section ->
  366. * section.param1 : explanation
  367. * section.param2 : explanation
  368. *
  369. * @param cfg
  370. * @param root_path
  371. * @param example_data
  372. * @param example_len
  373. * @return
  374. */
  375. ucl_object_t *rspamd_rcl_add_doc_by_example(struct rspamd_config *cfg,
  376. const char *root_path,
  377. const char *doc_string,
  378. const char *doc_name,
  379. const char *example_data, gsize example_len);
  380. /**
  381. * Add lua modules path
  382. * @param cfg
  383. * @param path
  384. * @param err
  385. * @return
  386. */
  387. gboolean rspamd_rcl_add_lua_plugins_path(struct rspamd_rcl_sections_map *sections,
  388. struct rspamd_config *cfg,
  389. const char *path,
  390. gboolean main_path,
  391. GError **err);
  392. /**
  393. * Calls for an external lua function to apply potential config transformations
  394. * if needed. This function can change the cfg->rcl_obj.
  395. *
  396. * Example of transformation function:
  397. *
  398. * function(obj)
  399. * if obj.something == 'foo' then
  400. * obj.something = "bla"
  401. * return true, obj
  402. * end
  403. *
  404. * return false, nil
  405. * end
  406. *
  407. * If function returns 'false' then rcl_obj is not touched. Otherwise,
  408. * it is changed, then rcl_obj is imported from lua. Old config is dereferenced.
  409. * @param cfg
  410. */
  411. void rspamd_rcl_maybe_apply_lua_transform(struct rspamd_config *cfg);
  412. void rspamd_rcl_sections_free(struct rspamd_rcl_sections_map *sections);
  413. void rspamd_config_calculate_cksum(struct rspamd_config *cfg);
  414. /*
  415. * Read configuration file
  416. */
  417. gboolean rspamd_config_parse_ucl(struct rspamd_config *cfg,
  418. const char *filename,
  419. GHashTable *vars,
  420. ucl_include_trace_func_t inc_trace,
  421. void *trace_data,
  422. gboolean skip_jinja,
  423. GError **err);
  424. gboolean rspamd_config_read(struct rspamd_config *cfg,
  425. const char *filename,
  426. rspamd_rcl_section_fin_t logger_fin,
  427. gpointer logger_ud,
  428. GHashTable *vars,
  429. gboolean skip_jinja,
  430. char **lua_env);
  431. #ifdef __cplusplus
  432. }
  433. #endif
  434. #endif /* CFG_RCL_H_ */