summaryrefslogtreecommitdiff
path: root/src/openvpn/clinat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvpn/clinat.c')
-rw-r--r--src/openvpn/clinat.c320
1 files changed, 167 insertions, 153 deletions
diff --git a/src/openvpn/clinat.c b/src/openvpn/clinat.c
index ddefe12..9158437 100644
--- a/src/openvpn/clinat.c
+++ b/src/openvpn/clinat.c
@@ -5,7 +5,7 @@
* packet encryption, packet authentication, and
* packet compression.
*
- * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -37,229 +37,243 @@
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)
+ if (dest->n >= MAX_CLIENT_NAT)
{
- msg (M_WARN, "WARNING: client-nat table overflow (max %d entries)", MAX_CLIENT_NAT);
- return false;
+ msg(M_WARN, "WARNING: client-nat table overflow (max %d entries)", MAX_CLIENT_NAT);
+ return false;
}
- else
+ else
{
- dest->entries[dest->n++] = *e;
- return true;
+ dest->entries[dest->n++] = *e;
+ return true;
}
}
void
print_client_nat_list(const struct client_nat_option_list *list, int msglevel)
{
- struct gc_arena gc = gc_new ();
- int i;
+ struct gc_arena gc = gc_new();
+ int i;
- msg (msglevel, "*** CNAT list");
- if (list)
+ msg(msglevel, "*** CNAT list");
+ 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));
- }
+ 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));
+ }
}
- gc_free (&gc);
+ gc_free(&gc);
}
struct client_nat_option_list *
-new_client_nat_list (struct gc_arena *gc)
+new_client_nat_list(struct gc_arena *gc)
{
- struct client_nat_option_list *ret;
- ALLOC_OBJ_CLEAR_GC (ret, struct client_nat_option_list, gc);
- return ret;
+ struct client_nat_option_list *ret;
+ ALLOC_OBJ_CLEAR_GC(ret, struct client_nat_option_list, gc);
+ return ret;
}
struct client_nat_option_list *
-clone_client_nat_option_list (const struct client_nat_option_list *src, struct gc_arena *gc)
+clone_client_nat_option_list(const struct client_nat_option_list *src, struct gc_arena *gc)
{
- struct client_nat_option_list *ret;
- ALLOC_OBJ_GC (ret, struct client_nat_option_list, gc);
- *ret = *src;
- return ret;
+ struct client_nat_option_list *ret;
+ ALLOC_OBJ_GC(ret, struct client_nat_option_list, gc);
+ *ret = *src;
+ return ret;
}
void
-copy_client_nat_option_list (struct client_nat_option_list *dest,
- const struct client_nat_option_list *src)
+copy_client_nat_option_list(struct client_nat_option_list *dest,
+ const struct client_nat_option_list *src)
{
- int i;
- for (i = 0; i < src->n; ++i)
+ int i;
+ for (i = 0; i < src->n; ++i)
{
- if (!add_entry(dest, &src->entries[i]))
- break;
+ if (!add_entry(dest, &src->entries[i]))
+ {
+ 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)
+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)
{
- struct client_nat_entry e;
- bool ok;
+ struct client_nat_entry e;
+ bool ok;
- if (!strcmp(type, "snat"))
- e.type = CN_SNAT;
- else if (!strcmp(type, "dnat"))
- e.type = CN_DNAT;
- else
+ if (!strcmp(type, "snat"))
{
- msg(msglevel, "client-nat: type must be 'snat' or 'dnat'");
- return;
+ e.type = CN_SNAT;
+ }
+ else if (!strcmp(type, "dnat"))
+ {
+ e.type = CN_DNAT;
+ }
+ else
+ {
+ msg(msglevel, "client-nat: type must be 'snat' or 'dnat'");
+ return;
}
- e.network = getaddr(0, network, 0, &ok, NULL);
- if (!ok)
+ e.network = getaddr(0, network, 0, &ok, NULL);
+ if (!ok)
{
- msg(msglevel, "client-nat: bad network: %s", network);
- return;
+ msg(msglevel, "client-nat: bad network: %s", network);
+ return;
}
- e.netmask = getaddr(0, netmask, 0, &ok, NULL);
- if (!ok)
+ e.netmask = getaddr(0, netmask, 0, &ok, NULL);
+ if (!ok)
{
- msg(msglevel, "client-nat: bad netmask: %s", netmask);
- return;
+ msg(msglevel, "client-nat: bad netmask: %s", netmask);
+ return;
}
- e.foreign_network = getaddr(0, foreign_network, 0, &ok, NULL);
- if (!ok)
+ e.foreign_network = getaddr(0, foreign_network, 0, &ok, NULL);
+ if (!ok)
{
- msg(msglevel, "client-nat: bad foreign network: %s", foreign_network);
- return;
+ msg(msglevel, "client-nat: bad foreign network: %s", foreign_network);
+ return;
}
- add_entry(dest, &e);
+ add_entry(dest, &e);
}
#if 0
static void
-print_checksum (struct openvpn_iphdr *iph, const char *prefix)
+print_checksum(struct openvpn_iphdr *iph, const char *prefix)
{
- uint16_t *sptr;
- unsigned int sum = 0;
- int i = 0;
- for (sptr = (uint16_t *)iph; (uint8_t *)sptr < (uint8_t *)iph + sizeof(struct openvpn_iphdr); sptr++)
+ uint16_t *sptr;
+ unsigned int sum = 0;
+ int i = 0;
+ for (sptr = (uint16_t *)iph; (uint8_t *)sptr < (uint8_t *)iph + sizeof(struct openvpn_iphdr); sptr++)
{
- i += 1;
- sum += *sptr;
+ i += 1;
+ sum += *sptr;
}
- msg (M_INFO, "** CKSUM[%d] %s %08x", i, prefix, sum);
+ msg(M_INFO, "** CKSUM[%d] %s %08x", i, prefix, sum);
}
#endif
static void
-print_pkt (struct openvpn_iphdr *iph, const char *prefix, const int direction, const int msglevel)
+print_pkt(struct openvpn_iphdr *iph, const char *prefix, const int direction, const int msglevel)
{
- struct gc_arena gc = gc_new ();
+ struct gc_arena gc = gc_new();
- char *dirstr = "???";
- if (direction == CN_OUTGOING)
- dirstr = "OUT";
- else if (direction == CN_INCOMING)
- dirstr = "IN";
+ char *dirstr = "???";
+ if (direction == CN_OUTGOING)
+ {
+ dirstr = "OUT";
+ }
+ else if (direction == CN_INCOMING)
+ {
+ dirstr = "IN";
+ }
+
+ msg(msglevel, "** CNAT %s %s %s -> %s",
+ dirstr,
+ prefix,
+ print_in_addr_t(iph->saddr, IA_NET_ORDER, &gc),
+ print_in_addr_t(iph->daddr, IA_NET_ORDER, &gc));
- msg(msglevel, "** CNAT %s %s %s -> %s",
- dirstr,
- prefix,
- print_in_addr_t (iph->saddr, IA_NET_ORDER, &gc),
- print_in_addr_t (iph->daddr, IA_NET_ORDER, &gc));
-
- gc_free (&gc);
+ gc_free(&gc);
}
void
-client_nat_transform (const struct client_nat_option_list *list,
- struct buffer *ipbuf,
- const int direction)
+client_nat_transform(const struct client_nat_option_list *list,
+ struct buffer *ipbuf,
+ const int direction)
{
- struct ip_tcp_udp_hdr *h = (struct ip_tcp_udp_hdr *) BPTR (ipbuf);
- int i;
- uint32_t addr, *addr_ptr;
- const uint32_t *from, *to;
- int accumulate = 0;
- unsigned int amask;
- unsigned int alog = 0;
+ struct ip_tcp_udp_hdr *h = (struct ip_tcp_udp_hdr *) BPTR(ipbuf);
+ int i;
+ uint32_t addr, *addr_ptr;
+ const uint32_t *from, *to;
+ int accumulate = 0;
+ unsigned int amask;
+ unsigned int alog = 0;
- if (check_debug_level (D_CLIENT_NAT))
- print_pkt (&h->ip, "BEFORE", direction, D_CLIENT_NAT);
+ if (check_debug_level(D_CLIENT_NAT))
+ {
+ print_pkt(&h->ip, "BEFORE", direction, D_CLIENT_NAT);
+ }
- for (i = 0; i < list->n; ++i)
+ for (i = 0; i < list->n; ++i)
{
- const struct client_nat_entry *e = &list->entries[i]; /* current NAT rule */
- if (e->type ^ direction)
- {
- addr = *(addr_ptr = &h->ip.daddr);
- amask = 2;
- }
- else
- {
- addr = *(addr_ptr = &h->ip.saddr);
- amask = 1;
- }
- if (direction)
- {
- from = &e->foreign_network;
- to = &e->network;
- }
- else
- {
- from = &e->network;
- to = &e->foreign_network;
- }
+ const struct client_nat_entry *e = &list->entries[i]; /* current NAT rule */
+ if (e->type ^ direction)
+ {
+ addr = *(addr_ptr = &h->ip.daddr);
+ amask = 2;
+ }
+ else
+ {
+ addr = *(addr_ptr = &h->ip.saddr);
+ amask = 1;
+ }
+ if (direction)
+ {
+ from = &e->foreign_network;
+ to = &e->network;
+ }
+ else
+ {
+ from = &e->network;
+ to = &e->foreign_network;
+ }
- if (((addr & e->netmask) == *from) && !(amask & alog))
- {
- /* pre-adjust IP checksum */
- ADD_CHECKSUM_32(accumulate, addr);
+ if (((addr & e->netmask) == *from) && !(amask & alog))
+ {
+ /* 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 (alog)
{
- if (check_debug_level (D_CLIENT_NAT))
- print_pkt (&h->ip, "AFTER", direction, D_CLIENT_NAT);
+ if (check_debug_level(D_CLIENT_NAT))
+ {
+ print_pkt(&h->ip, "AFTER", direction, D_CLIENT_NAT);
+ }
- ADJUST_CHECKSUM(accumulate, h->ip.check);
+ 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);
- }
- }
- 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 (h->ip.protocol == OPENVPN_IPPROTO_TCP)
+ {
+ 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);
+ }
+ }
}
}