Add OLSR support for NIIT (IP 4to6 tunnel device)
authorHenning Rogge <hrogge@googlemail.com>
Wed, 13 Jan 2010 15:36:48 +0000 (16:36 +0100)
committerHenning Rogge <hrogge@googlemail.com>
Wed, 13 Jan 2010 15:36:48 +0000 (16:36 +0100)
src/cfgparser/olsrd_conf.c
src/cfgparser/oparse.y
src/cfgparser/oscan.lex
src/ipcalc.h
src/linux/kernel_routes.c
src/linux/net.c
src/main.c
src/net_os.h
src/olsr_cfg.h

index c40aa9c..88dfa79 100644 (file)
@@ -556,6 +556,9 @@ set_default_cnf(struct olsrd_config *cnf)
   cnf->exit_value = EXIT_SUCCESS;
   cnf->max_tc_vtime = 0.0;
   cnf->ioctl_s = 0;
+  cnf->use_niit = DEF_USE_NIIT;
+  cnf->niit_if_index = 0;
+
 #if LINUX_POLICY_ROUTING
   cnf->rtnl_s = 0;
 #endif
@@ -661,6 +664,8 @@ olsrd_print_cnf(struct olsrd_config *cnf)
 
   printf("Clear screen     : %s\n", cnf->clear_screen ? "yes" : "no");
 
