Attention is currently required from: plaisthos.

Hello plaisthos,

I'd like you to reexamine a change. Please visit

    http://gerrit.openvpn.net/c/openvpn/+/1786?usp=email

to look at the new patch set (#2).


Change subject: multi: assign IPv6 addresses from a tagged subnet-pool
......................................................................

multi: assign IPv6 addresses from a tagged subnet-pool

Add the IPv6 counterpart of --subnet-pool:

  subnet-pool-ipv6 <tag> <network>/<bits> [<gateway>]   (main config)

selected by the same per-client --subnet-pool-tag. A client's tag is
resolved against the IPv6 pool list too and, when it matches, an IPv6
address is handed out from the group's pool alongside any IPv4 one (a
single dual-stack ifconfig_pool per tag). A tag matching neither family
is still declined with AUTH_FAILED.

Change-Id: I64e0850d48647a2c0e3d385c2f20a9f445931727
GitHub: closes openvpn/OpenVPN#987
Signed-off-by: Antonio Quartulli <[email protected]>
---
M doc/man-sections/server-options.rst
M src/openvpn/multi.c
M src/openvpn/options.c
M src/openvpn/options.h
M src/openvpn/options_util.c
M src/openvpn/options_util.h
6 files changed, 138 insertions(+), 25 deletions(-)


  git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/86/1786/2

diff --git a/doc/man-sections/server-options.rst 
b/doc/man-sections/server-options.rst
index 8800b98..cf92905 100644
--- a/doc/man-sections/server-options.rst
+++ b/doc/man-sections/server-options.rst
@@ -349,11 +349,24 @@
   ``--route-gateway`` inside the subnet, and a host route back to the server's
   VPN IP, so it is reachable without manual per-client route pushes.

+--subnet-pool-ipv6 args
+  The IPv6 counterpart of ``--subnet-pool``. Repeatable main-config directive.
+
+  Valid syntax:
+  ::
+
+     subnet-pool-ipv6 tag network/bits [gateway]
+
+  ``bits`` must be between 64 and 124; ``gateway`` defaults to the first
+  address of the network. A tag may name an IPv4 pool, an IPv6 pool, or both;
+  a client referencing it with ``--subnet-pool-tag`` is then assigned an
+  address from each family the tag defines.
+
 --subnet-pool-tag tag
-  Assign this client to the ``--subnet-pool`` named ``tag``. Must be
-  associated with a specific client instance via ``--client-config-dir`` or
-  ``--client-connect``. Several clients may reference the same tag and are
-  then served from the same shared pool.
+  Assign this client to the ``--subnet-pool`` / ``--subnet-pool-ipv6`` named
+  ``tag``. Must be associated with a specific client instance via
+  ``--client-config-dir`` or ``--client-connect``. Several clients may
+  reference the same tag and are then served from the same shared pool(s).

 --ifconfig-ipv6-push args
   for ``--client-config-dir`` per-client static IPv6 interface
diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c
index da46cf4..1cd84b6 100644
--- a/src/openvpn/multi.c
+++ b/src/openvpn/multi.c
@@ -1438,11 +1438,14 @@
     }

     const struct subnet_pool_def *d4 = 
subnet_pool_by_tag(m->top.options.subnet_pools, tag);
+    const struct subnet_pool6_def *d6 = 
subnet_pool6_by_tag(m->top.options.subnet_pools_ipv6, tag);
     ALLOC_OBJ_CLEAR(sp, struct subnet_pool);
-    sp->tag = d4->tag;
-    sp->pool = ifconfig_pool_init(true, IFCONFIG_POOL_INDIV, d4->network + 2,
-                                  (d4->network | ~d4->netmask) - 1, 
m->top.options.duplicate_cn,
-                                  false, in6addr_any, 0);
+    sp->tag = d4 ? d4->tag : d6->tag;
+    sp->pool = ifconfig_pool_init(d4 != NULL, IFCONFIG_POOL_INDIV, d4 ? 
d4->network + 2 : 0,
+                                  d4 ? (d4->network | ~d4->netmask) - 1 : 0,
+                                  m->top.options.duplicate_cn, d6 != NULL,
+                                  d6 ? add_in6_addr(d6->network, 2) : 
in6addr_any,
+                                  d6 ? (int)d6->netbits : 0);
     sp->next = m->subnet_pools;
     m->subnet_pools = sp;
     return sp->pool;
