Allow default name for sections
[oonf.git] / src-api / config / cfg_schema.c
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 #include <assert.h>
43 #include <limits.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47
48 #include "common/avl.h"
49 #include "common/avl_comp.h"
50 #include "common/netaddr.h"
51 #include "common/netaddr_acl.h"
52 #include "common/string.h"
53 #include "config/cfg.h"
54 #include "config/cfg_db.h"
55 #include "config/cfg_schema.h"
56
57 static bool _validate_cfg_entry(
58     struct cfg_db *db, struct cfg_section_type *section,
59     struct cfg_named_section *named, struct cfg_entry *entry,
60     const char *section_name, bool cleanup, struct autobuf *out);
61 static bool _check_missing_entries(struct cfg_schema_section *schema_section,
62     struct cfg_db *db, struct cfg_named_section *named,
63     const char *section_name, struct autobuf *out);
64 static void _handle_named_section_change(struct cfg_schema_section *s_section,
65     struct cfg_db *pre_change, struct cfg_db *post_change,
66     const char *name, bool startup,
67     struct cfg_named_section *pre_defnamed,
68     struct cfg_named_section *post_defnamed);
69 static int _handle_db_changes(struct cfg_db *pre_change,
70     struct cfg_db *post_change, bool startup);
71 static int _get_known_prefix(struct netaddr *dst, const char *name);
72
73 const char *CFGLIST_BOOL_TRUE[] = { "true", "1", "on", "yes" };
74 const char *CFGLIST_BOOL[] = { "true", "1", "on", "yes", "false", "0", "off", "no" };
75 const char *CFG_SCHEMA_SECTIONMODE[CFG_SSMODE_MAX] = {
76     "unnamed",
77     "unnamed, optional",
78     "named",
79     "named, mandatory"
80 };
81
82 /* List of predefined address prefixes */
83 const struct {
84   const char *name;
85   const struct netaddr *prefix;
86 } _known_prefixes[] = {
87   { NETADDR_STR_ANY4, &NETADDR_IPV4_ANY },
88   { NETADDR_STR_ANY6, &NETADDR_IPV6_ANY },
89   { NETADDR_STR_LINKLOCAL4, &NETADDR_IPV4_LINKLOCAL },
90   { NETADDR_STR_LINKLOCAL6, &NETADDR_IPV6_LINKLOCAL },
91   { NETADDR_STR_ULA, &NETADDR_IPV6_ULA },
92 };
93
94 /**
95  * Initialize a schema
96  * @param schema pointer to uninitialized schema
97  */
98 void
99 cfg_schema_add(struct cfg_schema *schema) {
100   avl_init(&schema->sections, cfg_avlcmp_keys, true);
101   avl_init(&schema->entries, cfg_avlcmp_schemaentries, true);
102   avl_init(&schema->handlers, avl_comp_uint32, true);
103 }
104
105 /**
106  * Add a section to a schema
107  * @param schema pointer to configuration schema
108  * @param section pointer to section
109  */
110 void
111 cfg_schema_add_section(struct cfg_schema *schema,
112     struct cfg_schema_section *section) {
113 //  struct cfg_schema_entry *entry, *entry_it;
114   size_t i;
115
116   /* hook section into global section tree */
117   section->_section_node.key = section->type;
118   avl_insert(&schema->sections, &section->_section_node);
119
120   if (section->cb_delta_handler) {
121     /* hook callback into global callback handler tree */
122     section->_delta_node.key = &section->delta_priority;
123     avl_insert(&schema->handlers, &section->_delta_node);
124   }
125
126   for (i=0; i<section->entry_count; i++) {
127     section->entries[i]._parent = section;
128     section->entries[i].key.type = section->type;
129     section->entries[i]._node.key = &section->entries[i].key;
130 #if 0
131     /* make sure all defaults are the same */
132     avl_for_each_elements_with_key(&schema->entries, entry_it, _node, entry,
133         &section->entries[i].key) {
134       if (section->entries[i].def.value == NULL) {
135         /* if we have no default, copy the one from the first existing entry */
136         memcpy(&section->entries[i].def, &entry->def, sizeof(entry->def));
137         break;
138       }
139       else {
140         /* if we have one, overwrite all existing entries */
141         memcpy(&entry->def, &section->entries[i].def, sizeof(entry->def));
142
143         // TODO: maybe output some logging that we overwrite the default?
144       }
145     }
146 #endif
147     avl_insert(&schema->entries, &section->entries[i]._node);
148   }
149 }
150
151 /**
152  * Removes a section from a schema
153  * @param schema pointer to configuration schema
154  * @param section pointer to section
155  */
156 void
157 cfg_schema_remove_section(struct cfg_schema *schema, struct cfg_schema_section *section) {
158   size_t i;
159
160   if (section->_section_node.key) {
161     avl_remove(&schema->sections, &section->_section_node);
162     section->_section_node.key = NULL;
163
164     for (i=0; i<section->entry_count; i++) {
165       avl_remove(&schema->entries, &section->entries[i]._node);
166       section->entries[i]._node.key = NULL;
167     }
168   }
169   if (section->_delta_node.key) {
170     avl_remove(&schema->handlers, &section->_delta_node);
171     section->_delta_node.key = NULL;
172   }
173 }
174
175 /**
176  * Validates a database with a schema
177  * @param db pointer to configuration database
178  * @param cleanup if true, bad values will be removed from the database
179  * @param ignore_unknown_sections true if the validation should skip sections
180  *   in the database that have no schema.
181  * @param out autobuffer for validation output
182  * @return 0 if validation found no problems, -1 otherwise
183  */
184 int
185 cfg_schema_validate(struct cfg_db *db,
186     bool cleanup, bool ignore_unknown_sections,
187     struct autobuf *out) {
188   char section_name[256];
189   struct cfg_section_type *section, *section_it;
190   struct cfg_named_section *named, *named_it;
191   struct cfg_entry *entry, *entry_it;
192
193   struct cfg_schema_section *schema_section;
194   struct cfg_schema_section *schema_section_first, *schema_section_last;
195
196   bool error = false;
197   bool warning = false;
198   bool hasName = false;
199
200   if (db->schema == NULL) {
201     return -1;
202   }
203
204   CFG_FOR_ALL_SECTION_TYPES(db, section, section_it) {
205     /* check for missing schema sections */
206     schema_section_first = avl_find_element(&db->schema->sections, section->type,
207         schema_section_first, _section_node);
208
209     if (schema_section_first == NULL) {
210       if (ignore_unknown_sections) {
211         continue;
212       }
213
214       cfg_append_printable_line(out,
215           "Cannot find schema for section type '%s'", section->type);
216
217       if (cleanup) {
218         cfg_db_remove_sectiontype(db, section->type);
219       }
220
221       error |= true;
222       continue;
223     }
224
225     schema_section_last = avl_find_le_element(&db->schema->sections, section->type,
226         schema_section_last, _section_node);
227
228     /* iterate over all schema for a certain section type */
229     avl_for_element_range(schema_section_first, schema_section_last, schema_section, _section_node) {
230       /* check data of named sections in db */
231       CFG_FOR_ALL_SECTION_NAMES(section, named, named_it) {
232         warning = false;
233         hasName = cfg_db_is_named_section(named);
234
235         if (!(schema_section->mode == CFG_SSMODE_NAMED
236             || schema_section->mode == CFG_SSMODE_NAMED_MANDATORY) && hasName) {
237           cfg_append_printable_line(out, "The section type '%s'"
238               " has to be used without a name"
239               " ('%s' was given as a name)", section->type, named->name);
240
241           warning = true;
242         }
243
244         if (hasName && !cfg_is_allowed_key(named->name, true)) {
245           cfg_append_printable_line(out, "The section name '%s' for"
246               " type '%s' contains illegal characters",
247               named->name, section->type);
248           warning = true;
249         }
250
251         /* test abort condition */
252         if (warning && cleanup) {
253           /* remove bad named section */
254           cfg_db_remove_namedsection(db, section->type, named->name);
255         }
256
257         error |= warning;
258
259         if (warning) {
260           continue;
261         }
262
263         /* initialize section_name field for validate */
264         snprintf(section_name, sizeof(section_name), "'%s%s%s'",
265             section->type, hasName ? "=" : "", hasName ? named->name : "");
266
267         /* check for bad values */
268         CFG_FOR_ALL_ENTRIES(named, entry, entry_it) {
269           warning = _validate_cfg_entry(
270               db, section, named, entry, section_name,
271               cleanup, out);
272           error |= warning;
273         }
274
275         /* check for missing values */
276         warning = _check_missing_entries(schema_section, db, named, section_name, out);
277         error |= warning;
278
279         /* check custom section validation if everything was fine */
280         if (!error && schema_section->cb_validate != NULL) {
281           if (schema_section->cb_validate(section_name, named, out)) {
282             error = true;
283           }
284         }
285       }
286     }
287     if (cleanup && avl_is_empty(&section->names)) {
288       /* if section type is empty, remove it too */
289       cfg_db_remove_sectiontype(db, section->type);
290     }
291   }
292
293   /* search for missing mandatory sections */
294   avl_for_each_element(&db->schema->sections, schema_section, _section_node) {
295     if (schema_section->mode != CFG_SSMODE_NAMED_MANDATORY) {
296       continue;
297     }
298
299     section = cfg_db_find_sectiontype(db, schema_section->type);
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'",
309           schema_section->type);
310     }
311     error |= warning;
312   }
313   return error ? -1 : 0;
314 }
315
316 /**
317  * Convert the entries of a db section into binary representation by
318  * using the mappings defined in a schema section. The function assumes
319  * that the section was already validated.
320  * @param target pointer to target binary buffer
321  * @param named pointer to named section, might be NULL to refer to
322  *   default settings
323  * @param entries pointer to array of schema entries
324  * @param count number of schema entries
325  * @return 0 if conversion was successful, -(1+index) of the
326  *   failed conversion array entry if an error happened.
327  *   An error might result in a partial initialized target buffer.
328  */
329 int
330 cfg_schema_tobin(void *target, struct cfg_named_section *named,
331     const struct cfg_schema_entry *entries, size_t count) {
332   char *ptr;
333   size_t i;
334   const struct const_strarray *value;
335
336   ptr = (char *)target;
337
338   for (i=0; i<count; i++) {
339     if (entries[i].cb_to_binary == NULL) {
340       continue;
341     }
342
343     /* cleanup pointer */
344     if (named) {
345       value = cfg_db_get_entry_value(
346           named->section_type->db,
347           named->section_type->type,
348           named->name,
349           entries[i].key.entry);
350     }
351     else {
352       value = &entries[i].def;
353     }
354
355     if (entries[i].cb_to_binary(&entries[i], value, ptr + entries[i].bin_offset)) {
356       /* error in conversion */
357       return -1-i;
358     }
359   }
360   return 0;
361 }
362
363 /**
364  * Compare two databases with the same schema and call their change listeners
365  * @param pre_change database before change
366  * @param post_change database after change
367  * @return -1 if databases have different schema, 0 otherwise
368  */
369 int
370 cfg_schema_handle_db_changes(struct cfg_db *pre_change, struct cfg_db *post_change) {
371   return _handle_db_changes(pre_change, post_change, false);
372 }
373
374 /**
375  * Handle trigger of delta callbacks on program startup. Call every trigger
376  * except for CFG_SSMODE_UNNAMED_OPTIONAL_STARTUP_TRIGGER mode.
377  * @param post_db pointer to new configuration database
378  * @return -1 if an error happened, 0 otherwise
379  */
380 int
381 cfg_schema_handle_db_startup_changes(struct cfg_db *post_db) {
382   struct cfg_db *pre_db;
383   int result;
384
385   pre_db = cfg_db_add();
386   if (pre_db == NULL) {
387     return -1;
388   }
389   cfg_db_link_schema(pre_db, post_db->schema);
390
391   result = _handle_db_changes(pre_db, post_db, true);
392   cfg_db_remove(pre_db);
393   return result;
394 }
395
396 /**
397  * AVL comparator for two cfg_schema_entry_key entities.
398  * Will compare key.type first, if these are the same it will
399  * compare key.entry. NULL is valid as an entry and is smaller
400  * than all non-NULL entries. NULL is NOT valid as a type.
401  *
402  * @param p1 pointer to first key
403  * @param p2 pointer to second key
404  * @return <0 if p1 comes first, 0 if both are the same, >0 otherwise
405  */
406 int
407 cfg_avlcmp_schemaentries(const void *p1, const void *p2) {
408   const struct cfg_schema_entry_key *key1, *key2;
409   int result;
410
411   key1 = p1;
412   key2 = p2;
413
414   result = cfg_avlcmp_keys(key1->type, key2->type);
415   if (result != 0) {
416     return result;
417   }
418
419   if (key1->entry == NULL) {
420     return key2->entry == NULL ? 0 : 1;
421   }
422   if (key2->entry == NULL) {
423     return -1;
424   }
425
426   return cfg_avlcmp_keys(key1->entry, key2->entry);
427 }
428
429 /**
430  * Schema entry validator for string maximum length.
431  * See CFG_VALIDATE_STRING_LEN macro in cfg_schema.h
432  * @param entry pointer to schema entry
433  * @param section_name name of section type and name
434  * @param value value of schema entry, NULL for help text generation
435  * @param out pointer to autobuffer for validator output
436  * @return 0 if validation found no problems, -1 otherwise
437  */
438 int
439 cfg_schema_validate_strlen(const struct cfg_schema_entry *entry,
440     const char *section_name, const char *value, struct autobuf *out) {
441   if (strlen(value) > entry->validate_param[0].s) {
442     cfg_append_printable_line(out, "Value '%s' for entry '%s'"
443         " in section %s is longer than %"PRINTF_SIZE_T_SPECIFIER" characters",
444         value, entry->key.entry, section_name, entry->validate_param[0].s);
445     return -1;
446   }
447   return 0;
448 }
449
450 /**
451  * Schema entry validator for strings printable characters
452  * and a maximum length.
453  * See CFG_VALIDATE_PRINTABLE() and CFG_VALIDATE_PRINTABLE_LEN()
454  * macro in cfg_schema.h
455  * @param entry pointer to schema entry
456  * @param section_name name of section type and name
457  * @param value value of schema entry
458  * @param out pointer to autobuffer for validator output
459  * @return 0 if validation found no problems, -1 otherwise
460  */
461 int
462 cfg_schema_validate_printable(const struct cfg_schema_entry *entry,
463     const char *section_name, const char *value, struct autobuf *out) {
464   if (cfg_schema_validate_strlen(entry, section_name, value, out)) {
465     return 1;
466   }
467   if (!str_is_printable(value)) {
468     /* not a printable ascii character */
469     cfg_append_printable_line(out, "Value '%s' for entry '%s'"
470         " in section %s has has non-printable characters",
471         value, entry->key.entry, section_name);
472     return 1;
473
474   }
475   return 0;
476 }
477
478 /**
479  * Schema entry validator for choice (list of possible strings)
480  * List selection will be case insensitive.
481  * See CFG_VALIDATE_CHOICE() macro in cfg_schema.h
482  * @param entry pointer to schema entry
483  * @param section_name name of section type and name
484  * @param value value of schema entry
485  * @param out pointer to autobuffer for validator output
486  * @return 0 if validation found no problems, -1 otherwise
487  */
488 int
489 cfg_schema_validate_choice(const struct cfg_schema_entry *entry,
490     const char *section_name, const char *value, struct autobuf *out) {
491   const char **list = entry->validate_param[0].ptr;
492   int i;
493
494   i = cfg_get_choice_index(value, list, entry->validate_param[1].s);
495   if (i >= 0) {
496     return 0;
497   }
498
499   cfg_append_printable_line(out, "Unknown value '%s'"
500       " for entry '%s' in section %s",
501       value, entry->key.entry, section_name);
502   return -1;
503 }
504
505 /**
506  * Schema entry validator for integers.
507  * See CFG_VALIDATE_INT() and CFG_VALIDATE_INT_MINMAX() macro in cfg_schema.h
508  * @param entry pointer to schema entry
509  * @param section_name name of section type and name
510  * @param value value of schema entry
511  * @param out pointer to autobuffer for validator output
512  * @return 0 if validation found no problems, -1 otherwise
513  */
514 int
515 cfg_schema_validate_int(const struct cfg_schema_entry *entry,
516     const char *section_name, const char *value, struct autobuf *out) {
517   int32_t i;
518   char *endptr = NULL;
519
520   i = strtol(value, &endptr, 10);
521   if (endptr == NULL || *endptr != 0) {
522     cfg_append_printable_line(out, "Value '%s' for entry '%s'"
523         " in section %s is not an integer",
524         value, entry->key.entry, section_name);
525     return 1;
526   }
527   if (i < entry->validate_param[0].i32[0] || i > entry->validate_param[0].i32[1]) {
528     cfg_append_printable_line(out, "Value '%s' for entry '%s' in section %s is "
529         "not between %d and %d",
530         value, entry->key.entry, section_name,
531         entry->validate_param[0].i32[0], entry->validate_param[0].i32[1]);
532     return 1;
533   }
534   return 0;
535 }
536
537 /**
538  * Schema entry validator for fractional integers.
539  * See CFG_VALIDATE_FRACTIONAL() and CFG_VALIDATE_FRACTIONAL_MINMAX() macro in cfg_schema.h
540  * @param entry pointer to schema entry
541  * @param section_name name of section type and name
542  * @param value value of schema entry
543  * @param out pointer to autobuffer for validator output
544  * @return 0 if validation found no problems, -1 otherwise
545  */
546 int
547 cfg_schema_validate_fractional(const struct cfg_schema_entry *entry,
548     const char *section_name, const char *value, struct autobuf *out) {
549   int64_t i;
550
551   if (cfg_fraction_from_string(&i, value, entry->validate_param[1].i32[0])) {
552     cfg_append_printable_line(out, "Value '%s' for entry '%s'"
553         " in section %s is not a fractional integer"
554         " with a maximum of %d fractional digits",
555         value, entry->key.entry, section_name, entry->validate_param[1].i32[0]);
556     return 1;
557   }
558   if (i < entry->validate_param[0].i32[0] || i > entry->validate_param[0].i32[1]) {
559     cfg_append_printable_line(out, "Value '%s' for entry '%s' in section %s is "
560         "not between %d and %d",
561         value, entry->key.entry, section_name,
562         entry->validate_param[0].i32[0], entry->validate_param[0].i32[1]);
563     return 1;
564   }
565   return 0;
566 }
567
568 /**
569  * Schema entry validator for network addresses and prefixes.
570  * See CFG_VALIDATE_NETADDR_*() macros in cfg_schema.h
571  * @param entry pointer to schema entry
572  * @param section_name name of section type and name
573  * @param value value of schema entry
574  * @param out pointer to autobuffer for validator output
575  * @return 0 if validation found no problems, -1 otherwise
576  */
577 int
578 cfg_schema_validate_netaddr(const struct cfg_schema_entry *entry,
579     const char *section_name, const char *value, struct autobuf *out) {
580   struct netaddr addr;
581   uint8_t max_prefix;
582   int i;
583
584   if (_get_known_prefix(&addr, value)) {
585     if (netaddr_from_string(&addr, value)) {
586       cfg_append_printable_line(out, "Value '%s' for entry '%s'"
587           " in section %s is no valid network address",
588           value, entry->key.entry, section_name);
589       return -1;
590     }
591   }
592
593   max_prefix = netaddr_get_maxprefix(&addr);
594
595   /* check prefix length */
596   if (netaddr_get_prefix_length(&addr) > max_prefix) {
597     cfg_append_printable_line(out, "Value '%s' for entry '%s'"
598         " in section %s has an illegal prefix length",
599         value, entry->key.entry, section_name);
600     return -1;
601   }
602   if (!entry->validate_param[1].b && netaddr_get_prefix_length(&addr) != max_prefix) {
603     cfg_append_printable_line(out, "Value '%s' for entry '%s'"
604         " in section %s must be a single address, not a prefix",
605         value, entry->key.entry, section_name);
606     return -1;
607   }
608
609   for (i=0; i<5; i++) {
610     int8_t type;
611
612     type = entry->validate_param[0].i8[i];
613     if (type == netaddr_get_address_family(&addr)) {
614       return 0;
615     }
616   }
617
618   /* at least one condition was set, but no one matched */
619   cfg_append_printable_line(out, "Value '%s' for entry '%s'"
620       " in section '%s' is wrong address type",
621       value, entry->key.entry, section_name);
622   return -1;
623 }
624
625 /**
626  * Schema entry validator for access control lists.
627  * See CFG_VALIDATE_ACL_*() macros.
628  * @param entry pointer to schema entry
629  * @param section_name name of section type and name
630  * @param value value of schema entry
631  * @param out pointer to autobuffer for validator output
632  * @return 0 if validation found no problems, -1 otherwise
633  */
634 int
635 cfg_schema_validate_acl(const struct cfg_schema_entry *entry,
636     const char *section_name, const char *value, struct autobuf *out) {
637   struct netaddr_acl dummy;
638
639   if (value == NULL) {
640     cfg_schema_validate_netaddr(entry, section_name, value, out);
641     cfg_append_printable_line(out, "    Additional keywords are %s, %s, %s and %s",
642         ACL_FIRST_ACCEPT, ACL_FIRST_REJECT, ACL_DEFAULT_ACCEPT, ACL_DEFAULT_REJECT);
643     return 0;
644   }
645
646   if (netaddr_acl_handle_keywords(&dummy, value) == 0) {
647     return 0;
648   }
649
650   if (*value == '+' || *value == '-') {
651     return cfg_schema_validate_netaddr(entry, section_name, value+1, out);
652   }
653   return cfg_schema_validate_netaddr(entry, section_name, value, out);
654 }
655
656 /**
657  * Help generator for string maximum length validator.
658  * See CFG_VALIDATE_STRING_LEN macro in cfg_schema.h
659  * @param entry pointer to schema entry
660  * @param out pointer to autobuffer for help output
661  */
662 void
663 cfg_schema_help_strlen(
664     const struct cfg_schema_entry *entry, struct autobuf *out) {
665   cfg_append_printable_line(out, "    Parameter must have a maximum"
666       " length of %"PRINTF_SIZE_T_SPECIFIER" characters",
667       entry->validate_param[0].s);
668 }
669
670 /**
671  * Help generator for strings printable characters
672  * and a maximum length validator.
673  * See CFG_VALIDATE_PRINTABLE() and CFG_VALIDATE_PRINTABLE_LEN()
674  * macro in cfg_schema.h
675  * @param entry pointer to schema entry
676  * @param out pointer to autobuffer for validator output
677  */
678 void
679 cfg_schema_help_printable(
680     const struct cfg_schema_entry *entry, struct autobuf *out) {
681   cfg_schema_help_printable(entry, out);
682   cfg_append_printable_line(out, "    Parameter must only contain printable characters.");
683 }
684
685 /**
686  * Help generator for choice (list of possible strings) validator
687  * List selection will be case insensitive.
688  * See CFG_VALIDATE_CHOICE() macro in cfg_schema.h
689  * @param entry pointer to schema entry
690  * @param out pointer to autobuffer for validator output
691  */
692 void
693 cfg_schema_help_choice(
694     const struct cfg_schema_entry *entry, struct autobuf *out) {
695   const char **list = entry->validate_param[0].ptr;
696   size_t i;
697
698   cfg_append_printable_line(out, "    Parameter must be on of the following list:");
699
700   abuf_puts(out, "    ");
701   for (i=0; i < entry->validate_param[1].s; i++) {
702     abuf_appendf(out, "%s'%s'",
703         i==0 ? "" : ", ", list[i]);
704   }
705   abuf_puts(out, "\n");
706 }
707
708 /**
709  * Help generator for integer validator.
710  * See CFG_VALIDATE_INT() and CFG_VALIDATE_INT_MINMAX() macro in cfg_schema.h
711  * @param entry pointer to schema entry
712  * @param out pointer to autobuffer for validator output
713  */
714 void
715 cfg_schema_help_int(
716     const struct cfg_schema_entry *entry, struct autobuf *out) {
717   if (entry->validate_param[0].i32[0] > INT32_MIN) {
718     if (entry->validate_param[0].i32[1] < INT32_MAX) {
719       cfg_append_printable_line(out, "    Parameter must be an integer between %d and %d",
720           entry->validate_param[0].i32[0], entry->validate_param[0].i32[1]);
721     }
722     else {
723       cfg_append_printable_line(out, "    Parameter must be an integer larger or equal than %d",
724           entry->validate_param[0].i32[0]);
725     }
726   }
727   else {
728     if (entry->validate_param[0].i32[1] < INT32_MAX) {
729       cfg_append_printable_line(out, "    Parameter must be an integer less or equal than %d",
730           entry->validate_param[0].i32[1]);
731     }
732     else {
733       cfg_append_printable_line(out, "    Parameter must be a 32 bit signed integer");
734     }
735   }
736 }
737
738 /**
739  * Help generator for integer validator.
740  * See CFG_VALIDATE_INT() and CFG_VALIDATE_INT_MINMAX() macro in cfg_schema.h
741  * @param entry pointer to schema entry
742  * @param out pointer to autobuffer for validator output
743  */
744 void
745 cfg_schema_help_fractional(
746     const struct cfg_schema_entry *entry, struct autobuf *out) {
747   struct fraction_str buf1, buf2;
748
749   if (entry->validate_param[0].i32[0] > INT32_MIN) {
750     if (entry->validate_param[0].i32[1] < INT32_MAX) {
751       cfg_append_printable_line(out, "    Parameter must be an number between %s and %s",
752           cfg_fraction_to_string(&buf1,
753               entry->validate_param[0].i32[0], entry->validate_param[1].i32[0]),
754           cfg_fraction_to_string(&buf2,
755               entry->validate_param[0].i32[1], entry->validate_param[1].i32[0]));
756     }
757     else {
758       cfg_append_printable_line(out, "    Parameter must be an number larger or equal than %s",
759           cfg_fraction_to_string(&buf1,
760               entry->validate_param[0].i32[0], entry->validate_param[1].i32[0]));
761     }
762   }
763   else {
764     if (entry->validate_param[0].i32[1] < INT32_MAX) {
765       cfg_append_printable_line(out, "    Parameter must be an number less or equal than %s",
766           cfg_fraction_to_string(&buf2,
767               entry->validate_param[0].i32[1], entry->validate_param[1].i32[0]));
768     }
769     else {
770       cfg_append_printable_line(out, "    Parameter must be a signed integer");
771     }
772   }
773 }
774
775 /**
776  * Help generator for network addresses and prefixes validator.
777  * See CFG_VALIDATE_NETADDR_*() macros in cfg_schema.h
778  * @param entry pointer to schema entry
779  * @param out pointer to autobuffer for validator output
780  */
781 void
782 cfg_schema_help_netaddr(
783     const struct cfg_schema_entry *entry, struct autobuf *out) {
784   int8_t type;
785   bool first;
786   int i;
787
788   abuf_puts(out, "    Parameter must be an address of the following type: ");
789
790   first = true;
791   for (i=0; i<5; i++) {
792     type = entry->validate_param[0].i8[i];
793
794     if (first) {
795       first = false;
796     }
797     else {
798       abuf_puts(out, ", ");
799     }
800
801     switch (type) {
802       case AF_INET:
803         abuf_puts(out, "IPv4");
804         break;
805       case AF_INET6:
806         abuf_puts(out, "IPv6");
807         break;
808       case AF_MAC48:
809         abuf_puts(out, "MAC48");
810         break;
811       case AF_EUI64:
812         abuf_puts(out, "EUI64");
813         break;
814       default:
815         abuf_puts(out, "Unspec (-)");
816         break;
817     }
818   }
819
820   if (entry->validate_param[1].b) {
821     abuf_puts(out, " (with an optional prefix)");
822   }
823   abuf_puts(out, "\n");
824 }
825
826 /**
827  * Binary converter for string pointers. This validator will
828  * allocate additional memory for the string.
829  * See CFG_MAP_STRING() and CFG_MAP_STRING_LEN() macro
830  * 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_strptr(const struct cfg_schema_entry *s_entry __attribute__((unused)),
838     const struct const_strarray *value, void *reference) {
839   char **ptr;
840
841   ptr = (char **)reference;
842   if (*ptr) {
843     free(*ptr);
844   }
845
846   *ptr = strdup(strarray_get_first_c(value));
847   return *ptr == NULL ? -1 : 0;
848 }
849
850 /**
851  * Binary converter for string arrays.
852  * See CFG_MAP_STRING_ARRAY() macro in cfg_schema.h
853  * @param s_entry pointer to configuration entry schema.
854  * @param value pointer to value of configuration entry.
855  * @param reference pointer to binary output buffer.
856  * @return 0 if conversion succeeded, -1 otherwise.
857  */
858 int
859 cfg_schema_tobin_strarray(const struct cfg_schema_entry *s_entry,
860     const struct const_strarray *value, void *reference) {
861   char *ptr;
862
863   ptr = (char *)reference;
864
865   strscpy(ptr, strarray_get_first_c(value), s_entry->validate_param[0].s);
866   return 0;
867 }
868
869 /**
870  * Binary converter for integers chosen as an index in a predefined
871  * string list.
872  * See CFG_MAP_CHOICE() macro in cfg_schema.h
873  * @param s_entry pointer to configuration entry schema.
874  * @param value pointer to value of configuration entry.
875  * @param reference pointer to binary output buffer.
876  * @return 0 if conversion succeeded, -1 otherwise.
877  */
878 int
879 cfg_schema_tobin_choice(const struct cfg_schema_entry *s_entry,
880     const struct const_strarray *value, void *reference) {
881   int *ptr;
882
883   ptr = (int *)reference;
884
885   *ptr = cfg_get_choice_index(strarray_get_first_c(value),
886       s_entry->validate_param[0].ptr, s_entry->validate_param[1].s);
887   return 0;
888 }
889
890 /**
891  * Binary converter for integers.
892  * See CFG_MAP_INT() macro in cfg_schema.h
893  * @param s_entry pointer to configuration entry schema.
894  * @param value pointer to value of configuration entry.
895  * @param reference pointer to binary output buffer.
896  * @return 0 if conversion succeeded, -1 otherwise.
897  */
898 int
899 cfg_schema_tobin_int(const struct cfg_schema_entry *s_entry __attribute__((unused)),
900     const struct const_strarray *value, void *reference) {
901   int *ptr;
902
903   ptr = (int *)reference;
904
905   *ptr = strtol(strarray_get_first_c(value), NULL, 10);
906   return 0;
907 }
908
909 /**
910  * Binary converter for integers.
911  * See CFG_MAP_INT() macro in cfg_schema.h
912  * @param s_entry pointer to configuration entry schema.
913  * @param value pointer to value of configuration entry.
914  * @param reference pointer to binary output buffer.
915  * @return 0 if conversion succeeded, -1 otherwise.
916  */
917 int
918 cfg_schema_tobin_fractional(const struct cfg_schema_entry *s_entry,
919     const struct const_strarray *value, void *reference) {
920   int *ptr;
921   int64_t i, result;
922
923   ptr = (int *)reference;
924
925   result = cfg_fraction_from_string(&i, strarray_get_first_c(value),
926       s_entry->validate_param[1].i32[0]);
927   if (result == 0) {
928     *ptr = i;
929   }
930   return result;
931 }
932
933 /**
934  * Binary converter for netaddr objects.
935  * See CFG_MAP_NETADDR_*() macros in cfg_schema.h
936  * @param s_entry pointer to configuration entry schema.
937  * @param value pointer to value of configuration entry.
938  * @param reference pointer to binary output buffer.
939  * @return 0 if conversion succeeded, -1 otherwise.
940  */int
941 cfg_schema_tobin_netaddr(const struct cfg_schema_entry *s_entry __attribute__((unused)),
942     const struct const_strarray *value, void *reference) {
943   struct netaddr *ptr;
944
945   ptr = (struct netaddr *)reference;
946
947   if (!_get_known_prefix(ptr, strarray_get_first_c(value))) {
948     return 0;
949   }
950   return netaddr_from_string(ptr, strarray_get_first_c(value));
951 }
952
953 /**
954  * Schema entry binary converter for ACL entries.
955  * See CFG_MAP_ACL_*() macros.
956  * @param s_entry pointer to schema entry.
957  * @param value pointer to value to configuration entry
958  * @param reference pointer to binary target
959  * @return -1 if an error happened, 0 otherwise
960  */
961 int
962 cfg_schema_tobin_acl(const struct cfg_schema_entry *s_entry __attribute__((unused)),
963      const struct const_strarray *value, void *reference) {
964   struct netaddr_acl *ptr;
965
966   ptr = (struct netaddr_acl *)reference;
967
968   free(ptr->accept);
969   free(ptr->reject);
970
971   return netaddr_acl_from_strarray(ptr, value);
972 }
973
974
975  /**
976   * Binary converter for booleans.
977   * See CFG_MAP_BOOL() macro in cfg_schema.h
978   * @param s_entry pointer to configuration entry schema.
979   * @param value pointer to value of configuration entry.
980   * @param reference pointer to binary output buffer.
981   * @return 0 if conversion succeeded, -1 otherwise.
982   */
983 int
984 cfg_schema_tobin_bool(const struct cfg_schema_entry *s_entry __attribute__((unused)),
985     const struct const_strarray *value, void *reference) {
986   bool *ptr;
987
988   ptr = (bool *)reference;
989
990   *ptr = cfg_get_bool(strarray_get_first_c(value));
991   return 0;
992 }
993
994 /**
995  * Binary converter for list of strings.
996  * See CFG_MAP_STRINGLIST() macro in cfg_schema.h
997  * @param s_entry pointer to configuration entry schema.
998  * @param value pointer to value of configuration entry.
999  * @param reference pointer to binary output buffer.
1000  * @return 0 if conversion succeeded, -1 otherwise.
1001  */
1002 int
1003 cfg_schema_tobin_stringlist(const struct cfg_schema_entry *s_entry __attribute__((unused)),
1004     const struct const_strarray *value, void *reference) {
1005   struct strarray *array;
1006
1007   array = (struct strarray *)reference;
1008
1009   if (!value->value[0]) {
1010     strarray_init(array);
1011     return 0;
1012   }
1013   return strarray_copy_c(array, value);
1014 }
1015
1016 /**
1017  * Compare two sets of databases and trigger delta listeners according to connected
1018  * schema.
1019  * @param pre_change pre-change database
1020  * @param post_change post-change database
1021  * @param startup if true, also trigger unnamed sections which don't change, but are
1022  *   of type CFG_SSMODE_UNNAMED (and not CFG_SSMODE_UNNAMED_OPTIONAL_STARTUP_TRIGGER).
1023  * @return -1 if an error happened, 0 otherwise
1024  */
1025 static int
1026 _handle_db_changes(struct cfg_db *pre_change, struct cfg_db *post_change, bool startup) {
1027   struct cfg_section_type default_section_type[2];
1028   struct cfg_named_section default_named_section[2];
1029   struct cfg_schema_section *s_section;
1030   struct cfg_section_type *pre_type, *post_type;
1031   struct cfg_named_section *pre_named, *post_named, *named_it;
1032   struct cfg_named_section * pre_defnamed, *post_defnamed;
1033
1034   if (pre_change->schema == NULL || pre_change->schema != post_change->schema) {
1035     /* no valid schema found */
1036     return -1;
1037   }
1038
1039   /* initialize default named section mechanism */
1040   memset(default_named_section, 0, sizeof(default_named_section));
1041   memset(default_section_type, 0, sizeof(default_section_type));
1042
1043   avl_init(&default_named_section[0].entries, cfg_avlcmp_keys, false);
1044   avl_init(&default_named_section[1].entries, cfg_avlcmp_keys, false);
1045   default_named_section[0].section_type = &default_section_type[0];
1046   default_named_section[1].section_type = &default_section_type[1];
1047
1048   default_section_type[0].db = pre_change;
1049   default_section_type[1].db = post_change;
1050
1051   avl_for_each_element(&pre_change->schema->handlers, s_section, _delta_node) {
1052     /* get section types in both databases */
1053     pre_type = cfg_db_find_sectiontype(pre_change, s_section->type);
1054     post_type = cfg_db_find_sectiontype(post_change, s_section->type);
1055
1056     /* prepare for default named section */
1057     pre_defnamed = NULL;
1058     post_defnamed = NULL;
1059
1060     if (s_section->mode == CFG_SSMODE_NAMED_WITH_DEFAULT) {
1061       /* check if pre_change db has a named section with the default name */
1062       if (pre_type == NULL || !avl_find_element(
1063             &pre_type->names, s_section->def_name, pre_named, node)) {
1064         /* initialize dummy section type for pre-change db */
1065         default_section_type[0].type = s_section->type;
1066
1067         /* initialize dummy named section for pre-change */
1068         default_named_section[0].name = s_section->def_name;
1069
1070         /* remember decision */
1071         pre_defnamed = &default_named_section[0];
1072       }
1073
1074       /* check if post_change db has a named section with the default name */
1075       if (post_type == NULL || !avl_find_element(
1076             &post_type->names, s_section->def_name, post_named, node)) {
1077         /* initialize dummy section type for post-change db */
1078         default_section_type[1].type = s_section->type;
1079
1080         /* initialize dummy named section for post-change */
1081         default_named_section[1].name = s_section->def_name;
1082
1083         /* remember decision */
1084         post_defnamed = &default_named_section[1];
1085       }
1086     }
1087
1088     if (post_type) {
1089       /* handle new named sections and changes */
1090       pre_named = NULL;
1091       CFG_FOR_ALL_SECTION_NAMES(post_type, post_named, named_it) {
1092         _handle_named_section_change(s_section, pre_change, post_change,
1093             post_named->name, startup, pre_defnamed, post_defnamed);
1094       }
1095     }
1096     if (pre_type) {
1097       /* handle removed named sections */
1098       post_named = NULL;
1099       CFG_FOR_ALL_SECTION_NAMES(pre_type, pre_named, named_it) {
1100         if (post_type) {
1101           post_named = cfg_db_get_named_section(post_type, pre_named->name);
1102         }
1103
1104         if (!post_named) {
1105           _handle_named_section_change(s_section, pre_change, post_change,
1106               pre_named->name, startup, pre_defnamed, post_defnamed);
1107         }
1108       }
1109     }
1110     if (startup && s_section->mode == CFG_SSMODE_UNNAMED
1111         && pre_type == NULL && post_type == NULL) {
1112       /* send change signal on startup for unnamed section */
1113       _handle_named_section_change(s_section, pre_change, post_change, NULL, true,
1114           pre_defnamed, post_defnamed);
1115     }
1116     if (startup && s_section->mode == CFG_SSMODE_NAMED_WITH_DEFAULT
1117         && pre_defnamed != NULL && post_defnamed != NULL) {
1118       /* send change signal on startup for default named section */
1119       _handle_named_section_change(s_section, pre_change, post_change,
1120           s_section->def_name, true, NULL, post_defnamed);
1121     }
1122   }
1123   return 0;
1124 }
1125
1126 /**
1127  * Validates on configuration entry.
1128  * @param schema_section pointer to schema section
1129  * @param db pointer to database
1130  * @param section pointer to database section type
1131  * @param named pointer to named section
1132  * @param entry pointer to configuration entry
1133  * @param section_name name of section including type (for debug output)
1134  * @param cleanup true if bad _entries should be removed
1135  * @param out error output buffer
1136  * @return true if an error happened, false otherwise
1137  */
1138 static bool
1139 _validate_cfg_entry(struct cfg_db *db, struct cfg_section_type *section,
1140     struct cfg_named_section *named, struct cfg_entry *entry,
1141     const char *section_name, bool cleanup, struct autobuf *out) {
1142   struct cfg_schema_entry *schema_entry, *s_entry_it;
1143   struct cfg_schema_entry_key key;
1144   bool warning, do_remove;
1145   char *ptr1;
1146
1147   warning = false;
1148   ptr1 = NULL;
1149
1150   key.type = section->type;
1151   key.entry = entry->name;
1152
1153   avl_for_each_elements_with_key(
1154       &db->schema->entries, schema_entry, _node, s_entry_it, &key) {
1155
1156     if (schema_entry == NULL) {
1157       cfg_append_printable_line(out, "Unknown entry '%s'"
1158           " for section type '%s'", entry->name, section->type);
1159       return true;
1160     }
1161
1162     if (schema_entry->cb_validate == NULL) {
1163       continue;
1164     }
1165
1166     /* now validate syntax */
1167     ptr1 = entry->val.value;
1168
1169     do_remove = false;
1170     while (ptr1 < entry->val.value + entry->val.length) {
1171       if (!do_remove && schema_entry->cb_validate(schema_entry, section_name, ptr1, out) != 0) {
1172         /* warning is generated by the validate callback itself */
1173         warning = true;
1174       }
1175
1176       if ((warning || do_remove) && cleanup) {
1177         /* illegal entry found, remove it */
1178         strarray_remove_ext(&entry->val, ptr1, false);
1179       }
1180       else {
1181         ptr1 += strlen(ptr1) + 1;
1182       }
1183
1184       if (!schema_entry->list) {
1185         do_remove = true;
1186       }
1187     }
1188
1189     if (strarray_is_empty(&entry->val)) {
1190       /* remove entry */
1191       cfg_db_remove_entry(db, section->type, named->name, entry->name);
1192     }
1193   }
1194   return warning;
1195 }
1196
1197 /**
1198  * Checks a database section for missing mandatory _entries
1199  * @param schema_section pointer to schema of section
1200  * @param db pointer to database
1201  * @param section pointer to database section type
1202  * @param named pointer to named section
1203  * @param section_name name of section including type (for debug output)
1204  * @param out error output buffer
1205  * @return true if an error happened, false otherwise
1206  */
1207 static bool
1208 _check_missing_entries(struct cfg_schema_section *schema_section,
1209     struct cfg_db *db, struct cfg_named_section *named,
1210     const char *section_name, struct autobuf *out) {
1211   struct cfg_schema_entry *first_schema_entry, *schema_entry;
1212   struct cfg_schema_entry_key key;
1213   bool warning, error;
1214
1215   warning = false;
1216   error = false;
1217
1218   key.type = schema_section->type;
1219   key.entry = NULL;
1220
1221   /* check for missing values */
1222   first_schema_entry = avl_find_ge_element(&db->schema->entries, &key, schema_entry, _node);
1223   if (!first_schema_entry) {
1224     return 0;
1225   }
1226
1227   avl_for_element_to_last(&db->schema->entries, first_schema_entry, schema_entry, _node) {
1228     if (cfg_cmp_keys(schema_entry->key.type, schema_section->type) != 0)
1229       break;
1230
1231     if (!strarray_is_empty_c(&schema_entry->def)) {
1232       continue;
1233     }
1234
1235     /* mandatory parameter */
1236     warning = !cfg_db_find_entry(db, schema_entry->key.type,
1237         named->name, schema_entry->key.entry);
1238     error |= warning;
1239     if (warning) {
1240       cfg_append_printable_line(out, "Missing mandatory value for entry '%s' in section %s",
1241           schema_entry->key.entry, section_name);
1242     }
1243   }
1244   return error;
1245 }
1246
1247 /**
1248  * Handle changes in a single named section
1249  * @param s_section schema entry for section
1250  * @param pre_change pointer to database before changes
1251  * @param post_change pointer to database after changes
1252  * @param name
1253  */
1254 static void
1255 _handle_named_section_change(struct cfg_schema_section *s_section,
1256     struct cfg_db *pre_change, struct cfg_db *post_change,
1257     const char *name, bool startup,
1258     struct cfg_named_section *pre_defnamed,
1259     struct cfg_named_section *post_defnamed) {
1260   struct cfg_schema_entry *entry;
1261   bool changed;
1262   size_t i;
1263
1264   if ((s_section->mode == CFG_SSMODE_NAMED
1265        || s_section->mode == CFG_SSMODE_NAMED_MANDATORY
1266        || s_section->mode == CFG_SSMODE_NAMED_WITH_DEFAULT)
1267       && name == NULL) {
1268     /*
1269      * ignore unnamed data entry for named sections, they are only
1270      * used for delivering defaults
1271      */
1272     return;
1273   }
1274
1275   s_section->pre = cfg_db_find_namedsection(pre_change, s_section->type, name);
1276   s_section->post = cfg_db_find_namedsection(post_change, s_section->type, name);
1277
1278   if (s_section->mode == CFG_SSMODE_NAMED_WITH_DEFAULT
1279       && strcasecmp(s_section->def_name, name) == 0) {
1280     /* use the default named sections if necessary */
1281     if (s_section->pre == NULL && !startup) {
1282       s_section->pre = pre_defnamed;
1283     }
1284     if (s_section->post == NULL) {
1285       s_section->post = post_defnamed;
1286     }
1287   }
1288   changed = false;
1289
1290   for (i=0; i<s_section->entry_count; i++) {
1291     entry = &s_section->entries[i];
1292
1293     /* read values */
1294     entry->pre = cfg_db_get_entry_value(
1295         pre_change, s_section->type, name, entry->key.entry);
1296     entry->post = cfg_db_get_entry_value(
1297         post_change, s_section->type, name, entry->key.entry);
1298
1299     entry->delta_changed = strarray_cmp_c(entry->pre, entry->post);
1300     changed |= entry->delta_changed;
1301   }
1302
1303   if (changed || startup) {
1304     s_section->section_name = name;
1305     s_section->cb_delta_handler();
1306   }
1307 }
1308
1309 /**
1310  * Lookup if the name is in the list of known prefixes and
1311  * sets the address if the name is found.
1312  * Netaddr target will not be touched if name is not in known
1313  * prefix list.
1314  * @param dst pointer to target netaddr
1315  * @param name text name to look for
1316  * @return 0 if name was found, -1 otherwise
1317  */
1318 static int
1319 _get_known_prefix(struct netaddr *dst, const char *name) {
1320   size_t i;
1321
1322   for (i=0; i<ARRAYSIZE(_known_prefixes); i++) {
1323     if (strcasecmp(name, _known_prefixes[i].name) == 0) {
1324       memcpy(dst, _known_prefixes[i].prefix, sizeof(*dst));
1325       return 0;
1326     }
1327   }
1328   return -1;
1329 }