Add remotecontrol plugin
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Wed, 21 Sep 2011 06:08:59 +0000 (08:08 +0200)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Wed, 21 Sep 2011 06:08:59 +0000 (08:08 +0200)
18 files changed:
CMake.config
lib/CMakeLists.txt
lib/remotecontrol/CMakeLists.txt [new file with mode: 0644]
lib/remotecontrol/src/remotecontrol.c [new file with mode: 0644]
lib/remotecontrol/src/remotecontrol.h [new file with mode: 0644]
src/config/cfg_cmd.c
src/core/olsr.h
src/core/olsr_cfg.c
src/core/olsr_cfg.h
src/core/olsr_packet_socket.c
src/core/olsr_plugins.c
src/core/olsr_plugins.h
src/core/olsr_stream_socket.c
src/core/olsr_stream_socket.h
src/core/olsr_telnet.c
src/core/olsr_timer.h
src/core/os_net_generic.c
src/olsr.c

index ad97fe3..7fa59fe 100644 (file)
@@ -5,7 +5,7 @@ set (CMAKE_BUILD_TYPE Debug)
 set (OLSRD_VERSION 0.7.0)
 
 # set static plugins (space separated list of plugin names)
-set (OLSRD_STATIC_PLUGINS cfgparser_compact cfgio_file)
+set (OLSRD_STATIC_PLUGINS cfgparser_compact cfgio_file remotecontrol)
 
 # allow removal of Logging levels from code
 set (OLSRD_REMOVE_DEBUG_LOGGING false)
index 7dbf01c..c82944a 100644 (file)
@@ -1,3 +1,4 @@
 # add subdirectories
 add_subdirectory(cfgparser_compact)
 add_subdirectory(cfgio_file)
