Allow default name for sections
[oonf.git] / src-api / config / cfg_schema.h
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2013, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 #ifndef CFG_SCHEMA_H_
43 #define CFG_SCHEMA_H_
44
45 struct cfg_schema;
46 struct cfg_schema_section;
47 struct cfg_schema_entry;
48
49 #ifndef _WIN32
50 #include <arpa/inet.h>
51 #include <netinet/if_ether.h>
52 #include <netinet/ip.h>
53 #else
54 #include <winsock2.h>
55 #include <ws2tcpip.h>
56 #endif
57
58 #include "common/autobuf.h"
59 #include "common/avl.h"
60 #include "common/netaddr.h"
61 #include "common/string.h"
62
63 #include "config/cfg_db.h"
64
65 /* text names for defining netaddr prefixes */
66 #define NETADDR_STR_ANY4       "any4"
67 #define NETADDR_STR_ANY6       "any6"
68 #define NETADDR_STR_LINKLOCAL4 "linklocal4"
69 #define NETADDR_STR_LINKLOCAL6 "linklocal6"
70 #define NETADDR_STR_ULA        "ula"
71
72 /* macros for creating schema entries */
73 #if !defined(REMOVE_HELPTEXT)
74 #define _CFG_VALIDATE(p_name, p_def, p_help,args...)                         { .key.entry = (p_name), .def = { .value = (p_def), .length = sizeof(p_def)}, .help = (p_help), ##args }
75 #else
76 #define _CFG_VALIDATE(p_name, p_def, p_help,args...)                         { .key.entry = (p_name), .def = { .value = (p_def), .length = sizeof(p_def)}, ##args }
77 #endif
78
79 /*
80  * Example of a section schema definition.
81  *
82  * All CFG_VALIDATE_xxx macros follow a similar pattern.
83  * - the first parameter is the name of the key in the configuration file
84  * - the second parameter is the default value (as a string!)
85  * - the third parameter is the help text
86  *
87  * static struct cfg_schema_section section =
88  * {
89  *     .type = "testsection",
90  *     .mode = CFG_SSMODE_NAMED
91  * };
92  *
93  * static struct cfg_schema_entry entries[] = {
94  *     CFG_VALIDATE_PRINTABLE("text", "defaulttext", "help for text parameter"),
95  *     CFG_VALIDATE_INT_MINMAX("number", "0", "help for number parameter", 0, 10),
96  * };
97  */
98 #define CFG_VALIDATE_STRING(p_name, p_def, p_help, args...)                                _CFG_VALIDATE(p_name, p_def, p_help, ##args)
99 #define CFG_VALIDATE_STRING_LEN(p_name, p_def, p_help, maxlen, args...)                    _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_strlen, .cb_valhelp = cfg_schema_help_strlen, .validate_param = {{.s = (maxlen) }}, ##args )
100 #define CFG_VALIDATE_PRINTABLE(p_name, p_def, p_help, args...)                             _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_printable, .cb_valhelp = cfg_schema_help_printable, .validate_param = {{.s = INT32_MAX }}, ##args )
101 #define CFG_VALIDATE_PRINTABLE_LEN(p_name, p_def, p_help, maxlen, args...)                 _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_printable, .cb_valhelp = cfg_schema_help_printable, .validate_param = {{.s = (maxlen) }}, ##args )
102 #define CFG_VALIDATE_CHOICE(p_name, p_def, p_help, p_list, args...)                        _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_choice, .cb_valhelp = cfg_schema_help_choice, .validate_param = {{.ptr = (p_list)}, { .s = ARRAYSIZE(p_list)}}, ##args )
103 #define CFG_VALIDATE_INT(p_name, p_def, p_help, args...)                                   _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_int, .cb_valhelp = cfg_schema_help_int, .validate_param = {{.i32 = {INT32_MIN, INT32_MAX}}}, ##args )
104 #define CFG_VALIDATE_INT_MINMAX(p_name, p_def, p_help, min, max, args...)                  _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_int, .cb_valhelp = cfg_schema_help_int, .validate_param = {{.i32 = {(min),(max)}}}, ##args )
105 #define CFG_VALIDATE_FRACTIONAL(p_name, p_def, p_help, fraction, args...)                  _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_fractional, .cb_valhelp = cfg_schema_help_fractional, .validate_param = {{.i32 = {INT32_MIN, INT32_MAX}}, {.i32 = {(fraction), 0}}}, ##args )
106 #define CFG_VALIDATE_FRACTIONAL_MINMAX(p_name, p_def, p_help, fraction, min, max, args...) _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_fractional, .cb_valhelp = cfg_schema_help_fractional, .validate_param = {{.i32 = {(min),(max)}}, {.i32 = {(fraction), 0}}}, ##args )
107 #define CFG_VALIDATE_NETADDR(p_name, p_def, p_help, prefix, unspec, args...)               _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_netaddr, .cb_valhelp = cfg_schema_help_netaddr, .validate_param = {{.i8 = {AF_MAC48, AF_EUI64, AF_INET, AF_INET6, !!(unspec) ? AF_UNSPEC : -1}}, {.b = !!(prefix)}}, ##args )
108 #define CFG_VALIDATE_NETADDR_HWADDR(p_name, p_def, p_help, prefix, unspec, args...)        _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_netaddr, .cb_valhelp = cfg_schema_help_netaddr, .validate_param = {{.i8 = {AF_MAC48, AF_EUI64, -1,-1, !!(unspec) ? AF_UNSPEC : -1}}, {.b = !!(prefix)}}, ##args )
109 #define CFG_VALIDATE_NETADDR_MAC48(p_name, p_def, p_help, prefix, unspec, args...)         _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_netaddr, .cb_valhelp = cfg_schema_help_netaddr, .validate_param = {{.i8 = {AF_MAC48, -1,-1,-1, !!(unspec) ? AF_UNSPEC : -1}}, {.b = !!(prefix)}}, ##args )
110 #define CFG_VALIDATE_NETADDR_EUI64(p_name, p_def, p_help, prefix, unspec, args...)         _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_netaddr, .cb_valhelp = cfg_schema_help_netaddr, .validate_param = {{.i8 = {AF_EUI64, -1,-1,-1, !!(unspec) ? AF_UNSPEC : -1}}, {.b = !!(prefix)}}, ##args )
111 #define CFG_VALIDATE_NETADDR_V4(p_name, p_def, p_help, prefix, unspec, args...)            _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_netaddr, .cb_valhelp = cfg_schema_help_netaddr, .validate_param = {{.i8 = {AF_INET, -1,-1,-1, !!(unspec) ? AF_UNSPEC : -1}}, {.b = !!(prefix)}}, ##args )
112 #define CFG_VALIDATE_NETADDR_V6(p_name, p_def, p_help, prefix, unspec, args...)            _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_netaddr, .cb_valhelp = cfg_schema_help_netaddr, .validate_param = {{.i8 = {AF_INET6, -1,-1,-1, !!(unspec) ? AF_UNSPEC : -1}}, {.b = !!(prefix)}}, ##args )
113 #define CFG_VALIDATE_NETADDR_V46(p_name, p_def, p_help, prefix, unspec, args...)           _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_netaddr, .cb_valhelp = cfg_schema_help_netaddr, .validate_param = {{.i8 = {AF_INET, AF_INET6, -1,-1, !!(unspec) ? AF_UNSPEC : -1}}, {.b = !!(prefix)}}, ##args )
114 #define CFG_VALIDATE_ACL(p_name, p_def, p_help, args...)                                   _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_acl, .list = true, .validate_param = {{.i8 = {-1}}, {.b = true}}, ##args )
115 #define CFG_VALIDATE_ACL_HWADDR(p_name, p_def, p_help, args...)                            _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_acl, .list = true, .validate_param = {{.i8 = {AF_MAC48, AF_EUI64, -1}}, {.b = true}}, ##args )
116 #define CFG_VALIDATE_ACL_MAC48(p_name, p_def, p_help, args...)                             _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_acl, .list = true, .validate_param = {{.i8 = {AF_MAC48, -1}}, {.b = true}}, ##args )
117 #define CFG_VALIDATE_ACL_EUI64(p_name, p_def, p_help, args...)                             _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_acl, .list = true, .validate_param = {{.i8 = {AF_EUI64, -1}}, {.b = true}}, ##args )
118 #define CFG_VALIDATE_ACL_V4(p_name, p_def, p_help, args...)                                _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_acl, .list = true, .validate_param = {{.i8 = {AF_INET, -1}}, {.b = true}}, ##args )
119 #define CFG_VALIDATE_ACL_V6(p_name, p_def, p_help, args...)                                _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_acl, .list = true, .validate_param = {{.i8 = {AF_INET6, -1}}, {.b = true}}, ##args )
120 #define CFG_VALIDATE_ACL_V46(p_name, p_def, p_help, args...)                               _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_acl, .list = true, .validate_param = {{.i8 = {AF_INET, AF_INET6, -1}}, {.b = true}}, ##args )
121
122 #define CFG_VALIDATE_BOOL(p_name, p_def, p_help, args...)                                  CFG_VALIDATE_CHOICE(p_name, p_def, p_help, CFGLIST_BOOL, ##args)
123
124 /*
125  * Example of a section schema definition with binary mapping
126  *
127  * All CFG_MAP_xxx macros follow a similar pattern.
128  * - the first parameter is the name of the struct the data will be mapped into
129  * - the second parameter is the name of the field the data will be mapped into
130  * - the third parameter is the name of the key in the configuration file
131  * - the fourth parameter is the default value (as a string!)
132  * - the fifth parameter is the help text
133  *
134  * struct bin_data {
135  *   char *string;
136  *   int int_value;
137  * };
138  *
139  * static struct cfg_schema_section section =
140  * {
141  *     .type = "testsection",
142  *     .mode = CFG_SSMODE_NAMED
143  * };
144  *
145  * static struct cfg_schema_entry entries[] = {
146  *     CFG_MAP_PRINTABLE(bin_data, string, "text", "defaulttext", "help for text parameter"),
147  *     CFG_MAP_INT_MINMAX(bin_data, int_value, "number", "0", "help for number parameter", 0, 10),
148  * };
149  */
150 #define CFG_MAP_STRING(p_reference, p_field, p_name, p_def, p_help, args...)                                _CFG_VALIDATE(p_name, p_def, p_help, .cb_to_binary = cfg_schema_tobin_strptr, .bin_offset = offsetof(struct p_reference, p_field), ##args )
151 #define CFG_MAP_STRING_LEN(p_reference, p_field, p_name, p_def, p_help, maxlen, args...)                    CFG_VALIDATE_STRING_LEN(p_name, p_def, p_help, maxlen, .cb_to_binary = cfg_schema_tobin_strptr, .bin_offset = offsetof(struct p_reference, p_field), ##args)
152 #define CFG_MAP_STRING_ARRAY(p_reference, p_field, p_name, p_def, p_help, maxlen, args...)                  CFG_VALIDATE_STRING_LEN(p_name, p_def, p_help, maxlen, .cb_to_binary = cfg_schema_tobin_strarray, .bin_offset = offsetof(struct p_reference, p_field), ##args )
153 #define CFG_MAP_PRINTABLE(p_reference, p_field, p_name, p_def, p_help, args...)                             CFG_VALIDATE_PRINTABLE(p_name, p_def, p_help, .cb_to_binary = cfg_schema_tobin_strptr, .bin_offset = offsetof(struct p_reference, p_field), ##args)
154 #define CFG_MAP_PRINTABLE_LEN(p_reference, p_field, p_name, p_def, p_help, args...)                         CFG_VALIDATE_PRINTABLE_LEN(p_name, p_def, p_help, maxlen, .cb_to_binary = cfg_schema_tobin_strptr, .bin_offset = offsetof(struct p_reference, p_field), ##args)
155 #define CFG_MAP_PRINTABLE_ARRAY(p_reference, p_field, p_name, p_def, p_help, maxlen, args...)               CFG_VALIDATE_PRINTABLE_LEN(p_name, p_def, p_help, maxlen, .cb_to_binary = cfg_schema_tobin_strarray, .bin_offset = offsetof(struct p_reference, p_field), ##args)
156 #define CFG_MAP_CHOICE(p_reference, p_field, p_name, p_def, p_help, p_list, args...)                        CFG_VALIDATE_CHOICE(p_name, p_def, p_help, p_list, .cb_to_binary = cfg_schema_tobin_choice, .bin_offset = offsetof(struct p_reference, p_field), ##args)
157 #define CFG_MAP_INT(p_reference, p_field, p_name, p_def, p_help, args...)                                   CFG_VALIDATE_INT(p_name, p_def, p_help, .cb_to_binary = cfg_schema_tobin_int, .bin_offset = offsetof(struct p_reference, p_field), ##args)
158 #define CFG_MAP_INT_MINMAX(p_reference, p_field, p_name, p_def, p_help, min, max, args...)                  CFG_VALIDATE_INT_MINMAX(p_name, p_def, p_help, min, max, .cb_to_binary = cfg_schema_tobin_int, .bin_offset = offsetof(struct p_reference, p_field), ##args)
159 #define CFG_MAP_FRACTIONAL(p_reference, p_field, p_name, p_def, p_help, fraction, args...)                  CFG_VALIDATE_FRACTIONAL(p_name, p_def, p_help, fraction, .cb_to_binary = cfg_schema_tobin_fractional, .bin_offset = offsetof(struct p_reference, p_field), ##args)
160 #define CFG_MAP_FRACTIONAL_MINMAX(p_reference, p_field, p_name, p_def, p_help, fraction, min, max, args...) CFG_VALIDATE_FRACTIONAL_MINMAX(p_name, p_def, p_help, fraction, min, max, .cb_to_binary = cfg_schema_tobin_fractional, .bin_offset = offsetof(struct p_reference, p_field), ##args)
161 #define CFG_MAP_NETADDR(p_reference, p_field, p_name, p_def, p_help, prefix, unspec, args...)               CFG_VALIDATE_NETADDR(p_name, p_def, p_help, prefix, unspec, .cb_to_binary = cfg_schema_tobin_netaddr, .bin_offset = offsetof(struct p_reference, p_field), ##args)
162 #define CFG_MAP_NETADDR_HWADDR(p_reference, p_field, p_name, p_def, p_help, prefix, unspec, args...)        CFG_VALIDATE_NETADDR_HWADDR(p_name, p_def, p_help, prefix, unspec, .cb_to_binary = cfg_schema_tobin_netaddr, .bin_offset = offsetof(struct p_reference, p_field), ##args)
163 #define CFG_MAP_NETADDR_MAC48(p_reference, p_field, p_name, p_def, p_help, prefix, unspec, args...)         CFG_VALIDATE_NETADDR_MAC48(p_name, p_def, p_help, prefix, unspec, .cb_to_binary = cfg_schema_tobin_netaddr, .bin_offset = offsetof(struct p_reference, p_field), ##args)
164 #define CFG_MAP_NETADDR_EUI64(p_reference, p_field, p_name, p_def, p_help, prefix, unspec, args...)         CFG_VALIDATE_NETADDR_EUI64(p_name, p_def, p_help, prefix, unspec, .cb_to_binary = cfg_schema_tobin_netaddr, .bin_offset = offsetof(struct p_reference, p_field), ##args)
165 #define CFG_MAP_NETADDR_V4(p_reference, p_field, p_name, p_def, p_help, prefix, unspec, args...)            CFG_VALIDATE_NETADDR_V4(p_name, p_def, p_help, prefix, unspec, .cb_to_binary = cfg_schema_tobin_netaddr, .bin_offset = offsetof(struct p_reference, p_field), ##args)
166 #define CFG_MAP_NETADDR_V6(p_reference, p_field, p_name, p_def, p_help, prefix, unspec, args...)            CFG_VALIDATE_NETADDR_V6(p_name, p_def, p_help, prefix, unspec, .cb_to_binary = cfg_schema_tobin_netaddr, .bin_offset = offsetof(struct p_reference, p_field), ##args)
167 #define CFG_MAP_NETADDR_V46(p_reference, p_field, p_name, p_def, p_help, prefix, unspec, args...)           CFG_VALIDATE_NETADDR_V46(p_name, p_def, p_help, prefix, unspec, .cb_to_binary = cfg_schema_tobin_netaddr, .bin_offset = offsetof(struct p_reference, p_field), ##args)
168 #define CFG_MAP_ACL(p_reference, p_field, p_name, p_def, p_help, args...)                                   CFG_VALIDATE_ACL(p_name, p_def, p_help, .cb_to_binary = cfg_schema_tobin_acl, .bin_offset = offsetof(struct p_reference, p_field), ##args)
169 #define CFG_MAP_ACL_HWADDR(p_reference, p_field, p_name, p_def, p_help, args...)                            CFG_VALIDATE_ACL_HWADDR(p_name, p_def, p_help, .cb_to_binary = cfg_schema_tobin_acl, .bin_offset = offsetof(struct p_reference, p_field), ##args)
170 #define CFG_MAP_ACL_MAC48(p_reference, p_field, p_name, p_def, p_help, args...)                             CFG_VALIDATE_ACL_MAC48(p_name, p_def, p_help, .cb_to_binary = cfg_schema_tobin_acl, .bin_offset = offsetof(struct p_reference, p_field), ##args)
171 #define CFG_MAP_ACL_EUI64(p_reference, p_field, p_name, p_def, p_help, args...)                             CFG_VALIDATE_ACL_EUI64(p_name, p_def, p_help, .cb_to_binary = cfg_schema_tobin_acl, .bin_offset = offsetof(struct p_reference, p_field), ##args)
172 #define CFG_MAP_ACL_V4(p_reference, p_field, p_name, p_def, p_help, args...)                                CFG_VALIDATE_ACL_V4(p_name, p_def, p_help, .cb_to_binary = cfg_schema_tobin_acl, .bin_offset = offsetof(struct p_reference, p_field), ##args)
173 #define CFG_MAP_ACL_V6(p_reference, p_field, p_name, p_def, p_help, args...)                                CFG_VALIDATE_ACL_V6(p_name, p_def, p_help, .cb_to_binary = cfg_schema_tobin_acl, .bin_offset = offsetof(struct p_reference, p_field), ##args)
174 #define CFG_MAP_ACL_V46(p_reference, p_field, p_name, p_def, p_help, args...)                               CFG_VALIDATE_ACL_V46(p_name, p_def, p_help, .cb_to_binary = cfg_schema_tobin_acl, .bin_offset = offsetof(struct p_reference, p_field), ##args)
175
176 #define CFG_MAP_BOOL(p_reference, p_field, p_name, p_def, p_help, args...)                    CFG_VALIDATE_BOOL(p_name, p_def, p_help, .cb_to_binary = cfg_schema_tobin_bool, .bin_offset = offsetof(struct p_reference, p_field), ##args)
177 #define CFG_MAP_STRINGLIST(p_reference, p_field, p_name, p_def, p_help, args...)              _CFG_VALIDATE(p_name, p_def, p_help, .cb_to_binary = cfg_schema_tobin_stringlist, .bin_offset = offsetof(struct p_reference, p_field), .list = true, ##args )
178
179
180 struct cfg_schema {
181   /* tree of sections of this schema */
182   struct avl_tree sections;
183
184   /* tree of schema entries of this schema */
185   struct avl_tree entries;
186
187   /* tree of delta handlers of this schema */
188   struct avl_tree handlers;
189 };
190
191 enum cfg_schema_section_mode {
192   /*
193    * normal unnamed section, delta handlers will be triggered at
194    * startup even it does not exist in the configuration file
195    *
196    * default setting
197    */
198   CFG_SSMODE_UNNAMED = 0,
199
200   /*
201    * unnamed section, delta handler will only trigger if one value
202    * is set to a non-default value
203    */
204   CFG_SSMODE_UNNAMED_OPTIONAL_STARTUP_TRIGGER,
205
206   /*
207    * named section, delta handlers will always trigger for this
208    */
209   CFG_SSMODE_NAMED,
210
211   /*
212    * named section, configuration demands at least one existing
213    * section of this type to be valid.
214    */
215   CFG_SSMODE_NAMED_MANDATORY,
216
217   /*
218    * named section, if none exists the configuration will create
219    * a temporary (and empty) section with the defined default name.
220    */
221   CFG_SSMODE_NAMED_WITH_DEFAULT,
222
223   /* always last */
224   CFG_SSMODE_MAX,
225 };
226
227 /*
228  * Represents the schema of all named sections within
229  * a certain type
230  */
231 struct cfg_schema_section {
232
233   /* node for global section tree, initialized by schema_add() */
234   struct avl_node _section_node;
235
236   /* name of section type, key for section_node */
237   const char *type;
238
239   /* name of default section if mode is CFG_SSMODE_NAMED_WITH_DEFAULT */
240   const char *def_name;
241
242   /* mode of this section, see above */
243   enum cfg_schema_section_mode mode;
244
245   /* help text for section */
246   const char *help;
247
248   /* callback for checking configuration of section */
249   int (*cb_validate)(const char *section_name,
250       struct cfg_named_section *, struct autobuf *);
251
252   /* node for global delta handler tree, initialized by delta_add() */
253   struct avl_node _delta_node;
254
255   /* priority for delta handling, key for delta_node */
256   uint32_t delta_priority;
257
258   /* callback for delta handling, NULL if not interested */
259   void (*cb_delta_handler)(void);
260
261   /*
262    * pointer to former and later version of changed section, only valid
263    * during call of cb_delta_handler
264    */
265   struct cfg_named_section *pre, *post;
266
267   /*
268    * Name of configured section (or NULL if unnamed section), only valid
269    * during call of cb_delta_handler
270    */
271   const char *section_name;
272
273   /* list of entries in section */
274   struct cfg_schema_entry *entries;
275   size_t entry_count;
276
277   /* pointer to next section for subsystem initialization */
278   struct cfg_schema_section *next_section;
279 };
280
281 struct cfg_schema_entry_key {
282   const char *type, *entry;
283 };
284
285 /* Represents the schema of a configuration entry */
286 struct cfg_schema_entry {
287   /* node for global section tree */
288   struct avl_node _node;
289   struct cfg_schema_section *_parent;
290
291   /* name of entry */
292   struct cfg_schema_entry_key key;
293
294   /* default value */
295   struct const_strarray def;
296
297   /* help text for entry */
298   const char *help;
299
300   /* value is a list of parameters instead of a single one */
301   bool list;
302
303   /* callback for checking value and giving help for an entry */
304   int (*cb_validate)(const struct cfg_schema_entry *entry,
305       const char *section_name, const char *value, struct autobuf *out);
306
307   void (*cb_valhelp)(const struct cfg_schema_entry *entry, struct autobuf *out);
308
309   /* parameters for validator functions */
310   union {
311     int8_t i8[8];
312     uint8_t u8[8];
313     int16_t i16[4];
314     uint16_t u16[4];
315     int32_t i32[2];
316     uint32_t u32[2];
317     int64_t i64;
318     uint64_t u64;
319     bool b;
320     size_t s;
321     void *ptr;
322   } validate_param[2];
323
324   /* callback for converting string into binary */
325   int (*cb_to_binary)(const struct cfg_schema_entry *s_entry,
326       const struct const_strarray *value, void *ptr);
327
328   /* offset of current binary data compared to reference pointer */
329   size_t bin_offset;
330
331   /* return values for delta comparision */
332   const struct const_strarray *pre, *post;
333   bool delta_changed;
334 };
335
336 EXPORT extern const char *CFGLIST_BOOL_TRUE[4];
337 EXPORT extern const char *CFGLIST_BOOL[8];
338 EXPORT extern const char *CFG_SCHEMA_SECTIONMODE[CFG_SSMODE_MAX];
339
340 EXPORT void cfg_schema_add(struct cfg_schema *schema);
341
342 EXPORT void cfg_schema_add_section(struct cfg_schema *schema, struct cfg_schema_section *section);
343 EXPORT void cfg_schema_remove_section(struct cfg_schema *schema, struct cfg_schema_section *section);
344
345 EXPORT int cfg_schema_validate(struct cfg_db *db,
346     bool cleanup, bool ignore_unknown_sections, struct autobuf *out);
347
348 EXPORT int cfg_schema_tobin(void *target, struct cfg_named_section *named,
349     const struct cfg_schema_entry *entries, size_t count);
350
351 EXPORT int cfg_schema_handle_db_changes(struct cfg_db *pre_change, struct cfg_db *post_change);
352 EXPORT int cfg_schema_handle_db_startup_changes(struct cfg_db *db);
353
354 EXPORT int cfg_avlcmp_schemaentries(const void *p1, const void *p2);
355
356 EXPORT int cfg_schema_validate_printable(const struct cfg_schema_entry *entry,
357     const char *section_name, const char *value, struct autobuf *out);
358 EXPORT int cfg_schema_validate_strlen(const struct cfg_schema_entry *entry,
359     const char *section_name, const char *value, struct autobuf *out);
360 EXPORT int cfg_schema_validate_choice(const struct cfg_schema_entry *entry,
361     const char *section_name, const char *value, struct autobuf *out);
362 EXPORT int cfg_schema_validate_int(const struct cfg_schema_entry *entry,
363     const char *section_name, const char *value, struct autobuf *out);
364 EXPORT int cfg_schema_validate_fractional(const struct cfg_schema_entry *entry,
365     const char *section_name, const char *value, struct autobuf *out);
366 EXPORT int cfg_schema_validate_netaddr(const struct cfg_schema_entry *entry,
367     const char *section_name, const char *value, struct autobuf *out);
368 EXPORT int cfg_schema_validate_acl(const struct cfg_schema_entry *entry,
369     const char *section_name, const char *value, struct autobuf *out);
370
371 EXPORT void cfg_schema_help_printable(
372     const struct cfg_schema_entry *entry, struct autobuf *out);
373 EXPORT void cfg_schema_help_strlen(
374     const struct cfg_schema_entry *entry, struct autobuf *out);
375 EXPORT void cfg_schema_help_choice(
376     const struct cfg_schema_entry *entry, struct autobuf *out);
377 EXPORT void cfg_schema_help_int(
378     const struct cfg_schema_entry *entry, struct autobuf *out);
379 EXPORT void cfg_schema_help_fractional(
380     const struct cfg_schema_entry *entry, struct autobuf *out);
381 EXPORT void cfg_schema_help_netaddr(
382     const struct cfg_schema_entry *entry, struct autobuf *out);
383
384 EXPORT int cfg_schema_tobin_strptr(const struct cfg_schema_entry *s_entry,
385     const struct const_strarray *value, void *reference);
386 EXPORT int cfg_schema_tobin_strarray(const struct cfg_schema_entry *s_entry,
387     const struct const_strarray *value, void *reference);
388 EXPORT int cfg_schema_tobin_choice(const struct cfg_schema_entry *s_entry,
389     const struct const_strarray *value, void *reference);
390 EXPORT int cfg_schema_tobin_int(const struct cfg_schema_entry *s_entry,
391     const struct const_strarray *value, void *reference);
392 EXPORT int cfg_schema_tobin_fractional(const struct cfg_schema_entry *s_entry,
393     const struct const_strarray *value, void *reference);
394 EXPORT int cfg_schema_tobin_netaddr(const struct cfg_schema_entry *s_entry,
395     const struct const_strarray *value, void *reference);
396 EXPORT int cfg_schema_tobin_bool(const struct cfg_schema_entry *s_entry,
397     const struct const_strarray *value, void *reference);
398 EXPORT int cfg_schema_tobin_stringlist(const struct cfg_schema_entry *s_entry,
399     const struct const_strarray *value, void *reference);
400 EXPORT int cfg_schema_tobin_acl(const struct cfg_schema_entry *s_entry,
401     const struct const_strarray *value, void *reference);
402
403
404 /**
405  * Finds a section in a schema
406  * @param schema pointer to schema
407  * @param type type of section
408  * @return pointer to section, NULL if not found
409  */
410 static INLINE struct cfg_schema_section *
411 cfg_schema_find_section(struct cfg_schema *schema, const char *type) {
412   struct cfg_schema_section *section;
413
414   return avl_find_element(&schema->sections, type, section, _section_node);
415 }
416
417 /**
418  * Finds an entry in a schema section
419  * @param section pointer to section
420  * @param name name of entry
421  * @return pointer of entry, NULL if not found
422  */
423 static INLINE struct cfg_schema_entry *
424 cfg_schema_find_section_entry(struct cfg_schema_section *section, const char *name) {
425   size_t i;
426
427   for (i=0; i<section->entry_count; i++) {
428     if (strcmp(section->entries[i].key.entry, name) == 0) {
429       return &section->entries[i];
430     }
431   }
432   return NULL;
433 }
434
435 #endif /* CFG_SCHEMA_H_ */