detect if ipip tunnel go down, and clean up on olsr shutdown
authorMarkus Kittenberger <Markus.Kittenberger@gmx.at>
Sat, 9 Jan 2010 02:20:18 +0000 (03:20 +0100)
committerMarkus Kittenberger <Markus.Kittenberger@gmx.at>
Sat, 9 Jan 2010 02:20:18 +0000 (03:20 +0100)
src/kernel_routes.h
src/linux/kernel_routes.c
src/main.c
src/olsr_cfg.h

index 548d93d..5b7f096 100644 (file)
@@ -57,6 +57,7 @@ int olsr_ioctl_del_route6(const struct rt_entry *);
 int olsr_netlink_rule(uint8_t, uint8_t, uint16_t, uint32_t, char*);
 
 int olsr_dev_up(const char *, bool);
+int olsr_del_tunl(void);
 
 #if LINUX_RTNETLINK_LISTEN
 int rtnetlink_register_socket(int);
index c502913..8af431d 100644 (file)
@@ -164,6 +164,27 @@ static void netlink_process_link(struct nlmsghdr *h)
   struct interface *iface;
   struct olsr_if *tmp_if;
 
+  /*monitor tunl0 and olsrtunl*/
+  if (olsr_cnf->smart_gateway_active) {
+    if (ifi->ifi_index==olsr_cnf->ipip_if_index) {
+      /*we try to delete the interface completely*/
+      olsr_del_tunl();
+      //!!?? shall we mark the default route dirty?
+      /*we mark it unexisting -> we will create the tunnel again (if gateway changes)*/
+      olsr_cnf->ipip_if_index = false;
+      return;
+    }
+    if (ifi->ifi_index==olsr_cnf->ipip_base_if_index) {
+      /*we try to take it up again (if its only down it might workout)*/
+      if (olsr_dev_up("tunl0",false)) return; //!!?? test this
+      /*we disable -> this should stop us announcing being a smart gateway, and can not use tunnels as its unlikely to be able to crete them without tunl0*/
+      olsr_cnf->smart_gateway_active=false;
+      /*recovery is not easy as potentially the ipip module is not loaded any more*/
+      /*but it could just mean the tunl0 is down, and the gatewaytunnel would work*/
+      return;
+    }
+  }
+
   iface = if_ifwithindex(ifi->ifi_index);
   if (iface == NULL) {
     return;
@@ -260,6 +281,11 @@ static int set_tunl(int cmd, unsigned long int ipv4)
   return err;
 }
 
