Use tokenized config option to simplify a number of plugin options.
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Tue, 24 Oct 2017 06:10:58 +0000 (08:10 +0200)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Tue, 24 Oct 2017 06:10:58 +0000 (08:10 +0200)
Move old "locally attached network" to a plugin, add a new plugin with
a more sane config option (lan_import is still better!)

30 files changed:
openwrt/oonf-olsrd2-git-debug/Config.in
openwrt/oonf-olsrd2-git-debug/Makefile
openwrt/oonf-olsrd2-git/Config.in
openwrt/oonf-olsrd2-git/Makefile
src-plugins/generic/layer2_config/layer2_config.c
src-plugins/generic/link_config/link_config.c
src-plugins/generic/nl80211_listener/nl80211_listener.c
src-plugins/nhdp/auto_ll4/auto_ll4.c
src-plugins/nhdp/constant_metric/constant_metric.c
src-plugins/nhdp/ff_dat_metric/ff_dat_metric.c
src-plugins/nhdp/nhdp/nhdp.c
src-plugins/nhdp/nhdp/nhdp.h
src-plugins/olsrv2/CMakeLists.txt
src-plugins/olsrv2/olsrv2/olsrv2.c
src-plugins/olsrv2/olsrv2/olsrv2.h
src-plugins/olsrv2/olsrv2_lan/CMakeLists.txt [new file with mode: 0644]
src-plugins/olsrv2/olsrv2_lan/olsrv2_lan.c [new file with mode: 0644]
src-plugins/olsrv2/olsrv2_lan/olsrv2_lan.h [new file with mode: 0644]
src-plugins/olsrv2/olsrv2_old_lan/CMakeLists.txt [new file with mode: 0644]
src-plugins/olsrv2/olsrv2_old_lan/old_lan.c [new file with mode: 0644]
src-plugins/olsrv2/olsrv2_old_lan/old_lan.h [new file with mode: 0644]
src-plugins/subsystems/oonf_class.c
src-plugins/subsystems/oonf_layer2.c
src-plugins/subsystems/oonf_layer2.h
src-plugins/subsystems/oonf_rfc5444.c
src-plugins/subsystems/os_interface.h
src-plugins/subsystems/os_linux/os_interface_linux.c
src-plugins/subsystems/os_linux/os_routing_linux.c
src/olsrd2-dlep/CMakeLists.txt
src/olsrd2/CMakeLists.txt

index 1cc037a..0c11870 100644 (file)
                        The MPR plugin reduce the routing graph to limit the overhead of the OLSRv2 protocol
                default n
 
+        config OONF_OLSRV2_LAN
+                bool "New config option for Locally attached entries"
+                help
+                        Adds the 'lan' section to the config to configure LANs without setting multiple settings in a single key/value pair
+                default y
+
+        config OONF_OLSRV2_OLD_LAN
+                bool "Legacy option for Locally attached entries"
+                help
+                        Adds the olsr 'lan' config key in the olsrv2 section
+                default n
+
        endmenu
index 6d23c86..587c2da 100644 (file)
@@ -1,7 +1,7 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=oonf-olsrd2-git-debug
-PKG_VERSION:=2017-06-08
+PKG_VERSION:=2017-10-17
 
 CMAKE_INSTALL:=1
 
@@ -18,6 +18,8 @@ CMAKE_OPTIONAL_PLUGINS:= $(subst $(SPACE),;,$(strip \
         $(if $(filter y,$(CONFIG_OONF_GENERIC_REMOTECONTROL)),remotecontrol,) \
         $(if $(filter y,$(CONFIG_OONF_OLSRV2_MPR)),mpr,) \
         $(if $(filter y,$(CONFIG_OONF_GENERIC_HTTP)),http,) \
+        $(if $(filter y,$(CONFIG_OONF_OLSRV2_LAN)),olsrv2_lan,) \
+        $(if $(filter y,$(CONFIG_OONF_OLSRV2_OLD_LAN)),olsrv2_old_lan,) \
     ))
 
 CMAKE_SOURCE_DIR=$(CURDIR)/../../
index 1cc037a..b0d7d7c 100644 (file)
                        The MPR plugin reduce the routing graph to limit the overhead of the OLSRv2 protocol
                default n
 
+       config OONF_OLSRV2_LAN
+               bool "New config option for Locally attached entries"
+               help
+                       Adds the 'lan' section to the config to configure LANs without setting multiple settings in a single key/value pair
+               default y
+
+       config OONF_OLSRV2_OLD_LAN
+               bool "Legacy option for Locally attached entries"
+               help
+                       Adds the olsr 'lan' config key in the olsrv2 section
+               default n
+
        endmenu
index b70bdb9..2151458 100644 (file)
@@ -1,7 +1,7 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=oonf-olsrd2-git
-PKG_VERSION:=2017-06-08
+PKG_VERSION:=2017-10-17
 
 CMAKE_INSTALL:=1
 
@@ -18,6 +18,8 @@ CMAKE_OPTIONAL_PLUGINS:= $(subst $(SPACE),;,$(strip \
         $(if $(filter y,$(CONFIG_OONF_GENERIC_REMOTECONTROL)),remotecontrol,) \
         $(if $(filter y,$(CONFIG_OONF_OLSRV2_MPR)),mpr,) \
         $(if $(filter y,$(CONFIG_OONF_GENERIC_HTTP)),http,) \
+        $(if $(filter y,$(CONFIG_OONF_OLSRV2_LAN)),olsrv2_lan,) \
+        $(if $(filter y,$(CONFIG_OONF_OLSRV2_OLD_LAN)),olsrv2_old_lan,) \
     ))
 
 BUILD_TYPE:= $(if $(filter y,$(CONFIG_DEBUG)),Debug,Release)
index 1a8c908..0f101c7 100644 (file)
@@ -47,6 +47,7 @@
 #include "common/avl_comp.h"
 #include "common/common_types.h"
 #include "config/cfg_schema.h"
+#include "config/cfg_tobin.h"
 #include "config/cfg_validate.h"
 #include "core/oonf_logging.h"
 #include "core/oonf_subsystem.h"
@@ -59,6 +60,8 @@
 /* definitions and constants */
 #define LOG_LAYER2_CONFIG _oonf_layer2_config_subsystem.logging
 
