]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Enable IPv6 Payload in OpenVPN p2mp tun server mode. 20100104-1 release.
authorGert Doering <gert@greenie.muc.de>
Thu, 7 Jan 2010 13:51:40 +0000 (14:51 +0100)
committerGert Doering <gert@greenie.muc.de>
Sun, 24 Apr 2011 15:22:37 +0000 (17:22 +0200)
(cherry picked from commit ec9dce6387afd198881493bfebf13bb121e8a56b)

NOTES [new file with mode: 0644]
mroute.c
push.c
tun.c

diff --git a/NOTES b/NOTES
new file mode 100644 (file)
index 0000000..d494073
--- /dev/null
+++ b/NOTES
@@ -0,0 +1,180 @@
+TODO:
+
+ * tun.c -> init_tun()
+    [ifconfig-Parameter vorbereiten]
+
+    init.c -> do_open_tun() -> init.c::do_init_tun() -> tun.c::init_tun()
+                           -> do_ifconfig()
+
+ o tun.c -> do_ifconfig()
+    [ifconfig/ip aufrufen]
+
+    * Linux / ifconfig  
+    / Linux / iproute2  ** TESTEN **
+    o FreeBSD
+    / NetBSD ("needs patch", googlen) ** TESTEN **
+    / Solaris                         ** TESTEN **
+    o OpenBSD
+    o MacOS X
+
+ o tun.c (?) -> interface cleanup ("ip addr del dev tun0 ...")
+
+ o TAP mode und IPv6?  Fehlermeldung?
+    o einfach confen
+
+ o ifconfig_ipv6_remote -> kann eigentlich ersatzlos wegfallen
+   [tun.c, init.c, options.c, options.h]
+   o [kann nicht, braucht man als default-gateway auf Solaris :( ]
+
+ * push ifconfig-ipv6
+   push::send_push_reply() -> c->c2.push_ifconfig_local
+
+   ** wo wird das gesetzt? ** multi.c (und ggf. options.c / ifconfig-push)
+
+   o /netbits pushen (push.c) -> options.c "ifconfig-ipv6" muss auch
+     damit zurecht kommen, tut es derzeit aber nicht
+
+ * ifconfig_pool_write() -> IPv6 "wenn pool IPv6 hat"
+
+ * multi::multi_init() -> ifconfig_pool_init()
+   
+
+ * "route-ipv6"-Option und "push route-ipv6"
+   o "gateway" 
+   o "metric"
+   o "route-gateway-ipv6"-Option
+   o "ifconfig-ipv6-push"-Option
+      options.c -> options.push_ifconfig_...
+      multi.c 
+       mi->context.c2.push_ifconfig_local = mi->context.options.push_ifconfig_local;
+
+
+ o "server-ipv6"-Option
+
+   o options.c, add_option() -> wird fuer "lokale" und "push"-Options
+     aufgerufen
+     no_more_than_n_args()
+     struct options [options.h]
+
+   * add_route_to_option_list() 
+     [route.c -> add_route_ipv6_to_option_list]
+     [options.h -> options->routes_ipv6]
+
+     o was passiert danach damit?
+
+   * socket.c: ip_or_dns_addr_safe()
+     --> ipv6_addr_safe()
+     --> ipv6_addr_safe_hexplusbits()
+
+   * Makro?  helper.c -> helper_client_server()      ******
+     * Fehler, wenn options->mode != MODE_SERVER
+     * "tun-ipv6" auto-enablen
+
+   * if (options->tun_ipv6)
+                msg (M_USAGE, "--tun-ipv6 cannot be used with --mode server");
+     [options.c, 1710]
+     [raus]
+
+   o struct tuntap->ipv6 = true, wenn "ipv6" und "system kann das"
+   o Fehler, wenn System kein IPv6 kann
+     ("NetBSD needs patch" -> googlen)
+
+ o Adress-Allokation an Clients (/128 aus ifconfig-ipv6-pool /64 erstmal nur)
+   o hash aus Client-Key als host part?
+     (nein, wir nehmen einfach "den gleichen Offset wie bei IPv4" und
+     add_in6_addr())
+
+ o "iroute-ipv6"-Option
+ o "ifconfig-ipv6"
+ o "ifconfig-ipv6-pool"
+ o "ifconfig-pool-persist-ipv6"-Option
+
+ o was tut #define LINUX_IPV6?
+ o was tut bestehender Code mit "ipv6"?
+
+
+ o Routing-/Forwarding-Funktion
+   read_tun() --> ??
+   ?? --> write_tun() 
+
+   [muss für p2p schon funktionieren, d.h. vermutlich ist nur die
+   server-seite anzupassen]
+
+ o ICMP
+
+ o Optionen dokumentieren (-> berniv6)
+   o server-ipv6
+   o ifconfig-ipv6
+   o ifconfig-ipv6-pool
+   o ifconfig-pool-persist (v4+v6, Formataenderung im File)
+   o iroute-ipv6
+   o route-ipv6
+   o tun-ipv6
+
+   * http://www.greenie.net/ipv6/openvpn.html  - DONE
+   o man pages, --help
+
+ * options.c
+    - get_ip_addr() --> socket.c getaddr()
+    - openvpn_inet_aton -> OIA_IP "ist IP"
+
+ * options.c, show_p2mp_parms()
+
+ * socket.c, print_in_addr_t()  --> print_in6_addr()
+
+ o forward_compatible?
+
+ o ifconfig_ipv6_pool_persist --> einfach ifconfig_pool_persist mitbenutzen?
+   Entscheidung: JA
+   o to be implemented: pool.c
+
+ o route.c:
+    clone_route_option_list(), copy_route_option_list(),
+    new_route_list(), add_route(), init_route_list(), ...
+    add_routes(), delete_routes(), setenv_routes(), 
+
+    -> wo werden die aufgerufen, wofuer verwendet, IPv6-Anpassung?
+
+    * add_route() ruft "/sbin/route add..." auf
+    o div. (redirect gateway related) -> route.c::add_route3() -> add_route()
+    o init.c::do_route() -> route.c::add_routes() -> add_route()
+    o init.c::do_open_tun() -> do_route()
+    o forward.c::check_add_routes_action() -> do_route()
+    o init.c::do_open_tun() -> init.c::do_init_route_list() ->
+      route.c::init_route_list()
+    * init.c::do_open_tun() -> do_alloc_route_list() -> new_route_ipv6_list()
+
+ o add_route_ipv6() - implementieren und testen
+    * Linux / ifconfig  
+    * Linux / iproute2
+    i FreeBSD
+    i NetBSD ("needs patch", googlen)
+    i Solaris *braucht Gateway*
+    i OpenBSD
+    i MacOS X
+
+ o delete_route_ipv6() - implementieren und testen
+    * Linux / ifconfig  
+    * Linux / iproute2
+    i FreeBSD
+    i NetBSD ("needs patch", googlen)
+    i Solaris
+    i OpenBSD
+    i MacOS X
+
+ o Gateway-Logik für IPv6-Routen mitschleifen ("explizit angeben oder
+   aus ifconfig-ipv6 $remote")
+
+ o IPv6 TCPMSS oder "fragmentation required"?
+    o IPv6 MTU auf Interface setzen?
+    o sysdep!
+
+
+TESTEN
+ * ipv6_addr_safe() [--ifconfig-ipv6 null/zu lang/invalid]
+ o ipv6_addr_safe_hexplusbits() [--route-ipv6 ...]
+ * get_ipv6_addr() [--server-ipv6 ...]
+
+ o unmodifizierter 2.1-client -> 2.1+ipv6-Server?
+ o unmodifizierter 2.0-client -> 2.1+ipv6-Server?
+ o wie kann der Server das erkennen, und "kein v6" schicken?
index af00c1e2676085846121625af31b71fb6a51a14a..5ef07b223f60999743790ccd84f7eed8018d4927 100644 (file)
--- a/mroute.c
+++ b/mroute.c
@@ -525,6 +525,44 @@ mroute_helper_del_iroute6 (struct mroute_helper *mh,
     }
 }
 
+/* this is a bit inelegant, we really should have a helper to that 
+ * is only passed the netbits value, and not the whole struct iroute *
+ * - thus one helper could do IPv4 and IPv6.  For the sake of "not change
+ * code unrelated to IPv4" this is left for later cleanup, for now.
+ */
+void
+mroute_helper_add_iroute6 (struct mroute_helper *mh, 
+                           const struct iroute_ipv6 *ir6)
+{
+  if (ir6->netbits >= 0)
+    {
+      ASSERT (ir6->netbits < MR_HELPER_NET_LEN);
+      mroute_helper_lock (mh);
+      ++mh->cache_generation;
+      ++mh->net_len_refcount[ir6->netbits];
+      if (mh->net_len_refcount[ir6->netbits] == 1)
+       mroute_helper_regenerate (mh);
+      mroute_helper_unlock (mh);
+    }
+}
+
+void
+mroute_helper_del_iroute6 (struct mroute_helper *mh, 
+                          const struct iroute_ipv6 *ir6)
+{
+  if (ir6->netbits >= 0)
+    {
+      ASSERT (ir6->netbits < MR_HELPER_NET_LEN);
+      mroute_helper_lock (mh);
+      ++mh->cache_generation;
+      --mh->net_len_refcount[ir6->netbits];
+      ASSERT (mh->net_len_refcount[ir6->netbits] >= 0);
+      if (!mh->net_len_refcount[ir6->netbits])
+       mroute_helper_regenerate (mh);
+      mroute_helper_unlock (mh);
+    }
+}
+
 void
 mroute_helper_free (struct mroute_helper *mh)
 {
diff --git a/push.c b/push.c
index e2a91827bdeca669d91437d67005194ec352c891..1fd8bea39ac0da69d69c9573086d54505378e945 100644 (file)
--- a/push.c
+++ b/push.c
@@ -189,6 +189,8 @@ send_push_reply (struct context *c)
   const int safe_cap = BCAP (&buf) - extra;
   bool push_sent = false;
 
+  msg( M_INFO, "send_push_reply(): safe_cap=%d", safe_cap );
+
   buf_printf (&buf, "%s", cmd);
 
   if ( c->c2.push_ifconfig_ipv6_defined )
diff --git a/tun.c b/tun.c
index 9dcd9e6fbf8a2bb39bbb625686b8ded988e591f4..88e1f0fea9c0ba9353944dc98e358b977a57ba57 100644 (file)
--- a/tun.c
+++ b/tun.c
@@ -433,6 +433,7 @@ init_tun (const char *dev,       /* --dev option */
 {
   struct gc_arena gc = gc_new ();
   struct tuntap *tt;
+  bool tun;
 
   ALLOC_OBJ (tt, struct tuntap);
   clear_tuntap (tt);
@@ -440,18 +441,17 @@ init_tun (const char *dev,       /* --dev option */
   tt->type = dev_type_enum (dev, dev_type);
   tt->topology = topology;
 
+  /*
+   * We only handle TUN/TAP devices here, not --dev null devices.
+   */
+  tun = is_tun_p2p (tt);
+
   if (ifconfig_local_parm && ifconfig_remote_netmask_parm)
     {
-      bool tun = false;
       const char *ifconfig_local = NULL;
       const char *ifconfig_remote_netmask = NULL;
       const char *ifconfig_broadcast = NULL;
 
-      /*
-       * We only handle TUN/TAP devices here, not --dev null devices.
-       */
-      tun = is_tun_p2p (tt);
-
       /*
        * Convert arguments to binary IPv4 addresses.
        */
@@ -1973,6 +1973,15 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len)
  *
  */
 
+static inline int
+netbsd_modify_read_write_return (int len)
+{
+  if (len > 0)
+    return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0;
+  else
+    return len;
+}
+
 void
 open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
 {
@@ -2074,12 +2083,46 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len)
 int
 write_tun (struct tuntap* tt, uint8_t *buf, int len)
 {
+  if (tt->type == DEV_TYPE_TUN)
+    {
+      u_int32_t type;
+      struct iovec iv[2];
+      struct openvpn_iphdr *iph;
+
+      iph = (struct openvpn_iphdr *) buf;
+
+      if (tt->ipv6 && OPENVPN_IPH_GET_VER(iph->version_len) == 6)
+        type = htonl (AF_INET6);
+      else 
+        type = htonl (AF_INET);
+
+      iv[0].iov_base = (char *)&type;
+      iv[0].iov_len = sizeof (type);
+      iv[1].iov_base = buf;
+      iv[1].iov_len = len;
+
+      return netbsd_modify_read_write_return (writev (tt->fd, iv, 2));
+    }
+  else
     return write (tt->fd, buf, len);
 }
 
 int
 read_tun (struct tuntap* tt, uint8_t *buf, int len)
 {
+  if (tt->type == DEV_TYPE_TUN)
+    {
+      u_int32_t type;
+      struct iovec iv[2];
+
+      iv[0].iov_base = (char *)&type;
+      iv[0].iov_len = sizeof (type);
+      iv[1].iov_base = buf;
+      iv[1].iov_len = len;
+
+      return netbsd_modify_read_write_return (readv (tt->fd, iv, 2));
+    }
+  else
     return read (tt->fd, buf, len);
 }
 #endif /* NETBSD_MULTI_AF */