1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-06 05:21:22 +03:00

new network feature: NAPT (widely known as NAT) (#6360)

* lwIP: napt patches (enabled with lwip2 w/o IPv6 w/ features)
This commit is contained in:
david gauchard 2019-08-28 17:51:14 +02:00 committed by GitHub
parent 7436f3802a
commit 06f1865628
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 497 additions and 8 deletions

View File

@ -0,0 +1,97 @@
// NAPT example released to public domain
#if LWIP_FEATURES && !LWIP_IPV6
#define HAVE_NETDUMP 0
#ifndef STASSID
#define STASSID "mynetwork"
#define STAPSK "mynetworkpassword"
#endif
#include <ESP8266WiFi.h>
#include <lwip/napt.h>
#include <lwip/dns.h>
#include <dhcpserver.h>
#define NAPT 1000
#define NAPT_PORT 10
#if HAVE_NETDUMP
#include <NetDump.h>
void dump(int netif_idx, const char* data, size_t len, int out, int success) {
(void)success;
Serial.print(out ? F("out ") : F(" in "));
Serial.printf("%d ", netif_idx);
// optional filter example: if (netDump_is_ARP(data))
{
netDump(Serial, data, len);
//netDumpHex(Serial, data, len);
}
}
#endif
void setup() {
Serial.begin(115200);
Serial.printf("\n\nNAPT Range extender\n");
Serial.printf("Heap on start: %d\n", ESP.getFreeHeap());
#if HAVE_NETDUMP
phy_capture = dump;
#endif
// first, connect to STA so we can get a proper local DNS server
WiFi.mode(WIFI_STA);
WiFi.begin(STASSID, STAPSK);
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(500);
}
Serial.printf("\nSTA: %s (dns: %s / %s)\n",
WiFi.localIP().toString().c_str(),
WiFi.dnsIP(0).toString().c_str(),
WiFi.dnsIP(1).toString().c_str());
// give DNS servers to AP side
dhcps_set_dns(0, WiFi.dnsIP(0));
dhcps_set_dns(1, WiFi.dnsIP(1));
WiFi.softAPConfig( // enable AP, with android-compatible google domain
IPAddress(172, 217, 28, 254),
IPAddress(172, 217, 28, 254),
IPAddress(255, 255, 255, 0));
WiFi.softAP(STASSID "extender", STAPSK);
Serial.printf("AP: %s\n", WiFi.softAPIP().toString().c_str());
Serial.printf("Heap before: %d\n", ESP.getFreeHeap());
err_t ret = ip_napt_init(NAPT, NAPT_PORT);
Serial.printf("ip_napt_init(%d,%d): ret=%d (OK=%d)\n", NAPT, NAPT_PORT, (int)ret, (int)ERR_OK);
if (ret == ERR_OK) {
ret = ip_napt_enable_no(SOFTAP_IF, 1);
Serial.printf("ip_napt_enable_no(SOFTAP_IF): ret=%d (OK=%d)\n", (int)ret, (int)ERR_OK);
if (ret == ERR_OK) {
Serial.printf("WiFi Network '%s' with same password is now NATed behind '%s'\n", STASSID "extender", STASSID);
}
}
Serial.printf("Heap after napt init: %d\n", ESP.getFreeHeap());
if (ret != ERR_OK) {
Serial.printf("NAPT initialization failed\n");
}
}
#else
void setup() {
Serial.begin(115200);
Serial.printf("\n\nNAPT not supported in this configuration\n");
}
#endif
void loop() {
}

View File

@ -22,7 +22,6 @@
*
*/
#include <arch/cc.h>
#include <sys/time.h>
#include <IPAddress.h>
#include <AddrList.h>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -1 +1 @@
Subproject commit 2314329c86cb7eb9670e3adf7632bd52001f45cd
Subproject commit ffa962483cc1c5d874b11bec13080359619c4cb2

View File

@ -58,10 +58,12 @@ void sntp_set_system_time (uint32_t t);
#include "mem.h" // useful for os_malloc used in esp-arduino's mDNS
typedef uint32_t sys_prot_t; // not really used
#define SYS_ARCH_DECL_PROTECT(lev)
#define SYS_ARCH_PROTECT(lev) os_intr_lock()
#define SYS_ARCH_UNPROTECT(lev) os_intr_unlock()
#include "glue.h" // include assembly locking macro used below
typedef uint32_t sys_prot_t;
#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev
#define SYS_ARCH_PROTECT(lev) lev = lwip_xt_rsil(15)
#define SYS_ARCH_UNPROTECT(lev) lwip_xt_wsr_ps(lev)
#define LWIP_NO_CTYPE_H 1
///////////////////////////////

View File