@@ -1472,6 +1475,18 @@
             mi->context.options.subnet_pool_gateway = d->gateway;
         }
     }
+    if (mi->context.options.subnet_pool_tag && 
!mi->context.options.subnet_pool_ipv6_defined)
+    {
+        const struct subnet_pool6_def *d = subnet_pool6_by_tag(
+            m->top.options.subnet_pools_ipv6, 
mi->context.options.subnet_pool_tag);
+        if (d)
+        {
+            mi->context.options.subnet_pool_ipv6_defined = true;
+            mi->context.options.subnet_pool_ipv6_network = d->network;
+            mi->context.options.subnet_pool_ipv6_netbits = d->netbits;
+            mi->context.options.subnet_pool_ipv6_gateway = d->gateway;
+        }
+    }

     /*
      * If ifconfig addresses were set by dynamic config file,
@@ -1506,42 +1521,60 @@
                 "MULTI_sva: WARNING: if --ifconfig-push is used for IPv4, 
automatic IPv6 assignment from --ifconfig-ipv6-pool does not work.  Use 
--ifconfig-ipv6-push for IPv6 then.");
         }
     }
-    else if (mi->context.options.subnet_pool_defined)
+    else if (mi->context.options.subnet_pool_tag)
     {
-        /* dynamic address from this client's --subnet-pool group */
+        /* dynamic address(es) from this client's --subnet-pool group */

         /* the CCD is read after a global-pool address may already have been
-         * acquired; drop it so we can serve this client from its group */
+         * acquired; drop it so we serve this client from its group only */
         if (mi->vaddr_handle >= 0 && !mi->vaddr_pool)
         {
             ifconfig_pool_release(m->ifconfig_pool, mi->vaddr_handle, true);
             mi->vaddr_handle = -1;
+            mi->context.c2.push_ifconfig_defined = false;
+            mi->context.c2.push_ifconfig_ipv6_defined = false;
         }

