[Openvpn-devel] implement net_gateway_ipv6 for --route-ipv6

Message ID 20211123083758.15933-1-fkooman@tuxed.net
State Changes Requested
Headers show
Series [Openvpn-devel] implement net_gateway_ipv6 for --route-ipv6 | expand

Commit Message

François Kooman Nov. 22, 2021, 9:37 p.m. UTC
fix for #1161

Signed-off-by: François Kooman <fkooman@tuxed.net>
---
 src/openvpn/options.c |  2 +-
 src/openvpn/route.c   | 67 +++++++++++++++++++++++++++++++++++++++++--
 src/openvpn/route.h   |  1 +
 3 files changed, 67 insertions(+), 3 deletions(-)

Comments

Gert Doering Nov. 22, 2021, 9:59 p.m. UTC | #1
Hi,

On Tue, Nov 23, 2021 at 09:37:58AM +0100, François Kooman wrote:
> fix for #1161
> 
> Signed-off-by: François Kooman <fkooman@tuxed.net>

Is this a v2, or a re-sent "because nobody picked it up"?

The commit message *could* have a few more words, though :-) - and
the Ticket number wants to be "Trac: #1161".  But this is minor, and
I can handle this on the fly, if the rest is reviewed and ACKed
(not doing this right now, just clarifying the v1 vs. v2 status).

gert
François Kooman Nov. 22, 2021, 10:05 p.m. UTC | #2
On 23.11.21 09:59, Gert Doering wrote:
> Hi,

Hi Gert,

> Is this a v2, or a re-sent "because nobody picked it up"?

Well, if you consider the PR on GitHub [PR#160] the v1, then yes, this 
is v2.

> The commit message *could* have a few more words, though :-) - and
> the Ticket number wants to be "Trac: #1161".  But this is minor, and
> I can handle this on the fly, if the rest is reviewed and ACKed
> (not doing this right now, just clarifying the v1 vs. v2 status).

I could fix that for a v2 (or v3) as well.

Regards,
François
Gert Doering Nov. 22, 2021, 10:11 p.m. UTC | #3
Hi,

On Tue, Nov 23, 2021 at 10:05:16AM +0100, François Kooman wrote:
> > Is this a v2, or a re-sent "because nobody picked it up"?
> 
> Well, if you consider the PR on GitHub [PR#160] the v1, then yes, this 
> is v2.

Oh.  I really need more coffee.  I remembered I had seen a mail about
this, but my mailbox tells me it was only the GH PR notificaiton
(we decided at the hackathon that we want to be a bit more open about
GH PRs, and now I'm even more confused about "where have I seen 
this before?" :-) )

So, yeah, thanks for sending the patch to the list, so it's in patchwork
now and will be properly tracked there.

Sending a v2 for the commit message improvements is not needed (I can fix
that on the fly).  If code changes are requested, the v2 for those can
then include the message fixes.

gert
Antonio Quartulli Sept. 19, 2022, 9:13 a.m. UTC | #4
For the records, the following changes were requested to this patch 
(some via GH):

1) improve (add?) commit message;
2) add comments/documentation to ipv6_get_special_addr()
3) get rid of the ipv6_is_special_addr() wrapper as it is not really 
doing much.

Cheers,

