a9c2ec161a08d821dc41106ae970d2ba047cbac3
[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 (strarray_is_empty_c(&schema_entry->def)) {
317         /* found a mandatory schema entry */
318
319         warning = true;
320         if (section) {
321           named = cfg_db_get_unnamed_section(section);
322           if (named) {
323             /* entry not in unnamed section */
324             warning = cfg_db_get_entry(named, schema_entry->key.entry) == NULL;
325             if (named->name && 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                   break;
334                 }
335               }
336             }
337           }
338           else {
339             /* no unnamed section */
340             warning = true;
341           }
342         }
343         if (warning) {
344           cfg_append_printable_line(
345             out, "Missing mandatory entry of type '%s' and key '%s'", schema_section->type, schema_entry->key.entry);
346         }
347         error |= warning;
348       }
349     }
350   }
351   return error ? -1 : 0;
352 }
353
354 /**
355  * Convert the entries of a db section into binary representation by
356  * using the mappings defined in a schema section. The function assumes
357  * that the section was already validated.
358  * @param target pointer to target binary buffer
359  * @param named pointer to named section, might be NULL to refer to
360  *   default settings
361  * @param entries pointer to array of schema entries
362  * @param count number of schema entries
363  * @return 0 if conversion was successful, -(1+index) of the
364  *   failed conversion array entry if an error happened.
365  *   An error might result in a partial initialized target buffer.
366  */
367 int
368 cfg_schema_tobin(void *target, struct cfg_named_section *named, const struct cfg_schema_entry *entries, size_t count) {
369   char *ptr;
370   size_t i;
371   const struct const_strarray *value;
372
373   ptr = (char *)target;
374
375   for (i = 0; i < count; i++) {
376     if (entries[i].cb_to_binary == NULL) {
377       continue;
378     }
379
380     value = cfg_db_get_schema_entry_value(named, &entries[i]);
381     if (entries[i].cb_to_binary(&entries[i], value, ptr + entries[i].bin_offset)) {
382       /* error in conversion */
383       return -1 - i;
384     }
385   }
386   return 0;
387 }
388
389 /**
390  * Compare two databases with the same schema and call their change listeners
391  * @param pre_change database before change
392  * @param post_change database after change
393  * @return -1 if databases have different schema, 0 otherwise
394  */
395 int
396 cfg_schema_handle_db_changes(struct cfg_db *pre_change, struct cfg_db *post_change) {
397   return _handle_db_changes(pre_change, post_change, false);
398 }
399
400 /**
401  * Handle trigger of delta callbacks on program startup. Call every trigger
402  * except for CFG_SSMODE_UNNAMED_OPTIONAL_STARTUP_TRIGGER mode.
403  * @param post_db pointer to new configuration database
404  * @return -1 if an error happened, 0 otherwise
405  */
406 int
407 cfg_schema_handle_db_startup_changes(struct cfg_db *post_db) {
408   struct cfg_db *pre_db;
409   int result;
410
411   pre_db = cfg_db_add();
412   if (pre_db == NULL) {
413     return -1;
414   }
415   cfg_db_link_schema(pre_db, post_db->schema);
416
417   result = _handle_db_changes(pre_db, post_db, true);
418   cfg_db_remove(pre_db);
419   return result;
420 }
421
422 /**
423  * AVL comparator for two cfg_schema_entry_key entities.
424  * Will compare key.type first, if these are the same it will
425  * compare key.entry. NULL is valid as an entry and is smaller
426  * than all non-NULL entries. NULL is NOT valid as a type.
427  *
428  * @param p1 pointer to first key
429  * @param p2 pointer to second key
430  * @return <0 if p1 comes first, 0 if both are the same, >0 otherwise
431  */
432 int
433 cfg_avlcmp_schemaentries(const void *p1, const void *p2) {
434   const struct cfg_schema_entry_key *key1, *key2;
435   int result;
436
437   key1 = p1;
438   key2 = p2;
439
440   result = cfg_avlcmp_keys(key1->type, key2->type);
441   if (result != 0) {
442     return result;
443   }
444
445   return cfg_avlcmp_keys(key1->entry, key2->entry);
446 }
447
448 /**
449  * Helper function to get a value from an string array.
450  * Used by the CFG_xxx_CHOICE macro
451  * @param idx index to be retrieved from the string array
452  * @param ptr pointer to string array
453  * @return array element
454  */
455 const char *
456 cfg_schema_get_choice_value(size_t idx, const void *ptr) {
457   const char *const *array = ptr;
458
459   return array[idx];
460 }
461
462 /**
463  * Schema entry validator for string maximum length.
464  * See CFG_VALIDATE_STRING_LEN() macro in cfg_schema.h
465  * @param entry pointer to schema entry
466  * @param section_name name of section type and name
467  * @param value value of schema entry, NULL for help text generation
468  * @param out pointer to autobuffer for validator output
469  * @return 0 if validation found no problems, -1 otherwise
470  */
471 int
472 cfg_schema_validate_strlen(
473   const struct cfg_schema_entry *entry, const char *section_name, const char *value, struct autobuf *out) {
474   return cfg_validate_strlen(out, section_name, entry->key.entry, value, entry->validate_param[0].s);
475 }
476
477 /**
478  * Schema entry validator for strings printable characters
479  * and a maximum length.
480  * See CFG_VALIDATE_PRINTABLE*() macros in cfg_schema.h
481  * @param entry pointer to schema entry
482  * @param section_name name of section type and name
483  * @param value value of schema entry
484  * @param out pointer to autobuffer for validator output
485  * @return 0 if validation found no problems, -1 otherwise
486  */
487 int
488 cfg_schema_validate_printable(
489   const struct cfg_schema_entry *entry, const char *section_name, const char *value, struct autobuf *out) {
490   return cfg_validate_printable(out, section_name, entry->key.entry, value, entry->validate_param[0].s);
491 }
492
493 /**
494  * Schema entry validator for choice (list of possible strings)
495  * List selection will be case insensitive.
496  * See CFG_VALIDATE_CHOICE() macro in cfg_schema.h
497  * @param entry pointer to schema entry
498  * @param section_name name of section type and name
499  * @param value value of schema entry
500  * @param out pointer to autobuffer for validator output
501  * @return 0 if validation found no problems, -1 otherwise
502  */
503 int
504 cfg_schema_validate_choice(
505   const struct cfg_schema_entry *entry, const char *section_name, const char *value, struct autobuf *out) {
506   return cfg_validate_choice(out, section_name, entry->key.entry, value, entry->validate_param[0].ptr,
507     entry->validate_param[1].s, entry->validate_param[2].ptr);
508 }
509
510 /**
511  * Schema entry validator for integers.
512  * See CFG_VALIDATE_INT*() and CFG_VALIDATE_FRACTIONAL*() macros in cfg_schema.h
513  * @param entry pointer to schema entry
514  * @param section_name name of section type and name
515  * @param value value of schema entry
516  * @param out pointer to autobuffer for validator output
517  * @return 0 if validation found no problems, -1 otherwise
518  */
519 int
520 cfg_schema_validate_int(
521   const struct cfg_schema_entry *entry, const char *section_name, const char *value, struct autobuf *out) {
522   return cfg_validate_int(out, section_name, entry->key.entry, value, entry->validate_param[0].i64,
523     entry->validate_param[1].i64, entry->validate_param[2].i16[0], entry->validate_param[2].i16[1]);
524 }
525
526 /**
527  * Schema entry validator for network addresses and prefixes.
528  * See CFG_VALIDATE_NETADDR*() macros in cfg_schema.h
529  * @param entry pointer to schema entry
530  * @param section_name name of section type and name
531  * @param value value of schema entry
532  * @param out pointer to autobuffer for validator output
533  * @return 0 if validation found no problems, -1 otherwise
534  */
535 int
536 cfg_schema_validate_netaddr(
537   const struct cfg_schema_entry *entry, const char *section_name, const char *value, struct autobuf *out) {
538   return cfg_validate_netaddr(
539     out, section_name, entry->key.entry, value, entry->validate_param[1].b, entry->validate_param[0].i8, 5);
540 }
541
542 /**
543  * Schema entry validator for access control lists.
544  * See CFG_VALIDATE_ACL*() macros.
545  * @param entry pointer to schema entry
546  * @param section_name name of section type and name
547  * @param value value of schema entry
548  * @param out pointer to autobuffer for validator output
549  * @return 0 if validation found no problems, -1 otherwise
550  */
551 int
552 cfg_schema_validate_acl(
553   const struct cfg_schema_entry *entry, const char *section_name, const char *value, struct autobuf *out) {
554   return cfg_validate_acl(
555     out, section_name, entry->key.entry, value, entry->validate_param[1].b, entry->validate_param[0].i8, 5);
556 }
557
558 /**
559  * Schema entry validator for a bitmap256 object.
560  * See CFG_VALIDATE_BITMAP256() macros.
561  * @param entry pointer to schema entry
562  * @param section_name name of section type and name
563  * @param value value of schema entry
564  * @param out pointer to autobuffer for validator output
565  * @return 0 if validation found no problems, -1 otherwise
566  */
567 int
568 cfg_schema_validate_bitmap256(
569   const struct cfg_schema_entry *entry, const char *section_name, const char *value, struct autobuf *out) {
570   return cfg_validate_bitmap256(out, section_name, entry->key.entry, value);
571 }
572
573 /**
574  * Schema entry validator for a Token of space separated
575  * entries of a "sub"-schema.
576  * @param entry pointer to schema entry
577  * @param section_name name of section type and name
578  * @param value value of schema entry
579  * @param out pointer to autobuffer for validator output
580  * @return 0 if validation found no problems, -1 otherwise
581  */
582 int
583 cfg_schema_validate_tokens(
584   const struct cfg_schema_entry *entry, const char *section_name, const char *value, struct autobuf *out) {
585   return cfg_validate_tokens(out, section_name, entry->key.entry, value, entry->validate_param[0].ptr,
586     entry->validate_param[1].s, entry->validate_param[2].ptr);
587 }
588 /**
589  * Help generator for string maximum length validator.
590  * See CFG_VALIDATE_STRING_LEN() macro in cfg_schema.h
591  * @param entry pointer to schema entry
592  * @param out pointer to autobuffer for help output
593  */
594 void
595 cfg_schema_help_strlen(const struct cfg_schema_entry *entry, struct autobuf *out) {
596   cfg_help_strlen(out, entry->validate_param[0].s);
597 }
598
599 /**
600  * Help generator for strings printable characters
601  * and a maximum length validator.
602  * See CFG_VALIDATE_PRINTABLE*() macros in cfg_schema.h
603  * @param entry pointer to schema entry
604  * @param out pointer to autobuffer for validator output
605  */
606 void
607 cfg_schema_help_printable(const struct cfg_schema_entry *entry, struct autobuf *out) {
608   cfg_help_printable(out, entry->validate_param[0].s);
609 }
610
611 /**
612  * Help generator for choice (list of possible strings) validator
613  * List selection will be case insensitive.
614  * See CFG_VALIDATE_CHOICE() macro in cfg_schema.h
615  * @param entry pointer to schema entry
616  * @param out pointer to autobuffer for validator output
617  */
618 void
619 cfg_schema_help_choice(const struct cfg_schema_entry *entry, struct autobuf *out) {
620   cfg_help_choice(out, true, entry->validate_param[0].ptr, entry->validate_param[1].s, entry->validate_param[2].ptr);
621 }
622
623 /**
624  * Help generator for a fractional integer.
625  * See CFG_VALIDATE_INT*() macros in cfg_schema.h
626  * @param entry pointer to schema entry
627  * @param out pointer to autobuffer for validator output
628  */
629 void
630 cfg_schema_help_int(const struct cfg_schema_entry *entry, struct autobuf *out) {
631   cfg_help_int(out, entry->validate_param[0].i64, entry->validate_param[1].i64, entry->validate_param[2].i16[0],
632     entry->validate_param[2].i16[1]);
633 }
634
635 /**
636  * Help generator for network addresses and prefixes validator.
637  * See CFG_VALIDATE_NETADDR*() macros in cfg_schema.h
638  * @param entry pointer to schema entry
639  * @param out pointer to autobuffer for validator output
640  */
641 void
642 cfg_schema_help_netaddr(const struct cfg_schema_entry *entry, struct autobuf *out) {
643   cfg_help_netaddr(out, true, entry->validate_param[1].b, entry->validate_param[0].i8, 5);
644 }
645
646 /**
647  * Help generator for access control list validator.
648  * See CFG_VALIDATE_ACL*() macros in cfg_schema.h
649  * @param entry pointer to schema entry
650  * @param out pointer to autobuffer for validator output
651  */
652 void
653 cfg_schema_help_acl(const struct cfg_schema_entry *entry, struct autobuf *out) {
654   cfg_help_acl(out, true, entry->validate_param[1].b, entry->validate_param[0].i8, 5);
655 }
656
657 /**
658  * Help generator for bit-array validator.
659  * See CFG_VALIDATE_BITMAP256() macros in cfg_schema.h
660  * @param entry pointer to schema entry
661  * @param out pointer to autobuffer for validator output
662  */
663 void
664 cfg_schema_help_bitmap256(const struct cfg_schema_entry *entry __attribute__((unused)), struct autobuf *out) {
665   cfg_help_bitmap256(out, true);
666 }
667
668 /**
669  * Help generator for token validator.
670  * See CFG_VALIDATE_TOKEN() macro in cfg_schema.h
671  * @param entry pointer to schema entry
672  * @param out pointer to autobuffer for help output
673  */
674 void
675 cfg_schema_help_token(const struct cfg_schema_entry *entry, struct autobuf *out) {
676   cfg_help_token(
677     out, true, entry, entry->validate_param[0].ptr, entry->validate_param[1].s, entry->validate_param[2].ptr);
678 }
679
680 /**
681  * Binary converter for string pointers. This validator will
682  * allocate additional memory for the string.
683  * See CFG_MAP_STRING() and CFG_MAP_STRING_LEN() macro
684  * in cfg_schema.h
685  * @param s_entry pointer to configuration entry schema.
686  * @param value pointer to value of configuration entry.
687  * @param reference pointer to binary output buffer.
688  * @return 0 if conversion succeeded, -1 otherwise.
689  */
690 int
691 cfg_schema_tobin_strptr(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
692   if (s_entry->list) {
693     /* we don't support direct list conversion to binary */
694     return -1;
695   }
696   return cfg_tobin_strptr(reference, s_entry->bin_size, value);
697 }
698
699 /**
700  * Binary converter for string arrays.
701  * See CFG_MAP_STRING_ARRAY() macro in cfg_schema.h
702  * @param s_entry pointer to configuration entry schema.
703  * @param value pointer to value of configuration entry.
704  * @param reference pointer to binary output buffer.
705  * @return 0 if conversion succeeded, -1 otherwise.
706  */
707 int
708 cfg_schema_tobin_strarray(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
709   if (s_entry->list) {
710     /* we don't support direct list conversion to binary */
711     return -1;
712   }
713   return cfg_tobin_strarray(reference, s_entry->bin_size, value, s_entry->validate_param[0].s);
714 }
715
716 /**
717  * Binary converter for integers chosen as an index in a predefined
718  * string list.
719  * See CFG_MAP_CHOICE() macro in cfg_schema.h
720  * @param s_entry pointer to configuration entry schema.
721  * @param value pointer to value of configuration entry.
722  * @param reference pointer to binary output buffer.
723  * @return 0 if conversion succeeded, -1 otherwise.
724  */
725 int
726 cfg_schema_tobin_choice(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
727   if (s_entry->list) {
728     /* we don't support direct list conversion to binary */
729     return -1;
730   }
731   return cfg_tobin_choice(reference, s_entry->bin_size, value, s_entry->validate_param[0].ptr,
732     s_entry->validate_param[1].s, s_entry->validate_param[2].ptr);
733 }
734
735 /**
736  * Binary converter for integers.
737  * See CFG_VALIDATE_FRACTIONAL*() macro in cfg_schema.h
738  * @param s_entry pointer to configuration entry schema.
739  * @param value pointer to value of configuration entry.
740  * @param reference pointer to binary output buffer.
741  * @return 0 if conversion succeeded, -1 otherwise.
742  */
743 int
744 cfg_schema_tobin_int(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
745   if (s_entry->list) {
746     /* we don't support direct list conversion to binary */
747     return -1;
748   }
749   return cfg_tobin_int(
750     reference, s_entry->bin_size, value, s_entry->validate_param[2].u16[1], s_entry->validate_param[2].u16[0]);
751 }
752
753 /**
754  * Binary converter for netaddr objects.
755  * See CFG_MAP_NETADDR*() macros in cfg_schema.h
756  * @param s_entry pointer to configuration entry schema.
757  * @param value pointer to value of configuration entry.
758  * @param reference pointer to binary output buffer.
759  * @return 0 if conversion succeeded, -1 otherwise.
760  */
761 int
762 cfg_schema_tobin_netaddr(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
763   if (s_entry->list) {
764     /* we don't support direct list conversion to binary */
765     return -1;
766   }
767   return cfg_tobin_netaddr(reference, s_entry->bin_size, value);
768 }
769
770 /**
771  * Schema entry binary converter for ACL entries.
772  * See CFG_MAP_ACL_*() macros.
773  * @param s_entry pointer to schema entry.
774  * @param value pointer to value to configuration entry
775  * @param reference pointer to binary target
776  * @return -1 if an error happened, 0 otherwise
777  */
778 int
779 cfg_schema_tobin_acl(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
780   return cfg_tobin_acl(reference, s_entry->bin_size, value);
781 }
782
783 /**
784  * Schema entry binary converter for bitmap256 entries.
785  * See CFG_MAP_BITMAP256() macros.
786  * @param s_entry pointer to schema entry.
787  * @param value pointer to value to configuration entry
788  * @param reference pointer to binary target
789  * @return -1 if an error happened, 0 otherwise
790  */
791 int
792 cfg_schema_tobin_bitmap256(
793   const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
794   return cfg_tobin_bitmap256(reference, s_entry->bin_size, value);
795 }
796
797 /**
798  * Binary converter for booleans.
799  * See CFG_MAP_BOOL() macro in cfg_schema.h
800  * @param s_entry pointer to configuration entry schema.
801  * @param value pointer to value of configuration entry.
802  * @param reference pointer to binary output buffer.
803  * @return 0 if conversion succeeded, -1 otherwise.
804  */
805 int
806 cfg_schema_tobin_bool(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
807   if (s_entry->list) {
808     /* we don't support direct list conversion to binary */
809     return -1;
810   }
811   return cfg_tobin_bool(reference, s_entry->bin_size, value);
812 }
813
814 /**
815  * Binary converter for list of strings.
816  * See CFG_MAP_STRINGLIST() macro in cfg_schema.h
817  * @param s_entry pointer to configuration entry schema.
818  * @param value pointer to value of configuration entry.
819  * @param reference pointer to binary output buffer.
820  * @return 0 if conversion succeeded, -1 otherwise.
821  */
822 int
823 cfg_schema_tobin_stringlist(
824   const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
825   return cfg_tobin_stringlist(reference, s_entry->bin_size, value);
826 }
827
828 /**
829  * Binary converter for tokenized list of parameters.
830  * See CFG_MAP_TOKENS() macro in cfg_schema.h
831  * @param s_entry pointer to configuration entry schema.
832  * @param value pointer to value of configuration entry.
833  * @param reference pointer to binary output buffer.
834  * @return 0 if conversion succeeded, -1 otherwise.
835  */
836 int
837 cfg_schema_tobin_tokens(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
838   if (s_entry->list) {
839     /* we don't support direct list conversion to binary */
840     return -1;
841   }
842   return cfg_tobin_tokens(reference, strarray_get_first_c(value), s_entry->validate_param[0].ptr,
843     s_entry->validate_param[1].s, s_entry->validate_param[2].ptr);
844 }
845
846 /**
847  * Check if a section_type contains no named section
848  * @param type pointer to section_type
849  * @return true if section type contains no named section
850  */
851 static bool
852 _section_needs_default_named_one(struct cfg_section_type *type) {
853   struct cfg_named_section *named;
854
855   if (type == NULL || type->names.count == 0) {
856     /* no named sections there, so we need the default one */
857     return true;
858   }
859
860   if (type->names.count > 1) {
861     /* more than one section, that means at least one named one */
862     return false;
863   }
864
865   /* we have exactly one section inside */
866   named = avl_first_element(&type->names, named, node);
867
868   /* we need the default if the existing section has no name */
869   return !cfg_db_is_named_section(named);
870 }
871
872 /**
873  * Compare two sets of databases and trigger delta listeners according to connected
874  * schema.
875  * @param pre_change pre-change database
876  * @param post_change post-change database
877  * @param startup if true, also trigger unnamed sections which don't change, but are
878  *   of type CFG_SSMODE_UNNAMED (and not CFG_SSMODE_UNNAMED_OPTIONAL_STARTUP_TRIGGER).
879  * @return -1 if an error happened, 0 otherwise
880  */
881 static int
882 _handle_db_changes(struct cfg_db *pre_change, struct cfg_db *post_change, bool startup) {
883   struct cfg_section_type default_section_type[2];
884   struct cfg_named_section default_named_section[2];
885   struct cfg_schema_section *s_section;
886   struct cfg_section_type *pre_type, *post_type;
887   struct cfg_named_section *pre_named, *post_named, *named_it;
888   struct cfg_named_section *pre_defnamed, *post_defnamed;
889
890   if (pre_change->schema == NULL || pre_change->schema != post_change->schema) {
891     /* no valid schema found */
892     return -1;
893   }
894
895   /* initialize default named section mechanism */
896   memset(default_named_section, 0, sizeof(default_named_section));
897   memset(default_section_type, 0, sizeof(default_section_type));
898
899   avl_init(&default_named_section[0].entries, cfg_avlcmp_keys, false);
900   avl_init(&default_named_section[1].entries, cfg_avlcmp_keys, false);
901   default_named_section[0].section_type = &default_section_type[0];
902   default_named_section[1].section_type = &default_section_type[1];
903
904   default_section_type[0].db = pre_change;
905   default_section_type[1].db = post_change;
906
907   list_for_each_element(&pre_change->schema->handlers, s_section, _delta_node) {
908     /* get section types in both databases */
909     pre_type = cfg_db_find_sectiontype(pre_change, s_section->type);
910     post_type = cfg_db_find_sectiontype(post_change, s_section->type);
911
912     /* prepare for default named section */
913     pre_defnamed = NULL;
914     post_defnamed = NULL;
915
916     if (s_section->mode == CFG_SSMODE_NAMED_WITH_DEFAULT) {
917       /* check if we need a default section for pre_change db */
918       if (!startup && _section_needs_default_named_one(pre_type)) {
919         /* initialize dummy section type for pre-change db */
920         default_section_type[0].type = s_section->type;
921
922         /* initialize dummy named section for pre-change */
923         default_named_section[0].name = s_section->def_name;
924
925         /* remember decision */
926         pre_defnamed = &default_named_section[0];
927       }
928
929       /* check if we need a default section for post_change db */
930       if (_section_needs_default_named_one(post_type)) {
931         /* initialize dummy section type for post-change db */
932         default_section_type[1].type = s_section->type;
933
934         /* initialize dummy named section for post-change */
935         default_named_section[1].name = s_section->def_name;
936
937         /* remember decision */
938         post_defnamed = &default_named_section[1];
939       }
940     }
941
942     if (post_type) {
943       /* handle new named sections and changes */
944       pre_named = NULL;
945       CFG_FOR_ALL_SECTION_NAMES(post_type, post_named, named_it) {
946         _handle_named_section_change(
947           s_section, pre_change, post_change, post_named->name, startup, pre_defnamed, post_defnamed);
948       }
949     }
950     if (pre_type) {
951       /* handle removed named sections */
952       post_named = NULL;
953       CFG_FOR_ALL_SECTION_NAMES(pre_type, pre_named, named_it) {
954         if (post_type) {
955           post_named = cfg_db_get_named_section(post_type, pre_named->name);
956         }
957
958         if (!post_named) {
959           _handle_named_section_change(
960             s_section, pre_change, post_change, pre_named->name, startup, pre_defnamed, post_defnamed);
961         }
962       }
963     }
964     if (startup && s_section->mode == CFG_SSMODE_UNNAMED && pre_type == NULL && post_type == NULL) {
965       /* send change signal on startup for unnamed section */
966       _handle_named_section_change(s_section, pre_change, post_change, NULL, true, pre_defnamed, post_defnamed);
967     }
968     if ((pre_defnamed != NULL) != (post_defnamed != NULL)) {
969       /* status of default named section changed */
970       _handle_named_section_change(
971         s_section, pre_change, post_change, s_section->def_name, true, pre_defnamed, post_defnamed);
972     }
973   }
974   return 0;
975 }
976
977 /**
978  * Validates on configuration entry.
979  * @param db pointer to database
980  * @param section pointer to database section type
981  * @param named pointer to named section
982  * @param entry pointer to configuration entry
983  * @param section_name name of section including type (for debug output)
984  * @param cleanup true if bad _entries should be removed
985  * @param out error output buffer
986  * @return true if an error happened, false otherwise
987  */
988 static bool
989 _validate_cfg_entry(struct cfg_db *db, struct cfg_section_type *section, struct cfg_named_section *named,
990   struct cfg_entry *entry, const char *section_name, bool cleanup, struct autobuf *out) {
991   struct cfg_schema_entry *schema_entry, *s_entry_it;
992   struct cfg_schema_entry_key key;
993   bool warning, do_remove;
994   char *ptr1;
995
996   warning = false;
997   ptr1 = NULL;
998
999   key.type = section->type;
1000   key.entry = entry->name;
1001
1002   avl_for_each_elements_with_key(&db->schema->entries, schema_entry, _node, s_entry_it, &key) {
1003     if (schema_entry->cb_validate == NULL) {
1004       continue;
1005     }
1006
1007     /* now validate syntax */
1008     ptr1 = entry->val.value;
1009
1010     do_remove = false;
1011     while (!strarray_is_empty(&entry->val) && ptr1 < entry->val.value + entry->val.length) {
1012       if (!do_remove && schema_entry->cb_validate(schema_entry, section_name, ptr1, out) != 0) {
1013         /* warning is generated by the validate callback itself */
1014         warning = true;
1015       }
1016
1017       if ((warning || do_remove) && cleanup) {
1018         /* illegal entry found, remove it */
1019         strarray_remove_ext(&entry->val, ptr1, false);
1020       }
1021       else {
1022         ptr1 += strlen(ptr1) + 1;
1023       }
1024
1025       if (!schema_entry->list) {
1026         do_remove = true;
1027       }
1028     }
1029
1030     if (strarray_is_empty(&entry->val)) {
1031       /* remove entry */
1032       cfg_db_remove_entry(db, section->type, named->name, entry->name);
1033     }
1034   }
1035   return warning;
1036 }
1037
1038 /**
1039  * Handle changes in a single named section
1040  * @param s_section schema entry for section
1041  * @param pre_change pointer to database before changes
1042  * @param post_change pointer to database after changes
1043  * @param section_name name of section, might be NULL for unnamed one
1044  * @param startup true comparison against empty database at startup
1045  * @param pre_defnamed named section with default name before change
1046  * @param post_defnamed named section with default name after change
1047  */
1048 static void
1049 _handle_named_section_change(struct cfg_schema_section *s_section, struct cfg_db *pre_change,
1050   struct cfg_db *post_change, const char *section_name, bool startup, struct cfg_named_section *pre_defnamed,
1051   struct cfg_named_section *post_defnamed) {
1052   struct cfg_schema_entry *entry;
1053   bool changed;
1054   size_t i;
1055
1056   if ((s_section->mode == CFG_SSMODE_NAMED || s_section->mode == CFG_SSMODE_NAMED_MANDATORY ||
1057         s_section->mode == CFG_SSMODE_NAMED_WITH_DEFAULT) &&
1058       section_name == NULL) {
1059     /*
1060      * ignore unnamed data entry for named sections, they are only
1061      * used for delivering defaults
1062      */
1063     return;
1064   }
1065
1066   s_section->pre = cfg_db_find_namedsection(pre_change, s_section->type, section_name);
1067   s_section->post = cfg_db_find_namedsection(post_change, s_section->type, section_name);
1068
1069   if (s_section->mode == CFG_SSMODE_NAMED_WITH_DEFAULT && strcasecmp(s_section->def_name, section_name) == 0) {
1070     /* use the default named sections if necessary */
1071     if (s_section->pre == NULL && !startup) {
1072       s_section->pre = pre_defnamed;
1073     }
1074     if (s_section->post == NULL) {
1075       s_section->post = post_defnamed;
1076     }
1077   }
1078
1079   changed = false;
1080
1081   if ((s_section->mode == CFG_SSMODE_NAMED || s_section->mode == CFG_SSMODE_NAMED_MANDATORY ||
1082         s_section->mode == CFG_SSMODE_NAMED_WITH_DEFAULT) &&
1083       (s_section->pre == NULL) != (s_section->post == NULL)) {
1084     /* section vanished or appeared */
1085     changed = true;
1086   }
1087
1088   for (i = 0; i < s_section->entry_count; i++) {
1089     entry = &s_section->entries[i];
1090
1091     /* read values */
1092     entry->pre = cfg_db_get_entry_value(pre_change, s_section->type, section_name, entry->key.entry);
1093     entry->post = cfg_db_get_entry_value(post_change, s_section->type, section_name, entry->key.entry);
1094
1095     entry->delta_changed = strarray_cmp_c(entry->pre, entry->post);
1096     changed |= entry->delta_changed;
1097   }
1098
1099   if (changed || startup) {
1100     s_section->section_name = section_name;
1101     s_section->cb_delta_handler();
1102   }
1103 }