+int olsr_del_tunl(void)
+{
+  return set_tunl(SIOCDELTUNNEL,0x00000000);//!!??test if this deletes tunnel
+}
+
 static void
 olsr_netlink_addreq(struct olsr_rtreq *req, int type, const void *data, int len)
 {
@@ -367,13 +393,13 @@ olsr_netlink_route_int(const struct rt_entry *rt, uint8_t family, uint8_t rttabl
       req.r.rtm_scope = RT_SCOPE_LINK;
 
       /*add interface*/
-      if ((&olsr_cnf->smart_gateway_active) && family != AF_INET)
+      if ((olsr_cnf->smart_gateway_active) && family != AF_INET)
       {
         printf("smart gateway not available for ipv6 currently");
         return -1;
       }
       else if(flag == RT_SMARTGW)
-      //else if ((&olsr_cnf->smart_gateway_active) && (rt->rt_dst.prefix_len == 0) && (&olsr_cnf->ipip_if_index))
+      //else if ((olsr_cnf->smart_gateway_active) && (rt->rt_dst.prefix_len == 0) && (&olsr_cnf->ipip_if_index))
       {
         //add interface (without nexthop if possible (if not use &rt->rt_best->rtp_originator))
         olsr_netlink_addreq(&req, RTA_OIF, &olsr_cnf->ipip_if_index, sizeof(&olsr_cnf->ipip_if_index));
@@ -651,8 +677,8 @@ static int
 olsr_netlink_route(const struct rt_entry *rt, uint8_t family, uint8_t rttable, __u16 cmd)
 {
   /*check if this rule is relevant for smartgw*/
-  if ((&olsr_cnf->smart_gateway_active) && (rt->rt_dst.prefix_len == 0) ) {
-    if (&olsr_cnf->ipip_if_index==NULL) {
+  if ((olsr_cnf->smart_gateway_active) && (rt->rt_dst.prefix_len == 0) ) {
+    if (olsr_cnf->ipip_if_index == -1) {
       /*create tunnel*/
       set_tunl(SIOCADDTUNNEL,rt->rt_best->rtp_originator.v4.s_addr);
       /*!!?? currently it gets never deleted on shutdown, anyways reusing existing tunnel might be a safe approach if creating fails?*/
index ac76c4f..049b24c 100644 (file)
@@ -475,6 +475,7 @@ int main(int argc, char *argv[]) {
     const char* tunlbase = "tunl0";
     //take up tunl0 device or disable smartgateway
     olsr_cnf->smart_gateway_active = olsr_dev_up(tunlbase,false);//!!?? kernel 2.4 may need true to function as gateway, does it harm to do anyway
+    olsr_cnf->ipip_base_if_index = if_nametoindex(tunlbase);
 
     if (olsr_cnf->smart_gateway_active) {
       struct olsr_if *cfg_if;
@@ -501,6 +502,7 @@ int main(int argc, char *argv[]) {
       //should we start now doing so anyways? (beter not, use only new RTTableRule priority)
 
       //as above ist neither finalized nor done in parser, we use hardcoded values
+      olsr_cnf->ipip_if_index = false;
       olsr_cnf->ipip_name=ipip_default_name;
       olsr_cnf->rttable_default=112;
       olsr_cnf->rttable_smartgw=113;
@@ -704,12 +706,28 @@ static void olsr_shutdown(int signo __attribute__ ((unused)))
   close(olsr_cnf->ioctl_s);
 
 #if LINUX_POLICY_ROUTING
-//!!?? warning we do not delete any smartgw rules
-printf("smartgw rules where not deleted!");
 
-  /* RtTable (linux only!!) */
+  /*delete smartgw tunnel if it index is known*/
+  if (olsr_cnf->ipip_if_index) olsr_del_tunl();
+
+  /*!!?? we should take down the tunl0 interface*/
+
+  /*we shall delete all rules with an configured prio*/
+  if (olsr_cnf->rttable_default_rule>0) {
+    struct olsr_if * cfg_if;
+    for (cfg_if = olsr_cnf->interfaces; cfg_if; cfg_if = cfg_if->next) {
+      olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable_default, RTM_DELRULE, olsr_cnf->rttable_default_rule, cfg_if->name);
+    }
+  }
+  if (olsr_cnf->rttable_smartgw_rule>0)
+    olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable_smartgw, RTM_DELRULE, olsr_cnf->rttable_smartgw_rule, NULL);
+  if (olsr_cnf->rttable_backup_rule>0)
+    olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable_default, RTM_DELRULE, olsr_cnf->rttable_backup_rule, NULL);
+
+
+  /* RtTable backup rule */
   if ((olsr_cnf->rttable < 253) & (olsr_cnf->rttable > 0)) {
-    olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable, RTM_DELRULE, 65535, NULL);
+    olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable, RTM_DELRULE, (olsr_cnf->rttable_rule?olsr_cnf->rttable_rule:65535), NULL);
   }
 
   close(olsr_cnf->rtnl_s);
index 0afbb89..c4d88e5 100644 (file)
@@ -256,7 +256,7 @@ struct olsrd_config {
   bool smart_gateway_active;
   uint32_t smart_gateway_uplink;
   uint32_t smart_gateway_downlink;
-  uint32_t ipip_if_index;
+  int ipip_if_index, ipip_base_if_index;
   unsigned long int ipip_remote_address;
   const char *ipip_name;