Partly working telnet code for l2config
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Wed, 18 Jul 2018 13:18:10 +0000 (15:18 +0200)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Wed, 18 Jul 2018 13:18:10 +0000 (15:18 +0200)
src/base/oonf_layer2.c
src/generic/layer2_config/layer2_config.c
src/libconfig/cfg_schema.c

index 65074be..66a642c 100644 (file)
@@ -1318,7 +1318,12 @@ oonf_layer2_validate_mac_lid(const struct cfg_schema_entry *entry,
   return -1;
 }
 
-
+/**
+ * Help generator for layer2 neighbor lid parameter
+ * See CFG_MAP_LAYER2_NEIGH_MAC_LID*() macros in oonf_layer2.h
+ * @param entry pointer to schema entry
+ * @param out pointer to autobuffer for validator output
+ */
 void
 oonf_layer2_help_mac_lid(const struct cfg_schema_entry *entry __attribute__((unused)), struct autobuf *out) {
   static const int8_t AF_TYPES[] = { AF_MAC48, AF_EUI64 };
@@ -1326,6 +1331,7 @@ oonf_layer2_help_mac_lid(const struct cfg_schema_entry *entry __attribute__((unu
   abuf_puts(out, CFG_HELP_INDENT_PREFIX "The parameter can also have an optional link id at the end,\n"
                  CFG_HELP_INDENT_PREFIX "a hexadecimal string separated by a ',' from the address in front of it.\n");
 }
+
 /**
  * Binary converter for layer2 neighbor keys including lid.
  * See CFG_MAP_LAYER2_NEIGH_MAC_LID() macro in oonf_layer2.h
index 4c0c44f..73fbacf 100644 (file)
  * @file
  */
 
+#include <oonf/oonf.h>
 #include <oonf/libcommon/avl.h>
 #include <oonf/libcommon/avl_comp.h>
-#include <oonf/oonf.h>
+#include <oonf/libcommon/string.h>
 #include <oonf/libconfig/cfg_schema.h>
 #include <oonf/libconfig/cfg_tobin.h>
 #include <oonf/libconfig/cfg_validate.h>
@@ -53,6 +54,7 @@
 #include <oonf/libcore/oonf_subsystem.h>
 #include <oonf/base/oonf_class.h>
 #include <oonf/base/oonf_layer2.h>
+#include <oonf/base/oonf_telnet.h>
 #include <oonf/base/oonf_timer.h>
 
 #include <oonf/generic/layer2_config/layer2_config.h>
@@ -115,11 +117,16 @@ static int _cb_neigh_value_validator(struct autobuf *out, const char *section_na
   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 enum oonf_telnet_result _cb_telnet_cmd(struct oonf_telnet_data *con);
+
+static void _set_if_data(struct oonf_layer2_net *l2net, struct l2_config_data *entry, struct oonf_layer2_origin *origin);
+static void _reset_if_data(struct oonf_layer2_net *l2net, struct l2_config_data *entry, struct oonf_layer2_origin *origin);
+
 static void _cb_update_l2net(void *);
 static void _cb_update_l2neigh(void *);
 static void _cb_reconfigure(struct oonf_timer_instance *);
 
-static void _configure_if_data(struct l2_config_if_data *if_data);
+static void _configure_if_data(const char *ifname, struct l2_config_data *data, size_t data_count);
 static void _cb_config_changed(void);
 
 /* define configuration entries */
@@ -171,7 +178,7 @@ static struct cfg_schema_entry _l2_config_if_entries[] = {
     "Sets an interface wide layer2 entry into the database."
     " 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(
+  [L2_NET_IP] = CFG_MAP_NETADDR_V46(l2_config_data, data.addr,
     "l2net_ip", "", "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."
@@ -254,6 +261,18 @@ static struct oonf_timer_class _reconfigure_timer = {
   .callback = _cb_reconfigure,
 };
 
+/* telnet command */
+static struct oonf_telnet_command _telnet_l2config[] = {
+  TELNET_CMD("l2config", _cb_telnet_cmd,
+             "l2config add/remove l2net <if> <l2net_key> <l2net_value> <l2net_overwrite>\n"
+             "l2config add/remove l2net_ip <if> <ip>\n"
+             "l2config add/remove l2default <if> <l2neigh_key> <l2neigh_value> <l2net_overwrite>\n"
+             "l2config add/remove l2neighbor <if> l2neigh_key> <l2neigh_value> <l2neigh_mac> <l2net_overwrite>\n"
+             "l2config add/remove l2neighbor_ip <l2neigh_mac> <l2neigh_ip> <l2net_overwrite>\n"
+             "l2config add/remove l2destination <l2neigh_mac> <l2neigh_dst> <l2net_overwrite>\n"
+  ),
+};
+
 /**
  * Subsystem constructor
  * @return always returns 0
@@ -269,6 +288,7 @@ _init(void) {
 
   oonf_timer_add(&_reconfigure_timer);
 
+  oonf_telnet_add(&_telnet_l2config[0]);
   avl_init(&_if_data_tree, avl_comp_strcasecmp, false);
   return 0;
 }
@@ -283,6 +303,7 @@ _cleanup(void) {
   avl_for_each_element_safe(&_if_data_tree, if_data, _node, if_data_it) {
     _remove_if_data(if_data);
   }
+  oonf_telnet_remove(&_telnet_l2config[0]);
   oonf_timer_remove(&_reconfigure_timer);
 
   oonf_class_extension_remove(&_l2net_listener);
@@ -454,6 +475,123 @@ _cb_neigh_value_tobin(struct cfg_schema_entry *entries __attribute__((unused)),
   return 0;
 }
 
+static enum oonf_telnet_result
+_cb_telnet_cmd(struct oonf_telnet_data *con) {
+  struct oonf_layer2_origin *origin;
+  struct oonf_layer2_net *l2net;
+  struct l2_config_data data;
+  const char *param, *next;
+  char ifname[IF_NAMESIZE];
+  struct const_strarray strvalue;
+  bool add;
+
+#if 0
+             "l2config add/remove l2net <if> <l2net_key> <l2net_value> <l2net_overwrite>\n"
+             "l2config add/remove l2net_ip <if> <ip>\n"
+             "l2config add/remove l2default <if> <l2neigh_key> <l2neigh_value> <l2net_overwrite>\n"
+             "l2config add/remove l2neighbor <if> <l2neigh_key> <l2neigh_value> <l2neigh_mac> <l2net_overwrite>\n"
+             "l2config add/remove l2neighbor_ip <if> <l2neigh_key> <l2neigh_ip> <l2net_overwrite>\n"
+             "l2config add/remove l2destination <if> <l2neigh_key> <l2neigh_dst> <l2net_overwrite>\n"
+#endif
+
+  if (!con->parameter || !con->parameter[0]) {
+    abuf_puts(con->out, "Missing parameters for telnet command\n");
+    return TELNET_RESULT_ACTIVE;
+  }
+
+  memset(&data, 0, sizeof(data));
+
+  param = con->parameter;
+  if ((next = str_hasnextword(param, "add"))) {
+    add = true;
+  }
+  else if ((next = str_hasnextword(param, "remove"))) {
+    add = false;
+  }
+  else {
+    abuf_puts(con->out, "First parameter must be 'add' or 'remove'");
+    return TELNET_RESULT_ACTIVE;
+  }
+
+  param = next;
+  if ((next = str_hasnextword(param, "l2net"))) {
+    data.config_type = L2_NET;
+  }
+  else if ((next = str_hasnextword(param, "l2net_ip"))) {
+    data.config_type = L2_NET_IP;
+  }
+  else if ((next = str_hasnextword(param, "l2default"))) {
+    data.config_type = L2_DEF;
+  }
+  else if ((next = str_hasnextword(param, "l2neighbor"))) {
+    data.config_type = L2_NEIGH;
+  }
+  else if ((next = str_hasnextword(param, "l2neighbor_ip"))) {
+    data.config_type = L2_NEIGH_IP;
+  }
+  else if ((next = str_hasnextword(param, "l2destination"))) {
+    data.config_type = L2_DST;
+  }
+  else {
+    abuf_puts(con->out, "Second parameter must be 'l2net', 'l2default', 'l2neighbor', 'l2neighbor_ip' or 'l2destination'");
+    return TELNET_RESULT_ACTIVE;
+  }
+
+  param = next;
+  if (!(next = str_cpynextword(ifname, param, IF_NAMESIZE))) {
+    abuf_puts(con->out, "Not enough parameters");
+    return TELNET_RESULT_ACTIVE;
+  }
+  abuf_puts(con->out, "1\n");
+
+  if (data.config_type == L2_NET_IP) {
+    if (cfg_schema_validate_netaddr(&_l2_config_if_entries[data.config_type], "telnet", next, con->out)) {
+      return TELNET_RESULT_ACTIVE;
+    }
+  }
+  else {
+    if (cfg_schema_validate_tokens(&_l2_config_if_entries[data.config_type], "telnet", next, con->out)) {
+      return TELNET_RESULT_ACTIVE;
+    }
+  }
+
+  abuf_appendf(con->out, "2: '%s'\n", next);
+  strvalue.length = strlen(next);
+  strvalue.value = next;
+  if (data.config_type == L2_NET_IP) {
+    if (cfg_schema_tobin_netaddr(&_l2_config_if_entries[data.config_type], &strvalue, &data)) {
+      abuf_puts(con->out, "Could not convert input data to binary address\n");
+      return TELNET_RESULT_ACTIVE;
+    }
+  }
+  else {
+    if (cfg_schema_tobin_tokens(&_l2_config_if_entries[data.config_type], &strvalue, &data)) {
+      abuf_puts(con->out, "Could not convert input data to binary\n");
+      return TELNET_RESULT_ACTIVE;
+    }
+  }
+  abuf_puts(con->out, "3\n");
+
+  origin = data.overwrite ? &_l2_origin_current_overwrite : &_l2_origin_current_configured;
+  if (add) {
+    l2net = oonf_layer2_net_add(ifname);
+    if (!l2net) {
+      abuf_puts(con->out, "Could not generate layer2 interface entry");
+      return TELNET_RESULT_ACTIVE;
+    }
+    _set_if_data(l2net, &data, origin);
+  }
+  else {
+    l2net = oonf_layer2_net_get(ifname);
+    if (l2net) {
+      _reset_if_data(l2net, &data, origin);
+    }
+  }
+
+  return TELNET_RESULT_ACTIVE;
+}
+
+
 /**
  * Callback when a layer2 network entry is changed/removed
  * @param ptr l2net entry
@@ -499,7 +637,97 @@ _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);
+  _configure_if_data(if_data->interf, if_data->d, if_data->count);
+}
+
+static void
+_set_if_data(struct oonf_layer2_net *l2net, struct l2_config_data *entry, struct oonf_layer2_origin *origin) {
+  struct oonf_layer2_neigh *l2neigh;
+
+  switch (entry->config_type) {
+    case L2_NET:
+      oonf_layer2_data_set(&l2net->data[entry->data_idx], origin,
+                           oonf_layer2_net_metadata_get(entry->data_idx), &entry->data);
+      break;
+    case L2_NET_IP:
+      oonf_layer2_net_add_ip(l2net, origin, &entry->data.addr);
+      break;
+    case L2_DEF:
+      oonf_layer2_data_set(&l2net->neighdata[entry->data_idx], origin,
+                           oonf_layer2_neigh_metadata_get(entry->data_idx), &entry->data);
+      break;
+    case L2_NEIGH:
+      l2neigh = oonf_layer2_neigh_add_lid(l2net, &entry->key);
+      if (l2neigh) {
+        oonf_layer2_data_set(&l2neigh->data[entry->data_idx], origin,
+                             oonf_layer2_neigh_metadata_get(entry->data_idx), &entry->data);
+      }
+      break;
+    case L2_NEIGH_IP:
+      l2neigh = oonf_layer2_neigh_add_lid(l2net, &entry->key);
+      if (l2neigh) {
+        oonf_layer2_neigh_add_ip(l2neigh, origin, &entry->data.addr);
+      }
+      break;
+    case L2_DST:
+      l2neigh = oonf_layer2_neigh_add_lid(l2net, &entry->key);
+      if (l2neigh) {
+        oonf_layer2_destination_add(l2neigh, &entry->data.addr, origin);
+      }
+      break;
+    default:
+      break;
+  }
+}
+
+static void
+_reset_if_data(struct oonf_layer2_net *l2net, struct l2_config_data *entry, struct oonf_layer2_origin *origin) {
+  struct oonf_layer2_neighbor_address *l2_remote_ip;
+  struct oonf_layer2_peer_address *l2_local_peer;
+  struct oonf_layer2_destination *l2_neigh_dest;
+  struct oonf_layer2_neigh *l2neigh;
+
+  switch (entry->config_type) {
+    case L2_NET:
+      oonf_layer2_data_reset(&l2net->data[entry->data_idx]);
+
+      break;
+    case L2_NET_IP:
+      l2_local_peer = oonf_layer2_net_get_local_ip(l2net, &entry->data.addr);
+      if (l2_local_peer) {
+        oonf_layer2_net_remove_ip(l2_local_peer, origin);
+      }
+      break;
+    case L2_DEF:
+      oonf_layer2_data_reset(&l2net->neighdata[entry->data_idx]);
+      break;
+    case L2_NEIGH:
+      l2neigh = oonf_layer2_neigh_get_lid(l2net, &entry->key);
+      if (l2neigh) {
+        oonf_layer2_data_reset(&l2neigh->data[entry->data_idx]);
+      }
+      break;
+    case L2_NEIGH_IP:
+      l2neigh = oonf_layer2_neigh_get_lid(l2net, &entry->key);
+      if (l2neigh) {
+        l2_remote_ip = oonf_layer2_neigh_get_remote_ip(l2neigh, &entry->data.addr);
+        if (l2_remote_ip) {
+          oonf_layer2_neigh_remove_ip(l2_remote_ip, origin);
+        }
+      }
+      break;
+    case L2_DST:
+      l2neigh = oonf_layer2_neigh_get_lid(l2net, &entry->key);
+      if (l2neigh) {
+        l2_neigh_dest = oonf_layer2_destination_get(l2neigh, &entry->data.addr);
+        if (l2_neigh_dest) {
+          oonf_layer2_destination_remove(l2_neigh_dest);
+        }
+      }
+      break;
+    default:
+      break;
+  }
 }
 
 /**
@@ -507,16 +735,13 @@ _cb_reconfigure(struct oonf_timer_instance *timer) {
  * @param if_data interface data
  */
 static void
-_configure_if_data(struct l2_config_if_data *if_data) {
-  struct oonf_layer2_neigh *l2neigh;
+_configure_if_data(const char *ifname, struct l2_config_data *data, size_t data_count) {
   struct oonf_layer2_net *l2net;
-  struct l2_config_data *entry;
-  struct oonf_layer2_origin *origin;
   size_t i;
 
-  l2net = oonf_layer2_net_get(if_data->interf);
-  if (!l2net && if_data->count > 0) {
-    l2net = oonf_layer2_net_add(if_data->interf);
+  l2net = oonf_layer2_net_get(ifname);
+  if (!l2net && data_count > 0) {
+    l2net = oonf_layer2_net_add(ifname);
     if (!l2net) {
       return;
     }
@@ -527,52 +752,13 @@ _configure_if_data(struct l2_config_if_data *if_data) {
     oonf_layer2_net_relabel(l2net, &_l2_origin_old, &_l2_origin_current_configured);
     oonf_layer2_net_relabel(l2net, &_l2_origin_old, &_l2_origin_current_overwrite);
 
-    for (i = 0; i < if_data->count; i++) {
-      entry = &if_data->d[i];
-
-      origin = entry->overwrite ? &_l2_origin_current_overwrite : &_l2_origin_current_configured;
-      switch (entry->config_type) {
-        case L2_NET:
-          oonf_layer2_data_set(&l2net->data[entry->data_idx], origin,
-                               oonf_layer2_net_metadata_get(entry->data_idx), &entry->data);
-          break;
-        case L2_NET_IP:
-          oonf_layer2_net_add_ip(l2net, origin, &entry->data.addr);
-          break;
-        case L2_DEF:
-          oonf_layer2_data_set(&l2net->neighdata[entry->data_idx], origin,
-                               oonf_layer2_neigh_metadata_get(entry->data_idx), &entry->data);
-          break;
-        case L2_NEIGH:
-          l2neigh = oonf_layer2_neigh_add_lid(l2net, &entry->key);
-          if (l2neigh) {
-            oonf_layer2_data_set(&l2neigh->data[entry->data_idx], origin,
-                                 oonf_layer2_neigh_metadata_get(entry->data_idx), &entry->data);
-          }
-          break;
-        case L2_NEIGH_IP:
-          l2neigh = oonf_layer2_neigh_add_lid(l2net, &entry->key);
-          if (l2neigh) {
-            oonf_layer2_neigh_add_ip(l2neigh, origin, &entry->data.addr);
-          }
-          break;
-        case L2_DST:
-          l2neigh = oonf_layer2_neigh_add_lid(l2net, &entry->key);
-          if (l2neigh) {
-            oonf_layer2_destination_add(l2neigh, &entry->data.addr, origin);
-          }
-          break;
-        default:
-          break;
-      }
+    for (i = 0; i < data_count; i++) {
+      _set_if_data(l2net, &data[i], data[i].overwrite ? &_l2_origin_current_overwrite : &_l2_origin_current_configured);
     }
 
     /* remove old data */
     oonf_layer2_net_remove(l2net, &_l2_origin_old);
   }
-
-  /* stop update timer */
-  oonf_timer_stop(&if_data->_reconfigure_timer);
 }
 
 /**
@@ -642,5 +828,8 @@ _cb_config_changed(void) {
   if_data->count = total;
 
   /* reconfigure layer2 database */
-  _configure_if_data(if_data);
+  _configure_if_data(if_data->interf, if_data->d, if_data->count);
+
+  /* stop update timer */
+  oonf_timer_stop(&if_data->_reconfigure_timer);
 }
index 86e6f63..d56714e 100644 (file)
@@ -681,7 +681,7 @@ cfg_schema_help_token(const struct cfg_schema_entry *entry, struct autobuf *out)
  */
 int
 cfg_schema_tobin_strptr(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
-  if (s_entry->list) {
+  if (s_entry->list && strlen(value->value) < value->length) {
     /* we don't support direct list conversion to binary */
     return -1;
   }
@@ -698,7 +698,7 @@ cfg_schema_tobin_strptr(const struct cfg_schema_entry *s_entry, const struct con
  */
 int
 cfg_schema_tobin_strarray(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
-  if (s_entry->list) {
+  if (s_entry->list && strlen(value->value) < value->length) {
     /* we don't support direct list conversion to binary */
     return -1;
   }
@@ -716,7 +716,7 @@ cfg_schema_tobin_strarray(const struct cfg_schema_entry *s_entry, const struct c
  */
 int
 cfg_schema_tobin_choice(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
-  if (s_entry->list) {
+  if (s_entry->list && strlen(value->value) < value->length) {
     /* we don't support direct list conversion to binary */
     return -1;
   }
@@ -734,7 +734,7 @@ cfg_schema_tobin_choice(const struct cfg_schema_entry *s_entry, const struct con
  */
 int
 cfg_schema_tobin_int(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
-  if (s_entry->list) {
+  if (s_entry->list && strlen(value->value) < value->length) {
     /* we don't support direct list conversion to binary */
     return -1;
   }
@@ -752,7 +752,7 @@ cfg_schema_tobin_int(const struct cfg_schema_entry *s_entry, const struct const_
  */
 int
 cfg_schema_tobin_netaddr(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
-  if (s_entry->list) {
+  if (s_entry->list && strlen(value->value) < value->length) {
     /* we don't support direct list conversion to binary */
     return -1;
   }
@@ -796,7 +796,7 @@ cfg_schema_tobin_bitmap256(
  */
 int
 cfg_schema_tobin_bool(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
-  if (s_entry->list) {
+  if (s_entry->list && strlen(value->value) < value->length) {
     /* we don't support direct list conversion to binary */
     return -1;
   }
@@ -827,7 +827,7 @@ cfg_schema_tobin_stringlist(
  */
 int
 cfg_schema_tobin_tokens(const struct cfg_schema_entry *s_entry, const struct const_strarray *value, void *reference) {
-  if (s_entry->list) {
+  if (s_entry->list && strlen(value->value) < value->length) {
     /* we don't support direct list conversion to binary */
     return -1;
   }