Cleanup of HNA gateway data
authorHenning Rogge <hrogge@googlemail.com>
Wed, 13 Jan 2010 20:52:42 +0000 (21:52 +0100)
committerHenning Rogge <hrogge@googlemail.com>
Wed, 13 Jan 2010 20:52:42 +0000 (21:52 +0100)
Add option for external prefix of gateway

src/cfgparser/oparse.y
src/cfgparser/oscan.lex
src/gateway.c
src/gateway.h
src/olsr_cfg.h

index 538049b..fb0d37a 100644 (file)
@@ -213,6 +213,7 @@ static int add_ipv6_addr(YYSTYPE ipaddr_arg, YYSTYPE prefixlen_arg)
 %token TOK_USE_NIIT
 %token TOK_SMART_GW
 %token TOK_SMART_GW_SPEED
+%token TOK_SMART_GW_PREFIX
 
 %token TOK_HOSTLABEL
 %token TOK_NETLABEL
@@ -1170,6 +1171,32 @@ ismart_gw_speed: TOK_SMART_GW_SPEED TOK_INTEGER TOK_INTEGER
 }
 ;
 
+ismart_gw_prefix: TOK_SMART_GW_PREFIX TOK_IPV6_ADDR TOK_INTEGER
+{
+  PARSER_DEBUG_PRINTF("Smart gateway prefix: %s %u\n", $2->string, $3->integer);
+       if (inet_pton(olsr_cnf->ip_version, $2->string, &olsr_cnf->smart_gateway_prefix.prefix) == 0) {
+         fprintf(stderr, "Bad IP part of gateway prefix: %s\n", $2->string);
+    YYABORT;
+  }
+       olsr_cnf->smart_gateway_prefix.prefixlen = (uint8_t)$3->integer;
+       
+       free($2);
+       free($3);
+}
+        |       TOK_SMART_GW_PREFIX TOK_IPV6_ADDR TOK_SLASH TOK_INTEGER
+{
+       PARSER_DEBUG_PRINTF("Smart gateway prefix: %s %u\n", $2->string, $4->integer);
+       if (inet_pton(olsr_cnf->ip_version, $2->string, &olsr_cnf->smart_gateway_prefix.prefix) == 0) {
+         fprintf(stderr, "Bad IP part of gateway prefix: %s\n", $2->string);
+    YYABORT;
+  }
+       olsr_cnf->smart_gateway_prefix.prefixlen = (uint8_t)$4->integer;
+       
+       free($2);
+       free($4);
+}
+;
+
 plblock: TOK_PLUGIN TOK_STRING
 {
   struct plugin_entry *pe, *last;
index 23f2695..6cf1784 100644 (file)
@@ -438,6 +438,11 @@ IPV6ADDR {IPV6PAT1}|{IPV6PAT2}|{IPV6PAT3}|{IPV6PAT4}|{IPV6PAT5}|{IPV6PAT6}|{IPV6
     return TOK_SMART_GW_SPEED;
 }
 
+"SmartGatewayPrefix" {
+    yylval = NULL;
+    return TOK_SMART_GW_PREFIX;
+}
+
 "UseNiit" {
     yylval = NULL;
     return TOK_USE_NIIT;
index 1320b36..b05a968 100644 (file)
@@ -21,7 +21,7 @@ union olsr_ip_addr smart_gateway_netmask;
 static uint32_t deserialize_gw_speed(uint8_t value) {
   uint32_t speed, exp;
 
-  speed = value >> 3;
+  speed = (value >> 3)+1;
   exp = value & 7;
   while (exp-- > 0) {
     speed *= 10;
@@ -32,7 +32,7 @@ static uint32_t deserialize_gw_speed(uint8_t value) {
 static uint8_t serialize_gw_speed(uint32_t speed) {
   uint8_t exp = 0;
 
-  if (speed == 0 || speed > 310000000) {
+  if (speed == 0 || speed > 320000000) {
     return 0;
   }
 
@@ -40,7 +40,7 @@ static uint8_t serialize_gw_speed(uint32_t speed) {
     speed /= 10;
     exp ++;
   }
-  return (speed << 3) | exp;
+  return ((speed-1) << 3) | exp;
 }
 
 void
@@ -68,8 +68,21 @@ olsr_init_gateways(void) {
     }
 
     ip = (uint8_t *) &smart_gateway_netmask;
-    ip[olsr_cnf->ipsize - 2] = serialize_gw_speed(olsr_cnf->smart_gateway_uplink);
-    ip[olsr_cnf->ipsize - 1] = serialize_gw_speed(olsr_cnf->smart_gateway_downlink);
+
+    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;
+      ip[GW_HNA_DOWNLINK] = serialize_gw_speed(olsr_cnf->smart_gateway_downlink);
+    }
+    if (olsr_cnf->ip_version == AF_INET6 && olsr_cnf->smart_gateway_prefix.prefix_len > 0) {
+      ip[GW_HNA_FLAGS] |= GW_HNA_FLAG_IPV6PREFIX;
+      ip[GW_HNA_V6PREFIXLEN] = olsr_cnf->smart_gateway_prefix.prefix_len;
+      memcpy(&ip[GW_HNA_V6PREFIX], &olsr_cnf->smart_gateway_prefix.prefix, 8);
+    }
   }
 }
 
@@ -96,8 +109,25 @@ olsr_set_gateway(union olsr_ip_addr *originator, union olsr_ip_addr *subnetmask)
   }
 
   ip = (uint8_t *)subnetmask;
-  gw->uplink = deserialize_gw_speed(ip[olsr_cnf->ipsize - 2]);
-  gw->downlink = deserialize_gw_speed(ip[olsr_cnf->ipsize - 1]);
+  if ((ip[GW_HNA_FLAGS] & GW_HNA_FLAG_UPLINK) != 0) {
+    gw->uplink = deserialize_gw_speed(ip[GW_HNA_UPLINK]);
+  }
+  else {
+    gw->uplink = 1;
+  }
+
+  if ((ip[GW_HNA_FLAGS] & GW_HNA_FLAG_DOWNLINK) != 0) {
+    gw->downlink = deserialize_gw_speed(ip[GW_HNA_DOWNLINK]);
+  }
+  else {
+    gw->downlink = 1;
+  }
+
+  memset(&gw->external_prefix, 0, sizeof(gw->external_prefix));
+  if ((ip[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV6PREFIX) != 0 && olsr_cnf->ip_version == AF_INET6) {
+    gw->external_prefix.prefix_len = ip[GW_HNA_V6PREFIXLEN];
+    memcpy(&gw->external_prefix.prefix, &ip[GW_HNA_V6PREFIX], 8);
+  }
 }
 
 void
@@ -113,24 +143,14 @@ olsr_delete_gateway(union olsr_ip_addr *originator) {
 }
 
 bool olsr_is_smart_gateway(union olsr_ip_addr *net, union olsr_ip_addr *mask) {
-  uint8_t i;
   uint8_t *ip;
 
-  ip = (uint8_t *)net;
-  for (i=0; i<olsr_cnf->ipsize; i++) {
-    if (*ip++) {
-      return false;
-    }
+  if (memcmp(&in6addr_any, net, olsr_cnf->ipsize) != 0) {
+    return false;
   }
 
   ip = (uint8_t *)mask;
-  for (i=0; i<olsr_cnf->ipsize-2; i++) {
-    if (*ip++ != 0) {
-      return false;
-    }
-  }
-
-  return ip[0] > 0 && ip[1] > 0;
+  return ip[0] == 0 && ip[1] != 0;
 }
 
 void
@@ -140,11 +160,14 @@ olsr_print_gateway(void) {
   struct gateway_entry *gw;
   const int addrsize = olsr_cnf->ip_version == AF_INET ? 15 : 39;
 
-  OLSR_PRINTF(0, "\n--- %s ---------------------------------------------------- GATEWAYS\n\n", olsr_wallclock_string());
-  OLSR_PRINTF(0, "%-*s  %-9s %-9s\n", addrsize, "IP address", "Uplink", "Downlink");
+  OLSR_PRINTF(0, "\n--- %s ---------------------------------------------------- GATEWAYS\n\n",
+      olsr_wallclock_string());
+  OLSR_PRINTF(0, "%-*s  %-9s %-9s %s\n", addrsize, "IP address", "Uplink", "Downlink",
+      olsr_cnf->ip_version == AF_INET ? "" : "External Prefix");
 
   OLSR_FOR_ALL_GATEWAY_ENTRIES(gw) {
-    OLSR_PRINTF(0, "%-*s  %-9u %-9u\n", addrsize, olsr_ip_to_string(&buf, &gw->originator), gw->uplink, gw->downlink);
+    OLSR_PRINTF(0, "%-*s  %-9u %-9u %s\n", addrsize, olsr_ip_to_string(&buf, &gw->originator),
+        gw->uplink, gw->downlink, gw->external_prefix.prefix_len == 0 ? "" : olsr_ip_prefix_to_string(&gw->external_prefix));
   } OLSR_FOR_ALL_GATEWAY_ENTRIES_END(gw)
 #endif
 }
index 1a27b6f..9950ce4 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_IPV6PREFIX = 1<<3
+};
+
+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
+};
+
 struct gateway_entry {
   struct avl_node node;
   union olsr_ip_addr originator;
+  struct olsr_ip_prefix external_prefix;
   uint32_t uplink;
   uint32_t downlink;
 };
index 58cb7b4..aa77784 100644 (file)
@@ -256,6 +256,8 @@ struct olsrd_config {
   bool smart_gateway_active;
   uint32_t smart_gateway_uplink;
   uint32_t smart_gateway_downlink;
+  struct olsr_ip_prefix smart_gateway_prefix;
+
   struct interface ipip_base_if;
   int ipip_if_index;
   bool ipip_if_up;