First version that can establish a real tunnel to the gateway. Still lot's of stuff...
authorHenning Rogge <hrogge@googlemail.com>
Thu, 11 Feb 2010 20:19:53 +0000 (21:19 +0100)
committerHenning Rogge <hrogge@googlemail.com>
Thu, 11 Feb 2010 20:19:53 +0000 (21:19 +0100)
16 files changed:
make/Makefile.linux
src/duplicate_set.c
src/duplicate_set.h
src/gateway.c
src/gateway.h
src/gateway_default_handler.c
src/hna_set.c
src/ipcalc.c
src/ipcalc.h
src/kernel_routes.h
src/linux/kernel_routes_nl.c
src/linux/kernel_tunnel.c
src/main.c
src/olsr.c
src/olsr_cfg.h
src/process_routes.c

index 2784837..38d6814 100644 (file)
@@ -9,7 +9,7 @@ LIBDIR =        $(DESTDIR)$(shell if [ "$(ARCH)" = "x86_64" -a -d "/usr/lib64" ]; then
 SRCS +=        $(wildcard src/linux/*.c src/unix/*.c)
 HDRS +=                $(wildcard src/linux/*.h src/unix/*.h)
 
-CPPFLAGS +=    -Dlinux -D LINUX_NETLINK_ROUTING
+CPPFLAGS +=    -Dlinux -DLINUX_NETLINK_ROUTING
 LIBS +=                
 
 PLUGIN_FULLNAME ?= $(PLUGIN_NAME).so.$(PLUGIN_VER)
index 3bc55a9..7c0de1d 100644 (file)
@@ -99,6 +99,19 @@ olsr_cleanup_duplicate_entry(void __attribute__ ((unused)) * unused)
   OLSR_FOR_ALL_DUP_ENTRIES_END(entry);
 }
 
+int olsr_seqno_diff(uint16_t seqno1, uint16_t seqno2) {
+  int diff = (int)seqno1 - (int)(seqno2);
+
+  // overflow ?
+  if (diff > (1 << 15)) {
+    diff -= (1 << 16);
+  }
+  else if (diff < -(1 << 15)) {
+      diff += (1 << 16);
+  }
+  return diff;
+}
+
 int
 olsr_message_is_duplicate(union olsr_message *m)
 {
@@ -136,20 +149,13 @@ olsr_message_is_duplicate(union olsr_message *m)
     return false;               // okay, we process this package
   }
 
-  diff = (int)seqnr - (int)(entry->seqnr);
 
   // update timestamp
   if (valid_until > entry->valid_until) {
     entry->valid_until = valid_until;
   }
-  // overflow ?
-  if (diff > (1 << 15)) {
-    diff -= (1 << 16);
-  }
-  else if (diff < -(1 << 15)) {
-      diff += (1 << 16);
-  }
 
+  diff = olsr_seqno_diff(seqnr, entry->seqnr);
   if (diff < -31) {
     entry->too_low_counter++;
 
index d07a033..06439fa 100644 (file)
@@ -66,6 +66,7 @@ AVLNODE2STRUCT(duptree2dupentry, struct dup_entry, avl);
 void olsr_init_duplicate_set(void);
 void olsr_cleanup_duplicates(union olsr_ip_addr *orig);
 struct dup_entry *olsr_create_duplicate_entry(void *ip, uint16_t seqnr);
+int olsr_seqno_diff(uint16_t seqno1, uint16_t seqno2);
 int olsr_message_is_duplicate(union olsr_message *m);
 void olsr_print_duplicate_table(void);
 
index 4302fdf..bb53f3d 100644 (file)
 #include "olsr_cfg.h"
 #include "olsr_cookie.h"
 #include "scheduler.h"
+#include "kernel_routes.h"
 #include "kernel_tunnel.h"
+#include "net_os.h"
+#include "duplicate_set.h"
 #include "gateway_default_handler.h"
 #include "gateway.h"
 
-#include "assert.h"
+#include <assert.h>
+#include <net/if.h>
 
 struct avl_tree gateway_tree;
 
@@ -25,6 +29,11 @@ static uint8_t smart_gateway_netmask[sizeof(union olsr_ip_addr)];
 static struct gateway_entry *current_ipv4_gw, *current_ipv6_gw;
 static struct olsr_gw_handler *gw_handler;
 
+static const char v4gw_tunnel[] = "olsr_ipv4_inet";
+static const char v6gw_tunnel[] = "olsr_ipv6_inet";
+
+static uint32_t v4gw_index, v6gw_index;
+
 /**
  * Reconstructs an uplink/downlink speed value from the encoded
  * 1 byte transport value (3 bit mantissa, 5 bit exponent)
@@ -77,6 +86,9 @@ olsr_init_gateways(void) {
   current_ipv4_gw = NULL;
   current_ipv6_gw = NULL;
 
+  v4gw_index = 0;
+  v6gw_index = 0;
+
   memset(&smart_gateway_netmask, 0, sizeof(smart_gateway_netmask));
 
   if (olsr_cnf->smart_gw_active) {
@@ -96,7 +108,6 @@ olsr_init_gateways(void) {
       memcpy(&ip[GW_HNA_V6PREFIX], &olsr_cnf->smart_gw_prefix.prefix, 8);
     }
   }
-
   if (olsr_os_init_iptunnel()) {
     return 1;
   }
@@ -112,8 +123,12 @@ olsr_init_gateways(void) {
  * Cleanup gateway tunnel system
  */
 void olsr_cleanup_gateways(void) {
-  // TODO: inet gw tunnel cleanup
-
+  if (current_ipv4_gw) {
+    olsr_os_del_ipip_tunnel(v4gw_tunnel, true);
+  }
+  if (current_ipv6_gw) {
+    olsr_os_del_ipip_tunnel(v6gw_tunnel, false);
+  }
   olsr_os_cleanup_iptunnel();
 }
 
@@ -158,34 +173,73 @@ olsr_set_inetgw_handler(struct olsr_gw_handler *h) {
  * @param ipv6 set ipv6 gateway
  * @param external true if change was triggered directly by an user,
  *   false if triggered by automatic lookup.
- * @return 0 if successful, -1 otherwise
+ * @return true if an error happened, false otherwise
  */
-int
+bool
 olsr_set_inet_gateway(union olsr_ip_addr *originator, bool ipv4, bool ipv6, bool external) {
-  struct gateway_entry *entry;
+  struct gateway_entry *entry, *oldV4, *oldV6;
+  oldV4 = current_ipv4_gw;
+  oldV6 = current_ipv6_gw;
 
   ipv4 = ipv4 && (olsr_cnf->ip_version == AF_INET || olsr_cnf->use_niit);
   ipv6 = ipv6 && (olsr_cnf->ip_version == AF_INET6);
 
+  if (ipv4) {
+    current_ipv4_gw = NULL;
+  }
+  if (ipv6) {
+    current_ipv6_gw = NULL;
+  }
+
   entry = olsr_find_gateway_entry(originator);
   if (entry != NULL) {
-    if (ipv4 && entry->ipv4 && (!entry->ipv4nat || olsr_cnf->smart_gw_allow_nat)) {
+    if (ipv4 && entry != current_ipv4_gw && entry->ipv4
+        && (!entry->ipv4nat || olsr_cnf->smart_gw_allow_nat)) {
       /* valid ipv4 gateway */
       current_ipv4_gw = entry;
-      ipv4 = false;
     }
-    if (ipv6 && entry->ipv6) {
+    if (ipv6 && entry != current_ipv6_gw && entry->ipv6) {
       /* valid ipv6 gateway */
       current_ipv6_gw = entry;
-      ipv6 = false;
     }
   }
 
-  /* still gateway missing ? */
-  if (ipv4 || ipv6) {
-    return external ? olsr_trigger_inetgw_selection(ipv4, ipv6) : -1;
+  /* gateway missing ? */
+  if ((current_ipv4_gw != NULL || current_ipv6_gw != NULL)  && external) {
+    /* trigger automatic lookup if user failed */
+    olsr_trigger_inetgw_selection(ipv4, ipv6);
   }
-  return 0;
+
+  /* handle IPv4 */
+  if (oldV4 != current_ipv4_gw) {
+    if (oldV4 == NULL) {
+      olsr_os_add_ipip_tunnel(v4gw_tunnel, &current_ipv4_gw->originator, true);
+      olsr_if_set_state(v4gw_tunnel, true);
+
+      v4gw_index = if_nametoindex(v4gw_tunnel);
+      fprintf(stderr, "add tunnel: %s %d\n", v4gw_tunnel, v4gw_index);
+      olsr_os_inetgw_tunnel_route(v4gw_index, true, true);
+    }
+    else {
+      olsr_os_change_ipip_tunnel(v4gw_tunnel, &current_ipv4_gw->originator, true);
+      v4gw_index = if_nametoindex(v4gw_tunnel);
+    }
+  }
+  /* handle IPv6 */
+  if (oldV6 != current_ipv6_gw) {
+    if (oldV6 == NULL) {
+      olsr_os_add_ipip_tunnel(v6gw_tunnel, &current_ipv6_gw->originator, false);
+      olsr_if_set_state(v6gw_tunnel, true);
+
+      v6gw_index = if_nametoindex(v6gw_tunnel);
+      olsr_os_inetgw_tunnel_route(v4gw_index, false, true);
+    }
+    else {
+      olsr_os_change_ipip_tunnel(v6gw_tunnel, &current_ipv6_gw->originator, false);
+      v6gw_index = if_nametoindex(v6gw_tunnel);
+    }
+  }
+  return (ipv4 && current_ipv4_gw == NULL) || (ipv6 && current_ipv6_gw == NULL);
 }
 
 /**
@@ -215,7 +269,7 @@ olsr_find_gateway_entry(union olsr_ip_addr *originator) {
  * @param prefixlen of the HNA
  */
 void
-olsr_update_gateway_entry(union olsr_ip_addr *originator, union olsr_ip_addr *mask, int prefixlen) {
+olsr_update_gateway_entry(union olsr_ip_addr *originator, union olsr_ip_addr *mask, int prefixlen, uint16_t seqno) {
   struct gateway_entry *gw;
   uint8_t *ptr;
 
@@ -223,6 +277,7 @@ olsr_update_gateway_entry(union olsr_ip_addr *originator, union olsr_ip_addr *ma
 
   gw = olsr_find_gateway_entry(originator);
   if (!gw) {
+    struct ipaddr_str buf;
     gw = olsr_cookie_malloc(gw_mem_cookie);
 
     gw->originator = *originator;
@@ -230,6 +285,13 @@ olsr_update_gateway_entry(union olsr_ip_addr *originator, union olsr_ip_addr *ma
 
     avl_insert(&gateway_tree, &gw->node, AVL_DUP_NO);
   }
+  else if (olsr_seqno_diff(seqno, gw->seqno) <= 0) {
+    /* ignore older HNAs */
+    return;
+  }
+
+  /* keep new HNA seqno */
+  gw->seqno = seqno;
 
   if ((ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_LINKSPEED) != 0) {
     gw->uplink = deserialize_gw_speed(ptr[GW_HNA_UPLINK]);
@@ -259,9 +321,27 @@ olsr_update_gateway_entry(union olsr_ip_addr *originator, union olsr_ip_addr *ma
     }
   }
 
+  /* stop cleanup timer if necessary */
+  if (gw->cleanup_timer) {
+    olsr_stop_timer(gw->cleanup_timer);
+    gw->cleanup_timer = NULL;
+  }
+
+  /* call update handler */
   gw_handler->handle_update_gw(gw);
 }
 
+static void cleanup_gateway_handler(void *ptr) {
+  struct gateway_entry *gw = ptr;
+
+  if (gw->ipv4 || gw->ipv6) {
+    return;
+  }
+
+  /* remove gateway entry */
+  avl_delete(&gateway_tree, &gw->node);
+  olsr_cookie_free(gw_mem_cookie, gw);
+}
 /**
  * Delete a gateway based on the originator IP and the prefixlength of a HNA.
  * Should only be called if prefix is a smart_gw prefix or if node is removed
@@ -273,43 +353,49 @@ void
 olsr_delete_gateway_entry(union olsr_ip_addr *originator, uint8_t prefixlen) {
   struct gateway_entry *gw;
   bool change = false;
-
   gw = olsr_find_gateway_entry(originator);
-  if (gw) {
+  if (gw && (gw->cleanup_timer == NULL || gw->ipv4 || gw->ipv6)) {
     if (olsr_cnf->ip_version == AF_INET && prefixlen == 0) {
+      change = gw->ipv4;
       gw->ipv4 = false;
       gw->ipv4nat = false;
-      change = true;
     }
-    if (olsr_cnf->ip_version == AF_INET6 && prefixlen == ipv6_internet_route.prefix_len) {
+    else if (olsr_cnf->ip_version == AF_INET6 && prefixlen == ipv6_internet_route.prefix_len) {
+      change = gw->ipv6;
       gw->ipv6 = false;
-      change = true;
     }
-    if (olsr_cnf->ip_version == AF_INET6 && prefixlen == mapped_v4_gw.prefix_len) {
+    else if (olsr_cnf->ip_version == AF_INET6 && prefixlen == ipv6_mappedv4_route.prefix_len) {
+      change = gw->ipv4;
       gw->ipv4 = false;
       gw->ipv4nat = false;
-      change = true;
     }
 
     if (prefixlen == FORCE_DELETE_GW_ENTRY || !(gw->ipv4 || gw->ipv6)) {
       /* prevent this gateway from being choosen as the new gateway */
       gw->ipv4 = false;
+      gw->ipv4nat = false;
       gw->ipv6 = false;
 
       /* handle gateway loss */
       gw_handler->handle_delete_gw(gw);
-
-      /* cleanup gateway pointer if necessary */
+      /* cleanup gateway if necessary */
       if (current_ipv4_gw == gw) {
+        olsr_os_inetgw_tunnel_route(v4gw_index, true, false);
+        olsr_if_set_state(v4gw_tunnel, false);
+        olsr_os_del_ipip_tunnel(v4gw_tunnel, true);
         current_ipv4_gw = NULL;
+        v4gw_index = 0;
       }
       if (current_ipv6_gw == gw) {
+        olsr_os_inetgw_tunnel_route(v6gw_index, false, false);
+        olsr_if_set_state(v6gw_tunnel, false);
+        olsr_os_del_ipip_tunnel(v6gw_tunnel, false);
         current_ipv6_gw = NULL;
+        v6gw_index = 0;
       }
 
       /* remove gateway entry */
-      avl_delete(&gateway_tree, &gw->node);
-      olsr_cookie_free(gw_mem_cookie, gw);
+      olsr_set_timer(&gw->cleanup_timer, GW_CLEANUP_INTERVAL, 0, false, cleanup_gateway_handler, gw, NULL);
     }
     else if (change) {
       gw_handler->handle_update_gw(gw);
index da2e2f8..c4cfda0 100644 (file)
 #include "common/list.h"
 #include "defs.h"
 #include "olsr.h"
+#include "scheduler.h"
 
 #define FORCE_DELETE_GW_ENTRY 255
+#define GW_CLEANUP_INTERVAL 30000
 
 /*
  * hack for Vienna network to remove 0.0.0.0/128.0.0.0 and 128.0.0.0/128.0.0.0 routes
@@ -45,6 +47,9 @@ struct gateway_entry {
   struct olsr_ip_prefix external_prefix;
   uint32_t uplink, downlink;
   bool ipv4, ipv4nat, ipv6;
+
+  struct timer_entry *cleanup_timer;
+  uint16_t seqno;
 };
 
 AVLNODE2STRUCT(node2gateway, struct gateway_entry, node);
@@ -66,11 +71,11 @@ void olsr_trigger_inetgw_startup(void);
 int olsr_trigger_inetgw_selection(bool ipv4, bool ipv6);
 
 struct gateway_entry *olsr_find_gateway_entry(union olsr_ip_addr *originator);
-void olsr_update_gateway_entry(union olsr_ip_addr *originator, union olsr_ip_addr *mask, int prefixlen);
+void olsr_update_gateway_entry(union olsr_ip_addr *originator, union olsr_ip_addr *mask, int prefixlen, uint16_t seqno);
 void olsr_delete_gateway_entry(union olsr_ip_addr *originator, uint8_t prefixlen);
 void olsr_print_gateway_entries(void);
 
-int olsr_set_inet_gateway(union olsr_ip_addr *originator, bool ipv4, bool ipv6, bool external);
+bool olsr_set_inet_gateway(union olsr_ip_addr *originator, bool ipv4, bool ipv6, bool external);
 struct gateway_entry *olsr_get_inet_gateway(bool ipv6);
 bool olsr_is_smart_gateway(struct olsr_ip_prefix *prefix, union olsr_ip_addr *net);
 void olsr_modifiy_inetgw_netmask(union olsr_ip_addr *mask, int prefixlen);
index a163b84..4b25e2e 100644 (file)
@@ -19,13 +19,13 @@ static bool gw_def_finished_ipv4, gw_def_finished_ipv6;
 static struct timer_entry *gw_def_timer;
 
 static void gw_default_startup_handler(void);
-void olsr_gw_default_lookup_gateway(bool ipv4, bool ipv6);
+static void gw_default_choosegw_handler(bool ipv4, bool ipv6);
 static void gw_default_update_handler(struct gateway_entry *);
 static void gw_default_delete_handler(struct gateway_entry *);
 
 static struct olsr_gw_handler gw_def_handler = {
   &gw_default_startup_handler,
-  &olsr_gw_default_lookup_gateway,
+  &gw_default_choosegw_handler,
   &gw_default_update_handler,
   &gw_default_delete_handler
 };
@@ -96,6 +96,11 @@ static void gw_default_timer(void *unused __attribute__ ((unused))) {
 
 /* gateway handler callbacks */
 static void gw_default_startup_handler(void) {
+  /* reset node count */
+  gw_def_nodecount = tc_tree.count;
+  gw_def_stablecount = 0;
+
+  /* and start looking for gateway */
   olsr_set_timer(&gw_def_timer, GW_DEFAULT_TIMER_INTERVAL, 0, true, &gw_default_timer, NULL, 0);
 }
 
@@ -120,6 +125,14 @@ static void gw_default_delete_handler(struct gateway_entry *gw) {
   }
 }
 
+static void gw_default_choosegw_handler(bool ipv4, bool ipv6) {
+  olsr_gw_default_lookup_gateway(ipv4, ipv6);
+
+  if (!(gw_def_finished_ipv4 && gw_def_finished_ipv6)) {
+    gw_default_startup_handler();
+  }
+}
+
 /**
  * initialization of default gateway handler
  */
index fdb0648..bca0ceb 100644 (file)
@@ -371,7 +371,7 @@ olsr_input_hna(union olsr_message *m, struct interface *in_if __attribute__ ((un
   uint16_t olsr_msgsize;
   union olsr_ip_addr originator;
   uint8_t hop_count;
-  uint16_t packet_seq_number;
+  uint16_t msg_seq_number;
 
   int hnasize;
   const uint8_t *curr, *curr_end;
@@ -421,7 +421,7 @@ olsr_input_hna(union olsr_message *m, struct interface *in_if __attribute__ ((un
   pkt_get_u8(&curr, &hop_count);
 
   /* seqno */
-  pkt_get_u16(&curr, &packet_seq_number);
+  pkt_get_u16(&curr, &msg_seq_number);
 
   if ((hnasize % (2 * olsr_cnf->ipsize)) != 0) {
     OLSR_PRINTF(1, "Illegal HNA message from %s with size %d!\n",
@@ -451,7 +451,7 @@ olsr_input_hna(union olsr_message *m, struct interface *in_if __attribute__ ((un
     prefix.prefix_len = olsr_netmask_to_prefix(&mask);
 
     if (olsr_cnf->smart_gw_active && olsr_is_smart_gateway(&prefix, &mask)) {
-      olsr_update_gateway_entry(&originator, &mask, prefix.prefix_len);
+      olsr_update_gateway_entry(&originator, &mask, prefix.prefix_len, msg_seq_number);
     }
 
 #ifdef MAXIMUM_GATEWAY_PREFIX_LENGTH
index e17fb50..51c398d 100644 (file)
 #include "defs.h"
 #include "ipcalc.h"
 
+/* ipv4 prefix 0.0.0.0/0 */
+const struct olsr_ip_prefix ipv4_internet_route =
+{
+    .prefix.v4.s_addr = 0,
+    .prefix_len = 0
+};
+
 /* ipv6 prefix ::ffff:0:0/96 */
-const struct olsr_ip_prefix mapped_v4_gw =
+const struct olsr_ip_prefix ipv6_mappedv4_route =
 {
     .prefix.v6.s6_addr = { 0,0,0,0,0,0,0,0,0,0,0xff,0xff,0,0,0,0 },
     .prefix_len = 96
index 97bd6c9..ea4660c 100644 (file)
@@ -49,7 +49,8 @@
 #include <arpa/inet.h>
 #include <netinet/in.h>
 
-extern const struct olsr_ip_prefix mapped_v4_gw;
+extern const struct olsr_ip_prefix ipv4_internet_route;
+extern const struct olsr_ip_prefix ipv6_mappedv4_route;
 extern const struct olsr_ip_prefix ipv6_internet_route;
 
 struct ipaddr_str {
@@ -172,7 +173,7 @@ prefix_to_netmask4(uint8_t prefixlen)
 static INLINE bool
 is_prefix_niit_ipv6(const struct olsr_ip_prefix *p) {
   return olsr_cnf->ip_version == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&p->prefix.v6)
-      && p->prefix_len >= mapped_v4_gw.prefix_len;
+      && p->prefix_len >= ipv6_mappedv4_route.prefix_len;
 }
 
 static INLINE struct olsr_ip_prefix *
@@ -185,19 +186,20 @@ prefix_mappedv4_to_v4(struct olsr_ip_prefix *v4, const struct olsr_ip_prefix *v6
 
 static INLINE bool
 ip_prefix_is_mappedv4(const struct olsr_ip_prefix *prefix) {
-  return prefix->prefix_len >= mapped_v4_gw.prefix_len
-      && memcmp(prefix, &mapped_v4_gw, mapped_v4_gw.prefix_len / 8) == 0;
+  return prefix->prefix_len >= ipv6_mappedv4_route.prefix_len
+      && memcmp(prefix, &ipv6_mappedv4_route, ipv6_mappedv4_route.prefix_len / 8) == 0;
 }
 
 static INLINE bool
 ip_prefix_is_mappedv4_inetgw(const struct olsr_ip_prefix *prefix) {
-  return olsr_cnf->ip_version == AF_INET6 && prefix->prefix_len == mapped_v4_gw.prefix_len
-      && memcmp(prefix, &mapped_v4_gw, mapped_v4_gw.prefix_len / 8) == 0;
+  return olsr_cnf->ip_version == AF_INET6 && prefix->prefix_len == ipv6_mappedv4_route.prefix_len
+      && memcmp(prefix, &ipv6_mappedv4_route, ipv6_mappedv4_route.prefix_len / 8) == 0;
 }
 
 static INLINE bool
 ip_prefix_is_v4_inetgw(const struct olsr_ip_prefix *prefix) {
-  return olsr_cnf->ip_version == AF_INET && prefix->prefix_len == 0 && prefix->prefix.v4.s_addr == 0;
+  return olsr_cnf->ip_version == AF_INET && prefix->prefix_len == ipv4_internet_route.prefix_len
+      && prefix->prefix.v4.s_addr == ipv4_internet_route.prefix.v4.s_addr;
 }
 
 static INLINE bool
index 39b329a..442cd8e 100644 (file)
@@ -58,13 +58,10 @@ int rtnetlink_register_socket(int);
 
 void olsr_os_niit_4to6_route(const struct olsr_ip_prefix *dst_v4, bool set);
 void olsr_os_niit_6to4_route(const struct olsr_ip_prefix *dst_v6, bool set);
+void olsr_os_inetgw_tunnel_route(uint32_t if_idx, bool ipv4, bool set);
 
 int olsr_os_policy_rule(int family, int rttable, uint32_t priority, const char *if_name, bool set);
 int olsr_os_create_localhostif(union olsr_ip_addr *ip, bool create);
-
-int olsr_del_tunl(void);
-
-
 #endif
 
 #endif
index e56f035..4fede8a 100644 (file)
@@ -354,7 +354,7 @@ static int olsr_new_netlink_route(int family, int rttable, int if_index, int met
   req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
   req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
   if (set) {
-    req.n.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
+    req.n.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
   }
 
   req.n.nlmsg_type = set ? RTM_NEWROUTE : RTM_DELROUTE;
@@ -439,19 +439,32 @@ void olsr_os_niit_6to4_route(const struct olsr_ip_prefix *dst_v6, bool set) {
 void olsr_os_niit_4to6_route(const struct olsr_ip_prefix *dst_v4, bool set) {
   /* TODO: in welche Table kommen die NIIT-Routen ? ne eigene ? */
   if (olsr_new_netlink_route(AF_INET, olsr_cnf->rttable, olsr_cnf->niit4to6_if_index,
-      RT_METRIC_DEFAULT, RTPROT_BOOT, NULL, NULL, dst_v4, set, false)) {
+      RT_METRIC_DEFAULT, olsr_cnf->rtproto, NULL, NULL, dst_v4, set, false)) {
     olsr_syslog(OLSR_LOG_ERR, ". error while %s niit route to %s",
         set ? "setting" : "removing", olsr_ip_prefix_to_string(dst_v4));
   }
 }
 
-static bool olsr_netlink_process_smartgw(const struct rt_entry *rt, bool set) {
-  if (!olsr_cnf->smart_gw_active || !is_prefix_inetgw(&rt->rt_dst)) {
-    return false;
+void olsr_os_inetgw_tunnel_route(uint32_t if_idx, bool ipv4, bool set) {
+  const struct olsr_ip_prefix *dst;
+
+  if (olsr_cnf->ip_version == AF_INET) {
+    assert(ipv4);
+
+    dst = &ipv4_internet_route;
+  }
+  else if (ipv4) {
+    dst = &ipv6_mappedv4_route;
+  }
+  else {
+    dst = &ipv6_internet_route;
   }
 
-  /* TODO maybe block internet gateway route */
-  return set && false;
+  if (olsr_new_netlink_route(ipv4 ? AF_INET : AF_INET6, olsr_cnf->rttable,
+      if_idx, RT_METRIC_DEFAULT, olsr_cnf->rtproto,NULL, NULL, dst, set, false)) {
+    olsr_syslog(OLSR_LOG_ERR, ". error while %s inetgw tunnel route to %s",
+        set ? "setting" : "removing", olsr_ip_prefix_to_string(dst));
+  }
 }
 
 static int olsr_os_process_rt_entry(int af_family, const struct rt_entry *rt, bool set) {
@@ -461,12 +474,6 @@ static int olsr_os_process_rt_entry(int af_family, const struct rt_entry *rt, bo
   bool hostRoute;
   int err;
 
-  /* handle smart gateway case */
-  if (olsr_netlink_process_smartgw(rt, set)) {
-    /* skip inetgw routes if smartgw is active */
-    return 0;
-  }
-
   /* calculate metric */
   if (FIBM_FLAT == olsr_cnf->fib_metric) {
     metric = RT_METRIC_DEFAULT;
index a391089..0a815c3 100644 (file)
@@ -69,6 +69,7 @@ int olsr_os_init_iptunnel(void) {
   const char *dev = olsr_cnf->ip_version == AF_INET ? DEV_IPV4_TUNNEL : DEV_IPV6_TUNNEL;
 
   store_iptunnel_state = olsr_if_isup(dev);
+fprintf(stderr, "device %s was %s\n", dev, store_iptunnel_state ? "up" : "down");
   if (store_iptunnel_state) {
     return 0;
   }
@@ -77,6 +78,7 @@ int olsr_os_init_iptunnel(void) {
 
 void olsr_os_cleanup_iptunnel(void) {
   if (!store_iptunnel_state) {
+fprintf(stderr, "ifdown: %s\n", olsr_cnf->ip_version == AF_INET ? DEV_IPV4_TUNNEL : DEV_IPV6_TUNNEL);
     olsr_if_set_state(olsr_cnf->ip_version == AF_INET ? DEV_IPV4_TUNNEL : DEV_IPV6_TUNNEL, false);
   }
 }
index 4661409..f65ee45 100644 (file)
@@ -520,7 +520,9 @@ int main(int argc, char *argv[]) {
  * all and device-specific settings are now combined differently
  * new max(all,device) old: all && device 
  * !!?? does this change only affect rp_filter or other aswell (e.g. icmp_redirect)*/
-deactivate_spoof("all", &olsr_cnf->ipip_base_if, AF_INET );
+
+  // TODO: cleanup ?
+  // deactivate_spoof("all", &olsr_cnf->ipip_base_if, AF_INET );
 #endif
 
 #ifdef LINUX_NETLINK_ROUTING
@@ -758,7 +760,7 @@ static void olsr_shutdown(int signo __attribute__ ((unused)))
 #ifdef LINUX_NETLINK_ROUTING
   /* trigger gateway selection */
   if (olsr_cnf->smart_gw_active) {
-    // TODO: cleanup smart gateway routes
+    olsr_cleanup_gateways();
   }
 
   /* trigger niit static route cleanup */
@@ -840,8 +842,8 @@ static void olsr_shutdown(int signo __attribute__ ((unused)))
   close(olsr_cnf->rtnl_s);
   close (olsr_cnf->rt_monitor_socket);
 
-  /*rp_filter*/
-  if (olsr_cnf->ipip_base_if.if_index) printf("\nresetting of tunl0 rp_filter not implemented");//!!?? no function extists to reset a single interface
+  /*TODO: cleanup ?rp_filter*/
+  // if (olsr_cnf->ipip_base_if.if_index) printf("\nresetting of tunl0 rp_filter not implemented");//!!?? no function extists to reset a single interface
 #endif
 
 /*!!?? we need to reset rp_filter of conf/all aswell, so we really need a new rp_filter reset function*/
index e118d02..3e9192e 100644 (file)
@@ -311,9 +311,6 @@ olsr_init_tables(void)
   /* Initialize HNA set */
   olsr_init_hna_set();
 
-  /* Initialize smart gateways */
-  olsr_init_gateways();
-
   /* Initialize duplicate handler */
 #ifndef NO_DUPLICATE_DETECTION_HANDLER
   olsr_duplicate_handler_init();
index cb16eb7..67a5d5e 100644 (file)
@@ -266,13 +266,6 @@ struct olsrd_config {
   /*many potential parameters or helper variables for smartgateway*/
   bool has_ipv4_gateway, has_ipv6_gateway;
 
-  struct interface ipip_base_if;
-  int ipip_if_index;
-  bool ipip_if_up;
-  bool ipip_base_orig_down;
-  unsigned long int ipip_remote_address;
-  const char *ipip_name;
-
   int ioctl_s;                         /* Socket used for ioctl calls */
 #ifdef LINUX_NETLINK_ROUTING
   int rtnl_s;                          /* Socket used for rtnetlink messages */
index 8535da5..e784923 100644 (file)
@@ -160,6 +160,10 @@ olsr_enqueue_rt(struct list_node *head_node, struct rt_entry *rt)
 static void
 olsr_delete_kernel_route(struct rt_entry *rt)
 {
+  if (olsr_cnf->smart_gw_active && is_prefix_inetgw(&rt->rt_dst)) {
+    /* skip default route in smartgateway mode */
+    return;
+  }
   if (!olsr_cnf->host_emul) {
     int16_t error = olsr_cnf->ip_version == AF_INET ? olsr_delroute_function(rt) : olsr_delroute6_function(rt);
 
@@ -187,6 +191,10 @@ olsr_delete_kernel_route(struct rt_entry *rt)
 static void
 olsr_add_kernel_route(struct rt_entry *rt)
 {
+  if (olsr_cnf->smart_gw_active && is_prefix_inetgw(&rt->rt_dst)) {
+    /* skip default route in smartgateway mode */
+    return;
+  }
 
   if (!olsr_cnf->host_emul) {
     int16_t error = (olsr_cnf->ip_version == AF_INET) ? olsr_addroute_function(rt) : olsr_addroute6_function(rt);