On 23/11/2021 09:37, François Kooman wrote:
> fix for #1161
> 
> Signed-off-by: François Kooman <fkooman@tuxed.net>
> ---
>   src/openvpn/options.c |  2 +-
>   src/openvpn/route.c   | 67 +++++++++++++++++++++++++++++++++++++++++--
>   src/openvpn/route.h   |  1 +
>   3 files changed, 67 insertions(+), 3 deletions(-)
> 
> diff --git a/src/openvpn/options.c b/src/openvpn/options.c
> index cc3d9fa0..3d530d7a 100644
> --- a/src/openvpn/options.c
> +++ b/src/openvpn/options.c
> @@ -6558,7 +6558,7 @@ add_option(struct options *options,
>                   msg(msglevel, "route-ipv6 parameter network/IP '%s' must be a valid address", p[1]);
>                   goto err;
>               }
> -            if (p[2] && !ipv6_addr_safe(p[2]))
> +            if (p[2] && !ipv6_addr_safe(p[2]) && !ipv6_is_special_addr(p[2]))
>               {
>                   msg(msglevel, "route-ipv6 parameter gateway '%s' must be a valid address", p[2]);
>                   goto err;
> diff --git a/src/openvpn/route.c b/src/openvpn/route.c
> index fd1125ef..bd62b99a 100644
> --- a/src/openvpn/route.c
> +++ b/src/openvpn/route.c
> @@ -287,6 +287,38 @@ get_special_addr(const struct route_list *rl,
>       return false;
>   }
>   
> +static bool
> +ipv6_get_special_addr(const struct route_ipv6_list *rl,
> +                 const char *string,
> +                 struct in6_addr *out,
> +                 bool *status)
> +{
> +    if (status)
> +    {
> +        *status = true;
> +    }
> +    if (!strcmp(string, "net_gateway_ipv6"))
> +    {
> +        if (rl)
> +        {
> +            if (rl->rgi6.flags & RGI_ADDR_DEFINED)
> +            {
> +                *out = rl->rgi6.gateway.addr_ipv6;
> +            }
> +            else
> +            {
> +                msg(M_INFO, PACKAGE_NAME " ROUTE: net_gateway_ipv6 undefined -- unable to get default gateway from system");
> +                if (status)
> +                {
> +                    *status = false;
> +                }
> +            }
> +        }
> +        return true;
> +    }
> +    return false;
> +}
> +
>   bool
>   is_special_addr(const char *addr_str)
>   {
> @@ -300,6 +332,19 @@ is_special_addr(const char *addr_str)
>       }
>   }
>   
> +bool
> +ipv6_is_special_addr(const char *addr_str)
> +{
> +    if (addr_str)
> +    {
> +        return ipv6_get_special_addr(NULL, addr_str, NULL, NULL);
> +    }
> +    else
> +    {
> +        return false;
> +    }
> +}
> +
>   static bool
>   init_route(struct route_ipv4 *r,
>              struct addrinfo **network_list,
> @@ -438,6 +483,7 @@ init_route_ipv6(struct route_ipv6 *r6,
>                   const struct route_ipv6_option *r6o,
>                   const struct route_ipv6_list *rl6 )
>   {
> +    bool status;
>       CLEAR(*r6);
>   
>       if (!get_ipv6_addr( r6o->prefix, &r6->network, &r6->netbits, M_WARN ))
> @@ -448,9 +494,26 @@ init_route_ipv6(struct route_ipv6 *r6,
>       /* gateway */
>       if (is_route_parm_defined(r6o->gateway))
>       {
> -        if (inet_pton( AF_INET6, r6o->gateway, &r6->gateway ) != 1)
> +        if (ipv6_get_special_addr(rl6, r6o->gateway, &r6->gateway, &status))
>           {
> -            msg( M_WARN, PACKAGE_NAME "ROUTE6: cannot parse gateway spec '%s'", r6o->gateway );
> +            r6->metric = 1;
> +#ifdef _WIN32
> +            r6->adapter_index = rl6->rgi6.adapter_index;
> +#else
> +            r6->iface = rl6->rgi6.iface;
> +#endif
> +            r6->flags = RT_DEFINED | RT_METRIC_DEFINED;
> +        }
> +        else
> +        {
> +            if (inet_pton( AF_INET6, r6o->gateway, &r6->gateway ) != 1)
> +            {
> +                msg( M_WARN, PACKAGE_NAME "ROUTE6: cannot parse gateway spec '%s'", r6o->gateway );
> +            }
> +        }
> +        if (!status)
> +        {
> +            goto fail;
>           }
>       }
>       else if (rl6->spec_flags & RTSA_REMOTE_ENDPOINT)
> diff --git a/src/openvpn/route.h b/src/openvpn/route.h
> index dc448c74..bbb8d2f8 100644
> --- a/src/openvpn/route.h
> +++ b/src/openvpn/route.h
> @@ -320,6 +320,7 @@ void setenv_routes(struct env_set *es, const struct route_list *rl);
>   void setenv_routes_ipv6(struct env_set *es, const struct route_ipv6_list *rl6);
>   
>   bool is_special_addr(const char *addr_str);
> +bool ipv6_is_special_addr(const char *addr_str);
>   
>   void get_default_gateway(struct route_gateway_info *rgi,
>                            openvpn_net_ctx_t *ctx);
Gert Doering Dec. 5, 2022, 12:08 p.m. UTC | #5
Hi,

On Mon, Sep 19, 2022 at 09:13:10PM +0200, Antonio Quartulli wrote:
> For the records, the following changes were requested to this patch 
> (some via GH):
> 
> 1) improve (add?) commit message;
> 2) add comments/documentation to ipv6_get_special_addr()
> 3) get rid of the ipv6_is_special_addr() wrapper as it is not really 
> doing much.