+add_subdirectory(remotecontrol)
diff --git a/lib/remotecontrol/CMakeLists.txt b/lib/remotecontrol/CMakeLists.txt
new file mode 100644 (file)
index 0000000..349781c
--- /dev/null
@@ -0,0 +1,6 @@
+# set library name
+SET (libname "remotecontrol")
+SET (source "${CMAKE_CURRENT_SOURCE_DIR}/src/remotecontrol.c")
+
+# use generic plugin cmake file
+include (../plugin.cmake)
diff --git a/lib/remotecontrol/src/remotecontrol.c b/lib/remotecontrol/src/remotecontrol.c
new file mode 100644 (file)
index 0000000..6cab553
--- /dev/null
@@ -0,0 +1,476 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2009, 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.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#include <stdlib.h>
+
+#include "common/common_types.h"
+#include "common/autobuf.h"
+#include "common/avl.h"
+#include "common/avl_comp.h"
+#include "common/netaddr.h"
+#include "common/string.h"
+
+#include "config/cfg_cmd.h"
+
+#include "olsr_cfg.h"
+#include "olsr_logging.h"
+#include "olsr_memcookie.h"
+#include "olsr_plugins.h"
+#include "olsr_telnet.h"
+#include "olsr_timer.h"
+#include "olsr.h"
+#include "remotecontrol.h"
+
+static int _plugin_load(void);
+static int _plugin_enable(void);
+static int _plugin_disable(void);
+
+static enum olsr_telnet_result _handle_resource(struct olsr_telnet_session *con,
+    const char *cmd, const char *param);
+static enum olsr_telnet_result _handle_log(struct olsr_telnet_session *con,
+    const char *cmd, const char *param);
+static enum olsr_telnet_result _handle_config(struct olsr_telnet_session *con,
+    const char *cmd, const char *param);
+static enum olsr_telnet_result _update_logfilter(
+    struct olsr_telnet_session *con,
+    const char *cmd, const char *param, const char *current, bool value);
+
+static bool _print_memory(struct autobuf *buf);
+static bool _print_timer(struct autobuf *buf);
+
+static void _stop_logging(struct olsr_telnet_session *session);
+
+static void _print_log(struct log_handler_entry *,
+    enum log_severity, enum log_source,
+    bool, const char *, int, char *, int, int);
+static const char *_str_hasnextword (const char *buffer, const char *word);
+
+/* TODO: plugin configuration */
+
+/* plugin parameters */
+OLSR_PLUGIN7 {
+  .descr = "OLSRD remote control and debug plugin",
+  .author = "Henning Rogge",
+  .load = _plugin_load,
+  .enable = _plugin_enable,
+  .disable = _plugin_disable,
+};
+
+/* command callbacks and names */
+static struct olsr_telnet_command _telnet_cmds[] = {
+  TELNET_CMD("resources", _handle_resource,
+      "\"resources memory\": display information about memory usage\n"
+      "\"resources timer\": display information about active timers\n"
+      ),
+  TELNET_CMD("log", _handle_log,
+      "\"log\":      continuous output of logging to this console\n"
+      "\"log show\": show configured logging option for debuginfo output\n"
+      "\"log add <severity> <source1> <source2> ...\": Add one or more sources of a defined severity for logging\n"
+      "\"log remove <severity> <source1> <source2> ...\": Remove one or more sources of a defined severity for logging\n"
+      ),
+  TELNET_CMD("config", _handle_config,
+      "\"config commit\":                                   Commit changed configuration\n"
+      "\"config revert\":                                   Revert to active configuration\n"
+      "\"config schema\":                                   Display all allowed section types of configuration\n"
+      "\"config schema <section_type>\":                    Display all allowed entries of one configuration section\n"
+      "\"config schema <section_type.key>\":                Display help text for configuration entry\n"
+      "\"config load <SOURCE>\":                            Load configuration from a SOURCE\n"
+      "\"config save <TARGET>\":                            Save configuration to a TARGET\n"
+      "\"config set <section_type>.\":                      Add an unnamed section to the configuration\n"
+      "\"config set <section_type>.<key>=<value>\":         Add a key/value pair to an unnamed section\n"
+      "\"config set <section_type>[<name>].\":              Add a named section to the configuration\n"
+      "\"config set <section_type>[<name>].<key>=<value>\": Add a key/value pair to a named section\n"
+      "\"config remove <section_type>.\":                   Remove all sections of a certain type\n"
+      "\"config remove <section_type>.<key>\":              Remove a key in an unnamed section\n"
+      "\"config remove <section_type>[<name>].\":           Remove a named section\n"
+      "\"config remove <section_type>[<name>].<key>\":      Remove a key in a named section\n"
+      "\"config get\":                                      Show all section types in database\n"
+      "\"config get <section_type>.\":                      Show all named sections of a certain type\n"
+      "\"config get <section_type>.<key>\":                 Show the value(s) of a key in an unnamed section\n"
+      "\"config get <section_type>[<name>].<key>\":         Show the value(s) of a key in a named section\n"
+      "\"config format <FORMAT>\":                          Set the format for loading/saving data\n"
+      "\"config format AUTO\":                              Set the format to automatic detection\n"
+      ),
+};
+
+/* variables for log access */
+static struct log_handler_mask _logging_mask;
+static int _log_source_maxlen, _log_severity_maxlen;
+static struct olsr_telnet_session *_log_session;
+
+static struct log_handler_entry _log_handler = {
+  .bitmask_ptr = &_logging_mask,
+  .handler = _print_log
+};
+
+/**
+ * Initialize remotecontrol plugin
+ * @return 0 if plugin was initialized, -1 if an error happened
+ */
+static int
+_plugin_load(void)
+{
+  int i;
+
+  /* calculate maximum length of log source names */
+  _log_source_maxlen = 0;
+  for (i=1; i<LOG_SOURCE_COUNT; i++) {
+    int len = strlen(LOG_SOURCE_NAMES[i]);
+
+    if (len > _log_source_maxlen) {
+      _log_source_maxlen = len;
+    }
+  }
+
+  /* calculate maximum length of log severity names */
+  _log_severity_maxlen = 0;
+  for (i=1; i<LOG_SEVERITY_COUNT; i++) {
+    int len = strlen(LOG_SEVERITY_NAMES[i]);
+
+    if (len > _log_severity_maxlen) {
+      _log_severity_maxlen = len;
+    }
+  }
+
+  return 0;
+}
+
+/**
+ * Deactivate remotecontrol plugin
+ * @return 0 if plugin was disabled, -1 if an error happened
+ */
+static int
+_plugin_disable(void)
+{
+  size_t i;
+
+  for (i=0; i<ARRAYSIZE(_telnet_cmds); i++) {
+    olsr_telnet_remove(&_telnet_cmds[i]);
+  }
+
+  if (_log_session) {
+    olsr_stream_close(&_log_session->session);
+    olsr_log_removehandler(&_log_handler);
+    _log_session = NULL;
+  }
+  return 0;
+}
+
+/**
+ * Enable remotecontrol plugin
+ * @return 0 if plugin was enabled, -1 if an error happened
+ */
+static int
+_plugin_enable(void)
+{
+  size_t i;
+
+  _log_session = NULL;
+
+  for (i=0; i<ARRAYSIZE(_telnet_cmds); i++) {
+    olsr_telnet_add(&_telnet_cmds[i]);
+  }
+
+  /* copy global logging mask */
+  memcpy(&_logging_mask, &log_global_mask, sizeof(log_global_mask));
+
+  return 0;
+}
+
+static bool
+_print_memory(struct autobuf *buf) {
+  struct olsr_memcookie_info *c, *iterator;
+
+  OLSR_FOR_ALL_COOKIES(c, iterator) {
+    if (abuf_appendf(buf, "%-25s (MEMORY) size: %lu usage: %u freelist: %u\n",
+        c->ci_name, (unsigned long)c->ci_size, c->ci_usage, c->ci_free_list_usage) < 0) {
+      return true;
+    }
+  }
+  return false;
+}
+
+static bool
+_print_timer(struct autobuf *buf) {
+  struct olsr_timer_info *t, *iterator;
+
+  OLSR_FOR_ALL_TIMERS(t, iterator) {
+    if (abuf_appendf(buf, "%-25s (TIMER) usage: %u changes: %u\n",
+        t->name, t->usage, t->changes) < 0) {
+      return true;
+    }
+  }
+  return false;
+}
+
+static enum olsr_telnet_result
+_handle_resource(struct olsr_telnet_session *con,
+    const char *cmd __attribute__ ((unused)), const char *param)
+{
+  if (param == NULL || strcasecmp(param, "memory") == 0) {
+    if (abuf_puts(&con->session.out, "Memory cookies:\n") < 0) {
+      return TELNET_RESULT_ABUF_ERROR;
+    }
+
+    if (_print_memory(&con->session.out)) {
+      return TELNET_RESULT_ABUF_ERROR;
+    }
+  }
+
+  if (param == NULL || strcasecmp(param, "timer") == 0) {
+    if (abuf_puts(&con->session.out, "\nTimer cookies:\n") < 0) {
+      return TELNET_RESULT_ABUF_ERROR;
+    }
+
+    if (_print_timer(&con->session.out)) {
+      return TELNET_RESULT_ABUF_ERROR;
+    }
+  }
+  return TELNET_RESULT_ACTIVE;
+}
+
+static enum olsr_telnet_result
+_update_logfilter(struct olsr_telnet_session *con,
+    const char *cmd, const char *param, const char *current, bool value) {
+  const char *next;
+  int src, sev;
+
+  for (sev = 0; sev < LOG_SEVERITY_COUNT; sev++) {
+    if ((next = _str_hasnextword(current, LOG_SEVERITY_NAMES[sev])) != NULL) {
+      break;
+    }
+  }
+  if (sev == LOG_SEVERITY_COUNT) {
+    abuf_appendf(&con->session.out, "Error, unknown severity in command: %s %s\n", cmd, param);
+    return TELNET_RESULT_ACTIVE;
+  }
+
+  current = next;
+  while (current && *current) {
+    for (src = 0; src < LOG_SOURCE_COUNT; src++) {
+      if ((next = _str_hasnextword(current, LOG_SOURCE_NAMES[src])) != NULL) {
+        _logging_mask.mask[sev][src] = value;
+        break;
+      }
+    }
+    if (src == LOG_SOURCE_COUNT) {
+      abuf_appendf(&con->session.out, "Error, unknown source in command: %s %s\n", cmd, param);
+      return TELNET_RESULT_ACTIVE;
+    }
+    current = next;
+  }
+
+  olsr_log_updatemask();
+  return TELNET_RESULT_ACTIVE;
+}
+
+static void
+_print_log(struct log_handler_entry *h __attribute__((unused)),
+    enum log_severity severity __attribute__((unused)),
+    enum log_source source __attribute__((unused)),
+    bool no_header __attribute__((unused)),
+    const char *file __attribute__((unused)),
+    int line __attribute__((unused)),
+    char *buffer,
+    int timeLength __attribute__((unused)),
+    int prefixLength __attribute__((unused)))
+{
+  abuf_puts(&_log_session->session.out, buffer);
+  abuf_puts(&_log_session->session.out, "\n");
+
+  olsr_stream_flush(&_log_session->session);
+}
+
+static void
+_stop_logging(struct olsr_telnet_session *session) {
+  olsr_log_removehandler(&_log_handler);
+
+  session->stop_handler = NULL;
+  _log_session = NULL;
+}
+
+static enum olsr_telnet_result
+_handle_log(struct olsr_telnet_session *con, const char *cmd, const char *param) {
+  const char *next;
+  int src;
+
+  if (param == NULL) {
+    if (con->stop_handler) {
+      abuf_puts(&con->session.out, "Error, you cannot stack continuous output commands\n");
+      return TELNET_RESULT_ACTIVE;
+    }
+    if (_log_session != NULL) {
+      abuf_puts(&con->session.out, "Error, debuginfo cannot handle concurrent logging\n");
+      return TELNET_RESULT_ACTIVE;
+    }
+
+    _log_session = con;
+    con->stop_handler = _stop_logging;
+
+    olsr_log_addhandler(&_log_handler);
+    return TELNET_RESULT_CONTINOUS;
+  }
+
+  if (strcasecmp(param, "show") == 0) {
+    abuf_appendf(&con->session.out, "%*s %6s %6s %6s\n",
+        _log_source_maxlen, "",
+        LOG_SEVERITY_NAMES[SEVERITY_DEBUG],
+        LOG_SEVERITY_NAMES[SEVERITY_INFO],
+        LOG_SEVERITY_NAMES[SEVERITY_WARN]);
+
+    for (src=0; src<LOG_SOURCE_COUNT; src++) {
+      abuf_appendf(&con->session.out, "%*s %*s %*s %*s\n",
+        _log_source_maxlen, LOG_SOURCE_NAMES[src],
+        (int)sizeof(LOG_SEVERITY_NAMES[SEVERITY_DEBUG]),
+        _logging_mask.mask[SEVERITY_DEBUG][src] ? "*" : "",
+        (int)sizeof(LOG_SEVERITY_NAMES[SEVERITY_INFO]),
+        _logging_mask.mask[SEVERITY_INFO][src] ? "*" : "",
+        (int)sizeof(LOG_SEVERITY_NAMES[SEVERITY_WARN]),
+        _logging_mask.mask[SEVERITY_WARN][src] ? "*" : "");
+    }
+    return TELNET_RESULT_ACTIVE;
+  }
+
+  if ((next = _str_hasnextword(param, "add")) != NULL) {
+    return _update_logfilter(con, cmd, param, next, true);
+  }
+
+  if ((next = _str_hasnextword(param, "remove")) != NULL) {
+    return _update_logfilter(con, cmd, param, next, false);
+  }
+
+  return TELNET_RESULT_UNKNOWN_COMMAND;
+}
+
+static enum olsr_telnet_result
+_handle_config(struct olsr_telnet_session *con,
+    const char *cmd __attribute__((unused)), const char *param) {
+  const char *next = NULL;
+
+  if (param == NULL || *param == 0) {
+    abuf_puts(&con->session.out, "Error, 'config' needs a parameter\n");
+    return TELNET_RESULT_ACTIVE;
+  }
+
+  if ((next = _str_hasnextword(param, "commit"))) {
+    if (!cfg_schema_validate(olsr_cfg_get_rawdb(),
+        false, false, true, &con->session.out)) {
+      olsr_commit();
+    }
+  }
+  else if ((next = _str_hasnextword(param, "rollback"))) {
+    olsr_cfg_rollback();
+  }
+  else if ((next = _str_hasnextword(param, "format"))) {
+    cfg_cmd_handle_format(olsr_cfg_get_instance(), next);
+  }
+  else if ((next = _str_hasnextword(param, "get"))) {
+    cfg_cmd_handle_get(olsr_cfg_get_instance(),
+        olsr_cfg_get_rawdb(), next, &con->session.out);
+  }
+  else if ((next = _str_hasnextword(param, "load"))) {
+    cfg_cmd_handle_load(olsr_cfg_get_instance(),
+        olsr_cfg_get_rawdb(), next, &con->session.out);
+  }
+  else if ((next = _str_hasnextword(param, "remove"))) {
+    cfg_cmd_handle_remove(olsr_cfg_get_instance(),
+        olsr_cfg_get_rawdb(), next, &con->session.out);
+  }
+  else if ((next = _str_hasnextword(param, "save"))) {
+    cfg_cmd_handle_save(olsr_cfg_get_instance(),
+        olsr_cfg_get_rawdb(), next, &con->session.out);
+  }
+  else if ((next = _str_hasnextword(param, "schema"))) {
+    cfg_cmd_handle_schema(
+        olsr_cfg_get_rawdb(), next, &con->session.out);
+  }
+  else if ((next = _str_hasnextword(param, "set"))) {
+    cfg_cmd_handle_set(olsr_cfg_get_instance(),
+        olsr_cfg_get_rawdb(), next, &con->session.out);
+  }
+  else {
+    return TELNET_RESULT_UNKNOWN_COMMAND;
+  }
+
+  return TELNET_RESULT_ACTIVE;
+}
+/**
+ * Check if a string starts with a certain word. The function
+ * is not case sensitive.
+ * @param buffer pointer to string
+ * @param word pointer to the word
+ * @return pointer to the string behind the word, NULL if no match
+ */
+static const char *
+_str_hasnextword (const char *buffer, const char *word) {
+  /* skip whitespaces first */
+  while (isblank(*buffer)) {
+    buffer++;
+  }
+
+  while (*word != 0 && *buffer != 0 && !isblank(*buffer) && tolower(*word) == tolower(*buffer)) {
+    word++;
+    buffer++;
+  }
+
+  /* complete match ? */
+  if (*word == 0) {
+    while (isblank(*buffer)) {
+      buffer++;
+    }
+    return buffer;
+  }
+  return NULL;
+}
+
+
+/*
+ * Local Variables:
+ * mode: c
+ * style: linux
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/lib/remotecontrol/src/remotecontrol.h b/lib/remotecontrol/src/remotecontrol.h
new file mode 100644 (file)
index 0000000..c03b42e
--- /dev/null
@@ -0,0 +1,56 @@
+
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2009, 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.
+ *
+ */
+
+/*
+ * Dynamic linked library for the olsr.org olsr daemon
+ */
+
+#ifndef _OLSRD_DEBUGINFO
+#define _OLSRD_DEBUGINFO
+
+#endif
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * End:
+ */
index b65b879..f96b991 100644 (file)
@@ -326,7 +326,7 @@ cfg_cmd_handle_schema(struct cfg_db *db,
     return 1;
   }
 
