Cleanup error handling of mandatory olsrv2_lan parameters
[oonf.git] / src-api / config / cfg_schema.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon version 2 (olsrd2)
4  * Copyright (c) 2004-2015, 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 /**
43  * @file
44  */
45
46 #include <assert.h>
47 #include <errno.h>
48 #include <limits.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52
53 #include "common/avl.h"
54 #include "common/avl_comp.h"
55 #include "common/bitmap256.h"
56 #include "common/common_types.h"
57 #include "common/isonumber.h"
58 #include "common/netaddr.h"
59 #include "common/netaddr_acl.h"
60 #include "common/string.h"
61 #include "config/cfg.h"
62 #include "config/cfg_db.h"
63 #include "config/cfg_help.h"
64 #include "config/cfg_schema.h"
65 #include "config/cfg_tobin.h"
66 #include "config/cfg_validate.h"
67
68 static bool _validate_cfg_entry(struct cfg_db *db, struct cfg_section_type *section, struct cfg_named_section *named,
69   struct cfg_entry *entry, const char *section_name, bool cleanup, struct autobuf *out);
70 static bool _section_needs_default_named_one(struct cfg_section_type *type);
71 static void _handle_named_section_change(struct cfg_schema_section *s_section, struct cfg_db *pre_change,
72   struct cfg_db *post_change, const char *section_name, bool startup, struct cfg_named_section *pre_defnamed,
73   struct cfg_named_section *post_defnamed);
74 static int _handle_db_changes(struct cfg_db *pre_change, struct cfg_db *post_change, bool startup);
75
76 /*! string array with boolean options with value true */
77 const char *CFGLIST_BOOL_TRUE[] = { CFGLIST_BOOL_TRUE_VALUES };
78
79 /*! string arrray with valid boolean options */
80 const char *CFGLIST_BOOL[] = { CFGLIST_BOOL_VALUES };
81
82 /*! text values for configuration schema modes */
83 const char *CFG_SCHEMA_SECTIONMODE[CFG_SSMODE_MAX] = {
84   [CFG_SSMODE_UNNAMED] = "unnamed",
85   [CFG_SSMODE_NAMED] = "named",
86   [CFG_SSMODE_NAMED_MANDATORY] = "named, mandatory",
87   [CFG_SSMODE_NAMED_WITH_DEFAULT] = "named, default name",
88 };
89
90 /**
91  * Initialize a schema
92  * @param schema pointer to uninitialized schema
93  */
94 void
95 cfg_schema_add(struct cfg_schema *schema) {
96   avl_init(&schema->sections, cfg_avlcmp_keys, true);
97   avl_init(&schema->entries, cfg_avlcmp_schemaentries, true);
98   list_init_head(&schema->handlers);
99 }
100
101 /**
102  * Add a section to a schema
103  * @param schema pointer to configuration schema
104  * @param section pointer to section
105  */
106 void
107 cfg_schema_add_section(struct cfg_schema *schema, struct cfg_schema_section *section) {
108   struct cfg_schema_entry *entry;
109   size_t i;
110
111   /* make sure definitions in compiled code are correct */
112   assert(cfg_is_allowed_key(section->type));
113   assert(section->def_name == NULL || cfg_is_allowed_section_name(section->def_name));
114
115   /* hook section into global section tree */
116   section->_section_node.key = section->type;
117   avl_insert(&schema->sections, &section->_section_node);
118
119   if (section->cb_delta_handler) {
120     /* hook callback into global callback handler list */
121     list_add_tail(&schema->handlers, &section->_delta_node);
122   }
123
124   for (i = 0; i < section->entry_count; i++) {
125     entry = &section->entries[i];
126
127     /* make sure key name in compiled code is correct */
128     assert(cfg_is_allowed_key(entry->key.entry));
129
130     entry->_parent = section;
131     entry->key.type = section->type;
132     entry->_node.key = &entry->key;
133
134     if (entry->list && entry->def.length == 1) {
135       /* empty list, set length to zero */
136       entry->def.length = 0;
137     }
138
139 #if 0
140     /* make sure all defaults are the same */
141     avl_for_each_elements_with_key(&schema->entries, entry_it, _node, entry,
142         &section->entries[i].key) {
143       if (section->entries[i].def.value == NULL) {
144         /* if we have no default, copy the one from the first existing entry */
145         memcpy(&section->entries[i].def, &entry->def, sizeof(entry->def));
146         break;
147       }
148       else {
149         /* if we have one, overwrite all existing entries */
150         memcpy(&entry->def, &section->entries[i].def, sizeof(entry->def));
151
152         // TODO: maybe output some logging that we overwrite the default?
153       }
154     }
155 #endif
156     avl_insert(&schema->entries, &section->entries[i]._node);
157   }
158 }
159
160 /**
161  * Removes a section from a schema
162  * @param schema pointer to configuration schema
163  * @param section pointer to section
164  */
165 void
166 cfg_schema_remove_section(struct cfg_schema *schema, struct cfg_schema_section *section) {
167   size_t i;
168
169   if (section->_section_node.key) {
170     avl_remove(&schema->sections, &section->_section_node);
171     section->_section_node.key = NULL;
172
173     for (i = 0; i < section->entry_count; i++) {
174       avl_remove(&schema->entries, &section->entries[i]._node);
175       section->entries[i]._node.key = NULL;
176     }
177   }
178   if (list_is_node_added(&section->_delta_node)) {
179     list_remove(&section->_delta_node);
180   }
181 }
182
183 /**
184  * Validates a database with a schema
185  * @param db pointer to configuration database
186  * @param cleanup if true, bad values will be removed from the database
187  * @param ignore_unknown_sections true if the validation should skip sections
188  *   in the database that have no schema.
189  * @param out autobuffer for validation output
190  * @return 0 if validation found no problems, -1 otherwise
191  */
192 int
193 cfg_schema_validate(struct cfg_db *db, bool cleanup, bool ignore_unknown_sections, struct autobuf *out) {
194   char section_name[256];
195   struct cfg_section_type *section, *section_it;
196   struct cfg_named_section *named, *named_it;
197   struct cfg_entry *entry, *entry_it;
198
199   struct cfg_schema_section *schema_section;
200   struct cfg_schema_section *schema_section_first, *schema_section_last;
201   struct cfg_schema_entry *schema_entry;
202   size_t i;
203
204   bool error = false;
205   bool warning = false;
206   bool hasName = false;
207
208   if (db->schema == NULL) {
209     return -1;
210   }
211
212   CFG_FOR_ALL_SECTION_TYPES(db, section, section_it) {
213     /* check for missing schema sections */
214     schema_section_first = avl_find_element(&db->schema->sections, section->type, schema_section_first, _section_node);
215
216     if (schema_section_first == NULL) {
217       if (ignore_unknown_sections) {
218         continue;
219       }
220
221       cfg_append_printable_line(out, "Cannot find schema for section type '%s'", section->type);
222
223       if (cleanup) {
224         cfg_db_remove_sectiontype(db, section->type);
225       }
226
227       error |= true;
228       continue;
229     }
230
231     schema_section_last = avl_find_le_element(&db->schema->sections, section->type, schema_section_last, _section_node);
232
233     /* iterate over all schema for a certain section type */
234     avl_for_element_range(schema_section_first, schema_section_last, schema_section, _section_node) {
235       /* check data of named sections in db */
236       CFG_FOR_ALL_SECTION_NAMES(section, named, named_it) {
237         warning = false;
238         hasName = cfg_db_is_named_section(named);
239
240         if (hasName) {
241           if (schema_section->mode == CFG_SSMODE_UNNAMED) {
242             cfg_append_printable_line(out,
243               "The section type '%s'"
244               " has to be used without a name"
245               " ('%s' was given as a name)",
246               section->type, named->name);
247
248             warning = true;
249           }
250         }
251
252         if (hasName && !cfg_is_allowed_section_name(named->name)) {
253           cfg_append_printable_line(out,
254             "The section name '%s' for"
255             " type '%s' contains illegal characters",
256             named->name, section->type);
257           warning = true;
258         }
259
260         /* test abort condition */
261         if (warning && cleanup) {
262           /* remove bad named section */
263           cfg_db_remove_namedsection(db, section->type, named->name);
264         }
265
266         error |= warning;
267
268         if (warning) {
269           continue;
270         }
271
272         /* initialize section_name field for validate */
273         snprintf(section_name, sizeof(section_name), "'%s%s%s'", section->type, hasName ? "=" : "",
274           hasName ? named->name : "");
275
276         /* check for bad values */
277         CFG_FOR_ALL_ENTRIES(named, entry, entry_it) {
278           warning = _validate_cfg_entry(db, section, named, entry, section_name, cleanup, out);
279           error |= warning;
280         }
281
282         /* check custom section validation if everything was fine */
283         if (!error && schema_section->cb_validate != NULL) {
284           if (schema_section->cb_validate(section_name, named, out)) {
285             error = true;
286           }
287         }
288       }
289     }
290     if (cleanup && avl_is_empty(&section->names)) {
291       /* if section type is empty, remove it too */
292       cfg_db_remove_sectiontype(db, section->type);
293     }
294   }
295
296   avl_for_each_element(&db->schema->sections, schema_section, _section_node) {
297     section = cfg_db_find_sectiontype(db, schema_section->type);
298     if (schema_section->mode == CFG_SSMODE_NAMED_MANDATORY) {
299       /* search for missing mandatory sections */
300       if (section == NULL || avl_is_empty(&section->names)) {
301         warning = true;
302       }
303       else {
304         named = avl_first_element(&section->names, named, node);
305         warning = !cfg_db_is_named_section(named) && section->names.count < 2;
306       }
307       if (warning) {
308         cfg_append_printable_line(out, "Missing mandatory section of type '%s'", schema_section->type);
309       }
310       error |= warning;
311     }
312
313     /* check for missing values */
314     for (i = 0; i < schema_section->entry_count; i++) {
315       schema_entry = &schema_section->entries[i];
316       if (section && strarray_is_empty_c(&schema_entry->def)) {
317         /* found a mandatory schema entry */
318
319         warning = true;
320         named = cfg_db_get_unnamed_section(section);
321         if (named) {
322           /* entry not in unnamed section */
323           warning = cfg_db_get_entry(named, schema_entry->key.entry) == NULL;
324         }
325         if (warning) {
326           /* no mandatory value in unnamed section, check named sections */
327           warning = false;
328
329           avl_for_each_element(&section->names, named, node) {
330             if (named->name != NULL && cfg_db_get_entry(named, schema_entry->key.entry) == NULL) {
331               /* found a named section without mandatory entry */
332               warning = true;
333               cfg_append_printable_line(
334                 out, "Missing mandatory entry of type '%s', name '%s' and key '%s'",
335                 schema_section->type, named->name, schema_entry->key.entry);
336               break;
337             }
338           }
339         }
340         error |= warning;
341       }
342     }
343   }
344   return error ? -1 : 0;
345 }
346
347 /**
348  * Convert the entries of a db section into binary representation by
349  * using the mappings defined in a schema section. The function assumes
350  * that the section was already validated.
351  * @param target pointer to target binary buffer
352  * @param named pointer to named section, might be NULL to refer to
353  *   default settings
354  * @param entries pointer to array of schema entries
355  * @param count number of schema entries
356  * @return 0 if conversion was successful, -(1+index) of the
357  *   failed conversion array entry if an error happened.
358  *   An error might result in a partial initialized target buffer.
359  */
360 int
361 cfg_schema_tobin(void *target, struct cfg_named_section *named, const struct cfg_schema_entry *entries, size_t count) {
362   char *ptr;
363   size_t i;
364   const struct const_strarray *value;
365
366   ptr = (char *)target;
367
368   for (i = 0; i < count; i++) {
369     if (entries[i].cb_to_binary == NULL) {
370       continue;
371     }
372
373     value = cfg_db_get_schema_entry_value(named, &entries[i]);
374     if (entries[i].cb_to_binary(&entries[i], value, ptr + entries[i].bin_offset)) {
375       /* error in conversion */
376       return -1 - i;
377     }
378   }
379   return 0;
380 }
381
382 /**
383  * Compare two databases with the same schema and call their change listeners
384  * @param pre_change database before change
385  * @param post_change database after change
386  * @return -1 if databases have different schema, 0 otherwise
387  */
388 int
389 cfg_schema_handle_db_changes(struct cfg_db *pre_change, struct cfg_db *post_change) {
390   return _handle_db_changes(pre_change, post_change, false);
391 }
392
393 /**
394  * Handle trigger of delta callbacks on program startup. Call every trigger
395  * except for CFG_SSMODE_UNNAMED_OPTIONAL_STARTUP_TRIGGER mode.
396  * @param post_db pointer to new configuration database
397  * @return -1 if an error happened, 0 otherwise
398  */
399 int
400 cfg_schema_handle_db_startup_changes(struct cfg_db *post_db) {
401   struct cfg_db *pre_db;
402   int result;
403
404   pre_db = cfg_db_add();
405   if (pre_db == NULL) {
406     return -1;
407   }
408   cfg_db_link_schema(pre_db, post_db->schema);
409
410   result = _handle_db_changes(pre_db, post_db, true);
411   cfg_db_remove(pre_db);
412   return result;
413 }
414
415 /**
416  * AVL comparator for two cfg_schema_entry_key entities.
417  * Will compare key.type first, if these are the same it will
418  * compare key.entry. NULL is valid as an entry and is smaller
419  * than all non-NULL entries. NULL is NOT valid as a type.
420  *
421  * @param p1 pointer to first key
422  * @param p2 pointer to second key
423  * @return <0 if p1 comes first, 0 if both are the same, >0 otherwise
424  */
425 int
426 cfg_avlcmp_schemaentries(const void *p1, const void *p2) {
427   const struct cfg_schema_entry_key *key1, *key2;
428   int result;
429
430   key1 = p1;
431   key2 = p2;
432
433   result = cfg_avlcmp_keys(key1->type, key2->type);
434   if (result != 0) {
435     return result;
436   }
437
438   return cfg_avlcmp_keys(key1->entry, key2->entry);
439 }
440
441 /**
442  * Helper function to get a value from an string array.
443  * Used by the CFG_xxx_CHOICE macro
444  * @param idx index to be retrieved from the string array
445  * @param ptr pointer to string array
446  * @return array element
447  */
448 const char *
449 cfg_schema_get_choice_value(size_t idx, const void *ptr) {
450   const char *const *array = ptr;
451
452   return array[idx];
453 }
454
455 /**
456  * Schema entry validator for string maximum length.
457  * See CFG_VALIDATE_STRING_LEN() macro in cfg_schema.h
458  * @param entry pointer to schema entry
459  * @param section_name name of section type and name
460  * @param value value of schema entry, NULL for help text generation
461  * @param out pointer to autobuffer for validator output
462  * @return 0 if validation found no problems, -1 otherwise
463  */
464 int
465 cfg_schema_validate_strlen(
466   const struct cfg_schema_entry *entry, const char *section_name, const char *value, struct autobuf *out) {
467   return cfg_validate_strlen(out, section_name, entry->key.entry, value, entry->validate_param[0].s);
468 }
469
470 /**
471  * Schema entry validator for strings printable characters
472  * and a maximum length.
473  * See CFG_VALIDATE_PRINTABLE*() macros in cfg_schema.h
474  * @param entry pointer to schema entry
475  * @param section_name name of section type and name
476  * @param value value of schema entry
477  * @param out pointer to autobuffer for validator output
478  * @return 0 if validation found no problems, -1 otherwise
479  */
480 int
481 cfg_schema_validate_printable(
482   const struct cfg_schema_entry *entry, const char *section_name, const char *value, struct autobuf *out) {
483   return cfg_validate_printable(out, section_name, entry->key.entry, value, entry->validate_param[0].s);
484 }
485
486 /**
487  * Schema entry validator for choice (list of possible strings)
488  * List selection will be case insensitive.
489  * See CFG_VALIDATE_CHOICE() macro in cfg_schema.h
490  * @param entry pointer to schema entry
491  * @param section_name name of section type and name
492  * @param value value of schema entry
493  * @param out pointer to autobuffer for validator output
494  * @return 0 if validation found no problems, -1 otherwise
495  */
496 int
497 cfg_schema_validate_choice(
498   const struct cfg_schema_entry *entry, const char *section_name, const char *value, struct autobuf *out) {
499   return cfg_validate_choice(out, section_name, entry->key.entry, value, entry->validate_param[0].ptr,
500     entry->validate_param[1].s, entry->validate_param[2].ptr);
501 }
502
503 /**
504  * Schema entry validator for integers.
505  * See CFG_VALIDATE_INT*() and CFG_VALIDATE_FRACTIONAL*() macros in cfg_schema.h
506  * @param entry pointer to schema entry
507  * @param section_name name of section type and name
508  * @param value value of schema entry
509  * @param out pointer to autobuffer for validator output
510  * @return 0 if validation found no problems, -1 otherwise
511  */
512 int
513 cfg_schema_validate_int(
514   const struct cfg_schema_entry *entry, const char *section_name, const char *value, struct autobuf *out) {
515   return cfg_validate_int(out, section_name, entry->key.entry, value, entry->validate_param[0].i64,
516     entry->validate_param[1].i64, entry->validate_param[2].i16[0], entry->validate_param[2].i16[1]);
517 }
518
519 /**
520  * Schema entry validator for network addresses and prefixes.
521  * See CFG_VALIDATE_NETADDR*() macros in cfg_schema.h
522  * @param entry pointer to schema entry
523  * @param section_name name of section type and name
524  * @param value value of schema entry
525  * @param out pointer to autobuffer for validator output
526  * @return 0 if validation found no problems, -1 otherwise
527  */
528 int
529 cfg_schema_validate_netaddr(
530   const struct cfg_schema_entry *entry, const char *section_name, const char *value, struct autobuf *out) {
531   return cfg_validate_netaddr(
532     out, section_name, entry->key.entry, value, entry->validate_param[1].b, entry->validate_param[0].i8, 5);
533 }
534
535 /**
536  * Schema entry validator for access control lists.
537  * See CFG_VALIDATE_ACL*() macros.
538  * @param entry pointer to schema entry
539  * @param section_name name of section type and name
540  * @param value value of schema entry
541  * @param out pointer to autobuffer for validator output
542  * @return 0 if validation found no problems, -1 otherwise
543  */
544 int
545 cfg_schema_validate_acl(
546   const struct cfg_schema_entry *entry, const char *section_name, const char *value, struct autobuf *out) {
547   return cfg_validate_acl(
548     out, section_name, entry->key.entry, value, entry->validate_param[1].b, entry->validate_param[0].i8, 5);
549 }
550
551 /**
552  * Schema entry validator for a bitmap256 object.
553  * See CFG_VALIDATE_BITMAP256() macros.
554  * @param entry pointer to schema entry
555  * @param section_name name of section type and name
556  * @param value value of schema entry
557  * @param out pointer to autobuffer for validator output
558  * @return 0 if validation found no problems, -1 otherwise
559  */
560 int
561 cfg_schema_validate_bitmap256(
562   const struct cfg_schema_entry *entry, const char *section_name, const char *value, struct autobuf *out) {
563   return cfg_validate_bitmap256(out, section_name, entry->key.entry, value);
564 }
565
566 /**
567  * Schema entry validator for a Token of space separated
568  * entries of a "sub"-schema.
569  * @param entry pointer to schema entry
570  * @param section_name name of section type and name
571  * @param value value of schema entry
572  * @param out pointer to autobuffer for validator output
573  * @return 0 if validation found no problems, -1 otherwise
574  */
575 int
576 cfg_schema_validate_tokens(
577   const struct cfg_schema_entry *entry, const char *section_name, const char *value, struct autobuf *out) {
578   return cfg_validate_tokens(out, section_name, entry->key.entry, value, entry->validate_param[0].ptr,
579     entry->validate_param[1].s, entry->validate_param[2].ptr);
580 }
581 /**
582  * Help generator for string maximum length validator.
583  * See CFG_VALIDATE_STRING_LEN() macro in cfg_schema.h
584  * @param entry pointer to schema entry
585  * @param out pointer to autobuffer for help output
586  */
587 void
588 cfg_schema_help_strlen(const struct cfg_schema_entry *entry, struct autobuf *out) {
589   cfg_help_strlen(out, entry->validate_param[0].s);
590 }
591
592 /**
593  * Help generator for strings printable characters
594  * and a maximum length validator.
595  * See CFG_VALIDATE_PRINTABLE*() macros in cfg_schema.h
596  * @param entry pointer to schema entry
597  * @param out pointer to autobuffer for validator output
598  */
599 void
600 cfg_schema_help_printable(const struct cfg_schema_entry *entry, struct autobuf *out) {
601   cfg_help_printable(out, entry->validate_param[0].s);
602 }
603
604 /**
605  * Help generator for choice (list of possible strings) validator
606  * List selection will be case insensitive.
607  * See CFG_VALIDATE_CHOICE() macro in cfg_schema.h
608  * @param entry pointer to schema entry
609  * @param out pointer to autobuffer for validator output
610  */
611 void
612 cfg_schema_help_choice(const struct cfg_schema_entry *entry, struct autobuf *out) {
613   cfg_help_choice(out, true, entry->validate_param[0].ptr, entry->validate_param[1].s, entry->validate_param[2].ptr);
614 }
615
616 /**
617  * Help generator for a fractional integer.
618  * See CFG_VALIDATE_INT*() macros in cfg_schema.h
619  * @param entry pointer to schema entry
620  * @param out pointer to autobuffer for validator output
621  */
622 void
623 cfg_schema_help_int(const struct cfg_schema_entry *entry, struct autobuf *out) {
624   cfg_help_int(out, entry->validate_param[0].i64, entry->validate_param[1].i64, entry->validate_param[2].i16[0],
625     entry->validate_param[2].i16[1]);
626 }
627
628 /**
629  * Help generator for network addresses and prefixes validator.
630  * See CFG_VALIDATE_NETADDR*() macros in cfg_schema.h
631  * @param entry pointer to schema entry
632  * @param out pointer to autobuffer for validator output
633  */
634 void
635 cfg_schema_help_netaddr(const struct cfg_schema_entry *entry, struct autobuf *out) {
636   cfg_help_netaddr(out, true, entry->validate_param[1].b, entry->validate_param[0].i8, 5);
637 }
638
639 /**
640  * Help generator for access control list validator.
641  * See CFG_VALIDATE_ACL*() macros in cfg_schema.h
642  * @param entry pointer to schema entry
643  * @param out pointer to autobuffer for validator output
644  */
645 void
646 cfg_schema_help_acl(const struct cfg_schema_entry *entry, struct autobuf *out) {
647   cfg_help_acl(out, true, entry->validate_param[1].b, entry->validate_param[0].i8, 5);
648 }
649
650 /**
651  * Help generator for bit-array validator.
652  * See CFG_VALIDATE_BITMAP256() macros in cfg_schema.h
653  * @param entry pointer to schema entry
654  * @param out pointer to autobuffer for validator output
655  */
656 void
657 cfg_schema_help_bitmap256(const struct cfg_schema_entry *entry __attribute__((unused)), struct autobuf *out) {
658   cfg_help_bitmap256(out, true);
659 }
660
661 /**
662  * Help generator for token validator.
663  * See CFG_VALIDATE_TOKEN() macro in cfg_schema.h
664  * @param entry pointer to schema entry
665  * @param out pointer to autobuffer for help output
666  */
667 void
668 cfg_schema_help_token(const struct cfg_schema_entry *entry, struct autobuf *out) {
669   cfg_help_token(
670     out, true, entry, entry->validate_param[0].ptr, entry->validate_param[1].s, entry->validate_param[2].ptr);
671 }
672
673 /**
674  * Binary converter for string pointers. This validator will
675  * allocate additional memory for the string.
676  * See CFG_MAP_STRING() and CFG_MAP_STRING_LEN() macro
677  * in cfg_schema.h
678  * @param s_entry pointer to configuration entry schema.
679  * @param value pointer to value of configuration entry.
680  * @param reference pointer to binary output buffer.
681  * @return 0 if conversion succeeded, -1 otherwise.
682  */
683 int
684 cfg_schema_tobin_strptr(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
685   if (s_entry->list) {
686     /* we don't support direct list conversion to binary */
687     return -1;
688   }
689   return cfg_tobin_strptr(reference, s_entry->bin_size, value);
690 }
691
692 /**
693  * Binary converter for string arrays.
694  * See CFG_MAP_STRING_ARRAY() macro in cfg_schema.h
695  * @param s_entry pointer to configuration entry schema.
696  * @param value pointer to value of configuration entry.
697  * @param reference pointer to binary output buffer.
698  * @return 0 if conversion succeeded, -1 otherwise.
699  */
700 int
701 cfg_schema_tobin_strarray(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
702   if (s_entry->list) {
703     /* we don't support direct list conversion to binary */
704     return -1;
705   }
706   return cfg_tobin_strarray(reference, s_entry->bin_size, value, s_entry->validate_param[0].s);
707 }
708
709 /**
710  * Binary converter for integers chosen as an index in a predefined
711  * string list.
712  * See CFG_MAP_CHOICE() macro in cfg_schema.h
713  * @param s_entry pointer to configuration entry schema.
714  * @param value pointer to value of configuration entry.
715  * @param reference pointer to binary output buffer.
716  * @return 0 if conversion succeeded, -1 otherwise.
717  */
718 int
719 cfg_schema_tobin_choice(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
720   if (s_entry->list) {
721     /* we don't support direct list conversion to binary */
722     return -1;
723   }
724   return cfg_tobin_choice(reference, s_entry->bin_size, value, s_entry->validate_param[0].ptr,
725     s_entry->validate_param[1].s, s_entry->validate_param[2].ptr);
726 }
727
728 /**
729  * Binary converter for integers.
730  * See CFG_VALIDATE_FRACTIONAL*() macro in cfg_schema.h
731  * @param s_entry pointer to configuration entry schema.
732  * @param value pointer to value of configuration entry.
733  * @param reference pointer to binary output buffer.
734  * @return 0 if conversion succeeded, -1 otherwise.
735  */
736 int
737 cfg_schema_tobin_int(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
738   if (s_entry->list) {
739     /* we don't support direct list conversion to binary */
740     return -1;
741   }
742   return cfg_tobin_int(
743     reference, s_entry->bin_size, value, s_entry->validate_param[2].u16[1], s_entry->validate_param[2].u16[0]);
744 }
745
746 /**
747  * Binary converter for netaddr objects.
748  * See CFG_MAP_NETADDR*() macros in cfg_schema.h
749  * @param s_entry pointer to configuration entry schema.
750  * @param value pointer to value of configuration entry.
751  * @param reference pointer to binary output buffer.
752  * @return 0 if conversion succeeded, -1 otherwise.
753  */
754 int
755 cfg_schema_tobin_netaddr(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
756   if (s_entry->list) {
757     /* we don't support direct list conversion to binary */
758     return -1;
759   }
760   return cfg_tobin_netaddr(reference, s_entry->bin_size, value);
761 }
762
763 /**
764  * Schema entry binary converter for ACL entries.
765  * See CFG_MAP_ACL_*() macros.
766  * @param s_entry pointer to schema entry.
767  * @param value pointer to value to configuration entry
768  * @param reference pointer to binary target
769  * @return -1 if an error happened, 0 otherwise
770  */
771 int
772 cfg_schema_tobin_acl(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
773   return cfg_tobin_acl(reference, s_entry->bin_size, value);
774 }
775
776 /**
777  * Schema entry binary converter for bitmap256 entries.
778  * See CFG_MAP_BITMAP256() macros.
779  * @param s_entry pointer to schema entry.
780  * @param value pointer to value to configuration entry
781  * @param reference pointer to binary target
782  * @return -1 if an error happened, 0 otherwise
783  */
784 int
785 cfg_schema_tobin_bitmap256(
786   const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
787   return cfg_tobin_bitmap256(reference, s_entry->bin_size, value);
788 }
789
790 /**
791  * Binary converter for booleans.
792  * See CFG_MAP_BOOL() macro in cfg_schema.h
793  * @param s_entry pointer to configuration entry schema.
794  * @param value pointer to value of configuration entry.
795  * @param reference pointer to binary output buffer.
796  * @return 0 if conversion succeeded, -1 otherwise.
797  */
798 int
799 cfg_schema_tobin_bool(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
800   if (s_entry->list) {
801     /* we don't support direct list conversion to binary */
802     return -1;
803   }
804   return cfg_tobin_bool(reference, s_entry->bin_size, value);
805 }
806
807 /**
808  * Binary converter for list of strings.
809  * See CFG_MAP_STRINGLIST() macro in cfg_schema.h
810  * @param s_entry pointer to configuration entry schema.
811  * @param value pointer to value of configuration entry.
812  * @param reference pointer to binary output buffer.
813  * @return 0 if conversion succeeded, -1 otherwise.
814  */
815 int
816 cfg_schema_tobin_stringlist(
817   const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
818   return cfg_tobin_stringlist(reference, s_entry->bin_size, value);
819 }
820
821 /**
822  * Binary converter for tokenized list of parameters.
823  * See CFG_MAP_TOKENS() macro in cfg_schema.h
824  * @param s_entry pointer to configuration entry schema.
825  * @param value pointer to value of configuration entry.
826  * @param reference pointer to binary output buffer.
827  * @return 0 if conversion succeeded, -1 otherwise.
828  */
829 int
830 cfg_schema_tobin_tokens(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
831   if (s_entry->list) {
832     /* we don't support direct list conversion to binary */
833     return -1;
834   }
835   return cfg_tobin_tokens(reference, strarray_get_first_c(value), s_entry->validate_param[0].ptr,
836     s_entry->validate_param[1].s, s_entry->validate_param[2].ptr);
837 }
838
839 /**
840  * Check if a section_type contains no named section
841  * @param type pointer to section_type
842  * @return true if section type contains no named section
843  */
844 static bool
845 _section_needs_default_named_one(struct cfg_section_type *type) {
846   struct cfg_named_section *named;
847
848   if (type == NULL || type->names.count == 0) {
849     /* no named sections there, so we need the default one */
850     return true;
851   }
852
853   if (type->names.count > 1) {
854     /* more than one section, that means at least one named one */
855     return false;
856   }
857
858   /* we have exactly one section inside */
859   named = avl_first_element(&type->names, named, node);
860
861   /* we need the default if the existing section has no name */
862   return !cfg_db_is_named_section(named);
863 }
864
865 /**
866  * Compare two sets of databases and trigger delta listeners according to connected
867  * schema.
868  * @param pre_change pre-change database
869  * @param post_change post-change database
870  * @param startup if true, also trigger unnamed sections which don't change, but are
871  *   of type CFG_SSMODE_UNNAMED (and not CFG_SSMODE_UNNAMED_OPTIONAL_STARTUP_TRIGGER).
872  * @return -1 if an error happened, 0 otherwise
873  */
874 static int
875 _handle_db_changes(struct cfg_db *pre_change, struct cfg_db *post_change, bool startup) {
876   struct cfg_section_type default_section_type[2];
877   struct cfg_named_section default_named_section[2];
878   struct cfg_schema_section *s_section;
879   struct cfg_section_type *pre_type, *post_type;
880   struct cfg_named_section *pre_named, *post_named, *named_it;
881   struct cfg_named_section *pre_defnamed, *post_defnamed;
882
883   if (pre_change->schema == NULL || pre_change->schema != post_change->schema) {
884     /* no valid schema found */
885     return -1;
886   }
887
888   /* initialize default named section mechanism */
889   memset(default_named_section, 0, sizeof(default_named_section));
890   memset(default_section_type, 0, sizeof(default_section_type));
891
892   avl_init(&default_named_section[0].entries, cfg_avlcmp_keys, false);
893   avl_init(&default_named_section[1].entries, cfg_avlcmp_keys, false);
894   default_named_section[0].section_type = &default_section_type[0];
895   default_named_section[1].section_type = &default_section_type[1];
896
897   default_section_type[0].db = pre_change;
898   default_section_type[1].db = post_change;
899
900   list_for_each_element(&pre_change->schema->handlers, s_section, _delta_node) {
901     /* get section types in both databases */
902     pre_type = cfg_db_find_sectiontype(pre_change, s_section->type);
903     post_type = cfg_db_find_sectiontype(post_change, s_section->type);
904
905     /* prepare for default named section */
906     pre_defnamed = NULL;
907     post_defnamed = NULL;
908
909     if (s_section->mode == CFG_SSMODE_NAMED_WITH_DEFAULT) {
910       /* check if we need a default section for pre_change db */
911       if (!startup && _section_needs_default_named_one(pre_type)) {
912         /* initialize dummy section type for pre-change db */
913         default_section_type[0].type = s_section->type;
914
915         /* initialize dummy named section for pre-change */
916         default_named_section[0].name = s_section->def_name;
917
918         /* remember decision */
919         pre_defnamed = &default_named_section[0];
920       }
921
922       /* check if we need a default section for post_change db */
923       if (_section_needs_default_named_one(post_type)) {
924         /* initialize dummy section type for post-change db */
925         default_section_type[1].type = s_section->type;
926
927         /* initialize dummy named section for post-change */
928         default_named_section[1].name = s_section->def_name;
929
930         /* remember decision */
931         post_defnamed = &default_named_section[1];
932       }
933     }
934
935     if (post_type) {
936       /* handle new named sections and changes */
937       pre_named = NULL;
938       CFG_FOR_ALL_SECTION_NAMES(post_type, post_named, named_it) {
939         _handle_named_section_change(
940           s_section, pre_change, post_change, post_named->name, startup, pre_defnamed, post_defnamed);
941       }
942     }
943     if (pre_type) {
944       /* handle removed named sections */
945       post_named = NULL;
946       CFG_FOR_ALL_SECTION_NAMES(pre_type, pre_named, named_it) {
947         if (post_type) {
948           post_named = cfg_db_get_named_section(post_type, pre_named->name);
949         }
950
951         if (!post_named) {
952           _handle_named_section_change(
953             s_section, pre_change, post_change, pre_named->name, startup, pre_defnamed, post_defnamed);
954         }
955       }
956     }
957     if (startup && s_section->mode == CFG_SSMODE_UNNAMED && pre_type == NULL && post_type == NULL) {
958       /* send change signal on startup for unnamed section */
959       _handle_named_section_change(s_section, pre_change, post_change, NULL, true, pre_defnamed, post_defnamed);
960     }
961     if ((pre_defnamed != NULL) != (post_defnamed != NULL)) {
962       /* status of default named section changed */
963       _handle_named_section_change(
964         s_section, pre_change, post_change, s_section->def_name, true, pre_defnamed, post_defnamed);
965     }
966   }
967   return 0;
968 }
969
970 /**
971  * Validates on configuration entry.
972  * @param db pointer to database
973  * @param section pointer to database section type
974  * @param named pointer to named section
975  * @param entry pointer to configuration entry
976  * @param section_name name of section including type (for debug output)
977  * @param cleanup true if bad _entries should be removed
978  * @param out error output buffer
979  * @return true if an error happened, false otherwise
980  */
981 static bool
982 _validate_cfg_entry(struct cfg_db *db, struct cfg_section_type *section, struct cfg_named_section *named,
983   struct cfg_entry *entry, const char *section_name, bool cleanup, struct autobuf *out) {
984   struct cfg_schema_entry *schema_entry, *s_entry_it;
985   struct cfg_schema_entry_key key;
986   bool warning, do_remove;
987   char *ptr1;
988
989   warning = false;
990   ptr1 = NULL;
991
992   key.type = section->type;
993   key.entry = entry->name;
994
995   avl_for_each_elements_with_key(&db->schema->entries, schema_entry, _node, s_entry_it, &key) {
996     if (schema_entry->cb_validate == NULL) {
997       continue;
998     }
999
1000     /* now validate syntax */
1001     ptr1 = entry->val.value;
1002
1003     do_remove = false;
1004     while (!strarray_is_empty(&entry->val) && ptr1 < entry->val.value + entry->val.length) {
1005       if (!do_remove && schema_entry->cb_validate(schema_entry, section_name, ptr1, out) != 0) {
1006         /* warning is generated by the validate callback itself */
1007         warning = true;
1008       }
1009
1010       if ((warning || do_remove) && cleanup) {
1011         /* illegal entry found, remove it */
1012         strarray_remove_ext(&entry->val, ptr1, false);
1013       }
1014       else {
1015         ptr1 += strlen(ptr1) + 1;
1016       }
1017
1018       if (!schema_entry->list) {
1019         do_remove = true;
1020       }
1021     }
1022
1023     if (strarray_is_empty(&entry->val)) {
1024       /* remove entry */
1025       cfg_db_remove_entry(db, section->type, named->name, entry->name);
1026     }
1027   }
1028   return warning;
1029 }
1030
1031 /**
1032  * Handle changes in a single named section
1033  * @param s_section schema entry for section
1034  * @param pre_change pointer to database before changes
1035  * @param post_change pointer to database after changes
1036  * @param section_name name of section, might be NULL for unnamed one
1037  * @param startup true comparison against empty database at startup
1038  * @param pre_defnamed named section with default name before change
1039  * @param post_defnamed named section with default name after change
1040  */
1041 static void
1042 _handle_named_section_change(struct cfg_schema_section *s_section, struct cfg_db *pre_change,
1043   struct cfg_db *post_change, const char *section_name, bool startup, struct cfg_named_section *pre_defnamed,
1044   struct cfg_named_section *post_defnamed) {
1045   struct cfg_schema_entry *entry;
1046   bool changed;
1047   size_t i;
1048
1049   if ((s_section->mode == CFG_SSMODE_NAMED || s_section->mode == CFG_SSMODE_NAMED_MANDATORY ||
1050         s_section->mode == CFG_SSMODE_NAMED_WITH_DEFAULT) &&
1051       section_name == NULL) {
1052     /*
1053      * ignore unnamed data entry for named sections, they are only
1054      * used for delivering defaults
1055      */
1056     return;
1057   }
1058
1059   s_section->pre = cfg_db_find_namedsection(pre_change, s_section->type, section_name);
1060   s_section->post = cfg_db_find_namedsection(post_change, s_section->type, section_name);
1061
1062   if (s_section->mode == CFG_SSMODE_NAMED_WITH_DEFAULT && strcasecmp(s_section->def_name, section_name) == 0) {
1063     /* use the default named sections if necessary */
1064     if (s_section->pre == NULL && !startup) {
1065       s_section->pre = pre_defnamed;
1066     }
1067     if (s_section->post == NULL) {
1068       s_section->post = post_defnamed;
1069     }
1070   }
1071
1072   changed = false;
1073
1074   if ((s_section->mode == CFG_SSMODE_NAMED || s_section->mode == CFG_SSMODE_NAMED_MANDATORY ||
1075         s_section->mode == CFG_SSMODE_NAMED_WITH_DEFAULT) &&
1076       (s_section->pre == NULL) != (s_section->post == NULL)) {
1077     /* section vanished or appeared */
1078     changed = true;
1079   }
1080
1081   for (i = 0; i < s_section->entry_count; i++) {
1082     entry = &s_section->entries[i];
1083
1084     /* read values */
1085     entry->pre = cfg_db_get_entry_value(pre_change, s_section->type, section_name, entry->key.entry);
1086     entry->post = cfg_db_get_entry_value(post_change, s_section->type, section_name, entry->key.entry);
1087
1088     entry->delta_changed = strarray_cmp_c(entry->pre, entry->post);
1089     changed |= entry->delta_changed;
1090   }
1091
1092   if (changed || startup) {
1093     s_section->section_name = section_name;
1094     s_section->cb_delta_handler();
1095   }
1096 }