Update to new config/common API, fix some bugs in core
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Fri, 25 Nov 2011 11:33:36 +0000 (12:33 +0100)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Fri, 25 Nov 2011 11:33:36 +0000 (12:33 +0100)
22 files changed:
lib/httptelnet/src/httptelnet.c
lib/remotecontrol/src/remotecontrol.c
src/common/avl.c
src/common/avl.h
src/common/netaddr.c
src/common/netaddr.h
src/common/string.c
src/common/string.h
src/config/cfg_cmd.c
src/config/cfg_db.c
src/config/cfg_db.h
src/config/cfg_delta.c
src/config/cfg_schema.c
src/config/cfg_schema.h
src/core/olsr_cfg.c
src/core/olsr_http.c
src/core/olsr_logging_cfg.c
src/core/olsr_netaddr_acl.c
src/core/olsr_netaddr_acl.h
src/core/olsr_stream_socket.c
src/core/olsr_telnet.c
src/olsr_main.c

index 6b291cd..3276346 100644 (file)
@@ -56,13 +56,13 @@ OLSR_PLUGIN7 {
 
 /* configuration */
 static struct cfg_schema_section _httptelnet_section = {
-  .t_type = _CFG_SECTION
+  .type = _CFG_SECTION
 };
 
 static struct cfg_schema_entry _httptelnet_entries[] = {
-  CFG_MAP_STRING(olsr_http_handler, site, "/telnet", "Path for http2telnet bridge"),
-  CFG_MAP_ACL(olsr_http_handler, acl, "default_accept", "acl for http2telnet bridge"),
-  CFG_MAP_STRINGLIST(olsr_http_handler, auth, "", "TODO"),
+  CFG_MAP_STRING(olsr_http_handler, site, "site", "/telnet", "Path for http2telnet bridge"),
+  CFG_MAP_ACL(olsr_http_handler, acl, "acl", "default_accept", "acl for http2telnet bridge"),
+  CFG_MAP_STRINGLIST(olsr_http_handler, auth, "auth", "", "TODO"),
 };
 
 static struct cfg_delta_handler _httptelnet_delta_handler = {
index 8bf55ef..ab53a9e 100644 (file)
@@ -121,11 +121,11 @@ OLSR_PLUGIN7 {
 
 /* configuration */
 static struct cfg_schema_section _remotecontrol_section = {
-  .t_type = "remotecontrol"
+  .type = "remotecontrol"
 };
 
 static struct cfg_schema_entry _remotecontrol_entries[] = {
-  CFG_MAP_ACL(_remotecontrol_cfg, acl, "default_accept", "acl for remote control commands"),
+  CFG_MAP_ACL(_remotecontrol_cfg, acl, "acl", "default_accept", "acl for remote control commands"),
 };
 
 static struct cfg_delta_handler _remotecontrol_handler = {
@@ -516,7 +516,7 @@ _cb_handle_config(struct olsr_telnet_data *data) {
 
   if ((next = str_hasnextword(data->parameter, "commit"))) {
     if (!cfg_schema_validate(olsr_cfg_get_rawdb(),
-        false, false, true, data->out)) {
+        false, true, data->out)) {
       olsr_cfg_trigger_commit();
     }
   }
index c6158d0..0296433 100644 (file)
@@ -204,7 +204,7 @@ avl_insert(struct avl_tree *tree, struct avl_node *new)
   new->right = NULL;
 
   new->balance = 0;
-  new->leader = true;
+  new->follower = false;
 
   if (tree->root == NULL) {
     list_add_head(&tree->list_head, &new->list);
@@ -219,7 +219,7 @@ avl_insert(struct avl_tree *tree, struct avl_node *new)
 
   while (!list_is_last(&tree->list_head, &last->list)) {
     next = list_next_element(last, list);
-    if (next->leader) {
+    if (!next->follower) {
       break;
     }
     last = next;
@@ -231,7 +231,7 @@ avl_insert(struct avl_tree *tree, struct avl_node *new)
     if (!tree->allow_dups)
       return -1;
 
-    new->leader = 0;
+    new->follower = true;
 
     _avl_insert_after(tree, last, new);
     return 0;
@@ -286,11 +286,11 @@ avl_remove(struct avl_tree *tree, struct avl_node *node)
   struct avl_node *parent;
   struct avl_node *left;
   struct avl_node *right;
-  if (node->leader) {
+  if (!node->follower) {
     if (tree->allow_dups
         && !list_is_last(&tree->list_head, &node->list)
-        && !(next = list_next_element(node, list))->leader) {
-      next->leader = true;
+        && (next = list_next_element(node, list))->follower) {
+      next->follower = false;
       next->balance = node->balance;
 
       parent = node->parent;
index 19a0dbf..735e071 100644 (file)
@@ -88,9 +88,10 @@ struct avl_node {
   signed char balance;
 
   /**
-   * true if first of a series of nodes with same key
+   * true if this is an additional node with the same key
+   * as the one before
    */
-  bool leader;
+  bool follower;
 };
 
 /**
@@ -481,6 +482,25 @@ avl_delete(struct avl_tree *tree, struct avl_node *node) {
 #define avl_for_first_to_element_reverse(tree, last, element, node_member) \
   avl_for_element_range_reverse(avl_first_element(tree, element, node_member), last, element, node_member)
 
+/**
+ * Loop over a block of elements of a tree with a certain key, used similar
+ * to a for() command.
+ * This loop should not be used if elements are removed from the tree during
+ * the loop.
+ *
+ * @param tree pointer to avl-tree
+ * @param element pointer to a node of the tree, this element will
+ *    contain the current node of the list during the loop
+ * @param node_member name of the avl_node element inside the
+ *    larger struct
+ * @param start helper pointer to remember start of iteration
+ * @param key pointer to key
+ */
+#define avl_for_each_elements_with_key(tree, element, node_member, start, key) \
+  for (start = element = avl_find_element(tree, key, element, node_member); \
+       element != NULL && &element->node_member.list != &(tree)->list_head && (element == start || element->node_member.follower); \
+       element = avl_next_element(element, node_member))
+
 /**
  * Loop over a block of nodes of a tree, used similar to a for() command.
  * This loop can be used if the current element might be removed from
index aa913e5..8febc86 100644 (file)
@@ -56,6 +56,10 @@ static int _subnetmask_to_prefixlen(const char *src);
 static int _read_hexdigit(const char c);
 static bool _binary_is_in_subnet(const struct netaddr *subnet,
     const void *bin);
+
+const struct netaddr NETADDR_IPV4_ANY = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, AF_INET, 0 };
+const struct netaddr NETADDR_IPV6_ANY = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, AF_INET6, 0 };
+
 /**
  * Read the binary representation of an address into a netaddr object
  * @param dst pointer to netaddr object
@@ -65,7 +69,8 @@ static bool _binary_is_in_subnet(const struct netaddr *subnet,
  * @return 0 if successful read binary data, -1 otherwise
  */
 int
-netaddr_from_binary(struct netaddr *dst, void *binary, size_t len, uint8_t addr_type) {
+netaddr_from_binary(struct netaddr *dst, const void *binary,
+    size_t len, uint8_t addr_type) {
   memset(dst->addr, 0, sizeof(dst->addr));
   if (addr_type == AF_INET && len >= 4) {
     /* ipv4 */
@@ -106,7 +111,7 @@ netaddr_from_binary(struct netaddr *dst, void *binary, size_t len, uint8_t addr_
  * @return 0 if successful read binary data, -1 otherwise
  */
 int
-netaddr_to_binary(void *dst, struct netaddr *src, size_t len) {
+netaddr_to_binary(void *dst, const struct netaddr *src, size_t len) {
   if (src->type == AF_INET && len >= 4) {
     /* ipv4 */
     memcpy(dst, src->addr, 4);
@@ -138,7 +143,7 @@ netaddr_to_binary(void *dst, struct netaddr *src, size_t len) {
  * @return 0 if successful read binary data, -1 otherwise
  */
 int
-netaddr_from_socket(struct netaddr *dst, union netaddr_socket *src) {
+netaddr_from_socket(struct netaddr *dst, const union netaddr_socket *src) {
   memset(dst->addr, 0, sizeof(dst->addr));
   if (src->std.sa_family == AF_INET) {
     /* ipv4 */
@@ -166,7 +171,7 @@ netaddr_from_socket(struct netaddr *dst, union netaddr_socket *src) {
  * @return 0 if successful read binary data, -1 otherwise
  */
 int
-netaddr_to_socket(union netaddr_socket *dst, struct netaddr *src) {
+netaddr_to_socket(union netaddr_socket *dst, const struct netaddr *src) {
   /* copy address type */
   dst->std.sa_family = src->type;
 
@@ -190,7 +195,7 @@ netaddr_to_socket(union netaddr_socket *dst, struct netaddr *src) {
 
 
 int
-netaddr_to_autobuf(struct autobuf *abuf, struct netaddr *src) {
+netaddr_to_autobuf(struct autobuf *abuf, const struct netaddr *src) {
   switch (src->type) {
     case AF_INET:
       /* ipv4 */
@@ -214,6 +219,61 @@ netaddr_to_autobuf(struct autobuf *abuf, struct netaddr *src) {
   }
 }
 
+/**
+ * Creates a host address from a netmask and a host number part. This function
+ * will copy the netmask and then overwrite the bits after the prefix length
+ * with the one from the host number.
+ * @param host target buffer
+ * @param netmask prefix of result
+ * @param number postfix of result
+ * @param num_length length of the postfix in bytes
+ * @return -1 if an error happened, 0 otherwise
+ */
+int
+netaddr_create_host_bin(struct netaddr *host, const struct netaddr *netmask,
+    const void *number, size_t num_length) {
+  size_t host_index, number_index;
+  uint8_t host_part_length;
+  const uint8_t *number_byte;
+
+  number_byte = number;
+
+  /* copy netmask with prefixlength max */
+  memcpy(host, netmask, sizeof(*netmask));
+  host->prefix_len = netaddr_get_maxprefix(host);
+
+  /* unknown address type */
+  if (host->prefix_len == 0) {
+    return -1;
+  }
+
+  /* netmask has no host part */
+  if (host->prefix_len == netmask->prefix_len || num_length == 0) {
+    return 0;
+  }
+
+  /* calculate starting byte in host and number */
+  host_part_length = (host->prefix_len - netmask->prefix_len + 7)/8;
+  if (host_part_length > num_length) {
+    host_index = host->prefix_len/8 - num_length;
+    number_index = 0;
+  }
+  else {
+    host_index = netmask->prefix_len / 8;
+    number_index = num_length - host_part_length;
+
+    /* copy bit masked part */
+    if ((netmask->prefix_len & 7) != 0) {
+      host->addr[host_index++] |=
+          (number_byte[number_index++]) & (255 >> (netmask->prefix_len & 7));
+    }
+  }
+
+  /* copy bytes */
+  memcpy(&host->addr[host_index], &number_byte[number_index], num_length - number_index);
+  return 0;
+}
+
 /**
  * Initialize a netaddr_socket with a netaddr and a port number
  * @param combined pointer to netaddr_socket to be initialized
@@ -222,7 +282,7 @@ netaddr_to_autobuf(struct autobuf *abuf, struct netaddr *src) {
  * @return 0 if successful read binary data, -1 otherwise
  */
 int
-netaddr_socket_init(union netaddr_socket *combined, struct netaddr *addr, uint16_t port) {
+netaddr_socket_init(union netaddr_socket *combined, const struct netaddr *addr, uint16_t port) {
   /* initialize memory block */
   memset(combined, 0, sizeof(*combined));
 
@@ -251,7 +311,7 @@ netaddr_socket_init(union netaddr_socket *combined, struct netaddr *addr, uint16
  * @return port of socket
  */
 uint16_t
-netaddr_socket_get_port(union netaddr_socket *sock) {
+netaddr_socket_get_port(const union netaddr_socket *sock) {
   switch (sock->std.sa_family) {
     case AF_INET:
       return ntohs(sock->v4.sin_port);
@@ -438,7 +498,7 @@ netaddr_from_string(struct netaddr *dst, const char *src) {
  * @return pointer to target buffer, NULL if an error happened
  */
 const char *
-netaddr_socket_to_string(struct netaddr_str *dst, union netaddr_socket *src) {
+netaddr_socket_to_string(struct netaddr_str *dst, const union netaddr_socket *src) {
   struct netaddr_str buf;
 
   if (src->std.sa_family == AF_INET) {
index e4b52bb..0314907 100644 (file)
@@ -96,19 +96,24 @@ struct netaddr_str {
   char buf[INET6_ADDRSTRLEN+16];
 };
 
-EXPORT int netaddr_from_binary(struct netaddr *dst, void *binary, size_t len, uint8_t addr_type);
-EXPORT int netaddr_to_binary(void *dst, struct netaddr *src, size_t len);
-EXPORT int netaddr_from_socket(struct netaddr *dst, union netaddr_socket *src);
-EXPORT int netaddr_to_socket(union netaddr_socket *dst, struct netaddr *src);
-EXPORT int netaddr_to_autobuf(struct autobuf *, struct netaddr *src);
-
-EXPORT int netaddr_socket_init(union netaddr_socket *combined, struct netaddr *addr, uint16_t port);
-EXPORT uint16_t netaddr_socket_get_port(union netaddr_socket *sock);
+EXPORT extern const struct netaddr NETADDR_IPV4_ANY;
+EXPORT extern const struct netaddr NETADDR_IPV6_ANY;
+
+EXPORT int netaddr_from_binary(struct netaddr *dst, const void *binary, size_t len, uint8_t addr_type);
+EXPORT int netaddr_to_binary(void *dst, const struct netaddr *src, size_t len);
+EXPORT int netaddr_from_socket(struct netaddr *dst, const union netaddr_socket *src);
+EXPORT int netaddr_to_socket(union netaddr_socket *dst, const struct netaddr *src);
+EXPORT int netaddr_to_autobuf(struct autobuf *, const struct netaddr *src);
+EXPORT int netaddr_create_host_bin(struct netaddr *host, const struct netaddr *netmask,
+    const void *number, size_t num_length);
+EXPORT int netaddr_socket_init(union netaddr_socket *combined,
+    const struct netaddr *addr, uint16_t port);
+EXPORT uint16_t netaddr_socket_get_port(const union netaddr_socket *sock);
 
 EXPORT const char *netaddr_to_prefixstring(
     struct netaddr_str *dst, const struct netaddr *src, bool forceprefix);
 EXPORT int netaddr_from_string(struct netaddr *, const char *) __attribute__((warn_unused_result));
-EXPORT const char *netaddr_socket_to_string(struct netaddr_str *, union netaddr_socket *);
+EXPORT const char *netaddr_socket_to_string(struct netaddr_str *, const union netaddr_socket *);
 
 EXPORT int netaddr_cmp_to_socket(const struct netaddr *, const union netaddr_socket *);
 EXPORT bool netaddr_isequal_binary(const struct netaddr *addr,
@@ -137,6 +142,21 @@ netaddr_to_string(struct netaddr_str *dst, const struct netaddr *src) {
   return netaddr_to_prefixstring(dst, src, false);
 }
 
+/**
+ * Creates a host address from a netmask and a host number part. This function
+ * will copy the netmask and then overwrite the bits after the prefix length
+ * with the one from the host number.
+ * @param host target buffer
+ * @param netmask prefix of result
+ * @param host_number postfix of result
+ * @return -1 if an error happened, 0 otherwise
+ */
+static INLINE int
+netaddr_create_host(struct netaddr *host, const struct netaddr *netmask,
+    const struct netaddr *host_number) {
+  return netaddr_create_host_bin(host, netmask, host_number->addr,
+      netaddr_get_maxprefix(host_number));
+}
 
 /**
  * Compares two addresses.
index ca762c2..9d22535 100644 (file)
@@ -161,10 +161,10 @@ str_hasnextword (const char *buffer, const char *word) {
  * @return 0 if array was copied, -1 if an error happened
  */
 int
-strarray_copy(struct strarray *dst, struct strarray *src) {
+strarray_copy(struct strarray *dst, const struct strarray *src) {
   char *ptr;
 
-  if (src->length == 0) {
+  if (src->value == NULL || src->length == 0) {
     memset(dst, 0, sizeof(*dst));
     return 0;
   }
@@ -175,7 +175,6 @@ strarray_copy(struct strarray *dst, struct strarray *src) {
   }
 
   memcpy(ptr, src->value, src->length);
-  dst->last_value = src->last_value - src->value + ptr;
   dst->length = src->length;
   dst->value = ptr;
   return 0;
@@ -203,7 +202,33 @@ strarray_append(struct strarray *array, const char *string) {
 
   memcpy(ptr + array->length, string, length);
   array->value = ptr;
-  array->last_value = ptr + array->length;
+  array->length = new_length;
+  return 0;
+}
+
+/**
+ * Put a string to in front of an existing string array. Only use this
+ * if the string-array value has been allocated with malloc/calloc.
+ * @param array pointer to string array object
+ * @param string pointer to string to append
+ * @return 0 if string was appended, -1 if an error happened
+ */
+int
+strarray_prepend(struct strarray *array, const char *string) {
+  size_t length, new_length;
+  char *ptr;
+
+  length = strlen(string) + 1;
+
+  new_length = array->length + length;
+  ptr = realloc(array->value, STRARRAY_MEMSIZE(new_length));
+  if (ptr == NULL) {
+    return -1;
+  }
+
+  memmove(ptr + length, ptr, array->length);
+  memcpy(ptr, string, length);
+  array->value = ptr;
   array->length = new_length;
   return 0;
 }
@@ -217,37 +242,21 @@ strarray_append(struct strarray *array, const char *string) {
 void
 strarray_remove_ext(struct strarray *array,
     char *element, bool resize) {
-  char *ptr1, *ptr2 = NULL;
+  char *ptr1;
   size_t len;
 
-  if (array->value == array->last_value) {
-    /* remove only element */
+  /* get length of element to remove */
+  len = strlen(element) + 1;
+  if (len == array->length) {
     strarray_free(array);
     return;
   }
 
-  /* get length of element to remove */
-  len = strlen(element) + 1;
-
   /* adjust length */
   array->length -= len;
 
-  /* fix last_value pointer */
-  if (element == array->last_value) {
-    /* search for the 'second last' element */
-    FOR_ALL_STRINGS(array, ptr1) {
-      if (ptr1 == element) {
-        break;
-      }
-      ptr2 = ptr1;
-    }
-    array->last_value = ptr2;
-  }
-  else {
-    /* just move the last value pointer backwards */
-    array->last_value -= len;
-
-    /* remove element from memory */
+  /* remove element from memory */
+  if (element <= array->value + array->length) {
     memmove(element, element + len, array->length - (element - array->value));
   }
 
@@ -257,15 +266,12 @@ strarray_remove_ext(struct strarray *array,
 
   /* adjust memory block */
   ptr1 = realloc(array->value, STRARRAY_MEMSIZE(array->length));
-  if (ptr1 == NULL || array->value == ptr1) {
+  if (ptr1 == NULL) {
     /* just keep the current memory block */
     return;
   }
 
-  /* adjust last-value pointer to new memory block */
-  array->last_value = array->last_value - array->value + ptr1;
-
-  /* adjust value pointer to new memory block*/
+  /* adjust value pointer to new memory block */
   array->value = ptr1;
 }
 
@@ -274,7 +280,7 @@ strarray_remove_ext(struct strarray *array,
  * @return number of strings in string array
  */
 size_t
-strarray_get_count(struct strarray *array) {
+strarray_get_count(const struct strarray *array) {
   size_t count = 0;
   char *ptr;
 
@@ -290,7 +296,7 @@ strarray_get_count(struct strarray *array) {
  * @return string at the specified index, NULL if not found
  */
 char *
-strarray_get(struct strarray *array, size_t idx) {
+strarray_get(const struct strarray *array, size_t idx) {
   size_t count = 0;
   char *ptr;
 
index c76761e..36ec6bd 100644 (file)
@@ -57,8 +57,7 @@
  * Represents a string or an array of strings
  * The strings (including there Zero-Byte) are just appended
  * into a large binary buffer. The struct contains a pointer
- * to the first and to the last string and the size of the
- * binary buffer
+ * to the first string and the size of the binary buffer
  *
  * typically append operations are done by realloc() calls
  * while remove operations are done with memmove
@@ -67,24 +66,44 @@ struct strarray {
   /* pointer to the first string */
   char *value;
 
-  /* pointer to the last string */
-  char *last_value;
-
   /* total length of all strings including zero-bytes */
   size_t length;
 };
 
+struct const_strarray {
+  const char *value;
+
+  const size_t length;
+};
+
 EXPORT char *strscpy (char *dest, const char *src, size_t size);
 EXPORT char *strscat (char *dest, const char *src, size_t size);
 EXPORT char *str_trim (char *ptr);
 EXPORT const char *str_hasnextword (const char *buffer, const char *word);
 
-EXPORT int strarray_copy(struct strarray *dst, struct strarray *src);
+EXPORT int strarray_copy(struct strarray *dst, const struct strarray *src);
 EXPORT int strarray_append(struct strarray *, const char *);
+EXPORT int strarray_prepend(struct strarray *array, const char *string);
 EXPORT void strarray_remove_ext(struct strarray *, char *, bool);
 
-EXPORT char *strarray_get(struct strarray *array, size_t idx);
-EXPORT size_t strarray_get_count(struct strarray *array);
+EXPORT char *strarray_get(const struct strarray *array, size_t idx);
+EXPORT size_t strarray_get_count(const struct strarray *array);
+
+static INLINE int
+strarray_copy_c(struct strarray *dst, const struct const_strarray *src) {
+  return strarray_copy(dst, (const struct strarray *)src);
+}
+
+static INLINE const char *
+strarray_get_c(const struct const_strarray *array, size_t idx) {
+  return strarray_get((const struct strarray *)array, idx);
+}
+
+static INLINE size_t
+strarray_get_count_c(const struct const_strarray *array) {
+  return strarray_get_count((const struct strarray *)array);
+}
+
 
 /**
  * Initialize string array object
@@ -110,8 +129,13 @@ strarray_free(struct strarray *array) {
  * @return true if the array is empty, false otherwise
  */
 static INLINE bool
-strarray_is_empty(struct strarray *array) {
-  return array->length == 0;
+strarray_is_empty(const struct strarray *array) {
+  return array->value == NULL;
+}
+
+static INLINE bool
+strarray_is_empty_c(const struct const_strarray *array) {
+  return array->value == NULL;
 }
 
 /**
@@ -129,29 +153,28 @@ strarray_remove(struct strarray *array, char *element) {
  * @return pointer to first string of string array
  */
 static INLINE char *
-strarray_get_first(struct strarray *array) {
+strarray_get_first(const struct strarray *array) {
   return array->value;
 }
 
-/**
- * @param array pointer to strarray object
- * @return pointer to last string of string array
- */
-static INLINE char *
-strarray_get_last(struct strarray *array) {
-  return array->last_value;
+static INLINE const char *
+strarray_get_first_c(const struct const_strarray *array) {
+  return array->value;
 }
 
 /**
  * Do not call this function for the last string in
  * a string array.
- * @param array pointer to strarray object
  * @param current pointer to a string in array
  * @return pointer to next string in string array
  */
 static INLINE char *
-strarray_get_next(struct strarray *array __attribute__((unused)),
-    char *current) {
+strarray_get_next(char *current) {
+  return current + strlen(current) + 1;
+}
+
+static INLINE const char *
+strarray_get_next_c(const char *current) {
   return current + strlen(current) + 1;
 }
 
@@ -162,11 +185,26 @@ strarray_get_next(struct strarray *array __attribute__((unused)),
  *   NULL if there is no further string
  */
 static INLINE char *
-strarray_get_next_safe(struct strarray *array, char *current) {
-  if (current == array->last_value) {
+strarray_get_next_safe(const struct strarray *array, char *current) {
+  char *next;
+
+  next = current + strlen(current) + 1;
+  if (next > array->value + array->length) {
     return NULL;
   }
-  return current + strlen(current) + 1;
+  return next;
+}
+
+static INLINE const char *
+strarray_get_next_safe_c(const struct const_strarray *array,
+    const char *current) {
+  const char *next;
+
+  next = current + strlen(current) + 1;
+  if (next > array->value + array->length) {
+    return NULL;
+  }
+  return next;
 }
 
 /**
@@ -176,6 +214,6 @@ strarray_get_next_safe(struct strarray *array, char *current) {
  * @param array pointer to strarray object
  * @param charptr pointer to loop variable
  */
-#define FOR_ALL_STRINGS(array, charptr) for (charptr = strarray_get_first(array); charptr != NULL && charptr <= strarray_get_last(array); charptr = strarray_get_next(array, charptr))
+#define FOR_ALL_STRINGS(array, charptr) for (charptr = (array)->value; charptr != NULL && charptr < (array)->value + (array)->length; charptr += strlen(charptr) + 1)
 
 #endif
index bf5d203..b07edfc 100644 (file)
@@ -353,6 +353,7 @@ cfg_cmd_handle_schema(struct cfg_db *db,
     const char *arg, struct autobuf *log) {
   struct cfg_schema_section *s_section, *s_section_it;
   struct cfg_schema_entry *s_entry, *s_entry_it;
+  const char *c_ptr;
   char *copy, *ptr;
   int result;
 
@@ -367,11 +368,11 @@ cfg_cmd_handle_schema(struct cfg_db *db,
 
     CFG_FOR_ALL_SCHEMA_SECTIONS(db->schema, s_section, s_section_it) {
       cfg_append_printable_line(log, "    %s%s%s%s%s",
-          s_section->t_type,
-          s_section->t_named ? " (named)" : "",
-          s_section->t_mandatory ? " (mandatory)" : "",
-          s_section->t_help ? ": " : "",
-          s_section->t_help ? s_section->t_help : "");
+          s_section->type,
+          s_section->named ? " (named)" : "",
+          s_section->mandatory ? " (mandatory)" : "",
+          s_section->help ? ": " : "",
+          s_section->help ? s_section->help : "");
     }
     return 0;
   }
@@ -387,7 +388,8 @@ cfg_cmd_handle_schema(struct cfg_db *db,
     *ptr++ = 0;
   }
 
-  s_section = avl_find_element(&db->schema->sections, copy, s_section, node);
+  // TODO: support multiple schema with same section type
+  s_section = avl_find_element(&db->schema->sections, copy, s_section, _node);
   if (s_section == NULL) {
     cfg_append_printable_line(log, "Unknown section type '%s'", copy);
     goto handle_schema_cleanup;
@@ -398,17 +400,17 @@ cfg_cmd_handle_schema(struct cfg_db *db,
     abuf_puts(log, "(use this command with 'type.name' as parameter for more information)\n");
     CFG_FOR_ALL_SCHEMA_ENTRIES(s_section, s_entry, s_entry_it) {
       cfg_append_printable_line(log, "    %s%s%s%s%s",
-          s_entry->t_name,
-          s_entry->t_default == NULL ? " (mandatory)" : "",
-          s_entry->t_list ? " (list)" : "",
-          s_entry->t_help ? ": " : "",
-          s_entry->t_help ? s_entry->t_help : "");
+          s_entry->name,
+          strarray_is_empty_c(&s_entry->def) ? " (mandatory)" : "",
+          s_entry->list ? " (list)" : "",
+          s_entry->help ? ": " : "",
+          s_entry->help ? s_entry->help : "");
     }
     result = 0;
     goto handle_schema_cleanup;
   }
 
-  s_entry = avl_find_element(&s_section->entries, ptr, s_entry, node);
+  s_entry = avl_find_element(&s_section->_entries, ptr, s_entry, _node);
   if (s_entry == NULL) {
     cfg_append_printable_line(log, "Unknown entry name '%s' in section type '%s'",
         ptr, copy);
@@ -416,18 +418,21 @@ cfg_cmd_handle_schema(struct cfg_db *db,
   }
 
   cfg_append_printable_line(log, "%s.%s%s%s%s%s",
-      s_section->t_type,
-      s_entry->t_name,
-      s_entry->t_default == NULL ? " (mandatory)" : "",
-      s_entry->t_list ? " (list)" : "",
-      s_entry->t_help ? ": " : "",
-      s_entry->t_help ? s_entry->t_help : "");
-
-  if (s_entry->t_default) {
-    cfg_append_printable_line(log, "    Default value: '%s'", s_entry->t_default);
-  }
-  if (s_entry->t_validate) {
-    s_entry->t_validate(s_entry, NULL, NULL, log);
+      s_section->type,
+      s_entry->name,
+      strarray_is_empty_c(&s_entry->def) ? " (mandatory)" : "",
+      s_entry->list ? " (list)" : "",
+      s_entry->help ? ": " : "",
+      s_entry->help ? s_entry->help : "");
+
+  if (!strarray_is_empty_c(&s_entry->def)) {
+    cfg_append_printable_line(log, "    Default value:");
+    FOR_ALL_STRINGS(&s_entry->def, c_ptr) {
+      cfg_append_printable_line(log, "        '%s'", c_ptr);
+    }
+  }
+  if (s_entry->cb_valhelp) {
+    s_entry->cb_valhelp(s_entry, log);
   }
 
   result = 0;
index aad642f..2e6246f 100644 (file)
@@ -265,7 +265,7 @@ cfg_db_remove_namedsection(struct cfg_db *db, const char *section_type,
 struct cfg_entry *
 cfg_db_set_entry(struct cfg_db *db, const char *section_type,
     const char *section_name, const char *entry_name, const char *value,
-    bool append) {
+    bool prepend) {
   struct cfg_entry *entry;
   struct cfg_named_section *named;
   bool new_section = false, new_entry = NULL;
@@ -286,11 +286,11 @@ cfg_db_set_entry(struct cfg_db *db, const char *section_type,
     new_entry = true;
   }
 
-  if (!append) {
+  if (!prepend) {
     strarray_free(&entry->val);
   }
-  /* append new entry */
-  if (strarray_append(&entry->val, value)) {
+  /* prepend new entry */
+  if (strarray_prepend(&entry->val, value)) {
     goto set_entry_error;
   }
 
@@ -360,7 +360,7 @@ cfg_db_remove_entry(struct cfg_db *db, const char *section_type,
  * @param entry_name name of the entry
  * @return string value, NULL if not found or list of values
  */
-const char *
+const struct const_strarray *
 cfg_db_get_entry_value(struct cfg_db *db, const char *section_type,
     const char *section_name, const char *entry_name) {
   struct cfg_entry *entry;
@@ -369,7 +369,7 @@ cfg_db_get_entry_value(struct cfg_db *db, const char *section_type,
 
   entry = cfg_db_find_entry(db, section_type, section_name, entry_name);
   if (entry != NULL) {
-    return entry->val.last_value;
+    return (const struct const_strarray *)&entry->val;
   }
 
   if (db->schema == NULL) {
@@ -384,7 +384,7 @@ cfg_db_get_entry_value(struct cfg_db *db, const char *section_type,
 
   s_entry = cfg_schema_find_entry(s_section, entry_name);
   if (s_entry) {
-    return s_entry->t_default;
+    return &s_entry->def;
   }
   return NULL;
 }
@@ -430,25 +430,6 @@ cfg_db_remove_element(struct cfg_db *db, const char *section_type,
   return -1;
 }
 
-
-/**
- * Counts the number of list items of a configuration entry
- * @param entry pointer to cfg entry
- * @return number of items in the entries value
- */
-size_t
-cfg_db_entry_get_listsize(struct cfg_entry *entry) {
-  char *ptr;
-  size_t cnt = 1;
-
-  for (ptr = entry->val.value; ptr < entry->val.last_value; ptr++) {
-    if (*ptr == 0) {
-      cnt++;
-    }
-  }
-  return cnt;
-}
-
 /**
  * Creates a section type in a configuration database
  * @param db pointer to configuration database
index e72ef30..396d385 100644 (file)
@@ -135,12 +135,11 @@ EXPORT struct cfg_entry *cfg_db_find_entry(struct cfg_db *db,
     const char *section_type, const char *section_name, const char *entry_name);
 EXPORT int cfg_db_remove_entry(struct cfg_db *, const char *section_type,
     const char *section_name, const char *entry_name);
-EXPORT const char *cfg_db_get_entry_value(struct cfg_db *db,
+EXPORT const struct const_strarray *cfg_db_get_entry_value(struct cfg_db *db,
     const char *section_type, const char *section_name, const char *entry_name);
 
 EXPORT int cfg_db_remove_element(struct cfg_db *, const char *section_type,
     const char *section_name, const char *entry_name, const char *value);
-EXPORT size_t cfg_db_entry_get_listsize(struct cfg_entry *entry);
 
 /**
  * Link a configuration schema to a database
@@ -248,8 +247,6 @@ cfg_db_copy_entry(struct cfg_db *dst, struct cfg_db *src,
 static INLINE struct cfg_section_type *
 cfg_db_get_sectiontype(struct cfg_db *db, const char *section_type) {
   struct cfg_section_type *section;
-
-  /* get section */
   return avl_find_element(&db->sectiontypes, section_type, section, node);
 }
 
@@ -309,22 +306,13 @@ cfg_db_is_named_section(struct cfg_named_section *named) {
 
 /**
  * @param pointer to section type
- * @return pointer to named section element of unnamed section type,
- *   NULL if not an unnamed section or named entry is missing.
+ * @return pointer pointer to 'unnamed' named_section element,
+ *   NULL no unnamed section.
  */
 static INLINE struct cfg_named_section *
 cfg_db_get_unnamed_section(struct cfg_section_type *stype) {
   struct cfg_named_section *named;
-
-  if (avl_is_empty(&stype->names)) {
-    return NULL;
-  }
-
-  named = avl_first_element(&stype->names, named, node);
-  if (named != NULL && !cfg_db_is_named_section(named)) {
-    return named;
-  }
-  return NULL;
+  return avl_find_element(&stype->names, NULL, named, node);
 }
 
 /**
@@ -395,7 +383,18 @@ cfg_db_add_entry(struct cfg_db *db, const char *section_type,
  */
 static INLINE bool
 cfg_db_is_multipart_entry(struct cfg_entry *entry) {
-  return entry->val.value != entry->val.last_value;
+  return strarray_get(&entry->val, 1) != NULL;
+}
+
+
+/**
+ * Counts the number of list items of a configuration entry
+ * @param entry pointer to cfg entry
+ * @return number of items in the entries value
+ */
+static INLINE size_t
+cfg_db_entry_get_listsize(struct cfg_entry *entry) {
+  return strarray_get_count(&entry->val);
 }
 
 #endif /* CFG_DB_H_ */
index 9479f11..bf60971 100644 (file)
 #include "config/cfg_delta.h"
 
 static void _delta_section(struct cfg_delta_handler *handler,
-    struct cfg_section_type *pre_change, struct cfg_section_type *post_change,
-    struct cfg_schema_section *schema);
+    struct cfg_db *pre_db, struct cfg_db *post_db,
+    struct cfg_section_type *pre_change, struct cfg_section_type *post_change);
 static void _handle_namedsection(struct cfg_delta_handler *handler,
-    struct cfg_named_section *pre_change, struct cfg_named_section *post_change,
-    struct cfg_schema_section *schema_section);
+    struct cfg_db *pre_db, struct cfg_db *post_db,
+    struct cfg_named_section *pre_change, struct cfg_named_section *post_change);
 static bool _setup_filterresults(struct cfg_delta_handler *handler,
-    struct cfg_named_section *pre_change, struct cfg_named_section *post_change,
-    struct cfg_schema_section *schema);
-static bool _compare_db_keyvalue_pair(struct cfg_entry *pre, struct cfg_entry *post,
-    struct cfg_schema_section *schema);
+    struct cfg_db *pre_db, struct cfg_db *post_db,
+    struct cfg_named_section *pre_change, struct cfg_named_section *post_change);
+static bool _compare_db_keyvalue_pair(struct cfg_db *pre_db, struct cfg_db *post_db,
+    struct cfg_entry *pre, struct cfg_entry *post);
 static int _cmp_section_types(struct cfg_section_type *, struct cfg_section_type *);
 static int _cmp_named_section(struct cfg_named_section *, struct cfg_named_section *);
 static int _cmp_entries(struct cfg_entry *ptr1, struct cfg_entry *ptr2);
@@ -132,14 +132,14 @@ cfg_delta_add_handler_by_schema(
     size_t count) {
   size_t i;
 
-  d_handler->s_type = s_section->t_type;
+  d_handler->s_type = s_section->type;
   d_handler->callback = callback;
   d_handler->filter = d_filter;
   d_handler->priority = priority;
 
   for (i=0; i < count; i++) {
     memset(&d_filter[i], 0, sizeof(struct cfg_delta_filter));
-    d_filter[i].k = s_entries[i].t_name;
+    d_filter[i].k = s_entries[i].name;
   }
 
   /* last entry must be zero */
@@ -161,15 +161,6 @@ cfg_delta_calculate(struct cfg_delta *delta,
   struct cfg_section_type *section_pre = NULL, *section_post = NULL;
   struct cfg_named_section *named, *named_it;
   struct cfg_delta_handler *handler;
-  struct cfg_schema *schema;
-  struct cfg_schema_section *schema_section;
-
-  /* initialize section handling */
-  schema = NULL;
-  schema_section = NULL;
-  if (pre_change->schema == post_change->schema) {
-    schema = pre_change->schema;
-  }
 
   /* Iterate over delta handlers */
   avl_for_each_element(&delta->handler, handler, node) {
@@ -185,34 +176,24 @@ cfg_delta_calculate(struct cfg_delta *delta,
 
       if (cmp_sections < 0) {
         /* handle pre-section */
-        if (schema) {
-          schema_section = cfg_schema_find_section(schema, section_pre->type);
-        }
-
         if (handler->s_type == NULL || cfg_cmp_keys(handler->s_type, section_pre->type) == 0) {
           CFG_FOR_ALL_SECTION_NAMES(section_pre, named, named_it) {
-            _handle_namedsection(handler, named, NULL, schema_section);
+            _handle_namedsection(handler, pre_change, post_change, named, NULL);
           }
         }
       }
       else if (cmp_sections > 0) {
         /* handle post-section */
-        if (schema) {
-          schema_section = cfg_schema_find_section(schema, section_post->type);
-        }
         if (handler->s_type == NULL || cfg_cmp_keys(handler->s_type, section_post->type) == 0) {
           CFG_FOR_ALL_SECTION_NAMES(section_post, named, named_it) {
-            _handle_namedsection(handler, NULL, named, schema_section);
+            _handle_namedsection(handler, pre_change, post_change, NULL, named);
           }
         }
       }
       else {
         /* type is available in both db's, this might be an change event */
-        if (schema) {
-          schema_section = cfg_schema_find_section(schema, section_pre->type);
-        }
         if (handler->s_type == NULL || cfg_cmp_keys(handler->s_type, section_pre->type) == 0) {
-          _delta_section(handler, section_pre, section_post, schema_section);
+          _delta_section(handler, pre_change, post_change, section_pre, section_post);
         }
       }
 
@@ -233,7 +214,7 @@ cfg_delta_calculate(struct cfg_delta *delta,
  */
 void
 cfg_delta_trigger_non_optional(struct cfg_delta *delta,
-    struct cfg_db *post) {
+    struct cfg_db *post_db) {
   struct cfg_delta_handler *handler;
   struct cfg_schema_section *schema_section;
   struct cfg_section_type *post_type;
@@ -249,20 +230,20 @@ cfg_delta_trigger_non_optional(struct cfg_delta *delta,
       }
     }
 
-    avl_for_each_element(&post->schema->sections, schema_section, node) {
+    avl_for_each_element(&post_db->schema->sections, schema_section, _node) {
       if (handler->s_type != NULL
-          && cfg_cmp_keys(handler->s_type, schema_section->t_type) != 0) {
+          && cfg_cmp_keys(handler->s_type, schema_section->type) != 0) {
         /* handler only listenes to other section type */
         continue;
       }
 
-      post_type = cfg_db_find_sectiontype(post, schema_section->t_type);
+      post_type = cfg_db_find_sectiontype(post_db, schema_section->type);
 
-      if (schema_section->t_optional) {
+      if (schema_section->optional) {
         if (post_type) {
           /* optional section, handler normally */
           avl_for_each_element(&post_type->names, handler->post, node) {
-            _handle_namedsection(handler, NULL, handler->post, schema_section);
+            _handle_namedsection(handler, NULL, post_db, NULL, handler->post);
           }
         }
         continue;
@@ -301,8 +282,8 @@ cfg_delta_trigger_non_optional(struct cfg_delta *delta,
  */
 static void
 _delta_section(struct cfg_delta_handler *handler,
-    struct cfg_section_type *pre_change, struct cfg_section_type *post_change,
-    struct cfg_schema_section *schema) {
+    struct cfg_db *pre_db, struct cfg_db *post_db,
+    struct cfg_section_type *pre_change, struct cfg_section_type *post_change) {
   struct cfg_named_section *named_pre = NULL, *named_post = NULL;
 
   named_pre = avl_first_element_safe(&pre_change->names, named_pre, node);
@@ -316,15 +297,15 @@ _delta_section(struct cfg_delta_handler *handler,
 
     if (cmp_sections < 0) {
       /* handle pre-named */
-      _handle_namedsection(handler, named_pre, NULL, schema);
+      _handle_namedsection(handler, pre_db, post_db, named_pre, NULL);
     }
     else if (cmp_sections > 0) {
       /* handle post-section */
-      _handle_namedsection(handler, NULL, named_post, schema);
+      _handle_namedsection(handler, pre_db, post_db, NULL, named_post);
     }
     else {
       /* named section is available in both db's, we have section change */
-      _handle_namedsection(handler, named_pre, named_post, schema);
+      _handle_namedsection(handler, pre_db, post_db, named_pre, named_post);
     }
 
     if (cmp_sections <= 0) {
@@ -347,9 +328,9 @@ _delta_section(struct cfg_delta_handler *handler,
  */
 static void
 _handle_namedsection(struct cfg_delta_handler *handler,
-    struct cfg_named_section *pre_change, struct cfg_named_section *post_change,
-    struct cfg_schema_section *schema_section) {
-  if (_setup_filterresults(handler, pre_change, post_change, schema_section)) {
+    struct cfg_db *pre_db, struct cfg_db *post_db,
+    struct cfg_named_section *pre_change, struct cfg_named_section *post_change) {
+  if (_setup_filterresults(handler, pre_db, post_db, pre_change, post_change)) {
     handler->pre = pre_change;
     handler->post = post_change;
 
@@ -373,8 +354,8 @@ _handle_namedsection(struct cfg_delta_handler *handler,
  */
 static bool
 _setup_filterresults(struct cfg_delta_handler *handler,
-    struct cfg_named_section *pre_change, struct cfg_named_section *post_change,
-    struct cfg_schema_section *schema) {
+    struct cfg_db *pre_db, struct cfg_db *post_db,
+    struct cfg_named_section *pre_change, struct cfg_named_section *post_change) {
   struct cfg_entry *pre, *post;
   bool change;
   size_t i;
@@ -395,7 +376,7 @@ _setup_filterresults(struct cfg_delta_handler *handler,
       handler->filter[i].pre = pre;
       handler->filter[i].post = post;
 
-      handler->filter[i].changed = _compare_db_keyvalue_pair(pre, post, schema);
+      handler->filter[i].changed = _compare_db_keyvalue_pair(pre_db, post_db, pre, post);
       change |= handler->filter[i].changed;
     }
     return change;
@@ -417,19 +398,19 @@ _setup_filterresults(struct cfg_delta_handler *handler,
 
     if (cmp_entries < 0) {
       /* handle pre */
-      if (_compare_db_keyvalue_pair(pre, NULL, schema)) {
+      if (_compare_db_keyvalue_pair(pre_db, post_db, pre, NULL)) {
         return true;
       }
     }
     else if (cmp_entries > 0) {
       /* handle post */
-      if (_compare_db_keyvalue_pair(NULL, post, schema)) {
+      if (_compare_db_keyvalue_pair(pre_db, post_db, NULL, post)) {
         return true;
       }
     }
     else {
       /* entry is available in both db's, we might have change */
-      if (_compare_db_keyvalue_pair(pre, post, schema)) {
+      if (_compare_db_keyvalue_pair(pre_db, post_db, pre, post)) {
         return true;
       }
     }
@@ -455,52 +436,43 @@ _setup_filterresults(struct cfg_delta_handler *handler,
  * @return true if both entries are different
  */
 static bool
-_compare_db_keyvalue_pair(struct cfg_entry *pre, struct cfg_entry *post,
-    struct cfg_schema_section *schema) {
-  const char *_EMPTY = "";
-  struct cfg_schema_entry *schema_entry;
-  const char *pre_value, *post_value;
-  size_t pre_len, post_len;
+_compare_db_keyvalue_pair(struct cfg_db *pre_db, struct cfg_db *post_db,
+    struct cfg_entry *pre, struct cfg_entry *post) {
+  const struct const_strarray *pre_value, *post_value;
+  const char *type, *name, *entry;
 
   if (pre == NULL && post == NULL) {
     return false;
   }
 
-  pre_value = _EMPTY;
-  pre_len = 0;
-  post_value = _EMPTY;
-  post_len = 0;
+  pre_value = NULL;
+  post_value = NULL;
 
   if (pre) {
-    /* get value */
-    pre_value = pre->val.value;
-    pre_len = pre->val.length;
+    type = pre->named_section->section_type->type,
+    name = pre->named_section->name,
+    entry = pre->name;
   }
-  else if(schema) {
-    /* look for default value */
-    schema_entry = cfg_schema_find_entry(schema, post->name);
-    if (schema_entry) {
-      pre_value = schema_entry->t_default;
-      pre_len = strlen(pre_value) + 1;
-    }
+  else {
+    type = post->named_section->section_type->type,
+    name = post->named_section->name,
+    entry = post->name;
   }
 
-  if (post) {
-    /* get value */
-    post_value = post->val.value;
-    post_len = post->val.length;
+  if (pre_db) {
+    pre_value = cfg_db_get_entry_value(pre_db, type, name, entry);
   }
-  else if(schema) {
-    /* look for default value */
-    schema_entry = cfg_schema_find_entry(schema, pre->name);
-    if (schema_entry) {
-      post_value = schema_entry->t_default;
-      post_len = strlen(post_value) + 1;
-    }
+  post_value = cfg_db_get_entry_value(post_db, type, name, entry);
+
+  if (pre_value == NULL && post_value == NULL)
+    return false;
+
+  if (pre_value == NULL || post_value == NULL) {
+    return true;
   }
 
-  return  (pre_len != post_len)
-      || (memcmp(pre_value, post_value, pre_len) != 0);
+  return  pre_value->length != post_value->length
+      || (memcmp(pre_value->value, post_value->value, pre_value->length) != 0);
 }
 
 /**
index 3edfa94..4b15bd8 100644 (file)
 static bool _validate_cfg_entry(struct cfg_schema_section *schema_section,
     struct cfg_db *db, struct cfg_section_type *section,
     struct cfg_named_section *named, struct cfg_entry *entry,
-    const char *section_name, bool cleanup, bool failFast,
-    struct autobuf *out);
+    const char *section_name, bool cleanup, struct autobuf *out);
 static bool
 _check_missing_entries(struct cfg_schema_section *schema_section,
     struct cfg_db *db, struct cfg_section_type *section,
     struct cfg_named_section *named,
-    bool failFast, const char *section_name, struct autobuf *out);
-static bool
-_check_single_value(struct cfg_schema_entry *schema_entry,
-    struct cfg_db *db, struct cfg_section_type *section,
-    struct cfg_named_section *named, struct cfg_entry *entry,
-    bool cleanup, const char *section_name, struct autobuf *out);
+    const char *section_name, struct autobuf *out);
+static bool _extract_netaddr_filter(const struct cfg_schema_entry *entry,
+    int *address_family_1, int *address_family_2);
 
 const char *CFGLIST_BOOL_TRUE[] = { "true", "1", "on", "yes" };
 const char *CFGLIST_BOOL[] = { "true", "1", "on", "yes", "false", "0", "off", "no" };
@@ -80,7 +76,7 @@ const char *CFGLIST_BOOL[] = { "true", "1", "on", "yes", "false", "0", "off", "n
  */
 void
 cfg_schema_add(struct cfg_schema *schema) {
-  avl_init(&schema->sections, cfg_avlcmp_keys, false, NULL);
+  avl_init(&schema->sections, cfg_avlcmp_keys, true, NULL);
 }
 
 /**
@@ -105,16 +101,16 @@ cfg_schema_remove(struct cfg_schema *schema) {
  */
 int
 cfg_schema_add_section(struct cfg_schema *schema, struct cfg_schema_section *section) {
-  assert (cfg_is_allowed_key(section->t_type));
+  assert (cfg_is_allowed_key(section->type));
 
-  section->node.key = section->t_type;
-  if (avl_insert(&schema->sections, &section->node)) {
+  section->_node.key = section->type;
+  if (avl_insert(&schema->sections, &section->_node)) {
     /* name collision */
-    section->node.key = NULL;
+    section->_node.key = NULL;
     return -1;
   }
 
-  avl_init(&section->entries, cfg_avlcmp_keys, false, NULL);
+  avl_init(&section->_entries, cfg_avlcmp_keys, false, NULL);
   return 0;
 }
 
@@ -127,22 +123,22 @@ void
 cfg_schema_remove_section(struct cfg_schema *schema, struct cfg_schema_section *section) {
   struct cfg_schema_entry *entry, *ent_it;
 
-  if (section->node.key) {
-    /* kill entries of section_schema */
+  if (section->_node.key) {
+    /* kill _entries of section_schema */
     CFG_FOR_ALL_SCHEMA_ENTRIES(section, entry, ent_it) {
       cfg_schema_remove_entry(section, entry);
     }
 
-    avl_remove(&schema->sections, &section->node);
-    section->node.key = NULL;
+    avl_remove(&schema->sections, &section->_node);
+    section->_node.key = NULL;
   }
 }
 
 /**
- * Adds a series of entries to a schema section
+ * Adds a series of _entries to a schema section
  * @param section pointer to section
- * @param entries pointer to array of entries
- * @param e_cnt number of array entries
+ * @param _entries pointer to array of _entries
+ * @param e_cnt number of array _entries
  * @return -1 if an error happened, 0 otherwise
  */
 int
@@ -161,29 +157,32 @@ cfg_schema_add_entries(struct cfg_schema_section *section,
 }
 
 /**
- * Adds a single entry to a schema section
+ * Adds a single entry to a schema section, section must have
+ * already be added to the schema.
  * @param section pointer to section
  * @param entry pointer to entry
  * @return -1 if an error happened, 0 otherwise
  */
 int
 cfg_schema_add_entry(struct cfg_schema_section *section, struct cfg_schema_entry *entry) {
-  assert (cfg_is_allowed_key(entry->t_name));
+  assert (cfg_is_allowed_key(entry->name));
+  assert (avl_is_node_added(&section->_node));
 
-  entry->node.key = &entry->t_name[0];
-  if (avl_insert(&section->entries, &entry->node)) {
+  entry->_node.key = &entry->name[0];
+  if (avl_insert(&section->_entries, &entry->_node)) {
     /* name collision */
-    entry->node.key = NULL;
+    entry->_node.key = NULL;
     return -1;
   }
+
   return 0;
 }
 
 /**
- * Remove an array of entries from a schema section
+ * Remove an array of _entries from a schema section
  * @param section pointer to section
- * @param entries pointer to array of entries
- * @param e_cnt number of array entries
+ * @param _entries pointer to array of _entries
+ * @param e_cnt number of array _entries
  */
 void
 cfg_schema_remove_entries(struct cfg_schema_section *section, struct cfg_schema_entry *entries, size_t e_cnt) {
@@ -197,7 +196,6 @@ cfg_schema_remove_entries(struct cfg_schema_section *section, struct cfg_schema_
 /**
  * Validates a database with a schema
  * @param db pointer to configuration database
- * @param failFast if true, validation stops at the first error
  * @param cleanup if true, bad values will be removed from the database
  * @param ignore_unknown_sections true if the validation should skip sections
  *   in the database that have no schema.
@@ -206,7 +204,7 @@ cfg_schema_remove_entries(struct cfg_schema_section *section, struct cfg_schema_
  */
 int
 cfg_schema_validate(struct cfg_db *db,
-    bool failFast, bool cleanup, bool ignore_unknown_sections,
+    bool cleanup, bool ignore_unknown_sections,
     struct autobuf *out) {
   char section_name[256];
   struct cfg_section_type *section, *section_it;
@@ -214,6 +212,7 @@ cfg_schema_validate(struct cfg_db *db,
   struct cfg_entry *entry, *entry_it;
 
   struct cfg_schema_section *schema_section, *schema_section_it;
+  struct cfg_schema_section *schema_section_first, *schema_section_last;
 
   bool error = false;
   bool warning = false;
@@ -225,8 +224,10 @@ cfg_schema_validate(struct cfg_db *db,
 
   CFG_FOR_ALL_SECTION_TYPES(db, section, section_it) {
     /* check for missing schema sections */
-    schema_section = cfg_schema_find_section(db->schema, section->type);
-    if (schema_section == NULL) {
+    schema_section_first = avl_find_element(&db->schema->sections, section->type,
+        schema_section_first, _node);
+
+    if (schema_section_first == NULL) {
       if (ignore_unknown_sections) {
         continue;
       }
@@ -237,114 +238,92 @@ cfg_schema_validate(struct cfg_db *db,
       if (cleanup) {
         cfg_db_remove_sectiontype(db, section->type);
       }
-      if (failFast) {
-        /* stop here */
-        return -1;
-      }
 
       error |= true;
       continue;
     }
 
-    /* check data of named sections in db */
-    CFG_FOR_ALL_SECTION_NAMES(section, named, named_it) {
-      warning = false;
-      hasName = cfg_db_is_named_section(named);
+    schema_section_last = avl_find_le_element(&db->schema->sections, section->type,
+        schema_section_last, _node);
 
-      if (schema_section->t_named && !hasName) {
-        cfg_append_printable_line(out, "The section type '%s' demands a name", section->type);
+    /* iterate over all schema for a certain section type */
+    avl_for_element_range(schema_section_first, schema_section_last, schema_section, _node) {
+      /* check data of named sections in db */
+      CFG_FOR_ALL_SECTION_NAMES(section, named, named_it) {
+        warning = false;
+        hasName = cfg_db_is_named_section(named);
 
-        warning = true;
-      }
-      else if (!schema_section->t_named && hasName) {
-        cfg_append_printable_line(out, "The section type '%s'"
-            " has to be used without a name"
-            " ('%s' was given as a name)", section->type, named->name);
+        if (schema_section->named && !hasName) {
+          cfg_append_printable_line(out, "The section type '%s' demands a name", section->type);
 
-        warning = true;
-      }
+          warning = true;
+        }
+        else if (!schema_section->named && hasName) {
+          cfg_append_printable_line(out, "The section type '%s'"
+              " has to be used without a name"
+              " ('%s' was given as a name)", section->type, named->name);
 
-      if (hasName && !cfg_is_allowed_key(named->name)) {
-        cfg_append_printable_line(out, "The section name '%s' for"
-            " type '%s' contains illegal characters",
-            named->name, section->type);
-        warning = true;
-      }
+          warning = true;
+        }
 
-      /* test abort condition */
-      if (warning && cleanup) {
-        /* remove bad named section */
-        cfg_db_remove_namedsection(db, section->type, named->name);
-      }
+        if (hasName && !cfg_is_allowed_key(named->name)) {
+          cfg_append_printable_line(out, "The section name '%s' for"
+              " type '%s' contains illegal characters",
+              named->name, section->type);
+          warning = true;
+        }
 
-      if (warning && failFast) {
-        /* stop here */
-        break;
-      }
-      error |= warning;
+        /* test abort condition */
+        if (warning && cleanup) {
+          /* remove bad named section */
+          cfg_db_remove_namedsection(db, section->type, named->name);
+        }
 
-      if (warning) {
-        continue;
-      }
+        error |= warning;
 
-      /* initialize section_name field for validate */
-      snprintf(section_name, sizeof(section_name), "'%s%s%s'",
-          section->type, hasName ? "=" : "", hasName ? named->name : "");
-
-      /* check for bad values */
-      CFG_FOR_ALL_ENTRIES(named, entry, entry_it) {
-        warning = _validate_cfg_entry(schema_section,
-            db, section, named, entry, section_name,
-            cleanup, failFast, out);
-        if (warning && failFast) {
-          /* stop here */
-          return -1;
+        if (warning) {
+          continue;
+        }
+
+        /* initialize section_name field for validate */
+        snprintf(section_name, sizeof(section_name), "'%s%s%s'",
+            section->type, hasName ? "=" : "", hasName ? named->name : "");
+
+        /* check for bad values */
+        CFG_FOR_ALL_ENTRIES(named, entry, entry_it) {
+          warning = _validate_cfg_entry(schema_section,
+              db, section, named, entry, section_name,
+              cleanup, out);
+          error |= warning;
         }
-        error |= warning;
-      }
 
-      if (schema_section->t_validate) {
-        if (schema_section->t_validate(schema_section, section_name, named, out)) {
-          if (failFast) {
-            /* stop here */
-            return -1;
+        if (schema_section->cb_validate) {
+          if (schema_section->cb_validate(schema_section, section_name, named, out)) {
+            error = true;
           }
-          error = true;
         }
+        /* check for missing values */
+        warning = _check_missing_entries(schema_section, db, section, named, section_name, out);
+        error |= warning;
       }
-      /* check for missing values */
-      warning = _check_missing_entries(schema_section, db, section, named, failFast, section_name, out);
-      if (warning && failFast) {
-        /* stop here */
-        return -1;
-      }
-      error |= warning;
     }
-
     if (cleanup && avl_is_empty(&section->names)) {
       /* if section type is empty, remove it too */
       cfg_db_remove_sectiontype(db, section->type);
     }
-    if (warning && failFast) {
-      return -1;
-    }
   }
 
   /* search for missing mandatory sections */
   CFG_FOR_ALL_SCHEMA_SECTIONS(db->schema, schema_section, schema_section_it) {
-    if (!schema_section->t_mandatory) {
+    if (!schema_section->mandatory) {
       continue;
     }
 
-    section = cfg_db_find_sectiontype(db, schema_section->t_type);
+    section = cfg_db_find_sectiontype(db, schema_section->type);
     warning = section == NULL || avl_is_empty(&section->names);
     if (warning) {
       cfg_append_printable_line(out, "Missing mandatory section of type '%s'",
-          schema_section->t_type);
-    }
-    if (warning && failFast) {
-      /* stop here */
-      return -1;
+          schema_section->type);
     }
     error |= warning;
   }
@@ -352,13 +331,13 @@ cfg_schema_validate(struct cfg_db *db,
 }
 
 /**
- * Convert the entries of a db section into binary representation by
+ * Convert the _entries of a db section into binary representation by
  * using the mappings defined in a schema section. The function assumes
  * that the section was already validated.
  * @param target pointer to target binary buffer
  * @param named pointer to named section
- * @param entries pointer to array of schema entries
- * @param count number of schema entries
+ * @param _entries pointer to array of schema _entries
+ * @param count number of schema _entries
  * @return 0 if conversion was successful, -1 if an error happened.
  *   An error might result in a partial initialized target buffer.
  */
@@ -367,39 +346,28 @@ cfg_schema_tobin(void *target, struct cfg_named_section *named,
     const struct cfg_schema_entry *entries, size_t count) {
   char *ptr;
   size_t i;
-  struct strarray default_array, *value;
+  const struct const_strarray *value;
 
   ptr = (char *)target;
 
   for (i=0; i<count; i++) {
-    if (entries[i].t_to_binary == NULL) {
+    if (entries[i].cb_to_binary == NULL) {
       continue;
     }
 
     /* cleanup pointer */
-    value = NULL;
-
     if (named) {
-      struct cfg_entry *db_entry;
-      db_entry = avl_find_element(&named->entries, entries[i].t_name, db_entry, node);
-      if (db_entry) {
-        value = &db_entry->val;
-      }
+      value = cfg_db_get_entry_value(
+          named->section_type->db,
+          named->section_type->type,
+          named->name,
+          entries[i].name);
     }
-
-    if (value == NULL) {
-      if (entries[i].t_default == NULL) {
-        /* missing mandatory entry */
-        return -1;
-      }
-      memcpy(&default_array.value, &entries[i].t_default, sizeof(default_array.value));
-      default_array.last_value = default_array.value;
-      default_array.length = strlen(default_array.value);
-
-      value = &default_array;
+    else {
+      value = &entries[i].def;
     }
 
-    if (entries[i].t_to_binary(&entries[i], value, ptr + entries[i].t_offset)) {
+    if (entries[i].cb_to_binary(&entries[i], value, ptr + entries[i].t_offset)) {
       /* error in conversion */
       return -1;
     }
@@ -419,17 +387,10 @@ cfg_schema_tobin(void *target, struct cfg_named_section *named,
 int
 cfg_schema_validate_strlen(const struct cfg_schema_entry *entry,
     const char *section_name, const char *value, struct autobuf *out) {
-  if (value == NULL) {
-    if (entry->t_validate_params.p_i1 < INT32_MAX) {
-      cfg_append_printable_line(out, "    Parameter must have a maximum length of %d characters",
-          entry->t_validate_params.p_i1);
-    }
-    return 0;
-  }
-  if ((int)strlen(value) > entry->t_validate_params.p_i1) {
+  if ((int)strlen(value) > entry->validate_params.p_i1) {
     cfg_append_printable_line(out, "Value '%s' for entry '%s'"
         " in section %s is longer than %d characters",
-        value, entry->t_name, section_name, entry->t_validate_params.p_i1);
+        value, entry->name, section_name, entry->validate_params.p_i1);
     return 1;
   }
   return 0;
@@ -452,15 +413,11 @@ cfg_schema_validate_printable(const struct cfg_schema_entry *entry,
   if (cfg_schema_validate_strlen(entry, section_name, value, out)) {
     return 1;
   }
-  if (value == NULL) {
-    cfg_append_printable_line(out, "    Parameter must only contain printable characters.");
-    return 0;
-  }
   if (!cfg_is_printable(value)) {
     /* not a printable ascii character */
     cfg_append_printable_line(out, "Value '%s' for entry '%s'"
         " in section %s has has non-printable characters",
-        value, entry->t_name, section_name);
+        value, entry->name, section_name);
     return 1;
 
   }
@@ -480,28 +437,17 @@ cfg_schema_validate_printable(const struct cfg_schema_entry *entry,
 int
 cfg_schema_validate_choice(const struct cfg_schema_entry *entry,
     const char *section_name, const char *value, struct autobuf *out) {
-  const char **list = entry->t_validate_params.p_ptr;
+  const char **list = entry->validate_params.p_ptr;
   int i;
 
-  if (value == NULL) {
-    cfg_append_printable_line(out, "    Parameter must be on of the following list:");
-
-    abuf_puts(out, "    ");
-    for (i=0; i < entry->t_validate_params.p_i1; i++) {
-      abuf_appendf(out, "%s'%s'",
-          i==0 ? "" : ", ", list[i]);
-    }
-    abuf_puts(out, "\n");
-    return 0;
-  }
-  i = cfg_get_choice_index(value, list, (size_t)entry->t_validate_params.p_i1);
+  i = cfg_get_choice_index(value, list, (size_t)entry->validate_params.p_i1);
   if (i >= 0) {
     return 0;
   }
 
   cfg_append_printable_line(out, "Unknown value '%s'"
       " for entry '%s' in section %s",
-      value, entry->t_name, section_name);
+      value, entry->name, section_name);
   return -1;
 }
 
@@ -520,24 +466,18 @@ cfg_schema_validate_int(const struct cfg_schema_entry *entry,
   int32_t i;
   char *endptr = NULL;
 
-  if (value == NULL) {
-    cfg_append_printable_line(out, "    Parameter must be an integer between %d and %d",
-        entry->t_validate_params.p_i1, entry->t_validate_params.p_i2);
-    return 0;
-  }
-
   i = strtol(value, &endptr, 10);
   if (endptr == NULL || *endptr != 0) {
     cfg_append_printable_line(out, "Value '%s' for entry '%s'"
         " in section %s is not an integer",
-        value, entry->t_name, section_name);
+        value, entry->name, section_name);
     return 1;
   }
-  if (i < entry->t_validate_params.p_i1 || i > entry->t_validate_params.p_i2) {
+  if (i < entry->validate_params.p_i1 || i > entry->validate_params.p_i2) {
     cfg_append_printable_line(out, "Value '%s' for entry '%s' in section %s is "
         "not between %d and %d",
-        value, entry->t_name, section_name,
-        entry->t_validate_params.p_i1, entry->t_validate_params.p_i2);
+        value, entry->name, section_name,
+        entry->validate_params.p_i1, entry->validate_params.p_i2);
     return 1;
   }
   return 0;
@@ -557,59 +497,15 @@ cfg_schema_validate_netaddr(const struct cfg_schema_entry *entry,
     const char *section_name, const char *value, struct autobuf *out) {
   struct netaddr addr;
   bool prefix = false;
-  int p1,p2;
+  int af1, af2;
   uint8_t max_prefix;
 
-  p1 = entry->t_validate_params.p_i1;
-  p2 = entry->t_validate_params.p_i2;
-
-  /* check if we may accept a prefix */
-  if (p1 < 0) {
-    prefix = true;
-    p1 = -p1;
-  }
-  if (p2 < 0) {
-    prefix = true;
-    p2 = -p2;
-
-    /* explicit 'all addresses, but no prefix' case */
-    if (p1 == 0) {
-      p2 = 0;
-    }
-  }
-
-  if (value == NULL) {
-    const char *p_string = prefix ? " with optional prefix string" : "";
-
-    switch (p1) {
-      case AF_INET:
-        cfg_append_printable_line(out, "    Parameter must be an IPv4%s address%s",
-            p2 == AF_INET6 ? " or IPv6" : "", p_string);
-        break;
-      case AF_INET6:
-        cfg_append_printable_line(out, "    Parameter must be an IPv6 address%s",
-            p_string);
-        break;
-      case AF_MAC48:
-        cfg_append_printable_line(out, "    Parameter must be an MAC-48%s address%s",
-            p2 == AF_EUI64 ? " or EUI64" : "", p_string);
-        break;
-      case AF_EUI64:
-        cfg_append_printable_line(out, "    Parameter must be an EUI-64 address%s",
-            p_string);
-        break;
-      default:
-        cfg_append_printable_line(out, "    Parameter must be an IPv4, "
-            "IPv6, MAC-48 or EUI-64 address%s", p_string);
-        break;
-    }
-    return 0;
-  }
+  prefix = _extract_netaddr_filter(entry, &af1, &af2);
 
   if (netaddr_from_string(&addr, value)) {
     cfg_append_printable_line(out, "Value '%s' for entry '%s'"
         " in section %s is no valid network address",
-        value, entry->t_name, section_name);
+        value, entry->name, section_name);
     return -1;
   }
 
@@ -619,33 +515,140 @@ cfg_schema_validate_netaddr(const struct cfg_schema_entry *entry,
   if (addr.prefix_len > max_prefix) {
     cfg_append_printable_line(out, "Value '%s' for entry '%s'"
         " in section %s has an illegal prefix length",
-        value, entry->t_name, section_name);
+        value, entry->name, section_name);
     return -1;
   }
   if (!prefix && addr.prefix_len != max_prefix) {
     cfg_append_printable_line(out, "Value '%s' for entry '%s'"
         " in section %s must be a single address, not a prefix",
-        value, entry->t_name, section_name);
+        value, entry->name, section_name);
     return -1;
   }
 
-  if (p1 == 0) {
+  if (af1 == 0) {
     /* no further type check */
     return 0;
   }
 
   /* check address type */
-  if ((p2 != 0 && p2 == addr.type) || (p1 == addr.type)) {
+  if ((af2 != 0 && af2 == addr.type) || (af1 == addr.type)) {
     return 0;
   }
 
   /* at least one condition was set, but no one matched */
   cfg_append_printable_line(out, "Value '%s' for entry '%s'"
       " in section '%s' is wrong address type",
-      value, entry->t_name, section_name);
+      value, entry->name, section_name);
   return -1;
 }
 
+/**
+ * Help generator for string maximum length validator.
+ * See CFG_VALIDATE_STRING_LEN macro in cfg_schema.h
+ * @param entry pointer to schema entry
+ * @param out pointer to autobuffer for help output
+ */
+void
+cfg_schema_help_strlen(
+    const struct cfg_schema_entry *entry, struct autobuf *out) {
+  if (entry->validate_params.p_i1 < INT32_MAX) {
+    cfg_append_printable_line(out, "    Parameter must have a maximum length of %d characters",
+        entry->validate_params.p_i1);
+  }
+}
+
+/**
+ * Help generator for strings printable characters
+ * and a maximum length validator.
+ * See CFG_VALIDATE_PRINTABLE() and CFG_VALIDATE_PRINTABLE_LEN()
+ * macro in cfg_schema.h
+ * @param entry pointer to schema entry
+ * @param value value of schema entry
+ * @param out pointer to autobuffer for validator output
+ */
+void
+cfg_schema_help_printable(
+    const struct cfg_schema_entry *entry, struct autobuf *out) {
+  cfg_schema_help_printable(entry, out);
+  cfg_append_printable_line(out, "    Parameter must only contain printable characters.");
+}
+
+/**
+ * Help generator for choice (list of possible strings) validator
+ * List selection will be case insensitive.
+ * See CFG_VALIDATE_CHOICE() macro in cfg_schema.h
+ * @param entry pointer to schema entry
+ * @param out pointer to autobuffer for validator output
+ */
+void
+cfg_schema_help_choice(
+    const struct cfg_schema_entry *entry, struct autobuf *out) {
+  const char **list = entry->validate_params.p_ptr;
+  int i;
+
+  cfg_append_printable_line(out, "    Parameter must be on of the following list:");
+
+  abuf_puts(out, "    ");
+  for (i=0; i < entry->validate_params.p_i1; i++) {
+    abuf_appendf(out, "%s'%s'",
+        i==0 ? "" : ", ", list[i]);
+  }
+  abuf_puts(out, "\n");
+}
+
+/**
+ * Help generator for integer validator.
+ * See CFG_VALIDATE_INT() and CFG_VALIDATE_INT_MINMAX() macro in cfg_schema.h
+ * @param entry pointer to schema entry
+ * @param out pointer to autobuffer for validator output
+ */
+void
+cfg_schema_help_int(
+    const struct cfg_schema_entry *entry, struct autobuf *out) {
+  cfg_append_printable_line(out, "    Parameter must be an integer between %d and %d",
+      entry->validate_params.p_i1, entry->validate_params.p_i2);
+}
+
+/**
+ * Help generator for network addresses and prefixes validator.
+ * See CFG_VALIDATE_NETADDR_*() macros in cfg_schema.h
+ * @param entry pointer to schema entry
+ * @param out pointer to autobuffer for validator output
+ */
+void
+cfg_schema_help_netaddr(
+    const struct cfg_schema_entry *entry, struct autobuf *out) {
+  const char *p_string;
+  bool prefix = false;
+  int af1,af2;
+
+  prefix = _extract_netaddr_filter(entry, &af1, &af2);
+  p_string = prefix ? " with optional prefix string" : "";
+
+  switch (af1) {
+    case AF_INET:
+      cfg_append_printable_line(out, "    Parameter must be an IPv4%s address%s",
+          af2 == AF_INET6 ? " or IPv6" : "", p_string);
+      break;
+    case AF_INET6:
+      cfg_append_printable_line(out, "    Parameter must be an IPv6 address%s",
+          p_string);
+      break;
+    case AF_MAC48:
+      cfg_append_printable_line(out, "    Parameter must be an MAC-48%s address%s",
+          af2 == AF_EUI64 ? " or EUI64" : "", p_string);
+      break;
+    case AF_EUI64:
+      cfg_append_printable_line(out, "    Parameter must be an EUI-64 address%s",
+          p_string);
+      break;
+    default:
+      cfg_append_printable_line(out, "    Parameter must be an IPv4, "
+          "IPv6, MAC-48 or EUI-64 address%s", p_string);
+      break;
+  }
+}
+
 /**
  * Binary converter for string pointers. This validator will
  * allocate additional memory for the string.
@@ -658,7 +661,7 @@ cfg_schema_validate_netaddr(const struct cfg_schema_entry *entry,
  */
 int
 cfg_schema_tobin_strptr(const struct cfg_schema_entry *s_entry __attribute__((unused)),
-    struct strarray *value, void *reference) {
+    const struct const_strarray *value, void *reference) {
   char **ptr;
 
   ptr = (char **)reference;
@@ -666,7 +669,7 @@ cfg_schema_tobin_strptr(const struct cfg_schema_entry *s_entry __attribute__((un
     free(*ptr);
   }
 
-  *ptr = strdup(strarray_get_last(value));
+  *ptr = strdup(strarray_get_first_c(value));
   return *ptr == NULL ? -1 : 0;
 }
 
@@ -680,12 +683,12 @@ cfg_schema_tobin_strptr(const struct cfg_schema_entry *s_entry __attribute__((un
  */
 int
 cfg_schema_tobin_strarray(const struct cfg_schema_entry *s_entry,
-    struct strarray *value, void *reference) {
+    const struct const_strarray *value, void *reference) {
   char *ptr;
 
   ptr = (char *)reference;
 
-  strscpy(ptr, strarray_get_last(value), (size_t)s_entry->t_validate_params.p_i1);
+  strscpy(ptr, strarray_get_first_c(value), (size_t)s_entry->validate_params.p_i1);
   return 0;
 }
 
@@ -700,14 +703,14 @@ cfg_schema_tobin_strarray(const struct cfg_schema_entry *s_entry,
  */
 int
 cfg_schema_tobin_choice(const struct cfg_schema_entry *s_entry,
-    struct strarray *value, void *reference) {
+    const struct const_strarray *value, void *reference) {
   int *ptr;
 
   ptr = (int *)reference;
 
-  *ptr = cfg_get_choice_index(strarray_get_last(value),
-      s_entry->t_validate_params.p_ptr,
-      (size_t)s_entry->t_validate_params.p_i1);
+  *ptr = cfg_get_choice_index(strarray_get_first_c(value),
+      s_entry->validate_params.p_ptr,
+      (size_t)s_entry->validate_params.p_i1);
   return 0;
 }
 
@@ -721,12 +724,12 @@ cfg_schema_tobin_choice(const struct cfg_schema_entry *s_entry,
  */
 int
 cfg_schema_tobin_int(const struct cfg_schema_entry *s_entry __attribute__((unused)),
-    struct strarray *value, void *reference) {
+    const struct const_strarray *value, void *reference) {
   int *ptr;
 
   ptr = (int *)reference;
 
-  *ptr = strtol(strarray_get_last(value), NULL, 10);
+  *ptr = strtol(strarray_get_first_c(value), NULL, 10);
   return 0;
 }
 
@@ -739,12 +742,12 @@ cfg_schema_tobin_int(const struct cfg_schema_entry *s_entry __attribute__((unuse
  * @return 0 if conversion succeeded, -1 otherwise.
  */int
 cfg_schema_tobin_netaddr(const struct cfg_schema_entry *s_entry __attribute__((unused)),
-    struct strarray *value, void *reference) {
+    const struct const_strarray *value, void *reference) {
   struct netaddr *ptr;
 
   ptr = (struct netaddr *)reference;
 
-  return netaddr_from_string(ptr, strarray_get_last(value));
+  return netaddr_from_string(ptr, strarray_get_first_c(value));
 }
 
  /**
@@ -757,12 +760,12 @@ cfg_schema_tobin_netaddr(const struct cfg_schema_entry *s_entry __attribute__((u
   */
 int
 cfg_schema_tobin_bool(const struct cfg_schema_entry *s_entry __attribute__((unused)),
-    struct strarray *value, void *reference) {
+    const struct const_strarray *value, void *reference) {
   bool *ptr;
 
   ptr = (bool *)reference;
 
-  *ptr = cfg_get_bool(strarray_get_last(value));
+  *ptr = cfg_get_bool(strarray_get_first_c(value));
   return 0;
 }
 
@@ -776,12 +779,12 @@ cfg_schema_tobin_bool(const struct cfg_schema_entry *s_entry __attribute__((unus
  */
 int
 cfg_schema_tobin_stringlist(const struct cfg_schema_entry *s_entry __attribute__((unused)),
-    struct strarray *value, void *reference) {
+    const struct const_strarray *value, void *reference) {
   struct strarray *array;
 
   array = (struct strarray *)reference;
 
-  return strarray_copy(array, value);
+  return strarray_copy_c(array, value);
 }
 
 /**
@@ -792,9 +795,7 @@ cfg_schema_tobin_stringlist(const struct cfg_schema_entry *s_entry __attribute__
  * @param named pointer to named section
  * @param entry pointer to configuration entry
  * @param section_name name of section including type (for debug output)
- * @param cleanup true if bad entries should be removed
- * @param failFast true if fail on first error instead of validating
- *   more list entries.
+ * @param cleanup true if bad _entries should be removed
  * @param out error output buffer
  * @return true if an error happened, false otherwise
  */
@@ -802,12 +803,10 @@ static bool
 _validate_cfg_entry(struct cfg_schema_section *schema_section,
     struct cfg_db *db, struct cfg_section_type *section,
     struct cfg_named_section *named, struct cfg_entry *entry,
-    const char *section_name, bool cleanup, bool failFast,
-    struct autobuf *out) {
+    const char *section_name, bool cleanup, struct autobuf *out) {
   struct cfg_schema_entry *schema_entry;
   bool warning = false;
-  char *ptr1 = NULL, *ptr2 = NULL;
-  size_t size;
+  char *ptr1 = NULL;
 
   schema_entry = cfg_schema_find_entry(schema_section, entry->name);
 
@@ -817,60 +816,35 @@ _validate_cfg_entry(struct cfg_schema_section *schema_section,
     return true;
   }
 
-  if (!schema_entry->t_list) {
-    return _check_single_value(schema_entry,
-        db, section, named, entry,
-        cleanup, section_name, out);
-  }
-
-  if (cleanup) {
-    /* first remove duplicate entries */
-    FOR_ALL_STRINGS(&entry->val, ptr1) {
-      /* get pointer to next element */
-      ptr2 = ptr1 + strlen(ptr1)+1;
-
-      /* compare list value to any later value */
-      while (ptr2 <= strarray_get_last(&entry->val)) {
-        if (strcmp(ptr2, ptr1) == 0) {
-          /* duplicate found, remove it */
-
-          strarray_remove_ext(&entry->val, ptr2, false);
-        }
-        else {
-          ptr2 = strarray_get_next(&entry->val, ptr2);
-        }
-      }
-    }
+  if (schema_entry->cb_validate == NULL) {
+    return false;
   }
 
   /* now validate syntax */
   ptr1 = entry->val.value;
-  if (schema_entry->t_validate) {
-    while (ptr1 < entry->val.value + entry->val.length) {
-      if (schema_entry->t_validate(schema_entry, section_name, ptr1, out)) {
-        /* warning is generated by the validate callback itself */
-        warning = true;
-
-        if (failFast) {
-          return true;
-        }
-      }
+  while (ptr1 < entry->val.value + entry->val.length) {
+    if (schema_entry->cb_validate(schema_entry, section_name, ptr1, out)) {
+      /* warning is generated by the validate callback itself */
+      warning = true;
+    }
 
-      size = strlen(ptr1) + 1;
+    if (warning && cleanup) {
+      /* illegal entry found, remove it */
+      strarray_remove_ext(&entry->val, ptr1, false);
+    }
+    else {
+      ptr1 += strlen(ptr1) + 1;
+    }
 
-      if (warning && cleanup) {
-        /* illegal entry found, remove it */
-        size_t offset = (size_t)(ptr2 - entry->val.value);
-        memmove(ptr1, ptr1 + size, entry->val.length - size - offset);
-      }
-      else {
-        ptr1 += size;
-      }
+    if (!schema_entry->list) {
+      /* ignore the rest */
+      break;
     }
   }
 
-  if (entry->val.length == 0) {
-    /* remove empty entry */
+  if (strarray_is_empty(&entry->val)
+      || (!schema_entry->list && warning && cleanup)) {
+    /* remove entry */
     cfg_db_remove_entry(db, section->type, named->name, entry->name);
   }
 
@@ -878,49 +852,11 @@ _validate_cfg_entry(struct cfg_schema_section *schema_section,
 }
 
 /**
- * Checks configuration database entries which are not a list of values.
- * @param schema_entry pointer the schema of entry
- * @param db pointer to database
- * @param section pointer to database section type
- * @param named pointer to named section
- * @param entry pointer to configuration entry
- * @param cleanup true if bad values should be removed
- * @param section_name name of section including type (for debug output)
- * @param out error output buffer
- * @return true if an error happened, false otherwise
- */
-static bool
-_check_single_value(struct cfg_schema_entry *schema_entry,
-    struct cfg_db *db, struct cfg_section_type *section,
-    struct cfg_named_section *named, struct cfg_entry *entry,
-    bool cleanup, const char *section_name, struct autobuf *out) {
-  bool warning = false;
-
-  /* warning is generated by the validate callback itself */
-  if (schema_entry->t_validate) {
-    warning = schema_entry->t_validate(schema_entry, section_name, entry->val.last_value, out) != 0;
-  }
-
-  if (warning && cleanup) {
-    /* remove bad entry */
-    cfg_db_remove_entry(db, section->type, named->name, entry->name);
-  }
-  else if (cleanup && entry->val.last_value != entry->val.value) {
-    /* shorten value */
-    entry->val.length = strlen(entry->val.last_value) + 1;
-    memmove(entry->val.value, entry->val.last_value, entry->val.length);
-  }
-  return warning;
-}
-
-/**
- * Checks a database section for missing mandatory entries
+ * Checks a database section for missing mandatory _entries
  * @param schema_section pointer to schema of section
  * @param db pointer to database
  * @param section pointer to database section type
  * @param named pointer to named section
- * @param failFast true if fail on first error instead of validating
- *   the rest of the section.
  * @param section_name name of section including type (for debug output)
  * @param out error output buffer
  * @return true if an error happened, false otherwise
@@ -929,7 +865,7 @@ static bool
 _check_missing_entries(struct cfg_schema_section *schema_section,
     struct cfg_db *db, struct cfg_section_type *section,
     struct cfg_named_section *named,
-    bool failFast, const char *section_name, struct autobuf *out) {
+    const char *section_name, struct autobuf *out) {
   struct cfg_schema_entry *schema_entry, *schema_entry_it;
   bool warning, error;
 
@@ -938,22 +874,54 @@ _check_missing_entries(struct cfg_schema_section *schema_section,
 
   /* check for missing values */
   CFG_FOR_ALL_SCHEMA_ENTRIES(schema_section, schema_entry, schema_entry_it) {
-    if (schema_entry->t_default != NULL) {
+    if (!strarray_is_empty_c(&schema_entry->def)) {
       continue;
     }
 
     /* mandatory parameter */
-    warning = !cfg_db_find_entry(db, section->type, named->name, schema_entry->t_name);
+    warning = !cfg_db_find_entry(db, section->type, named->name, schema_entry->name);
     error |= warning;
     if (warning) {
       cfg_append_printable_line(out, "Missing mandatory value for entry '%s' in section %s",
-          schema_entry->t_name, section_name);
-
-      if (failFast) {
-        /* stop here */
-        break;
-      }
+          schema_entry->name, section_name);
     }
   }
   return error;
 }
+
+/**
+ * Extract the encoded address families and the prefix flag
+ * from the parameters of a netaddr validator.
+ * @param entry pointer to schema entry
+ * @param address_family_1 pointer to address family 1 (return value)
+ * @param address_family_2 pointer to address family 2 (return value)
+ * @return true if the validator allows a prefix, false otherwise
+ */
+static bool
+_extract_netaddr_filter(const struct cfg_schema_entry *entry,
+    int *address_family_1, int *address_family_2) {
+  bool prefix = false;
+  int p1, p2;
+
+  p1 = entry->validate_params.p_i1;
+  p2 = entry->validate_params.p_i2;
+
+  /* check if we may accept a prefix */
+  if (p1 < 0) {
+    prefix = true;
+    p1 = -p1;
+  }
+  if (p2 < 0) {
+    prefix = true;
+    p2 = -p2;
+
+    /* explicit 'all addresses, but no prefix' case */
+    if (p1 == 0) {
+      p2 = 0;
+    }
+  }
+
+  *address_family_1 = p1;
+  *address_family_2 = p2;
+  return prefix;
+}
index 92c4c7f..c68bd2f 100644 (file)
@@ -63,59 +63,59 @@ struct cfg_schema_entry;
 #include "config/cfg_db.h"
 
 #if !defined(REMOVE_HELPTEXT)
-#define _CFG_VALIDATE(name, def, help, args...)                  { .t_name = (name), .t_default = (def), .t_help = (help), ##args }
+#define _CFG_VALIDATE(p_name, p_def, p_help,args...)                         { .name = (p_name), .def = { .value = (p_def), .length = sizeof(p_def)}, .help = (p_help), ##args }
 #else
-#define _CFG_VALIDATE(name, def, help, args...)                  { .t_name = (name), .t_default = (def), ##args }
+#define _CFG_VALIDATE(p_name, p_def, p_help,args...)                         { .name = (p_name), .def = { .value = (p_def), .length = sizeof(p_def)}, ##args }
 #endif
 
-#define CFG_VALIDATE_STRING(name, def, help, args...)                  _CFG_VALIDATE(name, def, help, ##args)
-#define CFG_VALIDATE_STRING_LEN(name, def, help, maxlen, args...)      _CFG_VALIDATE(name, def, help, .t_validate = cfg_schema_validate_strlen, .t_validate_params = {.p_i1 = (maxlen) }, ##args )
-#define CFG_VALIDATE_PRINTABLE(name, def, help, args...)               _CFG_VALIDATE(name, def, help, .t_validate = cfg_schema_validate_printable, .t_validate_params = {.p_i1 = INT32_MAX }, ##args )
-#define CFG_VALIDATE_PRINTABLE_LEN(name, def, help, maxlen, args...)   _CFG_VALIDATE(name, def, help, .t_validate = cfg_schema_validate_printable, .t_validate_params = {.p_i1 = (maxlen) }, ##args )
-#define CFG_VALIDATE_CHOICE(name, def, help, list, args...)            _CFG_VALIDATE(name, def, help, .t_validate = cfg_schema_validate_choice, .t_validate_params = {.p_ptr = (list), .p_i1 = ARRAYSIZE(list)}, ##args )
-#define CFG_VALIDATE_INT(name, def, help, args...)                     _CFG_VALIDATE(name, def, help, .t_validate = cfg_schema_validate_int, .t_validate_params = {.p_i1 = INT32_MIN, .p_i2 = INT32_MAX}, ##args )
-#define CFG_VALIDATE_INT_MINMAX(name, def, help, min, max, args...)    _CFG_VALIDATE(name, def, help, .t_validate = cfg_schema_validate_int, .t_validate_params = {.p_i1 = (min), .p_i2 = (max)}, ##args )
-#define CFG_VALIDATE_NETADDR(name, def, help, prefix, args...)         _CFG_VALIDATE(name, def, help, .t_validate = cfg_schema_validate_netaddr, .t_validate_params = {.p_i1 = 0, .p_i2 = !!(prefix) ? -1 : 0 }, ##args )
-#define CFG_VALIDATE_NETADDR_HWADDR(name, def, help, prefix, args...)  _CFG_VALIDATE(name, def, help, .t_validate = cfg_schema_validate_netaddr, .t_validate_params = {.p_i1 = !!(prefix) ? -AF_MAC48 : AF_MAC48, .p_i2 = AF_EUI64 }, ##args )
-#define CFG_VALIDATE_NETADDR_MAC48(name, def, help, prefix, args...)   _CFG_VALIDATE(name, def, help, .t_validate = cfg_schema_validate_netaddr, .t_validate_params = {.p_i1 = !!(prefix) ? -AF_MAC48 : AF_MAC48}, ##args )
-#define CFG_VALIDATE_NETADDR_EUI64(name, def, help, prefix, args...)   _CFG_VALIDATE(name, def, help, .t_validate = cfg_schema_validate_netaddr, .t_validate_params = {.p_i1 = !!(prefix) ? -AF_EUI64 : AF_EUI64}, ##args )
-#define CFG_VALIDATE_NETADDR_V4(name, def, help, prefix, args...)      _CFG_VALIDATE(name, def, help, .t_validate = cfg_schema_validate_netaddr, .t_validate_params = {.p_i1 = !!(prefix) ? -AF_INET : AF_INET }, ##args )
-#define CFG_VALIDATE_NETADDR_V6(name, def, help, prefix, args...)      _CFG_VALIDATE(name, def, help, .t_validate = cfg_schema_validate_netaddr, .t_validate_params = {.p_i1 = !!(prefix) ? -AF_INET6 : AF_INET6 }, ##args )
-#define CFG_VALIDATE_NETADDR_V46(name, def, help, prefix, args...)     _CFG_VALIDATE(name, def, help, .t_validate = cfg_schema_validate_netaddr, .t_validate_params = {.p_i1 = !!(prefix) ? -AF_INET : AF_INET, .p_i2 = AF_INET6}, ##args )
-
-#define CFG_VALIDATE_BOOL(name, def, help, args...)                    CFG_VALIDATE_CHOICE(name, def, help, CFGLIST_BOOL, ##args)
-
-#define CFG_MAP_STRING(reference, name, def, help, args...)                  _CFG_VALIDATE(#name, def, help, .t_to_binary = cfg_schema_tobin_strptr, .t_offset = offsetof(struct reference, name), ##args )
-#define CFG_MAP_STRING_LEN(reference, name, def, help, maxlen, args...)      CFG_VALIDATE_STRING_LEN(#name, def, help, maxlen, .t_to_binary = cfg_schema_tobin_strptr, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_STRING_ARRAY(reference, name, def, help, maxlen, args...)    _CFG_VALIDATE(#name, def, help, .t_validate_params = {.p_i1 = (maxlen) }, .t_to_binary = cfg_schema_tobin_strarray, .t_offset = offsetof(struct reference, name), ##args )
-#define CFG_MAP_PRINTABLE(reference, name, def, help, args...)               CFG_VALIDATE_PRINTABLE(#name, def, help, .t_to_binary = cfg_schema_tobin_strptr, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_PRINTABLE_LEN(reference, name, def, help, args...)           CFG_VALIDATE_PRINTABLE_LEN(#name, def, help, maxlen, .t_to_binary = cfg_schema_tobin_strptr, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_PRINTABLE_ARRAY(reference, name, def, help, maxlen, args...) CFG_VALIDATE_PRINTABLE_LEN(#name, def, help, maxlen, .t_to_binary = cfg_schema_tobin_strarray, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_CHOICE(reference, name, def, help, list, args...)            CFG_VALIDATE_CHOICE(#name, def, help, list, .t_to_binary = cfg_schema_tobin_choice, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_INT(reference, name, def, help, args...)                     CFG_VALIDATE_INT(#name, def, help, .t_to_binary = cfg_schema_tobin_int, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_INT_MINMAX(reference, name, def, help, min, max, args...)    CFG_VALIDATE_INT_MINMAX(#name, def, help, min, max, .t_to_binary = cfg_schema_tobin_int, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_NETADDR(reference, name, def, help, prefix, args...)         CFG_VALIDATE_NETADDR(#name, def, help, prefix, .t_to_binary = cfg_schema_tobin_netaddr, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_NETADDR_HWADDR(reference, name, def, help, prefix, args...)  CFG_VALIDATE_NETADDR_HWADDR(#name, def, help, prefix, .t_to_binary = cfg_schema_tobin_netaddr, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_NETADDR_MAC48(reference, name, def, help, prefix, args...)   CFG_VALIDATE_NETADDR_MAC48(#name, def, help, prefix, .t_to_binary = cfg_schema_tobin_netaddr, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_NETADDR_EUI64(reference, name, def, help, prefix, args...)   CFG_VALIDATE_NETADDR_EUI64(#name, def, help, prefix, .t_to_binary = cfg_schema_tobin_netaddr, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_NETADDR_V4(reference, name, def, help, prefix, args...)      CFG_VALIDATE_NETADDR_V4(#name, def, help, prefix, .t_to_binary = cfg_schema_tobin_netaddr, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_NETADDR_V6(reference, name, def, help, prefix, args...)      CFG_VALIDATE_NETADDR_V6(#name, def, help, prefix, .t_to_binary = cfg_schema_tobin_netaddr, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_NETADDR_V46(reference, name, def, help, prefix, args...)     CFG_VALIDATE_NETADDR_V46(#name, def, help, prefix, .t_to_binary = cfg_schema_tobin_netaddr, .t_offset = offsetof(struct reference, name), ##args)
-
-#define CFG_MAP_BOOL(reference, name, def, help, args...)                    CFG_VALIDATE_BOOL(#name, def, help, .t_to_binary = cfg_schema_tobin_bool, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_STRINGLIST(reference, name, def, help, args...)              _CFG_VALIDATE(#name, def, help, .t_to_binary = cfg_schema_tobin_stringlist, .t_offset = offsetof(struct reference, name), .t_list = true, ##args )
+#define CFG_VALIDATE_STRING(p_name, p_def, p_help, args...)                  _CFG_VALIDATE(p_name, p_def, p_help, ##args)
+#define CFG_VALIDATE_STRING_LEN(p_name, p_def, p_help, maxlen, args...)      _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_strlen, .cb_valhelp = cfg_schema_help_strlen, .validate_params = {.p_i1 = (maxlen) }, ##args )
+#define CFG_VALIDATE_PRINTABLE(p_name, p_def, p_help, args...)               _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_printable, .cb_valhelp = cfg_schema_help_printable, .validate_params = {.p_i1 = INT32_MAX }, ##args )
+#define CFG_VALIDATE_PRINTABLE_LEN(p_name, p_def, p_help, maxlen, args...)   _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_printable, .cb_valhelp = cfg_schema_help_printable, .validate_params = {.p_i1 = (maxlen) }, ##args )
+#define CFG_VALIDATE_CHOICE(p_name, p_def, p_help, p_list, args...)          _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_choice, .cb_valhelp = cfg_schema_help_choice, .validate_params = {.p_ptr = (p_list), .p_i1 = ARRAYSIZE(p_list)}, ##args )
+#define CFG_VALIDATE_INT(p_name, p_def, p_help, args...)                     _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_int, .cb_valhelp = cfg_schema_help_int, .validate_params = {.p_i1 = INT32_MIN, .p_i2 = INT32_MAX}, ##args )
+#define CFG_VALIDATE_INT_MINMAX(p_name, p_def, p_help, min, max, args...)    _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_int, .cb_valhelp = cfg_schema_help_int, .validate_params = {.p_i1 = (min), .p_i2 = (max)}, ##args )
+#define CFG_VALIDATE_NETADDR(p_name, p_def, p_help, prefix, args...)         _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_netaddr, .cb_valhelp = cfg_schema_help_netaddr, .validate_params = {.p_i1 = 0, .p_i2 = !!(prefix) ? -1 : 0 }, ##args )
+#define CFG_VALIDATE_NETADDR_HWADDR(p_name, p_def, p_help, prefix, args...)  _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_netaddr, .cb_valhelp = cfg_schema_help_netaddr, .validate_params = {.p_i1 = !!(prefix) ? -AF_MAC48 : AF_MAC48, .p_i2 = AF_EUI64 }, ##args )
+#define CFG_VALIDATE_NETADDR_MAC48(p_name, p_def, p_help, prefix, args...)   _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_netaddr, .cb_valhelp = cfg_schema_help_netaddr, .validate_params = {.p_i1 = !!(prefix) ? -AF_MAC48 : AF_MAC48}, ##args )
+#define CFG_VALIDATE_NETADDR_EUI64(p_name, p_def, p_help, prefix, args...)   _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_netaddr, .cb_valhelp = cfg_schema_help_netaddr, .validate_params = {.p_i1 = !!(prefix) ? -AF_EUI64 : AF_EUI64}, ##args )
+#define CFG_VALIDATE_NETADDR_V4(p_name, p_def, p_help, prefix, args...)      _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_netaddr, .cb_valhelp = cfg_schema_help_netaddr, .validate_params = {.p_i1 = !!(prefix) ? -AF_INET : AF_INET }, ##args )
+#define CFG_VALIDATE_NETADDR_V6(p_name, p_def, p_help, prefix, args...)      _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_netaddr, .cb_valhelp = cfg_schema_help_netaddr, .validate_params = {.p_i1 = !!(prefix) ? -AF_INET6 : AF_INET6 }, ##args )
+#define CFG_VALIDATE_NETADDR_V46(p_name, p_def, p_help, prefix, args...)     _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = cfg_schema_validate_netaddr, .cb_valhelp = cfg_schema_help_netaddr, .validate_params = {.p_i1 = !!(prefix) ? -AF_INET : AF_INET, .p_i2 = AF_INET6}, ##args )
+
+#define CFG_VALIDATE_BOOL(p_name, p_def, p_help, args...)                    CFG_VALIDATE_CHOICE(p_name, p_def, p_help, CFGLIST_BOOL, ##args)
+
+#define CFG_MAP_STRING(p_reference, p_field, p_name, p_def, p_help, args...)                  _CFG_VALIDATE(p_name, p_def, p_help, .cb_to_binary = cfg_schema_tobin_strptr, .t_offset = offsetof(struct p_reference, p_field), ##args )
+#define CFG_MAP_STRING_LEN(p_reference, p_field, p_name, p_def, p_help, maxlen, args...)      CFG_VALIDATE_STRING_LEN(p_name, p_def, p_help, maxlen, .cb_to_binary = cfg_schema_tobin_strptr, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_STRING_ARRAY(p_reference, p_field, p_name, p_def, p_help, maxlen, args...)    _CFG_VALIDATE(p_name, p_def, p_help, .validate_params = {.p_i1 = (maxlen) }, .cb_to_binary = cfg_schema_tobin_strarray, .t_offset = offsetof(struct p_reference, p_field), ##args )
+#define CFG_MAP_PRINTABLE(p_reference, p_field, p_name, p_def, p_help, args...)               CFG_VALIDATE_PRINTABLE(p_name, p_def, p_help, .cb_to_binary = cfg_schema_tobin_strptr, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_PRINTABLE_LEN(p_reference, p_field, p_name, p_def, p_help, args...)           CFG_VALIDATE_PRINTABLE_LEN(p_name, p_def, p_help, maxlen, .cb_to_binary = cfg_schema_tobin_strptr, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_PRINTABLE_ARRAY(p_reference, p_field, p_name, p_def, p_help, maxlen, args...) CFG_VALIDATE_PRINTABLE_LEN(p_name, p_def, p_help, maxlen, .cb_to_binary = cfg_schema_tobin_strarray, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_CHOICE(p_reference, p_field, p_name, p_def, p_help, p_list, args...)          CFG_VALIDATE_CHOICE(p_name, p_def, p_help, p_list, .cb_to_binary = cfg_schema_tobin_choice, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_INT(p_reference, p_field, p_name, p_def, p_help, args...)                     CFG_VALIDATE_INT(p_name, p_def, p_help, .cb_to_binary = cfg_schema_tobin_int, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_INT_MINMAX(p_reference, p_field, p_name, p_def, p_help, min, max, args...)    CFG_VALIDATE_INT_MINMAX(p_name, p_def, p_help, min, max, .cb_to_binary = cfg_schema_tobin_int, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_NETADDR(p_reference, p_field, p_name, p_def, p_help, prefix, args...)         CFG_VALIDATE_NETADDR(p_name, p_def, p_help, prefix, .cb_to_binary = cfg_schema_tobin_netaddr, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_NETADDR_HWADDR(p_reference, p_field, p_name, p_def, p_help, prefix, args...)  CFG_VALIDATE_NETADDR_HWADDR(p_name, p_def, p_help, prefix, .cb_to_binary = cfg_schema_tobin_netaddr, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_NETADDR_MAC48(p_reference, p_field, p_name, p_def, p_help, prefix, args...)   CFG_VALIDATE_NETADDR_MAC48(p_name, p_def, p_help, prefix, .cb_to_binary = cfg_schema_tobin_netaddr, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_NETADDR_EUI64(p_reference, p_field, p_name, p_def, p_help, prefix, args...)   CFG_VALIDATE_NETADDR_EUI64(p_name, p_def, p_help, prefix, .cb_to_binary = cfg_schema_tobin_netaddr, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_NETADDR_V4(p_reference, p_field, p_name, p_def, p_help, prefix, args...)      CFG_VALIDATE_NETADDR_V4(p_name, p_def, p_help, prefix, .cb_to_binary = cfg_schema_tobin_netaddr, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_NETADDR_V6(p_reference, p_field, p_name, p_def, p_help, prefix, args...)      CFG_VALIDATE_NETADDR_V6(p_name, p_def, p_help, prefix, .cb_to_binary = cfg_schema_tobin_netaddr, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_NETADDR_V46(p_reference, p_field, p_name, p_def, p_help, prefix, args...)     CFG_VALIDATE_NETADDR_V46(p_name, p_def, p_help, prefix, .cb_to_binary = cfg_schema_tobin_netaddr, .t_offset = offsetof(struct p_reference, p_field), ##args)
+
+#define CFG_MAP_BOOL(p_reference, p_field, p_name, p_def, p_help, args...)                    CFG_VALIDATE_BOOL(p_name, p_def, p_help, .cb_to_binary = cfg_schema_tobin_bool, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_STRINGLIST(p_reference, p_field, p_name, p_def, p_help, args...)              _CFG_VALIDATE(p_name, p_def, p_help, .cb_to_binary = cfg_schema_tobin_stringlist, .t_offset = offsetof(struct p_reference, p_field), .list = true, ##args )
 
 /*
  * Example of a section schema definition
  *
  * struct cfg_schema_section test_section = {
- *   .t_type = "plugin", .t_named = true
+ *   .type = "plugin", .named = true
  * };
  *
  * struct cfg_schema_entry test_entries[] = {
  *   CFG_VALIDATE_BOOL("enable", "true", "boolean help text"),
  *   CFG_VALIDATE_PRINTABLE("logfile", "/tmp/test",
- *     "printable helptext", .t_list = true),
+ *     "printable helptext", .list = true),
  *   CFG_VALIDATE_INT_MINMAX("value", "0", "int helptext", 0, 20),
  * };
  */
@@ -126,18 +126,18 @@ struct cfg_schema_entry;
  * struct bin_data {
  *   bool enable;
  *   char *logfile;
- *   int value;
+ *   int int_value;
  * };
  *
  * struct cfg_schema_section test_section = {
- *   .t_type = "plugin", .t_named = true
+ *   .type = "plugin", .named = true
  * };
  *
  * struct cfg_schema_entry test_entries[] = {
- *   CFG_MAP_BOOL(bin_data, enable, "boolean help text"),
- *   CFG_MAP_PRINTABLE(bin_data, logfile, "/tmp/test",
- *     "printable helptext", .t_list = true),
- *   CFG_MAP_INT_MINMAX(bin_data, value, "0", "int helptext", 0, 20),
+ *   CFG_MAP_BOOL(bin_data, enable, "enable", "boolean help text"),
+ *   CFG_MAP_PRINTABLE(bin_data, logfile, "logfile", "/tmp/test",
+ *     "printable helptext", .list = true),
+ *   CFG_MAP_INT_MINMAX(bin_data, int_value, "value", "0", "int helptext", 0, 20),
  * };
  */
 
@@ -152,71 +152,66 @@ struct cfg_schema {
  */
 struct cfg_schema_section {
   /* node for tree in schema, initialized by schema_add() */
-  struct avl_node node;
+  struct avl_node _node;
 
   /* name of section type */
-  const char *t_type;
+  const char *type;
 
   /* true if sections of this  schema have a name */
-  bool t_named;
+  bool named;
 
   /* true if at least one section of this type must exist */
-  bool t_mandatory;
+  bool mandatory;
 
   /*
    * true if delta listeners should NOT be triggered for
    * this section on a cfg_delta_trigger_non_optional() call.
    */
-  bool t_optional;
+  bool optional;
 
   /* help text for section */
-  const char *t_help;
+  const char *help;
 
   /* callback for checking configuration of section */
-  int (*t_validate)(struct cfg_schema_section *, const char *section_name,
+  int (*cb_validate)(struct cfg_schema_section *, const char *section_name,
       struct cfg_named_section *, struct autobuf *);
 
   /* list of entries in section */
-  struct avl_tree entries;
+  struct avl_tree _entries;
 };
 
 /* Represents the schema of a configuration entry */
 struct cfg_schema_entry {
   /* node for tree in section schema */
-  struct avl_node node;
+  struct avl_node _node;
 
   /* name of entry */
-  const char *t_name;
+  const char *name;
 
   /* default value */
-  const char *t_default;
+  const struct const_strarray def;
 
   /* help text for entry */
-  const char *t_help;
+  const char *help;
 
   /* value is a list of parameters instead of a single one */
-  bool t_list;
+  bool list;
 
-  /*
-   * set to true to mark entry as stateful, so it must be
-   * acknowledged before being written over by configuration
-   * changes
-   */
-  bool t_confirm;
-
-  /* callback for checking value of entry */
-  int (*t_validate)(const struct cfg_schema_entry *entry,
+  /* callback for checking value and giving help for an entry */
+  int (*cb_validate)(const struct cfg_schema_entry *entry,
       const char *section_name, const char *value, struct autobuf *out);
 
+  void (*cb_valhelp)(const struct cfg_schema_entry *entry, struct autobuf *out);
+
   /* parameters for check functions */
   struct validate_params {
       int p_i1, p_i2;
       void *p_ptr;
-  } t_validate_params;
+  } validate_params;
 
   /* callback for converting string into binary */
-  int (*t_to_binary)(const struct cfg_schema_entry *s_entry,
-      struct strarray *value, void *ptr);
+  int (*cb_to_binary)(const struct cfg_schema_entry *s_entry,
+      const struct const_strarray *value, void *ptr);
 
   /* offset of current binary data compared to reference pointer */
   size_t t_offset;
@@ -225,8 +220,8 @@ struct cfg_schema_entry {
 EXPORT const char *CFGLIST_BOOL_TRUE[4];
 EXPORT const char *CFGLIST_BOOL[8];
 
-#define CFG_FOR_ALL_SCHEMA_SECTIONS(tmpl, section, iterator) avl_for_each_element_safe(&(tmpl->sections), section, node, iterator)
-#define CFG_FOR_ALL_SCHEMA_ENTRIES(section, entry, iterator) avl_for_each_element_safe(&section->entries, entry, node, iterator)
+#define CFG_FOR_ALL_SCHEMA_SECTIONS(tmpl, section, iterator) avl_for_each_element_safe(&(tmpl->sections), section, _node, iterator)
+#define CFG_FOR_ALL_SCHEMA_ENTRIES(section, entry, iterator) avl_for_each_element_safe(&section->_entries, entry, _node, iterator)
 
 EXPORT void cfg_schema_add(struct cfg_schema *schema);
 EXPORT void cfg_schema_remove(struct cfg_schema *schema);
@@ -239,7 +234,7 @@ EXPORT int cfg_schema_add_entry(struct cfg_schema_section *, struct cfg_schema_e
 EXPORT void cfg_schema_remove_entries(struct cfg_schema_section *, struct cfg_schema_entry *entries, size_t e_cnt);
 
 EXPORT int cfg_schema_validate(struct cfg_db *db,
-    bool failFast, bool cleanup, bool ignore_unknown_sections, struct autobuf *out);
+    bool cleanup, bool ignore_unknown_sections, struct autobuf *out);
 
 EXPORT int cfg_schema_tobin(void *target, struct cfg_named_section *named,
     const struct cfg_schema_entry *entries, size_t count);
@@ -255,20 +250,43 @@ EXPORT int cfg_schema_validate_int(const struct cfg_schema_entry *entry,
 EXPORT int cfg_schema_validate_netaddr(const struct cfg_schema_entry *entry,
     const char *section_name, const char *value, struct autobuf *out);
 
+EXPORT void cfg_schema_help_printable(
+    const struct cfg_schema_entry *entry, struct autobuf *out);
+EXPORT void cfg_schema_help_strlen(
+    const struct cfg_schema_entry *entry, struct autobuf *out);
+EXPORT void cfg_schema_help_choice(
+    const struct cfg_schema_entry *entry, struct autobuf *out);
+EXPORT void cfg_schema_help_int(
+    const struct cfg_schema_entry *entry, struct autobuf *out);
+EXPORT void cfg_schema_help_netaddr(
+    const struct cfg_schema_entry *entry, struct autobuf *out);
+
 EXPORT int cfg_schema_tobin_strptr(const struct cfg_schema_entry *s_entry,
-    struct strarray *value, void *reference);
+    const struct const_strarray *value, void *reference);
 EXPORT int cfg_schema_tobin_strarray(const struct cfg_schema_entry *s_entry,
-    struct strarray *value, void *reference);
+    const struct const_strarray *value, void *reference);
 EXPORT int cfg_schema_tobin_choice(const struct cfg_schema_entry *s_entry,
-    struct strarray *value, void *reference);
+    const struct const_strarray *value, void *reference);
 EXPORT int cfg_schema_tobin_int(const struct cfg_schema_entry *s_entry,
-    struct strarray *value, void *reference);
+    const struct const_strarray *value, void *reference);
 EXPORT int cfg_schema_tobin_netaddr(const struct cfg_schema_entry *s_entry,
-    struct strarray *value, void *reference);
+    const struct const_strarray *value, void *reference);
 EXPORT int cfg_schema_tobin_bool(const struct cfg_schema_entry *s_entry,
-    struct strarray *value, void *reference);
+    const struct const_strarray *value, void *reference);
 EXPORT int cfg_schema_tobin_stringlist(const struct cfg_schema_entry *s_entry,
-    struct strarray *value, void *reference);
+    const struct const_strarray *value, void *reference);
+
+/**
+ * Remove a single entry from a schema section
+ * @param section pointer to section
+ * @param entry pointer to entry
+ */
+static INLINE void
+cfg_schema_remove_entry(struct cfg_schema_section *section,
+    struct cfg_schema_entry *entry) {
+  avl_remove(&section->_entries, &entry->_node);
+  entry->_node.key = NULL;
+}
 
 /**
  * Finds a section in a schema
@@ -280,19 +298,7 @@ static INLINE struct cfg_schema_section *
 cfg_schema_find_section(struct cfg_schema *schema, const char *type) {
   struct cfg_schema_section *section;
 
-  return avl_find_element(&schema->sections, type, section, node);
-}
-
-/**
- * Remove a single entry from a schema section
- * @param section pointer to section
- * @param entry pointer to entry
- */
-static INLINE void
-cfg_schema_remove_entry(struct cfg_schema_section *section,
-    struct cfg_schema_entry *entry) {
-  avl_remove(&section->entries, &entry->node);
-  entry->node.key = NULL;
+  return avl_find_element(&schema->sections, type, section, _node);
 }
 
 /**
@@ -305,7 +311,7 @@ static INLINE struct cfg_schema_entry *
 cfg_schema_find_entry(struct cfg_schema_section *section, const char *name) {
   struct cfg_schema_entry *entry;
 
-  return avl_find_element(&section->entries, name, entry, node);
+  return avl_find_element(&section->_entries, name, entry, _node);
 }
 
 #endif /* CFG_SCHEMA_H_ */
index 097531d..c6cacac 100644 (file)
@@ -74,21 +74,21 @@ OLSR_SUBSYSTEM_STATE(_cfg_state);
 
 /* define global configuration template */
 static struct cfg_schema_section global_section = {
-  .t_type = CFG_SECTION_GLOBAL,
-  .t_validate = _cb_validate_global,
+  .type = CFG_SECTION_GLOBAL,
+  .cb_validate = _cb_validate_global,
 };
 
 static struct cfg_schema_entry global_entries[] = {
-  CFG_MAP_BOOL(olsr_config_global, fork, "no",
+  CFG_MAP_BOOL(olsr_config_global, fork, "fork", "no",
       "Set to true to fork daemon into background."),
-  CFG_MAP_BOOL(olsr_config_global, failfast, "no",
+  CFG_MAP_BOOL(olsr_config_global, failfast, "failfast", "no",
       "Set to true to stop daemon statup if at least one plugin doesn't load."),
-  CFG_MAP_BOOL(olsr_config_global, ipv4, "yes",
+  CFG_MAP_BOOL(olsr_config_global, ipv4, "ipv4", "yes",
       "Set to true to enable ipv4 support in program."),
-  CFG_MAP_BOOL(olsr_config_global, ipv6, "yes",
+  CFG_MAP_BOOL(olsr_config_global, ipv6, "ipv6", "yes",
       "Set to true to enable ipv6 support in program."),
 
-  CFG_MAP_STRINGLIST(olsr_config_global, plugin, "",
+  CFG_MAP_STRINGLIST(olsr_config_global, plugin, "plugin", NULL,
       "Set list of plugins to be loaded by daemon. Some might need configuration options."),
 };
 
@@ -241,7 +241,7 @@ olsr_cfg_apply(void) {
 
   /*** phase 2: check configuration and apply it ***/
   /* re-validate configuration data */
-  if (cfg_schema_validate(_olsr_raw_db, config_global.failfast, false, true, &log)) {
+  if (cfg_schema_validate(_olsr_raw_db, false, true, &log)) {
     OLSR_WARN(LOG_CONFIG, "Configuration validation failed");
     OLSR_WARN_NH(LOG_CONFIG, "%s", log.buf);
     goto apply_failed;
@@ -270,7 +270,7 @@ olsr_cfg_apply(void) {
   }
 
   /* remove everything not valid */
-  cfg_schema_validate(new_db, false, true, false, NULL);
+  cfg_schema_validate(new_db, true, false, NULL);
 
   if (olsr_cfg_update_globalcfg(false)) {
 
index f27b5e8..5cb79c1 100644 (file)
@@ -69,19 +69,19 @@ static void  _decode_uri(char *src);
 
 /* configuration variables */
 static struct cfg_schema_section _http_section = {
-  .t_type = _CFG_HTTP_SECTION,
-  .t_help = "Settings for the http interface",
+  .type = _CFG_HTTP_SECTION,
+  .help = "Settings for the http interface",
 };
 
 static struct cfg_schema_entry _http_entries[] = {
   CFG_MAP_ACL_V46(olsr_stream_managed_config,
-      acl, "127.0.0.1", "Access control list for http interface"),
+      acl, "acl", "127.0.0.1", "Access control list for http interface"),
   CFG_MAP_NETADDR_V4(olsr_stream_managed_config,
-      bindto_v4, "127.0.0.1", "Bind http ipv4 socket to this address", false),
+      bindto_v4, "bindto_v4", "127.0.0.1", "Bind http ipv4 socket to this address", false),
   CFG_MAP_NETADDR_V6(olsr_stream_managed_config,
-      bindto_v6, "::1", "Bind http ipv6 socket to this address", false),
+      bindto_v6, "bindto_v6", "::1", "Bind http ipv6 socket to this address", false),
   CFG_MAP_INT_MINMAX(olsr_stream_managed_config,
-      port, "1978", "Network port for http interface", 1, 65535),
+      port, "port", "1978", "Network port for http interface", 1, 65535),
 };
 
 static struct cfg_delta_handler _http_handler = {
index f8c2ce3..5df5a1c 100644 (file)
@@ -72,20 +72,20 @@ static void _apply_log_setting(struct cfg_named_section *named,
 
 /* define logging configuration template */
 static struct cfg_schema_section logging_section = {
-  .t_type = LOG_SECTION
+  .type = LOG_SECTION
 };
 
 static struct cfg_schema_entry logging_entries[] = {
   CFG_VALIDATE_INT_MINMAX(LOG_LEVEL_ENTRY, "0", "Set debug level template", -2, 3),
   CFG_VALIDATE_CHOICE(LOG_DEBUG_ENTRY, "",
       "Set logging sources that display debug, info and warnings",
-      LOG_SOURCE_NAMES, .t_list = true),
+      LOG_SOURCE_NAMES, .list = true),
   CFG_VALIDATE_CHOICE(LOG_INFO_ENTRY, "",
       "Set logging sources that display info and warnings",
-      LOG_SOURCE_NAMES, .t_list = true),
+      LOG_SOURCE_NAMES, .list = true),
   CFG_VALIDATE_CHOICE(LOG_WARN_ENTRY, "",
       "Set logging sources that display warnings",
-      LOG_SOURCE_NAMES, .t_list = true),
+      LOG_SOURCE_NAMES, .list = true),
   CFG_VALIDATE_BOOL(LOG_STDERR_ENTRY, "false", "Set to true to activate logging to stderr"),
   CFG_VALIDATE_BOOL(LOG_SYSLOG_ENTRY, "false", "Set to true to activate logging to syslog"),
   CFG_VALIDATE_STRING(LOG_FILE_ENTRY, "", "Set a filename to log to a file"),
@@ -189,7 +189,7 @@ olsr_logcfg_apply(struct cfg_db *db) {
   memset(&logging_cfg, 0, sizeof(logging_cfg));
 
   /* first apply debug level */
-  ptr = cfg_db_get_entry_value(db, LOG_SECTION, NULL, LOG_LEVEL_ENTRY);
+  ptr = cfg_db_get_entry_value(db, LOG_SECTION, NULL, LOG_LEVEL_ENTRY)->value;
   switch (atoi(ptr)) {
     case -1:
       /* no logging */
@@ -226,13 +226,13 @@ olsr_logcfg_apply(struct cfg_db *db) {
   }
 
   /* load settings which loggershould be activated */
-  ptr = cfg_db_get_entry_value(db, LOG_SECTION, NULL, LOG_SYSLOG_ENTRY);
+  ptr = cfg_db_get_entry_value(db, LOG_SECTION, NULL, LOG_SYSLOG_ENTRY)->value;
   activate_syslog = cfg_get_bool(ptr);
 
-  file_name = cfg_db_get_entry_value(db, LOG_SECTION, NULL, LOG_FILE_ENTRY);
+  file_name = cfg_db_get_entry_value(db, LOG_SECTION, NULL, LOG_FILE_ENTRY)->value;
   activate_file = file_name != NULL && *file_name != 0;
 
-  ptr = cfg_db_get_entry_value(db, LOG_SECTION, NULL, LOG_STDERR_ENTRY);
+  ptr = cfg_db_get_entry_value(db, LOG_SECTION, NULL, LOG_STDERR_ENTRY)->value;
   activate_stderr = cfg_get_bool(ptr);
 
   /* and finally modify the logging handlers */
index af7b16b..18782f6 100644 (file)
@@ -47,9 +47,9 @@ olsr_acl_remove(struct olsr_netaddr_acl *acl) {
  * @return -1 if an error happened, 0 otherwise
  */
 int
-olsr_acl_from_strarray(struct olsr_netaddr_acl *acl, struct strarray *array) {
+olsr_acl_from_strarray(struct olsr_netaddr_acl *acl, const struct const_strarray *value) {
   size_t accept_count, reject_count;
-  char *ptr;
+  const char *ptr;
   accept_count = 0;
   reject_count = 0;
 
@@ -57,7 +57,7 @@ olsr_acl_from_strarray(struct olsr_netaddr_acl *acl, struct strarray *array) {
   memset(acl, 0, sizeof(acl));
 
   /* count number of address entries */
-  FOR_ALL_STRINGS(array, ptr) {
+  FOR_ALL_STRINGS(value, ptr) {
     if (_handle_control_cmd(acl, ptr) == 0) {
       continue;
     }
@@ -85,8 +85,8 @@ olsr_acl_from_strarray(struct olsr_netaddr_acl *acl, struct strarray *array) {
   }
 
   /* read netaddr strings into buffers */
-  FOR_ALL_STRINGS(array, ptr) {
-    char *addr;
+  FOR_ALL_STRINGS(value, ptr) {
+    const char *addr;
     if (_handle_control_cmd(acl, ptr) == 0) {
       continue;
     }
@@ -213,7 +213,7 @@ olsr_acl_validate(const struct cfg_schema_entry *entry,
  */
 int
 olsr_acl_tobin(const struct cfg_schema_entry *s_entry __attribute__((unused)),
-    struct strarray *value, void *reference) {
+    const struct const_strarray *value, void *reference) {
   struct olsr_netaddr_acl *ptr;
 
   ptr = (struct olsr_netaddr_acl *)reference;
index 52e1e15..9c1de1f 100644 (file)
 
 #include "config/cfg_schema.h"
 
-#define CFG_VALIDATE_ACL(name, def, help, args...)         _CFG_VALIDATE(name, def, help, .t_validate = olsr_acl_validate, .t_list = true, .t_validate_params = {.p_i1 = 0, .p_i2 = -1 }, ##args )
-#define CFG_VALIDATE_ACL_HWADDR(name, def, help, args...)  _CFG_VALIDATE(name, def, help, .t_validate = olsr_acl_validate, .t_list = true, .t_validate_params = {.p_i1 = -AF_MAC48, .p_i2 = AF_EUI64 }, ##args )
-#define CFG_VALIDATE_ACL_MAC48(name, def, help, args...)   _CFG_VALIDATE(name, def, help, .t_validate = olsr_acl_validate, .t_list = true, .t_validate_params = {.p_i1 = -AF_MAC48}, ##args )
-#define CFG_VALIDATE_ACL_EUI64(name, def, help, args...)   _CFG_VALIDATE(name, def, help, .t_validate = olsr_acl_validate, .t_list = true, .t_validate_params = {.p_i1 = -AF_EUI64}, ##args )
-#define CFG_VALIDATE_ACL_V4(name, def, help, args...)      _CFG_VALIDATE(name, def, help, .t_validate = olsr_acl_validate, .t_list = true, .t_validate_params = {.p_i1 = -AF_INET }, ##args )
-#define CFG_VALIDATE_ACL_V6(name, def, help, args...)      _CFG_VALIDATE(name, def, help, .t_validate = olsr_acl_validate, .t_list = true, .t_validate_params = {.p_i1 = -AF_INET6 }, ##args )
-#define CFG_VALIDATE_ACL_V46(name, def, help, args...)     _CFG_VALIDATE(name, def, help, .t_validate = olsr_acl_validate, .t_list = true, .t_validate_params = {.p_i1 = -AF_INET, .p_i2 = AF_INET6}, ##args )
-
-#define CFG_MAP_ACL(reference, name, def, help, args...)         CFG_VALIDATE_ACL(#name, def, help, .t_to_binary = olsr_acl_tobin, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_ACL_HWADDR(reference, name, def, help, args...)  CFG_VALIDATE_ACL_HWADDR(#name, def, help, .t_to_binary = olsr_acl_tobin, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_ACL_MAC48(reference, name, def, help, args...)   CFG_VALIDATE_ACL_MAC48(#name, def, help, .t_to_binary = olsr_acl_tobin, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_ACL_EUI64(reference, name, def, help, args...)   CFG_VALIDATE_ACL_EUI64(#name, def, help, .t_to_binary = olsr_acl_tobin, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_ACL_V4(reference, name, def, help, args...)      CFG_VALIDATE_ACL_V4(#name, def, help, .t_to_binary = olsr_acl_tobin, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_ACL_V6(reference, name, def, help, args...)      CFG_VALIDATE_ACL_V6(#name, def, help, .t_to_binary = olsr_acl_tobin, .t_offset = offsetof(struct reference, name), ##args)
-#define CFG_MAP_ACL_V46(reference, name, def, help, args...)     CFG_VALIDATE_ACL_V46(#name, def, help, .t_to_binary = olsr_acl_tobin, .t_offset = offsetof(struct reference, name), ##args)
+#define CFG_VALIDATE_ACL(p_name, p_def, p_help, args...)         _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = olsr_acl_validate, .list = true, .validate_params = {.p_i1 = 0, .p_i2 = -1 }, ##args )
+#define CFG_VALIDATE_ACL_HWADDR(p_name, p_def, p_help, args...)  _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = olsr_acl_validate, .list = true, .validate_params = {.p_i1 = -AF_MAC48, .p_i2 = AF_EUI64 }, ##args )
+#define CFG_VALIDATE_ACL_MAC48(p_name, p_def, p_help, args...)   _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = olsr_acl_validate, .list = true, .validate_params = {.p_i1 = -AF_MAC48}, ##args )
+#define CFG_VALIDATE_ACL_EUI64(p_name, p_def, p_help, args...)   _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = olsr_acl_validate, .list = true, .validate_params = {.p_i1 = -AF_EUI64}, ##args )
+#define CFG_VALIDATE_ACL_V4(p_name, p_def, p_help, args...)      _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = olsr_acl_validate, .list = true, .validate_params = {.p_i1 = -AF_INET }, ##args )
+#define CFG_VALIDATE_ACL_V6(p_name, p_def, p_help, args...)      _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = olsr_acl_validate, .list = true, .validate_params = {.p_i1 = -AF_INET6 }, ##args )
+#define CFG_VALIDATE_ACL_V46(p_name, p_def, p_help, args...)     _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = olsr_acl_validate, .list = true, .validate_params = {.p_i1 = -AF_INET, .p_i2 = AF_INET6}, ##args )
+
+#define CFG_MAP_ACL(p_reference, p_field, p_name, p_def, p_help, args...)         CFG_VALIDATE_ACL(p_name, p_def, p_help, .cb_to_binary = olsr_acl_tobin, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_ACL_HWADDR(p_reference, p_field, p_name, p_def, p_help, args...)  CFG_VALIDATE_ACL_HWADDR(p_name, p_def, p_help, .cb_to_binary = olsr_acl_tobin, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_ACL_MAC48(p_reference, p_field, p_name, p_def, p_help, args...)   CFG_VALIDATE_ACL_MAC48(p_name, p_def, p_help, .cb_to_binary = olsr_acl_tobin, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_ACL_EUI64(p_reference, p_field, p_name, p_def, p_help, args...)   CFG_VALIDATE_ACL_EUI64(p_name, p_def, p_help, .cb_to_binary = olsr_acl_tobin, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_ACL_V4(p_reference, p_field, p_name, p_def, p_help, args...)      CFG_VALIDATE_ACL_V4(p_name, p_def, p_help, .cb_to_binary = olsr_acl_tobin, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_ACL_V6(p_reference, p_field, p_name, p_def, p_help, args...)      CFG_VALIDATE_ACL_V6(p_name, p_def, p_help, .cb_to_binary = olsr_acl_tobin, .t_offset = offsetof(struct p_reference, p_field), ##args)
+#define CFG_MAP_ACL_V46(p_reference, p_field, p_name, p_def, p_help, args...)     CFG_VALIDATE_ACL_V46(p_name, p_def, p_help, .cb_to_binary = olsr_acl_tobin, .t_offset = offsetof(struct p_reference, p_field), ##args)
 
 struct olsr_netaddr_acl {
   struct netaddr *accept;
@@ -41,7 +41,7 @@ struct olsr_netaddr_acl {
 };
 
 EXPORT void olsr_acl_add(struct olsr_netaddr_acl *);
-EXPORT int olsr_acl_from_strarray(struct olsr_netaddr_acl *, struct strarray *);
+EXPORT int olsr_acl_from_strarray(struct olsr_netaddr_acl *, const struct const_strarray *value);
 EXPORT void olsr_acl_remove(struct olsr_netaddr_acl *);
 EXPORT int olsr_acl_copy(struct olsr_netaddr_acl *to, struct olsr_netaddr_acl *from);
 
@@ -50,6 +50,6 @@ EXPORT bool olsr_acl_check_accept(struct olsr_netaddr_acl *, struct netaddr *);
 EXPORT int olsr_acl_validate(const struct cfg_schema_entry *entry,
     const char *section_name, const char *value, struct autobuf *out);
 EXPORT int olsr_acl_tobin(const struct cfg_schema_entry *s_entry,
-    struct strarray *value, void *reference);
+    const struct const_strarray *value, void *reference);
 
 #endif /* OLSR_NETADDR_ACL_H_ */
index 08a81e7..1d0f0b4 100644 (file)
@@ -138,7 +138,8 @@ olsr_stream_flush(struct olsr_stream_session *con) {
 /**
  * Add a new stream socket to the scheduler
  * @param stream_socket pointer to uninitialized stream socket struct
- * @param local pointer to local ip/port of socket
+ * @param local pointer to local ip/port of socket, port must be 0 if
+ *   this shall be an outgoing socket
  * @return -1 if an error happened, 0 otherwise
  */
 int
@@ -151,25 +152,28 @@ olsr_stream_add(struct olsr_stream_socket *stream_socket,
 
   memset(stream_socket, 0, sizeof(*stream_socket));
 
-  /* Init socket */
-  s = os_net_getsocket(local, OS_SOCKET_TCP, 0, LOG_SOCKET_STREAM);
-  if (s < 0) {
-    goto add_stream_error;
-  }
+  /* server socket not necessary for outgoing connections */
+  if (netaddr_socket_get_port(local) != 0) {
+    /* Init socket */
+    s = os_net_getsocket(local, OS_SOCKET_TCP, 0, LOG_SOCKET_STREAM);
+    if (s < 0) {
+      goto add_stream_error;
+    }
 
-  /* show that we are willing to listen */
-  if (listen(s, 1) == -1) {
-    OLSR_WARN(LOG_SOCKET_STREAM, "tcp socket listen failed for %s: %s (%d)\n",
-        netaddr_socket_to_string(&buf, local), strerror(errno), errno);
-    goto add_stream_error;
-  }
+    /* show that we are willing to listen */
+    if (listen(s, 1) == -1) {
+      OLSR_WARN(LOG_SOCKET_STREAM, "tcp socket listen failed for %s: %s (%d)\n",
+          netaddr_socket_to_string(&buf, local), strerror(errno), errno);
+      goto add_stream_error;
+    }
 
-  stream_socket->scheduler_entry.fd = s;
-  stream_socket->scheduler_entry.process = _cb_parse_request;
-  stream_socket->scheduler_entry.data = stream_socket;
-  stream_socket->scheduler_entry.event_read = true;
+    stream_socket->scheduler_entry.fd = s;
+    stream_socket->scheduler_entry.process = _cb_parse_request;
+    stream_socket->scheduler_entry.data = stream_socket;
+    stream_socket->scheduler_entry.event_read = true;
 
-  olsr_socket_add(&stream_socket->scheduler_entry);
+    olsr_socket_add(&stream_socket->scheduler_entry);
+  }
   memcpy(&stream_socket->local_socket, local, sizeof(stream_socket->local_socket));
 
   if (stream_socket->config.memcookie == NULL) {
@@ -214,8 +218,11 @@ olsr_stream_remove(struct olsr_stream_socket *stream_socket) {
 
     list_remove(&stream_socket->node);
 
-    os_close(stream_socket->scheduler_entry.fd);
-    olsr_socket_remove(&stream_socket->scheduler_entry);
+    if (stream_socket->scheduler_entry.fd) {
+      /* only for server sockets */
+      os_close(stream_socket->scheduler_entry.fd);
+      olsr_socket_remove(&stream_socket->scheduler_entry);
+    }
   }
 }
 
@@ -236,7 +243,8 @@ olsr_stream_connect_to(struct olsr_stream_socket *stream_socket,
   struct netaddr_str buf;
 #endif
 
-  s = os_net_getsocket(remote, OS_SOCKET_TCP, 0, LOG_SOCKET_STREAM);
+  s = os_net_getsocket(&stream_socket->local_socket,
+      OS_SOCKET_TCP, 0, LOG_SOCKET_STREAM);
   if (s < 0) {
     return NULL;
   }
index a50a2ef..83aac6b 100644 (file)
@@ -51,19 +51,19 @@ static enum olsr_telnet_result _cb_telnet_plugin(struct olsr_telnet_data *data);
 
 /* global and static variables */
 static struct cfg_schema_section telnet_section = {
-  .t_type = _CFG_TELNET_SECTION,
-  .t_help = "Settings for the telnet interface",
+  .type = _CFG_TELNET_SECTION,
+  .help = "Settings for the telnet interface",
 };
 
 static struct cfg_schema_entry telnet_entries[] = {
   CFG_MAP_ACL_V46(olsr_stream_managed_config,
-      acl, "127.0.0.1", "Access control list for telnet interface"),
+      acl, "acl", "127.0.0.1", "Access control list for telnet interface"),
   CFG_MAP_NETADDR_V4(olsr_stream_managed_config,
-      bindto_v4, "127.0.0.1", "Bind telnet ipv4 socket to this address", false),
+      bindto_v4, "bindto_v4", "127.0.0.1", "Bind telnet ipv4 socket to this address", false),
   CFG_MAP_NETADDR_V6(olsr_stream_managed_config,
-      bindto_v6, "::1", "Bind telnet ipv6 socket to this address", false),
+      bindto_v6, "bindto_v6", "::1", "Bind telnet ipv6 socket to this address", false),
   CFG_MAP_INT_MINMAX(olsr_stream_managed_config,
-      port, "2006", "Network port for telnet interface", 1, 65535),
+      port, "port", "2006", "Network port for telnet interface", 1, 65535),
 };
 
 static struct cfg_delta_handler telnet_handler = {
index ff7c308..61bfa6c 100644 (file)
@@ -554,7 +554,7 @@ parse_commandline(int argc, char **argv, bool reload_only) {
 
   if (return_code == -1) {
     /* validate configuration */
-    if (cfg_schema_validate(db, false, false, true, &log)) {
+    if (cfg_schema_validate(db, false, true, &log)) {
       return_code = 1;
     }
   }