-        if (mi->vaddr_handle < 0)
+        if ((mi->context.options.subnet_pool_defined
+             || mi->context.options.subnet_pool_ipv6_defined)
+            && mi->vaddr_handle < 0)
         {
             in_addr_t local = 0, remote = 0;
+            struct in6_addr remote_ipv6;
             const char *cn = NULL;

+            CLEAR(remote_ipv6);
             if (!mi->context.options.duplicate_cn)
             {
                 cn = tls_common_name(mi->context.c2.tls_multi, true);
             }

             mi->vaddr_pool = multi_get_group_pool(m, 
mi->context.options.subnet_pool_tag);
-            mi->vaddr_handle = ifconfig_pool_acquire(mi->vaddr_pool, &local, 
&remote, NULL, cn);
-            if (mi->vaddr_handle >= 0)
-            {
-                mi->context.c2.push_ifconfig_local = remote;
-                mi->context.c2.push_ifconfig_remote_netmask =
-                    mi->context.options.subnet_pool_netmask;
-                mi->context.c2.push_ifconfig_defined = true;
-            }
-            else
+            mi->vaddr_handle =
+                ifconfig_pool_acquire(mi->vaddr_pool, &local, &remote, 
&remote_ipv6, cn);
+            if (mi->vaddr_handle < 0)
             {
                 msg(D_MULTI_ERRORS, "MULTI: no free --subnet-pool addresses 
are available for %s",
                     multi_instance_string(mi, false, &gc));
             }
+            else
+            {
+                if (mi->context.options.subnet_pool_defined)
+                {
+                    mi->context.c2.push_ifconfig_local = remote;
+                    mi->context.c2.push_ifconfig_remote_netmask =
+                        mi->context.options.subnet_pool_netmask;
+                    mi->context.c2.push_ifconfig_defined = true;
+                }
+                if (mi->context.options.subnet_pool_ipv6_defined)
+                {
+                    mi->context.c2.push_ifconfig_ipv6_local = remote_ipv6;
+                    mi->context.c2.push_ifconfig_ipv6_remote = 
mi->context.c1.tuntap->local_ipv6;
+                    mi->context.c2.push_ifconfig_ipv6_netbits =
+                        mi->context.options.subnet_pool_ipv6_netbits;
+                    mi->context.c2.push_ifconfig_ipv6_defined = true;
+                }
+            }
         }
     }
     else if (m->ifconfig_pool && mi->vaddr_handle < 0) /* otherwise, choose a 
pool address */
@@ -2852,7 +2885,9 @@
     }

     if (mi->context.options.subnet_pool_tag
-        && !subnet_pool_by_tag(m->top.options.subnet_pools, 
mi->context.options.subnet_pool_tag))
+        && !subnet_pool_by_tag(m->top.options.subnet_pools, 
mi->context.options.subnet_pool_tag)
+        && !subnet_pool6_by_tag(m->top.options.subnet_pools_ipv6,
+                                mi->context.options.subnet_pool_tag))
     {
         msg(D_MULTI_ERRORS, "MULTI: client has been rejected due to unknown 
--subnet-pool-tag '%s'",
             mi->context.options.subnet_pool_tag);
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 3f9f7de..b4485ca 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -446,6 +446,8 @@
     "--subnet-pool tag network netmask [gateway] : Define a named pool of\n"
     "                  addresses outside the --server network, selected per\n"
     "                  client with --subnet-pool-tag.\n"
+    "--subnet-pool-ipv6 tag network/bits [gateway] : IPv6 counterpart of\n"
+    "                  --subnet-pool.\n"
     "--subnet-pool-tag tag : Assign this client to the --subnet-pool named 
tag.\n"
     "                  Only valid in a client-specific config file.\n"
     "--ifconfig-push local remote-netmask : Push an ifconfig option to 
remote,\n"
@@ -7658,6 +7660,37 @@
         sp->next = options->subnet_pools;
         options->subnet_pools = sp;
     }
+    else if (streq(p[0], "subnet-pool-ipv6") && p[1] && p[2] && !p[4])
+    {
+        struct subnet_pool6_def *sp;
+        struct in6_addr network, gateway;
+        unsigned int netbits = 0;
+
+        VERIFY_PERMISSION(OPT_P_GENERAL);
+        if (!get_ipv6_addr(p[2], &network, &netbits, msglevel))
+        {
+            msg(msglevel, "cannot parse --subnet-pool-ipv6 network");
+            goto err;
+        }
+        if (netbits < 64 || netbits > 124)
+        {
+            msg(msglevel, "--subnet-pool-ipv6 network must be between /64 and 
/124 (not /%d)",
+                netbits);
+            goto err;
+        }
+        if (p[3] && !get_ipv6_addr(p[3], &gateway, NULL, msglevel))
+        {
+            msg(msglevel, "cannot parse --subnet-pool-ipv6 gateway");
+            goto err;
+        }
+        ALLOC_OBJ_GC(sp, struct subnet_pool6_def, &options->gc);
+        sp->tag = p[1];
+        sp->network = network;
+        sp->netbits = netbits;
+        sp->gateway = p[3] ? gateway : add_in6_addr(network, 1);
+        sp->next = options->subnet_pools_ipv6;
+        options->subnet_pools_ipv6 = sp;
+    }
     else if (streq(p[0], "subnet-pool-tag") && p[1] && !p[2])
     {
         VERIFY_PERMISSION(OPT_P_INSTANCE);
diff --git a/src/openvpn/options.h b/src/openvpn/options.h
index 0c810b3..7f0e3ce 100644
--- a/src/openvpn/options.h
+++ b/src/openvpn/options.h
@@ -261,6 +261,16 @@
     in_addr_t gateway;
 };

