napt: Add basic support for NAT by martin-ger

319d4d3c napt: Add basic support for NAT by martin-ger
Co-Authored-By: David Cermak <cermak@espressif.com> (4b4d6b28, 754b8d5d)
Co-Authored-By: leo chung <gewalalb@gmail.com> (bb63eed1)
Co-Authored-By: yuanjm <yuanjianmin@espressif.com> (74cf7f9f)
This commit is contained in:
martin-ger
2020-02-06 13:37:45 +01:00
committed by David Cermak
parent 8b1edee8d0
commit 39773525d2
19 changed files with 1759 additions and 4 deletions
+3
View File
@@ -323,4 +323,7 @@ void lwip_example_app_platform_assert(const char *msg, int line, const char *fil
#define LWIP_PLATFORM_ASSERT(x) lwip_example_app_platform_assert(x, __LINE__, __FILE__)
#endif
/* ESP options */
#define ESP_LWIP LWIP_NETCONN_FULLDUPLEX
#endif /* LWIP_LWIPOPTS_H */
+1
View File
@@ -66,6 +66,7 @@ set(lwipcore4_SRCS
${LWIP_DIR}/src/core/ipv4/igmp.c
${LWIP_DIR}/src/core/ipv4/ip4_frag.c
${LWIP_DIR}/src/core/ipv4/ip4.c
${LWIP_DIR}/src/core/ipv4/ip4_napt.c
${LWIP_DIR}/src/core/ipv4/ip4_addr.c
)
set(lwipcore6_SRCS
+1
View File
@@ -59,6 +59,7 @@ CORE4FILES=$(LWIPDIR)/core/ipv4/acd.c \
$(LWIPDIR)/core/ipv4/igmp.c \
$(LWIPDIR)/core/ipv4/ip4_frag.c \
$(LWIPDIR)/core/ipv4/ip4.c \
$(LWIPDIR)/core/ipv4/ip4_napt.c \
$(LWIPDIR)/core/ipv4/ip4_addr.c
CORE6FILES=$(LWIPDIR)/core/ipv6/dhcp6.c \
+2
View File
@@ -244,6 +244,8 @@ PACK_STRUCT_END
#error "For LWIP_NETCONN_FULLDUPLEX to work, LWIP_NETCONN_SEM_PER_THREAD is required"
#endif
#if LWIP_SOCKET
#endif /* LWIP_SOCKET */
/* Compile-time checks for deprecated options.
*/
+30 -1
View File
@@ -56,6 +56,7 @@
#include "lwip/autoip.h"
#include "lwip/stats.h"
#include "lwip/prot/iana.h"
#include "lwip/ip4_napt.h"
#include <string.h>
@@ -329,6 +330,13 @@ ip4_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
return;
}
#if ESP_LWIP
#if IP_NAPT
if (ip_napt_forward(p, iphdr, inp, netif) != ERR_OK)
return;
#endif
#endif /* ESP_LWIP */
/* Incrementally update the IP checksum. */
if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) {
IPH_CHKSUM_SET(iphdr, (u16_t)(IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1));
@@ -459,7 +467,11 @@ ip4_input_accept(struct netif *netif)
err_t
ip4_input(struct pbuf *p, struct netif *inp)
{
#if ESP_LWIP && IP_NAPT
struct ip_hdr *iphdr;
#else
const struct ip_hdr *iphdr;
#endif /* IP_NAPT && ESP_LWIP */
struct netif *netif;
u16_t iphdr_hlen;
u16_t iphdr_len;
@@ -545,6 +557,14 @@ ip4_input(struct pbuf *p, struct netif *inp)
}
#endif
#if ESP_LWIP
#if IP_NAPT
/* for unicast packet, check NAPT table and modify dest if needed */
if (!inp->napt && ip4_addr_cmp(&iphdr->dest, netif_ip4_addr(inp)))
ip_napt_recv(p, iphdr);
#endif
#endif /* ESP_LWIP */
/* copy IP addresses to aligned ip_addr_t */
ip_addr_copy_from_ip4(ip_data.current_iphdr_dest, iphdr->dest);
ip_addr_copy_from_ip4(ip_data.current_iphdr_src, iphdr->src);
@@ -678,7 +698,11 @@ ip4_input(struct pbuf *p, struct netif *inp)
if (p == NULL) {
return ERR_OK;
}
#if ESP_LWIP && IP_NAPT
iphdr = (struct ip_hdr *)p->payload;
#else
iphdr = (const struct ip_hdr *)p->payload;
#endif
#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
pbuf_free(p);
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
@@ -1015,7 +1039,11 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d
ip4_debug_print(p);
#if ENABLE_LOOPBACK
if (ip4_addr_eq(dest, netif_ip4_addr(netif))
#if ESP_LWIP && IP_NAPT
/* doesn't work for external wifi interfaces */
#else
if (ip4_addr_cmp(dest, netif_ip4_addr(netif))
#if !LWIP_HAVE_LOOPIF
|| ip4_addr_isloopback(dest)
#endif /* !LWIP_HAVE_LOOPIF */
@@ -1029,6 +1057,7 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d
netif_loop_output(netif, p);
}
#endif /* LWIP_MULTICAST_TX_OPTIONS */
#endif /* ESP_LWIP && IP_NAPT */
#endif /* ENABLE_LOOPBACK */
#if IP_FRAG
/* don't fragment if interface has mtu set to 0 [loopif] */
+800
View File
@@ -0,0 +1,800 @@
/**
* @file
* This is the NAPT implementation on IPv4 layer
*
* @see ip4.c
*
*/
#include "lwip/opt.h"
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* original reassembly code by Adam Dunkels <adam@sics.se>
*
*/
#if ESP_LWIP
#if LWIP_IPV4
#if IP_NAPT
#include "lwip/sys.h"
#include "lwip/ip.h"
#include "lwip/def.h"
#include "lwip/inet_chksum.h"
#include "lwip/netif.h"
#include "lwip/icmp.h"
#include "lwip/udp.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/lwip_napt.h"
#include "lwip/ip4_napt.h"
#include "string.h"
#include "assert.h"
#define NO_IDX ((u16_t)-1)
#define NT(x) ((x) == NO_IDX ? NULL : &ip_napt_table[x])
struct napt_table {
u32_t last;
u32_t src;
u32_t dest;
u16_t sport;
u16_t dport;
u16_t mport;
u8_t proto;
unsigned int fin1 : 1;
unsigned int fin2 : 1;
unsigned int finack1 : 1;
unsigned int finack2 : 1;
unsigned int synack : 1;
unsigned int rst : 1;
u16_t next, prev;
};
struct portmap_table {
u32_t maddr;
u32_t daddr;
u16_t mport;
u16_t dport;
u8_t proto;
u8_t valid;
};
static u16_t napt_list = NO_IDX, napt_list_last = NO_IDX, napt_free = 0;
static struct napt_table *ip_napt_table = NULL;
static struct portmap_table *ip_portmap_table = NULL;
static int nr_active_napt_tcp = 0, nr_active_napt_udp = 0, nr_active_napt_icmp = 0;
static uint16_t ip_napt_max = 0;
static uint8_t ip_portmap_max = 0;
#if NAPT_DEBUG
/* Print NAPT table using LWIP_DEBUGF
*/
static void
napt_debug_print(void)
{
int i, next;
LWIP_DEBUGF(NAPT_DEBUG, ("NAPT table:\n"));
LWIP_DEBUGF(NAPT_DEBUG, (" src dest sport dport mport \n"));
LWIP_DEBUGF(NAPT_DEBUG, ("+-----------------------+-----------------------+-------+-------+-------+\n"));
for (i = napt_list; i != NO_IDX; i = next) {
struct napt_table *t = &ip_napt_table[i];
next = t->next;
LWIP_DEBUGF(NAPT_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" |",
((const u8_t*) (&t->src))[0],
((const u8_t*) (&t->src))[1],
((const u8_t*) (&t->src))[2],
((const u8_t*) (&t->src))[3]));
LWIP_DEBUGF(NAPT_DEBUG, (" %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" |",
((const u8_t*) (&t->dest))[0],
((const u8_t*) (&t->dest))[1],
((const u8_t*) (&t->dest))[2],
((const u8_t*) (&t->dest))[3]));
LWIP_DEBUGF(NAPT_DEBUG, (" %5"U16_F" | %5"U16_F" | %5"U16_F" |\n",
lwip_htons(t->sport),
lwip_htons(t->dport),
lwip_htons(t->mport)));
}
}
#endif /* NAPT_DEBUG */
/**
* Deallocates the NAPT tables.
*
*/
static void
ip_napt_deinit(void)
{
mem_free(ip_napt_table);
mem_free(ip_portmap_table);
ip_portmap_table = NULL;
ip_napt_table = NULL;
}
/**
* Allocates and initializes the NAPT tables.
*
* @param max_nat max number of enties in the NAPT table (use IP_NAPT_MAX if in doubt)
* @param max_portmap max number of enties in the NAPT table (use IP_PORTMAP_MAX if in doubt)
*/
static void
ip_napt_init(uint16_t max_nat, uint8_t max_portmap)
{
u16_t i;
if (ip_portmap_table == NULL && ip_napt_table == NULL) {
ip_napt_max = max_nat;
ip_portmap_max = max_portmap;
ip_napt_table = (struct napt_table*)mem_calloc(ip_napt_max, sizeof(struct napt_table[1]));
ip_portmap_table = (struct portmap_table*)mem_calloc(ip_portmap_max, sizeof(struct portmap_table[1]));
assert(ip_portmap_table != NULL && ip_napt_table != NULL);
for (i = 0; i < ip_napt_max - 1; i++)
ip_napt_table[i].next = i + 1;
ip_napt_table[i].next = NO_IDX;
}
}
void
ip_napt_enable(u32_t addr, int enable)
{
struct netif *netif;
int napt_in_any_netif = 0;
for (netif = netif_list; netif; netif = netif->next) {
if (netif->napt)
napt_in_any_netif = 1;
if (netif_is_up(netif) && !ip_addr_isany(&netif->ip_addr) && (ip_2_ip4(&netif->ip_addr)->addr) == addr && enable) {
netif->napt = 1;
ip_napt_init(IP_NAPT_MAX, IP_PORTMAP_MAX);
break;
}
}
if (!enable && !napt_in_any_netif) {
for (netif = netif_list; netif; netif = netif->next)
netif->napt = 0;
ip_napt_deinit();
}
}
void
ip_napt_enable_no(u8_t number, int enable)
{
struct netif *netif;
for (netif = netif_list; netif; netif = netif->next) {
if (netif->num == number) {
netif->napt = !!enable;
if (enable)
ip_napt_init(IP_NAPT_MAX, IP_PORTMAP_MAX);
else
ip_napt_deinit();
break;
}
}
}
/* adjusts checksum in a packet
- chksum points to the chksum in the packet
- optr points to the old data in the packet (before)
- nptr points to the new data in the packet (after)
*/
static void
checksumadjust(u8_t *chksum, u8_t *optr, int olen, u8_t *nptr, int nlen)
{
s32_t x, before, after;
x=chksum[0]*256+chksum[1];
x=~x & 0xFFFFU;
while (olen)
{
before=optr[0]*256+optr[1]; optr+=2;
x-=before & 0xFFFFU;
if (x<=0) { x--; x&=0xFFFFU; }
olen-=2;
}
while (nlen)
{
after=nptr[0]*256+nptr[1]; nptr+=2;
x+=after & 0xFFFFU;
if (x & 0x10000U) { x++; x&=0xFFFFU; }
nlen-=2;
}
x=~x & 0xFFFFU;
chksum[0]=x/256; chksum[1]=x & 0xFFU;
}
/* t must be indexed by napt_free */
static void
ip_napt_insert(struct napt_table *t)
{
u16_t ti = t - ip_napt_table;
assert(ti == napt_free);
napt_free = t->next;
t->prev = NO_IDX;
t->next = napt_list;
if (napt_list != NO_IDX)
NT(napt_list)->prev = ti;
napt_list = ti;
if (napt_list_last == NO_IDX)
napt_list_last = ti;
#if LWIP_TCP
if (t->proto == IP_PROTO_TCP)
nr_active_napt_tcp++;
#endif
#if LWIP_UDP
if (t->proto == IP_PROTO_UDP)
nr_active_napt_udp++;
#endif
#if LWIP_ICMP
if (t->proto == IP_PROTO_ICMP)
nr_active_napt_icmp++;
#endif
LWIP_DEBUGF(NAPT_DEBUG, ("ip_napt_insert(): TCP=%d, UDP=%d, ICMP=%d\n", nr_active_napt_tcp, nr_active_napt_udp, nr_active_napt_icmp));
}
static void
ip_napt_free(struct napt_table *t)
{
u16_t ti = t - ip_napt_table;
if (ti == napt_list)
napt_list = t->next;
if (ti == napt_list_last)
napt_list_last = t->prev;
if (t->next != NO_IDX)
NT(t->next)->prev = t->prev;
if (t->prev != NO_IDX)
NT(t->prev)->next = t->next;
t->prev = NO_IDX;
t->next = napt_free;
napt_free = ti;
#if LWIP_TCP
if (t->proto == IP_PROTO_TCP)
nr_active_napt_tcp--;
#endif
#if LWIP_UDP
if (t->proto == IP_PROTO_UDP)
nr_active_napt_udp--;
#endif
#if LWIP_ICMP
if (t->proto == IP_PROTO_ICMP)
nr_active_napt_icmp--;
#endif
LWIP_DEBUGF(NAPT_DEBUG, ("ip_napt_free\n"));
#if NAPT_DEBUG
napt_debug_print();
#endif
}
#if LWIP_TCP
static u8_t
ip_napt_find_port(u8_t proto, u16_t port)
{
int i, next;
for (i = napt_list; i != NO_IDX; i = next) {
struct napt_table *t = &ip_napt_table[i];
next = t->next;
if (t->proto == proto && t->mport == port)
return 1;
}
return 0;
}
static struct portmap_table *
ip_portmap_find(u8_t proto, u16_t mport);
static u8_t
tcp_listening(u16_t port)
{
struct tcp_pcb_listen *t;
for (t = tcp_listen_pcbs.listen_pcbs; t; t = t->next)
if (t->local_port == port)
return 1;
if (ip_portmap_find(IP_PROTO_TCP, port))
return 1;
return 0;
}
#endif /* LWIP_TCP */
#if LWIP_UDP
static u8_t
udp_listening(u16_t port)
{
struct udp_pcb *pcb;
for (pcb = udp_pcbs; pcb; pcb = pcb->next)
if (pcb->local_port == port)
return 1;
if (ip_portmap_find(IP_PROTO_UDP, port))
return 1;
return 0;
}
#endif /* LWIP_UDP */
static u16_t
ip_napt_new_port(u8_t proto, u16_t port)
{
if (PP_NTOHS(port) >= IP_NAPT_PORT_RANGE_START && PP_NTOHS(port) <= IP_NAPT_PORT_RANGE_END)
if (!ip_napt_find_port(proto, port) && !tcp_listening(port))
return port;
for (;;) {
port = PP_HTONS(IP_NAPT_PORT_RANGE_START +
LWIP_RAND() % (IP_NAPT_PORT_RANGE_END - IP_NAPT_PORT_RANGE_START + 1));
if (ip_napt_find_port(proto, port))
continue;
#if LWIP_TCP
if (proto == IP_PROTO_TCP && tcp_listening(port))
continue;
#endif /* LWIP_TCP */
#if LWIP_UDP
if (proto == IP_PROTO_UDP && udp_listening(port))
continue;
#endif /* LWIP_UDP */
return port;
}
}
static struct napt_table*
ip_napt_find(u8_t proto, u32_t addr, u16_t port, u16_t mport, u8_t dest)
{
u16_t i, next;
u32_t now;
struct napt_table *t;
LWIP_DEBUGF(NAPT_DEBUG, ("ip_napt_find\n"));
LWIP_DEBUGF(NAPT_DEBUG, ("looking up in table %s: %"U16_F".%"U16_F".%"U16_F".%"U16_F", port: %u, mport: %u\n",
(dest ? "dest" : "src"),
((const u8_t*) (&addr))[0], ((const u8_t*) (&addr))[1],
((const u8_t*) (&addr))[2], ((const u8_t*) (&addr))[3],
PP_HTONS(port),
PP_HTONS(mport)));
#if NAPT_DEBUG
napt_debug_print();
#endif
now = sys_now();
for (i = napt_list; i != NO_IDX; i = next) {
t = NT(i);
next = t->next;
#if LWIP_TCP
if (t->proto == IP_PROTO_TCP &&
((((t->finack1 && t->finack2) || !t->synack) &&
now - t->last > IP_NAPT_TIMEOUT_MS_TCP_DISCON) ||
now - t->last > IP_NAPT_TIMEOUT_MS_TCP)) {
ip_napt_free(t);
continue;
}
#endif
#if LWIP_UDP
if (t->proto == IP_PROTO_UDP && now - t->last > IP_NAPT_TIMEOUT_MS_UDP) {
ip_napt_free(t);
continue;
}
#endif
#if LWIP_ICMP
if (t->proto == IP_PROTO_ICMP && now - t->last > IP_NAPT_TIMEOUT_MS_ICMP) {
ip_napt_free(t);
continue;
}
#endif
if (dest == 0 && t->proto == proto && t->src == addr && t->sport == port) {
t->last = now;
LWIP_DEBUGF(NAPT_DEBUG, ("found\n"));
return t;
}
if (dest == 1 && t->proto == proto && t->dest == addr && t->dport == port
&& t->mport == mport) {
t->last = now;
LWIP_DEBUGF(NAPT_DEBUG, ("found\n"));
return t;
}
}
LWIP_DEBUGF(NAPT_DEBUG, ("not found\n"));
return NULL;
}
static u16_t
ip_napt_add(u8_t proto, u32_t src, u16_t sport, u32_t dest, u16_t dport)
{
struct napt_table *t = ip_napt_find(proto, src, sport, 0, 0);
if (t) {
t->last = sys_now();
t->dest = dest;
t->dport = dport;
/* move this entry to the top of napt_list */
ip_napt_free(t);
ip_napt_insert(t);
LWIP_DEBUGF(NAPT_DEBUG, ("ip_napt_add\n"));
#if NAPT_DEBUG
napt_debug_print();
#endif
return t->mport;
}
t = NT(napt_free);
if (t) {
u16_t mport = sport;
#if LWIP_TCP
if (proto == IP_PROTO_TCP)
mport = ip_napt_new_port(IP_PROTO_TCP, sport);
#endif
#if LWIP_TCP
if (proto == IP_PROTO_UDP)
mport = ip_napt_new_port(IP_PROTO_UDP, sport);
#endif
t->last = sys_now();
t->src = src;
t->dest = dest;
t->sport = sport;
t->dport = dport;
t->mport = mport;
t->proto = proto;
t->fin1 = t->fin2 = t->finack1 = t->finack2 = t->synack = t->rst = 0;
ip_napt_insert(t);
LWIP_DEBUGF(NAPT_DEBUG, ("ip_napt_add\n"));
#if NAPT_DEBUG
napt_debug_print();
#endif
return mport;
}
LWIP_DEBUGF(NAPT_DEBUG, ("ip_napt_add() failed to insert\n"));
return 0;
}
u8_t
ip_portmap_add(u8_t proto, u32_t maddr, u16_t mport, u32_t daddr, u16_t dport)
{
int i;
mport = PP_HTONS(mport);
dport = PP_HTONS(dport);
for (i = 0; i < ip_portmap_max; i++) {
struct portmap_table *p = &ip_portmap_table[i];
if (p->valid && p->proto == proto && p->mport == mport) {
p->dport = dport;
p->daddr = daddr;
} else if (!p->valid) {
p->maddr = maddr;
p->daddr = daddr;
p->mport = mport;
p->dport = dport;
p->proto = proto;
p->valid = 1;
return 1;
}
}
return 0;
}
static struct portmap_table *
ip_portmap_find(u8_t proto, u16_t mport)
{
int i;
for (i = 0; i < ip_portmap_max; i++) {
struct portmap_table *p = &ip_portmap_table[i];
if (!p->valid)
return 0;
if (p->proto == proto && p->mport == mport)
return p;
}
return NULL;
}
static struct portmap_table *
ip_portmap_find_dest(u8_t proto, u16_t dport, u32_t daddr)
{
int i;
for (i = 0; i < ip_portmap_max; i++) {
struct portmap_table *p = &ip_portmap_table[i];
if (!p->valid)
return 0;
if (p->proto == proto && p->dport == dport && p->daddr == daddr)
return p;
}
return NULL;
}
u8_t
ip_portmap_remove(u8_t proto, u16_t mport)
{
struct portmap_table *last = &ip_portmap_table[ip_portmap_max - 1];
struct portmap_table *m = ip_portmap_find(proto, PP_HTONS(mport));
if (!m)
return 0;
for (; m != last; m++)
memcpy(m, m + 1, sizeof(*m));
last->valid = 0;
return 1;
}
#if LWIP_TCP
static void
ip_napt_modify_port_tcp(struct tcp_hdr *tcphdr, u8_t dest, u16_t newval)
{
if (dest) {
checksumadjust((u8_t *)&tcphdr->chksum, (u8_t *)&tcphdr->dest, 2, (u8_t *)&newval, 2);
tcphdr->dest = newval;
} else {
checksumadjust((u8_t *)&tcphdr->chksum, (u8_t *)&tcphdr->src, 2, (u8_t *)&newval, 2);
tcphdr->src = newval;
}
}
static void
ip_napt_modify_addr_tcp(struct tcp_hdr *tcphdr, ip4_addr_p_t *oldval, u32_t newval)
{
checksumadjust((u8_t *)&tcphdr->chksum, (u8_t *)&oldval->addr, 4, (u8_t *)&newval, 4);
}
#endif /* LWIP_TCP */
#if LWIP_UDP
static void
ip_napt_modify_port_udp(struct udp_hdr *udphdr, u8_t dest, u16_t newval)
{
if (dest) {
if (udphdr->chksum != 0)
checksumadjust((u8_t *)&udphdr->chksum, (u8_t *)&udphdr->dest, 2, (u8_t *)&newval, 2);
udphdr->dest = newval;
} else {
if (udphdr->chksum != 0)
checksumadjust((u8_t *)&udphdr->chksum, (u8_t *)&udphdr->src, 2, (u8_t *)&newval, 2);
udphdr->src = newval;
}
}
static void
ip_napt_modify_addr_udp(struct udp_hdr *udphdr, ip4_addr_p_t *oldval, u32_t newval)
{
if (udphdr->chksum != 0)
checksumadjust( (u8_t *)&udphdr->chksum, (u8_t *)&oldval->addr, 4, (u8_t *)&newval, 4);
}
#endif /* LWIP_UDP */
static void
ip_napt_modify_addr(struct ip_hdr *iphdr, ip4_addr_p_t *field, u32_t newval)
{
checksumadjust((u8_t *)&IPH_CHKSUM(iphdr), (u8_t *)&field->addr, 4, (u8_t *)&newval, 4);
field->addr = newval;
}
void
ip_napt_recv(struct pbuf *p, struct ip_hdr *iphdr)
{
struct portmap_table *m;
struct napt_table *t;
#if LWIP_ICMP
/* NAPT for ICMP Echo Request using identifier */
if (IPH_PROTO(iphdr) == IP_PROTO_ICMP) {
struct icmp_echo_hdr *iecho = (struct icmp_echo_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
if (iecho->type == ICMP_ER) {
t = ip_napt_find(IP_PROTO_ICMP, iphdr->src.addr, iecho->id, iecho->id, 1);
if (!t)
return;
ip_napt_modify_addr(iphdr, &iphdr->dest, t->src);
return;
}
return;
}
#endif /* LWIP_ICMP */
#if LWIP_TCP
if (IPH_PROTO(iphdr) == IP_PROTO_TCP) {
struct tcp_hdr *tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
LWIP_DEBUGF(NAPT_DEBUG, ("ip_napt_recv\n"));
LWIP_DEBUGF(NAPT_DEBUG, ("src: %"U16_F".%"U16_F".%"U16_F".%"U16_F", dest: %"U16_F".%"U16_F".%"U16_F".%"U16_F", \n",
ip4_addr1_16(&iphdr->src), ip4_addr2_16(&iphdr->src),
ip4_addr3_16(&iphdr->src), ip4_addr4_16(&iphdr->src),
ip4_addr1_16(&iphdr->dest), ip4_addr2_16(&iphdr->dest),
ip4_addr3_16(&iphdr->dest), ip4_addr4_16(&iphdr->dest)));
LWIP_DEBUGF(NAPT_DEBUG, ("sport %u, dport: %u\n",
lwip_htons(tcphdr->src),
lwip_htons(tcphdr->dest)));
m = ip_portmap_find(IP_PROTO_TCP, tcphdr->dest);
if (m) {
/* packet to mapped port: rewrite destination */
if (m->dport != tcphdr->dest)
ip_napt_modify_port_tcp(tcphdr, 1, m->dport);
ip_napt_modify_addr_tcp(tcphdr, &iphdr->dest, m->daddr);
ip_napt_modify_addr(iphdr, &iphdr->dest, m->daddr);
return;
}
t = ip_napt_find(IP_PROTO_TCP, iphdr->src.addr, tcphdr->src, tcphdr->dest, 1);
if (!t)
return; /* Unknown TCP session; do nothing */
if (t->sport != tcphdr->dest)
ip_napt_modify_port_tcp(tcphdr, 1, t->sport);
ip_napt_modify_addr_tcp(tcphdr, &iphdr->dest, t->src);
ip_napt_modify_addr(iphdr, &iphdr->dest, t->src);
if ((TCPH_FLAGS(tcphdr) & (TCP_SYN|TCP_ACK)) == (TCP_SYN|TCP_ACK))
t->synack = 1;
if ((TCPH_FLAGS(tcphdr) & TCP_FIN))
t->fin1 = 1;
if (t->fin2 && (TCPH_FLAGS(tcphdr) & TCP_ACK))
t->finack2 = 1; /* FIXME: Currently ignoring ACK seq... */
if (TCPH_FLAGS(tcphdr) & TCP_RST)
t->rst = 1;
return;
}
#endif /* LWIP_TCP */
#if LWIP_UDP
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
m = ip_portmap_find(IP_PROTO_UDP, udphdr->dest);
if (m) {
/* packet to mapped port: rewrite destination */
if (m->dport != udphdr->dest)
ip_napt_modify_port_udp(udphdr, 1, m->dport);
ip_napt_modify_addr_udp(udphdr, &iphdr->dest, m->daddr);
ip_napt_modify_addr(iphdr, &iphdr->dest, m->daddr);
return;
}
t = ip_napt_find(IP_PROTO_UDP, iphdr->src.addr, udphdr->src, udphdr->dest, 1);
if (!t)
return; /* Unknown session; do nothing */
if (t->sport != udphdr->dest)
ip_napt_modify_port_udp(udphdr, 1, t->sport);
ip_napt_modify_addr_udp(udphdr, &iphdr->dest, t->src);
ip_napt_modify_addr(iphdr, &iphdr->dest, t->src);
return;
}
#endif /* LWIP_UDP */
}
err_t
ip_napt_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp, struct netif *outp)
{
if (!inp->napt)
return ERR_OK;
#if LWIP_ICMP
/* NAPT for ICMP Echo Request using identifier */
if (IPH_PROTO(iphdr) == IP_PROTO_ICMP) {
struct icmp_echo_hdr *iecho = (struct icmp_echo_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
if (iecho->type == ICMP_ECHO) {
/* register src addr and iecho->id and dest info */
ip_napt_add(IP_PROTO_ICMP, iphdr->src.addr, iecho->id, iphdr->dest.addr, iecho->id);
ip_napt_modify_addr(iphdr, &iphdr->src, ip_2_ip4(&outp->ip_addr)->addr);
}
return ERR_OK;
}
#endif
#if LWIP_TCP
if (IPH_PROTO(iphdr) == IP_PROTO_TCP) {
struct tcp_hdr *tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
u16_t mport;
struct portmap_table *m = ip_portmap_find_dest(IP_PROTO_TCP, tcphdr->src, iphdr->src.addr);
if (m) {
/* packet from port-mapped dest addr/port: rewrite source to this node */
if (m->mport != tcphdr->src)
ip_napt_modify_port_tcp(tcphdr, 0, m->mport);
ip_napt_modify_addr_tcp(tcphdr, &iphdr->src, m->maddr);
ip_napt_modify_addr(iphdr, &iphdr->src, m->maddr);
return ERR_OK;
}
if ((TCPH_FLAGS(tcphdr) & (TCP_SYN|TCP_ACK)) == TCP_SYN &&
PP_NTOHS(tcphdr->src) >= 1024) {
/* Register new TCP session to NAPT */
mport = ip_napt_add(IP_PROTO_TCP, iphdr->src.addr, tcphdr->src,
iphdr->dest.addr, tcphdr->dest);
if (mport == 0)
return ERR_RTE; /* routing err if add entry failed */
} else {
struct napt_table *t = ip_napt_find(IP_PROTO_TCP, iphdr->src.addr, tcphdr->src, 0, 0);
if (!t || t->dest != iphdr->dest.addr || t->dport != tcphdr->dest) {
#if LWIP_ICMP
icmp_dest_unreach(p, ICMP_DUR_PORT);
#endif
return ERR_RTE; /* Drop unknown TCP session */
}
mport = t->mport;
if ((TCPH_FLAGS(tcphdr) & TCP_FIN))
t->fin2 = 1;
if (t->fin1 && (TCPH_FLAGS(tcphdr) & TCP_ACK))
t->finack1 = 1; /* FIXME: Currently ignoring ACK seq... */
if (TCPH_FLAGS(tcphdr) & TCP_RST)
t->rst = 1;
}
if (mport != tcphdr->src)
ip_napt_modify_port_tcp(tcphdr, 0, mport);
ip_napt_modify_addr_tcp(tcphdr, &iphdr->src, ip_2_ip4(&outp->ip_addr)->addr);
ip_napt_modify_addr(iphdr, &iphdr->src, ip_2_ip4(&outp->ip_addr)->addr);
return ERR_OK;
}
#endif
#if LWIP_UDP
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
u16_t mport;
struct portmap_table *m = ip_portmap_find_dest(IP_PROTO_UDP, udphdr->src, iphdr->src.addr);
if (m) {
/* packet from port-mapped dest addr/port: rewrite source to this node */
if (m->mport != udphdr->src)
ip_napt_modify_port_udp(udphdr, 0, m->mport);
ip_napt_modify_addr_udp(udphdr, &iphdr->src, m->maddr);
LWIP_DEBUGF(NAPT_DEBUG, ("Modify UDP addr %x %x", iphdr->src.addr, m->maddr));
ip_napt_modify_addr(iphdr, &iphdr->src, m->maddr);
return ERR_OK;
}
if (PP_NTOHS(udphdr->src) >= 1024) {
/* Register new UDP session */
mport = ip_napt_add(IP_PROTO_UDP, iphdr->src.addr, udphdr->src,
iphdr->dest.addr, udphdr->dest);
if (mport == 0)
return ERR_RTE; /* routing err if add entry failed */
} else {
struct napt_table *t = ip_napt_find(IP_PROTO_UDP, iphdr->src.addr, udphdr->src, 0, 0);
if (!t || t->dest != iphdr->dest.addr || t->dport != udphdr->dest) {
#if LWIP_ICMP
icmp_dest_unreach(p, ICMP_DUR_PORT);
#endif
return ERR_RTE; /* Drop unknown UDP session */
}
mport = t->mport;
}
if (mport != udphdr->src)
ip_napt_modify_port_udp(udphdr, 0, mport);
ip_napt_modify_addr_udp(udphdr, &iphdr->src, ip_2_ip4(&outp->ip_addr)->addr);
ip_napt_modify_addr(iphdr, &iphdr->src, ip_2_ip4(&outp->ip_addr)->addr);
return ERR_OK;
}
#endif
return ERR_OK;
}
#endif /* IP_NAPT */
#endif /* LWIP_IPV4 */
#endif /* ESP_LWIP */
+6
View File
@@ -380,6 +380,12 @@ netif_add(struct netif *netif,
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
#endif /* ENABLE_LOOPBACK */
#if ESP_LWIP
#if IP_NAPT
netif->napt = 0;
#endif /* IP_NAPT */
#endif /* ESP_LWIP */
#if LWIP_IPV4
netif_set_addr(netif, ipaddr, netmask, gw);
#endif /* LWIP_IPV4 */
+95
View File
@@ -0,0 +1,95 @@
/**
* @file ip4_napt.h
* This is a private interface of ip4_napt used from ip4.c
*
* @see ip4_napt.c
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* original reassembly code by Adam Dunkels <adam@sics.se>
*
*/
#ifndef LWIP_HDR_IP4_NAPT_H
#define LWIP_HDR_IP4_NAPT_H
#include "lwip/opt.h"
#if ESP_LWIP
#if IP_FORWARD
#if IP_NAPT
#include "lwip/def.h"
#include "lwip/pbuf.h"
#include "lwip/ip4_addr.h"
#include "lwip/err.h"
#include "lwip/netif.h"
#include "lwip/prot/ip4.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "lwip/err.h"
#include "lwip/ip4.h"
/**
* NAPT for a forwarded packet. It checks weather we need NAPT and modify
* the packet source address and port if needed.
*
* @param p the packet to forward (p->payload points to IP header)
* @param iphdr the IP header of the input packet
* @param inp the netif on which this packet was received
* @param outp the netif on which this packet will be sent
* @return ERR_OK if packet should be sent, or ERR_RTE if it should be dropped
*/
err_t
ip_napt_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp, struct netif *outp);
/**
* NAPT for an input packet. It checks weather the destination is on NAPT
* table and modify the packet destination address and port if needed.
*
* @param p the packet to forward (p->payload points to IP header)
* @param iphdr the IP header of the input packet
*/
void
ip_napt_recv(struct pbuf *p, struct ip_hdr *iphdr);
#ifdef __cplusplus
}
#endif
#endif /* IP_NAPT */
#endif /* IP_FORWARD */
#endif /* ESP_LWIP */
#endif /* LWIP_HDR_IP4_NAPT_H */
+122
View File
@@ -0,0 +1,122 @@
/**
* @file lwip_napt.h
* public API of ip4_napt
*
* @see ip4_napt.c
*/
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* original reassembly code by Adam Dunkels <adam@sics.se>
*
*/
#ifndef __LWIP_NAPT_H__
#define __LWIP_NAPT_H__
#include "lwip/opt.h"
#ifdef __cplusplus
extern "C" {
#endif
#if ESP_LWIP
#if IP_FORWARD
#if IP_NAPT
/* Default size of the tables used for NAPT */
#ifndef IP_NAPT_MAX
#define IP_NAPT_MAX 512
#endif
#ifndef IP_PORTMAP_MAX
#define IP_PORTMAP_MAX 32
#endif
/* Timeouts in sec for the various protocol types */
#define IP_NAPT_TIMEOUT_MS_TCP (30*60*1000)
#define IP_NAPT_TIMEOUT_MS_TCP_DISCON (20*1000)
#define IP_NAPT_TIMEOUT_MS_UDP (2*1000)
#define IP_NAPT_TIMEOUT_MS_ICMP (2*1000)
#define IP_NAPT_PORT_RANGE_START 49152
#define IP_NAPT_PORT_RANGE_END 61439
/**
* Enable/Disable NAPT for a specified interface.
*
* @param addr ip address of the interface
* @param enable non-zero to enable NAPT, or 0 to disable.
*/
void
ip_napt_enable(u32_t addr, int enable);
/**
* Enable/Disable NAPT for a specified interface.
*
* @param number netif number of the interface
* @param enable non-zero to enable NAPT, or 0 to disable.
*/
void
ip_napt_enable_no(u8_t number, int enable);
/**
* Register port mapping on the external interface to internal interface.
* When the same port mapping is registered again, the old mapping is overwritten.
* In this implementation, only 1 unique port mapping can be defined for each target address/port.
*
* @param proto target protocol
* @param maddr ip address of the external interface
* @param mport mapped port on the external interface, in host byte order.
* @param daddr destination ip address
* @param dport destination port, in host byte order.
*/
u8_t
ip_portmap_add(u8_t proto, u32_t maddr, u16_t mport, u32_t daddr, u16_t dport);
/**
* Unregister port mapping on the external interface to internal interface.
*
* @param proto target protocol
* @param mport mapped port
*/
u8_t
ip_portmap_remove(u8_t proto, u16_t mport);
#endif /* IP_NAPT */
#endif /* IP_FORWARD */
#endif /* ESP_LWIP */
#ifdef __cplusplus
}
#endif
#endif /* __LWIP_NAPT_H__ */
+3
View File
@@ -403,6 +403,9 @@ struct netif {
u8_t reschedule_poll;
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
#endif /* ENABLE_LOOPBACK */
#if LWIP_IPV4 && IP_NAPT
u8_t napt;
#endif /*LWIP_IPV4 && IP_NAPT */
};
#if LWIP_CHECKSUM_CTRL_PER_NETIF
+15
View File
@@ -771,6 +771,14 @@
#define IP_FRAG 0
#endif /* !LWIP_IPV4 */
/**
* IP_NAPT==1: Enables IPv4 Network Address and Port Translation
* Note that IP_FORWARD needs to be enabled for NAPT to work
*/
#if !defined IP_NAPT || defined __DOXYGEN__
#define IP_NAPT 0
#endif
/**
* IP_OPTIONS_ALLOWED: Defines the behavior for IP options.
* IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped.
@@ -3571,6 +3579,13 @@
#define LWIP_TESTMODE 0
#endif
/**
* NAPT_DEBUG: Enable debugging for NAPT.
*/
#ifndef NAPT_DEBUG
#define NAPT_DEBUG LWIP_DBG_OFF
#endif
/*
--------------------------------------------------
---------- Performance tracking options ----------
+1 -1
View File
@@ -24,7 +24,7 @@ make -j 4 check
make clean
export EXTRA_CFLAGS="-DESP_LWIP=1 -DIP_FORWARD=1 -DIP_NAPT=1" && export CC="${ORIG_CC} ${EXTRA_CFLAGS}"
make -j 4 check
# Please uncomment the below to test IP_FORWARD/IP_NAPT tests with debug output (only ip4_route test suite will be executed)
# test only ip4_route with debug options enabled
make clean
export EXTRA_CFLAGS="-DESP_LWIP=1 -DIP_FORWARD=1 -DESP_TEST_DEBUG=1 -DIP_NAPT=1" && export CC="${ORIG_CC} ${EXTRA_CFLAGS}"
make -j 4 check
+1
View File
@@ -23,6 +23,7 @@ set(LWIP_TESTFILES
${LWIP_TESTDIR}/core/test_netif.c
${LWIP_TESTDIR}/core/test_pbuf.c
${LWIP_TESTDIR}/core/test_timers.c
${LWIP_TESTDIR}/core/test_ip4_route.c
${LWIP_TESTDIR}/dhcp/test_dhcp.c
${LWIP_TESTDIR}/etharp/test_etharp.c
${LWIP_TESTDIR}/ip4/test_ip4.c
+1
View File
@@ -37,6 +37,7 @@ TESTFILES=$(TESTDIR)/lwip_unittests.c \
$(TESTDIR)/core/test_dns.c \
$(TESTDIR)/core/test_mem.c \
$(TESTDIR)/core/test_netif.c \
$(TESTDIR)/core/test_ip4_route.c \
$(TESTDIR)/core/test_pbuf.c \
$(TESTDIR)/core/test_timers.c \
$(TESTDIR)/dhcp/test_dhcp.c \
+88
View File
@@ -0,0 +1,88 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef LWIP_ARCH_CC_ESP_H
#define LWIP_ARCH_CC_ESP_H
/* see https://sourceforge.net/p/predef/wiki/OperatingSystems/ */
#if defined __ANDROID__
#define LWIP_UNIX_ANDROID
#elif defined __linux__
#define LWIP_UNIX_LINUX
#elif defined __APPLE__
#define LWIP_UNIX_MACH
#elif defined __OpenBSD__
#define LWIP_UNIX_OPENBSD
#elif defined __CYGWIN__
#define LWIP_UNIX_CYGWIN
#elif defined __GNU__
#define LWIP_UNIX_HURD
#endif
#define LWIP_TIMEVAL_PRIVATE 0
#include <sys/time.h>
#define LWIP_ERRNO_INCLUDE <errno.h>
#if defined(LWIP_UNIX_LINUX) || defined(LWIP_UNIX_HURD)
#define LWIP_ERRNO_STDINCLUDE 1
#endif
#ifdef LWIP_RAND
#define LWIP_RAND() ((u32_t)rand())
#endif
/* different handling for unit test, normally not needed */
#ifdef LWIP_NOASSERT_ON_ERROR
#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
handler;}} while(0)
#endif
#if defined(LWIP_UNIX_ANDROID) && defined(FD_SET)
typedef __kernel_fd_set fd_set;
#endif
#if defined(LWIP_UNIX_MACH)
/* sys/types.h and signal.h bring in Darwin byte order macros. pull the
header here and disable LwIP's version so that apps still can get
the macros via LwIP headers and use system headers */
#include <sys/types.h>
#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
#endif
struct sio_status_s;
typedef struct sio_status_s sio_status_t;
#define sio_fd_t sio_status_t*
#define __sio_fd_t_defined
typedef unsigned int sys_prot_t;
#endif /* LWIP_ARCH_CC_ESP_H */
+561
View File
@@ -0,0 +1,561 @@
#include "test_ip4_route.h"
#include "lwip/netif.h"
#include "lwip/stats.h"
#include "lwip/etharp.h"
#include "netif/ethernet.h"
#include "lwip/ip4.h"
#include "lwip/udp.h"
#include "lwip/inet_chksum.h"
#include "lwip/stats.h"
#include "lwip/prot/ip.h"
#include "lwip/prot/ip4.h"
#include "lwip/lwip_napt.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/tcpip.h"
#if !LWIP_IPV4 || !IP_REASSEMBLY || !MIB2_STATS || !IPFRAG_STATS
#error "This tests needs LWIP_IPV4, IP_REASSEMBLY; MIB2- and IPFRAG-statistics enabled"
#endif
#if !LWIP_NETIF_EXT_STATUS_CALLBACK
#error "This tests needs LWIP_NETIF_EXT_STATUS_CALLBACK enabled"
#endif
static struct netif sta;
static struct netif ap;
static int ap_cnt = 0;
static int sta_cnt = 0;
static u32_t last_src_addr = 0;
static u32_t last_dst_addr = 0;
static u16_t last_src_port = 0;
#if IP_NAPT
static int random_mock = -1;
/* Mock the esp-random to return 0 for easier result checking */
uint32_t esp_random(void)
{
if (random_mock == -1) {
/* fall back to default "port/unix" rand (if other tests are launched with IP_NAPT ON) */
return rand();
}
return random_mock;
}
#endif
/* Setups/teardown functions */
static void
ip4route_setup(void)
{
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
}
static void
ip4route_teardown(void)
{
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
}
/* test helper functions */
static void debug_print_packet(struct pbuf *q)
{
struct ip_hdr *iphdr = (struct ip_hdr *)q->payload;
u16_t iphdr_hlen;
iphdr_hlen = IPH_HL_BYTES(iphdr);
fail_unless(0 == inet_chksum((struct ip_hdr *)q->payload, iphdr_hlen));
ip4_debug_print(q);
last_src_addr = iphdr->src.addr;
last_dst_addr = iphdr->dest.addr;
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
struct udp_hdr *udphdr = (struct udp_hdr *)(( u8_t *)iphdr + iphdr_hlen);
udp_debug_print(udphdr);
LWIP_DEBUGF(UDP_DEBUG, ("udp ("));
ip_addr_debug_print_val(UDP_DEBUG, *ip_current_dest_addr());
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", lwip_ntohs(udphdr->dest)));
ip_addr_debug_print_val(UDP_DEBUG, *ip_current_src_addr());
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", lwip_ntohs(udphdr->src)));
last_src_port = udphdr->src;
} else if (IPH_PROTO(iphdr) == IP_PROTO_TCP) {
struct tcp_hdr* tcphdr;
pbuf_header(q, -(s16_t)sizeof(struct ip_hdr));
tcphdr = (struct tcp_hdr*)q->payload;
tcp_debug_print(tcphdr);
last_src_port = tcphdr->src;
}
}
static err_t
ap_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
{
ap_cnt++;
debug_print_packet(q);
LWIP_UNUSED_ARG(netif);
LWIP_UNUSED_ARG(q);
LWIP_UNUSED_ARG(ipaddr);
return ERR_OK;
}
static err_t
sta_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
{
sta_cnt++;
debug_print_packet(q);
LWIP_UNUSED_ARG(netif);
LWIP_UNUSED_ARG(q);
LWIP_UNUSED_ARG(ipaddr);
return ERR_OK;
}
static err_t
sta_tx_func(struct netif *netif, struct pbuf *p)
{
LWIP_UNUSED_ARG(netif);
LWIP_UNUSED_ARG(p);
return ERR_OK;
}
static err_t
ap_tx_func(struct netif *netif, struct pbuf *p)
{
LWIP_UNUSED_ARG(netif);
LWIP_UNUSED_ARG(p);
return ERR_OK;
}
#if IP_NAPT
static struct pbuf*
test_create_tcp_packet(u32_t src_ip4, u32_t dst_ip4,
u16_t src_port, u16_t dst_port,
u32_t seqno, u32_t ackno, u8_t headerflags, u16_t wnd)
{
struct pbuf *p, *q;
ip_addr_t src_ip;
ip_addr_t dst_ip;
struct ip_hdr* iphdr;
struct tcp_hdr* tcphdr;
u16_t pbuf_len = (u16_t)(sizeof(struct ip_hdr) + sizeof(struct tcp_hdr));
src_ip.u_addr.ip4.addr = src_ip4;
dst_ip.u_addr.ip4.addr = dst_ip4;
p = pbuf_alloc(PBUF_RAW, pbuf_len, PBUF_POOL);
EXPECT_RETNULL(p != NULL);
/* first pbuf must be big enough to hold the headers */
EXPECT_RETNULL(p->len >= (sizeof(struct ip_hdr) + sizeof(struct tcp_hdr)));
for(q = p; q != NULL; q = q->next) {
memset(q->payload, 0, q->len);
}
iphdr = (struct ip_hdr*)p->payload;
/* fill IP header */
iphdr->dest.addr = ip_2_ip4(&dst_ip)->addr;
iphdr->src.addr = ip_2_ip4(&src_ip)->addr;
IPH_VHL_SET(iphdr, 4, IP_HLEN / 4);
IPH_TOS_SET(iphdr, 0);
IPH_LEN_SET(iphdr, htons(p->tot_len));
iphdr->_ttl = 32;
iphdr->_proto = IP_PROTO_TCP;
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
/* let p point to TCP header */
pbuf_header(p, -(s16_t)sizeof(struct ip_hdr));
tcphdr = (struct tcp_hdr*)p->payload;
tcphdr->src = htons(src_port);
tcphdr->dest = htons(dst_port);
tcphdr->seqno = htonl(seqno);
tcphdr->ackno = htonl(ackno);
TCPH_HDRLEN_SET(tcphdr, sizeof(struct tcp_hdr)/4);
TCPH_FLAGS_SET(tcphdr, headerflags);
tcphdr->wnd = htons(wnd);
/* calculate checksum */
tcphdr->chksum = ip_chksum_pseudo(p,
IP_PROTO_TCP, p->tot_len, &src_ip, &dst_ip);
pbuf_header(p, sizeof(struct ip_hdr));
return p;
}
#endif
static struct pbuf *
test_udp_create_test_packet(u16_t length, u16_t dst_port, u16_t src_port, u32_t dst_addr, u32_t src_addr)
{
err_t err;
u8_t ret;
struct udp_hdr *uh;
struct ip_hdr *ih;
struct pbuf *p;
const u8_t test_data[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
p = pbuf_alloc(PBUF_TRANSPORT, length, PBUF_POOL);
fail_unless(p != NULL);
if (p == NULL) {
return NULL;
}
fail_unless(p->next == NULL);
err = pbuf_take(p, test_data, length);
fail_unless(err == ERR_OK);
/* add UDP header */
ret = pbuf_add_header(p, sizeof(struct udp_hdr));
fail_unless(!ret);
uh = (struct udp_hdr *)p->payload;
uh->chksum = 0;
uh->dest = lwip_htons(dst_port);
uh->src = lwip_htons(src_port);
uh->len = lwip_htons(p->tot_len);
/* add IPv4 header */
ret = pbuf_add_header(p, sizeof(struct ip_hdr));
fail_unless(!ret);
ih = (struct ip_hdr *)p->payload;
memset(ih, 0, sizeof(*ih));
ih->dest.addr = dst_addr;
ih->src.addr = src_addr;
ih->_len = lwip_htons(p->tot_len);
ih->_ttl = 32;
ih->_proto = IP_PROTO_UDP;
IPH_VHL_SET(ih, 4, sizeof(struct ip_hdr) / 4);
IPH_CHKSUM_SET(ih, inet_chksum(ih, sizeof(struct ip_hdr)));
return p;
}
static void
send_to_netif(struct netif *input_netif, struct pbuf *p)
{
err_t err;
if (p != NULL) {
err = ip4_input(p, input_netif);
fail_unless(err == ERR_OK);
}
}
static err_t
testif_init_sta(struct netif *netif)
{
netif->name[0] = 's';
netif->name[1] = 't';
netif->output = sta_output;
netif->linkoutput = sta_tx_func;
netif->mtu = 1500;
netif->hwaddr_len = 6;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6 | NETIF_FLAG_LINK_UP;
netif->hwaddr[0] = 0x02;
netif->hwaddr[1] = 0x03;
netif->hwaddr[2] = 0x04;
netif->hwaddr[3] = 0x05;
netif->hwaddr[4] = 0x06;
netif->hwaddr[5] = 0x08;
return ERR_OK;
}
static err_t
testif_init_ap(struct netif *netif)
{
netif->name[0] = 'a';
netif->name[1] = 'p';
netif->output = ap_output;
netif->linkoutput = ap_tx_func;
netif->mtu = 1500;
netif->hwaddr_len = 6;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6 | NETIF_FLAG_LINK_UP;
netif->hwaddr[0] = 0x02;
netif->hwaddr[1] = 0x03;
netif->hwaddr[2] = 0x04;
netif->hwaddr[3] = 0x05;
netif->hwaddr[4] = 0x06;
netif->hwaddr[5] = 0x07;
return ERR_OK;
}
/* Test functions */
START_TEST(test_ip4_route_netif_forward)
{
#define UDP_PORT 1234
ip4_addr_t addr, src_addr;
ip4_addr_t netmask;
ip4_addr_t gw;
struct pbuf *p;
LWIP_UNUSED_ARG(_i);
/* setup station */
IP4_ADDR(&addr, 1, 2, 4, 4);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 1, 2, 4, 10);
netif_add(&sta, &addr, &netmask, &gw, &sta, testif_init_sta, ethernet_input);
netif_set_up(&sta);
/* setup access point */
IP4_ADDR(&addr, 1, 2, 3, 5);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 1, 2, 3, 4);
netif_add(&ap, &addr, &netmask, &gw, &ap, testif_init_ap, ethernet_input);
netif_set_up(&ap);
/* create packet and send it to the AP */
IP4_ADDR(&addr, 1, 2, 4, 100);
IP4_ADDR(&src_addr, 1, 2, 3, 5);
p = test_udp_create_test_packet(16, UDP_PORT, UDP_PORT, addr.addr, src_addr.addr);
send_to_netif(&ap, p);
/* cleanup */
netif_set_down(&ap);
netif_remove(&ap);
netif_set_down(&sta);
netif_remove(&sta);
fail_unless(ap_cnt == 0);
#if IP_FORWARD
fail_unless(sta_cnt == 1);
fail_unless(last_src_port == lwip_ntohs(UDP_PORT));
fail_unless(last_src_addr == src_addr.addr);
#else
/* if IP FORWARD disabled, no packet to be found on the other interface */
fail_unless(sta_cnt == 0);
#endif
#undef UDP_PORT
}
END_TEST
#if IP_NAPT
START_TEST(test_ip4_route_netif_napt_udp)
{
#define UDP_PORT 1234
ip4_addr_t addr, src_addr, sta_addr;
ip4_addr_t netmask;
ip4_addr_t gw;
struct pbuf *p;
LWIP_UNUSED_ARG(_i);
/* setup station */
IP4_ADDR(&sta_addr, 1, 2, 4, 4);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 1, 2, 4, 10);
netif_add(&sta, &sta_addr, &netmask, &gw, &sta, testif_init_sta, ethernet_input);
netif_set_up(&sta);
/* setup access point */
IP4_ADDR(&addr, 10, 0, 0, 1);
IP4_ADDR(&netmask, 255, 255, 0, 0);
IP4_ADDR(&gw, 10, 0, 0, 1);
netif_add(&ap, &addr, &netmask, &gw, &ap, testif_init_ap, ethernet_input);
netif_set_up(&ap);
ip_napt_enable(addr.addr, 1);
/* create packet and send it to the AP */
IP4_ADDR(&addr, 1, 2, 4, 100);
IP4_ADDR(&src_addr, 10, 0, 0, 2);
p = test_udp_create_test_packet(16, UDP_PORT, UDP_PORT, addr.addr, src_addr.addr);
random_mock = 1;
send_to_netif(&ap, p);
/* expect to see a random port and translated source address to be station address */
fail_unless(last_src_port == lwip_ntohs(IP_NAPT_PORT_RANGE_START+random_mock));
fail_unless(last_src_addr == sta_addr.addr);
fail_unless(ap_cnt == 0);
fail_unless(sta_cnt == 1);
p = test_udp_create_test_packet(16, IP_NAPT_PORT_RANGE_START+random_mock, UDP_PORT, sta_addr.addr, addr.addr);
send_to_netif(&sta, p);
fail_unless(ap_cnt == 1);
fail_unless(sta_cnt == 1);
/* expect to see a random port and translated source address to be station address */
fail_unless(last_src_port == lwip_ntohs(UDP_PORT));
fail_unless(last_dst_addr == src_addr.addr);
/* cleanup */
netif_set_down(&ap);
netif_remove(&ap);
netif_set_down(&sta);
netif_remove(&sta);
IP4_ADDR(&addr, 10, 0, 0, 1);
ip_napt_enable(addr.addr, 0);
#undef UDP_PORT
}
END_TEST
START_TEST(test_ip4_route_netif_napt_tcp)
{
#define TCP_PORT 2222
ip4_addr_t addr, src_addr, sta_addr;
ip4_addr_t netmask;
ip4_addr_t gw;
struct pbuf *p;
LWIP_UNUSED_ARG(_i);
/* setup station */
IP4_ADDR(&sta_addr, 1, 2, 4, 4);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 1, 2, 4, 10);
netif_add(&sta, &sta_addr, &netmask, &gw, &sta, testif_init_sta, ethernet_input);
netif_set_up(&sta);
/* setup access point */
IP4_ADDR(&addr, 10, 0, 0, 1);
IP4_ADDR(&netmask, 255, 255, 0, 0);
IP4_ADDR(&gw, 10, 0, 0, 1);
netif_add(&ap, &addr, &netmask, &gw, &ap, testif_init_ap, ethernet_input);
netif_set_up(&ap);
ip_napt_enable_no(ap.num, 1);
/* create packet and send it to the AP */
IP4_ADDR(&addr, 1, 2, 4, 100);
IP4_ADDR(&src_addr, 10, 0, 0, 2);
p = test_create_tcp_packet(src_addr.addr, addr.addr, TCP_PORT, TCP_PORT, 0, 0, TCP_SYN, 0);
random_mock = 2;
send_to_netif(&ap, p);
/* expect to see a random port and translated source address to be station address */
fail_unless(last_src_port == lwip_ntohs(IP_NAPT_PORT_RANGE_START+random_mock));
fail_unless(last_src_addr == sta_addr.addr);
fail_unless(ap_cnt == 0);
fail_unless(sta_cnt == 1);
p = test_create_tcp_packet(addr.addr, sta_addr.addr, TCP_PORT, IP_NAPT_PORT_RANGE_START+random_mock, 0, 0, TCP_SYN|TCP_ACK, 0);
send_to_netif(&sta, p);
fail_unless(ap_cnt == 1);
fail_unless(sta_cnt == 1);
/* expect to see a random port and translated source address to be station address */
fail_unless(last_src_port == lwip_ntohs(TCP_PORT));
fail_unless(last_dst_addr == src_addr.addr);
/* cleanup */
ip_napt_enable_no(ap.num, 0);
netif_set_down(&ap);
netif_remove(&ap);
netif_set_down(&sta);
netif_remove(&sta);
#undef TCP_PORT
}
END_TEST
START_TEST(test_ip4_route_netif_max_napt)
{
#define TCP_PORT 2222
ip4_addr_t addr, src_addr, sta_addr;
ip4_addr_t netmask;
ip4_addr_t gw;
struct pbuf *p;
int i;
LWIP_UNUSED_ARG(_i);
/* setup station */
IP4_ADDR(&sta_addr, 1, 2, 4, 4);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 1, 2, 4, 10);
netif_add(&sta, &sta_addr, &netmask, &gw, &sta, testif_init_sta, ethernet_input);
netif_set_up(&sta);
/* setup access point */
IP4_ADDR(&addr, 10, 0, 0, 1);
IP4_ADDR(&netmask, 255, 255, 0, 0);
IP4_ADDR(&gw, 10, 0, 0, 1);
netif_add(&ap, &addr, &netmask, &gw, &ap, testif_init_ap, ethernet_input);
netif_set_up(&ap);
ip_napt_enable_no(ap.num, 1);
/* create packet and send it to the AP */
IP4_ADDR(&addr, 1, 2, 4, 100);
IP4_ADDR(&src_addr, 10, 0, 0, 2);
for (i=0; i<IP_NAPT_MAX*2; ++i) {
random_mock = i;
p = test_create_tcp_packet(src_addr.addr, addr.addr, TCP_PORT + i, TCP_PORT + i, 0, 0, TCP_SYN, 0);
send_to_netif(&ap, p);
if (i<IP_NAPT_MAX) {
/* if translated pairs of addr/port still below IP_NAT_MAX -> expect to see an outgoing packet */
fail_unless(last_src_port == lwip_ntohs(IP_NAPT_PORT_RANGE_START+random_mock));
fail_unless(last_src_addr == sta_addr.addr);
fail_unless(sta_cnt == 1+i);
p = test_create_tcp_packet(addr.addr, sta_addr.addr, TCP_PORT+i, IP_NAPT_PORT_RANGE_START+random_mock, 0, 0, TCP_SYN | TCP_ACK, 0);
send_to_netif(&sta, p);
} else {
/* if more than NAPT_MAX, no more packet to be forwarded */
fail_unless(sta_cnt == IP_NAPT_MAX);
}
}
/* moves time forward to test releasing: */
lwip_sys_now += IP_NAPT_TIMEOUT_MS_TCP_DISCON + 1;
p = test_create_tcp_packet(addr.addr, sta_addr.addr, TCP_PORT, IP_NAPT_PORT_RANGE_START+0, 0, 0, TCP_PSH, 0);
send_to_netif(&sta, p);
p = test_create_tcp_packet(src_addr.addr, addr.addr, TCP_PORT + IP_NAPT_MAX*2, TCP_PORT + IP_NAPT_MAX*2, 0, 0, TCP_PSH | TCP_ACK, 0);
sta_cnt = 0;
send_to_netif(&ap, p);
/* should not be released yet, since all the TCP connections are active */
fail_unless(sta_cnt == 0); /* expect no packet forwarded */
/* FIN the first connection so it could be released */
p = test_create_tcp_packet(addr.addr, sta_addr.addr, TCP_PORT+0, IP_NAPT_PORT_RANGE_START+0, 0, 0, TCP_FIN, 0);
send_to_netif(&sta, p);
p = test_create_tcp_packet(src_addr.addr, addr.addr, TCP_PORT+0, TCP_PORT + 0, 0, 0, TCP_FIN | TCP_ACK, 0);
send_to_netif(&ap, p);
p = test_create_tcp_packet(addr.addr, sta_addr.addr, TCP_PORT+0, IP_NAPT_PORT_RANGE_START+0, 0, 0, TCP_ACK, 0);
send_to_netif(&sta, p);
/* moves time forward to test releasing: */
lwip_sys_now += IP_NAPT_TIMEOUT_MS_TCP_DISCON + 1;
/* now sending a new packet with max port, that should be forwarded */
p = test_create_tcp_packet(src_addr.addr, addr.addr, TCP_PORT + IP_NAPT_MAX*2, TCP_PORT + IP_NAPT_MAX*2, 0, 0, TCP_SYN, 0);
random_mock = 0;
sta_cnt = 0;
send_to_netif(&ap, p);
fail_unless(last_src_port == lwip_ntohs(IP_NAPT_PORT_RANGE_START+0));
fail_unless(last_src_addr == sta_addr.addr);
fail_unless(sta_cnt == 1); /* expect this packet gets forwarded */
/* cleanup */
netif_set_down(&ap);
ip_napt_enable_no(ap.num, 0);
netif_remove(&ap);
netif_set_down(&sta);
netif_remove(&sta);
#undef TCP_PORT
}
END_TEST
#endif
/** Create the suite including all tests for this module */
Suite *
ip4route_suite(void)
{
testfunc tests[] = {
TESTFUNC(test_ip4_route_netif_forward),
#if IP_NAPT
TESTFUNC(test_ip4_route_netif_napt_udp),
TESTFUNC(test_ip4_route_netif_napt_tcp),
TESTFUNC(test_ip4_route_netif_max_napt),
#endif
};
return create_suite("IP4_ROUTE", tests, sizeof(tests)/sizeof(testfunc), ip4route_setup, ip4route_teardown);
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef LWIP_HDR_TEST_IP4ROUTE_H
#define LWIP_HDR_TEST_IP4ROUTE_H
#include "../lwip_check.h"
Suite *ip4route_suite(void);
#endif
+6 -2
View File
@@ -10,6 +10,7 @@
#include "core/test_dns.h"
#include "core/test_mem.h"
#include "core/test_netif.h"
#include "core/test_ip4_route.h"
#include "core/test_pbuf.h"
#include "core/test_timers.h"
#include "etharp/test_etharp.h"
@@ -75,6 +76,7 @@ int main(void)
SRunner *sr;
size_t i;
suite_getter_fn* suites[] = {
#ifndef ESP_TEST_DEBUG
ip4_suite,
ip6_suite,
udp_suite,
@@ -91,10 +93,12 @@ int main(void)
dhcp_suite,
mdns_suite,
mqtt_suite,
sockets_suite
sockets_suite,
#if PPP_SUPPORT && PPPOS_SUPPORT
, pppos_suite
pppos_suite,
#endif /* PPP_SUPPORT && PPPOS_SUPPORT */
#endif /* ESP_TEST_DEBUG */
ip4route_suite
};
size_t num = sizeof(suites)/sizeof(void*);
LWIP_ASSERT("No suites defined", num > 0);
+15
View File
@@ -94,4 +94,19 @@
/* Enable Espressif specific options */
#define ESP_LWIP 1
#ifdef IP_NAPT
#define IP_NAPT_MAX 16
#include "lwip/arch.h"
#undef LWIP_RAND
#define LWIP_RAND() (esp_random())
u32_t esp_random(void);
#endif /* IP_NAPT */
/* ESP debug options */
#ifdef ESP_TEST_DEBUG
#define NAPT_DEBUG LWIP_DBG_ON
#define IP_DEBUG LWIP_DBG_ON
#define UDP_DEBUG LWIP_DBG_ON
#define TCP_DEBUG LWIP_DBG_ON
#endif /* ESP_TEST_DEBUG */
#endif /* LWIP_HDR_LWIPOPTS_H */