More code for netlink and route handling
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Thu, 23 Feb 2012 09:42:04 +0000 (10:42 +0100)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Thu, 23 Feb 2012 09:42:04 +0000 (10:42 +0100)
20 files changed:
config.txt
lib/cfgio_file/src/cfgio_file.c
lib/remotecontrol/src/remotecontrol.c
src/common/autobuf.c
src/common/autobuf.h
src/core/olsr_cfg.c
src/core/olsr_http.c
src/core/olsr_logging.c
src/core/olsr_logging.h
src/core/olsr_packet_socket.c
src/core/olsr_plugins.c
src/core/olsr_stream_socket.c
src/core/olsr_telnet.c
src/core/olsr_timer.c
src/core/os_linux/os_net_linux.c
src/core/os_linux/os_routing_linux.c
src/core/os_linux/os_system_linux.c
src/core/os_linux/os_system_linux.h
src/core/os_routing.h
src/olsr_main.c

index 0ee746f..28eb51b 100644 (file)
@@ -4,7 +4,7 @@
 #      ipv4            yes
 #      ipv6            yes
 
-#[telnet]
+[telnet]
 #      acl             127.0.0.1/8
 #      acl             default_reject
 #      bindto_v4       11.0.0.1
 #      bindto_v4       11.0.0.1
 #      port            8080
 
-[httptelnet]
+#[httptelnet]
 #      acl             127.0.0.1/8
 #      acl             default_reject
 #       site           /telnet
 #       Example name/password "wiki"/"pedia"
 #       auth           d2lraTpwZWRpYQ==
+
+[remotecontrol]
+#      acl          accept_default
index 740fe8a..f296881 100644 (file)
@@ -134,7 +134,7 @@ _cb_file_load(struct cfg_instance *instance,
   }
 
   bytes = 1;
