Reapplying client-ip NAT patch fixing the following issues raised by Arne
Schwabe:

    - Fixing TABs and whitespaces;
    - Added comments to the Client IP Marker.

Thanks

Rafael

--------

>From 6bc85f6ef89f27771c48e1e6d837302d5dad0910 Mon Sep 17 00:00:00 2001
From: vntraol <rafael.olive...@venturus.org.br>
List-Post: openvpn-devel@lists.sourceforge.net
Date: Wed, 4 May 2016 13:48:36 -0300
Subject: [PATCH] Allow the user to use the string 'client-ip' on the
 client-nat network configuration as a convenient way to use
 the leased IP address received from the OpenVPN server.

Usage example:

client-nat snat client-ip 255.255.255.255 172.20.1.15 # replaces the
'client-ip' string with the leased IP address received from the OpenVPN
server

Signed-off-by: vntraol <rafael.olive...@venturus.org.br>
---
 src/openvpn/clinat.c  |  168
++++++++++++++++++++++++++++++-------------------
 src/openvpn/clinat.h  |   24 ++++---
 src/openvpn/init.c    |    2 +
 src/openvpn/options.c |    1 +
 4 files changed, 124 insertions(+), 71 deletions(-)
 mode change 100644 => 100755 src/openvpn/clinat.c
 mode change 100644 => 100755 src/openvpn/clinat.h
 mode change 100644 => 100755 src/openvpn/init.c
 mode change 100644 => 100755 src/openvpn/options.c

