Added kernel_tunnel.c for linux
authorHenning Rogge <hrogge@googlemail.com>
Mon, 8 Feb 2010 20:09:49 +0000 (21:09 +0100)
committerHenning Rogge <hrogge@googlemail.com>
Mon, 8 Feb 2010 20:09:49 +0000 (21:09 +0100)
src/kernel_routes.h
src/kernel_tunnel.h [new file with mode: 0644]
src/linux/kernel_routes_nl.c
src/linux/kernel_tunnel.c [new file with mode: 0644]
src/main.c

index 8e31ea9..39b329a 100644 (file)
@@ -54,8 +54,6 @@ int olsr_ioctl_del_route(const struct rt_entry *);
 int olsr_ioctl_del_route6(const struct rt_entry *);
 
 #ifdef LINUX_NETLINK_ROUTING
-static const char TUNL_BASE[IFNAMSIZ] = "tunl0";
-
 int rtnetlink_register_socket(int);
 
 void olsr_os_niit_4to6_route(const struct olsr_ip_prefix *dst_v4, bool set);
diff --git a/src/kernel_tunnel.h b/src/kernel_tunnel.h
new file mode 100644 (file)
index 0000000..68a468c
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * kernel_tunnel.h
+ *
+ *  Created on: 08.02.2010
+ *      Author: henning
+ */
+
+#ifndef KERNEL_TUNNEL_H_
+#define KERNEL_TUNNEL_H_
+
+#include "defs.h"
+#include "olsr_types.h"
+
+#ifdef linux
+int olsr_os_add_ipip_tunnel(const char *name, union olsr_ip_addr *target, bool transportV4);
+int olsr_os_change_ipip_tunnel(const char *name, union olsr_ip_addr *target, bool transportV4);
+int olsr_os_del_ipip_tunnel(const char *name, bool transportV4);
+#endif
+
+#endif /* KERNEL_TUNNEL_H_ */
index a83a5fa..38e8ef5 100644 (file)
@@ -119,42 +119,6 @@ static void netlink_process_link(struct nlmsghdr *h)
   struct interface *iface;
   struct olsr_if *oif;
 