+enum { _MAX_L2_VALUE_LEN = 64 };
+
 enum l2_data_type {
   L2_NET,
   L2_NET_IP,
@@ -66,8 +69,11 @@ enum l2_data_type {
   L2_NEIGH,
   L2_NEIGH_IP,
   L2_DST,
+
+  L2_TYPE_COUNT,
 };
 
+/* one layer2 configuration option for an interface */
 struct l2_config_data {
   enum l2_data_type config_type;
   struct netaddr mac;
@@ -76,8 +82,10 @@ struct l2_config_data {
 
   enum oonf_layer2_data_type data_type;
   union oonf_layer2_value data;
+  char txt_value[_MAX_L2_VALUE_LEN];
 };
 
+/* all configuration options for an interface */
 struct l2_config_if_data {
   char interf[IF_NAMESIZE];
 
@@ -96,73 +104,91 @@ static struct l2_config_if_data *_add_if_data(
     const char *ifname, size_t data_count);
 static void _remove_if_data(struct l2_config_if_data *);
 
+static int _cb_if_value_validator(
+    struct autobuf *out, const char *section_name,
+    const char *entry_name, const char *value,
+    struct cfg_schema_entry *entries, size_t entry_count);
+static int _cb_if_value_tobin(
+    struct cfg_schema_entry *entries, size_t entry_count,
+      const char *value, void *ptr);
+static int _cb_neigh_value_validator(
+    struct autobuf *out, const char *section_name,
+    const char *entry_name, const char *value,
+    struct cfg_schema_entry *entries, size_t entry_count);
+static int _cb_neigh_value_tobin(
+    struct cfg_schema_entry *entries, size_t entry_count,
+      const char *value, void *ptr);
+
 static void _cb_update_l2net(void *);
 static void _cb_update_l2neigh(void *);
 static void _cb_reconfigure(struct oonf_timer_instance *);
 
-static int _parse_l2net_config(
-    struct l2_config_data *storage, const char *value);
-static int _parse_l2net_ip_config(
-    struct l2_config_data *storage, const char *value);
-static int _parse_l2neigh_config(
-    struct l2_config_data *storage, const char *value);
-static int _parse_l2_addr_config(
-    struct l2_config_data *storage, const char *value);
 static void _configure_if_data(struct l2_config_if_data *if_data);
-
-static int _cb_validate_l2netdata(const struct cfg_schema_entry *entry,
-    const char *section_name, const char *value, struct autobuf *out);
-static int _cb_validate_l2defdata(const struct cfg_schema_entry *entry,
-    const char *section_name, const char *value, struct autobuf *out);
-static int _cb_validate_l2neighdata(const struct cfg_schema_entry *entry,
-    const char *section_name, const char *value, struct autobuf *out);
-static int _cb_validate_l2neighip(const struct cfg_schema_entry *entry,
-    const char *section_name, const char *value, struct autobuf *out);
-static int _cb_validate_l2dst(const struct cfg_schema_entry *entry,
-    const char *section_name, const char *value, struct autobuf *out);
-
-static void _cb_valhelp_l2net(
-    const struct cfg_schema_entry *entry, struct autobuf *out);
-static void _cb_valhelp_l2def(
-    const struct cfg_schema_entry *entry, struct autobuf *out);
-static void _cb_valhelp_l2neigh(
-    const struct cfg_schema_entry *entry, struct autobuf *out);
-static void _create_neigh_help(struct autobuf *out, bool mac);
-
 static void _cb_config_changed(void);
 
 /* define configuration entries */
 
-/*! configuration validator for linkdata */
-#define CFG_VALIDATE_L2NETDATA(p_name, p_def, p_help, args...)         _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = _cb_validate_l2netdata, .cb_valhelp = _cb_valhelp_l2net, .list = true, ##args )
-#define CFG_VALIDATE_L2DEFDATA(p_name, p_def, p_help, args...)         _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = _cb_validate_l2defdata, .cb_valhelp = _cb_valhelp_l2def, .list = true, ##args )
-#define CFG_VALIDATE_L2NEIGHDATA(p_name, p_def, p_help, args...)       _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = _cb_validate_l2neighdata, .cb_valhelp = _cb_valhelp_l2neigh, .list = true, ##args )
-#define CFG_VALIDATE_L2NEIGHIP(p_name, p_def, p_help, args...)         _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = _cb_validate_l2neighip, .list = true, ##args )
-#define CFG_VALIDATE_L2DST(p_name, p_def, p_help, args...)             _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = _cb_validate_l2dst, .list = true, ##args )
+/*! configuration for linkdata */
+static struct cfg_schema_entry _l2net_entries[] = {
+  CFG_MAP_CHOICE_L2NET(l2_config_data, data_idx, "l2net_key", "", "Layer2 network key for configuration"),
+  CFG_MAP_STRING_ARRAY(l2_config_data, txt_value, "l2net_value", "", "Layer2 network value", _MAX_L2_VALUE_LEN),
+};
+static struct cfg_schema_entry _l2net_def_entries[] = {
+  CFG_MAP_CHOICE_L2NEIGH(l2_config_data, data_idx, "l2net_key", "", "Layer2 neighbor key for configuration"),
+  CFG_MAP_STRING_ARRAY(l2_config_data, txt_value, "l2net_value", "", "Layer2 neighbor value for default neighbor data", _MAX_L2_VALUE_LEN),
+};
+static struct cfg_schema_entry _l2neigh_entries[] = {
+  CFG_MAP_CHOICE_L2NET(l2_config_data, data_idx, "l2neigh_key", "", "Layer2 neighbor key for configuration"),
+  CFG_MAP_NETADDR_MAC48(l2_config_data, mac, "l2neigh_mac", "", "MAC address of neighbor", false, false),
+  CFG_MAP_STRING_ARRAY(l2_config_data, txt_value, "l2neigh_value", "", "Layer2 neighbor value", _MAX_L2_VALUE_LEN),
+};
+static struct cfg_schema_entry _l2neigh_ip_entries[] = {
+  CFG_MAP_NETADDR_MAC48(l2_config_data, mac, "l2neigh_mac", "", "MAC address of neighbor", false, false),
+  CFG_MAP_NETADDR_V46(l2_config_data, data.addr, "l2neigh_ip", "", "IP address to neighbor", false, false),
+};
+static struct cfg_schema_entry _l2neigh_dst_entries[] = {
+  CFG_MAP_NETADDR_MAC48(l2_config_data, mac, "l2neigh_mac", "", "MAC address of neighbor", false, false),
+  CFG_MAP_NETADDR_MAC48(l2_config_data, data.addr, "l2neigh_dst", "", "Secondary MAC address of neighbor", false, false),
+};
+
+static struct cfg_schema_token_customizer _if_value_customizer = {
+  .cb_validator = _cb_if_value_validator,
+  .cb_tobin = _cb_if_value_tobin,
+};
+
+static struct cfg_schema_token_customizer _neigh_value_customizer = {
+  .cb_validator = _cb_neigh_value_validator,
+  .cb_tobin = _cb_neigh_value_tobin,
+};
 
 static struct cfg_schema_entry _l2_config_if_entries[] = {
-  [L2_NET]    = CFG_VALIDATE_L2NETDATA("l2net", "",
+  [L2_NET]    = CFG_VALIDATE_TOKENS_CUSTOM("l2net", "",
     "Sets an interface wide layer2 entry into the database."
-    " Parameters are the key of the interface data followed by the data."),
+    " Parameters are the key of the interface data followed by the data.",
+    _l2net_entries, _if_value_customizer, .list = true),
   [L2_NET_IP] = CFG_VALIDATE_NETADDR_V46("l2net_ip", "",
-    "Sets an ip address/prefix for the local radio in the database", true, false),
-  [L2_DEF] = CFG_VALIDATE_L2DEFDATA("l2default", "",
+    "Sets an ip address/prefix for the local radio in the database", true, false, .list = true),
+  [L2_DEF] = CFG_VALIDATE_TOKENS_CUSTOM("l2default", "",
     "Sets an interface wide default neighbor layer2 entry into the database."
-    " Parameters are the key of the neighbor data followed by the data."),
-  [L2_NEIGH] = CFG_VALIDATE_L2NEIGHDATA("l2neighbor", "",
+    " Parameters are the key of the neighbor data followed by the data.",
+    _l2net_def_entries, _neigh_value_customizer, .list = true),
+  [L2_NEIGH] = CFG_VALIDATE_TOKENS_CUSTOM("l2neighbor", "",
     "Sets an neighbor specific layer2 entry into the database."
-    " Parameters are the key of the neighbor data followed by the data and the mac address of the neighbor."),
-  [L2_NEIGH_IP] = CFG_VALIDATE_L2NEIGHIP("l2neighbor_ip", "",
+    " Parameters are the key of the neighbor data followed by the data and the mac address of the neighbor.",
+    _l2neigh_entries, _neigh_value_customizer, .list = true),
+  [L2_NEIGH_IP] = CFG_VALIDATE_TOKENS("l2neighbor_ip", "",
     "Sets an neighbor specific ip address/prefix into the database."
-    " Parameters are the mac address and then the ip address/prefix."),
-  [L2_DST] = CFG_VALIDATE_L2DST("l2destination", "",
+    " Parameters are the mac address and then the ip address/prefix.",
+    _l2neigh_ip_entries, .list = true),
+  [L2_DST] = CFG_VALIDATE_TOKENS("l2destination", "",
     "Sets an neighbor specific bridged MAC destination into the database."
-    " Parameters are the mac address of the neighbor and then the proxied mac address."),
+    " Parameters are the mac address of the neighbor and then the proxied mac address.",
+    _l2neigh_dst_entries, .list = true),
 };
 
 static struct cfg_schema_section _l2_config_section = {
-  .type = CFG_INTERFACE_SECTION,
-  .mode = CFG_INTERFACE_SECTION_MODE,
+  CFG_OSIF_SCHEMA_INTERFACE_SECTION_INIT,
+
   .cb_delta_handler = _cb_config_changed,
   .entries = _l2_config_if_entries,
   .entry_count = ARRAYSIZE(_l2_config_if_entries),
@@ -307,342 +333,171 @@ _remove_if_data(struct l2_config_if_data *if_data) {
 }
 
 /**
- * Callback when a layer2 network entry is changed/removed
- * @param ptr l2net entry
- */
-static void
-_cb_update_l2net(void *ptr) {
-  struct oonf_layer2_net *l2net;
-  struct l2_config_if_data *if_data;
-
-  l2net = ptr;
-
-  if_data = avl_find_element(&_if_data_tree, l2net->name, if_data, _node);
-  if (if_data && !oonf_timer_is_active(&if_data->_reconfigure_timer)) {
-    OONF_DEBUG(LOG_LAYER2_CONFIG, "Received update for l2net: %s", l2net->name);
-    oonf_timer_set(&if_data->_reconfigure_timer, LAYER2_RECONFIG_DELAY);
-  }
-}
-
-/**
- * Callback when a layer2 neighbor entry is changed/removed
- * @param ptr l2net entry
- */
-static void
-_cb_update_l2neigh(void *ptr) {
-  struct oonf_layer2_neigh *l2neigh;
-  struct l2_config_if_data *if_data;
-
-  l2neigh = ptr;
-
-  if_data = avl_find_element(&_if_data_tree, l2neigh->network->name, if_data, _node);
-  if (if_data && !oonf_timer_is_active(&if_data->_reconfigure_timer)) {
-    OONF_DEBUG(LOG_LAYER2_CONFIG, "Received update for l2neigh: %s", l2neigh->network->name);
-    oonf_timer_set(&if_data->_reconfigure_timer, LAYER2_RECONFIG_DELAY);
-  }
-}
-
-/**
- * Timer called for delayed layer2 config update
- * @param timer timer entry
- */
-static void
-_cb_reconfigure(struct oonf_timer_instance *timer) {
-  struct l2_config_if_data *if_data;
-
-  if_data = container_of(timer, typeof(*if_data), _reconfigure_timer);
-  _configure_if_data(if_data);
-}
-
-/**
- * Configuration subsystem validator for linkdata
- * @param entry configuration schema entry
- * @param section_name section name the entry was set
- * @param value value of the entry
- * @param out output buffer for error messages
- * @return -1 if validation failed, 0 otherwise
+ * Validate interface setting for layer2 data
+ * @param out buffer for validation errors
+ * @param section_name name of configuration section
+ * @param entry_name name of configuration entries
+ * @param value value to be validated
+ * @param entries subentries of token config options
+ * @param entry_count number of subentries
+ * @return -1 if an error happened, 0 otherwise
  */
 static int
-_cb_validate_l2netdata(const struct cfg_schema_entry *entry,
-    const char *section_name, const char *value, struct autobuf *out) {
-  enum oonf_layer2_network_index idx;
-  const char *ptr;
-
-  ptr = NULL;
-
-  /* search for network metadata index */
-  for (idx = 0; idx < OONF_LAYER2_NET_COUNT; idx++) {
-    if ((ptr = str_hasnextword(value, oonf_layer2_net_metadata_get(idx)->key))) {
-      break;
-    }
-  }
+_cb_if_value_validator(struct autobuf *out, const char *section_name,
+    const char *entry_name, const char *value,
+    struct cfg_schema_entry *entries, size_t entry_count) {
+  struct l2_config_data l2_data;
+  const struct oonf_layer2_metadata *meta;
+  union oonf_layer2_value dst;
 
-  if (!ptr) {
-    cfg_append_printable_line(out, "First word of '%s' for entry '%s'"
-        " in section %s is unknown layer2 network key",
-        value, entry->key.entry, section_name);
+  if (cfg_tobin_tokens(&l2_data, value, entries, entry_count, NULL)) {
     return -1;
   }
 
-  /* test if second word is a human readable number */
-  if (cfg_validate_int(out, section_name, entry->key.entry, ptr,
-      INT64_MIN, INT64_MAX, 8, oonf_layer2_net_metadata_get(idx)->fraction)) {
-    return -1;
+  meta = oonf_layer2_net_metadata_get(l2_data.data_idx);
+
+  if (oonf_layer2_data_parse_string(&dst, meta, l2_data.txt_value)) {
+    cfg_append_printable_line(out,
+        "Value '%s' for entry '%s' in section %s does not use the data"
+        " type %s for layer2 network key %s",
+        value, entry_name, section_name,
+        oonf_layer2_data_get_type_string(meta->type), meta->key);
   }
   return 0;
 }
 
 /**
- * Configuration subsystem validator for linkdata
- * @param entry configuration schema entry
- * @param section_name section name the entry was set
- * @param value value of the entry
- * @param out output buffer for error messages
- * @return -1 if validation failed, 0 otherwise
+ * Finalize binary conversion of layer2 interface config entry
+ * @param entries configuration subentries
+ * @param entry_count number of subentries
+ * @param value (non-tokenized) value of tokens
+ * @param ptr pointer to binary destination
+ * @return -1 if an error happened, 0 otherwise
  */
 static int
-_cb_validate_l2defdata(const struct cfg_schema_entry *entry,
-    const char *section_name, const char *value, struct autobuf *out) {
-  enum oonf_layer2_neighbor_index idx;
-  const char *ptr;
-
-  ptr = NULL;
-
-  /* search for network metadata index */
-  for (idx = 0; idx < OONF_LAYER2_NEIGH_COUNT; idx++) {
-    if ((ptr = str_hasnextword(value, oonf_layer2_neigh_metadata_get(idx)->key))) {
-      break;
-    }
-  }
+_cb_if_value_tobin(
+    struct cfg_schema_entry *entries __attribute__((unused)),
+    size_t entry_count __attribute__((unused)),
+    const char *value __attribute__((unused)), void *ptr) {
+  struct l2_config_data *l2_data;
+  const struct oonf_layer2_metadata *meta;
 
-  if (!ptr) {
-    cfg_append_printable_line(out, "First word of '%s' for entry '%s'"
-        " in section %s is unknown layer2 neighbor key",
-        value, entry->key.entry, section_name);
-    return -1;
-  }
+  l2_data = ptr;
 
-  /* test if second word is a human readable number */
-  if (cfg_validate_int(out, section_name, entry->key.entry, ptr,
-      INT64_MIN, INT64_MAX, 8, oonf_layer2_neigh_metadata_get(idx)->fraction)) {
+  meta = oonf_layer2_net_metadata_get(l2_data->data_idx);
+  if (oonf_layer2_data_parse_string(&l2_data->data, meta, l2_data->txt_value)) {
     return -1;
   }
+  l2_data->data_type = meta->type;
   return 0;
 }
 
 /**
- * Configuration subsystem validator for linkdata
- * @param entry configuration schema entry
- * @param section_name section name the entry was set
- * @param value value of the entry
- * @param out output buffer for error messages
- * @return -1 if validation failed, 0 otherwise
+ * Validate neighbor setting for layer2 data
+ * @param out buffer for validation errors
+ * @param section_name name of configuration section
+ * @param entry_name name of configuration entries
+ * @param value value to be validated
+ * @param entries subentries of token config options
+ * @param entry_count number of subentries
+ * @return -1 if an error happened, 0 otherwise
  */
 static int
-_cb_validate_l2neighdata(const struct cfg_schema_entry *entry,
-    const char *section_name, const char *value, struct autobuf *out) {
-  static const int8_t MAC48 = AF_MAC48;
-  enum oonf_layer2_neighbor_index idx;
-  struct isonumber_str sbuf;
-  const char *ptr;
-
-  ptr = NULL;
-
-  /* search for network metadata index */
-  for (idx = 0; idx < OONF_LAYER2_NEIGH_COUNT; idx++) {
-    if ((ptr = str_hasnextword(value, oonf_layer2_neigh_metadata_get(idx)->key))) {
-      break;
-    }
-  }
-
-  if (!ptr) {
-    cfg_append_printable_line(out, "First word of '%s' for entry '%s'"
-        " in section %s is unknown layer2 neighbor key",
-        value, entry->key.entry, section_name);
-    return -1;
-  }
-
-  /* test if second word is a human readable number */
-  ptr = str_cpynextword(sbuf.buf, ptr, sizeof(sbuf));
-  if (cfg_validate_int(out, section_name, entry->key.entry, sbuf.buf,
-      INT64_MIN, INT64_MAX, 8, oonf_layer2_neigh_metadata_get(idx)->fraction)) {
-    return -1;
-  }
-
-  if (!ptr) {
-    cfg_append_printable_line(out, "Mac address of neighbor missing for entry '%s'"
-        " in section %s", entry->key.entry, section_name);
-    return -1;
-  }
-
-  /* test if third word is a mac address */
-  if (cfg_validate_netaddr(out, section_name, entry->key.entry, ptr,
-      false, &MAC48, 1)) {
-    return -1;
-  }
-  return 0;
-}
-
-static int
-_cb_validate_l2neighip(const struct cfg_schema_entry *entry,
-    const char *section_name, const char *value, struct autobuf *out) {
-  static const int8_t MAC48[] = { AF_MAC48 };
-  static const int8_t IP46[] = { AF_INET, AF_INET6 };
-  struct netaddr_str nbuf;
-  const char *ptr;
-
-  /* test if first word is a MAC */
-  ptr = str_cpynextword(nbuf.buf, value, sizeof(nbuf));
-  if (cfg_validate_netaddr(out, section_name, entry->key.entry, nbuf.buf,
-      false, MAC48, ARRAYSIZE(MAC48))) {
-    return -1;
-  }
+_cb_neigh_value_validator(struct autobuf *out, const char *section_name,
+    const char *entry_name, const char *value,
+    struct cfg_schema_entry *entries, size_t entry_count) {
+  struct l2_config_data l2_data;
+  const struct oonf_layer2_metadata *meta;
+  union oonf_layer2_value dst;
 
-  /* test if second word is an IP (prefix) */
-  ptr = str_cpynextword(nbuf.buf, ptr, sizeof(nbuf));
-  if (cfg_validate_netaddr(out, section_name, entry->key.entry, nbuf.buf,
-      true, IP46, ARRAYSIZE(IP46))) {
+  if (cfg_tobin_tokens(&l2_data, value, entries, entry_count, NULL)) {
     return -1;
   }
-  return 0;
-}
 
-static int
-_cb_validate_l2dst(const struct cfg_schema_entry *entry,
-    const char *section_name, const char *value, struct autobuf *out) {
-  static const int8_t MAC48[] = { AF_MAC48 };
-  struct netaddr_str nbuf;
-  const char *ptr;
-
-  /* test if first word is a MAC */
-  ptr = str_cpynextword(nbuf.buf, value, sizeof(nbuf));
-  if (cfg_validate_netaddr(out, section_name, entry->key.entry, nbuf.buf,
-      false, MAC48, ARRAYSIZE(MAC48))) {
-    return -1;
-  }
+  meta = oonf_layer2_neigh_metadata_get(l2_data.data_idx);
 
-  /* test if the rest is a MAC */
-  if (cfg_validate_netaddr(out, section_name, entry->key.entry, ptr,
-      true, MAC48, ARRAYSIZE(MAC48))) {
-    return -1;
+  if (oonf_layer2_data_parse_string(&dst, meta, l2_data.txt_value)) {
+    cfg_append_printable_line(out,
+        "Value '%s' for entry '%s' in section %s does not use the data"
+        " type %s for layer2 neighbor key %s",
+        value, entry_name, section_name,
+        oonf_layer2_data_get_type_string(meta->type), meta->key);
   }
   return 0;
-
 }
 
 /**
- * Parse the parameters of a layer2 network config entry
- * @param storage buffer to store results
- * @param value configuration string
+ * Finalize binary conversion of layer2 network config entry
+ * @param entries configuration subentries
+ * @param entry_count number of subentries
+ * @param value (non-tokenized) value of tokens
+ * @param ptr pointer to binary destination
  * @return -1 if an error happened, 0 otherwise
  */
 static int
-_parse_l2net_config(struct l2_config_data *storage, const char *value) {
+_cb_neigh_value_tobin(
+    struct cfg_schema_entry *entries __attribute__((unused)),
+    size_t entry_count __attribute__((unused)),
+    const char *value __attribute__((unused)), void *ptr) {
+  struct l2_config_data *l2_data;
   const struct oonf_layer2_metadata *meta;
-  const char *ptr;
-  int idx;
-
-  ptr = NULL;
 
-  /* search for network metadata index */
-  for (idx = 0; idx < OONF_LAYER2_NET_COUNT; idx++) {
-    if ((ptr = str_hasnextword(value, oonf_layer2_net_metadata_get(idx)->key))) {
-      break;
-    }
-  }
+  l2_data = ptr;
 
-  if (!ptr) {
+  meta = oonf_layer2_neigh_metadata_get(l2_data->data_idx);
+  if (oonf_layer2_data_parse_string(&l2_data->data, meta, l2_data->txt_value)) {
     return -1;
   }
-
-  meta = oonf_layer2_net_metadata_get(idx);
-  storage->data_idx = idx;
-  storage->data_type = meta->type;
-  return oonf_layer2_data_parse_string(&storage->data, meta, ptr);
-}
-
-/**
- * Parse the parameters of a layer2 network ip config entry
- * @param storage buffer to store results
- * @param value configuration string
- * @return -1 if an error happened, 0 otherwise
- */
-static int
-_parse_l2net_ip_config(struct l2_config_data *storage, const char *value) {
-  return netaddr_from_string(&storage->data.addr, value);
+  l2_data->data_type = meta->type;
+  return 0;
 }
 
 /**
- * Parse the parameters of a layer2 neighbor config entry
- * @param storage buffer to store results
- * @param value configuration string
- * @return -1 if an error happened, 0 otherwise
+ * Callback when a layer2 network entry is changed/removed
+ * @param ptr l2net entry
  */
-static int
-_parse_l2neigh_config(struct l2_config_data *storage, const char *value) {
-  const struct oonf_layer2_metadata *meta;
-  struct isonumber_str sbuf;
-  const char *ptr;
-  int idx;
-
-  ptr = NULL;
+static void
+_cb_update_l2net(void *ptr) {
+  struct oonf_layer2_net *l2net;
+  struct l2_config_if_data *if_data;
 
-  /* search for network metadata index */
-  for (idx = 0; idx < OONF_LAYER2_NEIGH_COUNT; idx++) {
-    if ((ptr = str_hasnextword(value, oonf_layer2_neigh_metadata_get(idx)->key))) {
-      break;
-    }
-  }
+  l2net = ptr;
 
-  if (!ptr) {
-    return -1;
+  if_data = avl_find_element(&_if_data_tree, l2net->name, if_data, _node);
+  if (if_data && !oonf_timer_is_active(&if_data->_reconfigure_timer)) {
+    OONF_DEBUG(LOG_LAYER2_CONFIG, "Received update for l2net: %s", l2net->name);
+    oonf_timer_set(&if_data->_reconfigure_timer, LAYER2_RECONFIG_DELAY);
   }
+}
 
-  meta = oonf_layer2_neigh_metadata_get(idx);
-  storage->data_idx = idx;
-  storage->data_type = meta->type;
-
-  /* convert number */
-  ptr = str_cpynextword(sbuf.buf, ptr, sizeof(sbuf));
-  if (oonf_layer2_data_parse_string(&storage->data, meta, sbuf.buf)) {
-    return -1;
-  }
+/**
+ * Callback when a layer2 neighbor entry is changed/removed
+ * @param ptr l2net entry
+ */
+static void
+_cb_update_l2neigh(void *ptr) {
+  struct oonf_layer2_neigh *l2neigh;
+  struct l2_config_if_data *if_data;
 
-  if (ptr) {
-    if (netaddr_from_string(&storage->mac, ptr)) {
-      return -1;
-    }
+  l2neigh = ptr;
 
-    if (netaddr_get_address_family(&storage->mac) == AF_MAC48) {
-      return 0;
-    }
+  if_data = avl_find_element(&_if_data_tree, l2neigh->network->name, if_data, _node);
+  if (if_data && !oonf_timer_is_active(&if_data->_reconfigure_timer)) {
+    OONF_DEBUG(LOG_LAYER2_CONFIG, "Received update for l2neigh: %s", l2neigh->network->name);
+    oonf_timer_set(&if_data->_reconfigure_timer, LAYER2_RECONFIG_DELAY);
   }
-  netaddr_invalidate(&storage->mac);
-  return 0;
 }
 
 /**
- * Parse the parameters of a layer2 network ip config entry
- * @param storage buffer to store results
- * @param value configuration string
- * @return -1 if an error happened, 0 otherwise
+ * Timer called for delayed layer2 config update
+ * @param timer timer entry
  */
-static int
-_parse_l2_addr_config(struct l2_config_data *storage, const char *value) {
-  struct netaddr_str nbuf;
-  const char *ptr;
-
-  /* copy MAC address */
-  ptr = str_cpynextword(nbuf.buf, value, sizeof(nbuf));
-  if (netaddr_from_string(&storage->mac, nbuf.buf)) {
-    return -1;
-  }
+static void
+_cb_reconfigure(struct oonf_timer_instance *timer) {
+  struct l2_config_if_data *if_data;
 
-  /* copy second address */
-  if (netaddr_from_string(&storage->data.addr, ptr)) {
-    return -1;
-  }
-  return 0;
+  if_data = container_of(timer, typeof(*if_data), _reconfigure_timer);
+  _configure_if_data(if_data);
 }
 
 /**
@@ -719,89 +574,16 @@ _configure_if_data(struct l2_config_if_data *if_data) {
   oonf_timer_stop(&if_data->_reconfigure_timer);
 }
 
-/**
- * Create a help text for the l2net configuration parameter
- * @param entry configuration entry
- * @param out help output
- */
-static void
-_cb_valhelp_l2net(const struct cfg_schema_entry *entry __attribute((unused)),
-    struct autobuf *out) {
-  size_t i;
-
-  abuf_puts(out, "    Parameter has the form '<l2net-key> <value>\n");
-  abuf_puts(out, "    <l2net-key> is one of the following list;\n");
-
-  for (i=0; i<OONF_LAYER2_NET_COUNT; i++) {
-    abuf_appendf(out, "        %s\n",
-        oonf_layer2_net_metadata_get(i)->key);
-  }
-
-  abuf_puts(out, "    <value> is an numeric value (with optional iso prefix)\n");
-}
-
-/**
- * Create a help text for the l2default configuration parameter
- * @param entry configuration entry
- * @param out help output
- */
-static void
-_cb_valhelp_l2def(const struct cfg_schema_entry *entry __attribute((unused)),
-    struct autobuf *out) {
-  _create_neigh_help(out, false);
-}
-
-/**
- * Create a help text for the l2neighbor configuration parameter
- * @param entry configuration entry
- * @param out help output
- */
-static void
-_cb_valhelp_l2neigh(const struct cfg_schema_entry *entry __attribute((unused)),
-    struct autobuf *out) {
-  _create_neigh_help(out, true);
-}
-
-/**
- * Create a help text for the l2default and l2neighbor
- * configuration parameter
- * @param out help output
- */
-static void
-_create_neigh_help(struct autobuf *out, bool mac) {
-  size_t i;
-
-
-  abuf_appendf(out, "    Parameter has the form '<l2neigh-key> <value>%s\n",
-      mac ? " <neighbor mac>" : "");
-  abuf_puts(out, "    <l2neigh-key> is one of the following list;\n");
-
-  for (i=0; i<OONF_LAYER2_NEIGH_COUNT; i++) {
-    abuf_appendf(out, "        %s\n",
-        oonf_layer2_neigh_metadata_get(i)->key);
-  }
-
-  abuf_puts(out, "    <value> is an numeric value (with optional iso prefix)\n");
-  if (mac) {
-    abuf_puts(out, "    <mac> is the ethernet mac address of the neighbor\n");
-  }
-}
-
-
 /**
  * Parse configuration change
  */
 static void
 _cb_config_changed(void) {
   struct l2_config_if_data *if_data;
-  struct cfg_entry *l2net_entry, *l2net_ip_entry;
-  struct cfg_entry *l2def_entry;
-  struct cfg_entry *l2neigh_entry, *l2neigh_ip_entry;
-  struct cfg_entry *l2dst_entry;
-
+  struct cfg_entry *entry;
   char ifbuf[IF_NAMESIZE];
+  const char *txt_value;
   const char *ifname;
-  char *txt_value;
   size_t i, total;
 
   ifname = cfg_get_phy_if(ifbuf, _l2_config_section.section_name);
@@ -815,38 +597,13 @@ _cb_config_changed(void) {
      return;
   }
 
-  l2net_entry = cfg_db_get_entry(_l2_config_section.post,
-      _l2_config_if_entries[L2_NET].key.entry);
-  l2net_ip_entry = cfg_db_get_entry(_l2_config_section.post,
-      _l2_config_if_entries[L2_NET_IP].key.entry);
-  l2def_entry = cfg_db_get_entry(_l2_config_section.post,
-      _l2_config_if_entries[L2_DEF].key.entry);
-  l2neigh_entry = cfg_db_get_entry(_l2_config_section.post,
-      _l2_config_if_entries[L2_NEIGH].key.entry);
-  l2neigh_ip_entry = cfg_db_get_entry(_l2_config_section.post,
-      _l2_config_if_entries[L2_NEIGH_IP].key.entry);
-  l2dst_entry = cfg_db_get_entry(_l2_config_section.post,
-      _l2_config_if_entries[L2_DST].key.entry);
-
-  /* calculate number of settings */
   total = 0;
-  if (l2net_entry) {
-    total += strarray_get_count(&l2net_entry->val);
-  }
-  if (l2net_ip_entry) {
-    total += strarray_get_count(&l2net_ip_entry->val);
-  }
-  if (l2def_entry) {
-    total += strarray_get_count(&l2def_entry->val);
-  }
-  if (l2neigh_entry) {
-    total += strarray_get_count(&l2neigh_entry->val);
-  }
-  if (l2neigh_ip_entry) {
-    total += strarray_get_count(&l2neigh_ip_entry->val);
-  }
-  if (l2dst_entry) {
-    total += strarray_get_count(&l2dst_entry->val);
+  for (i=0; i<L2_TYPE_COUNT; i++) {
+    entry = cfg_db_get_entry(_l2_config_section.post,
+        _l2_config_if_entries[i].key.entry);
+    if (entry) {
+      total += strarray_get_count(&entry->val);
+    }
   }
 
   if_data = _add_if_data(_l2_config_section.section_name, total);
@@ -863,81 +620,30 @@ _cb_config_changed(void) {
   avl_insert(&_if_data_tree, &if_data->_node);
 
   /* initialize data */
-  i = 0;
-  if (l2net_entry) {
-    /* parse layer2 network data */
-    strarray_for_each_element(&l2net_entry->val, txt_value) {
-      if (!_parse_l2net_config(&if_data->d[i], txt_value)) {
-        if_data->d[i].config_type = L2_NET;
-        i++;
-      }
-      else {
-        OONF_WARN(LOG_LAYER2_CONFIG, "Could not parse parameter: %s", txt_value);
-      }
-    }
-  }
-  if (l2net_ip_entry) {
-    /* parse layer2 network data */
-    strarray_for_each_element(&l2net_ip_entry->val, txt_value) {
-      if (!_parse_l2net_ip_config(&if_data->d[i], txt_value)) {
-        if_data->d[i].config_type = L2_NET_IP;
-        i++;
-      }
-      else {
-        OONF_WARN(LOG_LAYER2_CONFIG, "Could not parse parameter: %s", txt_value);
-      }
-    }
-  }
-  if (l2def_entry) {
-    /* parse layer2 default data */
-    strarray_for_each_element(&l2def_entry->val, txt_value) {
-      if (!_parse_l2neigh_config(&if_data->d[i], txt_value)) {
-        if_data->d[i].config_type = L2_DEF;
-        i++;
-      }
-      else {
-        OONF_WARN(LOG_LAYER2_CONFIG, "Could not parse parameter: %s", txt_value);
-      }
-    }
-  }
-  if (l2neigh_entry) {
-    /* parse layer2 network data */
-    strarray_for_each_element(&l2neigh_entry->val, txt_value) {
-      if (!_parse_l2neigh_config(&if_data->d[i], txt_value)) {
-        if_data->d[i].config_type = L2_NEIGH;
-        i++;
-      }
-      else {
-        OONF_WARN(LOG_LAYER2_CONFIG, "Could not parse parameter: %s", txt_value);
-      }
-    }
-  }
-  if (l2neigh_ip_entry) {
-    /* parse layer2 network data */
-    strarray_for_each_element(&l2neigh_ip_entry->val, txt_value) {
-      if (!_parse_l2_addr_config(&if_data->d[i], txt_value)) {
-        if_data->d[i].config_type = L2_NEIGH_IP;
-        i++;
-      }
-      else {
-        OONF_WARN(LOG_LAYER2_CONFIG, "Could not parse parameter: %s", txt_value);
-      }
-    }
-  }
-  if (l2dst_entry) {
-    /* parse layer2 network data */
-    strarray_for_each_element(&l2dst_entry->val, txt_value) {
-      if (!_parse_l2_addr_config(&if_data->d[i], txt_value)) {
-        if_data->d[i].config_type = L2_DST;
-        i++;
-      }
-      else {
-        OONF_WARN(LOG_LAYER2_CONFIG, "Could not parse parameter: %s", txt_value);
+  total = 0;
+  for (i=0; i<L2_TYPE_COUNT; i++) {
+    entry = cfg_db_get_entry(_l2_config_section.post,
+        _l2_config_if_entries[i].key.entry);
+    if (entry) {
+      strarray_for_each_element(&entry->val, txt_value) {
+
+        /*
+         * assume that the data type is "address", we will overwrite it for
+         * other variants in the next function call.
+         */
+        if_data->d[total].data_type = OONF_LAYER2_NETWORK_DATA;
+        if(!cfg_tobin_tokens(&if_data->d[total], txt_value,
+            _l2_config_if_entries[i].validate_param[0].ptr,
+            _l2_config_if_entries[i].validate_param[1].s,
+            _l2_config_if_entries[i].validate_param[2].ptr)) {
+          if_data->d[total].config_type = i;
+          total++;
+        }
       }
     }
   }
 
-  if_data->count = i;
+  if_data->count = total;
 
   /* reconfigure layer2 database */
   _configure_if_data(if_data);
index 7df4020..21c6ce8 100644 (file)
@@ -98,8 +98,8 @@ static struct cfg_schema_entry _link_config_if_entries[] = {
 };
 
 static struct cfg_schema_section _link_config_section = {
-  .type = CFG_INTERFACE_SECTION,
-  .mode = CFG_INTERFACE_SECTION_MODE,
+  CFG_OSIF_SCHEMA_INTERFACE_SECTION_INIT,
+
   .cb_delta_handler = _cb_config_changed,
   .entries = _link_config_if_entries,
   .entry_count = ARRAYSIZE(_link_config_if_entries),
index 41947bf..cfa12c4 100644 (file)
@@ -200,8 +200,8 @@ static void _cb_nl_done(uint32_t seq);
 
 /* configuration */
 static struct cfg_schema_section _if_section = {
-  .type = CFG_INTERFACE_SECTION,
-  .mode = CFG_INTERFACE_SECTION_MODE,
+  CFG_OSIF_SCHEMA_INTERFACE_SECTION_INIT,
+
   .cb_delta_handler = _cb_if_config_changed,
   .entries = NULL,
   .entry_count = 0,
index 9d02628..c476432 100644 (file)
@@ -132,8 +132,8 @@ static struct cfg_schema_entry _interface_entries[] = {
 };
 
 static struct cfg_schema_section _interface_section = {
-  .type = CFG_INTERFACE_SECTION,
-  .mode = CFG_INTERFACE_SECTION_MODE,
+  CFG_OSIF_SCHEMA_INTERFACE_SECTION_INIT,
+
   .cb_delta_handler = _cb_if_cfg_changed,
   .entries = _interface_entries,
   .entry_count = ARRAYSIZE(_interface_entries),
index f3abc18..593adb6 100644 (file)
@@ -51,6 +51,7 @@
 #include "common/avl.h"
 #include "common/avl_comp.h"
 #include "config/cfg_schema.h"
+#include "config/cfg_tobin.h"
 #include "config/cfg_validate.h"
 #include "core/oonf_cfg.h"
 #include "core/oonf_logging.h"
@@ -79,11 +80,11 @@ struct _linkcost {
   /*! name of interface */
   char if_name[IF_NAMESIZE];
 
-  /*! neighbor IP the metric is restricted to, NULL if interface generic */
+  /*! neighbor IP the metric is restricted to, NULL if neighbor generic */
   struct netaddr neighbor;
 
   /*! configured metric */
-  uint32_t cost;
+  int32_t cost;
 };
 
 /* prototypes */
@@ -95,22 +96,23 @@ static void _cb_set_linkcost(struct oonf_timer_instance *);
 
 static int _avlcmp_linkcost(const void *, const void *);
 
-static int _cb_validate_link(const struct cfg_schema_entry *entry,
-      const char *section_name, const char *value, struct autobuf *out);
 static void _cb_cfg_changed(void);
 
 /* plugin declaration */
+static struct cfg_schema_entry _constant_entry[] = {
+  CFG_MAP_NETADDR_V46(_linkcost, neighbor, "neighbor", "-",
+      "Originator of neighbor, '-' for all neighbors", false, true),
+  CFG_MAP_INT32_MINMAX(_linkcost, cost, "cost", "1000",
+      "Link cost to neighbor (or all neighbors)", 0,
+      RFC7181_METRIC_MIN, RFC7181_METRIC_MAX),
+};
 static struct cfg_schema_entry _constant_entries[] = {
-  _CFG_VALIDATE("link", "", "Defines the static cost to the link to a neighbor."
-      " Value consists of the originator address (or '-' for all neighbors)"
-      " followed by the link cost",
-      .cb_validate = _cb_validate_link, .list = true),
+  CFG_VALIDATE_TOKENS("constant_metric", "", "Defines the static cost to the link to a neighbor.",
+      _constant_entry, .list=true),
 };
 
 static struct cfg_schema_section _constant_section = {
-  .type = OONF_CONSTANT_METRIC_SUBSYSTEM,
-  .mode = CFG_SSMODE_NAMED_WITH_DEFAULT,
-  .def_name = OS_INTERFACE_ANY,
+  CFG_OSIF_SCHEMA_INTERFACE_SECTION_INIT,
   .cb_delta_handler = _cb_cfg_changed,
   .entries = _constant_entries,
   .entry_count = ARRAYSIZE(_constant_entries),
@@ -310,45 +312,6 @@ _avlcmp_linkcost(const void *ptr1, const void *ptr2) {
   return result;
 }
 
-/**
- * Validate configuration parameter for a constant metric
- * @param entry configuration schema entry
- * @param section_name name of section the entry was set
- * @param value value of the entry
- * @param out output buffer for error messages
- * @return -1 if validation failed, 0 otherwise
- */
-static int
-_cb_validate_link(const struct cfg_schema_entry *entry,
-      const char *section_name, const char *value, struct autobuf *out) {
-  struct isonumber_str sbuf;
-  struct netaddr_str nbuf;
-  const char *ptr;
-  int8_t af[] = { AF_INET, AF_INET6, AF_UNSPEC };
-
-  /* test if first word is a network address readable number */
-  ptr = str_cpynextword(nbuf.buf, value, sizeof(nbuf));
-  if (cfg_validate_netaddr(out, section_name, entry->key.entry, nbuf.buf,
-      false, af, ARRAYSIZE(af))) {
-    return -1;
-  }
-
-  /* test if second word is a human readable number */
-  ptr = str_cpynextword(sbuf.buf, ptr, sizeof(sbuf));
-  if (cfg_validate_int(out, section_name, entry->key.entry, sbuf.buf,
-      RFC7181_METRIC_MIN, RFC7181_METRIC_MAX, 4, 0)) {
-    return -1;
-  }
-
-  if (ptr) {
-    cfg_append_printable_line(out, "Value '%s' for entry '%s'"
-        " in section %s should have only an address and a link cost",
-        value, entry->key.entry, section_name);
-    return -1;
-  }
-  return 0;
-}
-
 /**
  * Callback triggered when configuration changes
  */
@@ -356,9 +319,8 @@ static void
 _cb_cfg_changed(void) {
   struct _linkcost *lk, *lk_it;
   struct netaddr_str nbuf;
-  const char *ptr, *cost_ptr;
+  const char *ptr;
   const struct const_strarray *array;
-  int64_t cost;
 
   /* remove old entries for this interface */
   avl_for_each_element_safe(&_linkcost_tree, lk, _node, lk_it) {
@@ -378,25 +340,19 @@ _cb_cfg_changed(void) {
   strarray_for_each_element(array, ptr) {
     lk = oonf_class_malloc(&_linkcost_class);
     if (lk) {
-      cost_ptr = str_cpynextword(nbuf.buf, ptr, sizeof(nbuf));
-
-      strscpy(lk->if_name, _constant_section.section_name, IF_NAMESIZE);
-      if (netaddr_from_string(&lk->neighbor, nbuf.buf)) {
-        oonf_class_free(&_linkcost_class, lk);
-        continue;
-      }
-      if (isonumber_to_s64(&cost, cost_ptr, 0)) {
-        oonf_class_free(&_linkcost_class, lk);
-        continue;
+      if (cfg_tobin_tokens(lk, ptr, _constant_entry, ARRAYSIZE(_constant_entry), NULL)) {
+        OONF_WARN(LOG_CONSTANT_METRIC,
+            "Could not convert value '%s' in section/key '%s/%s' to binary",
+            _constant_section.type, _constant_entries[0].key.entry, ptr);
       }
+      else {
+        strscpy(lk->if_name, _constant_section.section_name, IF_NAMESIZE);
+        lk->_node.key = lk;
+        avl_insert(&_linkcost_tree, &lk->_node);
 
-      lk->cost = cost;
-
-      lk->_node.key = lk;
-      avl_insert(&_linkcost_tree, &lk->_node);
-
-      OONF_DEBUG(LOG_CONSTANT_METRIC, "Add entry (%s/%s: %s)",
-          lk->if_name, nbuf.buf, cost_ptr);
+        OONF_DEBUG(LOG_CONSTANT_METRIC, "Add entry (%s/%s: %d)",
+            lk->if_name, netaddr_to_string(&nbuf, &lk->neighbor), lk->cost);
+      }
     }
   }
 
index 85e4de2..230279b 100644 (file)
@@ -226,8 +226,8 @@ static struct cfg_schema_entry _datff_entries[] = {
 
 /* Subsystem definition */
 static struct cfg_schema_section _datff_section = {
-  .type = CFG_INTERFACE_SECTION,
-  .mode = CFG_INTERFACE_SECTION_MODE,
+  CFG_OSIF_SCHEMA_INTERFACE_SECTION_INIT,
+
   .cb_delta_handler = _cb_cfg_changed,
   .entries = _datff_entries,
   .entry_count = ARRAYSIZE(_datff_entries),
index f505396..071fdb8 100644 (file)
@@ -112,7 +112,8 @@ static struct cfg_schema_entry _nhdp_entries[] = {
 };
 
 static struct cfg_schema_section _nhdp_section = {
-  .type = OONF_NHDP_SUBSYSTEM,
+  CFG_NHDP_SCHEMA_NHDP_SECTION_INIT,
+
   .cb_delta_handler = _cb_cfg_nhdp_changed,
   .entries = _nhdp_entries,
   .entry_count = ARRAYSIZE(_nhdp_entries),
@@ -129,8 +130,8 @@ static struct cfg_schema_entry _interface_entries[] = {
 };
 
 static struct cfg_schema_section _interface_section = {
-  .type = CFG_INTERFACE_SECTION,
-  .mode = CFG_INTERFACE_SECTION_MODE,
+  CFG_OSIF_SCHEMA_INTERFACE_SECTION_INIT,
+
   .cb_delta_handler = _cb_cfg_interface_changed,
   .entries = _interface_entries,
   .entry_count = ARRAYSIZE(_interface_entries),
@@ -155,9 +156,7 @@ static struct cfg_schema_entry _domain_entries[] = {
 };
 
 static struct cfg_schema_section _domain_section = {
-  .type = CFG_NHDP_DOMAIN_SECTION,
-  .mode = CFG_SSMODE_NAMED_WITH_DEFAULT,
-  .def_name = CFG_NHDP_DEFAULT_DOMAIN,
+  CFG_NHDP_SCHEMA_DOMAIN_SECTION_INIT,
 
   .cb_delta_handler = _cb_cfg_domain_changed,
   .cb_validate = _cb_validate_domain_section,
index c05a36c..9bf5d42 100644 (file)
@@ -48,7 +48,7 @@
 
 #include "common/common_types.h"
 #include "common/netaddr.h"
-
+#include "config/cfg_schema.h"
 #include "core/oonf_subsystem.h"
 #include "subsystems/oonf_rfc5444.h"
 
 #define OONF_NHDP_SUBSYSTEM "nhdp"
 
 /*! configuration section for NHDP */
-#define CFG_NHDP_SECTION        "nhdp"
+#define CFG_NHDP_SCHEMA_DOMAIN_SECTION_INIT    .type = "domain", .mode = CFG_SSMODE_NAMED_WITH_DEFAULT, .def_name = "0"
 
 /*! configuration section for NHDP domains */
-#define CFG_NHDP_DOMAIN_SECTION "domain"
-
-/*! default NHDP domain name */
-#define CFG_NHDP_DEFAULT_DOMAIN "0"
+#define CFG_NHDP_SCHEMA_NHDP_SECTION_INIT      .type = "nhdp", .mode = CFG_SSMODE_UNNAMED
 
 /*! special name for 'no' metric/mpr */
 #define CFG_DOMAIN_NO_METRIC_MPR    "-"
index 6b411eb..a85cf81 100644 (file)
@@ -3,4 +3,7 @@ add_subdirectory(netjsoninfo)
 add_subdirectory(lan_import)
 add_subdirectory(olsrv2)
 add_subdirectory(olsrv2info)
+add_subdirectory(olsrv2_old_lan)
+add_subdirectory(olsrv2_lan)
 add_subdirectory(route_modifier)
+
index 2c065ba..e2a9890 100644 (file)
@@ -145,9 +145,6 @@ static int _init(void);
 static void _initiate_shutdown(void);
 static void _cleanup(void);
 
-static const char *_parse_lan_parameters(struct os_route_key *prefix,
-               struct _lan_data *dst, const char *src);
-static void _parse_lan_array(struct cfg_named_section *section, bool add);
 static void _cb_generate_tc(struct oonf_timer_instance *);
 
 static void _update_originator(int af_family);
@@ -171,9 +168,8 @@ static struct cfg_schema_entry _rt_domain_entries[] = {
 };
 
 static struct cfg_schema_section _rt_domain_section = {
-  .type = CFG_NHDP_DOMAIN_SECTION,
-  .mode = CFG_SSMODE_NAMED_WITH_DEFAULT,
-  .def_name = CFG_NHDP_DEFAULT_DOMAIN,
+  CFG_NHDP_SCHEMA_DOMAIN_SECTION_INIT,
+
   .cb_delta_handler = _cb_cfg_domain_changed,
   .entries = _rt_domain_entries,
   .entry_count = ARRAYSIZE(_rt_domain_entries),
@@ -197,15 +193,6 @@ static struct cfg_schema_entry _olsrv2_entries[] = {
   CFG_MAP_ACL_V46(_config, routable_acl, "routable_acl",
       OLSRV2_ROUTABLE_IPV4 OLSRV2_ROUTABLE_IPV6 ACL_DEFAULT_ACCEPT,
     "Filter to decide which addresses are considered routable"),
-
-  CFG_VALIDATE_LAN(_LOCAL_ATTACHED_NETWORK_KEY, "",
-    "locally attached network, a combination of an"
-    " ip address or prefix followed by an up to four optional parameters"
-    " which define link metric cost, hopcount distance, domain of the prefix"
-    " and the source-prefix ( <"LAN_OPTION_METRIC"...> <"LAN_OPTION_DIST"...>"
-    " <"LAN_OPTION_DOMAIN"<num>/all> <"LAN_OPTION_SRC"...> ).",
-    .list = true),
-
   CFG_MAP_ACL_V46(_config, originator_acl, "originator",
     OLSRV2_ORIGINATOR_IPV4 OLSRV2_ORIGINATOR_IPV6 ACL_DEFAULT_ACCEPT,
     "Filter for router originator addresses (ipv4 and ipv6)"
@@ -577,210 +564,6 @@ olsrv2_set_tc_validity(uint64_t interval) {
   return old;
 }
 
-/**
- * Schema entry validator for an attached network.
- * See CFG_VALIDATE_ACL_*() macros.
- * @param entry pointer to schema entry
- * @param section_name name of section type and name
- * @param value value of schema entry
- * @param out pointer to autobuffer for validator output
- * @return 0 if validation found no problems, -1 otherwise
- */
-int
-olsrv2_validate_lan(const struct cfg_schema_entry *entry,
-    const char *section_name, const char *value, struct autobuf *out) {
-  struct netaddr_str buf;
-  struct _lan_data data;
-  const char *ptr, *result;
-  struct os_route_key prefix;
-
-  if (value == NULL) {
-    cfg_schema_help_netaddr(entry, out);
-    cfg_append_printable_line(out,
-        "    This value is followed by a list of four optional parameters.");
-    cfg_append_printable_line(out,
-        "    - '"LAN_OPTION_SRC"<prefix>' the source specific prefix of this attached network."
-        " The default is 2.");
-    cfg_append_printable_line(out,
-        "    - '"LAN_OPTION_METRIC"<m>' the link metric of the LAN (between %u and %u)."
-        " The default is 0.", RFC7181_METRIC_MIN, RFC7181_METRIC_MAX);
-    cfg_append_printable_line(out,
-        "    - '"LAN_OPTION_DOMAIN"<d>' the domain of the LAN (between 0 and 255) or 'all'."
-        " The default is all.");
-    cfg_append_printable_line(out,
-        "    - '"LAN_OPTION_DIST"<d>' the hopcount distance of the LAN (between 0 and 255)."
-        " The default is 2.");
-    return 0;
-  }
-
-  ptr = str_cpynextword(buf.buf, value, sizeof(buf));
-  if (cfg_schema_validate_netaddr(entry, section_name, buf.buf, out)) {
-    /* check prefix first */
-    return -1;
-  }
-
-  if (netaddr_from_string(&prefix.dst, buf.buf)) {
-    return -1;
-  }
-
-  result = _parse_lan_parameters(&prefix, &data, ptr);
-  if (result) {
-    cfg_append_printable_line(out, "Value '%s' for entry '%s'"
-        " in section %s has %s",
-        value, entry->key.entry, section_name, result);
-    return -1;
-  }
-
-  if (data.metric < RFC7181_METRIC_MIN || data.metric > RFC7181_METRIC_MAX) {
-    cfg_append_printable_line(out, "Metric %u for prefix %s must be between %u and %u",
-        data.metric, buf.buf, RFC7181_METRIC_MIN, RFC7181_METRIC_MAX);
-    return -1;
-  }
-  if (data.dist > 255) {
-    cfg_append_printable_line(out,
-        "Distance %u for prefix %s must be between 0 and 255", data.dist, buf.buf);
-    return -1;
-  }
-
-  return 0;
-}
-
-/**
- * Parse parameters of lan prefix string
- * @param prefix source specific prefix (to store source prefix)
- * @param dst pointer to data structure to store results.
- * @param src source string
- * @return NULL if parser worked without an error, a pointer
- *   to the suffix of the error message otherwise.
- */
-static const char *
-_parse_lan_parameters(struct os_route_key *prefix,
-               struct _lan_data *dst, const char *src) {
-  char buffer[64];
-  const char *ptr, *next;
-  unsigned ext;
-
-  ptr = src;
-  dst->ext = -1;
-  dst->metric = LAN_DEFAULT_METRIC;
-  dst->dist   = LAN_DEFAULT_DISTANCE;
-
-  while (ptr != NULL) {
-    next = str_cpynextword(buffer, ptr, sizeof(buffer));
-
-    if (strncasecmp(buffer, LAN_OPTION_METRIC, 7) == 0) {
-      dst->metric = strtoul(&buffer[7], NULL, 0);
-      if (dst->metric == 0 && errno != 0) {
-        return "an illegal metric parameter";
-      }
-    }
-    else if (strncasecmp(buffer, LAN_OPTION_DOMAIN, 7) == 0) {
-      if (strcasecmp(&buffer[7], "all") == 0) {
-        dst->ext = -1;
-      }
-      else {
-        ext = strtoul(&buffer[7], NULL, 10);
-        if ((ext == 0 && errno != 0) || ext > 255) {
-          return "an illegal domain parameter";
-        }
-        dst->ext = ext;
-      }
-    }
-    else if (strncasecmp(buffer, LAN_OPTION_DIST, 5) == 0) {
-      dst->dist = strtoul(&buffer[5], NULL, 10);
-      if (dst->dist == 0 && errno != 0) {
-        return "an illegal distance parameter";
-      }
-    }
-    else if (strncasecmp(buffer, LAN_OPTION_SRC, 4) == 0) {
-      if (netaddr_from_string(&prefix->src, &buffer[4])) {
-        return "an illegal source prefix";
-      }
-      if (netaddr_get_address_family(&prefix->dst)
-            != netaddr_get_address_family(&prefix->src)) {
-         return "an illegal source prefix address type";
-      }
-      if (!os_routing_supports_source_specific(
-          netaddr_get_address_family(&prefix->dst))) {
-        return "an unsupported sourc specific prefix";
-      }
-    }
-    else {
-      return "an unknown parameter";
-    }
-    ptr = next;
-  }
-  return NULL;
-}
-
-/**
- * Takes a named configuration section, extracts the attached network
- * array and apply it
- * @param section pointer to configuration section.
- * @param add true if new lan entries should be created, false if
- *   existing entries should be removed.
- */
-static void
-_parse_lan_array(struct cfg_named_section *section, bool add) {
-  struct netaddr_str addr_buf;
-  struct netaddr addr;
-  struct os_route_key prefix;
-  struct _lan_data data;
-  struct nhdp_domain *domain;
-
-  const char *value, *ptr;
-  struct cfg_entry *entry;
-
-  if (section == NULL) {
-    return;
-  }
-
-  entry = cfg_db_get_entry(section, _LOCAL_ATTACHED_NETWORK_KEY);
-  if (entry == NULL) {
-    return;
-  }
-
-  strarray_for_each_element(&entry->val, value) {
-    /* extract data */
-    ptr = str_cpynextword(addr_buf.buf, value, sizeof(addr_buf));
-    if (netaddr_from_string(&addr, addr_buf.buf)) {
-      continue;
-    }
-
-    os_routing_init_sourcespec_prefix(&prefix, &addr);
-
-    /* truncate address */
-    netaddr_truncate(&prefix.dst, &prefix.dst);
-
-    if (_parse_lan_parameters(&prefix, &data, ptr)) {
-      continue;
-    }
-
-    if (data.ext == -1) {
-      list_for_each_element(nhdp_domain_get_list(), domain, _node) {
-        if (add) {
-          olsrv2_lan_add(domain, &prefix, data.metric, data.dist);
-        }
-        else {
-          olsrv2_lan_remove(domain, &prefix);
-        }
-      }
-    }
-    else {
-      domain = nhdp_domain_add(data.ext);
-      if (!domain) {
-        continue;
-      }
-      if (add) {
-        olsrv2_lan_add(domain, &prefix, data.metric, data.dist);
-      }
-      else {
-        olsrv2_lan_remove(domain, &prefix);
-      }
-    }
-  }
-}
-
 /**
  * Callback to trigger normal tc generation with timer
  * @param ptr timer instance that fired
@@ -941,12 +724,6 @@ _cb_cfg_olsrv2_changed(void) {
   /* check if we have to change the originators */
   _update_originator(AF_INET);
   _update_originator(AF_INET6);
-
-  /* run through all pre-update LAN entries and remove them */
-  _parse_lan_array(_olsrv2_section.pre, false);
-
-  /* run through all post-update LAN entries and add them */
-  _parse_lan_array(_olsrv2_section.post, true);
 }
 
 /**
index c343a13..90db25b 100644 (file)
 /*! default IPv6 originator addresses */
 #define OLSRV2_ORIGINATOR_IPV6 "-::1\0-ff00::/8\0"
 
-/**
- * Creates a cfg_schema_entry for a locally attached network
- * @param p_name parameter name
- * @param p_def parameter default value
- * @param p_help help text for configuration entry
- * @param args variable list of additional arguments
- */
-#define CFG_VALIDATE_LAN(p_name, p_def, p_help, args...)         _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = olsrv2_validate_lan, .validate_param = {{.i8 = {AF_INET, AF_INET6, -1,-1, -1}}, {.b = true}}, ##args )
-
 EXPORT uint64_t olsrv2_get_tc_interval(void);
 EXPORT uint64_t olsrv2_get_tc_validity(void);
 EXPORT bool olsrv2_is_nhdp_routable(struct netaddr *addr);
@@ -90,9 +81,6 @@ EXPORT bool olsrv2_mpr_shall_forwarding(
     struct rfc5444_reader_tlvblock_context *context,
     struct netaddr *source_address, uint64_t vtime);
 EXPORT void olsrv2_generate_tcs(bool);
-EXPORT int olsrv2_validate_lan(const struct cfg_schema_entry *entry,
-    const char *section_name, const char *value, struct autobuf *out);
-
 EXPORT uint64_t olsrv2_set_tc_interval(uint64_t new_interval);
 EXPORT uint64_t olsrv2_set_tc_validity(uint64_t new_interval);
 
diff --git a/src-plugins/olsrv2/olsrv2_lan/CMakeLists.txt b/src-plugins/olsrv2/olsrv2_lan/CMakeLists.txt
new file mode 100644 (file)
index 0000000..ac3808f
--- /dev/null
@@ -0,0 +1,6 @@
+# set library parameters
+SET (source  olsrv2_lan.c)
+SET (include olsrv2_lan.h)
+
+# use generic plugin maker
+oonf_create_plugin("olsrv2_lan" "${source}" "${include}" "")
diff --git a/src-plugins/olsrv2/olsrv2_lan/olsrv2_lan.c b/src-plugins/olsrv2/olsrv2_lan/olsrv2_lan.c
new file mode 100644 (file)
index 0000000..546e4da
--- /dev/null
@@ -0,0 +1,212 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon version 2 (olsrd2)
+ * Copyright (c) 2004-2015, the olsr.org team - see HISTORY file
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+#include <errno.h>
+
+#include "common/avl.h"
+#include "common/common_types.h"
+#include "common/list.h"
+#include "common/netaddr.h"
+#include "common/netaddr_acl.h"
+#include "config/cfg_schema.h"
+#include "core/oonf_logging.h"
+#include "core/oonf_subsystem.h"
+#include "olsrv2/olsrv2_lan.h"
+
+#include "olsrv2_lan/olsrv2_lan.h"
+
+/*! logging for plugin */
+#define LOG_OLSRV2_LAN _olsrv2_lan_subsystem.logging
+
+/*! locally attached network option for source-specific prefix */
+#define LAN_DEFAULT_DOMAIN -1
+
+/**
+ * Additional parameters of a single locally attached network
+ */
+struct _lan_data {
+  /*! prefix for OLSRv2 LAN */
+  struct os_route_key prefix;
+
+  /*! extension domain of LAN */
+  int32_t extension;
+
+  /*! olsrv2 metric */
+  int32_t metric;
+
+  /*! routing metric (distance) */
+  int32_t distance;
+};
+
+/* prototypes */
+static int _init(void);
+static void _cleanup(void);
+
+static void _cb_cfg_olsrv2_lan_changed(void);
+
+static struct cfg_schema_entry _olsrv2_lan_entries[] = {
+  CFG_MAP_NETADDR_V46(_lan_data, prefix.dst, "prefix", "",
+      "locally attached network prefix", true, false),
+  CFG_MAP_INT32_MINMAX(_lan_data, extension, "domain", "-1",
+      "domain for this LAN entry, -1 for all domains",
+      0, -1, 255),
+  CFG_MAP_NETADDR_V6(_lan_data, prefix.src, "source_prefix", "-",
+      "source prefix for lan (source specific routing)", true, true),
+  CFG_MAP_INT32_MINMAX(_lan_data, metric, "metric", "2",
+      "metric value for this LAN entry",
+      0, RFC7181_METRIC_MIN, RFC7181_METRIC_MAX),
+  CFG_MAP_INT32_MINMAX(_lan_data, distance, "distance", "1",
+      "routing table distance for this LAN entry", 0, 1, 255),
+};
+
+static struct cfg_schema_section _olsrv2_lan_section = {
+  .type = CFG_OLSRV2_SECTION,
+  .mode = CFG_SSMODE_NAMED,
+  .cb_delta_handler = _cb_cfg_olsrv2_lan_changed,
+  .entries = _olsrv2_lan_entries,
+  .entry_count = ARRAYSIZE(_olsrv2_lan_entries),
+};
+
+static const char *_dependencies[] = {
+  OONF_OLSRV2_SUBSYSTEM,
+};
+static struct oonf_subsystem _olsrv2_lan_subsystem = {
+  .name = OONF_OLSRV2_LAN_SUBSYSTEM,
+  .dependencies = _dependencies,
+  .dependencies_count = ARRAYSIZE(_dependencies),
+  .init = _init,
+  .cleanup = _cleanup,
+  .cfg_section = &_olsrv2_lan_section,
+};
+DECLARE_OONF_PLUGIN(_olsrv2_lan_subsystem);
+
+/**
+ * Initialize OLSRV2 old LAN subsystem
+ * @return -1 if an error happened, 0 otherwise
+ */
+static int
+_init(void) {
+  return 0;
+}
+
+/**
+ * Cleanup OLSRV2 subsystem
+ */
+static void
+_cleanup(void) {
+  /* TODO: cleanup set LAN entries */
+}
+
+/**
+ * Add or remove a set of "lan data" gathered from config
+ * @param data data to add/remove
+ * @param add true to add data, false to remove it
+ */
+static void
+_apply_lan_data(struct _lan_data *data, bool add) {
+  struct nhdp_domain *domain;
+
+  if (netaddr_is_unspec(&data->prefix.src)) {
+    switch (netaddr_get_address_family(&data->prefix.dst)) {
+      case AF_INET:
+        memcpy(&data->prefix.src, &NETADDR_IPV4_ANY, sizeof(data->prefix.src));
+        break;
+      case AF_INET6:
+        memcpy(&data->prefix.src, &NETADDR_IPV6_ANY, sizeof(data->prefix.src));
+        break;
+      default:
+        return;
+    }
+  }
+
+  if (data->extension == LAN_DEFAULT_DOMAIN) {
+    /* all domains */
+    list_for_each_element(nhdp_domain_get_list(), domain, _node) {
+      if (add) {
+        olsrv2_lan_add(domain, &data->prefix, data->metric, data->distance);
+      }
+      else {
+        olsrv2_lan_remove(domain, &data->prefix);
+      }
+    }
+  }
+  else {
+    domain = nhdp_domain_add(data->extension);
+    if (domain) {
+      if (add) {
+        olsrv2_lan_add(domain, &data->prefix, data->metric, data->distance);
+      }
+      else {
+        olsrv2_lan_remove(domain, &data->prefix);
+      }
+    }
+  }
+}
+
+/**
+ * Callback fired when olsrv2 section changed
+ */
+static void
+_cb_cfg_olsrv2_lan_changed(void) {
+  struct _lan_data data;
+
+  if (_olsrv2_lan_section.pre) {
+    if (cfg_schema_tobin(&data, _olsrv2_lan_section.pre,
+        _olsrv2_lan_entries, ARRAYSIZE(_olsrv2_lan_entries))) {
+      OONF_WARN(LOG_OLSRV2_LAN, "Could not convert section %s to binary",
+          _olsrv2_lan_section.type);
+      return;
+    }
+
+    _apply_lan_data(&data, false);
+  }
+  if (_olsrv2_lan_section.post) {
+    if (cfg_schema_tobin(&data, _olsrv2_lan_section.post,
+        _olsrv2_lan_entries, ARRAYSIZE(_olsrv2_lan_entries))) {
+      OONF_WARN(LOG_OLSRV2_LAN, "Could not convert section %s to binary",
+          _olsrv2_lan_section.type);
+      return;
+    }
+
+    _apply_lan_data(&data, true);
+  }
+}
+
diff --git a/src-plugins/olsrv2/olsrv2_lan/olsrv2_lan.h b/src-plugins/olsrv2/olsrv2_lan/olsrv2_lan.h
new file mode 100644 (file)
index 0000000..2c0ff48
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * old_lan.h
+ *
+ *  Created on: 18.10.2017
+ *      Author: rogge
+ */
+
+#ifndef _OLSRV2_LAN_H_
+#define _OLSRV2_LAN_H_
+
+#define OONF_OLSRV2_LAN_SUBSYSTEM "olsrv2_lan"
+
+#endif /* _OLSRV2_LAN_H_ */
diff --git a/src-plugins/olsrv2/olsrv2_old_lan/CMakeLists.txt b/src-plugins/olsrv2/olsrv2_old_lan/CMakeLists.txt
new file mode 100644 (file)
index 0000000..9662a66
--- /dev/null
@@ -0,0 +1,6 @@
+# set library parameters
+SET (source  old_lan.c)
+SET (include old_lan.h)
+
+# use generic plugin maker
+oonf_create_plugin("olsrv2_old_lan" "${source}" "${include}" "")
diff --git a/src-plugins/olsrv2/olsrv2_old_lan/old_lan.c b/src-plugins/olsrv2/olsrv2_old_lan/old_lan.c
new file mode 100644 (file)
index 0000000..63b5905
--- /dev/null
@@ -0,0 +1,374 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon version 2 (olsrd2)
+ * Copyright (c) 2004-2015, the olsr.org team - see HISTORY file
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+#include <errno.h>
+
+#include "common/avl.h"
+#include "common/common_types.h"
+#include "common/list.h"
+#include "common/netaddr.h"
+#include "common/netaddr_acl.h"
+#include "config/cfg_schema.h"
+#include "core/oonf_logging.h"
+#include "core/oonf_subsystem.h"
+#include "olsrv2/olsrv2_lan.h"
+
+#include "olsrv2_old_lan/old_lan.h"
+
+/*! logging for plugin */
+#define LOG_OLD_LAN _old_lan_subsystem.logging
+
+/*! configuration option for locally attached networks */
+#define _LOCAL_ATTACHED_NETWORK_KEY "lan"
+
+/**
+ * Default values for locally attached network parameters
+ */
+enum _lan_option_defaults {
+  LAN_DEFAULT_DOMAIN    = 0,//!< LAN_DEFAULT_DOMAIN
+  LAN_DEFAULT_METRIC    = 1,//!< LAN_DEFAULT_METRIC
+  LAN_DEFAULT_DISTANCE  = 2,//!< LAN_DEFAULT_DISTANCE
+};
+
+/*! locally attached network option for source-specific prefix */
+#define LAN_OPTION_SRC    "src="
+
+/*! locally attached network option for outgoing metric */
+#define LAN_OPTION_METRIC "metric="
+
+/*! locally attached network option for domain */
+#define LAN_OPTION_DOMAIN "domain="
+
+/*! locally attached network option for hopcount distance */
+#define LAN_OPTION_DIST   "dist="
+
+/**
+ * Additional parameters of a single locally attached network
+ */
+struct _lan_data {
+  /*! extension domain of LAN */
+  int32_t ext;
+
+  /*! source prefix */
+  struct netaddr source_prefix;
+
+  /*! olsrv2 metric */
+  uint32_t metric;
+
+  /*! routing metric (distance) */
+  uint32_t dist;
+};
+
+/* prototypes */
+static int _init(void);
+static void _cleanup(void);
+
+static const char *_parse_lan_parameters(struct os_route_key *prefix,
+    struct _lan_data *dst, const char *src);
+static void _parse_lan_array(struct cfg_named_section *section, bool add);
+
+static void _cb_cfg_olsrv2_changed(void);
+
+static struct cfg_schema_entry _olsrv2_entries[] = {
+  CFG_VALIDATE_LAN(_LOCAL_ATTACHED_NETWORK_KEY, "",
+    "locally attached network, a combination of an"
+    " ip address or prefix followed by an up to four optional parameters"
+    " which define link metric cost, hopcount distance, domain of the prefix"
+    " and the source-prefix ( <"LAN_OPTION_METRIC"...> <"LAN_OPTION_DIST"...>"
+    " <"LAN_OPTION_DOMAIN"<num>/all> <"LAN_OPTION_SRC"...> ).",
+    .list = true),
+};
+
+static struct cfg_schema_section _olsrv2_section = {
+  .type = CFG_OLSRV2_SECTION,
+  .cb_delta_handler = _cb_cfg_olsrv2_changed,
+  .entries = _olsrv2_entries,
+  .entry_count = ARRAYSIZE(_olsrv2_entries),
+};
+
+static const char *_dependencies[] = {
+  OONF_OLSRV2_SUBSYSTEM,
+};
+static struct oonf_subsystem _old_lan_subsystem = {
+  .name = OONF_OLD_LAN_SUBSYSTEM,
+  .dependencies = _dependencies,
+  .dependencies_count = ARRAYSIZE(_dependencies),
+  .init = _init,
+  .cleanup = _cleanup,
+  .cfg_section = &_olsrv2_section,
+};
+DECLARE_OONF_PLUGIN(_old_lan_subsystem);
+
+/**
+ * Initialize OLSRV2 old LAN subsystem
+ * @return -1 if an error happened, 0 otherwise
+ */
+static int
+_init(void) {
+  OONF_WARN(LOG_OLD_LAN, "Old LAN plugin does add support for the"
+      " deprecated olsrv2/lan config option");
+  return 0;
+}
+
+/**
+ * Cleanup OLSRV2 subsystem
+ */
+static void
+_cleanup(void) {
+  /* TODO: cleanup set LAN entries */
+}
+
+/**
+ * Schema entry validator for an attached network.
+ * See CFG_VALIDATE_ACL_*() macros.
+ * @param entry pointer to schema entry
+ * @param section_name name of section type and name
+ * @param value value of schema entry
+ * @param out pointer to autobuffer for validator output
+ * @return 0 if validation found no problems, -1 otherwise
+ */
+int
+olsrv2_validate_lan(const struct cfg_schema_entry *entry,
+    const char *section_name, const char *value, struct autobuf *out) {
+  struct netaddr_str buf;
+  struct _lan_data data;
+  const char *ptr, *result;
+  struct os_route_key prefix;
+
+  if (value == NULL) {
+    cfg_schema_help_netaddr(entry, out);
+    cfg_append_printable_line(out,
+        "    This value is followed by a list of four optional parameters.");
+    cfg_append_printable_line(out,
+        "    - '"LAN_OPTION_SRC"<prefix>' the source specific prefix of this attached network."
+        " The default is 2.");
+    cfg_append_printable_line(out,
+        "    - '"LAN_OPTION_METRIC"<m>' the link metric of the LAN (between %u and %u)."
+        " The default is 0.", RFC7181_METRIC_MIN, RFC7181_METRIC_MAX);
+    cfg_append_printable_line(out,
+        "    - '"LAN_OPTION_DOMAIN"<d>' the domain of the LAN (between 0 and 255) or 'all'."
+        " The default is all.");
+    cfg_append_printable_line(out,
+        "    - '"LAN_OPTION_DIST"<d>' the hopcount distance of the LAN (between 0 and 255)."
+        " The default is 2.");
+    return 0;
+  }
+
+  ptr = str_cpynextword(buf.buf, value, sizeof(buf));
+  if (cfg_schema_validate_netaddr(entry, section_name, buf.buf, out)) {
+    /* check prefix first */
+    return -1;
+  }
+
+  if (netaddr_from_string(&prefix.dst, buf.buf)) {
+    return -1;
+  }
+
+  result = _parse_lan_parameters(&prefix, &data, ptr);
+  if (result) {
+    cfg_append_printable_line(out, "Value '%s' for entry '%s'"
+        " in section %s has %s",
+        value, entry->key.entry, section_name, result);
+    return -1;
+  }
+
+  if (data.metric < RFC7181_METRIC_MIN || data.metric > RFC7181_METRIC_MAX) {
+    cfg_append_printable_line(out, "Metric %u for prefix %s must be between %u and %u",
+        data.metric, buf.buf, RFC7181_METRIC_MIN, RFC7181_METRIC_MAX);
+    return -1;
+  }
+  if (data.dist > 255) {
+    cfg_append_printable_line(out,
+        "Distance %u for prefix %s must be between 0 and 255", data.dist, buf.buf);
+    return -1;
+  }
+
+  return 0;
+}
+
+/**
+ * Parse parameters of lan prefix string
+ * @param prefix source specific prefix (to store source prefix)
+ * @param dst pointer to data structure to store results.
+ * @param src source string
+ * @return NULL if parser worked without an error, a pointer
+ *   to the suffix of the error message otherwise.
+ */
+static const char *
+_parse_lan_parameters(struct os_route_key *prefix,
+    struct _lan_data *dst, const char *src) {
+  char buffer[64];
+  const char *ptr, *next;
+  unsigned ext;
+
+  ptr = src;
+  dst->ext = -1;
+  dst->metric = LAN_DEFAULT_METRIC;
+  dst->dist   = LAN_DEFAULT_DISTANCE;
+
+  while (ptr != NULL) {
+    next = str_cpynextword(buffer, ptr, sizeof(buffer));
+
+    if (strncasecmp(buffer, LAN_OPTION_METRIC, 7) == 0) {
+      dst->metric = strtoul(&buffer[7], NULL, 0);
+      if (dst->metric == 0 && errno != 0) {
+        return "an illegal metric parameter";
+      }
+    }
+    else if (strncasecmp(buffer, LAN_OPTION_DOMAIN, 7) == 0) {
+      if (strcasecmp(&buffer[7], "all") == 0) {
+        dst->ext = -1;
+      }
+      else {
+        ext = strtoul(&buffer[7], NULL, 10);
+        if ((ext == 0 && errno != 0) || ext > 255) {
+          return "an illegal domain parameter";
+        }
+        dst->ext = ext;
+      }
+    }
+    else if (strncasecmp(buffer, LAN_OPTION_DIST, 5) == 0) {
+      dst->dist = strtoul(&buffer[5], NULL, 10);
+      if (dst->dist == 0 && errno != 0) {
+        return "an illegal distance parameter";
+      }
+    }
+    else if (strncasecmp(buffer, LAN_OPTION_SRC, 4) == 0) {
+      if (netaddr_from_string(&prefix->src, &buffer[4])) {
+        return "an illegal source prefix";
+      }
+      if (netaddr_get_address_family(&prefix->dst)
+            != netaddr_get_address_family(&prefix->src)) {
+        return "an illegal source prefix address type";
+      }
+      if (!os_routing_supports_source_specific(
+          netaddr_get_address_family(&prefix->dst))) {
+        return "an unsupported sourc specific prefix";
+      }
+    }
+    else {
+      return "an unknown parameter";
+    }
+    ptr = next;
+  }
+  return NULL;
+}
+
+/**
+ * Takes a named configuration section, extracts the attached network
+ * array and apply it
+ * @param section pointer to configuration section.
+ * @param add true if new lan entries should be created, false if
+ *   existing entries should be removed.
+ */
+static void
+_parse_lan_array(struct cfg_named_section *section, bool add) {
+  struct netaddr_str addr_buf;
+  struct netaddr addr;
+  struct os_route_key prefix;
+  struct _lan_data data;
+  struct nhdp_domain *domain;
+
+  const char *value, *ptr;
+  struct cfg_entry *entry;
+
+  if (section == NULL) {
+    return;
+  }
+
+  entry = cfg_db_get_entry(section, _LOCAL_ATTACHED_NETWORK_KEY);
+  if (entry == NULL) {
+    return;
+  }
+
+  strarray_for_each_element(&entry->val, value) {
+    /* extract data */
+    ptr = str_cpynextword(addr_buf.buf, value, sizeof(addr_buf));
+    if (netaddr_from_string(&addr, addr_buf.buf)) {
+      continue;
+    }
+
+    os_routing_init_sourcespec_prefix(&prefix, &addr);
+
+    /* truncate address */
+    netaddr_truncate(&prefix.dst, &prefix.dst);
+
+    if (_parse_lan_parameters(&prefix, &data, ptr)) {
+      continue;
+    }
+
+    if (data.ext == -1) {
+      list_for_each_element(nhdp_domain_get_list(), domain, _node) {
+        if (add) {
+          olsrv2_lan_add(domain, &prefix, data.metric, data.dist);
+        }
+        else {
+          olsrv2_lan_remove(domain, &prefix);
+        }
+      }
+    }
+    else {
+      domain = nhdp_domain_add(data.ext);
+      if (!domain) {
+        continue;
+      }
+      if (add) {
+        olsrv2_lan_add(domain, &prefix, data.metric, data.dist);
+      }
+      else {
+        olsrv2_lan_remove(domain, &prefix);
+      }
+    }
+  }
+}
+
+/**
+ * Callback fired when olsrv2 section changed
+ */
+static void
+_cb_cfg_olsrv2_changed(void) {
+  /* run through all pre-update LAN entries and remove them */
+  _parse_lan_array(_olsrv2_section.pre, false);
+
+  /* run through all post-update LAN entries and add them */
+  _parse_lan_array(_olsrv2_section.post, true);
+}
+
diff --git a/src-plugins/olsrv2/olsrv2_old_lan/old_lan.h b/src-plugins/olsrv2/olsrv2_old_lan/old_lan.h
new file mode 100644 (file)
index 0000000..e74c5d5
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * old_lan.h
+ *
+ *  Created on: 18.10.2017
+ *      Author: rogge
+ */
+
+#ifndef _OLD_LAN_H_
+#define _OLD_LAN_H_
+
+#include "config/cfg_schema.h"
+
+#define OONF_OLD_LAN_SUBSYSTEM "olsrv2_old_lan"
+
+/**
+ * Creates a cfg_schema_entry for a locally attached network
+ * @param p_name parameter name
+ * @param p_def parameter default value
+ * @param p_help help text for configuration entry
+ * @param args variable list of additional arguments
+ */
+#define CFG_VALIDATE_LAN(p_name, p_def, p_help, args...)         _CFG_VALIDATE(p_name, p_def, p_help, .cb_validate = olsrv2_validate_lan, .validate_param = {{.i8 = {AF_INET, AF_INET6, -1,-1, -1}}, {.b = true}}, ##args )
+
+EXPORT int olsrv2_validate_lan(const struct cfg_schema_entry *entry,
+    const char *section_name, const char *value, struct autobuf *out);
+
+#endif /* _OLD_LAN_H_ */
index 62ef11a..f6b5800 100644 (file)
@@ -313,7 +313,7 @@ oonf_class_extension_add(struct oonf_class_extension *ext) {
  */
 void
 oonf_class_extension_remove(struct oonf_class_extension *ext) {
-  if (list_is_node_added(&ext->_node)) {
+  if (oonf_class_is_extension_registered(ext)) {
     list_remove(&ext->_node);
     ext->_offset = 0;
   }
index 787e82f..9a91816 100644 (file)
@@ -81,7 +81,7 @@ static struct oonf_subsystem _oonf_layer2_subsystem = {
 DECLARE_OONF_PLUGIN(_oonf_layer2_subsystem);
 
 /* layer2 neighbor metadata */
-static const struct oonf_layer2_metadata _oonf_layer2_metadata_neigh[OONF_LAYER2_NEIGH_COUNT] = {
+static const struct oonf_layer2_metadata _metadata_neigh[OONF_LAYER2_NEIGH_COUNT] = {
   [OONF_LAYER2_NEIGH_TX_SIGNAL]      = { .key = "tx_signal", .type = OONF_LAYER2_INTEGER_DATA, .unit = "dBm", .fraction = 3 },
   [OONF_LAYER2_NEIGH_RX_SIGNAL]      = { .key = "rx_signal", .type = OONF_LAYER2_INTEGER_DATA, .unit = "dBm", .fraction = 3 },
   [OONF_LAYER2_NEIGH_TX_BITRATE]     = { .key = "tx_bitrate", .type = OONF_LAYER2_INTEGER_DATA, .unit = "bit/s" },
@@ -102,7 +102,7 @@ static const struct oonf_layer2_metadata _oonf_layer2_metadata_neigh[OONF_LAYER2
 };
 
 /* layer2 network metadata */
-static const struct oonf_layer2_metadata _oonf_layer2_metadata_net[OONF_LAYER2_NET_COUNT] = {
+static const struct oonf_layer2_metadata _metadata_net[OONF_LAYER2_NET_COUNT] = {
   [OONF_LAYER2_NET_FREQUENCY_1]     = { .key = "frequency1", .type = OONF_LAYER2_INTEGER_DATA , .unit = "Hz" },
   [OONF_LAYER2_NET_FREQUENCY_2]     = { .key = "frequency2", .type = OONF_LAYER2_INTEGER_DATA , .unit = "Hz" },
   [OONF_LAYER2_NET_BANDWIDTH_1]     = { .key = "bandwidth1", .type = OONF_LAYER2_INTEGER_DATA , .unit = "Hz" },
@@ -118,13 +118,29 @@ static const struct oonf_layer2_metadata _oonf_layer2_metadata_net[OONF_LAYER2_N
   [OONF_LAYER2_NET_TX_ONLY_UNICAST] = { .key = "tx_only_unicast", .type = OONF_LAYER2_BOOLEAN_DATA },
 };
 
-static const char *oonf_layer2_network_type[OONF_LAYER2_TYPE_COUNT] = {
+static const char *_network_type[OONF_LAYER2_TYPE_COUNT] = {
   [OONF_LAYER2_TYPE_UNDEFINED] = "undefined",
   [OONF_LAYER2_TYPE_WIRELESS]  = "wireless",
   [OONF_LAYER2_TYPE_ETHERNET]  = "ethernet",
   [OONF_LAYER2_TYPE_TUNNEL]    = "tunnel",
 };
 
+static const char *_data_comparators[OONF_LAYER2_DATA_CMP_COUNT] = {
+  [OONF_LAYER2_DATA_CMP_EQUALS]            = "==",
+  [OONF_LAYER2_DATA_CMP_NOT_EQUALS]        = "!=",
+  [OONF_LAYER2_DATA_CMP_LESSER]            = "<",
+  [OONF_LAYER2_DATA_CMP_LESSER_OR_EQUALS]  = "<=",
+  [OONF_LAYER2_DATA_CMP_GREATER]           = ">",
+  [OONF_LAYER2_DATA_CMP_GREATER_OR_EQUALS] = ">=",
+};
+
+static const char *_data_types[OONF_LAYER2_DATA_TYPE_COUNT] = {
+  [OONF_LAYER2_NO_DATA]       = "none",
+  [OONF_LAYER2_INTEGER_DATA]  = "integer",
+  [OONF_LAYER2_BOOLEAN_DATA]  = "boolean",
+  [OONF_LAYER2_NETWORK_DATA]  = "network",
+};
+
 /* infrastructure for l2net/l2neigh tree */
 static struct oonf_class _l2network_class = {
   .name = LAYER2_CLASS_NETWORK,
@@ -218,6 +234,13 @@ oonf_layer2_origin_remove(struct oonf_layer2_origin *origin) {
   avl_remove(&_oonf_originator_tree, &origin->_node);
 }
 
+/**
+ * Parse a string into a layer2 data object
+ * @param value target buffer for layer2 data
+ * @param meta metadata for layer2 data
+ * @param input input string
+ * @return -1 if an error happened, 0 otherwise
+ */
 int
 oonf_layer2_data_parse_string(union oonf_layer2_value *value,
     const struct oonf_layer2_metadata *meta, const char *input) {
@@ -229,15 +252,27 @@ oonf_layer2_data_parse_string(union oonf_layer2_value *value,
           &value->integer, input, meta->fraction);
 
     case OONF_LAYER2_BOOLEAN_DATA:
-        value->boolean = cfg_get_bool(input);
-        return 0;
+      if (!cfg_is_bool(input)) {
+        return -1;
+      }
+      value->boolean = cfg_get_bool(input);
+      return 0;
 
     default:
       return -1;
   }
 }
 
-int
+/**
+ * Convert a layer2 data object into a string representation
+ * @param buffer destination string buffer
+ * @param length length of string buffer
+ * @param data layer2 data
+ * @param meta layer2 metadata
+ * @param raw true for raw conversion (switch of isoprefix conversion)
+ * @return pointer to output buffer, NULL if an error happened
+ */
+const char *
 oonf_layer2_data_to_string(char *buffer, size_t length,
     const struct oonf_layer2_data *data,
     const struct oonf_layer2_metadata *meta, bool raw) {
@@ -247,20 +282,26 @@ oonf_layer2_data_to_string(char *buffer, size_t length,
     case OONF_LAYER2_INTEGER_DATA:
       if (!isonumber_from_s64(&iso_str, data->_value.integer,
           meta->unit, meta->fraction, raw)) {
-        return -1;
+        return NULL;
       }
-      strscpy(buffer, iso_str.buf, length);
-      return 0;
+      return strscpy(buffer, iso_str.buf, length);
 
     case OONF_LAYER2_BOOLEAN_DATA:
-      strscpy(buffer, json_getbool(data->_value.boolean), length);
-      return 0;
+      return strscpy(buffer, json_getbool(data->_value.boolean), length);
 
     default:
-      return -1;
+      return NULL;
   }
 }
 
+/**
+ * (Over)write the value of a layer2 data object
+ * @param l2data layer2 data object
+ * @param origin origin of new data
+ * @param type type of new data
+ * @param input new data value
+ * @return true if data changed, false otherwise
+ */
 bool
 oonf_layer2_data_set(struct oonf_layer2_data *l2data,
     const struct oonf_layer2_origin *origin,
@@ -281,6 +322,99 @@ oonf_layer2_data_set(struct oonf_layer2_data *l2data,
   return changed;
 }
 
+/**
+ * Compare two layer2 data objects
+ * @param left left parameter for comparator
+ * @param right right parameter for comparator
+ * @param cmp comparator
+ * @return comparator result, false if not valid
+ *   (e.g. comparing different types of data)
+ */
+bool
+oonf_layer2_data_compare(const union oonf_layer2_value *left,
+    const union oonf_layer2_value *right,
+    enum oonf_layer2_data_comparator_type comparator,
+    enum oonf_layer2_data_type data_type) {
+  int result;
+
+  switch (data_type) {
+    case OONF_LAYER2_INTEGER_DATA:
+      if (left->integer > right->integer) {
+        result = 1;
+      }
+      else if (left->integer < right->integer) {
+        result = -1;
+      }
+      else {
+        result = 0;
+      }
+      break;
+    case OONF_LAYER2_BOOLEAN_DATA:
+      result = memcmp(&left->boolean, &right->boolean,
+          sizeof(left->boolean));
+      break;
+    case OONF_LAYER2_NETWORK_DATA:
+      result = memcmp(&left->addr, &right->addr,
+                sizeof(left->addr));
+      break;
+    default:
+      return false;
+  }
+
+
+  switch (comparator) {
+    case OONF_LAYER2_DATA_CMP_EQUALS:
+      return result == 0;
+    case OONF_LAYER2_DATA_CMP_NOT_EQUALS:
+      return result != 0;
+    case OONF_LAYER2_DATA_CMP_LESSER:
+      return result < 0;
+    case OONF_LAYER2_DATA_CMP_LESSER_OR_EQUALS:
+      return result <= 0;
+    case OONF_LAYER2_DATA_CMP_GREATER:
+      return result > 0;
+    case OONF_LAYER2_DATA_CMP_GREATER_OR_EQUALS:
+      return result >= 0;
+    default:
+      return false;
+  }
+}
+
+/**
+ * Get comparator type from string
+ * @param string string (C) representation of comparator
+ * @return comparator type
+ */
+enum oonf_layer2_data_comparator_type
+oonf_layer2_data_get_comparator(const char *string) {
+  enum oonf_layer2_data_comparator_type i;
+
+  for (i=0; i<OONF_LAYER2_DATA_CMP_COUNT; i++) {
+    if (strcmp(string, _data_comparators[i]) == 0) {
+      return i;
+    }
+  }
+  return OONF_LAYER2_DATA_CMP_ILLEGAL;
+}
+
+/**
+ * @param type layer2 comparator type
+ * @return string representation of comparator
+ */
+const char *
+oonf_layer2_data_get_comparator_string(enum oonf_layer2_data_comparator_type type) {
+  return _data_comparators[type];
+}
+
+/**
+ * @param type type index of layer2 data
+ * @return the string name of a layer2 data type
+ */
+const char *
+oonf_layer2_data_get_type_string(enum oonf_layer2_data_type type) {
+  return _data_types[type];
+}
+
 /**
  * Add a layer-2 network to the database
  * @param ifname name of interface
@@ -892,7 +1026,7 @@ oonf_layer2_neigh_get_data(const struct oonf_layer2_neigh *l2neigh,
  */
 const struct oonf_layer2_metadata *
 oonf_layer2_neigh_metadata_get(enum oonf_layer2_neighbor_index idx) {
-  return &_oonf_layer2_metadata_neigh[idx];
+  return &_metadata_neigh[idx];
 }
 
 /**
@@ -902,7 +1036,40 @@ oonf_layer2_neigh_metadata_get(enum oonf_layer2_neighbor_index idx) {
  */
 const struct oonf_layer2_metadata *
 oonf_layer2_net_metadata_get(enum oonf_layer2_network_index idx) {
-  return &_oonf_layer2_metadata_net[idx];
+  return &_metadata_net[idx];
+}
+
+/**
+ * Callback for configuration choice of layer2 network key
+ * @param idx index
+ * @param unused not used
+ * @return pointer to network key
+ */
+const char *
+oonf_layer2_cfg_get_l2net_key(size_t idx, const void *unused __attribute__((unused))) {
+  return _metadata_net[idx].key;
+}
+
+/**
+ * Callback for configuration choice of layer2 neighbor key
+ * @param idx index
+ * @param unused not used
+ * @return pointer to neighbor key
+ */
+const char *
+oonf_layer2_cfg_get_l2neigh_key(size_t idx, const void *unused __attribute__((unused))) {
+  return _metadata_neigh[idx].key;
+}
+
+/**
+ * Callback for configuration choice of layer2 neighbor key
+ * @param idx index
+ * @param unused not used
+ * @return pointer to neighbor key
+ */
+const char *
+oonf_layer2_cfg_get_l2comp(size_t idx, const void *unused __attribute__((unused))) {
+  return _data_comparators[idx];
 }
 
 /**
@@ -912,7 +1079,7 @@ oonf_layer2_net_metadata_get(enum oonf_layer2_network_index idx) {
  */
 const char *
 oonf_layer2_net_get_type_name(enum oonf_layer2_network_type type) {
-  return oonf_layer2_network_type[type];
+  return _network_type[type];
 }
 
 /**
index d630076..8458204 100644 (file)
 /*! memory class for layer2 neighbor address */
 #define LAYER2_CLASS_NEIGHBOR_ADDRESS "layer2_neighbor_address"
 
+/* configuration Macros for Layer2 keys */
+
+/**
+ * Creates a cfg_schema_entry for a parameter that can be choosen
+ * from the layer2 interface keys
+ * @param p_name parameter name
+ * @param p_def parameter default value
+ * @param p_help help text for configuration entry
+ * @param args variable list of additional arguments
+ */
+#define CFG_VALIDATE_LAYER2_NET_KEY(p_name, p_def, p_help, args...)   CFG_VALIDATE_CHOICE_CB_ARG(p_name, p_def, p_help, oonf_layer2_cfg_get_l2net_key, OONF_LAYER2_NET_COUNT, NULL, ##args )
+
+/**
+ * Creates a cfg_schema_entry for a parameter that can be choosen
+ * from the layer2 interface keys
+ * @param p_name parameter name
+ * @param p_def parameter default value
+ * @param p_help help text for configuration entry
+ * @param args variable list of additional arguments
+ */
+#define CFG_VALIDATE_LAYER2_NEIGH_KEY(p_name, p_def, p_help, args...)   CFG_VALIDATE_CHOICE_CB_ARG(p_name, p_def, p_help, oonf_layer2_cfg_get_l2neigh_key, OONF_LAYER2_NEIGH_COUNT, NULL, ##args )
+
+/**
+ * Creates a cfg_schema_entry for a parameter that can be choosen
+ * from the layer2 data comparators
+ * @param p_name parameter name
+ * @param p_def parameter default value
+ * @param p_help help text for configuration entry
+ * @param args variable list of additional arguments
+ */
+#define CFG_VALIDATE_LAYER2_COMP(p_name, p_def, p_help, args...)   CFG_VALIDATE_CHOICE_CB_ARG(p_name, p_def, p_help, oonf_layer2_cfg_get_l2comp, OONF_LAYER2_DATA_CMP_COUNT, NULL, ##args )
+
+/**
+ * Creates a cfg_schema_entry for a parameter that can be choosen
+ * from the layer2 interface keys
+ * @param p_name parameter name
+ * @param p_def parameter default value
+ * @param p_help help text for configuration entry
+ * @param args variable list of additional arguments
+ */
+#define CFG_MAP_CHOICE_L2NET(p_reference, p_field, p_name, p_def, p_help, args...)   CFG_MAP_CHOICE_CB_ARG(p_reference, p_field, p_name, p_def, p_help, oonf_layer2_cfg_get_l2net_key, OONF_LAYER2_NET_COUNT, NULL, ##args )
+
+/**
+ * Creates a cfg_schema_entry for a parameter that can be choosen
+ * from the layer2 interface keys
+ * @param p_name parameter name
+ * @param p_def parameter default value
+ * @param p_help help text for configuration entry
+ * @param args variable list of additional arguments
+ */
+#define CFG_MAP_CHOICE_L2NEIGH(p_reference, p_field, p_name, p_def, p_help, args...)   CFG_MAP_CHOICE_CB_ARG(p_reference, p_field, p_name, p_def, p_help, oonf_layer2_cfg_get_l2neigh_key, OONF_LAYER2_NEIGH_COUNT, NULL, ##args )
+
+/**
+ * Creates a cfg_schema_entry for a parameter that can be choosen
+ * from the layer2 data comparators
+ * @param p_name parameter name
+ * @param p_def parameter default value
+ * @param p_help help text for configuration entry
+ * @param args variable list of additional arguments
+ */
+#define CFG_MAP_CHOICE_L2COMP(p_reference, p_field, p_name, p_def, p_help, args...)   CFG_MAP_CHOICE_CB_ARG(p_reference, p_field, p_name, p_def, p_help, oonf_layer2_cfg_get_l2comp, OONF_LAYER2_DATA_CMP_COUNT, NULL, ##args )
+
 /**
  * priorities of layer2 originators
  */
@@ -99,6 +161,9 @@ enum oonf_layer2_data_type {
   OONF_LAYER2_NO_DATA,
   OONF_LAYER2_INTEGER_DATA,
   OONF_LAYER2_BOOLEAN_DATA,
+  OONF_LAYER2_NETWORK_DATA,
+
+  OONF_LAYER2_DATA_TYPE_COUNT,
 };
 
 union oonf_layer2_value {
@@ -138,6 +203,22 @@ struct oonf_layer2_metadata {
   const int fraction;
 };
 
+/**
+ * Comparator options for layer2 data
+ */
+enum oonf_layer2_data_comparator_type {
+  OONF_LAYER2_DATA_CMP_EQUALS,
+  OONF_LAYER2_DATA_CMP_NOT_EQUALS,
+  OONF_LAYER2_DATA_CMP_LESSER,
+  OONF_LAYER2_DATA_CMP_LESSER_OR_EQUALS,
+  OONF_LAYER2_DATA_CMP_GREATER,
+  OONF_LAYER2_DATA_CMP_GREATER_OR_EQUALS,
+
+  OONF_LAYER2_DATA_CMP_COUNT,
+
+  OONF_LAYER2_DATA_CMP_ILLEGAL = -1,
+};
+
 /**
  * list of layer2 network metrics
  */
@@ -386,13 +467,20 @@ EXPORT void oonf_layer2_origin_remove(struct oonf_layer2_origin *origin);
 EXPORT int oonf_layer2_data_parse_string(union oonf_layer2_value *value,
     const struct oonf_layer2_metadata *meta,
     const char *input);
-EXPORT int oonf_layer2_data_to_string(char *buffer, size_t length,
+EXPORT const char *oonf_layer2_data_to_string(char *buffer, size_t length,
     const struct oonf_layer2_data *data,
     const struct oonf_layer2_metadata *meta, bool raw);
 EXPORT bool oonf_layer2_data_set(struct oonf_layer2_data *data,
     const struct oonf_layer2_origin *origin,
     enum oonf_layer2_data_type type,
     const union oonf_layer2_value *input);
+EXPORT bool oonf_layer2_data_compare(const union oonf_layer2_value *left,
+    const union oonf_layer2_value *right,
+    enum oonf_layer2_data_comparator_type comparator,
+    enum oonf_layer2_data_type data_type);
+EXPORT enum oonf_layer2_data_comparator_type oonf_layer2_data_get_comparator(const char *);
+EXPORT const char *oonf_layer2_data_get_comparator_string(enum oonf_layer2_data_comparator_type type);
+EXPORT const char *oonf_layer2_data_get_type_string(enum oonf_layer2_data_type type);
 
 EXPORT struct oonf_layer2_net *oonf_layer2_net_add(const char *ifname);
 EXPORT bool oonf_layer2_net_remove(
@@ -444,6 +532,10 @@ EXPORT const struct oonf_layer2_metadata *oonf_layer2_neigh_metadata_get(
     enum oonf_layer2_neighbor_index);
 EXPORT const struct oonf_layer2_metadata *oonf_layer2_net_metadata_get(
     enum oonf_layer2_network_index);
+EXPORT const char *oonf_layer2_cfg_get_l2net_key(size_t index, const void *unused);
+EXPORT const char *oonf_layer2_cfg_get_l2neigh_key(size_t index, const void *unused);
+EXPORT const char *oonf_layer2_cfg_get_l2comp(size_t index, const void *unused);
+
 EXPORT const char *oonf_layer2_net_get_type_name(enum oonf_layer2_network_type);
 
 EXPORT struct avl_tree *oonf_layer2_get_net_tree(void);
@@ -642,14 +734,14 @@ oonf_layer2_data_from_string(struct oonf_layer2_data *data,
   return oonf_layer2_data_set(data, origin, meta->type, &value);
 }
 
-static INLINE int
+static INLINE const char *
 oonf_layer2_net_data_to_string(char *buffer, size_t length,
     const struct oonf_layer2_data *data, enum oonf_layer2_network_index idx, bool raw) {
   return oonf_layer2_data_to_string(buffer, length, data,
       oonf_layer2_net_metadata_get(idx), raw);
 }
 
-static INLINE int
+static INLINE const char *
 oonf_layer2_neigh_data_to_string(char *buffer, size_t length,
     const struct oonf_layer2_data *data, enum oonf_layer2_neighbor_index idx, bool raw) {
   return oonf_layer2_data_to_string(buffer, length, data,
index e656877..980aa35 100644 (file)
@@ -212,8 +212,8 @@ static struct cfg_schema_entry _interface_entries[] = {
 };
 
 static struct cfg_schema_section _interface_section = {
-  .type = CFG_INTERFACE_SECTION,
-  .mode = CFG_INTERFACE_SECTION_MODE,
+  CFG_OSIF_SCHEMA_INTERFACE_SECTION_INIT,
+
   .cb_delta_handler = _cb_cfg_interface_changed,
   .entries = _interface_entries,
   .entry_count = ARRAYSIZE(_interface_entries),
@@ -1477,9 +1477,8 @@ _cb_cfg_interface_changed(void) {
   result = cfg_schema_tobin(&config, _interface_section.post,
       _interface_entries, ARRAYSIZE(_interface_entries));
   if (result) {
-    OONF_WARN(LOG_RFC5444,
-        "Could not convert "CFG_INTERFACE_SECTION" '%s' to binary (%d)",
-        ifname, -(result+1));
+    OONF_WARN(LOG_RFC5444, "Could not convert %s '%s' to binary (%d)",
+        _interface_section.type, ifname, -(result+1));
     goto interface_changed_cleanup;
   }
 
index 39fc131..ce8d371 100644 (file)
 #define OONF_OS_INTERFACE_SUBSYSTEM "os_interface"
 
 /*! interface configuration section name */
-#define CFG_INTERFACE_SECTION      "interface"
-
-/*! interface configuration section mode */
-#define CFG_INTERFACE_SECTION_MODE CFG_SSMODE_NAMED
+#define CFG_OSIF_SCHEMA_INTERFACE_SECTION_INIT      .type = "interface", .mode = CFG_SSMODE_NAMED
 
 /* include os-specific headers */
 #if defined(__linux__)
index e99746a..bbbd519 100644 (file)
@@ -141,8 +141,7 @@ static struct cfg_schema_entry _interface_entries[] = {
 };
 
 static struct cfg_schema_section _interface_section = {
-  .type = CFG_INTERFACE_SECTION,
-  .mode = CFG_INTERFACE_SECTION_MODE,
+  CFG_OSIF_SCHEMA_INTERFACE_SECTION_INIT,
   .cb_delta_handler = _cb_cfg_changed,
   .entries = _interface_entries,
   .entry_count = ARRAYSIZE(_interface_entries),
@@ -1497,7 +1496,8 @@ _handle_unused_parameter(const char *arg) {
 
   ifname = cfg_get_phy_if(ifbuf, arg);
 
-  cfg_db_add_namedsection(oonf_cfg_get_rawdb(), CFG_INTERFACE_SECTION, ifname);
+  cfg_db_add_namedsection(
+      oonf_cfg_get_rawdb(), _interface_section.type, ifname);
   return 0;
 }
 
@@ -1526,9 +1526,8 @@ _cb_cfg_changed(void) {
     result = cfg_schema_tobin(data, _interface_section.post,
         _interface_entries, ARRAYSIZE(_interface_entries));
     if (result) {
-      OONF_WARN(LOG_OS_INTERFACE,
-          "Could not convert "CFG_INTERFACE_SECTION" '%s' to binary (%d)",
-          data->name, -(result+1));
+      OONF_WARN(LOG_OS_INTERFACE, "Could not convert %s '%s' to binary (%d)",
+          _interface_section.type, data->name, -(result+1));
       return;
     }
   }
index 3c7a03a..51d21d9 100644 (file)
@@ -517,6 +517,7 @@ _routing_parse_nlmsg(struct os_route *route, struct nlmsghdr *msg) {
   rt_len = RTM_PAYLOAD(msg);
 
   if ((rt_msg->rtm_flags & RTM_F_CLONED) != 0) {
+    OONF_DEBUG(LOG_OS_ROUTING, "Received a cloned route");
     /* ignore cloned route events by returning the wildcard route */
     return 1;
   }
@@ -528,6 +529,7 @@ _routing_parse_nlmsg(struct os_route *route, struct nlmsghdr *msg) {
   route->p.family = rt_msg->rtm_family;
 
   if (route->p.family != AF_INET && route->p.family != AF_INET6) {
+    OONF_WARN(LOG_OS_ROUTING, "Got illegal route address family: %d", route->p.family);
     return -1;
   }
 
@@ -540,8 +542,8 @@ _routing_parse_nlmsg(struct os_route *route, struct nlmsghdr *msg) {
     }
   }
   if (route->p.type == OS_ROUTE_UNDEFINED) {
-    OONF_WARN(LOG_OS_ROUTING, "Got route type: %u", rt_msg->rtm_type);
-    return -1;
+    OONF_DEBUG(LOG_OS_ROUTING, "Got route type: %u", rt_msg->rtm_type);
+    return 2;
   }
 
   for(; RTA_OK(rt_attr, rt_len); rt_attr = RTA_NEXT(rt_attr,rt_len)) {
@@ -643,7 +645,7 @@ _cb_rtnetlink_message(struct nlmsghdr *msg) {
 
   if ((result = _routing_parse_nlmsg(&rt, msg))) {
     if (result < 0) {
-      OONF_WARN(LOG_OS_ROUTING, "Error while processing route reply");
+      OONF_WARN(LOG_OS_ROUTING, "Error while processing route reply (result %d)", result);
     }
     return;
   }
index 5a20b7d..d41e9ee 100644 (file)
@@ -53,6 +53,7 @@ IF (NOT OONF_STATIC_PLUGINS)
                              nhdpinfo
                              olsrv2
                              olsrv2info
+                             olsrv2_lan
                              netjsoninfo
                              lan_import
                              auto_ll4
index 4e6a060..714639d 100644 (file)
@@ -53,6 +53,7 @@ IF (NOT OONF_STATIC_PLUGINS)
                              nhdpinfo
                              olsrv2
                              olsrv2info
+                             olsrv2_lan
                              netjsoninfo
                              lan_import
                              auto_ll4