+  printf("Use niit:        : %s\n", cnf->use_niit ? "yes" : "no");
+
   /* Interfaces */
   if (in) {
     /*print interface default config*/
index ff584df..4c81bd3 100644 (file)
@@ -212,6 +212,7 @@ static int add_ipv6_addr(YYSTYPE ipaddr_arg, YYSTYPE prefixlen_arg)
 %token TOK_PLPARAM
 %token TOK_MIN_TC_VTIME
 %token TOK_LOCK_FILE
+%token TOK_USE_NIIT
 
 %token TOK_HOSTLABEL
 %token TOK_NETLABEL
@@ -276,6 +277,7 @@ stmt:       idebug
           | vcomment
           | amin_tc_vtime
           | alock_file
+          | suse_niit
 ;
 
 block:      TOK_HNA4 hna4body
@@ -1117,12 +1119,21 @@ anat_thresh: TOK_LQ_NAT_THRESH TOK_FLOAT
 
 bclear_screen: TOK_CLEAR_SCREEN TOK_BOOLEAN
 {
-  PARSER_DEBUG_PRINTF("Clear screen %s\n", olsr_cnf->clear_screen ? "enabled" : "disabled");
+  PARSER_DEBUG_PRINTF("Clear screen %s\n", $2->boolean ? "enabled" : "disabled");
   olsr_cnf->clear_screen = $2->boolean;
   free($2);
 }
 ;
 
+suse_niit: TOK_USE_NIIT TOK_BOOLEAN
+{
+  PARSER_DEBUG_PRINTF("Use NIIT ip translation: %s\n", $2->boolean ? "enabled" : "disabled");
+  olsr_cnf->use_niit = $2->boolean;
+  free($2);
+}
+;
+
+
 plblock: TOK_PLUGIN TOK_STRING
 {
   struct plugin_entry *pe, *last;
index 75a68e0..8bfb4b2 100644 (file)
@@ -428,6 +428,11 @@ IPV6ADDR {IPV6PAT1}|{IPV6PAT2}|{IPV6PAT3}|{IPV6PAT4}|{IPV6PAT5}|{IPV6PAT6}|{IPV6
     return TOK_CLEAR_SCREEN;
 }
 
+"UseNiit" {
+    yylval = NULL;
+    return TOK_USE_NIIT;
+}
+
 "Weight" {
     yylval = NULL;
     return TOK_IFWEIGHT;
index a5f8750..dde66f0 100644 (file)
@@ -166,6 +166,17 @@ prefix_to_netmask4(uint8_t prefixlen)
   return prefixlen == 0 ? 0 : (~0U << (32 - prefixlen));
 }
 
+static INLINE bool
+olsr_is_niit_ip(const union olsr_ip_addr *ip) {
+  return olsr_cnf->ip_version == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&ip->v6);
+}
+
+static INLINE union olsr_ip_addr *
+olsr_ipv6_to_ipv4(const union olsr_ip_addr *ipv6, union olsr_ip_addr *ipv4) {
+  memcpy(&ipv4->v4, &ipv6->v6.s6_addr[12], sizeof(ipv4->v4));
+  return ipv4;
+}
+
 #endif
 
 /*
index a244887..63bc12b 100644 (file)
@@ -52,6 +52,7 @@
 #define RT_DELETE_SIMILAR_ROUTE 3
 #define RT_AUTO_ADD_GATEWAY_ROUTE 4
 #define RT_DELETE_SIMILAR_AUTO_ROUTE 5
+#define RT_NIIT 6
 
 #if !LINUX_POLICY_ROUTING
 
@@ -233,7 +234,20 @@ olsr_netlink_route_int(const struct rt_entry *rt, uint8_t family, uint8_t rttabl
   req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
   req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK;
   req.n.nlmsg_type = cmd;
-  req.r.rtm_family = family;
+  
+  /*sanity check for niit ipv4 over ipv6 routes*/
+  if (family == AF_INET && flag == RT_NIIT) {
+    olsr_syslog(OLSR_LOG_ERR,"niit makes no sense with olsrd running on ipv4!");
+    return -1;
+  }
+
+  if (flag == RT_NIIT) {
+    req.r.rtm_family=AF_INET; /*we create an ipv4 niit route*/
+  }
+  else {
+    req.r.rtm_family = family;
+  }
+
   req.r.rtm_table = rttable;
 
   /* RTN_UNSPEC would be the wildcard, but blackhole broadcast or nat roules should usually not conflict */
@@ -246,7 +260,14 @@ olsr_netlink_route_int(const struct rt_entry *rt, uint8_t family, uint8_t rttabl
   /* as wildcard for deletion */
   req.r.rtm_scope = RT_SCOPE_NOWHERE;
 
-  if ( ( cmd != RTM_NEWRULE ) && ( cmd != RTM_DELRULE ) ) {
+  if ( ( cmd == RTM_NEWRULE ) || ( cmd == RTM_DELRULE ) ) {
+    /* add or delete a rule */
+    static uint32_t priority = 65535;
+
+    req.r.rtm_scope = RT_SCOPE_UNIVERSE;
+    olsr_netlink_addreq(&req, RTA_PRIORITY, &priority, sizeof(priority));
+  }
+  else {
     req.r.rtm_dst_len = rt->rt_dst.prefix_len;
 
     /* do not specify much as we wanna delete similar/conflicting routes */
@@ -258,15 +279,25 @@ olsr_netlink_route_int(const struct rt_entry *rt, uint8_t family, uint8_t rttabl
       req.r.rtm_scope = RT_SCOPE_LINK;
 
       /*add interface*/
-      olsr_netlink_addreq(&req, RTA_OIF, &nexthop->iif_index, sizeof(nexthop->iif_index));
-
-#if SOURCE_IP_ROUTES
-      /* source ip here is based on now static olsr_cnf->main_addr in this olsr-0.5.6-r4, should be based on orignator-id in newer olsrds */
-      if (AF_INET == family) {
-        olsr_netlink_addreq(&req, RTA_PREFSRC, &olsr_cnf->main_addr.v4.s_addr, sizeof(olsr_cnf->main_addr.v4.s_addr));
+      if (flag == RT_NIIT) {
+        olsr_netlink_addreq(&req, RTA_OIF, &olsr_cnf->niit_if_index, sizeof(&olsr_cnf->niit_if_index));
       }
       else {
-        olsr_netlink_addreq(&req, RTA_PREFSRC, &olsr_cnf->main_addr.v6.s6_addr, sizeof(olsr_cnf->main_addr.v6.s6_addr));
+        olsr_netlink_addreq(&req, RTA_OIF, &nexthop->iif_index, sizeof(nexthop->iif_index));
+      }
+
+#if SOURCE_IP_ROUTES
+      /**
+       * source ip here is based on now static olsr_cnf->main_addr in this olsr-0.5.6-r4,
+       * should be based on orignator-id in newer olsrds
+       **/
+      if (flag != RT_NIIT) {
+        if (AF_INET == family) {
+          olsr_netlink_addreq(&req, RTA_PREFSRC, &olsr_cnf->main_addr.v4.s_addr, sizeof(olsr_cnf->main_addr.v4.s_addr));
+        }
+        else {
+          olsr_netlink_addreq(&req, RTA_PREFSRC, &olsr_cnf->main_addr.v6.s6_addr, sizeof(olsr_cnf->main_addr.v6.s6_addr));
+        }
       }
 #endif
     }
@@ -281,10 +312,12 @@ olsr_netlink_route_int(const struct rt_entry *rt, uint8_t family, uint8_t rttabl
       req.r.rtm_dst_len = olsr_cnf->maxplen;
     }
 
-    /* for ipv4 or ipv6 we add gateway if one is specified, 
-    * or leave gateway away if we want to delete similar routes aswell, 
-    * or even use the gateway as target if we add a auto-generated route, 
-    * or if delete-similar to make insertion of auto-generated route possible */
+    /**
+     * for ipv4 or ipv6 we add gateway if one is specified,
+     * or leave gateway away if we want to delete similar routes aswell,
+     * or even use the gateway as target if we add a auto-generated route,
+     * or if delete-similar to make insertion of auto-generated route possible
+     **/
     if (AF_INET == family) {
       if ( ( flag != RT_AUTO_ADD_GATEWAY_ROUTE ) && (flag != RT_DELETE_SIMILAR_ROUTE) && 
            ( flag != RT_DELETE_SIMILAR_AUTO_ROUTE) && (rt->rt_dst.prefix.v4.s_addr != nexthop->gateway.v4.s_addr) ) {
@@ -294,20 +327,25 @@ olsr_netlink_route_int(const struct rt_entry *rt, uint8_t family, uint8_t rttabl
       olsr_netlink_addreq(&req, RTA_DST, ( (flag == RT_AUTO_ADD_GATEWAY_ROUTE) || (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) ) ? 
                           &nexthop->gateway.v4 : &rt->rt_dst.prefix.v4, sizeof(rt->rt_dst.prefix.v4));
     } else {
-      if ( ( flag != RT_AUTO_ADD_GATEWAY_ROUTE ) && (flag != RT_DELETE_SIMILAR_ROUTE ) && ( flag != RT_DELETE_SIMILAR_AUTO_ROUTE) 
-          && (0 != memcmp(&rt->rt_dst.prefix.v6, &nexthop->gateway.v6, sizeof(nexthop->gateway.v6))) ) {
-        olsr_netlink_addreq(&req, RTA_GATEWAY, &nexthop->gateway.v6, sizeof(nexthop->gateway.v6));
-        req.r.rtm_scope = RT_SCOPE_UNIVERSE;
+      if (flag == RT_NIIT) {
+        union olsr_ip_addr ipv4_addr;
+        /* create an ipv4 route */
+        olsr_syslog(OLSR_LOG_ERR,"niit suport not fully implemented!!"); 
+
+        /* fix prefix length */
+        req.r.rtm_dst_len = rt->rt_dst.prefix_len - 96;
+        olsr_netlink_addreq(&req, RTA_DST, olsr_ipv6_to_ipv4(&rt->rt_dst.prefix, &ipv4_addr), sizeof(ipv4_addr.v4));
+      }
+      else {
+        if ( ( flag != RT_AUTO_ADD_GATEWAY_ROUTE ) && (flag != RT_DELETE_SIMILAR_ROUTE ) && ( flag != RT_DELETE_SIMILAR_AUTO_ROUTE) 
+            && (0 != memcmp(&rt->rt_dst.prefix.v6, &nexthop->gateway.v6, sizeof(nexthop->gateway.v6))) ) {
+          olsr_netlink_addreq(&req, RTA_GATEWAY, &nexthop->gateway.v6, sizeof(nexthop->gateway.v6));
+          req.r.rtm_scope = RT_SCOPE_UNIVERSE;
+        }
+        olsr_netlink_addreq(&req, RTA_DST, ( (flag == RT_AUTO_ADD_GATEWAY_ROUTE) || (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) ) ? 
+                            &nexthop->gateway.v6 : &rt->rt_dst.prefix.v6, sizeof(rt->rt_dst.prefix.v6));
       }
-      olsr_netlink_addreq(&req, RTA_DST, ( (flag == RT_AUTO_ADD_GATEWAY_ROUTE) || (flag == RT_DELETE_SIMILAR_AUTO_ROUTE) ) ? 
-                          &nexthop->gateway.v6 : &rt->rt_dst.prefix.v6, sizeof(rt->rt_dst.prefix.v6));
     }
-  } else {
-    /* add or delete a rule */
-    static uint32_t priority = 65535;
-
-    req.r.rtm_scope = RT_SCOPE_UNIVERSE;
-    olsr_netlink_addreq(&req, RTA_PRIORITY, &priority, sizeof(priority));
   }
 
   iov.iov_base = &req.n;
@@ -343,6 +381,9 @@ olsr_netlink_route_int(const struct rt_entry *rt, uint8_t family, uint8_t rttabl
               else if ( cmd == RTM_DELRULE ) {
                 olsr_syslog(OLSR_LOG_ERR,"Error '%s' (%d) on deleting empty policy rule aimed to activate rtTable %u!", err_msg, errno, rttable);
               }
+              else if ( flag == RT_NIIT ) {
+                olsr_syslog(OLSR_LOG_ERR,"Error '%s' (%d) on manipulating niit route of %s!", err_msg, errno, olsr_ip_to_string(&ibuf,&rt->rt_dst.prefix));
+              }
               else if ( flag <= RT_RETRY_AFTER_DELETE_SIMILAR ) {
                 if (rt->rt_dst.prefix.v4.s_addr!=nexthop->gateway.v4.s_addr) {
                   olsr_syslog(OLSR_LOG_ERR, "error '%s' (%d) %s route to %s/%d via %s dev %s",
@@ -509,6 +550,11 @@ olsr_netlink_rule(uint8_t family, uint8_t rttable, uint16_t cmd)
 static int
 olsr_netlink_route(const struct rt_entry *rt, uint8_t family, uint8_t rttable, __u16 cmd)
 {
+  /*create/delete niit route if we have an niit device*/
+  if ((olsr_cnf->niit_if_index!=0) && (family != AF_INET) && (olsr_is_niit_ip(&rt->rt_dst.prefix))) {
+    olsr_netlink_route_int(rt, family, rttable, cmd, RT_NIIT);
+  }
+
   return olsr_netlink_route_int(rt, family, rttable, cmd, RT_ORIG_REQUEST);
 }
 
index 40fb011..1931232 100644 (file)
@@ -821,6 +821,22 @@ calculate_if_metric(char *ifname)
 }
 #endif
 
+bool olsr_check_ifup(const char * dev)
+{
+  int r;
+  struct ifreq ifr;
+  memset(&ifr, 0, sizeof(ifr));
+  strncpy(ifr.ifr_name, dev, IFNAMSIZ);
+
+  r = ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr);
+  if (r < 0) {
+    perror("ioctl to check interface up/down");
+    return false;
+  }
+
+  return (ifr.ifr_flags & IFF_UP) != 0;
+}
+
 /*
  * Local Variables:
  * c-basic-offset: 2
index c2edd6b..a6873b5 100644 (file)
@@ -78,6 +78,8 @@ bool olsr_win32_end_flag = false;
 static void olsr_shutdown(int) __attribute__ ((noreturn));
 #endif
 
+#define DEF_NIIT_IFNAME         "niit4to6"
+
 /*
  * Local function prototypes
  */
@@ -162,6 +164,21 @@ static void olsr_create_lock_file(void) {
   return;
 }
 
+#ifdef linux
+static void handle_niit_config(void) {
+  int if_index;
+
+  if (olsr_cnf->ip_version == AF_INET || !olsr_cnf->use_niit) {
+    return;
+  }
+
+  if_index = if_nametoindex(DEF_NIIT_IFNAME);
+  if (if_index > 0 && olsr_check_ifup(DEF_NIIT_IFNAME)) {
+    olsr_cnf->niit_if_index = if_index;
+  }
+}
+#endif
+
 /**
  * loads a config file
  * @return <0 if load failed, 0 otherwise
@@ -374,6 +391,11 @@ int main(int argc, char *argv[]) {
   }
 #endif
 
+#if defined linux
+  /* initialize niit if index */
+  handle_niit_config();
+#endif
+
   /* Init empty TC timer */
   set_empty_tc_timer(GET_TIMESTAMP(0));
 
index 67f86ba..8b1fd9d 100644 (file)
@@ -89,6 +89,10 @@ bool is_if_link_up(char *);
 
 int join_mcast(struct interface *, int);
 
+#ifdef linux
+bool olsr_check_ifup(const char * dev);
+#endif
+
 #endif
 
 /*
index 9ac72a4..083af76 100644 (file)
@@ -86,6 +86,7 @@
 #define DEF_RTPROTO         0 /* 0 means OS-specific default */
 #define DEF_RTTABLE         254
 #define DEF_MIN_TC_VTIME    0.0
+#define DEF_USE_NIIT        true
 
 /* Bounds */
 
@@ -248,6 +249,9 @@ struct olsrd_config {
 
   char *lock_file;
 
+  bool use_niit;
+  int niit_if_index;
+
   int ioctl_s;                         /* Socket used for ioctl calls */
 #if LINUX_POLICY_ROUTING
   int rtnl_s;                          /* Socket used for rtnetlink messages */