napt: cosmetic updates on NAPT functionality implemented by martin-ger

Overview of the changes:
- moved NAPT specific code from ip4.c to ip4_napt.c
- formatting updates to keep the changes easier to review
- updated per C-90 style used for lwip upstream (fixed warning,
renaming, lwip types)
- esp_random() -> LWIP_RAND()
- drop the connection with routing err if failed to add new napt record
- prepared for lwip unit testing
This commit is contained in:
David Cermak
2020-03-16 14:09:58 +01:00
parent a3cacab60e
commit 4b4d6b2871
11 changed files with 1045 additions and 830 deletions
+1
View File
@@ -61,6 +61,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
@@ -58,6 +58,7 @@ CORE4FILES=$(LWIPDIR)/core/ipv4/autoip.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 \
+75 -85
View File
@@ -57,7 +57,6 @@
#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"
@@ -68,8 +67,7 @@
# 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;
@@ -85,187 +83,183 @@ 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_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"
#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"
#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"
#endif
#if (LWIP_MULTICAST_TX_OPTIONS && !LWIP_IPV4)
#error "LWIP_MULTICAST_TX_OPTIONS needs LWIP_IPV4 enabled in your lwipopts.h"
#error "IGMP 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_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"
#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"
#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"
#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"
#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"
#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"
#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
@@ -300,31 +294,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 */
@@ -340,7 +334,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);
@@ -379,12 +373,8 @@ 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 */
}
+17 -696
View File
@@ -42,7 +42,6 @@
#if LWIP_IPV4
#include "lwip/sys.h"
#include "lwip/ip.h"
#include "lwip/def.h"
#include "lwip/mem.h"
@@ -57,7 +56,7 @@
#include "lwip/autoip.h"
#include "lwip/stats.h"
#include "lwip/prot/iana.h"
#include "lwip/lwip_napt.h"
#include "lwip/ip4_napt.h"
#include <string.h>
@@ -281,699 +280,6 @@ 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
@@ -1075,10 +381,12 @@ 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)) {
@@ -1176,7 +484,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;
@@ -1262,11 +574,13 @@ 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);
@@ -1401,7 +715,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",
@@ -1737,8 +1055,10 @@ 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 0 && ENABLE_LOOPBACK
#if ENABLE_LOOPBACK
#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
@@ -1754,6 +1074,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] */
+796
View File
@@ -0,0 +1,796 @@
/**
* @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) && netif->ip_addr.u_addr.ip4.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)
{
mport = PP_HTONS(mport);
dport = PP_HTONS(dport);
for (int 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) {
checksumadjust((u8_t *)&udphdr->chksum, (u8_t *)&udphdr->dest, 2, (u8_t *)&newval, 2);
udphdr->dest = newval;
} else {
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)
{
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, 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);
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, 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);
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, 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 */
#endif /* LWIP_IPV4 */
#endif /* ESP_LWIP */
+2
View File
@@ -367,9 +367,11 @@ netif_add(struct netif *netif,
netif->loop_cnt_current = 0;
#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
#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);
-6
View File
@@ -172,12 +172,6 @@ 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.
+96
View File
@@ -0,0 +1,96 @@
/**
* @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
* @param inp the netif on which this packet was received
*/
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 */
+47 -39
View File
@@ -1,3 +1,42 @@
/**
* @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__
@@ -7,12 +46,17 @@
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)
@@ -23,43 +67,6 @@ extern "C" {
#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.
*
@@ -91,7 +98,7 @@ ip_napt_enable_no(u8_t number, int enable);
* @param daddr destination ip address
* @param dport destination port, in host byte order.
*/
u8_t
u8_t
ip_portmap_add(u8_t proto, u32_t maddr, u16_t mport, u32_t daddr, u16_t dport);
@@ -101,11 +108,12 @@ ip_portmap_add(u8_t proto, u32_t maddr, u16_t mport, u32_t daddr, u16_t dport);
* @param proto target protocol
* @param maddr ip address of the external interface
*/
u8_t
u8_t
ip_portmap_remove(u8_t proto, u16_t mport);
#endif /* IP_NAPT */
#endif /* IP_FORWARD */
#endif /* ESP_LWIP */
#ifdef __cplusplus
}
+2
View File
@@ -410,9 +410,11 @@ 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 ESP_LWIP
#if LWIP_IPV4 && IP_NAPT
u8_t napt;
#endif
#endif /* ESP_LWIP */
};
#if LWIP_CHECKSUM_CTRL_PER_NETIF
#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) do { \
+8 -4
View File
@@ -736,7 +736,7 @@
* interface, define this to 0.
*/
#if !defined IP_FORWARD || defined __DOXYGEN__
#define IP_FORWARD 1
#define IP_FORWARD 0
#endif
/**
@@ -767,8 +767,12 @@
#define IP_FRAG 0
#endif /* !LWIP_IPV4 */
#ifndef IP_NAPT
#define IP_NAPT 1
/**
* 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
/**
@@ -1118,7 +1122,7 @@
* transport.
*/
#if !defined LWIP_DNS || defined __DOXYGEN__
#define LWIP_DNS 1
#define LWIP_DNS 0
#endif
/** DNS maximum number of entries to maintain locally. */