1 /*------------------------------------------------------------------------------
2  *
3  * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4  * The YADIFA TM software product is provided under the BSD 3-clause license:
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *        * Redistributions in binary form must reproduce the above copyright
13  *          notice, this list of conditions and the following disclaimer in the
14  *          documentation and/or other materials provided with the distribution.
15  *        * Neither the name of EURid nor the names of its contributors may be
16  *          used to endorse or promote products derived from this software
17  *          without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  *------------------------------------------------------------------------------
32  *
33  */
34 
35 /** @defgroup
36  *  @ingroup
37  *  @brief
38  *
39  * @{
40  */
41 
42 #pragma once
43 
44 #include <stddef.h>
45 
46 #include <dnscore/output_stream.h>
47 #include <dnscore/input_stream.h>
48 #include <dnscore/host_address.h>
49 #include <dnscore/ptr_vector.h>
50 #include <dnscore/cmdline.h>
51 
52 /*
53  Each section/container descriptor is registered.
54 
55    config section descriptor -------> target base (ie: g_config)
56               |
57               V
58   config table descriptor vtbl -----> callbacks (init, start, stop, finalise, ...)
59               |
60               V
61       table descriptor (BEGIN/END, names, offsets in target base, setters)
62 */
63 
64 #define CONFIG_ERROR_BASE                       0x800C0000
65 #define CONFIG_ERROR_CODE(code_)                ((s32)(CONFIG_ERROR_BASE+(code_)))
66 
67 // Bugs in the program
68 #define CONFIG_SECTION_ALREADY_REGISTERED       CONFIG_ERROR_CODE(0xff01)
69 #define CONFIG_ALIAS_CHAIN_TOO_BIG              CONFIG_ERROR_CODE(0xff02)
70 // Parsing issues
71 #define CONFIG_PARSE_SECTION_TAG_NOT_CLOSED     CONFIG_ERROR_CODE(0x0001)
72 #define CONFIG_PARSE_UNEXPECTED_SECTION_OPEN    CONFIG_ERROR_CODE(0x0002)
73 #define CONFIG_PARSE_UNEXPECTED_SECTION_CLOSE   CONFIG_ERROR_CODE(0x0003)
74 #define CONFIG_PARSE_CLOSED_WRONG_SECTION       CONFIG_ERROR_CODE(0x0004)
75 #define CONFIG_PARSE_SECTION_TAG_TOO_SMALL      CONFIG_ERROR_CODE(0x0005)
76 #define CONFIG_PARSE_INCLUDE_EXPECTED_FILE_PATH CONFIG_ERROR_CODE(0x0006)
77 #define CONFIG_PARSE_UNKNOWN_KEYWORD            CONFIG_ERROR_CODE(0x0007)
78 #define CONFIG_PARSE_EXPECTED_VALUE             CONFIG_ERROR_CODE(0x0008)
79 // Content issues
80 #define CONFIG_UNKNOWN_SETTING                  CONFIG_ERROR_CODE(0x0011)
81 #define CONFIG_VALUE_OUT_OF_RANGE               CONFIG_ERROR_CODE(0x0012)
82 #define CONFIG_FILE_PATH_TOO_BIG                CONFIG_ERROR_CODE(0x0013)
83 #define CONFIG_BAD_UID                          CONFIG_ERROR_CODE(0x0014)
84 #define CONFIG_BAD_GID                          CONFIG_ERROR_CODE(0x0015)
85 #define CONFIG_TEXT_LENGHT_TOO_BIG              CONFIG_ERROR_CODE(0x0016)
86 #define CONFIG_ARRAY_SIZE_TOO_BIG               CONFIG_ERROR_CODE(0x0017)
87 
88 // Logger config specific issues
89 #define CONFIG_LOGGER_HANDLE_ALREADY_DEFINED    CONFIG_ERROR_CODE(0x1001)
90 #define CONFIG_LOGGER_INVALID_DEBUGLEVEL        CONFIG_ERROR_CODE(0x1002)
91 
92 // TSIG key config specific issues
93 #define CONFIG_KEY_INCOMPLETE_KEY               CONFIG_ERROR_CODE(0x2001)
94 #define CONFIG_KEY_UNSUPPORTED_ALGORITHM        CONFIG_ERROR_CODE(0x2002)
95 
96 /*
97 #define CONFIG_LOGGER_INVALID_DEBUGLEVEL              CONFIG_ERROR_CODE(0x0001)
98 */
99 
100 #define CONFIG_TABLE_SOURCE_NONE                0
101 #define CONFIG_TABLE_SOURCE_DEFAULT             1
102 #define CONFIG_TABLE_SOURCE_CONFIGURATION_FILE  2
103 #define CONFIG_TABLE_SOURCE_COMMAND_LINE        3
104 
105 #define CONFIG_HOST_LIST_FLAGS_IPV4             0x01
106 #define CONFIG_HOST_LIST_FLAGS_IPV6             0x02
107 #define CONFIG_HOST_LIST_FLAGS_FQDN             0x04
108 #define CONFIG_HOST_LIST_FLAGS_PORT             0x08
109 #define CONFIG_HOST_LIST_FLAGS_TSIG             0x10
110 #define CONFIG_HOST_LIST_FLAGS_APPEND           0x20
111 
112 #define CONFIG_HOST_LIST_FLAGS_DEFAULT          (CONFIG_HOST_LIST_FLAGS_IPV4 | CONFIG_HOST_LIST_FLAGS_IPV6 | CONFIG_HOST_LIST_FLAGS_PORT | CONFIG_HOST_LIST_FLAGS_TSIG)
113 
114 #define CONFIG_FLAG_ON  "1"
115 #define CONFIG_FLAG_OFF "0"
116 
117 #define CONFIG_SOURCE_NONE    0
118 #define CONFIG_SOURCE_DEFAULT 1
119 #define CONFIG_SOURCE_FILE    128
120 #define CONFIG_SOURCE_CMDLINE 250
121 #define CONFIG_SOURCE_HIGHEST 255
122 
123 #define CONFIG_SETTINGS_DEBUG 0
124 
125 #define CONFIG_FIELD_ALLOCATION_DIRECT  0       // direct value
126 #define CONFIG_FIELD_ALLOCATION_MALLOC  1       // mallocated value
127 #define CONFIG_FIELD_ALLOCATION_ZALLOC  2       // zallocated value
128 
129 /**
130  * This union covers 64 bits
131  * Meant to be used to store different parameters
132  */
133 
134 union anytype_u
135 {
136     /* DO NOT ADD THIS : bool    _bool; */
137     intptr  _intptr;
138     u8      _u8;
139     u16     _u16;
140     u32     _u32;
141     u64     _u64;
142     u8      _8u8[8];
143     u16     _4u16[4];
144     u32     _2u32[2];
145     s8      _s8;
146     s16     _s16;
147     s32     _s32;
148     s64     _s64;
149     s8      _8s8[8];
150     s16     _4s16[4];
151     s32     _2s32[2];
152     callback_function *void_callback;
153     result_callback_function *result_callback;
154     void*   _voidp;
155     char*   _charp;
156     u8*     _u8p;
157 };
158 
159 typedef union anytype_u anytype;
160 
161 
162 
163 typedef ya_result config_set_field_function(const char*, void*, const anytype);
164 
165 struct config_section_descriptor_s;
166 
167 /**
168  * name is the name of the key, expected in the config file
169  * field_offset is the offset of the value from the beginning of the target struct
170  * setter is the function able to parse the value of the key and store it at target + offset
171  * default_value_string is the string containing the default value for the key
172  * function_specific is a parameter given to the setter.  The meaning is different for each setter.
173  * source is the level that wrote the current value in the table
174  */
175 
176 struct config_table_descriptor_item_s
177 {
178     const char *name;
179     size_t field_offset;
180     config_set_field_function *setter;
181     const char *default_value_string;
182     anytype function_specific;
183     size_t expected_size;
184     size_t field_size;
185     u8 source;
186     u8 allocation_mode;
187     // help text
188 };
189 
190 typedef struct config_table_descriptor_item_s config_table_descriptor_item_s;
191 
192 typedef ya_result config_section_set_wild_method(struct config_section_descriptor_s *, const char *key, const char *value);
193 typedef ya_result config_section_print_wild_method(const struct config_section_descriptor_s *, output_stream *os, const char *key);
194 
195 typedef ya_result config_section_init_method(struct config_section_descriptor_s *);
196 typedef ya_result config_section_start_method(struct config_section_descriptor_s *);
197 typedef ya_result config_section_stop_method(struct config_section_descriptor_s *);
198 typedef ya_result config_section_postprocess_method(struct config_section_descriptor_s *);
199 typedef ya_result config_section_finalize_method(struct config_section_descriptor_s *);
200 
201 #define CFGSVTBL_TAG 0x42545653474643
202 
203 struct config_section_descriptor_vtbl_s
204 {
205     /// section name
206     const char                                 *name; // the table name
207     config_table_descriptor_item_s            *table; // the descriptor for the table (static fields)
208 
209     config_section_set_wild_method         *set_wild; // sets an undefined (dynamic) field
210     config_section_print_wild_method     *print_wild; // prints an undefined (dynamic) field
211 
212     config_section_init_method                 *init; // initialises
213     config_section_start_method               *start; // called when a section starts
214     config_section_stop_method                 *stop; // called when a section stops
215     config_section_postprocess_method   *postprocess; // called after the section has been processed
216     config_section_finalize_method         *finalise; // finishes, deletes all memory for this section, this vtbl included (if needed)
217 };
218 
219 typedef struct config_section_descriptor_vtbl_s config_section_descriptor_vtbl_s;
220 
221 #define CFGSDESC_TAG 0x4353454453474643
222 
223 struct config_section_descriptor_s
224 {
225     void *base; // base of the structure to fill up
226     const config_section_descriptor_vtbl_s *vtbl;
227 };
228 
229 typedef struct config_section_descriptor_s config_section_descriptor_s;
230 
231 /**
232  * Here are the helper macro used to define the fields in the structure
233  *
234  * The definition of the table always be done like this:
235  *
236  * struct my_struct_type
237  * {
238  *      u32 field_name_in_my_struct_type;
239  * };
240  *
241  * typedef struct my_struct_type my_struct_type;
242  *
243  * #define CONFIG_TYPE my_struct_type
244  * CONFIG_BEGIN(my_struct_type_table_desc)
245  * CONFIG_U32(field_name_in_my_struct_type,default_value_in_text_form)
246  * CONFIG_END(my_struct_type_table_desc)
247  * #undef CONFIG_TYPE
248  *
249  *
250  */
251 
252 #undef CONFIG_TYPE /* please_define_me */
253 
254 #define CONFIG_BEGIN(name_) static /* DO NOT const */ config_table_descriptor_item_s name_[] = {
255 #define CONFIG_BOOL(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_bool, defaultvalue_,{._intptr=0}, sizeof(bool), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
256 #define CONFIG_FLAG8(fieldname_,defaultvalue_, realfieldname_, mask_) {#fieldname_,offsetof(CONFIG_TYPE, realfieldname_), (config_set_field_function*)config_set_flag8, defaultvalue_,{(u8)(mask_)}, sizeof(u8), sizeof(u8), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
257 #define CONFIG_FLAG16(fieldname_,defaultvalue_, realfieldname_,mask_) {#fieldname_,offsetof(CONFIG_TYPE, realfieldname_), (config_set_field_function*)config_set_flag16, defaultvalue_,{(u16)(mask_)}, sizeof(u16), sizeof(u16), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
258 #define CONFIG_FLAG32(fieldname_,defaultvalue_, realfieldname_,mask_) {#fieldname_,offsetof(CONFIG_TYPE, realfieldname_), (config_set_field_function*)config_set_flag32, defaultvalue_,{(u32)(mask_)}, sizeof(u32), sizeof(u32), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
259 #define CONFIG_FLAG64(fieldname_,defaultvalue_, realfieldname_,mask_) {#fieldname_,offsetof(CONFIG_TYPE, realfieldname_), (config_set_field_function*)config_set_flag64, defaultvalue_,{(u64)(mask_)}, sizeof(u64), sizeof(u64), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
260 #define CONFIG_U64(fieldname_,defaultvalue_)                 {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_u64,       defaultvalue_,{._intptr=0}, sizeof(u64), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
261 #define CONFIG_U32(fieldname_,defaultvalue_)                 {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_u32,       defaultvalue_,{._intptr=0}, sizeof(u32), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
262 #define CONFIG_S32(fieldname_,defaultvalue_)                 {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_s32,       defaultvalue_,{._intptr=0}, sizeof(u32), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
263 #define CONFIG_U32_RANGE(fieldname_,defaultvalue_,min_,max_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_u32_range, defaultvalue_,{._2u32={(min_),(max_)}}, sizeof(u32), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
264 #define CONFIG_U32_CLAMP(fieldname_,defaultvalue_,min_,max_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_u32_clamp, defaultvalue_,{._2u32={(min_),(max_)}}, sizeof(u32), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
265 #define CONFIG_U16(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_u16, defaultvalue_,{._intptr=0}, sizeof(u16), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
266 #define CONFIG_DNS_TYPE(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_dnstype, defaultvalue_,{._intptr=0}, sizeof(u16), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
267 #define CONFIG_DNS_CLASS(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_dnsclass, defaultvalue_,{._intptr=0}, sizeof(u16), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
268 #define CONFIG_U8(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_u8, defaultvalue_,{._intptr=0}, sizeof(u8), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
269 #define CONFIG_DNSKEY_ALGORITHM(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_dnskey_algorithm, defaultvalue_,{._intptr=0}, sizeof(u8), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
270 #define CONFIG_U8_INC(fieldname_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_inc_u8, 0,{._intptr=0}, sizeof(u8), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
271 #define CONFIG_STRING(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_string, defaultvalue_,{._intptr=0}, sizeof(char*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
272 #define CONFIG_STRING_COPY(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_string_copy, defaultvalue_,{._u32=(sizeof(((CONFIG_TYPE*)NULL)->fieldname_))}, sizeof(((CONFIG_TYPE*)NULL)->fieldname_), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
273 #define CONFIG_STRING_ARRAY(fieldname_,default_value_,max_size_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_append_string_array_item, default_value_,{._u32=(max_size_)}, sizeof(ptr_vector), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
274 #define CONFIG_PASSWORD(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_password, defaultvalue_,{._intptr=0}, sizeof(char*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
275 #define CONFIG_FQDN(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_fqdn, defaultvalue_,{._intptr=0}, sizeof(u8*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_MALLOC },
276 #define CONFIG_PATH(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_path, defaultvalue_,{._intptr=0}, sizeof(char*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
277 #define CONFIG_CHROOT(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_chroot, defaultvalue_,{._intptr=0}, sizeof(char*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
278 #define CONFIG_LOGPATH(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_logpath, defaultvalue_,{._intptr=0}, sizeof(char*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
279 #define CONFIG_FILE(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_file, defaultvalue_,{._intptr=0}, sizeof(char*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
280 #define CONFIG_UID(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_uid_t, defaultvalue_,{._intptr=0}, sizeof(uid_t), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
281 #define CONFIG_GID(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_gid_t, defaultvalue_,{._intptr=0}, sizeof(gid_t), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
282 //#define CONFIG_ACL(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, ac) + offsetof(access_control,fieldname_), (config_set_field_function*)config_set_acl_item, defaultvalue_,{._intptr=0}, sizeof(), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
283 //#define CONFIG_ACL_FILTER(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_acl_item, defaultvalue_,{._intptr=0}, sizeof(), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
284 //#define CONFIG_LIST_ITEM(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_add_list_item, defaultvalue_,{._intptr=0}, sizeof(), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
285 #define CONFIG_ENUM(fieldname_,defaultvalue_,enumtable_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_enum_value, defaultvalue_, {(intptr)(enumtable_)}, sizeof(u32), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
286 //#define CONFIG_ENUM8(fieldname_,defaultvalue_,enumtable_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_enum8_value, defaultvalue_, {(intptr)enumtable_}, sizeof(u8), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
287 #define CONFIG_HOST_LIST(fieldname_,defaultvalue_) {#fieldname_, offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_host_list, defaultvalue_,{._8u8={CONFIG_HOST_LIST_FLAGS_DEFAULT,255,0,0,0,0,0,0}}, sizeof(host_address*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
288 #define CONFIG_HOST_LIST_EX(fieldname_,defaultvalue_,flags_,host_list_max_) {#fieldname_, offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_host_list, defaultvalue_,{._8u8={(flags_),(host_list_max_),0,0,0,0,0,0}}, sizeof(host_address*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
289 #define CONFIG_BYTES(fieldname_,defaultvalue_,maxsize_) {#fieldname_, offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_bytes, defaultvalue_, {maxsize_}, maxsize_, sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
290 //#define CONFIG_DNSSEC(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_dnssec, defaultvalue_,{._intptr=0}, sizeof(), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
291 #define CONFIG_TSIG_ITEM(fieldname_,defaultvalue_) {#fieldname_, offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_tsig_item, defaultvalue_, {._intptr=0}, sizeof(struct tsig_item*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
292 #define CONFIG_OBSOLETE(fieldname_) {#fieldname_,0, (config_set_field_function*)config_set_obsolete, NULL,{._intptr=0}, 0, 0, CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT },
293 
294 #define CONFIG_ALIAS(fieldname_, aliasedname_) {#fieldname_, 0, NULL, #aliasedname_, {._intptr=0}, 0, 0, CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT},
295     /*#define CONFIG_CATEGORY(fieldname_, category_) {#fieldname_, 0, NULL, NULL, #category},*/
296 
297 #define CONFIG_END(name_) {NULL,0,NULL,NULL, {._intptr=0}, 0, 0, CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT} }; // name_
298 
299 struct tsig_item;
300 
301 ya_result config_set_bool(const char *value, bool *dest, const anytype notused);
302 ya_result config_set_flag8(const char *value, u8 *dest, const anytype mask8);
303 ya_result config_set_flag16(const char *value, u16 *dest, const anytype mask16);
304 ya_result config_set_flag32(const char *value, u32 *dest, const anytype mask32);
305 ya_result config_set_flag64(const char *value, u64 *dest, const anytype mask64);
306 ya_result config_set_u64(const char *value,u64 *dest, const anytype notused);
307 ya_result config_set_u32(const char *value,u32 *dest, const anytype notused);
308 ya_result config_set_s32(const char *value,s32 *dest, const anytype notused);
309 ya_result config_set_u32_range(const char *value,u32 *dest, const anytype min_max);
310 ya_result config_set_u16(const char *value,u16 *dest, const anytype notused);
311 ya_result config_set_u8(const char *value,u8 *dest, const anytype notused);
312 ya_result config_inc_u8(const char *value_notused,u8 *dest, const anytype notused);
313 ya_result config_set_dnskey_algorithm(const char *value, u8 *dest, const anytype notused);
314 ya_result config_set_string(const char *value, char **dest, const anytype notused);
315 ya_result config_set_string_copy(const char *value, char *dest, const anytype maxlen);
316 ya_result config_append_string_array_item(const char *value, ptr_vector *dest, const anytype maxsize);
317 ya_result config_set_password(const char *value, char **dest, const anytype notused);
318 ya_result config_set_fqdn(const char *value, u8 **dest, const anytype notused);
319 ya_result config_set_path(const char *value, char **dest, const anytype notused);
320 ya_result config_set_chroot(const char *value, char **dest, const anytype notused);
321 ya_result config_set_logpath(const char *value, char **dest, const anytype notused);
322 ya_result config_set_file(const char *value, char **dest, const anytype notused);
323 ya_result config_set_uid_t(const char *value, uid_t *dest, const anytype notused);
324 ya_result config_set_gid_t(const char *value, gid_t *dest, const anytype notused);
325 ya_result config_set_dnstype(const char *value, u16 *dest, const anytype notused);
326 ya_result config_set_dnsclass(const char *value, u16 *dest, const anytype notused);
327 ya_result config_set_enum_value(const char *value, u32 *dest, const anytype enum_value_name_table);
328 ya_result config_set_enum8_value(const char *value, u8 *dest, const anytype enum_value_name_table);
329 ya_result config_set_host_list(const char *value, host_address **dest, const anytype notused);
330 ya_result config_set_bytes(const char *value, void *dest, const anytype sizeoftarget);
331 ya_result config_set_tsig_item(const char *value, struct tsig_item **dest, const anytype notused);
332 ya_result config_set_obsolete(const char *value, void *dest, const anytype sizeoftarget);
333 
334 // life of the config processing
335 
336 void config_init_error_codes();
337 
338 struct config_error_s
339 {
340     const char *variable_name;
341     u32 line_number;
342     bool has_content;
343     char line[256];
344     char file[PATH_MAX];
345 };
346 
347 typedef struct config_error_s config_error_s;
348 
config_error_reset(config_error_s * cfgerr)349 static inline void config_error_reset(config_error_s* cfgerr)
350 {
351     if(cfgerr != NULL)
352     {
353         cfgerr->variable_name = "";
354         cfgerr->line_number = 0;
355         cfgerr->has_content = FALSE;
356         cfgerr->line[0] = '\0';
357         cfgerr->file[0] = '\0';
358     }
359 }
360 
361 #define CONFIG_ERROR_INITIALISER { NULL, 0, "?", "?"}
362 
363 struct config_source_s;
364 
365 typedef ya_result config_source_provider_callback_function(struct config_source_s *source, input_stream *out_source, config_error_s *cfgerr);
366 
367 struct config_source_file_name_s
368 {
369     const char* name;
370 };
371 
372 struct config_source_buffer_s
373 {
374     const char* text;
375     u32 size;
376 };
377 
378 /**
379  * An help tool to register many sources at once
380  */
381 
382 struct config_source_s
383 {
384     config_source_provider_callback_function *get_source;
385     const char *name;
386     const char *__class__;
387     union
388     {
389         struct config_source_file_name_s file_name;
390         struct config_source_buffer_s buffer;
391     } source;
392     u8 level;
393 };
394 
395 #ifdef TODO
396 struct config_s
397 {
398     u32_set section_descriptor_set = U32_SET_EMPTY;
399 }:
400 #endif
401 
402 ya_result config_init();
403 
404 /**
405  * Configuration:
406  *
407  * priority : the lowest value, the fastest to be parsed
408  *            negative value : choose
409  *
410  * level    : ex: 0 for none, 1 for default, 2 for config, 3 for command line
411  *           command line has priority on everything else
412  */
413 
414 /**
415  * Gets the current source level
416  * @return the current source level
417  */
418 
419 u8 config_get_source();
420 
421 /**
422  * Sets the current source level
423  *
424  * @param l the current source level
425  */
426 
427 void config_set_source(u8 l);
428 
429 /**
430  * If the source level has been parsed, automatically fill the default values
431  * for fields that are not set yet.
432  *
433  * @return after what level do we automatically set the default values in the container
434  */
435 
436 u8 config_get_autodefault_after_source();
437 
438 /**
439  * If the source level has been parsed, automatically fill the default values
440  * for fields that are not set yet.
441  *
442  * @param l after what level do we automatically set the default values in the container ?
443  */
444 
445 void config_set_autodefault_after_source(u8 l); // if a configuration is read at this level, the default is automatically applied after
446 
447 /**
448  * Gets the default source level
449  *
450  * @return the default source level
451  */
452 
453 u8 config_get_default_source();
454 
455 /**
456  * Sets the default source level (default = 1)
457  *
458  * @param l the default source level
459  */
460 
461 void config_set_default_source(u8 l);           // this level is meant for default (1)
462 
463 #define CONFIG_CALLBACK_RESULT_CONTINUE 0
464 #define CONFIG_CALLBACK_RESULT_STOP     1
465 
466 typedef ya_result config_callback_function(const char *section_name, int section_index);
467 
468 /**
469  * Adds a callback called when a section has been read
470  *
471  * @param section_name the name of the section
472  * @param on_section_read the function to call
473  *
474  *  * @return continue, stop or an error code to fail
475  */
476 
477 ya_result config_add_on_section_read_callback(const char *section_name, config_callback_function *on_section_read);
478 
479 /**
480  * Removes a callback called when a section has been read
481  *
482  * @param section_name the name of the section
483  * @param on_section_read the function to call
484  *
485  * @return continue, stop or an error code to fail
486  */
487 
488 ya_result config_remove_on_section_read_callback(const char *section_name, config_callback_function *on_section_read);
489 
490 /**
491  * Registers a descriptor at the given priority
492  *
493  * @param section_descritor config descriptor
494  * @param priority config priority
495  *
496  * @return an error code
497  */
498 
499 ya_result config_register(config_section_descriptor_s *section_descritor, s32 priority);
500 
501 ya_result config_register_const(const config_section_descriptor_s *section_descriptor, s32 priority);
502 
503 ya_result config_unregister(config_section_descriptor_s *section_descriptor);
504 
505 config_section_descriptor_s *config_unregister_by_name(const char *name);
506 
507 /**
508  *
509  * Reads matching section/containers from a file on disk
510  *
511  * @param configuration_file_path the file path
512  * @param cfgerr error handling structure (can be NULL)
513  * @param section_name the name to match, or if NULL : all sections
514  *
515  * @return an error code
516  */
517 
518 ya_result config_read_section(const char *configuration_file_path, config_error_s *cfgerr, const char *section_name);
519 
520 /**
521  * Reads all sections/containers from a file
522  *
523  * @param configuration_file_path the file path
524  * @param cfgerr if not NULL, the error reporting structure
525  *
526  * @return an error code
527  */
528 
529 ya_result config_read(const char *configuration_file_path, config_error_s *cfgerr);
530 
531 /**
532  * Reads all sections/containers from a buffer
533  *
534  * @param buffer the text buffer
535  * @param buffer_len the text buffer length
536  * @param buffer_name the name of the buffer for error reporting
537  * @param cfgerr if not NULL, the error reporting structure
538  *
539  * @return an error code
540  */
541 
542 ya_result config_read_from_buffer(const char *buffer, u32 buffer_len, const char *buffer_name, config_error_s *cfgerr);
543 
544 /**
545  * Sets a text buffer in a source
546  *
547  * @param source the source struct to initialise
548  * @param name the name of the source
549  * @param level the level of the source
550  * @param buffer text for the source
551  * @param buffer_len text length for the source
552  */
553 
554 void config_source_set_buffer(struct config_source_s *source, const char *name, u8 level, const char *buffer, u32 buffer_len);
555 
556 /**
557  * Sets a file in a source
558  *
559  * @param source the source struct to initialise
560  * @param name the name of the file
561  * @param level the level of the source
562  */
563 
564 void config_source_set_file(struct config_source_s *source, const char *name, u8 level);
565 
566 ya_result config_source_set_commandline(struct config_source_s *source, const cmdline_desc_s *cmdline, int argc, char **argv);
567 
568 /**
569  * Read all sources from a table
570  *
571  * @param sources a pointer to the first source
572  * @param sources_count the number of sources
573  * @param cfgerr if not NULL, the error reporting structure
574  *
575  * @return an error code
576  */
577 
578 ya_result config_read_from_sources(struct config_source_s *sources, u32 sources_count, config_error_s *cfgerr);
579 
580 /**
581  * Applies default values to uninitialised fields. * @param cfgerr
582  *
583  * @param cfgerr if not NULL, the error reporting structure
584  *
585  * @return an error code
586  */
587 
588 ya_result config_set_default(config_error_s *cfgerr);
589 
590 /**
591  * Gets the section descriptor for the section/container name
592  *
593  * @param name the name of the section descriptor
594  *
595  * @return a pointer to the section descriptor or NULL if not found
596  */
597 
598 config_section_descriptor_s *config_section_get_descriptor(const char *name);
599 
600 /**
601  * Sets the table default values
602  *
603  * @param section_descriptor the descriptor to use (points to the table)
604  * @param cfgerr if not NULL, the error reporting structure
605  *
606  * @return an error code
607  */
608 
609 ya_result config_set_section_default(config_section_descriptor_s *section_descriptor, config_error_s *cfgerr);
610 
611 
612 /**
613  * Sets the key to a value
614  * Source level is taken into account.
615  * ie: config_value_set(&yadifa_config_main_desc, "daemon", "on");
616  *
617  * @param section_descriptor the descriptor pointing to the table
618  * @param key the key to set
619  * @param value to value to set it to
620  * @param cfgerr a structure that contains details about an error
621  *
622  * @return an error code
623  */
624 
625 ya_result config_value_set(config_section_descriptor_s *section_descriptor, const char *key, const char *value, config_error_s *cfgerr);
626 
627 ya_result config_source_set_by_target(config_section_descriptor_s *section_descriptor, void *target_ptr);
628 
629 /**
630  *
631  * Sets the key of the section/container to its default value
632  *
633  * @param section_name name of the section
634  * @param name key of the value
635  * @param cfgerr if not NULL, the error reporting structure
636  *
637  * @return an error code
638  */
639 
640 ya_result config_value_set_to_default(const char *section_name, const char *name, config_error_s *cfgerr);
641 
642 /**
643  *
644  * Returns the source of a value from the given section/container
645  *
646  * Look at CONFIG_SOURCE_* defines above for the predefined sources.
647  *
648  * @param section_name name of the section
649  * @param name key of the value
650  *
651  * @return the source index or an error code
652  */
653 
654 ya_result config_value_get_source(const char *section_name, const char *name);
655 
656 typedef bool config_section_struct_type_handler(output_stream *os, const char *name, void *ptr);
657 
658 bool config_section_struct_register_type_handler(config_set_field_function* setter, config_section_struct_type_handler *handler);
659 
660 /**
661  *
662  * Prints the content of every supported types of the table using the descriptor
663  *
664  * @param section_descriptor the descriptor
665  * @param os where to print to
666  */
667 
668 void config_section_print(const config_section_descriptor_s *section_descriptor, output_stream *os);
669 
670 /**
671  *
672  * Prints the content of every supported types of the table using the given descriptor on the given struct
673  *
674  * @param section_descriptor the descriptor
675  * @param a pointer to the config struct base
676  * @param os where to print to
677  */
678 
679 void config_section_struct_print(const config_section_descriptor_s *section_descriptor, const void* configbase, output_stream *os);
680 
681 /**
682  *
683  * Gets the index of the key on the table
684  *
685  * @param table a config table
686  * @param name the field key name
687  *
688  * @return an error code
689  */
690 
691 ya_result config_item_index_get(const config_table_descriptor_item_s *table, const char *name);
692 
693 /**
694  * Prints the config to the output stream
695  *
696  * @param os the output stream
697  */
698 
699 void config_print(output_stream *os);
700 
701 /**
702  * Call the postproces callback on the registered tables
703  */
704 
705 ya_result config_postprocess();
706 
707 /**
708  * Call the finalise callback on the registered tables
709  *
710  */
711 
712 ya_result config_finalize();
713 
714 // helpers
715 
716 typedef void *config_section_struct_collection_get_next_method(void *previous_data_struct);
717 
718 /**
719  *
720  * Registers a struct with its descriptor and name, for configuration.
721  *
722  * @param name name of the struct
723  * @param table table describing the struct
724  * @param data_struct pointer to the struct
725  * @param priority priority level (order of read)
726  *
727  * @return an error code
728  */
729 
730 ya_result config_register_struct(const char *name, config_table_descriptor_item_s *table, void *data_struct, s32 priority);
731 
732 void* config_unregister_struct(const char *name, const config_table_descriptor_item_s *table);
733 
734 /**
735  *
736  * Registers the logger configuration.
737  *
738  * @note logger_handle_create("handle-name",logger_handle_for_handle_name_ptr_ptr) MUST be called
739  *        before the config_read is done
740  *
741  * @param null_or_channels_name
742  * @param null_or_loggers_name
743  * @param priority
744  *
745  * @return an error code
746  */
747 
748 ya_result config_register_logger(const char *null_or_channels_name, const char *null_or_loggers_name, s32 priority);
749 
750 /**
751  * Returns TRUE iff any logging section has been found.
752  *
753  * @return TRUE iff any logging section has been found.
754  */
755 
756 bool config_logger_isconfigured();
757 
758 /**
759  * Clears the logger-configured flag
760  */
761 
762 void config_logger_clearconfigured();
763 
764 /**
765  * Sets the base path for the logger
766  *
767  * @param null_or_key_name
768  * @param priority
769  * @return
770  */
771 
772 void config_set_log_base_path(const char *path);
773 
774 /**
775  * Registers the key configuration (TSIG)
776  *
777  * @param null_or_key_name
778  * @param priority
779  * @return
780  */
781 ya_result config_register_key(const char *null_or_key_name, s32 priority);
782 
783 /** @} */
784