Let interface monitor take interface down and up
authorHenning Rogge <hrogge@googlemail.com>
Thu, 4 Feb 2010 19:51:57 +0000 (20:51 +0100)
committerHenning Rogge <hrogge@googlemail.com>
Thu, 4 Feb 2010 19:51:57 +0000 (20:51 +0100)
Some refactorings on the interface system

Makefile
lib/bmf/src/Bmf.c
lib/bmf/src/Bmf.h
src/interfaces.c
src/interfaces.h
src/linux/kernel_routes.c
src/linux/net.c
src/process_routes.c
src/process_routes.h
src/unix/ifnet.c
src/win32/ifnet.c

index 658400e..c8f577d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -85,13 +85,12 @@ src/builddata.c:
 
 clean:
        -rm -f $(OBJS) $(SRCS:%.c=%.d) $(EXENAME) $(EXENAME).exe src/builddata.c $(TMPFILES)
-ifeq ($(OS), win32)
        -rm -f libolsrd.a
+       -rm -f olsr_switch.exe
        -rm -f gui/win32/Main/olsrd_cfgparser.lib
        -rm -f olsr-setup.exe
        -rm -fr gui/win32/Main/Release
        -rm -fr gui/win32/Shim/Release
-endif
 
 uberclean:     clean clean_libs
        -rm -f $(TAGFILE)
index dc91d43..ac89b42 100644 (file)
@@ -1157,7 +1157,7 @@ BmfRun(void *useless __attribute__ ((unused)))
  * Data Used  : none
  * ------------------------------------------------------------------------- */
 int