-#if 0
-  /*monitor tunl0 and olsrtunl*/
-  if (olsr_cnf->smart_gw_active) {
-    if (ifi->ifi_index==olsr_cnf->ipip_if_index) {
-      printf("olsrtunl state change:\n");
-      if (ifi->ifi_flags&IFF_UP)
-      {
-        printf("is up now\n");
-        olsr_cnf->ipip_if_up=true;
-      }
-      else if (olsr_cnf->ipip_if_up) {
-        /*we try to delete the interface completely (only if it is down, and was up before)*/
-        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 = olsr_cnf->ipip_if_up = false;
-      }
-      else printf("interface is down, but was never up -> ignoring!\n");
-      return;
-    }
-    if (ifi->ifi_index==olsr_cnf->ipip_base_if.if_index) {
-      if (ifi->ifi_flags&IFF_UP) {
-        /*we try to take it up again (if its only down it might workout)*/
-        printf("tunl0 is down, we try to take it up again\n");
-        if (olsr_if_set_state("tunl0",true)) return; //!!?? todo: test if we can really know that its up now
-        /*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_gw_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;
-      }
-    }
-  }
-#endif
-
   iface = if_ifwithindex(ifi->ifi_index);
   oif = NULL;
   if (iface == NULL && (ifi->ifi_flags & IFF_UP) != 0) {
@@ -222,44 +186,6 @@ static void rtnetlink_read(int sock, void *data __attribute__ ((unused)), unsign
   }
 }
 
-/*create or change a ipip tunnel ipv4 only*/
-static int set_tunl(int cmd, unsigned long int ipv4)
-{
-  struct ifreq ifr;
-  int fd;
-  int err;
-  struct ip_tunnel_parm p;
-
-  p.iph.version = 4;
-  p.iph.ihl = 5;
-  p.iph.protocol=IPPROTO_IPIP; //IPPROTO_IPV6
-  p.iph.saddr=0x00000000;
-  p.iph.daddr=ipv4;
-
-  strncpy(p.name, olsr_cnf->ipip_name, IFNAMSIZ);
-printf("set tunl to name: %s\n",p.name);
-
-  //specify existing interface name
-  if (cmd==SIOCADDTUNNEL) strncpy(ifr.ifr_name, TUNL_BASE, IFNAMSIZ);
-  else strncpy(ifr.ifr_name, olsr_cnf->ipip_name, IFNAMSIZ);
-
-printf("set tunl %s\n",ifr.ifr_name);
-
-  ifr.ifr_ifru.ifru_data = (void *) &p;
-  fd = socket(AF_INET, SOCK_DGRAM, 0);//warning hardcoded AF_INET
-  err = ioctl(fd, cmd, &ifr);
-printf("set tunl result %i\n",err);
-  if (err) perror("ioctl");
-  close(fd);
-  return err;
-}
-
-int olsr_del_tunl(void)
-{
-  printf("-----\ndelete olsrtunle!\n");
-  return set_tunl(SIOCDELTUNNEL,0x00000000);//!!??test if this deletes tunnel
-}
-
 static void
 olsr_netlink_addreq(struct nlmsghdr *n, size_t reqSize __attribute__ ((unused)), int type, const void *data, int len)
 {
diff --git a/src/linux/kernel_tunnel.c b/src/linux/kernel_tunnel.c
new file mode 100644 (file)
index 0000000..e5d8596
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
+ * Copyright (c) 2007, Sven-Ola for the policy routing stuff
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its
+ *   contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+#include "kernel_tunnel.h"
+#include "log.h"
+#include "olsr_types.h"
+
+#include <assert.h>
+
+//ipip includes
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <linux/ip.h>
+#include <linux/if_tunnel.h>
+#include <linux/ip6_tunnel.h>
+
+//ifup includes
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <net/if.h>
+
+static const char DEV_IPV4_TUNNEL[IFNAMSIZ] = "tunl0";
+static const char DEV_IPV6_TUNNEL[IFNAMSIZ] = "ip6tnl0";
+
+static const char *get_tunnelcmd_name(uint32_t cmd) {
+  static const char ADD[] = "add";
+  static const char CHANGE[] = "change";
+  static const char DELETE[] = "delete";
+
+  switch (cmd) {
+    case SIOCADDTUNNEL:
+      return ADD;
+    case SIOCCHGTUNNEL:
+      return CHANGE;
+    case SIOCDELTUNNEL:
+      return DELETE;
+    default:
+      return NULL;
+  }
+}
+
+static int os_ip4_tunnel(const char *name, in_addr_t *target, uint32_t cmd)
+{
+  struct ifreq ifr;
+  int err;
+  struct ip_tunnel_parm p;
+
+  /* no IPIP tunnel if OLSR runs with IPv6 */
+  assert (olsr_cnf->ip_version == AF_INET);
+  memset(&p, 0, sizeof(p));
+  p.iph.version = 4;
+  p.iph.ihl = 5;
+  p.iph.protocol = IPPROTO_IPIP;
+  if (target) {
+    p.iph.daddr = *target;
+  }
+  strncpy(p.name, name, IFNAMSIZ);
+
+  memset(&ifr, 0, sizeof(ifr));
+  strncpy(ifr.ifr_name, cmd == SIOCADDTUNNEL ? DEV_IPV4_TUNNEL : name, IFNAMSIZ);
+  ifr.ifr_ifru.ifru_data = (void *) &p;
+
+  if ((err = ioctl(olsr_cnf->ioctl_s, cmd, &ifr))) {
+    olsr_syslog(OLSR_LOG_ERR, "Cannot %s a tunnel %s: %s (%d)\n",
+        get_tunnelcmd_name(cmd), name, strerror(errno), errno);
+  }
+  return err;
+}
+
+static int os_ip6_tunnel(const char *name, struct in6_addr *target, uint32_t cmd, uint8_t proto)
+{
+  struct ifreq ifr;
+  int err;
+  struct ip6_tnl_parm p;
+
+  /* no IPIP tunnel if OLSR runs with IPv6 */
+  assert (olsr_cnf->ip_version == AF_INET6);
+  memset(&p, 0, sizeof(p));
+  p.proto = proto; //  ? IPPROTO_IPV6 : IPPROTO_IPIP;
+  if (target) {
+    p.raddr = *target;
+  }
+  strncpy(p.name, name, IFNAMSIZ);
+
+  memset(&ifr, 0, sizeof(ifr));
+  strncpy(ifr.ifr_name, cmd == SIOCADDTUNNEL ? DEV_IPV6_TUNNEL : name, IFNAMSIZ);
+  ifr.ifr_ifru.ifru_data = (void *) &p;
+
+  if ((err = ioctl(olsr_cnf->ioctl_s, cmd, &ifr))) {
+    olsr_syslog(OLSR_LOG_ERR, "Cannot %s a tunnel %s: %s (%d)\n",
+        get_tunnelcmd_name(cmd), name, strerror(errno), errno);
+  }
+  return err;
+}
+
+int olsr_os_add_ipip_tunnel(const char *name, union olsr_ip_addr *target, bool transportV4) {
+  if (olsr_cnf->ip_version == AF_INET) {
+    assert(transportV4);
+
+    return os_ip4_tunnel(name, &target->v4.s_addr, SIOCADDTUNNEL);
+  }
+  return os_ip6_tunnel(name, &target->v6, SIOCADDTUNNEL, transportV4 ? IPPROTO_IPIP : IPPROTO_IPV6);
+}
+
+int olsr_os_change_ipip_tunnel(const char *name, union olsr_ip_addr *target, bool transportV4) {
+  if (olsr_cnf->ip_version == AF_INET) {
+    assert(transportV4);
+
+    return os_ip4_tunnel(name, &target->v4.s_addr, SIOCCHGTUNNEL);
+  }
+  return os_ip6_tunnel(name, &target->v6, SIOCCHGTUNNEL, transportV4 ? IPPROTO_IPIP : IPPROTO_IPV6);
+}
+
+int olsr_os_del_ipip_tunnel(const char *name, bool transportV4) {
+  if (olsr_cnf->ip_version == AF_INET) {
+    assert(transportV4);
+
+    return os_ip4_tunnel(name, NULL, SIOCDELTUNNEL);
+  }
+  return os_ip6_tunnel(name, NULL, SIOCDELTUNNEL, transportV4 ? IPPROTO_IPIP : IPPROTO_IPV6);
+}
index 653bb32..46fa080 100644 (file)
@@ -91,10 +91,6 @@ void olsr_reconfigure(int) __attribute__ ((noreturn));
 
 static void print_usage(bool error);
 
-#ifdef LINUX_NETLINK_ROUTING
-static const char* ipip_default_name = "olsr_tunnel";
-#endif
-
 static int set_default_ifcnfs(struct olsr_if *, struct if_config_options *);
 
 static int olsr_process_arguments(int, char *[], struct olsrd_config *,
@@ -523,6 +519,7 @@ deactivate_spoof("all", &olsr_cnf->ipip_base_if, AF_INET );
 #ifdef LINUX_NETLINK_ROUTING
   /*create smart-gateway-tunnel policy rules*/
   //!!?? disable smartgateway if not ipv4?, or better: do not start olsr
+#if 0
   if (olsr_cnf->smart_gw_active) {
     int r = olsr_if_setip(TUNL_BASE, &olsr_cnf->main_addr, 0);
 printf("set interface up returned %i",r);
@@ -591,7 +588,7 @@ printf("\nMain Table is %i prio %i", olsr_cnf->rttable, olsr_cnf->rttable_rule);
                         olsr_cnf->rttable_backup_rule, NULL, true);
     }
   }
-
+#endif
   /* Create rule for RtTable to resolve route insertion problems*/
   if ((olsr_cnf->rttable < 253) & (olsr_cnf->rttable > 0)) {
     olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rttable, (olsr_cnf->rttable_rule>0?olsr_cnf->rttable_rule:65535), NULL, true);
@@ -804,7 +801,9 @@ static void olsr_shutdown(int signo __attribute__ ((unused)))
 #ifdef LINUX_NETLINK_ROUTING
 
   /*delete smartgw tunnel if it index is known*/
+#if 0
   if (olsr_cnf->ipip_if_index) olsr_del_tunl();
+#endif
 
   /*!!?? we should take down the tunl0 interface*/
 
@@ -820,12 +819,13 @@ static void olsr_shutdown(int signo __attribute__ ((unused)))
   if (olsr_cnf->rttable_backup_rule>0)
     olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rttable_default, olsr_cnf->rttable_backup_rule, NULL, false);
 
+#if 0
   /*tunl0*/
   if (olsr_cnf->ipip_base_orig_down) {
     printf("\ntakig down tunl0 again");
     olsr_if_set_state(TUNL_BASE, false);
   }
-
+#endif
   /* RtTable backup rule */
   if ((olsr_cnf->rttable < 253) & (olsr_cnf->rttable > 0)) {
     olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rttable, (olsr_cnf->rttable_rule?olsr_cnf->rttable_rule:65535), NULL, false);