@ -0,0 +1,130 @@
// adapted from dhcpserver.c distributed in esp8266 sdk 2.0.0
// same license may apply
#ifndef __DHCPS_H__
#define __DHCPS_H__
#include "glue.h" // for UDEBUG
#define USE_DNS
typedef struct dhcps_state{
sint16_t state;
} dhcps_state;
typedef struct dhcps_msg {
uint8_t op, htype, hlen, hops;
uint8_t xid[4];
uint16_t secs, flags;
uint8_t ciaddr[4];
uint8_t yiaddr[4];
uint8_t siaddr[4];
uint8_t giaddr[4];
uint8_t chaddr[16];
uint8_t sname[64];
uint8_t file[128];
uint8_t options[312];
}dhcps_msg;
#ifndef LWIP_OPEN_SRC
struct dhcps_lease {
bool enable;
struct ipv4_addr start_ip;
struct ipv4_addr end_ip;
};
enum dhcps_offer_option{
OFFER_START = 0x00,
OFFER_ROUTER = 0x01,
OFFER_END
};
#endif
typedef enum {
DHCPS_TYPE_DYNAMIC,
DHCPS_TYPE_STATIC
} dhcps_type_t;
typedef enum {
DHCPS_STATE_ONLINE,
DHCPS_STATE_OFFLINE
} dhcps_state_t;
struct dhcps_pool{
struct ipv4_addr ip;
uint8 mac[6];
uint32 lease_timer;
dhcps_type_t type;
dhcps_state_t state;
};
typedef struct _list_node{
void *pnode;
struct _list_node *pnext;
}list_node;
extern uint32 dhcps_lease_time;
#define DHCPS_LEASE_TIMER dhcps_lease_time //0x05A0
#define DHCPS_MAX_LEASE 0x64
#define BOOTP_BROADCAST 0x8000
#define DHCP_REQUEST 1
#define DHCP_REPLY 2
#define DHCP_HTYPE_ETHERNET 1
#define DHCP_HLEN_ETHERNET 6
#define DHCP_MSG_LEN 236
#define DHCPS_SERVER_PORT 67
#define DHCPS_CLIENT_PORT 68
#define DHCPDISCOVER 1
#define DHCPOFFER 2
#define DHCPREQUEST 3
#define DHCPDECLINE 4
#define DHCPACK 5
#define DHCPNAK 6
#define DHCPRELEASE 7
#define DHCP_OPTION_SUBNET_MASK 1
#define DHCP_OPTION_ROUTER 3
#define DHCP_OPTION_DNS_SERVER 6
#define DHCP_OPTION_REQ_IPADDR 50
#define DHCP_OPTION_LEASE_TIME 51
#define DHCP_OPTION_MSG_TYPE 53
#define DHCP_OPTION_SERVER_ID 54
#define DHCP_OPTION_INTERFACE_MTU 26
#define DHCP_OPTION_PERFORM_ROUTER_DISCOVERY 31
#define DHCP_OPTION_BROADCAST_ADDRESS 28
#define DHCP_OPTION_REQ_LIST 55
#define DHCP_OPTION_END 255
//#define USE_CLASS_B_NET 1
#define DHCPS_DEBUG UDEBUG
#define MAX_STATION_NUM 8
#define DHCPS_STATE_OFFER 1
#define DHCPS_STATE_DECLINE 2
#define DHCPS_STATE_ACK 3
#define DHCPS_STATE_NAK 4
#define DHCPS_STATE_IDLE 5
#define DHCPS_STATE_RELEASE 6
#define dhcps_router_enabled(offer) ((offer & OFFER_ROUTER) != 0)
#ifdef __cplusplus
extern "C"
{
#endif
void dhcps_set_dns (int num, const ipv4_addr_t* dns);
void dhcps_start(struct ip_info *info);
void dhcps_stop(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,113 @@
/*
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.
author: d. gauchard
*/
#ifndef GLUE_H
#define GLUE_H
#ifndef ARDUINO
#define ARDUINO 0
#endif
#ifndef OPENSDK
#define OPENSDK 0
#endif
#if !ARDUINO && !OPENSDK
#error Must defined ARDUINO or OPENSDK
#endif
#include "gluedebug.h"
#ifdef __cplusplus
extern "C"
{
#endif
#include "ets_sys.h"
#include "osapi.h"
#include "user_interface.h"
#ifdef __cplusplus
}
#endif
typedef enum
{
GLUE_ERR_OK = 0,
GLUE_ERR_MEM = -1,
GLUE_ERR_BUF = -2,
GLUE_ERR_TIMEOUT = -3,
GLUE_ERR_RTE = -4,
GLUE_ERR_INPROGRESS = -5,
GLUE_ERR_VAL = -6,
GLUE_ERR_WOULDBLOCK = -7,
GLUE_ERR_USE = -8,
GLUE_ERR_ALREADY = -9,
GLUE_ERR_ISCONN = -10,
GLUE_ERR_CONN = -11,
GLUE_ERR_IF = -12,
GLUE_ERR_ABRT = -13,
GLUE_ERR_RST = -14,
GLUE_ERR_CLSD = -15,
GLUE_ERR_ARG = -16
} err_glue_t;
typedef enum
{
GLUE_NETIF_FLAG_BROADCAST = 1,
GLUE_NETIF_FLAG_UP = 2,
GLUE_NETIF_FLAG_ETHARP = 4,
GLUE_NETIF_FLAG_IGMP = 8,
GLUE_NETIF_FLAG_LINK_UP = 16,
} glue_netif_flags_t;
void esp2glue_lwip_init (void);
void esp2glue_espconn_init (void);
void esp2glue_dhcps_start (struct ip_info* info);
err_glue_t esp2glue_dhcp_start (int netif_idx);
void esp2glue_dhcp_stop (int netif_idx);
void esp2glue_netif_updated (int netif_idx, uint32_t ip, uint32_t mask, uint32_t gw, glue_netif_flags_t flags, size_t hwlen, const uint8_t* hw /*, void* state*/);
err_glue_t esp2glue_ethernet_input (int netif_idx, void* glue_pbuf);
void esp2glue_alloc_for_recv (size_t len, void** glue_pbuf, void** glue_data);
void esp2glue_pbuf_freed (void* ref_saved);
void esp2glue_netif_set_default (int netif_idx);
void esp2glue_netif_update (int netif_idx, uint32_t ip, uint32_t mask, uint32_t gw, size_t hwlen, const uint8_t* hwaddr, uint16_t mtu);
void esp2glue_netif_set_up1down0 (int netif_idx, int up1_or_down0);
void glue2esp_ifupdown (int netif_idx, uint32_t ip, uint32_t mask, uint32_t gw);
err_glue_t glue2esp_linkoutput (int netif_idx, void* ref2save, void* data, size_t size);
// fixed definitions from esp8266/arduino
// renamed with lwip_ to avoid name collision
// reference and credits: https://github.com/esp8266/Arduino/pull/6301
#ifndef __STRINGIFY
#define __STRINGIFY(a) #a
#endif
#define lwip_xt_rsil(level) (__extension__({uint32_t state; __asm__ __volatile__("rsil %0," __STRINGIFY(level) : "=a" (state) :: "memory"); state;}))
#define lwip_xt_wsr_ps(state) __asm__ __volatile__("wsr %0,ps; isync" :: "a" (state) : "memory")
#endif // GLUE_H

View File

@ -1,5 +1,5 @@
// generated by makefiles/make-lwip2-hash
#ifndef LWIP_HASH_H
#define LWIP_HASH_H
#define LWIP_HASH_STR "STABLE-2_1_2_RELEASE/glue:1.1-8-g2314329"
#define LWIP_HASH_STR "STABLE-2_1_2_RELEASE/glue:1.2-8-g7958710"
#endif // LWIP_HASH_H

View File

@ -189,6 +189,12 @@ extern struct ip_globals ip_data;
/** Destination IP4 address of current_header */
#define ip4_current_dest_addr() (&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_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */
/** Get the IPv6 header of the current packet.

View File

@ -0,0 +1,116 @@
#ifndef __LWIP_NAPT_H__
#define __LWIP_NAPT_H__
#include "lwip/opt.h"
#include "lwip/err.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)
*/
err_t
ip_napt_init(u16_t max_nat, u8_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.
*/
err_t
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.
*/
err_t
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__ */

View File

@ -387,6 +387,9 @@ struct netif {
u16_t loop_cnt_current;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
#endif /* ENABLE_LOOPBACK */
#if LWIP_IPV4 && IP_NAPT
u8_t napt;
#endif
};
#if LWIP_CHECKSUM_CTRL_PER_NETIF

View File

@ -764,6 +764,10 @@
#define IP_FRAG 0
#endif /* !LWIP_IPV4 */
#ifndef IP_NAPT
#define IP_NAPT 0
#endif
/**
* IP_OPTIONS_ALLOWED: Defines the behavior for IP options.
* IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped.
@ -3484,6 +3488,14 @@
#if !defined DHCP6_DEBUG || defined __DOXYGEN__
#define DHCP6_DEBUG LWIP_DBG_OFF
#endif
/**
* NAPT_DEBUG: Enable debugging for NAPT.
*/
#ifndef NAPT_DEBUG
#define NAPT_DEBUG LWIP_DBG_OFF
#endif
/**
* @}
*/

View File

@ -741,7 +741,7 @@
* interface, define this to 0.
*/
#if !defined IP_FORWARD || defined __DOXYGEN__
#define IP_FORWARD 0
#define IP_FORWARD LWIP_FEATURES
#endif
/**
@ -772,6 +772,10 @@
#define IP_FRAG 0
#endif /* !LWIP_IPV4 */
#ifndef IP_NAPT
#define IP_NAPT (LWIP_FEATURES && !LWIP_IPV6)
#endif
/**
* IP_OPTIONS_ALLOWED: Defines the behavior for IP options.
* IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped.
@ -3496,6 +3500,13 @@
* @}
*/
/**
* NAPT_DEBUG: Enable debugging for NAPT.
*/
#ifndef NAPT_DEBUG
#define NAPT_DEBUG LWIP_DBG_OFF
#endif
/**
* LWIP_TESTMODE: Changes to make unit test possible
*/