-  if (abuf_init(&dst, 4096)) {
+  if (abuf_init(&dst)) {
     cfg_append_printable_line(log,
         "Out of memory error while allocating io buffer");
     close (fd);
@@ -188,7 +188,7 @@ _cb_file_save(struct cfg_instance *instance,
   size_t total;
   struct autobuf abuf;
 
-  if (abuf_init(&abuf, 4096)) {
+  if (abuf_init(&abuf)) {
     cfg_append_printable_line(log,
         "Out of memory error while allocating io buffer");
     return -1;
index 5092d03..0b649f8 100644 (file)
  *
  */
 
-/*
- * Dynamic linked library for the olsr.org olsr daemon
- */
-
 #include <stdlib.h>
 
 #include "common/common_types.h"
@@ -637,7 +633,7 @@ _cb_handle_route(struct olsr_telnet_data *data) {
     }
 
     abuf_appendf(data->out, "set route: %d",
-        os_routing_set(NULL, src.type == 0 ? NULL: &src, &gw, &dst,
+        os_routing_set(src.type == 0 ? NULL: &src, &gw, &dst,
             table, if_index, metric, protocol, set, true));
     return TELNET_RESULT_ACTIVE;
   }
index 3243ff2..7591e6f 100644 (file)
@@ -88,19 +88,13 @@ abuf_set_memory_handler(
 /**
  * Initialize an autobuffer and allocate a chunk of memory
  * @param autobuf pointer to autobuf object
- * @param initial_size size of allocated memory, might be 0
  * @return -1 if an out-of-memory error happened, 0 otherwise
  */
 int
-abuf_init(struct autobuf *autobuf, size_t initial_size)
+abuf_init(struct autobuf *autobuf)
 {
   autobuf->len = 0;
-  if (initial_size <= 0) {
-    autobuf->size = AUTOBUFCHUNK;
-  }
-  else {
-    autobuf->size = ROUND_UP_TO_POWER_OF_2(initial_size, AUTOBUFCHUNK);
-  }
+  autobuf->size = AUTOBUFCHUNK;
   autobuf->buf = autobuf_malloc(autobuf->size);
   if (autobuf->buf == NULL) {
     autobuf->size = 0;
index a2633db..5b3110b 100644 (file)
@@ -70,7 +70,7 @@ EXPORT void abuf_set_memory_handler(
     void *(*custom_realloc)(void *, size_t),
     void (*custom_free)(void *));
 
-EXPORT int abuf_init(struct autobuf *autobuf, size_t initial_size);
+EXPORT int abuf_init(struct autobuf *autobuf);
 EXPORT void abuf_free(struct autobuf *autobuf);
 EXPORT int abuf_vappendf(struct autobuf *autobuf, const char *fmt,
     va_list ap) __attribute__ ((format(printf, 2, 0)));
index c2e95cc..b8f03b3 100644 (file)
@@ -236,7 +236,7 @@ olsr_cfg_apply(void) {
   struct autobuf log;
   int result;
 
-  if (abuf_init(&log, 0)) {
+  if (abuf_init(&log)) {
     OLSR_WARN_OOM(LOG_CONFIG);
     return -1;
   }
index 5c9ba66..1f28be4 100644 (file)
@@ -469,7 +469,7 @@ _create_http_header(struct olsr_stream_session *session,
   struct autobuf buf;
   struct timeval currtime;
 
-  abuf_init(&buf, 1024);
+  abuf_init(&buf);
 
   abuf_appendf(&buf, "%s %d %s\r\n", HTTP_VERSION_1_0, code, _get_headertype_string(code));
 
index f2d64b6..adf380a 100644 (file)
@@ -85,6 +85,7 @@ static const char *_LOG_SOURCE_NAMES[LOG_CORESOURCE_COUNT] = {
   "interface",
   "os-net",
   "os-system",
+  "os-routing",
   "plugin-loader",
   "telnet",
   "plugins",
@@ -128,7 +129,7 @@ olsr_log_init(const struct olsr_builddata *data, enum log_severity def_severity,
 
   list_init_head(&_handler_list);
 
-  if (abuf_init(&_logbuffer, 4096)) {
+  if (abuf_init(&_logbuffer)) {
     fputs("Not enough memory for logging buffer\n", stderr);
     return -1;
   }
index e894abc..5d3c78c 100644 (file)
@@ -82,6 +82,7 @@ enum log_source {
   LOG_INTERFACE,
   LOG_OS_NET,
   LOG_OS_SYSTEM,
+  LOG_OS_ROUTING,
   LOG_PLUGINLOADER,
   LOG_TELNET,
   LOG_PLUGINS,
index b442168..299d3cd 100644 (file)
@@ -114,7 +114,7 @@ olsr_packet_add(struct olsr_packet_socket *pktsocket,
 
   olsr_socket_add(&pktsocket->scheduler_entry);
 
-  abuf_init(&pktsocket->out, 2048);
+  abuf_init(&pktsocket->out);
   list_add_tail(&packet_sockets, &pktsocket->node);
   memcpy(&pktsocket->local_socket, local, sizeof(pktsocket->local_socket));
 
index 9bea5b7..20a729d 100644 (file)
@@ -386,7 +386,7 @@ _open_plugin(const char *filename) {
   size_t i;
   int indexCount;
 
-  if (abuf_init(&abuf, strlen(filename))) {
+  if (abuf_init(&abuf)) {
     OLSR_WARN_OOM(LOG_PLUGINLOADER);
     return NULL;
   }
index afcd4aa..7038ad2 100644 (file)
@@ -507,11 +507,11 @@ _create_session(struct olsr_stream_socket *stream_socket,
     goto parse_request_error;
   }
 
-  if (abuf_init(&session->in, 1024)) {
+  if (abuf_init(&session->in)) {
     OLSR_WARN(LOG_SOCKET_STREAM, "Cannot allocate memory for comport session");
     goto parse_request_error;
   }
-  if (abuf_init(&session->out, 0)) {
+  if (abuf_init(&session->out)) {
     OLSR_WARN(LOG_SOCKET_STREAM, "Cannot allocate memory for comport session");
     goto parse_request_error;
   }
index 08985f3..8e00913 100644 (file)
@@ -558,7 +558,12 @@ _cb_telnet_echo(struct olsr_telnet_data *data) {
  */
 static enum olsr_telnet_result
 _cb_telnet_timeout(struct olsr_telnet_data *data) {
-  data->timeout_value = (uint32_t)strtoul(data->parameter, NULL, 10) * 1000;
+  if (data->parameter == NULL) {
+    data->timeout_value = 0;
+  }
+  else {
+    data->timeout_value = (uint32_t)strtoul(data->parameter, NULL, 10) * 1000;
+  }
   return TELNET_RESULT_ACTIVE;
 }
 
index 83264b6..69bdfb2 100644 (file)
@@ -158,6 +158,10 @@ olsr_timer_add(const char *name, timer_cb_func callback, bool periodic) {
   struct olsr_timer_info *ti;
 
   ti = olsr_memcookie_malloc(timerinfo_cookie);
+  if (ti == NULL) {
+    OLSR_WARN_OOM(LOG_MEMCOOKIE);
+    return NULL;
+  }
   ti->name = strdup(name);
   ti->callback = callback;
   ti->periodic = periodic;
index ca7f840..b53b597 100644 (file)
@@ -1,8 +1,42 @@
+
 /*
- * os_net_linux.c
+ * 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.
  *
- *  Created on: Oct 18, 2011
- *      Author: rogge
  */
 
 #include <net/if.h>
index d3027bc..38d27bf 100644 (file)
@@ -1,8 +1,42 @@
+
 /*
- * os_routing_linux.c
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2011, 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.
  *
- *  Created on: Feb 13, 2012
- *      Author: rogge
  */
 
 /* must be first because of a problem with linux/rtnetlink.h */
 static bool _is_at_least_linuxkernel_2_6_31(void);
 static int _os_linux_writeToProc(const char *file, char *old, char value);
 
+static void _cb_rtnetlink_feedback(uint32_t seq, int error);
+static void _cb_rtnetlink_timeout(void);
+
 /* global procfile state before initialization */
 static char _original_rp_filter;
 static char _original_icmp_redirect;
 
-/* buffer for outgoing rtnetlink messages */
-static struct nlmsghdr *_rtnetlink_buffer;
+/* netlink socket for route set/get commands */
+struct os_system_netlink _rtnetlink_socket;
 
 OLSR_SUBSYSTEM_STATE(_os_routing_state);
 
+/**
+ * Initialize routing subsystem
+ * @return -1 if an error happened, 0 otherwise
+ */
 int
 os_routing_init(void) {
   if (olsr_subsystem_is_initialized(&_os_routing_state))
     return 0;
 
-  _rtnetlink_buffer = calloc(UIO_MAXIOV, 1);
-  if (_rtnetlink_buffer == NULL) {
-    OLSR_WARN_OOM(LOG_OS_SYSTEM);
+  if (os_system_netlink_add(&_rtnetlink_socket, NETLINK_ROUTE, 0)) {
     return -1;
   }
 
+  _rtnetlink_socket.cb_feedback = _cb_rtnetlink_feedback;
+  _rtnetlink_socket.cb_timeout = _cb_rtnetlink_timeout;
+
   if (_os_linux_writeToProc(PROC_ALL_REDIRECT, &_original_icmp_redirect, '0')) {
     OLSR_WARN(LOG_OS_SYSTEM, "WARNING! Could not disable ICMP redirects! "
         "You should manually ensure that ICMP redirects are disabled!");
@@ -75,6 +117,9 @@ os_routing_init(void) {
   return 0;
 }
 
+/**
+ * Cleanup all resources allocated by the routing subsystem
+ */
 void
 os_routing_cleanup(void) {
   if (olsr_subsystem_cleanup(&_os_routing_state))
@@ -94,7 +139,7 @@ os_routing_cleanup(void) {
         PROC_ALL_SPOOF, _original_rp_filter);
   }
 
-  free (_rtnetlink_buffer);
+  os_system_netlink_remove(&_rtnetlink_socket);
 }
 
 /**
@@ -188,12 +233,13 @@ os_routing_cleanup_mesh_if(struct olsr_interface *interf) {
  * @return -1 if an error happened, rtnetlink sequence number otherwise
  */
 int
-os_routing_set(struct olsr_system_feedback *feedback,
-    const struct netaddr *src, const struct netaddr *gw, const struct netaddr *dst,
+os_routing_set(const struct netaddr *src, const struct netaddr *gw, const struct netaddr *dst,
     int rttable, int if_index, int metric, int protocol, bool set, bool del_similar) {
+  uint8_t buffer[UIO_MAXIOV];
+  struct nlmsghdr *msg;
   struct rtmsg *rt_msg;
 
-  assert(olsr_subsystem_is_initialized(&_os_routing_state));
+  msg = (void *)&buffer[0];
 
   /* consistency check */
   if (dst == NULL || (dst->type != AF_INET && dst->type != AF_INET6)) {
@@ -204,23 +250,21 @@ os_routing_set(struct olsr_system_feedback *feedback,
     return -1;
   }
 
-  memset(_rtnetlink_buffer, 0, sizeof(*_rtnetlink_buffer));
-
-  rt_msg = NLMSG_DATA(_rtnetlink_buffer);
-  memset(rt_msg, 0, sizeof(*rt_msg));
+  memset(buffer, 0, sizeof(buffer));
 
+  rt_msg = NLMSG_DATA(buffer);
   rt_msg->rtm_flags = RTNH_F_ONLINK;
   rt_msg->rtm_family = dst->type;
   rt_msg->rtm_table = rttable;
 
-  _rtnetlink_buffer->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
-  _rtnetlink_buffer->nlmsg_flags = NLM_F_REQUEST;
+  msg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+  msg->nlmsg_flags = NLM_F_REQUEST;
 
   if (set) {
-    _rtnetlink_buffer->nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
-    _rtnetlink_buffer->nlmsg_type = RTM_NEWROUTE;
+    msg->nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
+    msg->nlmsg_type = RTM_NEWROUTE;
   } else {
-    _rtnetlink_buffer->nlmsg_type = RTM_DELROUTE;
+    msg->nlmsg_type = RTM_DELROUTE;
   }
 
   /* RTN_UNSPEC would be the wildcard, but blackhole broadcast or nat roules should usually not conflict */
@@ -246,26 +290,36 @@ os_routing_set(struct olsr_system_feedback *feedback,
 
   if (set || !del_similar) {
     /* add interface*/
-    os_system_netlink_addreq(_rtnetlink_buffer, RTA_OIF, &if_index, sizeof(if_index));
+    if (os_system_netlink_addreq(msg, RTA_OIF, &if_index, sizeof(if_index))) {
+      return -1;
+    }
   }
 
   if (set && src != NULL) {
     /* add src-ip */
-    os_system_netlink_addnetaddr(_rtnetlink_buffer, RTA_PREFSRC, src);
+    if (os_system_netlink_addnetaddr(msg, RTA_PREFSRC, src)) {
+      return -1;
+    }
   }
 
   if (metric != -1) {
     /* add metric */
-    os_system_netlink_addreq(_rtnetlink_buffer, RTA_PRIORITY, &metric, sizeof(metric));
+    if (os_system_netlink_addreq(msg, RTA_PRIORITY, &metric, sizeof(metric))) {
+      return -1;
+    }
   }
 
   if (gw) {
     /* add gateway */
-    os_system_netlink_addnetaddr(_rtnetlink_buffer, RTA_GATEWAY, gw);
+    if (os_system_netlink_addnetaddr(msg, RTA_GATEWAY, gw)) {
+      return -1;
+    }
   }
-  else if ( dst->prefix_len == 32 ) {
+  else if (dst->prefix_len == netaddr_get_maxprefix(dst)) {
     /* use destination as gateway, to 'force' linux kernel to do proper source address selection */
-    os_system_netlink_addnetaddr(_rtnetlink_buffer, RTA_GATEWAY, dst);
+    if (os_system_netlink_addnetaddr(msg, RTA_GATEWAY, dst)) {
+      return -1;
+    }
   }
   else {
     /*
@@ -276,9 +330,29 @@ os_routing_set(struct olsr_system_feedback *feedback,
   }
 
    /* add destination */
-  os_system_netlink_addnetaddr(_rtnetlink_buffer, RTA_DST, dst);
+  if (os_system_netlink_addnetaddr(msg, RTA_DST, dst)) {
+    return -1;
+  }
 
-  return os_system_netlink_async_send(feedback, _rtnetlink_buffer);
+  os_system_netlink_send(&_rtnetlink_socket, msg);
+  return 0;
+}
+/**
+ * TODO: Handle feedback from netlink socket
+ * @param seq
+ * @param error
+ */
+static void
+_cb_rtnetlink_feedback(uint32_t seq, int error) {
+  OLSR_INFO(LOG_OS_ROUTING, "Got feedback: %d %d", seq, error);
+}
+
+/**
+ * TODO: Handle ack timeout from netlink socket
+ */
+static void
+_cb_rtnetlink_timeout(void) {
+  OLSR_INFO(LOG_OS_ROUTING, "Got timeout");
 }
 
 /**
@@ -331,6 +405,9 @@ writetoproc_error:
   return -1;
 }
 
+/**
+ * @return true if linux kernel is at least 2.6.31
+ */
 static bool
 _is_at_least_linuxkernel_2_6_31(void) {
   struct utsname uts;
index cb20010..5a0b59a 100644 (file)
@@ -1,8 +1,42 @@
+
 /*
- * os_netlink.c
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2011, 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.
  *
- *  Created on: Oct 19, 2011
- *      Author: rogge
  */
 
 /* must be first because of a problem with linux/rtnetlink.h */
 
 #define OS_SYSTEM_NETLINK_TIMEOUT 100
 
-static void _cb_handle_feedback_timerout(void *);
+static void _cb_handle_netlink_timerout(void *);
 static void _netlink_handler(int fd, void *data,
     bool event_read, bool event_write);
-static void _handle_nl_link(struct nlmsghdr *);
-static void _handle_nl_addr(struct nlmsghdr *);
-static void _handle_nl_err(struct nlmsghdr *);
-
-/* rtnetlink data */
-static int _rtnetlink_async_fd = -1;
-static int _rtnetlink_sync_fd = -1;
-static struct olsr_socket_entry _rtnetlink_socket = {
-  .process = _netlink_handler,
-  .event_read = true,
-};
+static void _handle_rtnetlink(struct nlmsghdr *hdr);
 
-static uint32_t _async_seq = 0;
+static void _handle_nl_err(struct os_system_netlink *, struct nlmsghdr *);
 
 /* ioctl socket */
 static int _ioctl_fd = -1;
@@ -62,31 +86,31 @@ static struct msghdr _netlink_rcv_msg = {
   0
 };
 
-static struct iovec _netlink_send_iov;
+static struct nlmsghdr _netlink_hdr_done = {
+  .nlmsg_len = sizeof(struct nlmsghdr),
+  .nlmsg_type = NLMSG_DONE
+};
+
+static struct iovec _netlink_send_iov[2] = {
+    { NULL, 0 },
+    { &_netlink_hdr_done, sizeof(_netlink_hdr_done) },
+};
+
 static struct msghdr _netlink_send_msg = {
   &_netlink_nladdr,
   sizeof(_netlink_nladdr),
-  &_netlink_send_iov,
-  1,
+  &_netlink_send_iov[0],
+  2,
   NULL,
   0,
   0
 };
 
-static struct nlmsghdr _netlink_hdr_done = {
-  .nlmsg_len = sizeof(struct nlmsghdr),
-  .nlmsg_type = NLMSG_DONE
-};
-
-/* buffer for incoming netlink messages */
-struct nlmsghdr *_netlink_recv_buffer;
+/* netlink timeout handling */
+static struct olsr_timer_info *_netlink_timer;
 
-/* buffer for outgoing netlink messages */
-struct autobuf _netlink_send_buffer;
-
-/* rtnetlink feedback handling */
-static struct list_entity _feedback_handlers;
-static struct olsr_timer_info *_feedback_timer;
+/* built in rtnetlink multicast receiver */
+static struct os_system_netlink _rtnetlink_receiver;
 
 OLSR_SUBSYSTEM_STATE(_os_system_state);
 
@@ -96,98 +120,33 @@ OLSR_SUBSYSTEM_STATE(_os_system_state);
  */
 int
 os_system_init(void) {
-  struct sockaddr_nl addr;
-
   if (olsr_subsystem_is_initialized(&_os_system_state)) {
     return 0;
   }
 
-  _ioctl_fd = -1;
-  _rtnetlink_sync_fd = -1;
-  _rtnetlink_async_fd = -1;
-  _netlink_recv_buffer = NULL;
-
-  if ((_feedback_timer =
-      olsr_timer_add("rtnetlink feedback timer", _cb_handle_feedback_timerout, false)) != NULL) {
+  if ((_netlink_timer =
+      olsr_timer_add("rtnetlink feedback timer", _cb_handle_netlink_timerout, false)) == NULL) {
+    OLSR_WARN(LOG_OS_SYSTEM, "Cannot allocate timer class for netlink timeout");
     return -1;
   }
 
-  list_init_head(&_feedback_handlers);
-
   _ioctl_fd = socket(AF_INET, SOCK_DGRAM, 0);
   if (_ioctl_fd == -1) {
     OLSR_WARN(LOG_OS_SYSTEM, "Cannot open ioctl socket: %s (%d)",
         strerror(errno), errno);
-    goto os_system_init_failed;
-  }
-
-  if (abuf_init(&_netlink_send_buffer, UIO_MAXIOV)) {
-    OLSR_WARN_OOM(LOG_OS_SYSTEM);
-    goto os_system_init_failed;
-  }
-
-  _netlink_recv_buffer = calloc(UIO_MAXIOV, 1);
-  if (_netlink_recv_buffer == NULL) {
-    OLSR_WARN_OOM(LOG_OS_SYSTEM);
-    goto os_system_init_failed;
-  }
-  _netlink_rcv_iov.iov_base = _netlink_recv_buffer;
-  _netlink_rcv_iov.iov_len = UIO_MAXIOV;
-
-  _rtnetlink_async_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
-  if (_rtnetlink_async_fd < 0) {
-    OLSR_WARN(LOG_OS_SYSTEM, "Cannot open async rtnetlink socket: %s (%d)",
-        strerror(errno), errno);
-    goto os_system_init_failed;
-  }
-
-  _rtnetlink_sync_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
-  if (_rtnetlink_sync_fd < 0) {
-    OLSR_WARN(LOG_OS_SYSTEM, "Cannot open sync rtnetlink socket: %s (%d)",
-        strerror(errno), errno);
-    goto os_system_init_failed;
-  }
-
-  memset(&addr, 0, sizeof(addr));
-  addr.nl_family = AF_NETLINK;
-  addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
-
-  /* kernel will assign appropriate number instead of pid */
-  /* addr.nl_pid = 0; */
-
-  if (bind(_rtnetlink_async_fd, (struct sockaddr *)&addr, sizeof(addr))<0) {
-    OLSR_WARN(LOG_OS_SYSTEM, "Could not bind async rtnetlink socket: %s (%d)",
-        strerror(errno), errno);
-    goto os_system_init_failed;
+    olsr_timer_remove(_netlink_timer);
+    return -1;
   }
 
-  memset(&addr, 0, sizeof(addr));
-  addr.nl_family = AF_NETLINK;
-
-  /* kernel will assign appropriate number instead of pid */
-  /* addr.nl_pid = 0; */
-
-  if (bind(_rtnetlink_sync_fd, (struct sockaddr *)&addr, sizeof(addr))<0) {
-    OLSR_WARN(LOG_OS_SYSTEM, "Could not bind sync rtnetlink socket: %s (%d)",
-        strerror(errno), errno);
-    goto os_system_init_failed;
+  if (os_system_netlink_add(&_rtnetlink_receiver, NETLINK_ROUTE,
+      RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR)) {
+    olsr_timer_remove(_netlink_timer);
+    close(_ioctl_fd);
+    return -1;
   }
-
-  /* add socket listener */
-  _rtnetlink_socket.fd = _rtnetlink_async_fd;
-  olsr_socket_add(&_rtnetlink_socket);
-
+  _rtnetlink_receiver.cb_message = _handle_rtnetlink;
   olsr_subsystem_init(&_os_system_state);
   return 0;
-os_system_init_failed:
-  if (_rtnetlink_sync_fd != -1)
-    close (_rtnetlink_sync_fd);
-  if (_rtnetlink_async_fd != -1)
-    close (_rtnetlink_async_fd);
-  free(_netlink_recv_buffer);
-  abuf_free(&_netlink_send_buffer);
-  close(_ioctl_fd);
-  return -1;
 }
 
 /**
@@ -195,25 +154,12 @@ os_system_init_failed:
  */
 void
 os_system_cleanup(void) {
-  struct olsr_system_feedback *fb, *it;
   if (olsr_subsystem_cleanup(&_os_system_state))
     return;
 
-  /* call timeout for all routing ack timers still left */
-  list_for_each_element_safe(&_feedback_handlers, fb, _node, it) {
-    olsr_timer_stop(fb->timeout);
-    fb->cb_timeout(fb);
-    list_remove(&fb->_node);
-  }
-
-  olsr_timer_remove(_feedback_timer);
-
-  close (_rtnetlink_sync_fd);
-  close(_rtnetlink_async_fd);
+  os_system_netlink_remove(&_rtnetlink_receiver);
+  olsr_timer_remove(_netlink_timer);
   close(_ioctl_fd);
-
-  abuf_free(&_netlink_send_buffer);
-  free (_netlink_recv_buffer);
 }
 
 /**
@@ -259,6 +205,99 @@ os_system_set_interface_state(const char *dev, bool up) {
   return 0;
 }
 
+/**
+ * Open a new bidirectional netlink socket
+ * @param nl pointer to uninitialized netlink socket handler
+ * @param protocol protocol id (NETLINK_ROUTING for example)
+ * @param multicast multicast groups this socket should listen to
+ * @return -1 if an error happened, 0 otherwise
+ */
+int
+os_system_netlink_add(struct os_system_netlink *nl, int protocol, uint32_t multicast) {
+  struct sockaddr_nl addr;
+
+  memset(nl, 0, sizeof(*nl));
+
+  nl->socket.fd = socket(PF_NETLINK, SOCK_RAW, protocol);
+  if (nl->socket.fd < 0) {
+    OLSR_WARN(LOG_OS_SYSTEM, "Cannot open sync rtnetlink socket: %s (%d)",
+        strerror(errno), errno);
+    goto os_add_netlink_fail;
+  }
+
+  if (abuf_init(&nl->out)) {
+    OLSR_WARN_OOM(LOG_OS_SYSTEM);
+    goto os_add_netlink_fail;
+  }
+
+  nl->in = calloc(1, UIO_MAXIOV);
+  if (nl->in == NULL) {
+    OLSR_WARN_OOM(LOG_OS_SYSTEM);
+    goto os_add_netlink_fail;
+  }
+
+
+  memset(&addr, 0, sizeof(addr));
+  addr.nl_family = AF_NETLINK;
+  addr.nl_groups = multicast;
+
+  /* kernel will assign appropriate number instead of pid */
+  /* addr.nl_pid = 0; */
+
+  if (bind(nl->socket.fd, (struct sockaddr *)&addr, sizeof(addr))<0) {
+    OLSR_WARN(LOG_OS_SYSTEM, "Could not bind netlink socket: %s (%d)",
+        strerror(errno), errno);
+    goto os_add_netlink_fail;
+  }
+
+  nl->socket.process = _netlink_handler;
+  nl->socket.event_read = true;
+  nl->socket.data = nl;
+  olsr_socket_add(&nl->socket);
+
+  return 0;
+
+os_add_netlink_fail:
+  if (nl->socket.fd != -1) {
+    close(nl->socket.fd);
+  }
+  free (nl->in);
+  abuf_free(&nl->out);
+  return -1;
+}
+
+/**
+ * Close a netlink socket handler
+ * @param nl pointer to handler
+ */
+void
+os_system_netlink_remove(struct os_system_netlink *nl) {
+  olsr_socket_remove(&nl->socket);
+
+  close(nl->socket.fd);
+  free (nl->in);
+  abuf_free(&nl->out);
+}
+
+/**
+ * Add a netlink message to the outgoign queue of a handler
+ * @param nl pointer to netlink handler
+ * @param nl_hdr pointer to netlink message
+ */
+void
+os_system_netlink_send(struct os_system_netlink *nl,
+    struct nlmsghdr *nl_hdr) {
+  nl->seq_used++;
+
+  nl_hdr->nlmsg_seq = nl->seq_used;
+  nl_hdr->nlmsg_flags |= NLM_F_ACK | NLM_F_MULTI;
+
+  abuf_memcpy(&nl->out, nl_hdr, nl_hdr->nlmsg_len);
+
+  /* trigger write */
+  olsr_socket_set_write(&nl->socket, true);
+}
+
 /**
  * Add an attribute to a netlink message
  * @param n pointer to netlink header
@@ -293,156 +332,51 @@ os_system_netlink_addreq(struct nlmsghdr *n,
 }
 
 /**
- * Sends a single netlink message to the kernel, blocks until it receives the
- * answer and checks the error code. The answer must only contain a single
- * NLMSG_ERROR message.
- * @param nl_hdr pointer to netlink header
- * @return negative if an error happened, 0 if everything was okay.
+ * Handle timeout of netlink acks
+ * @param ptr pointer to netlink handler
  */
-int
-os_system_netlink_sync_send(struct nlmsghdr *nl_hdr)
-{
-  struct nlmsgerr *l_err;
-  int ret;
-
-  _netlink_send_iov.iov_base = nl_hdr;
-  _netlink_send_iov.iov_len = nl_hdr->nlmsg_len;
-
-  if (sendmsg(_rtnetlink_sync_fd, &_netlink_send_msg, 0) <= 0) {
-    OLSR_WARN(LOG_OS_SYSTEM,
-        "Cannot send data to netlink socket (%d: %s)",
-        errno, strerror(errno));
-    return -1;
-  }
-
-  ret = recvmsg(_rtnetlink_sync_fd, &_netlink_rcv_msg, 0);
-  if (ret <= 0) {
-    OLSR_WARN(LOG_OS_SYSTEM,
-        "Error while reading answer to netlink message (%d: %s)",
-        errno, strerror(errno));
-    return -1;
-  }
+static void
+_cb_handle_netlink_timerout(void *ptr) {
+  struct os_system_netlink *nl = ptr;
 
-  if (!NLMSG_OK(_netlink_recv_buffer, (unsigned int)ret)) {
-    OLSR_WARN(LOG_OS_SYSTEM,
-        "Received netlink message was malformed (ret=%d, %u)",
-        ret, _netlink_recv_buffer->nlmsg_len);
-    return -1;
-  }
+  nl->timeout = NULL;
 
-  if (_netlink_recv_buffer->nlmsg_type != NLMSG_ERROR) {
-    OLSR_WARN(LOG_OS_SYSTEM,
-        "Received unknown netlink response: %u bytes, type %u (not %u) with seqnr %u and flags %u from %u",
-        _netlink_recv_buffer->nlmsg_len, _netlink_recv_buffer->nlmsg_type,
-        NLMSG_ERROR, _netlink_recv_buffer->nlmsg_seq, _netlink_recv_buffer->nlmsg_flags, _netlink_recv_buffer->nlmsg_pid);
-    return -1;
-  }
-  if (NLMSG_LENGTH(sizeof(struct nlmsgerr)) > _netlink_recv_buffer->nlmsg_len) {
-    OLSR_WARN(LOG_OS_SYSTEM,
-        "Received invalid netlink message size %zu != %u",
-        sizeof(struct nlmsgerr), _netlink_recv_buffer->nlmsg_len);
-    return -1;
+  if (nl->cb_timeout) {
+    nl->cb_timeout();
   }
 
-  l_err = (struct nlmsgerr *)NLMSG_DATA(_netlink_recv_buffer);
-
-  if (l_err->error) {
-    OLSR_WARN(LOG_OS_SYSTEM,
-        "Received netlink error code %s (%d)",
-        strerror(-l_err->error), l_err->error);
-  }
-  return -l_err->error;
+  nl->seq_used = 0;
 }
 
 /**
- * Sends a single netlink message to the kernel. The answer will be delivered
- * to the netlink listener.
- * @param nl_hdr pointer to netlink header
- * @return sequence number of buffered netlink message
+ * Send all netlink messages in the outgoing queue to the kernel
+ * @param nl pointer to netlink handler
  */
-int
-os_system_netlink_async_send(struct olsr_system_feedback *fb, struct nlmsghdr *nl_hdr) {
-  if (fb) {
-    if (fb->seq_max > 0 && fb->seq_max != _async_seq) {
-      return -1;
-    }
-    _async_seq++;
-
-    if (fb->outstanding_fb == 0) {
-      olsr_timer_start(OS_SYSTEM_NETLINK_TIMEOUT, 0, fb, _feedback_timer);
-      fb->seq_min = _async_seq;
-      fb->seq_max = _async_seq;
-    }
-    fb->seq_max++;
-    fb->outstanding_fb++;
-
-    nl_hdr->nlmsg_seq = _async_seq;
-    nl_hdr->nlmsg_flags |= NLM_F_ACK;
-  }
-  else {
-    nl_hdr->nlmsg_seq = 0;
-  }
-
-  nl_hdr->nlmsg_flags |= NLM_F_MULTI;
-
-  abuf_memcpy(&_netlink_send_buffer, nl_hdr, nl_hdr->nlmsg_len);
-
-  /* trigger write */
-  olsr_socket_set_write(&_rtnetlink_socket, true);
-  return _async_seq;
-}
-
-void
-os_system_feedback_add(struct olsr_system_feedback *feedback) {
-  feedback->outstanding_fb = 0;
-  feedback->timeout = NULL;
-
-  list_init_node(&feedback->_node);
-}
-
-void
-os_system_feedback_remove(struct olsr_system_feedback *feedback) {
-  if (feedback->timeout) {
-    olsr_timer_stop(feedback->timeout);
-  }
-
-  list_remove(&feedback->_node);
-}
-
-static void
-_cb_handle_feedback_timerout(void *ptr) {
-  struct olsr_system_feedback *fb = ptr;
-
-  fb->timeout = NULL;
-  list_remove(&fb->_node);
-
-  fb->cb_timeout(fb);
-
-
-}
-
 static void
-_flush_netlink_buffer(void) {
+_flush_netlink_buffer(struct os_system_netlink *nl) {
   ssize_t ret;
 
-  /* add DONE message */
-  abuf_memcpy(&_netlink_send_buffer, &_netlink_hdr_done, sizeof(_netlink_hdr_done));
+  /* start feedback timer */
+  olsr_timer_set(&nl->timeout, OS_SYSTEM_NETLINK_TIMEOUT*10, 0, nl, _netlink_timer);
 
   /* send outgoing message */
-  _netlink_send_iov.iov_base = _netlink_send_buffer.buf;
-  _netlink_send_iov.iov_len = _netlink_send_buffer.len;
+  _netlink_send_iov[0].iov_base = nl->out.buf;
+  _netlink_send_iov[0].iov_len = nl->out.len;
 
-  if ((ret = sendmsg(_rtnetlink_async_fd, &_netlink_send_msg, 0)) <= 0) {
+  if ((ret = sendmsg(nl->socket.fd, &_netlink_send_msg, 0)) <= 0) {
     OLSR_WARN(LOG_OS_SYSTEM,
         "Cannot send data to netlink socket (%d: %s)",
         errno, strerror(errno));
   }
   else {
-    abuf_clear(&_netlink_send_buffer);
+    OLSR_DEBUG(LOG_OS_SYSTEM, "Sent %zd/%zu bytes for netlink seqno: %d",
+        ret, nl->out.len, nl->seq_used);
+    nl->seq_sent = nl->seq_used;
+    abuf_clear(&nl->out);
   }
 
-  if (_netlink_send_buffer.len == 0) {
-    olsr_socket_set_write(&_rtnetlink_socket, false);
+  if (nl->out.len == 0) {
+    olsr_socket_set_write(&nl->socket, false);
   }
 }
 
@@ -454,16 +388,16 @@ _flush_netlink_buffer(void) {
  * @param event_write
  */
 static void
-_netlink_handler(int fd,
-    void *data __attribute__((unused)),
-    bool event_read,
-    bool event_write) {
+_netlink_handler(int fd, void *data, bool event_read, bool event_write) {
+  struct os_system_netlink *nl;
+  struct nlmsghdr *nh;
   ssize_t ret;
   size_t len;
-  struct nlmsghdr *nh;
 
+  OLSR_DEBUG(LOG_OS_SYSTEM, "Got netlink message (%d/%d)", event_read, event_write);
+  nl = data;
   if (event_write) {
-    _flush_netlink_buffer();
+    _flush_netlink_buffer(nl);
   }
 
   if (!event_read) {
@@ -471,6 +405,8 @@ _netlink_handler(int fd,
   }
 
   /* handle incoming messages */
+  _netlink_rcv_iov.iov_base = nl->in;
+  _netlink_rcv_iov.iov_len = UIO_MAXIOV;
   if ((ret = recvmsg(fd, &_netlink_rcv_msg, MSG_DONTWAIT)) < 0) {
     if (errno != EAGAIN) {
       OLSR_WARN(LOG_OS_SYSTEM,"netlink recvmsg error: %s (%d)\n",
@@ -481,11 +417,9 @@ _netlink_handler(int fd,
 
   /* loop through netlink headers */
   len = (size_t) ret;
-  for (nh = _netlink_recv_buffer; NLMSG_OK (nh, len);
-       nh = NLMSG_NEXT (nh, len)) {
-
+  for (nh = nl->in; NLMSG_OK (nh, len); nh = NLMSG_NEXT (nh, len)) {
     OLSR_DEBUG(LOG_OS_SYSTEM,
-        "Netlink message received: type %d\n", _netlink_recv_buffer->nlmsg_type);
+        "Netlink message received: type %d\n", nl->in->nlmsg_type);
 
     switch (nh->nlmsg_type) {
       case NLMSG_NOOP:
@@ -497,100 +431,76 @@ _netlink_handler(int fd,
 
       case NLMSG_ERROR:
         /* Feedback for async netlink message */
-        _handle_nl_err(nh);
-        break;
-
-      case RTM_NEWLINK:
-      case RTM_DELLINK:
-        /* link up/down */
-        _handle_nl_link(nh);
-        break;
-
-      case RTM_NEWADDR:
-      case RTM_DELADDR:
-        /* address added/removed */
-        _handle_nl_addr(nh);
+        _handle_nl_err(nl, nh);
         break;
 
       default:
+        if (nl->cb_message) {
+          nl->cb_message(nh);
+        }
         break;
     }
   }
 }
 
 /**
- * Handle incoming RTM_NEWLINK/RTM_DELLINK netlink messages
- * @param nl pointer to netlink message header
+ * Handle incoming rtnetlink multicast messages for interface listeners
+ * @param hdr pointer to netlink message
  */
 static void
-_handle_nl_link(struct nlmsghdr *nl) {
+_handle_rtnetlink(struct nlmsghdr *hdr) {
   struct ifinfomsg *ifi;
+  struct ifaddrmsg *ifa;
+
   char if_name[IF_NAMESIZE];
 
-  ifi = (struct ifinfomsg *) NLMSG_DATA(nl);
+  if (hdr->nlmsg_type == RTM_NEWLINK || hdr->nlmsg_type == RTM_DELLINK) {
+    ifi = (struct ifinfomsg *) NLMSG_DATA(hdr);
 
-  if (if_indextoname(ifi->ifi_index, if_name) == NULL) {
-    OLSR_WARN(LOG_OS_SYSTEM,
-        "Failed to convert if-index to name: %d", ifi->ifi_index);
-    return;
-  }
-
-  OLSR_DEBUG(LOG_OS_SYSTEM, "Linkstatus of interface '%s' changed", if_name);
-  olsr_interface_trigger_change(if_name);
-}
+    if (if_indextoname(ifi->ifi_index, if_name) == NULL) {
+      OLSR_WARN(LOG_OS_SYSTEM,
+          "Failed to convert if-index to name: %d", ifi->ifi_index);
+      return;
+    }
 
-/**
- * Handle incoming RTM_NEWADDR/RTM_DELADDR netlink messages
- * @param nl pointer to netlink message header
- */
-static void
-_handle_nl_addr(struct nlmsghdr *nl) {
-  struct ifaddrmsg *ifa;
+    OLSR_DEBUG(LOG_OS_SYSTEM, "Linkstatus of interface '%s' changed", if_name);
+    olsr_interface_trigger_change(if_name);
+  }
 
-  char if_name[IF_NAMESIZE];
+  else if (hdr->nlmsg_type == RTM_NEWADDR || hdr->nlmsg_type == RTM_DELADDR) {
+    ifa = (struct ifaddrmsg *) NLMSG_DATA(hdr);
 
-  ifa = (struct ifaddrmsg *) NLMSG_DATA(nl);
+    if (if_indextoname(ifa->ifa_index, if_name) == NULL) {
+      OLSR_WARN(LOG_OS_SYSTEM,
+          "Failed to convert if-index to name: %d", ifa->ifa_index);
+      return;
+    }
 
-  if (if_indextoname(ifa->ifa_index, if_name) == NULL) {
-    OLSR_WARN(LOG_OS_SYSTEM,
-        "Failed to convert if-index to name: %d", ifa->ifa_index);
-    return;
+    OLSR_DEBUG(LOG_OS_SYSTEM, "Address of interface '%s' changed", if_name);
+    olsr_interface_trigger_change(if_name);
   }
-
-  OLSR_DEBUG(LOG_OS_SYSTEM, "Address of interface '%s' changed", if_name);
-  olsr_interface_trigger_change(if_name);
 }
 
+/**
+ * Handle result code in netlink message
+ * @param nl pointer to netlink handler
+ * @param nh pointer to netlink message
+ */
 static void
-_handle_nl_err(struct nlmsghdr *nl) {
-  struct olsr_system_feedback *fb;
+_handle_nl_err(struct os_system_netlink *nl, struct nlmsghdr *nh) {
   struct nlmsgerr *err;
 
-  err = (struct nlmsgerr *) NLMSG_DATA(nl);
+  err = (struct nlmsgerr *) NLMSG_DATA(nh);
 
-  if (err->msg.nlmsg_type == RTM_NEWROUTE
-      || err->msg.nlmsg_type == RTM_DELROUTE) {
-    OLSR_DEBUG(LOG_OS_SYSTEM, "Got feedback for routing seq %d: %d", nl->nlmsg_seq, err->error);
+  if (nl->cb_feedback) {
+    nl->cb_feedback(err->msg.nlmsg_seq, err->error);
   }
-
-  if (err->msg.nlmsg_seq != 0) {
-    /* handle counting of outstanding feedback */
-    list_for_each_element(&_feedback_handlers, fb, _node) {
-      if (err->msg.nlmsg_seq >= fb->seq_min && err->msg.nlmsg_seq <= fb->seq_max) {
-        fb->outstanding_fb--;
-
-        if (fb->outstanding_fb == 0) {
-          olsr_timer_stop(fb->timeout);
-          fb->timeout = NULL;
-          list_remove(&fb->_node);
-        }
-
-        fb->cb_ack(fb, err->msg.nlmsg_seq, err->error);
-        break;
-      }
-    }
-    if (list_is_empty(&_feedback_handlers)) {
-      _async_seq = 0;
-    }
+  if (nl->msg_in_transit > 0) {
+    nl->msg_in_transit--;
+  }
+  if (nl->msg_in_transit == 0) {
+    olsr_timer_stop(nl->timeout);
+    nl->timeout= NULL;
+    nl->seq_used = 0;
   }
 }
index b44e60c..f4c55a7 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/netlink.h>
 
 #include "common/netaddr.h"
+#include "olsr_socket.h"
 #include "os_helper.h"
 
 /* Linux os_system runs on "all default" except for init/cleanup */
 #define OS_SYSTEM_GETTIMEOFDAY OS_GENERIC
 #define OS_SYSTEM_LOG          OS_GENERIC
 
+struct os_system_netlink {
+  struct olsr_socket_entry socket;
+  struct autobuf out;
+  struct nlmsghdr *in;
+
+  int seq_used;
+  int seq_sent;
+
+  int msg_in_transit;
+
+  void (*cb_message)(struct nlmsghdr *hdr);
+  void (*cb_feedback)(uint32_t seq, int error);
+  void (*cb_timeout)(void);
+
+  struct olsr_timer_entry *timeout;
+};
+
+int os_system_netlink_add(struct os_system_netlink *,
+    int protocol, uint32_t multicast);
+void os_system_netlink_remove(struct os_system_netlink *);
+void os_system_netlink_send(struct os_system_netlink *fd,
+    struct nlmsghdr *nl_hdr);
+
 int os_system_netlink_addreq(struct nlmsghdr *n,
     int type, const void *data, int len);
-int os_system_netlink_sync_send(struct nlmsghdr *nl_hdr);
-int os_system_netlink_async_send(struct olsr_system_feedback *fd,
-    struct nlmsghdr *nl_hdr);
 
 static INLINE int
 os_system_netlink_addnetaddr(struct nlmsghdr *n,
index 511eff2..7c7f996 100644 (file)
@@ -1,7 +1,7 @@
 
 /*
  * The olsr.org Optimized Link-State Routing daemon(olsrd)
- * Copyright (c) 2004-2011, the olsr.org team - see HISTORY file
+ * 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
@@ -92,8 +92,7 @@ EXPORT void os_routing_cleanup(void);
 EXPORT int os_routing_init_mesh_if(struct olsr_interface *);
 EXPORT void os_routing_cleanup_mesh_if(struct olsr_interface *);
 
-EXPORT int os_routing_set(struct olsr_system_feedback *fb,
-    const struct netaddr *src, const struct netaddr *gw, const struct netaddr *dst,
+EXPORT int os_routing_set(const struct netaddr *src, const struct netaddr *gw, const struct netaddr *dst,
     int rttable, int if_index, int metric, int protocol, bool set, bool del_similar);
 
 #endif /* OS_ROUTING_H_ */
index dec0060..fdc1eef 100644 (file)
@@ -246,7 +246,9 @@ main(int argc, char **argv) {
   }
 
 #ifdef NEED_ROUTING
-  os_routing_init();
+  if (os_routing_init()) {
+    goto olsrd_cleanup;
+  }
 #endif
 
   if (os_net_init()) {
@@ -478,7 +480,7 @@ parse_commandline(int argc, char **argv, bool reload_only) {
   opt_idx = -1;
   optind = 1;
 
-  abuf_init(&log, 1024);
+  abuf_init(&log);
   cfg_cmd_clear_state(olsr_cfg_get_instance());
 
   if (reload_only) {
@@ -604,7 +606,7 @@ display_schema(void) {
 
   return_code = 0;
 
-  abuf_init(&log, 1024);
+  abuf_init(&log);
   cfg_cmd_clear_state(olsr_cfg_get_instance());
 
   if (cfg_cmd_handle_schema(olsr_cfg_get_rawdb(), _schema_name, &log)) {