Hello All, I'm looking forward to hearing from you guys a feedback if the patch for the features added to the NAT will be accepted or not or if is there anything else that I need to do or change in order to have it merged into the code.
>From the previous replies, it seems that a minor change was requested to replace the localhost string with client-ip. Anything else? Thanks in advance, Rafael On Tue, Aug 25, 2015 at 10:43 PM, Rafael Gava <gava...@gmail.com> wrote: > Hi, > > this is my first submission to the list and I hope that I'm doing in the > right way. :-) > > > Well, the features added to Network Address Translator are: > > 1) Allow the user to use the string "localhost" on the client-nat network > configuration in a way that is not necessary to inform the IP address > beforehand. Openvpn will set the dynamic received IP from DHCP. > Example: > > client-nat snat localhost 255.255.255.255 172.20.1.15 # replaces the > 'localhost' string with the DHCP address received from openvpn server. > > 2) Allow the user to enable the FTP NAT support through the > --enable-nat-ftp-support option. > This is useful for systems that don't have conntrack-tools support, for > example on Windows systems. On windows this feature is enabled by default. > > enable-nat-ftp-support (yes | no) > > > The following patch was written based on release/2.3 branch. > > -------------------------------------------------------------------------------------------------------------------------------------- > > From d11957a025dc6c113874e7b04ce4c8e9513c3b02 Mon Sep 17 00:00:00 2001 > From: venturus <venturus@venturus-virtual-machine.(none)> > Date: Thu, 13 Aug 2015 08:26:36 -0300 > Subject: [PATCH] Replaces the client-nat network string 'localhost' with > the > dynamic IP set to the tun/tap interface by the openvpn > server. Example: > > --client-nat snat localhost 255.255.255.255 172.20.1.15 # replaces the > 'localhost' string with the DHCP address received from openvpn server. > > Signed-off-by: Rafael Gava <rafael.olive...@venturus.org.br> > --- > src/openvpn/clinat.c | 57 > ++++++++++++++++++++++++++++++++++++++++++-------- > src/openvpn/clinat.h | 2 ++ > src/openvpn/init.c | 4 ++++ > 3 files changed, 54 insertions(+), 9 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 > > diff --git a/src/openvpn/clinat.c b/src/openvpn/clinat.c > old mode 100644 > new mode 100755 > index af75fc9..2460185 > --- a/src/openvpn/clinat.c > +++ b/src/openvpn/clinat.c > @@ -107,11 +107,11 @@ copy_client_nat_option_list (struct > client_nat_option_list *dest, > > 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; > @@ -126,12 +126,19 @@ 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, "localhost")) > { > - msg(msglevel, "client-nat: bad network: %s", network); > - return; > + msg (M_INFO, "*** client-nat localhost detected..."); > + e.network = 0xFFFFFFFF; > + } 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) > { > @@ -148,6 +155,7 @@ add_client_nat_to_option_list (struct > client_nat_option_list *dest, > add_entry(dest, &e); > } > > + > #if 0 > static void > print_checksum (struct openvpn_iphdr *iph, const char *prefix) > @@ -266,4 +274,35 @@ client_nat_transform (const struct > client_nat_option_list *list, > } > } > > +/* > +* Replaces the localhost token with the IP received from OpenVPN > +*/ > +bool > +update_localhost_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 == 0xFFFFFFFF) > + { > + 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, "Updating NAT table from localhost to: %s", > dot_ip); > + ret = true; > + } > + } > + > + return ret; > +} > + > #endif > diff --git a/src/openvpn/clinat.h b/src/openvpn/clinat.h > old mode 100644 > new mode 100755 > index d55a727..ce995d9 > --- a/src/openvpn/clinat.h > +++ b/src/openvpn/clinat.h > @@ -62,4 +62,6 @@ void client_nat_transform (const struct > client_nat_option_list *list, > struct buffer *ipbuf, > const int direction); > > +bool update_localhost_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 71c91a2..4a63ee8 > --- a/src/openvpn/init.c > +++ b/src/openvpn/init.c > @@ -1476,6 +1476,10 @@ do_open_tun (struct context *c) > c->c1.tuntap->post_open_mtu, > SET_MTU_TUN | SET_MTU_UPPER_BOUND); > > +#ifdef ENABLE_CLIENT_NAT > + update_localhost_nat(c->options.client_nat, c->c1.tuntap->local); > +#endif > + > ret = true; > static_context = c; > } > -- > 1.7.9.5 > > > From 18b1411689df67feafeb15630c3519ab2cbd42d4 Mon Sep 17 00:00:00 2001 > From: Rafael Gava <rafael.olive...@venturus.org.br> > Date: Fri, 14 Aug 2015 15:27:50 -0300 > Subject: [PATCH] Added FTP NAT support. This feature can be enabled via > --enable-nat-ftp-support option. > > > Signed-off-by: Rafael Gava <rafael.olive...@venturus.org.br> > --- > src/openvpn/clinat.c | 773 > ++++++++++++++++++++++++++++++++++++++++++++++--- > src/openvpn/clinat.h | 15 +- > src/openvpn/forward.c | 75 ++--- > src/openvpn/options.c | 12 + > src/openvpn/options.h | 1 + > 5 files changed, 787 insertions(+), 89 deletions(-) > mode change 100644 => 100755 src/openvpn/forward.c > mode change 100644 => 100755 src/openvpn/options.c > mode change 100644 => 100755 src/openvpn/options.h > > diff --git a/src/openvpn/clinat.c b/src/openvpn/clinat.c > index 2460185..1d213f5 100755 > --- a/src/openvpn/clinat.c > +++ b/src/openvpn/clinat.c > @@ -36,6 +36,159 @@ > #include "proto.h" > #include "socket.h" > #include "memdbg.h" > +#include <stdio.h> > +#include <ctype.h> > +#include <string.h> > + > +/* Delta Table Types */ > + > +typedef struct delta_table_key { > + uint32_t src_addr; > + uint32_t dest_addr; > + uint16_t src_port; > + uint16_t dest_port; > +} delta_table_key_t; > + > +typedef struct delta_table_entry { > + delta_table_key_t key; > + uint16_t delta_out; > + uint16_t delta_in; > + uint8_t marked_to_remove; > + uint8_t reserved[3]; > + uint32_t timestamp; > + struct delta_table_entry *_next; > +} delta_table_entry_t; > + > +typedef struct delta_table { > + struct delta_table_entry *head; > +} delta_table_t; > + > + > +// Global delta table > +//#define DEBUG_DELTA 1 > + > +delta_table_t *table = NULL; > + > +#define TIME_TO_RESPOND 60 * 5 // 5 Minutes > +#define TIME_TO_LIVE 24 * 60 * 60 > + > +/* Delta Table Functions */ > + > +// In seconds, since epoch > +static uint32_t > +get_timestamp() { > + return (uint32_t)time(NULL); > +} > + > +static void > +print_delta_table_entries(delta_table_t *table) { > + delta_table_entry_t *current = table->head; > + > + if (current == NULL) { > + return; > + } > + > + while (current != NULL) { > + printf("from %d -> to %d: removed: %s, timestamp: %d, delta_out: %d, > delta_in: %d\n", > + current->key.src_addr, current->key.dest_addr, > current->marked_to_remove ? "true" : "false", > + current->timestamp, current->delta_out, current->delta_in); > + current = current->_next; > + } > +} > + > +static struct delta_table * > +init_delta_table() { > + delta_table_t *table = malloc(sizeof(delta_table_t)); > + table->head = NULL; > + return table; > +} > + > +static struct delta_table_entry * > +add_delta_entry(delta_table_t *table, delta_table_entry_t > *new_delta_entry) { > + if (table->head == NULL) { > + table->head = new_delta_entry; > + table->head->_next = NULL; > + } else { > + // Add element to HEAD, for performance gain > + new_delta_entry->_next = table->head; > + table->head = new_delta_entry; > + } > + return new_delta_entry; > +} > + > +static int > +remove_delta_entry(delta_table_t *table, delta_table_entry_t > *delta_entry) { > + delta_table_entry_t *current = table->head; > + delta_table_entry_t *before = NULL; > + uint8_t found = 0; > + > + //msg (M_INFO, "On remove_delta_entry - entry: %p", &delta_entry); > + > + while (current != NULL) { > + if(current == delta_entry) { > + found = 1; > + break; > + } > + before = current; > + current = current->_next; > + } > + > + //Element not found > + if (!found) { > + return 0; > + } > + > + if(before==NULL){ > + table->head = table->head->_next; > + } else { > + before->_next = delta_entry->_next; > + } > + > + //msg (M_INFO, "On remove_delta_entry - entry: %p - freed", > &delta_entry); > + > + free(delta_entry); > + return 1; > +} > + > +static struct delta_table_entry * > +get_delta_entry(delta_table_t *table, delta_table_key_t key) { > + delta_table_entry_t *current = table->head; > + delta_table_entry_t *aux = NULL; > + delta_table_entry_t *el = NULL; > + > + while (current != NULL) { > + // Check TTL and Timeout > + if ((current->marked_to_remove && get_timestamp() - > current->timestamp >= TIME_TO_RESPOND) /* || get_timestamp() - > current->timestamp >= TIME_TO_LIVE */){ > + aux = current; > + //If the CURRENT is to be removed, then dont return it > + if (aux == el) { > + el = NULL; > + } > + current = current->_next; > + remove_delta_entry(table, aux); > + } else { > + if (( > + // Regular connection > + (current->key.src_addr == key.src_addr && > + current->key.src_port == key.src_port && > + current->key.dest_addr == key.dest_addr && > + current->key.dest_port == key.dest_port) || > + //Check if it is a returned connection > + (current->key.dest_addr == key.src_addr && > + current->key.dest_port == key.src_port && > + current->key.src_addr == key.dest_addr && > + current->key.src_port == key.dest_port))) { > + el = current; > + } > + current = current->_next; > + } > + } > + > + return el; > +} > + > +/* Delta Table Functions End */ > + > > static bool > add_entry(struct client_nat_option_list *dest, > @@ -192,19 +345,533 @@ print_pkt (struct openvpn_iphdr *iph, const char > *prefix, const int direction, c > gc_free (&gc); > } > > +#if DEBUG_DELTA > + > +#ifndef HEXDUMP_COLS > +#define HEXDUMP_COLS 8 > +#endif > + > +static void hexdump(void *mem, unsigned int len) > +{ > + unsigned int i, j; > + > + for(i = 0; i < len + ((len % HEXDUMP_COLS) ? (HEXDUMP_COLS - len % > HEXDUMP_COLS) : 0); i++) > + { > + /* print offset */ > + if(i % HEXDUMP_COLS == 0) > + { > + printf("0x%06x: ", i); > + } > + > + /* print hex data */ > + if(i < len) > + { > + printf("%02x ", 0xFF & ((char*)mem)[i]); > + } > + else /* end of block, just aligning for ASCII dump */ > + { > + printf(" "); > + } > + > + /* print ASCII dump */ > + if(i % HEXDUMP_COLS == (HEXDUMP_COLS - 1)) > + { > + for(j = i - (HEXDUMP_COLS - 1); j <= i; j++) > + { > + unsigned char ch = 0xFF & ((char*)mem)[j]; > + > + if(j >= len) /* end of block, not really printing */ > + { > + putchar(' '); > + } > + else if (ch >= 0x80) > + { > + putchar('.'); > + } > + else if(isprint(((char*)mem)[j])) /* printable char */ > + { > + putchar(0xFF & ((char*)mem)[j]); > + } > + else /* other char */ > + { > + putchar('.'); > + } > + } > + putchar('\n'); > + } > + } > +} > +#endif > + > +static int try_number(const char *data, size_t dlen, uint32_t array[], > + int array_size, char sep, char term) > +{ > + uint32_t i, len; > + > + memset(array, 0, sizeof(array[0])*array_size); > + > + /* Keep data pointing at next char. */ > + for (i = 0, len = 0; len < dlen && i < array_size; len++, data++) { > + if (*data >= '0' && *data <= '9') { > + array[i] = array[i]*10 + *data - '0'; > + } > + else if (*data == sep) > + i++; > + else { > + /* Unexpected character; true if it's the > + terminator and we're finished. */ > + if (*data == term && i == array_size - 1) > + return len; > + > + msg (M_ERRNO, "CNAT - try_number - Char %u (got %u nums) `%u' > unexpected\n", len, i, *data); > + return 0; > + } > + } > + > + msg (M_ERRNO, "CNAT - ERROR: Failed to fill %u numbers separated by > %c\n", array_size, sep); > + > + return 0; > +} > + > +static int try_rfc959(const char *, size_t, u_int32_t [], char); > + > +static struct ftp_search { > + int direction; > + const char *pattern; > + size_t plen; > + char skip; > + char term; > + int (*getnum)(const char *, size_t, u_int32_t[], char); > +} search[] = { > + { > + CN_OUTGOING, > + "PORT", sizeof("PORT") - 1, ' ', '\r', > + try_rfc959, > + }, > + { > + CN_INCOMING, > + "227 ", sizeof("227 ") - 1, '(', ')', > + try_rfc959, > + }, > +}; > + > + > +/* Returns 0, or length of numbers: 192,168,1,1,5,6 */ > +static int > +try_rfc959(const char *data, size_t dlen, u_int32_t array[6], > + char term) > +{ > + return try_number(data, dlen, array, 6, ',', term); > +} > + > +/* Grab port: number up to delimiter */ > +static int > +get_port(const char *data, int start, size_t dlen, char delim, > + u_int32_t array[2]) > +{ > + u_int16_t port = 0; > + int i; > + > + for (i = start; i < dlen; i++) { > + /* Finished? */ > + if (data[i] == delim) { > + if (port == 0) > + break; > + array[0] = port >> 8; > + array[1] = port; > + return i + 1; > + } > + else if (data[i] >= '0' && data[i] <= '9') > + port = port*10 + data[i] - '0'; > + else /* Some other crap */ > + break; > + } > + return 0; > +} > + > +/* Return 1 for match, 0 for accept, -1 for partial. */ > +static int > +find_pattern(const char *data, size_t dlen, > + const char *pattern, size_t plen, > + char skip, char term, > + unsigned int *numoff, > + unsigned int *numlen, > + u_int32_t array[6], > + int (*getnum)(const char *, size_t, u_int32_t[], char)) > +{ > + size_t i; > + > + if (check_debug_level (D_CLIENT_NAT)) > + msg (M_INFO, "CNAT - find_pattern %s: dlen = %u\n", pattern, dlen); > + > + if (dlen == 0) > + return 0; > + > + if (dlen <= plen) { > + /* Short packet: try for partial? */ > + if (strncasecmp(data, pattern, dlen) == 0) > + return -1; > + else return 0; > + } > + > + if (strncasecmp(data, pattern, plen) != 0) { > + return 0; > + } > + > + if (check_debug_level (D_CLIENT_NAT)) > + msg (M_INFO, "CNAT - Pattern matches!\n"); > + > + /* Now we've found the constant string, try to skip > + to the 'skip' character */ > + for (i = plen; data[i] != skip; i++) > + if (i == dlen - 1) return -1; > + > + /* Skip over the last character */ > + i++; > + > + if (check_debug_level (D_CLIENT_NAT)) > + msg (M_INFO, "CNAT - Skipped up to `%c'!\n", skip); > + > + *numoff = i; > + *numlen = getnum(data + i, dlen - i, array, term); > + if (!*numlen) > + return -1; > + > + if (check_debug_level (D_CLIENT_NAT)) > + msg (M_INFO, "CNAT - Match succeeded!\n"); > + > + return 1; > +} > + > +static uint16_t > +tcp_checksum (const uint8_t *buf, > + const int len_tcp, > + const uint32_t src_addr, > + const uint32_t dest_addr) > +{ > + uint16_t word16; > + uint32_t sum = 0; > + int i; > + uint8_t * psrc_addr = (uint8_t *) &src_addr; > + uint8_t * pdest_addr = (uint8_t *) &dest_addr; > + > + /* make 16 bit words out of every two adjacent 8 bit words and */ > + /* calculate the sum of all 16 bit words */ > + for (i = 0; i < len_tcp; i += 2){ > + word16 = ((buf[i] << 8) & 0xFF00) + ((i + 1 < len_tcp) ? (buf[i+1] & > 0xFF) : 0); > + sum += word16; > + } > + > + /* add the TCP pseudo header which contains the IP source and > destination addresses */ > + for (i = 0; i < 4; i += 2){ > + word16 =((psrc_addr[i] << 8) & 0xFF00) + (psrc_addr[i+1] & 0xFF); > + sum += word16; > + } > + for (i = 0; i < 4; i += 2){ > + word16 =((pdest_addr[i] << 8) & 0xFF00) + (pdest_addr[i+1] & 0xFF); > + sum += word16; > + } > + > + /* the protocol number and the length of the TCP packet */ > + sum += (uint16_t) OPENVPN_IPPROTO_TCP + (uint16_t) len_tcp; > + > + /* keep only the last 16 bits of the 32 bit calculated sum and add the > carries */ > + while (sum >> 16) > + sum = (sum & 0xFFFF) + (sum >> 16); > + > + /* Take the one's complement of sum */ > + return ((uint16_t) ~sum); > +} > + > +static uint16_t > +ip_checksum(const void *buf, uint16_t hdr_len) { > + unsigned long sum = 0; > + const uint16_t *ip1; > + > + ip1 = buf; > + while (hdr_len > 1) { > + sum += *ip1++; > + if (sum & 0x80000000) > + sum = (sum & 0xFFFF) + (sum >> 16); > + hdr_len -= 2; > + } > + > + while (sum >> 16) > + sum = (sum & 0xFFFF) + (sum >> 16); > + > + return(~sum); > +} > + > +static int > +client_nat_ftp_transform(struct buffer *ipbuf, > + const int direction, const uint32_t from_address, uint32_t > replace_address) { > + > + uint32_t array[6] = {0}; > + int ret = 0; > + int data_len = 0; > + > + struct ip_tcp_udp_hdr *hdr = (struct ip_tcp_udp_hdr *) BPTR (ipbuf); > + > + if (hdr->ip.protocol != OPENVPN_IPPROTO_TCP) > + return ret; > + > + if (table == NULL) > + table = init_delta_table(); > + > + delta_table_entry_t *entry = NULL; > + delta_table_key_t delta_key; > + > + // Because the address already was NATed, probably on OpenVPN Server > + if (direction == CN_OUTGOING) > + delta_key.src_addr = from_address; > + else if (direction == CN_INCOMING) > + delta_key.src_addr = hdr->ip.saddr; > + > + delta_key.src_port = hdr->u.tcp.source; > + delta_key.dest_addr = hdr->ip.daddr; > + delta_key.dest_port = hdr->u.tcp.dest; > + > +#if DEBUG_DELTA > + msg (M_INFO, "delta_key - saddr: %d, sport: %d, daddr: %d, dport: %d", > + delta_key.src_addr, delta_key.src_port, delta_key.dest_addr, > delta_key.dest_port); > + > + msg (M_INFO, "seq: %x, ack: %x", > + hdr->u.tcp.seq, hdr->u.tcp.ack_seq); > +#endif > + > + int tcp_data_offset = OPENVPN_TCPH_GET_DOFF (hdr->u.tcp.doff_res); > + > + struct buffer tcpbuf = *ipbuf; > + if (!buf_advance (&tcpbuf, sizeof(struct openvpn_iphdr) + > tcp_data_offset)) > + return ret; > + > + uint8_t * tcp_data = (uint8_t *) BPTR (&tcpbuf); > + > +#if DEBUG_DELTA > + msg (M_INFO, "TCP DATA BEFORE NAT:"); > + hexdump(tcp_data, BLEN(&tcpbuf)); > +#endif > + > + u_int32_t matchlen, matchoff; > + int found_pattern = -1; > + int i = 0; > + > + for (i = 0; i < sizeof(search) / sizeof(search[0]); i++) { > + if (search[i].direction != direction) continue; > + > + found_pattern = find_pattern(tcp_data, BLEN(&tcpbuf), > + search[i].pattern, > + search[i].plen, > + search[i].skip, > + search[i].term, > + &matchoff, &matchlen, > + array, > + search[i].getnum); > + if (found_pattern) break; > + } > + > + if (found_pattern > 0) > + { > + > + if (check_debug_level (D_CLIENT_NAT)) > + { > + msg (M_INFO, "client-nat FTP match: %.*s - data: %.*s\n", > + matchoff, tcp_data, matchlen, &tcp_data[matchoff]); > + } > + > + data_len = BLEN(&tcpbuf) - matchoff; > + > + uint32_t ip = htonl((array[0] << 24) | (array[1] << 16) > + | (array[2] << 8) | array[3]); > + uint16_t port = htons(array[4] << 8 | array[5]); > + uint8_t * addr_tmp = (uint8_t *) &replace_address; > + > + uint8_t new_tcp_data[32]; > + memset(&new_tcp_data[0], 0, sizeof(new_tcp_data)); > + > + int new_len = sprintf((char *) &new_tcp_data[0], > "%d,%d,%d,%d,%d,%d%.*s", > + addr_tmp[0], addr_tmp[1], addr_tmp[2], addr_tmp[3], array[4], > array[5], > + data_len - matchlen, (char *)&tcp_data[matchoff + matchlen]); > + > + if (check_debug_level (D_CLIENT_NAT)) > + { > + msg (M_INFO, "client-nat replaced address from: %.*s to: > %.*s\n", > + data_len, &tcp_data[matchoff], new_len, &new_tcp_data[0]); > + } > + > + //If the new len is greater than the old, there will be there an > adjustment > + if (new_len > data_len) > + { > + //If the entry already exists > + if (entry = get_delta_entry(table, delta_key)) > + { > + if (direction == CN_OUTGOING) > + { > + hdr->u.tcp.seq = htonl(ntohl(hdr->u.tcp.seq) + > (entry->delta_out)); // Need to update seq and ack > + hdr->u.tcp.ack_seq = htonl(ntohl(hdr->u.tcp.ack_seq) - > entry->delta_in); > + entry->delta_out += new_len - data_len; > + } > + else > + { > + hdr->u.tcp.seq = htonl(ntohl(hdr->u.tcp.seq) + > (entry->delta_in)); // Need to update seq and ack > + hdr->u.tcp.ack_seq = htonl(ntohl(hdr->u.tcp.ack_seq) - > entry->delta_out); > + entry->delta_in += new_len - data_len; > + } > + //Update timestamp entry on delta entry, to keep this delta > alive > + entry->timestamp = get_timestamp(); > + } > + else > + { > + // No entry found. Add a new one. > + entry = malloc(sizeof(delta_table_entry_t)); > + entry->key = delta_key; > + > + if (direction == CN_OUTGOING) > + { > + entry->delta_out = new_len - data_len; > + entry->delta_in = 0; > + } > + else > + { > + entry->delta_in = new_len - data_len; > + entry->delta_out = 0; > + } > + entry->marked_to_remove = 0; > + entry->timestamp = get_timestamp(); > + > + //Add it to delta table > + add_delta_entry(table, entry); > + } > + > +#if DEBUG_DELTA > + print_delta_table_entries(table); > +#endif > + > + //Increase the tcpbuf and ipbuf reflecting the delta chars > added to the segment. > + ASSERT(buf_inc_len(&tcpbuf, new_len - data_len)); > + ASSERT(buf_inc_len(ipbuf, new_len - data_len)); > + > + //Update tot_len > + hdr->ip.tot_len = htons(ntohs(hdr->ip.tot_len) + (new_len - > data_len)); > + > + // Readjust IP Checksum > + uint16_t head_len = OPENVPN_IPH_GET_LEN(hdr->ip.version_len); > + hdr->ip.check = 0; > + uint16_t check = ip_checksum( BPTR (ipbuf), head_len); > + hdr->ip.check = check; > + > + //Use new_len here! > + memcpy(&tcp_data[matchoff], new_tcp_data, new_len); > + } > + else > + { > + // The replace size is the lesser or iqual the original? Pad > with 0 if necessary. > + memcpy(&tcp_data[matchoff], new_tcp_data, data_len); > + > + //If the entry already exists > + if (entry = get_delta_entry(table, delta_key)) > + { > + if (direction == CN_OUTGOING) > + { > + hdr->u.tcp.seq = htonl(ntohl(hdr->u.tcp.seq) + > (entry->delta_out)); // Need to update seq and ack > + hdr->u.tcp.ack_seq = htonl(ntohl(hdr->u.tcp.ack_seq) - > entry->delta_in); > + } > + else > + { > + hdr->u.tcp.seq = htonl(ntohl(hdr->u.tcp.seq) + > (entry->delta_in)); // Need to update seq and ack > + hdr->u.tcp.ack_seq = htonl(ntohl(hdr->u.tcp.ack_seq) - > entry->delta_out); > + } > + //Update timestamp entry on delta entry, to keep this delta > alive > + entry->timestamp = get_timestamp(); > + } > + > + } > + > + //Update TCP checksum > + hdr->u.tcp.check = 0; > + > + uint16_t tot_len = ntohs(hdr->ip.tot_len); > + uint16_t head_len = OPENVPN_IPH_GET_LEN(hdr->ip.version_len); > + > + uint16_t check = tcp_checksum(BPTR (ipbuf) + head_len, > + tot_len - head_len, hdr->ip.saddr, hdr->ip.daddr); > + > + hdr->u.tcp.check = htons(check); > + ret = 1; > + } > + else > + { > + //No pattern found. Check if there is a delta entry for this > connection > + if(entry = get_delta_entry(table, delta_key)) > + { > + if (direction == CN_OUTGOING) > + { > + hdr->u.tcp.seq = htonl(ntohl(hdr->u.tcp.seq) + > entry->delta_out); > + hdr->u.tcp.ack_seq = htonl(ntohl(hdr->u.tcp.ack_seq) - > entry->delta_in); > + } > + else > + { > + hdr->u.tcp.seq = htonl(ntohl(hdr->u.tcp.seq) + > entry->delta_in); > + hdr->u.tcp.ack_seq = htonl(ntohl(hdr->u.tcp.ack_seq) - > entry->delta_out); > + } > + > + //Update TCP checksum > + hdr->u.tcp.check = 0; > + > + uint16_t tot_len = ntohs(hdr->ip.tot_len); > + uint16_t head_len = OPENVPN_IPH_GET_LEN(hdr->ip.version_len); > + > + uint16_t check = tcp_checksum(BPTR (ipbuf) + head_len, > + tot_len - head_len, hdr->ip.saddr, hdr->ip.daddr); > + > + hdr->u.tcp.check = htons(check); > + > + //Update timestamp entry on delta entry > + entry->timestamp = get_timestamp(); > + > + // If it is a FIN package, then remove entry from delta table > + if (OPENVPN_TCPH_FIN_MASK & hdr->u.tcp.flags) > + { > + entry->marked_to_remove = 1; > + msg (M_INFO, "Delta marked to be removed!"); > + } > + > + ret = 1; > + } > + else > + { > +#if DEBUG_DELTA > + // Regular package! > + msg (M_INFO, "Regular package!: tot_len %d, seq %x, ack %x\n", > ntohs(hdr->ip.tot_len), ntohl(hdr->u.tcp.seq), ntohl(hdr->u.tcp.ack_seq)); > +#endif > + } > + } > + > +#if DEBUG_DELTA > + msg (M_INFO, "TCP DATA AFTER NAT:"); > + hexdump(tcp_data, BLEN(&tcpbuf)); > +#endif > + > + return ret; > +} > + > void > client_nat_transform (const struct client_nat_option_list *list, > - struct buffer *ipbuf, > - const int direction) > + struct buffer *ipbuf, > + const int direction, > + const bool enable_nat_ftp_support) > { > struct ip_tcp_udp_hdr *h = (struct ip_tcp_udp_hdr *) BPTR (ipbuf); > int i; > - uint32_t addr, *addr_ptr; > + uint32_t addr, *addr_ptr, from_addr; > const uint32_t *from, *to; > int accumulate = 0; > unsigned int amask; > unsigned int alog = 0; > > + uint32_t orig_saddr = h->ip.saddr; > + uint32_t orig_daddr = h->ip.daddr; > + > if (check_debug_level (D_CLIENT_NAT)) > print_pkt (&h->ip, "BEFORE", direction, D_CLIENT_NAT); > > @@ -212,65 +879,81 @@ 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); > + { > + from_addr = *from; > + > + /* 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); > + } > + > + uint32_t repl_addr = addr; > + > + if (amask == 2) > + { > + if (direction) > + repl_addr = orig_saddr; > + else > + repl_addr = orig_daddr; > + } > + > + if (enable_nat_ftp_support) > + client_nat_ftp_transform(ipbuf, direction, from_addr, > repl_addr); > + > + } > 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); > + } > + } > } > } > > @@ -297,7 +980,7 @@ update_localhost_nat(struct client_nat_option_list > *dest, in_addr_t local_ip) > addr.s_addr = nat_entry->network; > char *dot_ip = inet_ntoa(addr); > > - msg (M_INFO, "Updating NAT table from localhost to: %s", > dot_ip); > + msg (M_INFO, "CNAT - Updating NAT table from localhost to: %s", > dot_ip); > ret = true; > } > } > diff --git a/src/openvpn/clinat.h b/src/openvpn/clinat.h > index ce995d9..a58da5d 100755 > --- a/src/openvpn/clinat.h > +++ b/src/openvpn/clinat.h > @@ -52,15 +52,16 @@ 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, > + const bool enable_nat_ftp_support); > > bool update_localhost_nat(struct client_nat_option_list *dest, in_addr_t > local_ip); > > diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c > old mode 100644 > new mode 100755 > index 217fbb3..615db7a > --- a/src/openvpn/forward.c > +++ b/src/openvpn/forward.c > @@ -980,9 +980,6 @@ process_incoming_tun (struct context *c) > > perf_push (PERF_PROC_IN_TUN); > > - if (c->c2.buf.len > 0) > - c->c2.tun_read_bytes += c->c2.buf.len; > - > #ifdef LOG_RW > if (c->c2.log_rw && c->c2.buf.len > 0) > fprintf (stderr, "r"); > @@ -999,6 +996,9 @@ process_incoming_tun (struct context *c) > */ > process_ip_header (c, PIPV4_PASSTOS|PIP_MSSFIX|PIPV4_CLIENT_NAT, > &c->c2.buf); > > + if (c->c2.buf.len > 0) > + c->c2.tun_read_bytes += c->c2.buf.len; > + > #ifdef PACKET_TRUNCATION_CHECK > /* if (c->c2.buf.len > 1) --c->c2.buf.len; */ > ipv4_packet_size_verify (BPTR (&c->c2.buf), > @@ -1041,43 +1041,44 @@ process_ip_header (struct context *c, unsigned int > flags, struct buffer *buf) > #else > if (flags & PIP_MSSFIX) > #endif > - { > - struct buffer ipbuf = *buf; > - if (is_ipv4 (TUNNEL_TYPE (c->c1.tuntap), &ipbuf)) > - { > -#if PASSTOS_CAPABILITY > - /* extract TOS from IP header */ > - if (flags & PIPV4_PASSTOS) > - link_socket_extract_tos (c->c2.link_socket, &ipbuf); > -#endif > - > - /* possibly alter the TCP MSS */ > - if (flags & PIP_MSSFIX) > - mss_fixup_ipv4 (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC > (&c->c2.frame))); > + { > + if (is_ipv4 (TUNNEL_TYPE (c->c1.tuntap), buf)) > + { > > #ifdef ENABLE_CLIENT_NAT > - /* possibly do NAT on packet */ > - if ((flags & PIPV4_CLIENT_NAT) && c->options.client_nat) > - { > - const int direction = (flags & PIPV4_OUTGOING) ? CN_INCOMING : > CN_OUTGOING; > - client_nat_transform (c->options.client_nat, &ipbuf, direction); > - } > + /* possibly do NAT on packet */ > + if ((flags & PIPV4_CLIENT_NAT) && c->options.client_nat) > + { > + const int direction = (flags & PIPV4_OUTGOING) ? > CN_INCOMING : CN_OUTGOING; > + client_nat_transform(c->options.client_nat, buf, > direction, c->options.enable_nat_ftp_support); > + } > #endif > - /* possibly extract a DHCP router message */ > - if (flags & PIPV4_EXTRACT_DHCP_ROUTER) > - { > - const in_addr_t dhcp_router = dhcp_extract_router_msg (&ipbuf); > - if (dhcp_router) > - route_list_add_vpn_gateway (c->c1.route_list, c->c2.es, dhcp_router); > - } > - } > - else if (is_ipv6 (TUNNEL_TYPE (c->c1.tuntap), &ipbuf)) > - { > - /* possibly alter the TCP MSS */ > - if (flags & PIP_MSSFIX) > - mss_fixup_ipv6 (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC > (&c->c2.frame))); > - } > - } > + > +#if PASSTOS_CAPABILITY > + /* extract TOS from IP header */ > + if (flags & PIPV4_PASSTOS) > + link_socket_extract_tos (c->c2.link_socket, buf); > +#endif > + > + /* possibly alter the TCP MSS */ > + if (flags & PIP_MSSFIX) > + mss_fixup_ipv4 (buf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC > (&c->c2.frame))); > + > + /* possibly extract a DHCP router message */ > + if (flags & PIPV4_EXTRACT_DHCP_ROUTER) > + { > + const in_addr_t dhcp_router = dhcp_extract_router_msg > (buf); > + if (dhcp_router) > + route_list_add_vpn_gateway (c->c1.route_list, c-> > c2.es, dhcp_router); > + } > + } > + else if (is_ipv6 (TUNNEL_TYPE (c->c1.tuntap), buf)) > + { > + /* possibly alter the TCP MSS */ > + if (flags & PIP_MSSFIX) > + mss_fixup_ipv6 (buf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC > (&c->c2.frame))); > + } > + } > } > } > > diff --git a/src/openvpn/options.c b/src/openvpn/options.c > old mode 100644 > new mode 100755 > index 007bd8c..73b615a > --- a/src/openvpn/options.c > +++ b/src/openvpn/options.c > @@ -236,6 +236,7 @@ static const char usage_message[] = > " the default gateway. Useful when pushing private > subnets.\n" > #ifdef ENABLE_CLIENT_NAT > "--client-nat snat|dnat network netmask alias : on client add 1-to-1 > NAT rule.\n" > + "--enable-nat-ftp-support : Enable NAT FTP Support, updating the IP > address on FTP PORT commands or PASV responses\n" > #endif > #ifdef ENABLE_PUSH_PEER_INFO > "--push-peer-info : (client only) push client info to server.\n" > @@ -789,6 +790,11 @@ init_options (struct options *o, const bool init_gc) > o->max_routes = MAX_ROUTES_DEFAULT; > o->resolve_retry_seconds = RESOLV_RETRY_INFINITE; > o->proto_force = -1; > + > +#ifdef ENABLE_CLIENT_NAT > + o->enable_nat_ftp_support = false; > +#endif > + > #ifdef ENABLE_OCC > o->occ = true; > #endif > @@ -1535,6 +1541,8 @@ show_settings (const struct options *o) > #ifdef ENABLE_CLIENT_NAT > if (o->client_nat) > print_client_nat_list(o->client_nat, D_SHOW_PARMS); > + > + SHOW_BOOL(enable_nat_ftp_support); > #endif > > #ifdef ENABLE_MANAGEMENT > @@ -5287,6 +5295,10 @@ add_option (struct options *options, > cnol_check_alloc (options); > add_client_nat_to_option_list(options->client_nat, p[1], p[2], > p[3], p[4], msglevel); > } > + else if (streq (p[0], "enable_nat_ftp_support")) > + { > + options->enable_nat_ftp_support = true; > + } > #endif > else if (streq (p[0], "route") && p[1]) > { > diff --git a/src/openvpn/options.h b/src/openvpn/options.h > old mode 100644 > new mode 100755 > index af9a47f..2b27368 > --- a/src/openvpn/options.h > +++ b/src/openvpn/options.h > @@ -347,6 +347,7 @@ struct options > bool allow_pull_fqdn; /* as a client, allow server to push a FQDN for > certain parameters */ > > #ifdef ENABLE_CLIENT_NAT > + bool enable_nat_ftp_support; > struct client_nat_option_list *client_nat; > #endif > > -- > 1.7.9.5 > > > From 0aa64f57ecf653cd067dbef2b2378bdfc4f9a754 Mon Sep 17 00:00:00 2001 > From: Rafael Gava <rafael.olive...@venturus.org.br> > Date: Fri, 14 Aug 2015 16:46:13 -0300 > Subject: [PATCH] Removed debug messages. > > > Signed-off-by: Rafael Gava <rafael.olive...@venturus.org.br> > --- > src/openvpn/clinat.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/src/openvpn/clinat.c b/src/openvpn/clinat.c > index 1d213f5..991ea75 100755 > --- a/src/openvpn/clinat.c > +++ b/src/openvpn/clinat.c > @@ -833,7 +833,9 @@ client_nat_ftp_transform(struct buffer *ipbuf, > if (OPENVPN_TCPH_FIN_MASK & hdr->u.tcp.flags) > { > entry->marked_to_remove = 1; > +#if DEBUG_DELTA > msg (M_INFO, "Delta marked to be removed!"); > +#endif > } > > ret = 1; > -- > 1.7.9.5 > > > From cf7af4e4784c83a64b8c1e12601d33bdc5b14d59 Mon Sep 17 00:00:00 2001 > From: Rafael Gava <rafael.olive...@venturus.org.br> > Date: Thu, 20 Aug 2015 08:47:08 -0300 > Subject: [PATCH] Fixed FTP NAT IP address. > > > Signed-off-by: Rafael Gava <rafael.olive...@venturus.org.br> > --- > src/openvpn/clinat.c | 30 +++++++++++++++--------------- > 1 file changed, 15 insertions(+), 15 deletions(-) > > diff --git a/src/openvpn/clinat.c b/src/openvpn/clinat.c > index 991ea75..ef400de 100755 > --- a/src/openvpn/clinat.c > +++ b/src/openvpn/clinat.c > @@ -423,7 +423,7 @@ static int try_number(const char *data, size_t dlen, > uint32_t array[], > if (*data == term && i == array_size - 1) > return len; > > - msg (M_ERRNO, "CNAT - try_number - Char %u (got %u nums) `%u' > unexpected\n", len, i, *data); > + msg (M_ERRNO, "CNAT - try_number - Char %u (got %u nums) '%u' > unexpected\n", len, i, *data); > return 0; > } > } > @@ -433,7 +433,7 @@ static int try_number(const char *data, size_t dlen, > uint32_t array[], > return 0; > } > > -static int try_rfc959(const char *, size_t, u_int32_t [], char); > +static int try_rfc959(const char *, size_t, uint32_t [], char); > > static struct ftp_search { > int direction; > @@ -441,7 +441,7 @@ static struct ftp_search { > size_t plen; > char skip; > char term; > - int (*getnum)(const char *, size_t, u_int32_t[], char); > + int (*getnum)(const char *, size_t, uint32_t[], char); > } search[] = { > { > CN_OUTGOING, > @@ -458,7 +458,7 @@ static struct ftp_search { > > /* Returns 0, or length of numbers: 192,168,1,1,5,6 */ > static int > -try_rfc959(const char *data, size_t dlen, u_int32_t array[6], > +try_rfc959(const char *data, size_t dlen, uint32_t array[6], > char term) > { > return try_number(data, dlen, array, 6, ',', term); > @@ -467,9 +467,9 @@ try_rfc959(const char *data, size_t dlen, u_int32_t > array[6], > /* Grab port: number up to delimiter */ > static int > get_port(const char *data, int start, size_t dlen, char delim, > - u_int32_t array[2]) > + uint32_t array[2]) > { > - u_int16_t port = 0; > + uint16_t port = 0; > int i; > > for (i = start; i < dlen; i++) { > @@ -496,13 +496,13 @@ find_pattern(const char *data, size_t dlen, > char skip, char term, > unsigned int *numoff, > unsigned int *numlen, > - u_int32_t array[6], > - int (*getnum)(const char *, size_t, u_int32_t[], char)) > + uint32_t array[6], > + int (*getnum)(const char *, size_t, uint32_t[], char)) > { > size_t i; > > if (check_debug_level (D_CLIENT_NAT)) > - msg (M_INFO, "CNAT - find_pattern %s: dlen = %u\n", pattern, dlen); > + msg (M_INFO, "CNAT - find_pattern %s: dlen = %u\n", pattern, > (uint32_t) dlen); > > if (dlen == 0) > return 0; > @@ -530,7 +530,7 @@ find_pattern(const char *data, size_t dlen, > i++; > > if (check_debug_level (D_CLIENT_NAT)) > - msg (M_INFO, "CNAT - Skipped up to `%c'!\n", skip); > + msg (M_INFO, "CNAT - Skipped up to '%c' (%d)!\n", skip, skip); > > *numoff = i; > *numlen = getnum(data + i, dlen - i, array, term); > @@ -652,7 +652,7 @@ client_nat_ftp_transform(struct buffer *ipbuf, > hexdump(tcp_data, BLEN(&tcpbuf)); > #endif > > - u_int32_t matchlen, matchoff; > + uint32_t matchlen, matchoff; > int found_pattern = -1; > int i = 0; > > @@ -689,7 +689,7 @@ client_nat_ftp_transform(struct buffer *ipbuf, > uint8_t new_tcp_data[32]; > memset(&new_tcp_data[0], 0, sizeof(new_tcp_data)); > > - int new_len = sprintf((char *) &new_tcp_data[0], > "%d,%d,%d,%d,%d,%d%.*s", > + int new_len = sprintf((char *) &new_tcp_data[0], > "%03d,%03d,%03d,%03d,%03d,%03d%.*s", > addr_tmp[0], addr_tmp[1], addr_tmp[2], addr_tmp[3], array[4], > array[5], > data_len - matchlen, (char *)&tcp_data[matchoff + matchlen]); > > @@ -700,7 +700,7 @@ client_nat_ftp_transform(struct buffer *ipbuf, > } > > //If the new len is greater than the old, there will be there an > adjustment > - if (new_len > data_len) > + if (replace_address != ip && new_len > data_len) > { > //If the entry already exists > if (entry = get_delta_entry(table, delta_key)) > @@ -765,8 +765,8 @@ client_nat_ftp_transform(struct buffer *ipbuf, > } > else > { > - // The replace size is the lesser or iqual the original? Pad > with 0 if necessary. > - memcpy(&tcp_data[matchoff], new_tcp_data, data_len); > + if (replace_address != ip) > + memcpy(&tcp_data[matchoff], new_tcp_data, data_len); > > //If the entry already exists > if (entry = get_delta_entry(table, delta_key)) > -- > 1.7.9.5 > > > From 63b1ddad1628eb1a179c2bf5010b781284d2bc4f Mon Sep 17 00:00:00 2001 > From: Rafael Gava <rafael.olive...@venturus.org.br> > Date: Sat, 15 Aug 2015 16:58:45 -0300 > Subject: [PATCH] Fixed options parameter name enable-nat-ftp-support. > > > Signed-off-by: Rafael Gava <rafael.olive...@venturus.org.br> > --- > src/openvpn/options.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/src/openvpn/options.c b/src/openvpn/options.c > index 73b615a..1a012e4 100755 > --- a/src/openvpn/options.c > +++ b/src/openvpn/options.c > @@ -5295,7 +5295,7 @@ add_option (struct options *options, > cnol_check_alloc (options); > add_client_nat_to_option_list(options->client_nat, p[1], p[2], > p[3], p[4], msglevel); > } > - else if (streq (p[0], "enable_nat_ftp_support")) > + else if (streq (p[0], "enable-nat-ftp-support")) > { > options->enable_nat_ftp_support = true; > } > -- > 1.7.9.5 > > > From 2f5ac96c0c2c5d9d06a11e0b08ae958e09c2e9b5 Mon Sep 17 00:00:00 2001 > From: Rafael Gava <rafael.olive...@venturus.org.br> > Date: Mon, 24 Aug 2015 09:15:34 -0300 > Subject: [PATCH] Allows set yes/no option to enable-nat-ftp-support > feature. > > > Signed-off-by: Rafael Gava <rafael.olive...@venturus.org.br> > --- > src/openvpn/options.c | 21 +++++++++++++++++++-- > 1 file changed, 19 insertions(+), 2 deletions(-) > > diff --git a/src/openvpn/options.c b/src/openvpn/options.c > index 1a012e4..4d73d87 100755 > --- a/src/openvpn/options.c > +++ b/src/openvpn/options.c > @@ -236,7 +236,9 @@ static const char usage_message[] = > " the default gateway. Useful when pushing private > subnets.\n" > #ifdef ENABLE_CLIENT_NAT > "--client-nat snat|dnat network netmask alias : on client add 1-to-1 > NAT rule.\n" > - "--enable-nat-ftp-support : Enable NAT FTP Support, updating the IP > address on FTP PORT commands or PASV responses\n" > + "--enable-nat-ftp-support : Enable NAT FTP Support, replacing the IP > address on FTP PORT commands or PASV responses?\n" > + " 'no' -- No, disable this feature.\n" > + " 'yes' -- Yes, enable this feature (Enabled by > default on Windows).\n" > #endif > #ifdef ENABLE_PUSH_PEER_INFO > "--push-peer-info : (client only) push client info to server.\n" > @@ -792,8 +794,12 @@ init_options (struct options *o, const bool init_gc) > o->proto_force = -1; > > #ifdef ENABLE_CLIENT_NAT > +#ifdef WIN32 > + o->enable_nat_ftp_support = true; > +#else > o->enable_nat_ftp_support = false; > #endif > +#endif > > #ifdef ENABLE_OCC > o->occ = true; > @@ -5297,7 +5303,18 @@ add_option (struct options *options, > } > else if (streq (p[0], "enable-nat-ftp-support")) > { > - options->enable_nat_ftp_support = true; > + if (p[1]) > + { > + if (streq (p[1], "yes")) > + options->enable_nat_ftp_support = true; > + else if (streq (p[1], "no")) > + options->enable_nat_ftp_support = false; > + else > + { > + msg (msglevel, "bad enable-nat-ftp-support option: %s -- > must be 'yes' or 'no'", p[1]); > + goto err; > + } > + } > } > #endif > else if (streq (p[0], "route") && p[1]) > -- > 1.7.9.5 > > >