-InterfaceChange(struct interface *interf, int action)
+InterfaceChange(struct interface *interf, enum olsr_ifchg_flag action)
 {
   switch (action) {
   case (IFCHG_IF_ADD):
index 38257f8..f57fb4d 100644 (file)
@@ -41,6 +41,7 @@
  * ------------------------------------------------------------------------- */
 
 #include "olsrd_plugin.h"       /* union set_plugin_parameter_addon */
+#include "interfaces.h"
 
 /* BMF plugin data */
 #define PLUGIN_NAME "OLSRD Basic Multicast Forwarding (BMF) plugin"
@@ -62,7 +63,7 @@ extern int BroadcastRetransmitCount;
 
 void BmfPError(const char *format, ...) __attribute__ ((format(printf, 1, 2)));
 union olsr_ip_addr *MainAddressOf(union olsr_ip_addr *ip);
-int InterfaceChange(struct interface *interf, int action);
+int InterfaceChange(struct interface *interf, enum olsr_ifchg_flag action);
 int SetFanOutLimit(const char *value, void *data, set_plugin_parameter_addon addon);
 int InitBmf(struct interface *skipThisIntf);
 void CloseBmf(void);
index acd2969..d5c855c 100644 (file)
 #ifdef WIN32
 #include <winbase.h>
 #define close(x) closesocket(x)
-int __stdcall SignalHandler(unsigned long signo);
-
-static unsigned long __stdcall
-SignalHandlerWrapper(void *Dummy __attribute__ ((unused)))
-{
-  SignalHandler(0);
-  return 0;
-}
-
-static void
-CallSignalHandler(void)
-{
-  unsigned long ThreadId;
-
-  CreateThread(NULL, 0, SignalHandlerWrapper, NULL, 0, &ThreadId);
-}
-
-
 #endif
 
 /* The interface linked-list */
@@ -81,7 +63,7 @@ struct interface *ifnet;
 
 /* Ifchange functions */
 struct ifchgf {
-  int (*function) (struct interface *, int);
+  int (*function) (struct interface *, enum olsr_ifchg_flag);
   struct ifchgf *next;
 };
 
@@ -138,7 +120,7 @@ olsr_init_interfacedb(void)
 }
 
 void
-olsr_trigger_ifchange(struct interface *ifp, int flag)
+olsr_trigger_ifchange(struct interface *ifp, enum olsr_ifchg_flag flag)
 {
   struct ifchgf *tmp_ifchgf_list = ifchgf_list;
 
@@ -230,6 +212,28 @@ if_ifwithname(const char *if_name)
 }
 
 /**
+ *Find the olsr_if with a given label.
+ *
+ *@param if_name the label of the interface to find.
+ *
+ *@return return the interface struct representing the interface
+ *that matched the label.
+ */
+struct olsr_if *
+olsrif_ifwithname(const char *if_name)
+{
+  struct olsr_if *oifp = olsr_cnf->interfaces;
+  while (oifp) {
+    /* good ol' strcmp should be sufficcient here */
+    if (strcmp(oifp->name, if_name) == 0) {
+      return oifp;
+    }
+    oifp = oifp->next;
+  }
+  return NULL;
+}
+
+/**
  *Find the interface with a given interface index.
  *
  *@param iif_index of the interface to find.
@@ -318,7 +322,7 @@ olsr_create_olsrif(const char *name, int hemu)
  *@return
  */
 int
-olsr_add_ifchange_handler(int (*f) (struct interface *, int))
+olsr_add_ifchange_handler(int (*f) (struct interface *, enum olsr_ifchg_flag))
 {
 
   struct ifchgf *new_ifchgf;
@@ -337,7 +341,7 @@ olsr_add_ifchange_handler(int (*f) (struct interface *, int))
  * Remove an ifchange function
  */
 int
-olsr_remove_ifchange_handler(int (*f) (struct interface *, int))
+olsr_remove_ifchange_handler(int (*f) (struct interface *, enum olsr_ifchg_flag))
 {
   struct ifchgf *tmp_ifchgf, *prev;
 
@@ -364,10 +368,9 @@ olsr_remove_ifchange_handler(int (*f) (struct interface *, int))
 }
 
 void
-olsr_remove_interface(struct olsr_if * iface, bool went_down)
+olsr_remove_interface(struct olsr_if * iface)
 {
   struct interface *ifp, *tmp_ifp;
-  struct rt_entry *rt;
   ifp = iface->interf;
 
   OLSR_PRINTF(1, "Removing interface %s\n", iface->name);
@@ -380,16 +383,8 @@ olsr_remove_interface(struct olsr_if * iface, bool went_down)
    */
   olsr_trigger_ifchange(ifp, IFCHG_IF_REMOVE);
 
-  /*remove all routes*/
-  if (went_down) {
-    OLSR_FOR_ALL_RT_ENTRIES(rt) {
-      if (rt->rt_nexthop.iif_index == ifp->if_index) {
-        //marks route as unexisting in kernel, do this better !?
-        rt->rt_nexthop.iif_index=-1;
-      }
-    }
-    OLSR_FOR_ALL_RT_ENTRIES_END(rt);
-  }
+  /* cleanup routes over this interface */
+  olsr_delete_interface_routes(ifp->if_index);
 
   /* Dequeue */
   if (ifp == ifnet) {
@@ -431,23 +426,23 @@ olsr_remove_interface(struct olsr_if * iface, bool went_down)
 
   iface->configured = 0;
   iface->interf = NULL;
+
   /* Close olsr socket */
   close(ifp->olsr_socket);
   remove_olsr_socket(ifp->olsr_socket, &olsr_input);
 
+  if (ifp->send_socket != ifp->olsr_socket) {
+    close(ifp->send_socket);
+    remove_olsr_socket(ifp->send_socket, &olsr_input);
+  }
+
   /* Free memory */
   free(ifp->int_name);
   free(ifp);
 
   if ((ifnet == NULL) && (!olsr_cnf->allow_no_interfaces)) {
-    OLSR_PRINTF(1, "No more active interfaces - exiting.\n");
     olsr_syslog(OLSR_LOG_INFO, "No more active interfaces - exiting.\n");
-    olsr_cnf->exit_value = EXIT_FAILURE;
-#ifndef WIN32
-    kill(getpid(), SIGINT);
-#else
-    CallSignalHandler();
-#endif
+    olsr_exit("No more active interfaces - exiting.\n", EXIT_FAILURE);
   }
 }
 
index 969b973..0eed0c1 100644 (file)
@@ -188,9 +188,11 @@ struct interface {
 
 /* Ifchange actions */
 
-#define IFCHG_IF_ADD           1
-#define IFCHG_IF_REMOVE        2
-#define IFCHG_IF_UPDATE        3
+enum olsr_ifchg_flag {
+  IFCHG_IF_ADD = 1,
+  IFCHG_IF_REMOVE = 2,
+  IFCHG_IF_UPDATE = 3
+};
 
 /* The interface linked-list */
 extern struct interface *ifnet;
@@ -198,13 +200,14 @@ extern struct interface *ifnet;
 int olsr_init_interfacedb(void);
 void olsr_delete_interfaces(void);
 
-void olsr_trigger_ifchange(struct interface *, int);
+void olsr_trigger_ifchange(struct interface *, enum olsr_ifchg_flag);
 
 struct interface *if_ifwithsock(int);
 
 struct interface *if_ifwithaddr(const union olsr_ip_addr *);
 
 struct interface *if_ifwithname(const char *);
+struct olsr_if *olsrif_ifwithname(const char *if_name);
 
 const char *if_ifwithindex_name(const int if_index);
 
@@ -212,11 +215,11 @@ struct interface *if_ifwithindex(const int if_index);
 
 struct olsr_if *olsr_create_olsrif(const char *name, int hemu);
 
-int olsr_add_ifchange_handler(int (*f) (struct interface *, int));
+int olsr_add_ifchange_handler(int (*f) (struct interface *, enum olsr_ifchg_flag));
 
-int olsr_remove_ifchange_handler(int (*f) (struct interface *, int));
+int olsr_remove_ifchange_handler(int (*f) (struct interface *, enum olsr_ifchg_flag));
 
-void olsr_remove_interface(struct olsr_if *, bool);
+void olsr_remove_interface(struct olsr_if *);
 
 extern struct olsr_cookie_info *interface_poll_timer_cookie;
 extern struct olsr_cookie_info *hello_gen_timer_cookie;
index 2b44ee8..0864b91 100644 (file)
@@ -119,7 +119,6 @@ static void netlink_process_link(struct nlmsghdr *h)
 {
   struct ifinfomsg *ifi = (struct ifinfomsg *) NLMSG_DATA(h);
   struct interface *iface;
-  struct olsr_if *tmp_if;
 
   /*monitor tunl0 and olsrtunl*/
   if (olsr_cnf->smart_gw_active) {
@@ -156,27 +155,19 @@ static void netlink_process_link(struct nlmsghdr *h)
   }
 
   iface = if_ifwithindex(ifi->ifi_index);
-  if (iface == NULL) {
-    return;
-  }
-  
-  //all IFF flags: LOOPBACK,BROADCAST;POINTOPOINT;MULTICAST;NOARP;ALLMULTI;PROMISC;MASTER;SLAVE;DEBUG;DYNAMIC;AUTOMEDIA;PORTSEL;NOTRAILERS;UP;LOWER_UP;DORMANT
-  /* check if interface is up and running? (a not running interface keeps its routes, so better not react like on ifdown!!??) */
-  if (ifi->ifi_flags&IFF_UP) {
-    OLSR_PRINTF(3,"interface %s changed but is still up!\n", iface->int_name);
-    return; //we are currently only interested in interfaces that are/go down
-  } else {
-    OLSR_PRINTF(1,"interface %s is down!\n", iface->int_name);
-  }
+  if (iface == NULL && (ifi->ifi_flags & IFF_UP) != 0) {
+    char namebuffer[IF_NAMESIZE];
+    struct olsr_if *oif;
 
-  //only for still configured interfaces (ifup has to be detected with regular interface polling)
-  for (tmp_if = olsr_cnf->interfaces; tmp_if != NULL; tmp_if = tmp_if->next) {
-    if (tmp_if->interf==iface) {
-      OLSR_PRINTF(1,"-> removing %s from olsr config!\n", iface->int_name);
-      olsr_remove_interface(tmp_if,true);
-      break;
+    if (if_indextoname(ifi->ifi_index, namebuffer)) {
+      if ((oif = olsrif_ifwithname(namebuffer)) != NULL) {
+        chk_if_up(oif, 3);
+      }
     }
   }
+  else if (iface != NULL && (ifi->ifi_flags & IFF_UP) == 0) {
+    olsr_remove_interface(iface->olsr_if);
+  }
 }
 
 void rtnetlink_read(int sock)
@@ -202,7 +193,7 @@ void rtnetlink_read(int sock)
   iov.iov_len = sizeof(buffer);
 
   while (true) { //read until ret<0;
-    ret=recvmsg(sock, &msg, 0);
+    ret=recvmsg(sock, &msg, MSG_DONTWAIT);
     if (ret<0) {
       if (errno != EAGAIN) OLSR_PRINTF(1,"netlink listen error %u - %s\n",errno,strerror(errno));
       return;
index 1e19937..820c2c4 100644 (file)
@@ -890,7 +890,7 @@ int olsr_if_setip(const char *dev, union olsr_ip_addr *ip, int ip_version) {
   }
   memcpy(&ifr.ifr_addr, &s, sizeof(s));
 
-  if (ioctl(olsr_cnf->ioctl_s, SIOCSIFADDR, ifr) < 0) {
+  if (ioctl(olsr_cnf->ioctl_s, SIOCSIFADDR, &ifr) < 0) {
     perror("ioctl SIOCSIFADDR (set addr)");
     return 1;
   }
index 2c8689c..c84e6b2 100644 (file)
@@ -269,7 +269,6 @@ olsr_delete_outdated_routes(struct rt_entry *rt)
   struct avl_node *rtp_tree_node, *next_rtp_tree_node;
 
   for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = next_rtp_tree_node) {
-
     /*
      * pre-fetch the next node before loosing context.
      */
@@ -282,15 +281,15 @@ olsr_delete_outdated_routes(struct rt_entry *rt)
      * comparing for unequalness avoids handling version number wraps.
      */
     if (routingtree_version != rtp->rtp_version) {
-
       /* remove from the originator tree */
       avl_delete(&rt->rt_path_tree, rtp_tree_node);
       rtp->rtp_rt = NULL;
+
+      if (rt->rt_best == rtp) {
+        rt->rt_best = NULL;
+      }
     }
   }
-
-  /* safety measure against dangling pointers */
-  rt->rt_best = NULL;
 }
 
 /**
@@ -336,6 +335,56 @@ olsr_update_rib_routes(void)
   OLSR_FOR_ALL_RT_ENTRIES_END(rt);
 }
 
+void
+olsr_delete_interface_routes(int if_index) {
+  struct rt_entry *rt;
+  bool triggerUpdate = false;
+
+  OLSR_FOR_ALL_RT_ENTRIES(rt) {
+    bool mightTrigger = false;
+    struct rt_path *rtp;
+    struct avl_node *rtp_tree_node, *next_rtp_tree_node;
+
+    /* run through all routing paths of route */
+    for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = next_rtp_tree_node) {
+      /*
+       * pre-fetch the next node before loosing context.
+       */
+      next_rtp_tree_node = avl_walk_next(rtp_tree_node);
+
+      rtp = rtp_tree2rtp(rtp_tree_node);
+
+      /* nexthop use lost interface ? */
+      if (rtp->rtp_nexthop.iif_index == if_index) {
+        /* remove from the originator tree */
+        avl_delete(&rt->rt_path_tree, rtp_tree_node);
+        rtp->rtp_rt = NULL;
+
+        if (rt->rt_best == rtp) {
+          rt->rt_best = NULL;
+          mightTrigger = true;
+        }
+      }
+    }
+
+    if (mightTrigger) {
+      if (!rt->rt_path_tree.count) {
+        /* oops, all routes are gone - flush the route head */
+        avl_delete(&routingtree, rt_tree_node);
+
+        /* do not dequeue route because they are already gone */
+      }
+      triggerUpdate = true;
+    }
+  } OLSR_FOR_ALL_RT_ENTRIES_END(rt)
+
+  /* trigger route update if necessary */
+  if (triggerUpdate) {
+    olsr_update_rib_routes();
+    olsr_update_kernel_routes();
+  }
+}
+
 /**
  * Propagate the accumulated changes from the last rib update to the kernel.
  */
index 776b49a..272a410 100644 (file)
@@ -57,6 +57,7 @@ void olsr_update_rib_routes(void);
 void olsr_update_kernel_routes(void);
 void olsr_delete_all_kernel_routes(void);
 uint8_t olsr_rt_flags(const struct rt_entry *);
+void olsr_delete_interface_routes(int if_index);
 
 #endif
 
index 09b1c02..bd50ab3 100644 (file)
@@ -358,9 +358,8 @@ chk_if_changed(struct olsr_if *iface)
 
 remove_interface:
 
-olsr_remove_interface(iface, false);
-
-return 0;
+  olsr_remove_interface(iface);
+  return 0;
 }
 
 /**
@@ -708,15 +707,15 @@ chk_if_up(struct olsr_if *iface, int debuglvl __attribute__ ((unused)))
 
   ifp = olsr_malloc(sizeof(struct interface), "Interface update 2");
 
-  /* initialize backpointer */
-  ifp->olsr_if = iface;
-
   iface->configured = 1;
   iface->interf = ifp;
 
   /* XXX bad code */
   memcpy(ifp, &ifs, sizeof(struct interface));
 
+  /* initialize backpointer */
+  ifp->olsr_if = iface;
+
   ifp->immediate_send_tc = (iface->cnf->tc_params.emission_interval < iface->cnf->hello_params.emission_interval);
   if (olsr_cnf->max_jitter == 0) {
     /* max_jitter determines the max time to store to-be-send-messages, correlated with random() */
index b107d5e..fef1b83 100644 (file)
@@ -638,7 +638,7 @@ chk_if_changed(struct olsr_if *IntConf)
   Int = IntConf->interf;
 
   if (GetIntInfo(&Info, IntConf->name) < 0) {
-    olsr_remove_interface(IntConf,false);
+    olsr_remove_interface(IntConf);
     return 1;
   }