-  if (arg == NULL) {
+  if (arg == NULL || *arg == 0) {
     abuf_puts(log, "List of section types:\n"
         "(use this command with the types as parameter for more information)\n");
 
index dc118f7..2227ed5 100644 (file)
@@ -52,6 +52,7 @@
 #define OLSR_SUBSYSTEM_STATE(var_name) static bool var_name = false
 
 EXPORT void olsr_exit(void);
+EXPORT void olsr_commit(void);
 
 /**
  * Subsystem marker API for 'being initialized' state.
index 0e68285..f3b7b91 100644 (file)
@@ -169,6 +169,8 @@ olsr_cfg_apply(void) {
     return -1;
   }
 
+  OLSR_INFO(LOG_CONFIG, "Apply configuration");
+
   /*** phase 1: activate all plugins ***/
   result = -1;
   old_db = NULL;
@@ -251,10 +253,32 @@ apply_failed:
   if (old_db) {
     cfg_db_remove(old_db);
   }
+
   abuf_free(&log);
   return result;
 }
 
+int
+olsr_cfg_rollback(void) {
+  struct cfg_db *db;
+
+  /* remember old db */
+  db = _olsr_raw_db;
+
+  OLSR_INFO(LOG_CONFIG, "Rollback configuration");
+
+  _olsr_raw_db = cfg_db_duplicate(_olsr_work_db);
+  if (_olsr_raw_db == NULL) {
+    OLSR_WARN(LOG_CONFIG, "Cannot create raw configuration database.");
+    _olsr_raw_db = db;
+    return -1;
+  }
+
+  /* free old db */
+  cfg_db_remove(db);
+  return 0;
+}
+
 int
 olsr_cfg_update_globalcfg(bool raw) {
   struct cfg_named_section *named;
@@ -272,16 +296,21 @@ olsr_cfg_update_globalcfg(bool raw) {
  */
 int
 olsr_cfg_create_new_rawdb(void) {
-  /* free old db */
-  cfg_db_remove(_olsr_raw_db);
+  struct cfg_db *db;
+
+  /* remember old db */
+  db = _olsr_raw_db;
 
   /* initialize database */
   if ((_olsr_raw_db = cfg_db_add()) == NULL) {
     OLSR_WARN(LOG_CONFIG, "Cannot create raw configuration database.");
-    olsr_exit();
+    _olsr_raw_db = db;
     return -1;
   }
 
+  /* free old db */
+  cfg_db_remove(db);
+
   cfg_db_link_schema(_olsr_raw_db, &_olsr_schema);
   return 0;
 }
index ea8aa4c..68b29f3 100644 (file)
@@ -43,6 +43,7 @@
 #define OLSR_CFG_H_
 
 #include "common/common_types.h"
+#include "common/autobuf.h"
 #include "common/list.h"
 #include "common/netaddr.h"
 #include "config/cfg_schema.h"
@@ -65,6 +66,7 @@ EXPORT extern struct olsr_config_global config_global;
 int olsr_cfg_init(void) __attribute__((warn_unused_result));
 void olsr_cfg_cleanup(void);
 int olsr_cfg_apply(void);
+int olsr_cfg_rollback(void);
 
 /* do not export this to plugins */
 int olsr_cfg_update_globalcfg(bool);
index 0818b40..6428594 100644 (file)
@@ -104,14 +104,14 @@ olsr_packet_add(struct olsr_packet_socket *pktsocket,
   memset(pktsocket, 0, sizeof(*pktsocket));
 
   /* Init socket */
-  s = os_net_getsocket(local, OS_SOCKET_UDP, 0, LOG_SOCKET_STREAM);
+  s = os_net_getsocket(local, OS_SOCKET_UDP, 0, LOG_SOCKET_PACKET);
   if (s < 0) {
     return -1;
   }
 
   if ((pktsocket->scheduler_entry = olsr_socket_add(
       s, olsr_packet_event, pktsocket, OLSR_SOCKET_READ)) == NULL) {
-    OLSR_WARN(LOG_SOCKET_STREAM, "Packet socket hookup to scheduler failed for %s\n",
+    OLSR_WARN(LOG_SOCKET_PACKET, "Packet socket hookup to scheduler failed for %s\n",
         netaddr_socket_to_string(&buf, local));
     goto open_comport_error;
   }
index 86ac9ac..f7a9f82 100644 (file)
 #include "common/avl.h"
 #include "common/avl_comp.h"
 #include "common/template.h"
+
 #include "builddata/data.h"
+#include "builddata/plugin_static.h"
+
 #include "olsr_logging.h"
 #include "olsr_memcookie.h"
 #include "olsr_plugins.h"
@@ -140,15 +143,27 @@ olsr_plugins_hook(struct olsr_plugin *pl_def) {
   pl_def->p_node.key = pl_def->name;
   avl_insert(&plugin_tree, &pl_def->p_node);
 
-  /* initialize the plugin */
-  if (olsr_plugins_load(pl_def->name) == NULL) {
-    OLSR_WARN(LOG_PLUGINLOADER, "Cannot load plugin %s", pl_def->name);
-    return;
-  }
-
-  OLSR_INFO(LOG_PLUGINLOADER, "Loaded plugin %s", pl_def->name);
+  OLSR_INFO(LOG_PLUGINLOADER, "Hooked plugin %s", pl_def->name);
 }
 
+int
+olsr_plugins_init_static(void) {
+  struct olsr_plugin *p, *it;
+  int error = 0;
+
+  assert(!avl_is_empty(&plugin_tree));
+
+  /* make sure all static plugins are loaded */
+  olsr_plugins_load_static();
+
+  OLSR_FOR_ALL_PLUGIN_ENTRIES(p, it) {
+    if (olsr_plugins_load(p->name) == NULL) {
+      OLSR_WARN(LOG_PLUGINLOADER, "Cannot load plugin '%s'", p->name);
+      error = 1;
+    }
+  }
+  return error;
+}
 /**
  * Query for a certain plugin name
  * @param libname name of plugin
index d36735a..a04f29b 100644 (file)
@@ -100,6 +100,7 @@ void olsr_plugins_init(void);
 void olsr_plugins_cleanup(void);
 
 EXPORT void olsr_plugins_hook(struct olsr_plugin *plugin);
+int olsr_plugins_init_static(void);
 
 EXPORT struct olsr_plugin *olsr_plugins_get(const char *libname);
 
index d87486b..02769b6 100644 (file)
@@ -75,7 +75,6 @@ static struct olsr_stream_session *_create_session(
     struct olsr_stream_socket *comport, int sock, struct netaddr *remote_addr);
 static void _parse_connection(int fd, void *data,
         enum olsr_sockethandler_flags flags);
-static void _remove_session(struct olsr_stream_session *con);
 
 static void _timeout_handler(void *);
 
@@ -208,7 +207,7 @@ olsr_stream_remove(struct olsr_stream_socket *comport) {
     comport = list_first_element(&olsr_stream_head, comport, node);
     while (!list_is_empty(&comport->session)) {
       session = list_first_element(&comport->session, session, node);
-      _remove_session(session);
+      olsr_stream_close(session);
     }
 
     list_remove(&comport->node);
@@ -265,6 +264,24 @@ olsr_stream_set_timeout(struct olsr_stream_session *con, uint32_t timeout) {
   olsr_timer_set(&con->timeout, timeout, 0, con, connection_timeout);
 }
 
+void
+olsr_stream_close(struct olsr_stream_session *session) {
+  if (session->comport->config.cleanup) {
+    session->comport->config.cleanup(session);
+  }
+
+  session->comport->config.allowed_sessions++;
+  list_remove(&session->node);
+
+  os_close(session->scheduler_entry->fd);
+  olsr_socket_remove(session->scheduler_entry);
+
+  abuf_free(&session->in);
+  abuf_free(&session->out);
+
+  olsr_memcookie_free(session->comport->config.memcookie, session);
+}
+
 void
 olsr_stream_add_managed(struct olsr_stream_managed *managed) {
   memset(managed, 0, sizeof(*managed));
@@ -284,12 +301,19 @@ olsr_stream_apply_managed(struct olsr_stream_managed *managed,
       return -1;
     }
   }
+  else {
+    olsr_stream_remove(&managed->socket_v4);
+  }
+
   if (config_global.ipv6) {
     if (_apply_managed_socket(managed,
         &managed->socket_v6, &config->bindto_v6, config->port)) {
       return -1;
     }
   }
+  else {
+    olsr_stream_remove(&managed->socket_v6);
+  }
   return 0;
 }
 
@@ -358,8 +382,8 @@ _parse_request(int fd, void *data, unsigned int flags) {
     return;
   }
 
+  netaddr_from_socket(&remote_addr, &remote_socket);
   if (comport->config.acl) {
-    netaddr_from_socket(&remote_addr, &remote_socket);
     if (!olsr_acl_check_accept(comport->config.acl, &remote_addr)) {
       OLSR_DEBUG(LOG_SOCKET_STREAM, "Access from %s to socket %s blocked because of ACL",
           netaddr_to_string(&buf1, &remote_addr),
@@ -449,28 +473,10 @@ parse_request_error:
   return NULL;
 }
 
-static void
-_remove_session(struct olsr_stream_session *session) {
-  if (session->comport->config.cleanup) {
-    session->comport->config.cleanup(session);
-  }
-
-  session->comport->config.allowed_sessions++;
-  list_remove(&session->node);
-
-  os_close(session->scheduler_entry->fd);
-  olsr_socket_remove(session->scheduler_entry);
-
-  abuf_free(&session->in);
-  abuf_free(&session->out);
-
-  olsr_memcookie_free(session->comport->config.memcookie, session);
-}
-
 static void
 _timeout_handler(void *data) {
   struct olsr_stream_session *session = data;
-  _remove_session(session);
+  olsr_stream_close(session);
 }
 
 static void
@@ -591,7 +597,7 @@ _parse_connection(int fd, void *data,
     /* clean up connection by calling cleanup directly */
     olsr_timer_stop(session->timeout);
     session->timeout = NULL;
-    _remove_session(session);
+    olsr_stream_close(session);
   }
   return;
 }
index 0b173b7..4d70d5c 100644 (file)
@@ -196,6 +196,7 @@ EXPORT void olsr_stream_flush(struct olsr_stream_session *con);
 
 EXPORT void olsr_stream_set_timeout(
     struct olsr_stream_session *con, uint32_t timeout);
+EXPORT void olsr_stream_close(struct olsr_stream_session *con);
 
 EXPORT void olsr_stream_add_managed(struct olsr_stream_managed *);
 EXPORT int olsr_stream_apply_managed(struct olsr_stream_managed *,
index fa7befc..9884aa2 100644 (file)
@@ -393,12 +393,17 @@ static enum olsr_telnet_result
 _telnet_handle_command(struct olsr_telnet_session *telnet,
     const char *command, const char *parameter) {
   struct olsr_telnet_command *cmd;
-
+#if !defined(REMOVE_LOG_INFO)
+  struct netaddr_str buf;
+#endif
   cmd = _check_telnet_command(telnet, NULL, command);
   if (cmd == NULL) {
     return TELNET_RESULT_UNKNOWN_COMMAND;
   }
 
+  OLSR_INFO(LOG_TELNET, "Executing command from %s: %s %s",
+      netaddr_to_string(&buf, &telnet->session.remote_address), command,
+      parameter == NULL ? "" : parameter);
   return cmd->handler(telnet, command, parameter);
 }
 
index 2b06d41..1c2767b 100644 (file)
@@ -114,7 +114,7 @@ struct olsr_timer_entry {
 };
 
 /* Timers */
-extern struct list_entity EXPORT(timerinfo_list);
+EXPORT extern struct list_entity timerinfo_list;
 #define OLSR_FOR_ALL_TIMERS(ti, iterator) list_for_each_element_safe(&timerinfo_list, ti, node, iterator)
 
 int olsr_timer_init(void) __attribute__((warn_unused_result));
index 5967170..28ed409 100644 (file)
@@ -157,7 +157,7 @@ os_net_getsocket(union netaddr_socket *bindto,
   }
 
   if (os_net_configsocket(sock, bindto, flags, recvbuf, log_src)) {
-    close(sock);
+    os_close(sock);
     return -1;
   }
   return sock;
index e4c9b89..6a5a4c9 100644 (file)
@@ -71,7 +71,7 @@
 #include "olsr_setup.h"
 #include "olsr.h"
 
-static bool running, reload_config, exit_called;
+static bool running, reload_config, commit_config, exit_called;
 static char *schema_name;
 
 enum argv_short_options {
@@ -153,6 +153,7 @@ main(int argc, char **argv) {
   /* setup signal handler */
   running = true;
   reload_config = false;
+  commit_config = false;
   exit_called = false;
   setup_signalhandler();
 
@@ -174,8 +175,11 @@ main(int argc, char **argv) {
   /* initialize logging schema */
   olsr_logcfg_addschema(olsr_cfg_get_schema());
 
+  /* prepare plugin initialization */
+  olsr_plugins_init();
+
   /* load static plugins */
-  olsr_plugins_load_static();
+  olsr_plugins_init_static();
 
   /* parse command line and read configuration files */
   return_code = parse_commandline(argc, argv, false);
@@ -238,9 +242,6 @@ main(int argc, char **argv) {
     goto olsrd_cleanup;
   }
 
-  /* activate plugins */
-  olsr_plugins_init();
-
   /* show schema if necessary */
   if (schema_name) {
     return_code = display_schema();
@@ -307,6 +308,11 @@ olsr_exit(void) {
   exit_called = true;
 }
 
+void
+olsr_commit(void) {
+  commit_config = true;
+}
+
 /**
  * Handle incoming SIGINT signal
  * @param signo
@@ -368,6 +374,14 @@ mainloop(int argc, char **argv) {
       }
       reload_config = false;
     }
+
+    /* commit config if triggered */
+    if (commit_config) {
+      OLSR_INFO(LOG_MAIN, "Commiting configuration");
+      olsr_cfg_apply();
+
+      commit_config = false;
+    }
   }
 
   /* wait for 500 milliseconds and process socket events */