More fixes for tunnel announcement (ipv6 inet-gw hna is 2000::/3, not ::/0)
authorHenning Rogge <hrogge@googlemail.com>
Sun, 17 Jan 2010 17:30:11 +0000 (18:30 +0100)
committerHenning Rogge <hrogge@googlemail.com>
Sun, 17 Jan 2010 17:30:11 +0000 (18:30 +0100)
src/gateway.c
src/gateway.h
src/ipcalc.c
src/ipcalc.h
src/olsr_cfg.h

index 2f3b929..445e22b 100644 (file)
@@ -69,14 +69,10 @@ olsr_init_gateways(void) {
 
     ip = (uint8_t *) &smart_gateway_netmask;
 
-    ip[GW_HNA_FLAGS] |= GW_HNA_FLAG_SMART;
-    if (olsr_cnf->smart_gateway_uplink > 0) {
-      ip[GW_HNA_FLAGS] |= GW_HNA_FLAG_UPLINK;
-      ip[GW_HNA_UPLINK] = serialize_gw_speed(olsr_cnf->smart_gateway_uplink);
-    }
-    if (olsr_cnf->smart_gateway_downlink > 0) {
-      ip[GW_HNA_FLAGS] |= GW_HNA_FLAG_DOWNLINK;
+    if (olsr_cnf->smart_gateway_uplink > 0 || olsr_cnf->smart_gateway_downlink > 0) {
+      ip[GW_HNA_FLAGS] |= GW_HNA_FLAG_LINKSPEED;
       ip[GW_HNA_DOWNLINK] = serialize_gw_speed(olsr_cnf->smart_gateway_downlink);
+      ip[GW_HNA_UPLINK] = serialize_gw_speed(olsr_cnf->smart_gateway_uplink);
     }
     if (olsr_cnf->ip_version == AF_INET6 && olsr_cnf->smart_gateway_prefix.prefix_len > 0) {
       ip[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV6PREFIX;
@@ -96,7 +92,7 @@ olsr_find_gateway(union olsr_ip_addr *originator) {
 void
 olsr_set_gateway(union olsr_ip_addr *originator, union olsr_ip_addr *mask, int prefixlen) {
   struct gateway_entry *gw;
-  uint8_t *ptr = ((uint8_t *)mask) + (prefixlen/8);
+  uint8_t *ptr = ((uint8_t *)mask) + ((prefixlen+7)/8);
 
   gw = olsr_find_gateway(originator);
   if (!gw) {
@@ -108,27 +104,29 @@ olsr_set_gateway(union olsr_ip_addr *originator, union olsr_ip_addr *mask, int p
     avl_insert(&gateway_tree, &gw->node, AVL_DUP_NO);
   }
 
-  if ((ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_UPLINK) != 0) {
+  if ((ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_LINKSPEED) != 0) {
     gw->uplink = deserialize_gw_speed(ptr[GW_HNA_UPLINK]);
-  }
-  else {
-    gw->uplink = 1;
-  }
-
-  if ((ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_DOWNLINK) != 0) {
     gw->downlink = deserialize_gw_speed(ptr[GW_HNA_DOWNLINK]);
   }
   else {
+    gw->uplink = 1;
     gw->downlink = 1;
   }
 
-  gw->ipv6 = (ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV6) != 0;
+  gw->ipv4 = (ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV4) != 0;
+  gw->ipv4nat = (ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV4_NAT) != 0;
 
-  memset(&gw->external_prefix, 0, sizeof(gw->external_prefix));
-  if (olsr_cnf->ip_version == AF_INET6 && prefixlen == 0
+  if (olsr_cnf->ip_version == AF_INET) {
+    gw->ipv6 = (ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV6) != 0;
+    if (prefixlen == IPV6_INET_GW_PREFIX_LEN) {
+      /* do not reset prefixlength for ::ffff:0:0 HNAs */
+      memset(&gw->external_prefix, 0, sizeof(gw->external_prefix));
+    }
+    if (prefixlen == IPV6_INET_GW_PREFIX_LEN && mask->v6.s6_addr[0] == IPV6_INET_GW_PREFIX
       && (ptr[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV6PREFIX) != 0) {
-    gw->external_prefix.prefix_len = ptr[GW_HNA_V6PREFIXLEN];
-    memcpy(&gw->external_prefix.prefix, &ptr[GW_HNA_V6PREFIX], 8);
+      gw->external_prefix.prefix_len = ptr[GW_HNA_V6PREFIXLEN];
+      memcpy(&gw->external_prefix.prefix, &ptr[GW_HNA_V6PREFIX], 8);
+    }
   }
 }
 
@@ -145,13 +143,13 @@ olsr_delete_gateway(union olsr_ip_addr *originator) {
 }
 
 bool olsr_is_smart_gateway(union olsr_ip_addr *net, union olsr_ip_addr *mask, int prefixlen) {
-  uint8_t *ptr = ((uint8_t *)mask) + (prefixlen/8);
+  uint8_t *ptr = ((uint8_t *)mask) + ((prefixlen+7)/8);
   struct ipaddr_str buf;
 
   fprintf(stderr, "olsr_is_smart_gw: %s\n", olsr_ip_to_string(&buf, mask));
 
-  if (prefixlen == 0) {
-    if (memcmp(&in6addr_any, net, olsr_cnf->ipsize) != 0) {
+  if (olsr_cnf->ip_version == AF_INET6 && prefixlen == IPV6_INET_GW_PREFIX_LEN) {
+    if (memcmp(&ipv6_internet_route, net, olsr_cnf->ipsize) != 0) {
       return false;
     }
   }
@@ -160,24 +158,32 @@ bool olsr_is_smart_gateway(union olsr_ip_addr *net, union olsr_ip_addr *mask, in
       return false;
     }
   }
+  else if (prefixlen == 0) {
+    if (memcmp(&in6addr_any, net, olsr_cnf->ipsize) != 0) {
+      return false;
+    }
+  }
   else {
     return false;
   }
-
   return ptr[GW_HNA_PAD] == 0 && ptr[GW_HNA_FLAGS] != 0;
 }
 
 void olsr_modifiy_inetgw_netmask(union olsr_ip_addr *mask, int prefixlen) {
-  uint8_t *ptr = ((uint8_t *)mask) + (prefixlen/8);
+  uint8_t *ptr = ((uint8_t *)mask) + ((prefixlen+7)/8);
 
+  memcpy(ptr, &smart_gateway_netmask, sizeof(smart_gateway_netmask) - prefixlen/8);
   if (olsr_cnf->has_ipv4_gateway) {
-    struct ipaddr_str buf;
-    memcpy(ptr, &smart_gateway_netmask, sizeof(smart_gateway_netmask) - prefixlen/8);
+    ptr[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV4;
+
+    if (olsr_cnf->has_ipv4_nat) {
+      ptr[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV4_NAT;
+    }
   }
   if (olsr_cnf->has_ipv6_gateway) {
     ptr[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV6;
   }
-  else {
+  if (!olsr_cnf->has_ipv6_gateway || prefixlen > 0){
     ptr[GW_HNA_FLAGS] &= ~GW_HNA_FLAG_IPV6PREFIX;
   }
 }
index 037eb22..7e56876 100644 (file)
 #define MAXIMUM_GATEWAY_PREFIX_LENGTH 0
 
 enum gateway_hna_flags {
-  GW_HNA_FLAG_SMART      = 1<<0,
-  GW_HNA_FLAG_UPLINK     = 1<<1,
-  GW_HNA_FLAG_DOWNLINK   = 1<<2,
+  GW_HNA_FLAG_LINKSPEED  = 1<<0,
+  GW_HNA_FLAG_IPV4       = 1<<1,
+  GW_HNA_FLAG_IPV4_NAT   = 1<<2,
   GW_HNA_FLAG_IPV6       = 1<<3,
   GW_HNA_FLAG_IPV6PREFIX = 1<<4
 };
 
-/* relative to the first zero byte in the netmask (0 or 12) */
+/* relative to the first zero byte in the netmask (0, 1 or 12) */
 enum gateway_hna_fields {
   GW_HNA_PAD         = 0,
   GW_HNA_FLAGS       = 1,
   GW_HNA_UPLINK      = 2,
   GW_HNA_DOWNLINK    = 3,
   GW_HNA_V6PREFIXLEN = 4,
-  GW_HNA_V6PREFIX    = 8
+  GW_HNA_V6PREFIX    = 5
 };
 
 struct gateway_entry {
   struct avl_node node;
   union olsr_ip_addr originator;
   struct olsr_ip_prefix external_prefix;
-  uint32_t uplink;
-  uint32_t downlink;
-  bool ipv6;
+  uint32_t last_heared;
+  uint32_t uplink, downlink;
+  bool ipv4, ipv4nat, ipv6;
 };
 
 AVLNODE2STRUCT(node2gateway, struct gateway_entry, node);
index f94b6b9..274b5c3 100644 (file)
@@ -43,6 +43,7 @@
 #include "ipcalc.h"
 
 const uint8_t mapped_v4_gw[] = { 0,0,0,0,0,0,0,0,0,0,0xff,0xff,0,0,0,0};
+const uint8_t ipv6_internet_route[] = { 0x20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
 
 int
 prefix_to_netmask(uint8_t * a, int len, uint8_t prefixlen)
index a8769d4..1a579ac 100644 (file)
 #include <arpa/inet.h>
 #include <netinet/in.h>
 
+#define IPV6_INET_GW_PREFIX     0x20
+#define IPV6_INET_GW_PREFIX_LEN 3
+
+extern const uint8_t mapped_v4_gw[];
+extern const uint8_t ipv6_internet_route[];
+
 struct ipaddr_str {
   char buf[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)];
 } __attribute__ ((unused));
 
-extern const uint8_t mapped_v4_gw[];
-
 /*
  * Macros for comparing and copying IP addresses
  */
index f289975..4e2f2e5 100644 (file)
@@ -253,7 +253,7 @@ struct olsrd_config {
   int niit_if_index;
 
   /*many potential parameters or helper variables for smartgateway*/
-  bool has_ipv4_gateway, has_ipv6_gateway;
+  bool has_ipv4_gateway, has_ipv6_gateway, has_ipv4_nat;
   bool smart_gateway_active;
   uint32_t smart_gateway_uplink;
   uint32_t smart_gateway_downlink;