I think the patch is small and "isolated" enough so it could go into
the next 2.6_beta2 - if I can have it, with these changes, by start
of next week...

Francois, would that work out?

gert

Patch

diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index cc3d9fa0..3d530d7a 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -6558,7 +6558,7 @@  add_option(struct options *options,
                 msg(msglevel, "route-ipv6 parameter network/IP '%s' must be a valid address", p[1]);
                 goto err;
             }
-            if (p[2] && !ipv6_addr_safe(p[2]))
+            if (p[2] && !ipv6_addr_safe(p[2]) && !ipv6_is_special_addr(p[2]))
             {
                 msg(msglevel, "route-ipv6 parameter gateway '%s' must be a valid address", p[2]);
                 goto err;
diff --git a/src/openvpn/route.c b/src/openvpn/route.c
index fd1125ef..bd62b99a 100644
--- a/src/openvpn/route.c
+++ b/src/openvpn/route.c
@@ -287,6 +287,38 @@  get_special_addr(const struct route_list *rl,
     return false;
 }
 
+static bool
+ipv6_get_special_addr(const struct route_ipv6_list *rl,
+                 const char *string,
+                 struct in6_addr *out,
+                 bool *status)
+{
+    if (status)
+    {
+        *status = true;
+    }
+    if (!strcmp(string, "net_gateway_ipv6"))
+    {
+        if (rl)
+        {
+            if (rl->rgi6.flags & RGI_ADDR_DEFINED)
+            {
+                *out = rl->rgi6.gateway.addr_ipv6;
+            }
+            else
+            {
+                msg(M_INFO, PACKAGE_NAME " ROUTE: net_gateway_ipv6 undefined -- unable to get default gateway from system");
+                if (status)
+                {
+                    *status = false;
+                }
+            }
+        }
+        return true;
+    }
+    return false;
+}
+
 bool
 is_special_addr(const char *addr_str)
 {
@@ -300,6 +332,19 @@  is_special_addr(const char *addr_str)
     }
 }
 
+bool
+ipv6_is_special_addr(const char *addr_str)
+{
+    if (addr_str)
+    {
+        return ipv6_get_special_addr(NULL, addr_str, NULL, NULL);
+    }
+    else
+    {
+        return false;
+    }
+}
+
 static bool
 init_route(struct route_ipv4 *r,
            struct addrinfo **network_list,
@@ -438,6 +483,7 @@  init_route_ipv6(struct route_ipv6 *r6,
                 const struct route_ipv6_option *r6o,
                 const struct route_ipv6_list *rl6 )
 {
+    bool status;
     CLEAR(*r6);
 
     if (!get_ipv6_addr( r6o->prefix, &r6->network, &r6->netbits, M_WARN ))
@@ -448,9 +494,26 @@  init_route_ipv6(struct route_ipv6 *r6,
     /* gateway */
     if (is_route_parm_defined(r6o->gateway))
     {
-        if (inet_pton( AF_INET6, r6o->gateway, &r6->gateway ) != 1)
+        if (ipv6_get_special_addr(rl6, r6o->gateway, &r6->gateway, &status))
         {
-            msg( M_WARN, PACKAGE_NAME "ROUTE6: cannot parse gateway spec '%s'", r6o->gateway );
+            r6->metric = 1;
+#ifdef _WIN32
+            r6->adapter_index = rl6->rgi6.adapter_index;
+#else
+            r6->iface = rl6->rgi6.iface;
+#endif
+            r6->flags = RT_DEFINED | RT_METRIC_DEFINED;
+        }
+        else
+        {
+            if (inet_pton( AF_INET6, r6o->gateway, &r6->gateway ) != 1)
+            {
+                msg( M_WARN, PACKAGE_NAME "ROUTE6: cannot parse gateway spec '%s'", r6o->gateway );
+            }
+        }
+        if (!status)
+        {
+            goto fail;
         }
     }
     else if (rl6->spec_flags & RTSA_REMOTE_ENDPOINT)
diff --git a/src/openvpn/route.h b/src/openvpn/route.h
index dc448c74..bbb8d2f8 100644
--- a/src/openvpn/route.h
+++ b/src/openvpn/route.h
@@ -320,6 +320,7 @@  void setenv_routes(struct env_set *es, const struct route_list *rl);
 void setenv_routes_ipv6(struct env_set *es, const struct route_ipv6_list *rl6);
 
 bool is_special_addr(const char *addr_str);
+bool ipv6_is_special_addr(const char *addr_str);
 
 void get_default_gateway(struct route_gateway_info *rgi,
                          openvpn_net_ctx_t *ctx);