+/* The IPv6 counterpart of struct subnet_pool_def (--subnet-pool-ipv6). */
+struct subnet_pool6_def
+{
+    struct subnet_pool6_def *next;
+    const char *tag;
+    struct in6_addr network;
+    unsigned int netbits;
+    struct in6_addr gateway;
+};
+
 /* Command line options */
 struct options
 {
@@ -526,12 +536,17 @@
     bool push_ifconfig_constraint_defined;
     in_addr_t push_ifconfig_constraint_network;
     in_addr_t push_ifconfig_constraint_netmask;
-    struct subnet_pool_def *subnet_pools; /* named pools (server config) */
-    const char *subnet_pool_tag;          /* which pool this client uses (CCD) 
*/
-    bool subnet_pool_defined;             /* resolved from the tag at connect 
*/
+    struct subnet_pool_def *subnet_pools;       /* named IPv4 pools (server 
config) */
+    struct subnet_pool6_def *subnet_pools_ipv6; /* named IPv6 pools (server 
config) */
+    const char *subnet_pool_tag;                /* which pool this client uses 
(CCD) */
+    bool subnet_pool_defined;                   /* resolved from the tag at 
connect */
     in_addr_t subnet_pool_network;
     in_addr_t subnet_pool_netmask;
     in_addr_t subnet_pool_gateway;
+    bool subnet_pool_ipv6_defined; /* resolved from the tag at connect */
+    struct in6_addr subnet_pool_ipv6_network;
+    unsigned int subnet_pool_ipv6_netbits;
+    struct in6_addr subnet_pool_ipv6_gateway;
     bool push_ifconfig_ipv4_blocked;           /* IPv4 */
     bool push_ifconfig_ipv6_defined;           /* IPv6 */
     struct in6_addr push_ifconfig_ipv6_local;  /* IPv6 */
diff --git a/src/openvpn/options_util.c b/src/openvpn/options_util.c
index ba04917..7826458 100644
--- a/src/openvpn/options_util.c
+++ b/src/openvpn/options_util.c
@@ -44,6 +44,19 @@
     return NULL;
 }

+const struct subnet_pool6_def *
+subnet_pool6_by_tag(const struct subnet_pool6_def *pools, const char *tag)
+{
+    for (const struct subnet_pool6_def *d = pools; d; d = d->next)
+    {
+        if (!strcmp(d->tag, tag))
+        {
+            return d;
+        }
+    }
+    return NULL;
+}
+
 const char *
 parse_auth_failed_temp(struct options *o, const char *reason)
 {
diff --git a/src/openvpn/options_util.h b/src/openvpn/options_util.h
index c54357c..ed2017a 100644
--- a/src/openvpn/options_util.h
+++ b/src/openvpn/options_util.h
@@ -38,6 +38,10 @@
 const struct subnet_pool_def *subnet_pool_by_tag(const struct subnet_pool_def 
*pools,
                                                  const char *tag);

+/** IPv6 counterpart of subnet_pool_by_tag(). */
+const struct subnet_pool6_def *subnet_pool6_by_tag(const struct 
subnet_pool6_def *pools,
+                                                   const char *tag);
+

 /** Checks if the string is a valid integer by checking if it can be
  *  converted to an integer */

--
To view, visit http://gerrit.openvpn.net/c/openvpn/+/1786?usp=email
To unsubscribe, or for help writing mail filters, visit 
http://gerrit.openvpn.net/settings?usp=email

Gerrit-MessageType: newpatchset
Gerrit-Project: openvpn
Gerrit-Branch: master
Gerrit-Change-Id: I64e0850d48647a2c0e3d385c2f20a9f445931727
Gerrit-Change-Number: 1786
Gerrit-PatchSet: 2
Gerrit-Owner: ordex <[email protected]>
Gerrit-Reviewer: plaisthos <[email protected]>
Gerrit-CC: openvpn-devel <[email protected]>
Gerrit-Attention: plaisthos <[email protected]>
_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to