diff --git a/src/openvpn/clinat.c b/src/openvpn/clinat.c
old mode 100644
new mode 100755
index ddefe12..b03dbf6
--- a/src/openvpn/clinat.c
+++ b/src/openvpn/clinat.c
@@ -37,7 +37,7 @@

 static bool
 add_entry(struct client_nat_option_list *dest,
-  const struct client_nat_entry *e)
+    const struct client_nat_entry *e)
 {
   if (dest->n >= MAX_CLIENT_NAT)
     {
@@ -61,15 +61,15 @@ print_client_nat_list(const struct
client_nat_option_list *list, int msglevel)
   if (list)
     {
       for (i = 0; i < list->n; ++i)
- {
-  const struct client_nat_entry *e = &list->entries[i];
-  msg (msglevel, "  CNAT[%d] t=%d %s/%s/%s",
-       i,
-       e->type,
-       print_in_addr_t (e->network, IA_NET_ORDER, &gc),
-       print_in_addr_t (e->netmask, IA_NET_ORDER, &gc),
-       print_in_addr_t (e->foreign_network, IA_NET_ORDER, &gc));
- }
+        {
+          const struct client_nat_entry *e = &list->entries[i];
+          msg (msglevel, "  CNAT[%d] t=%d %s/%s/%s",
+          i,
+          e->type,
+          print_in_addr_t (e->network, IA_NET_ORDER, &gc),
+          print_in_addr_t (e->netmask, IA_NET_ORDER, &gc),
+          print_in_addr_t (e->foreign_network, IA_NET_ORDER, &gc));
+        }
     }
   gc_free (&gc);
 }
@@ -93,23 +93,23 @@ clone_client_nat_option_list (const struct
client_nat_option_list *src, struct g

 void
 copy_client_nat_option_list (struct client_nat_option_list *dest,
-     const struct client_nat_option_list *src)
+                 const struct client_nat_option_list *src)
 {
   int i;
   for (i = 0; i < src->n; ++i)
     {
       if (!add_entry(dest, &src->entries[i]))
- break;
+        break;
     }
 }

 void
 add_client_nat_to_option_list (struct client_nat_option_list *dest,
-      const char *type,
-      const char *network,
-      const char *netmask,
-      const char *foreign_network,
-      int msglevel)
+                  const char *type,
+                  const char *network,
+                  const char *netmask,
+                  const char *foreign_network,
+                  int msglevel)
 {
   struct client_nat_entry e;
   bool ok;
@@ -124,12 +124,21 @@ add_client_nat_to_option_list (struct
client_nat_option_list *dest,
       return;
     }

-  e.network = getaddr(0, network, 0, &ok, NULL);
-  if (!ok)
+  if (network && !strcmp(network, "client-ip"))
     {
-      msg(msglevel, "client-nat: bad network: %s", network);
-      return;
+      // To be replaced later on with the leased IP Address received from
Openvpn Server.
+      e.network = CLIENT_IP_MARKER;
+    }
+  else
+    {
+      e.network = getaddr(0, network, 0, &ok, NULL);
+      if (!ok)
+        {
+          msg(msglevel, "client-nat: bad network: %s", network);
+          return;
+        }
     }
+
   e.netmask = getaddr(0, netmask, 0, &ok, NULL);
   if (!ok)
     {
@@ -184,8 +193,8 @@ print_pkt (struct openvpn_iphdr *iph, const char
*prefix, const int direction, c

 void
 client_nat_transform (const struct client_nat_option_list *list,
-      struct buffer *ipbuf,
-      const int direction)
+                  struct buffer *ipbuf,
+                  const int direction)
 {
   struct ip_tcp_udp_hdr *h = (struct ip_tcp_udp_hdr *) BPTR (ipbuf);
   int i;
@@ -202,64 +211,95 @@ client_nat_transform (const struct
client_nat_option_list *list,
     {
       const struct client_nat_entry *e = &list->entries[i]; /* current NAT
rule */
       if (e->type ^ direction)
- {
-  addr = *(addr_ptr = &h->ip.daddr);
-  amask = 2;
- }
+        {
+          addr = *(addr_ptr = &h->ip.daddr);
+          amask = 2;
+        }
       else
- {
-  addr = *(addr_ptr = &h->ip.saddr);
-  amask = 1;
- }
+        {
+          addr = *(addr_ptr = &h->ip.saddr);
+          amask = 1;
+        }
       if (direction)
- {
-  from = &e->foreign_network;
-  to = &e->network;
- }
+        {
+          from = &e->foreign_network;
+          to = &e->network;
+        }
       else
- {
-  from = &e->network;
-  to = &e->foreign_network;
- }
+        {
+          from = &e->network;
+          to = &e->foreign_network;
+        }

       if (((addr & e->netmask) == *from) && !(amask & alog))
- {
-  /* pre-adjust IP checksum */
-  ADD_CHECKSUM_32(accumulate, addr);
+        {
+          /* pre-adjust IP checksum */
+          ADD_CHECKSUM_32(accumulate, addr);

-  /* do NAT transform */
-  addr = (addr & ~e->netmask) | *to;
+          /* do NAT transform */
+          addr = (addr & ~e->netmask) | *to;

-  /* post-adjust IP checksum */
-  SUB_CHECKSUM_32(accumulate, addr);
+          /* post-adjust IP checksum */
+          SUB_CHECKSUM_32(accumulate, addr);

-  /* write the modified address to packet */
-  *addr_ptr = addr;
+          /* write the modified address to packet */
+          *addr_ptr = addr;

-  /* mark as modified */
-  alog |= amask;
- }
+          /* mark as modified */
+          alog |= amask;
+        }
     }
   if (alog)
     {
       if (check_debug_level (D_CLIENT_NAT))
- print_pkt (&h->ip, "AFTER", direction, D_CLIENT_NAT);
+        print_pkt (&h->ip, "AFTER", direction, D_CLIENT_NAT);

       ADJUST_CHECKSUM(accumulate, h->ip.check);

       if (h->ip.protocol == OPENVPN_IPPROTO_TCP)
- {
-  if (BLEN(ipbuf) >= sizeof(struct openvpn_iphdr) + sizeof(struct
openvpn_tcphdr))
-    {
-      ADJUST_CHECKSUM(accumulate, h->u.tcp.check);
-    }
- }
+        {
+          if (BLEN(ipbuf) >= sizeof(struct openvpn_iphdr) + sizeof(struct
openvpn_tcphdr))
+            {
+              ADJUST_CHECKSUM(accumulate, h->u.tcp.check);
+            }
+        }
       else if (h->ip.protocol == OPENVPN_IPPROTO_UDP)
- {
-  if (BLEN(ipbuf) >= sizeof(struct openvpn_iphdr) + sizeof(struct
openvpn_udphdr))
-    {
-      ADJUST_CHECKSUM(accumulate, h->u.udp.check);
-    }
- }
+        {
+          if (BLEN(ipbuf) >= sizeof(struct openvpn_iphdr) + sizeof(struct
openvpn_udphdr))
+            {
+              ADJUST_CHECKSUM(accumulate, h->u.udp.check);
+            }
+        }
     }
 }
+
+/*
+* Replaces the CLIENT_IP_MARKER with the leased IP address received from
OpenVPN Server.
+*/
+bool
+update_client_ip_nat(struct client_nat_option_list *dest, in_addr_t
local_ip)
+{
+  int i;
+  bool ret = false;
+
+  if (!dest)
+    return ret;
+
+  for (i=0; i <= dest->n; i++)
+    {
+      struct client_nat_entry *nat_entry = &dest->entries[i];
+      if (nat_entry && nat_entry->network == CLIENT_IP_MARKER)
+        {
+          struct in_addr addr;
+
+          nat_entry->network = ntohl(local_ip);
+          addr.s_addr = nat_entry->network;
+          char *dot_ip = inet_ntoa(addr);
+
+          msg (M_INFO, "CNAT - Updating NAT table from client-ip to: %s",
dot_ip);
+          ret = true;
+        }
+    }
+
+  return ret;
+}
diff --git a/src/openvpn/clinat.h b/src/openvpn/clinat.h
old mode 100644
new mode 100755
index a5779e1..8c84005
--- a/src/openvpn/clinat.h
+++ b/src/openvpn/clinat.h
@@ -32,6 +32,11 @@
 #define CN_OUTGOING 0
 #define CN_INCOMING 1

+/*
+  Used as a marker to replace with the leased IP address received from
OpenVPN server.
+*/
+#define CLIENT_IP_MARKER 0xFFFFFFFF
+
 struct client_nat_entry {
 # define CN_SNAT 0
 # define CN_DNAT 1
@@ -52,14 +57,19 @@ void copy_client_nat_option_list (struct
client_nat_option_list *dest, const str
 void print_client_nat_list(const struct client_nat_option_list *list, int
msglevel);

 void add_client_nat_to_option_list (struct client_nat_option_list *dest,
-    const char *type,
-    const char *network,
-    const char *netmask,
-    const char *foreign_network,
-    int msglevel);
+            const char *type,
+            const char *network,
+            const char *netmask,
+            const char *foreign_network,
+            int msglevel);

 void client_nat_transform (const struct client_nat_option_list *list,
-   struct buffer *ipbuf,
-   const int direction);
+        struct buffer *ipbuf,
+        const int direction);
+
+/*
+* Replaces the CLIENT_IP_MARKER with the leased IP address received from
OpenVPN Server.
+*/
+bool update_client_ip_nat(struct client_nat_option_list *dest, in_addr_t
local_ip);

 #endif
diff --git a/src/openvpn/init.c b/src/openvpn/init.c
old mode 100644
new mode 100755
index 42baf97..8359b29
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -1526,6 +1526,8 @@ do_open_tun (struct context *c)
        c->c1.tuntap->post_open_mtu,
        SET_MTU_TUN | SET_MTU_UPPER_BOUND);

+ update_client_ip_nat(c->options.client_nat, c->c1.tuntap->local);
+
       ret = true;
       static_context = c;
 #ifndef TARGET_ANDROID
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
old mode 100644
new mode 100755
index 764ca74..e81d525
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -223,6 +223,7 @@ static const char usage_message[] =
   "--redirect-private [flags]: Like --redirect-gateway, but omit actually
changing\n"
   "                  the default gateway.  Useful when pushing private
subnets.\n"
   "--client-nat snat|dnat network netmask alias : on client add 1-to-1 NAT
rule.\n"
+  "                  Set the network parameter to 'client-ip' to use the
received ip from OpenVPN Server.\n"
 #ifdef ENABLE_PUSH_PEER_INFO
   "--push-peer-info : (client only) push client info to server.\n"
 #endif
-- 
1.7.9.5



On Thu, Apr 28, 2016 at 1:20 PM, Arne Schwabe <a...@rfc2549.org> wrote:

> Am 28.04.16 um 04:01 schrieb Rafael Gava:
> > Hi Arne,
> >
> > what a surprise I thought that the NAT patch had been dropped. :-)
>
> More or less forgotten. IIrc the active FTP part was controversal. This
> part is okay.
>
> > So, please, should I change the code based on your comments and resend
> > the patch?
>
> Yes, please.
>
> Arne
>

Reply via email to