Let interface monitor take interface down and up
[olsrd.git] / src / interfaces.c
index cd2130d..d5c855c 100644 (file)
@@ -39,6 +39,9 @@
  *
  */
 
+#include <signal.h>
+#include <unistd.h>
+
 #include "defs.h"
 #include "interfaces.h"
 #include "ifnet.h"
 #include "olsr.h"
 #include "net_olsr.h"
 #include "ipcalc.h"
+#include "log.h"
+#include "parser.h"
+#include "socket_parser.h"
+
+#ifdef WIN32
+#include <winbase.h>
+#define close(x) closesocket(x)
+#endif
 
 /* The interface linked-list */
 struct interface *ifnet;
 
 /* Ifchange functions */
 struct ifchgf {
-  int (*function) (struct interface *, int);
+  int (*function) (struct interface *, enum olsr_ifchg_flag);
   struct ifchgf *next;
 };
 
@@ -73,7 +84,7 @@ struct olsr_cookie_info *hna_gen_timer_cookie = NULL;
  *@return the number of interfaces configured
  */
 int
-ifinit(void)
+olsr_init_interfacedb(void)
 {
   struct olsr_if *tmp_if;
 
@@ -109,7 +120,7 @@ ifinit(void)
 }
 
 void
-run_ifchg_cbs(struct interface *ifp, int flag)
+olsr_trigger_ifchange(struct interface *ifp, enum olsr_ifchg_flag flag)
 {
   struct ifchgf *tmp_ifchgf_list = ifchgf_list;
 
@@ -170,7 +181,7 @@ if_ifwithsock(int fd)
   ifp = ifnet;
 
   while (ifp) {
-    if (ifp->olsr_socket == fd)
+    if (ifp->olsr_socket == fd || ifp->send_socket == fd)
       return ifp;
     ifp = ifp->int_next;
   }
@@ -200,6 +211,28 @@ if_ifwithname(const char *if_name)
   return NULL;
 }
 
+/**
+ *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.
  *
@@ -244,7 +277,7 @@ if_ifwithindex_name(const int if_index)
  *@return nada
  */
 struct olsr_if *
-queue_if(const char *name, int hemu)
+olsr_create_olsrif(const char *name, int hemu)
 {
   struct olsr_if *interf_n = olsr_cnf->interfaces;
   size_t name_size;
@@ -253,7 +286,7 @@ queue_if(const char *name, int hemu)
 
   /* check if the inerfaces already exists */
   while (interf_n != NULL) {
-    if (memcmp(interf_n->name, name, strlen(name)) == 0) {
+    if (strcmp(interf_n->name, name) == 0) {
       fprintf(stderr, "Duplicate interfaces defined... not adding %s\n", name);
       return NULL;
     }
@@ -264,13 +297,16 @@ queue_if(const char *name, int hemu)
 
   name_size = strlen(name) + 1;
   interf_n->name = olsr_malloc(name_size, "queue interface name");
-  interf_n->cnf = NULL;
-  interf_n->interf = NULL;
-  interf_n->configured = 0;
+  strscpy(interf_n->name, name, name_size);
 
-  interf_n->host_emul = hemu ? OLSR_TRUE : OLSR_FALSE;
+  interf_n->cnf = olsr_malloc(sizeof(*interf_n->cnf), "queue cnf");
+
+  interf_n->cnfi = olsr_malloc(sizeof(*interf_n->cnfi), "queue cnfi");
+  memset(interf_n->cnfi, 0xFF, sizeof(*interf_n->cnfi));
+  interf_n->cnfi->orig_lq_mult_cnt=0;
+
+  interf_n->host_emul = hemu ? true : false;
 
-  strscpy(interf_n->name, name, name_size);
   interf_n->next = olsr_cnf->interfaces;
   olsr_cnf->interfaces = interf_n;
 
@@ -286,7 +322,7 @@ queue_if(const char *name, int hemu)
  *@return
  */
 int
-add_ifchgf(int (*f) (struct interface *, int))
+olsr_add_ifchange_handler(int (*f) (struct interface *, enum olsr_ifchg_flag))
 {
 
   struct ifchgf *new_ifchgf;
@@ -305,7 +341,7 @@ add_ifchgf(int (*f) (struct interface *, int))
  * Remove an ifchange function
  */
 int
-del_ifchgf(int (*f) (struct interface *, int))
+olsr_remove_ifchange_handler(int (*f) (struct interface *, enum olsr_ifchg_flag))
 {
   struct ifchgf *tmp_ifchgf, *prev;
 
@@ -331,6 +367,85 @@ del_ifchgf(int (*f) (struct interface *, int))
   return 0;
 }
 
+void
+olsr_remove_interface(struct olsr_if * iface)
+{
+  struct interface *ifp, *tmp_ifp;
+  ifp = iface->interf;
+
+  OLSR_PRINTF(1, "Removing interface %s\n", iface->name);
+  olsr_syslog(OLSR_LOG_INFO, "Removing interface %s\n", iface->name);
+
+  olsr_delete_link_entry_by_ip(&ifp->ip_addr);
+
+  /*
+   *Call possible ifchange functions registered by plugins
+   */
+  olsr_trigger_ifchange(ifp, IFCHG_IF_REMOVE);
+
+  /* cleanup routes over this interface */
+  olsr_delete_interface_routes(ifp->if_index);
+
+  /* Dequeue */
+  if (ifp == ifnet) {
+    ifnet = ifp->int_next;
+  } else {
+    tmp_ifp = ifnet;
+    while (tmp_ifp->int_next != ifp) {
+      tmp_ifp = tmp_ifp->int_next;
+    }
+    tmp_ifp->int_next = ifp->int_next;
+  }
+
+  /* Remove output buffer */
+  net_remove_buffer(ifp);
+
+  /* Check main addr */
+  /* deactivated to prevent change of originator IP */
+#if 0
+  if (ipequal(&olsr_cnf->main_addr, &ifp->ip_addr)) {
+    if (ifnet == NULL) {
+      /* No more interfaces */
+      memset(&olsr_cnf->main_addr, 0, olsr_cnf->ipsize);
+      OLSR_PRINTF(1, "No more interfaces...\n");
+    } else {
+      struct ipaddr_str buf;
+      olsr_cnf->main_addr = ifnet->ip_addr;
+      OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
+      olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
+    }
+  }
+#endif
+  /*
+   * Deregister functions for periodic message generation
+   */
+  olsr_stop_timer(ifp->hello_gen_timer);
+  olsr_stop_timer(ifp->tc_gen_timer);
+  olsr_stop_timer(ifp->mid_gen_timer);
+  olsr_stop_timer(ifp->hna_gen_timer);
+
+  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_syslog(OLSR_LOG_INFO, "No more active interfaces - exiting.\n");
+    olsr_exit("No more active interfaces - exiting.\n", EXIT_FAILURE);
+  }
+}
+
 /*
  * Local Variables:
  * c-basic-offset: 2