napt: added NAPT patches to 2.1.2

Closes https://github.com/espressif/esp-idf/issues/1527
Closes IDFGH-146
This commit is contained in:
martin-ger
2020-04-08 11:59:44 +02:00
committed by David Cermak
parent 5c181728c8
commit a3cacab60e
7 changed files with 935 additions and 79 deletions
+85 -75
View File
@@ -57,6 +57,7 @@
#include "lwip/nd6.h"
#include "lwip/mld6.h"
#include "lwip/api.h"
#include "lwip/lwip_napt.h"
#include "netif/ppp/ppp_opts.h"
#include "netif/ppp/ppp_impl.h"
@@ -67,7 +68,8 @@
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct packed_struct_test {
struct packed_struct_test
{
PACK_STRUCT_FLD_8(u8_t dummy1);
PACK_STRUCT_FIELD(u32_t dummy2);
} PACK_STRUCT_STRUCT;
@@ -83,183 +85,187 @@ PACK_STRUCT_END
* These can be done independently of LWIP_DEBUG, without penalty.
*/
#ifndef BYTE_ORDER
#error "BYTE_ORDER is not defined, you have to define it in your cc.h"
#error "BYTE_ORDER is not defined, you have to define it in your cc.h"
#endif
#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV)
#error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h"
#error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h"
#endif
#if (!LWIP_UDP && LWIP_UDPLITE)
#error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h"
#error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h"
#endif
#if (!LWIP_UDP && LWIP_DHCP)
#error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h"
#error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h"
#endif
#if (!LWIP_UDP && !LWIP_RAW && LWIP_MULTICAST_TX_OPTIONS)
#error "If you want to use LWIP_MULTICAST_TX_OPTIONS, you have to define LWIP_UDP=1 and/or LWIP_RAW=1 in your lwipopts.h"
#if (!LWIP_UDP && LWIP_MULTICAST_TX_OPTIONS)
#error "If you want to use IGMP/LWIP_MULTICAST_TX_OPTIONS, you have to define LWIP_UDP=1 in your lwipopts.h"
#endif
#if (!LWIP_UDP && LWIP_DNS)
#error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h"
#error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h"
#endif
#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */
#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0))
#error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h"
#error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h"
#endif
#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0))
#error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h"
#error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h"
#endif
#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0))
#error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h"
#error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h"
#endif
#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0))
#error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h"
#error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h"
#endif
#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1))
#error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h"
#error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h"
#endif
#if (LWIP_IGMP && !LWIP_MULTICAST_TX_OPTIONS)
#error "If you want to use IGMP, you have to define LWIP_MULTICAST_TX_OPTIONS==1 in your lwipopts.h"
#error "If you want to use IGMP, you have to define LWIP_MULTICAST_TX_OPTIONS==1 in your lwipopts.h"
#endif
#if (LWIP_IGMP && !LWIP_IPV4)
#error "IGMP needs LWIP_IPV4 enabled in your lwipopts.h"
#error "IGMP needs LWIP_IPV4 enabled in your lwipopts.h"
#endif
#if (LWIP_MULTICAST_TX_OPTIONS && !LWIP_IPV4)
#error "LWIP_MULTICAST_TX_OPTIONS needs LWIP_IPV4 enabled in your lwipopts.h"
#endif
#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0))
#error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h"
#error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h"
#endif
/* There must be sufficient timeouts, taking into account requirements of the subsystems. */
#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < LWIP_NUM_SYS_TIMEOUT_INTERNAL)
#error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts"
#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)))
#error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts"
#endif
#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS))
#error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!"
#error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!"
#endif
#endif /* !MEMP_MEM_MALLOC */
#if LWIP_WND_SCALE
#if (LWIP_TCP && (TCP_WND > 0xffffffff))
#error "If you want to use TCP, TCP_WND must fit in an u32_t, so, you have to reduce it in your lwipopts.h"
#error "If you want to use TCP, TCP_WND must fit in an u32_t, so, you have to reduce it in your lwipopts.h"
#endif
#if (LWIP_TCP && (TCP_RCV_SCALE > 14))
#error "The maximum valid window scale value is 14!"
#error "The maximum valid window scale value is 14!"
#endif
#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE)))
#error "TCP_WND is bigger than the configured LWIP_WND_SCALE allows!"
#error "TCP_WND is bigger than the configured LWIP_WND_SCALE allows!"
#endif
#if (LWIP_TCP && ((TCP_WND >> TCP_RCV_SCALE) == 0))
#error "TCP_WND is too small for the configured LWIP_WND_SCALE (results in zero window)!"
#error "TCP_WND is too small for the configured LWIP_WND_SCALE (results in zero window)!"
#endif
#else /* LWIP_WND_SCALE */
#if (LWIP_TCP && (TCP_WND > 0xffff))
#error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)"
#error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)"
#endif
#endif /* LWIP_WND_SCALE */
#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff))
#error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
#error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
#endif
#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2))
#error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work"
#error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work"
#endif
#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12)))
#error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h"
#error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h"
#endif
#if (LWIP_TCP && TCP_LISTEN_BACKLOG && ((TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff)))
#error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t"
#endif
#if (LWIP_TCP && LWIP_TCP_SACK_OUT && !TCP_QUEUE_OOSEQ)
#error "To use LWIP_TCP_SACK_OUT, TCP_QUEUE_OOSEQ needs to be enabled"
#endif
#if (LWIP_TCP && LWIP_TCP_SACK_OUT && (LWIP_TCP_MAX_SACK_NUM < 1))
#error "LWIP_TCP_MAX_SACK_NUM must be greater than 0"
#error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t"
#endif
#if (LWIP_NETIF_API && (NO_SYS==1))
#error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h"
#error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h"
#endif
#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1))
#error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h"
#error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h"
#endif
#if (LWIP_PPP_API && (NO_SYS==1))
#error "If you want to use PPP API, you have to define NO_SYS=0 in your lwipopts.h"
#error "If you want to use PPP API, you have to define NO_SYS=0 in your lwipopts.h"
#endif
#if (LWIP_PPP_API && (PPP_SUPPORT==0))
#error "If you want to use PPP API, you have to enable PPP_SUPPORT in your lwipopts.h"
#error "If you want to use PPP API, you have to enable PPP_SUPPORT in your lwipopts.h"
#endif
#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP)
#error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h"
#error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h"
#endif
#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK)
#error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h"
#error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h"
#endif
#if (!LWIP_ARP && LWIP_AUTOIP)
#error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h"
#error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h"
#endif
#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API)))
#error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h"
#endif
#if (LWIP_ALTCP && LWIP_EVENT_API)
#error "The application layered tcp API does not work with LWIP_EVENT_API"
#error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h"
#endif
#if (MEM_LIBC_MALLOC && MEM_USE_POOLS)
#error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h"
#error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h"
#endif
#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS)
#error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h"
#error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h"
#endif
#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT)
#error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf"
#error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf"
#endif
#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT)))
#error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST"
#error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST"
#endif
#if PPP_SUPPORT && !PPPOS_SUPPORT && !PPPOE_SUPPORT && !PPPOL2TP_SUPPORT
#error "PPP_SUPPORT needs at least one of PPPOS_SUPPORT, PPPOE_SUPPORT or PPPOL2TP_SUPPORT turned on"
#error "PPP_SUPPORT needs at least one of PPPOS_SUPPORT, PPPOE_SUPPORT or PPPOL2TP_SUPPORT turned on"
#endif
#if PPP_SUPPORT && !PPP_IPV4_SUPPORT && !PPP_IPV6_SUPPORT
#error "PPP_SUPPORT needs PPP_IPV4_SUPPORT and/or PPP_IPV6_SUPPORT turned on"
#error "PPP_SUPPORT needs PPP_IPV4_SUPPORT and/or PPP_IPV6_SUPPORT turned on"
#endif
#if PPP_SUPPORT && PPP_IPV4_SUPPORT && !LWIP_IPV4
#error "PPP_IPV4_SUPPORT needs LWIP_IPV4 turned on"
#error "PPP_IPV4_SUPPORT needs LWIP_IPV4 turned on"
#endif
#if PPP_SUPPORT && PPP_IPV6_SUPPORT && !LWIP_IPV6
#error "PPP_IPV6_SUPPORT needs LWIP_IPV6 turned on"
#error "PPP_IPV6_SUPPORT needs LWIP_IPV6 turned on"
#endif
#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT)
#error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT"
#error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT"
#endif
#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING
#error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too"
#error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too"
#endif
#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE
#error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets"
#error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets"
#endif
#if LWIP_NETCONN && LWIP_TCP
#if NETCONN_COPY != TCP_WRITE_FLAG_COPY
#error "NETCONN_COPY != TCP_WRITE_FLAG_COPY"
#error "NETCONN_COPY != TCP_WRITE_FLAG_COPY"
#endif
#if NETCONN_MORE != TCP_WRITE_FLAG_MORE
#error "NETCONN_MORE != TCP_WRITE_FLAG_MORE"
#error "NETCONN_MORE != TCP_WRITE_FLAG_MORE"
#endif
#endif /* LWIP_NETCONN && LWIP_TCP */
#if LWIP_SOCKET
/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */
#if SO_REUSEADDR != SOF_REUSEADDR
#error "WARNING: SO_REUSEADDR != SOF_REUSEADDR"
#endif
#if SO_KEEPALIVE != SOF_KEEPALIVE
#error "WARNING: SO_KEEPALIVE != SOF_KEEPALIVE"
#endif
#if SO_BROADCAST != SOF_BROADCAST
#error "WARNING: SO_BROADCAST != SOF_BROADCAST"
#endif
#endif /* LWIP_SOCKET */
/* Compile-time checks for deprecated options.
*/
#ifdef MEMP_NUM_TCPIP_MSG
#error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h."
#error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h."
#endif
#ifdef TCP_REXMIT_DEBUG
#error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h."
#error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h."
#endif
#ifdef RAW_STATS
#error "RAW_STATS option is deprecated. Remove it from your lwipopts.h."
#error "RAW_STATS option is deprecated. Remove it from your lwipopts.h."
#endif
#ifdef ETHARP_QUEUE_FIRST
#error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h."
#error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h."
#endif
#ifdef ETHARP_ALWAYS_INSERT
#error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h."
#error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h."
#endif
#if !NO_SYS && LWIP_TCPIP_CORE_LOCKING && LWIP_COMPAT_MUTEX && !defined(LWIP_COMPAT_MUTEX_ALLOWED)
#error "LWIP_COMPAT_MUTEX cannot prevent priority inversion. It is recommended to implement priority-aware mutexes. (Define LWIP_COMPAT_MUTEX_ALLOWED to disable this error.)"
#error "LWIP_COMPAT_MUTEX cannot prevent priority inversion. It is recommended to implement priority-aware mutexes. (Define LWIP_COMPAT_MUTEX_ALLOWED to disable this error.)"
#endif
#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS
@@ -294,31 +300,31 @@ PACK_STRUCT_END
#if !LWIP_DISABLE_TCP_SANITY_CHECKS
#if LWIP_TCP
#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN)
#error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif
#if TCP_SND_BUF < (2 * TCP_MSS)
#error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif
#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS))
#error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif
#if TCP_SNDLOWAT >= TCP_SND_BUF
#error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif
#if TCP_SNDLOWAT >= (0xFFFF - (4 * TCP_MSS))
#error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must at least be 4*MSS below u16_t overflow!"
#error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must at least be 4*MSS below u16_t overflow!"
#endif
#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN
#error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif
#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN))
#error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif
#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN))))
#error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif
#if TCP_WND < TCP_MSS
#error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
#endif
#endif /* LWIP_TCP */
#endif /* !LWIP_DISABLE_TCP_SANITY_CHECKS */
@@ -334,7 +340,7 @@ lwip_init(void)
#ifndef LWIP_SKIP_CONST_CHECK
int a = 0;
LWIP_UNUSED_ARG(a);
LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void *, &a) == &a);
LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void*, &a) == &a);
#endif
#ifndef LWIP_SKIP_PACKING_CHECK
LWIP_ASSERT("Struct packing not implemented correctly. Check your lwIP port.", sizeof(struct packed_struct_test) == PACKED_STRUCT_TEST_EXPECTED_SIZE);
@@ -373,8 +379,12 @@ lwip_init(void)
#if PPP_SUPPORT
ppp_init();
#endif
#if LWIP_TIMERS
sys_timeouts_init();
#endif /* LWIP_TIMERS */
#if IP_NAPT && !IP_NAPT_DYNAMIC
ip_napt_init(IP_NAPT_MAX, IP_PORTMAP_MAX);
#endif /* IP_NAPT */
}
+710 -2
View File
@@ -42,6 +42,7 @@
#if LWIP_IPV4
#include "lwip/sys.h"
#include "lwip/ip.h"
#include "lwip/def.h"
#include "lwip/mem.h"
@@ -56,6 +57,7 @@
#include "lwip/autoip.h"
#include "lwip/stats.h"
#include "lwip/prot/iana.h"
#include "lwip/lwip_napt.h"
#include <string.h>
@@ -279,6 +281,699 @@ ip4_route(const ip4_addr_t *dest)
}
#if IP_FORWARD
#if IP_NAPT
#define NO_IDX ((u16_t)-1)
#define NT(x) ((x) == NO_IDX ? NULL : &ip_napt_table[x])
u16_t napt_list = NO_IDX, napt_list_last = NO_IDX, napt_free = 0;
static struct napt_table *ip_napt_table;
struct portmap_table *ip_portmap_table;
int nr_active_napt_tcp = 0, nr_active_napt_udp = 0, nr_active_napt_icmp = 0;
uint16_t ip_napt_max = 0;
uint8_t ip_portmap_max = 0;
#if NAPT_DEBUG
/* Print NAPT table using LWIP_DEBUGF
*/
void
napt_debug_print()
{
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 */
void
ip_napt_init(uint16_t max_nat, uint8_t max_portmap)
{
u16_t i;
ip_napt_max = max_nat;
ip_portmap_max = max_portmap;
ip_napt_table = (struct napt_table*)calloc(1, sizeof(struct napt_table[ip_napt_max]));
ip_portmap_table = (struct portmap_table*)calloc(1, sizeof(struct portmap_table[ip_portmap_max]));
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;
for (netif = netif_list; netif; netif = netif->next) {
if (netif_is_up(netif) && !ip_addr_isany(&netif->ip_addr) && netif->ip_addr.u_addr.ip4.addr == addr) {
netif->napt = !!enable;
break;
}
}
}
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;
break;
}
}
}
void checksumadjust(unsigned char *chksum, unsigned char *optr,
int olen, unsigned char *nptr, int nlen)
/* assuming: unsigned char is 8 bits, long is 32 bits.
- chksum points to the chksum in the packet
- optr points to the old data in the packet
- nptr points to the new data in the packet
*/
{
long x, old, new;
x=chksum[0]*256+chksum[1];
x=~x & 0xFFFF;
while (olen)
{
old=optr[0]*256+optr[1]; optr+=2;
x-=old & 0xffff;
if (x<=0) { x--; x&=0xffff; }
olen-=2;
}
while (nlen)
{
new=nptr[0]*256+nptr[1]; nptr+=2;
x+=new & 0xffff;
if (x & 0x10000) { x++; x&=0xffff; }
nlen-=2;
}
x=~x & 0xFFFF;
chksum[0]=x/256; chksum[1]=x & 0xff;
}
/* t must be indexed by napt_free */
static void
ip_napt_insert(struct napt_table *t)
{
u16_t ti = t - ip_napt_table;
if (ti != napt_free) *((int*)1)=1; //DEBUG
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
//os_printf("T: %d, U: %d, I: %d\r\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 +
esp_random() % (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;
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
u32_t 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;
}
return 0;
}
u8_t
ip_portmap_add(u8_t proto, u32_t maddr, u16_t mport, u32_t daddr, u16_t dport)
{
mport = PP_HTONS(mport);
dport = PP_HTONS(dport);
int i;
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)
{
mport = PP_HTONS(mport);
struct portmap_table *last = &ip_portmap_table[ip_portmap_max - 1];
struct portmap_table *m = ip_portmap_find(proto, mport);
if (!m)
return 0;
for (; m != last; m++)
memcpy(m, m + 1, sizeof(*m));
last->valid = 0;
return 1;
}
#if LWIP_TCP
void
ip_napt_modify_port_tcp(struct tcp_hdr *tcphdr, u8_t dest, u16_t newval)
{
if (dest) {
checksumadjust((unsigned char *)&tcphdr->chksum, (unsigned char *)&tcphdr->dest, 2, (unsigned char *)&newval, 2);
tcphdr->dest = newval;
} else {
checksumadjust((unsigned char *)&tcphdr->chksum, (unsigned char *)&tcphdr->src, 2, (unsigned char *)&newval, 2);
tcphdr->src = newval;
}
}
void
ip_napt_modify_addr_tcp(struct tcp_hdr *tcphdr, ip4_addr_p_t *oldval, u32_t newval)
{
checksumadjust((unsigned char *)&tcphdr->chksum, (unsigned char *)&oldval->addr, 4, (unsigned char *)&newval, 4);
}
#endif // LWIP_TCP
#if LWIP_UDP
void
ip_napt_modify_port_udp(struct udp_hdr *udphdr, u8_t dest, u16_t newval)
{
if (dest) {
checksumadjust((unsigned char *)&udphdr->chksum, (unsigned char *)&udphdr->dest, 2, (unsigned char *)&newval, 2);
udphdr->dest = newval;
} else {
checksumadjust((unsigned char *)&udphdr->chksum, (unsigned char *)&udphdr->src, 2, (unsigned char *)&newval, 2);
udphdr->src = newval;
}
}
void
ip_napt_modify_addr_udp(struct udp_hdr *udphdr, ip4_addr_p_t *oldval, u32_t newval)
{
checksumadjust( (unsigned char *)&udphdr->chksum, (unsigned char *)&oldval->addr, 4, (unsigned char *)&newval, 4);
}
#endif // LWIP_UDP
void
ip_napt_modify_addr(struct ip_hdr *iphdr, ip4_addr_p_t *field, u32_t newval)
{
checksumadjust((unsigned char *)&IPH_CHKSUM(iphdr), (unsigned char *)&field->addr, 4, (unsigned char *)&newval, 4);
field->addr = newval;
}
/**
* NAPT for an input packet. It checks weather the destination is on NAPT
* table and modifythe 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
* @param inp the netif on which this packet was received
*/
static 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
}
/**
* 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
*/
static 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, outp->ip_addr.u_addr.ip4.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);
} 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, outp->ip_addr.u_addr.ip4.addr);
ip_napt_modify_addr(iphdr, &iphdr->src, outp->ip_addr.u_addr.ip4.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);
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);
} 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, outp->ip_addr.u_addr.ip4.addr);
ip_napt_modify_addr(iphdr, &iphdr->src, outp->ip_addr.u_addr.ip4.addr);
return ERR_OK;
}
#endif
return ERR_OK;
}
#endif // IP_NAPT
/**
* Determine whether an IP address is in a reserved set of addresses
* that may not be forwarded, or whether datagrams to that destination
@@ -380,6 +1075,11 @@ ip4_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
return;
}
#if IP_NAPT
if (ip_napt_forward(p, iphdr, inp, netif) != ERR_OK)
return;
#endif
/* 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));
@@ -476,7 +1176,7 @@ ip4_input_accept(struct netif *netif)
err_t
ip4_input(struct pbuf *p, struct netif *inp)
{
const struct ip_hdr *iphdr;
struct ip_hdr *iphdr;
struct netif *netif;
u16_t iphdr_hlen;
u16_t iphdr_len;
@@ -562,6 +1262,12 @@ ip4_input(struct pbuf *p, struct netif *inp)
}
#endif
#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
/* 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);
@@ -1031,7 +1737,9 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d
LWIP_DEBUGF(IP_DEBUG, ("ip4_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num));
ip4_debug_print(p);
#if ENABLE_LOOPBACK
#if 0 && ENABLE_LOOPBACK
/* doesn't work for external wifi interfaces */
if (ip4_addr_cmp(dest, netif_ip4_addr(netif))
#if !LWIP_HAVE_LOOPIF
|| ip4_addr_isloopback(dest)
+4
View File
@@ -367,6 +367,10 @@ netif_add(struct netif *netif,
netif->loop_cnt_current = 0;
#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
#if IP_NAPT
netif->napt = 0;
#endif /* IP_NAPT */
#if LWIP_IPV4
netif_set_addr(netif, ipaddr, netmask, gw);
#endif /* LWIP_IPV4 */
+6
View File
@@ -172,6 +172,12 @@ extern struct ip_globals ip_data;
/** Destination IP4 address of current_header */
#define ip4_current_dest_addr() (ip_2_ip4(&ip_data.current_iphdr_dest))
#if NAPT_DEBUG
void napt_debug_print()ICACHE_FLASH_ATTR;
#else
#define napt_debug_print(p)
#endif /* NAPT_DEBUG */
#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */
/** Get the IPv4 header of the current packet.
+114
View File
@@ -0,0 +1,114 @@
#ifndef __LWIP_NAPT_H__
#define __LWIP_NAPT_H__
#include "lwip/opt.h"
#ifdef __cplusplus
extern "C" {
#endif
#if IP_FORWARD
#if IP_NAPT
/* Default size of the tables used for NAPT */
#define IP_NAPT_MAX 512
#define IP_PORTMAP_MAX 32
/* 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
struct napt_table {
u32_t last;
u32_t src;
u32_t dest;
u16_t sport;
u16_t dport;
u16_t mport;
u8_t proto;
u8_t fin1 : 1;
u8_t fin2 : 1;
u8_t finack1 : 1;
u8_t finack2 : 1;
u8_t synack : 1;
u8_t 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;
};
extern struct portmap_table *ip_portmap_table;
/**
* 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)
*/
void ip_napt_init(uint16_t max_nat, uint8_t max_portmap);
/**
* 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 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 maddr ip address of the external interface
*/
u8_t
ip_portmap_remove(u8_t proto, u16_t mport);
#endif /* IP_NAPT */
#endif /* IP_FORWARD */
#ifdef __cplusplus
}
#endif
#endif /* __LWIP_NAPT_H__ */
+3
View File
@@ -410,6 +410,9 @@ struct netif {
void (*l2_buffer_free_notify)(struct netif *lwip_netif, void *user_buf); /* Allows LWIP to notify driver when a L2-supplied pbuf can be freed */
ip_addr_t last_ip_addr; /* Store last non-zero ip address */
#endif
#if LWIP_IPV4 && IP_NAPT
u8_t napt;
#endif
};
#if LWIP_CHECKSUM_CTRL_PER_NETIF
#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) do { \
+13 -2
View File
@@ -736,7 +736,7 @@
* interface, define this to 0.
*/
#if !defined IP_FORWARD || defined __DOXYGEN__
#define IP_FORWARD 0
#define IP_FORWARD 1
#endif
/**
@@ -767,6 +767,10 @@
#define IP_FRAG 0
#endif /* !LWIP_IPV4 */
#ifndef IP_NAPT
#define IP_NAPT 1
#endif
/**
* IP_OPTIONS_ALLOWED: Defines the behavior for IP options.
* IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped.
@@ -1114,7 +1118,7 @@
* transport.
*/
#if !defined LWIP_DNS || defined __DOXYGEN__
#define LWIP_DNS 0
#define LWIP_DNS 1
#endif
/** DNS maximum number of entries to maintain locally. */
@@ -3525,6 +3529,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 ----------