diff --git a/arduinoIDE_esp32_boards/README.md b/arduinoIDE_esp32_boards/README.md
index 431de7a888f4176590367c1929332f7c146fb60b..d333dd4de1a71107173b162e482615851742ee0c 100644
--- a/arduinoIDE_esp32_boards/README.md
+++ b/arduinoIDE_esp32_boards/README.md
@@ -1,7 +1,8 @@
-===== [apr.21] extending lwip with NTP servers from DHCP answer ======
+===== [aug.22] extending lwip with NTP servers from DHCP answer ======
 
-[experimental] To achieve this, you'll need to copy the following files:
+WARNING: only esp32 target will benefits from this enhancement (we don't have compiled for
+others targets like esp32s2, s3, c3 ...)
 
-cp opt.h ~/.arduino15/packages/esp32/hardware/esp32/1.0.6/tools/sdk/include/lwip/lwip/
-cp *.a ~/.arduino15/packages/esp32/hardware/esp32/1.0.6/tools/sdk/lib/
+cp opt.h ~/.arduino15/packages/esp32/hardware/esp32/2.0.4/tools/sdk/esp32/include/lwip/lwip/src/include/lwip/
+cp *.a ~/.arduino15/packages/esp32/hardware/esp32/2.0.4/tools/sdk/esp32/lib/
 
diff --git a/arduinoIDE_esp32_boards/boards.local.txt b/arduinoIDE_esp32_boards/boards.local.txt
index 041b1e1be8119ddccc535e0654d0d5ea03de64e6..4922be6601c742bb18514a01de4dd0be45902135 100644
--- a/arduinoIDE_esp32_boards/boards.local.txt
+++ b/arduinoIDE_esp32_boards/boards.local.txt
@@ -4,6 +4,9 @@
 # NEOSENSOR
 neOSensor.name=neOSensor
 
+neOSensor.bootloader.tool=esptool_py
+neOSensor.bootloader.tool.default=esptool_py
+
 neOSensor.upload.tool=esptool_py
 neOSensor.upload.maximum_size=1310720
 neOSensor.upload.maximum_data_size=327680
@@ -12,11 +15,14 @@ neOSensor.upload.wait_for_upload_port=true
 neOSensor.serial.disableDTR=true
 neOSensor.serial.disableRTS=true
 
+neOSensor.build.tarch=xtensa
+neOSensor.build.bootloader_addr=0x1000
+neOSensor.build.target=esp32
 neOSensor.build.mcu=esp32
 neOSensor.build.core=esp32
-# [aug.20] we keep node32s variant
-neOSensor.build.variant=node32s
-neOSensor.build.board=node32s
+# [aug.22] we keep node32s variant
+neOSensor.build.variant=nodemcu-32s
+neOSensor.build.board=nodeMCU_32S
 
 # [aug.20] seems to have some startup problems at 160MHz ... thus switching to 240MHz
 neOSensor.build.f_cpu=240000000L
@@ -65,6 +71,9 @@ neOSensor.menu.DebugLevel.verbose.build.code_debug=5
 # NEOSENSOR-AIRQUALITY
 neOSensor-airquality.name=neOSensor-airquality
 
+neOSensor-airquality.bootloader.tool=esptool_py
+neOSensor-airquality.bootloader.tool.default=esptool_py
+
 neOSensor-airquality.upload.tool=esptool_py
 neOSensor-airquality.upload.maximum_size=1310720
 neOSensor-airquality.upload.maximum_data_size=327680
@@ -73,11 +82,14 @@ neOSensor-airquality.upload.wait_for_upload_port=true
 neOSensor-airquality.serial.disableDTR=true
 neOSensor-airquality.serial.disableRTS=true
 
+neOSensor-airquality.build.tarch=xtensa
+neOSensor-airquality.build.bootloader_addr=0x1000
+neOSensor-airquality.build.target=esp32
 neOSensor-airquality.build.mcu=esp32
 neOSensor-airquality.build.core=esp32
-# [aug.20] we keep node32s variant
-neOSensor-airquality.build.variant=node32s
-neOSensor-airquality.build.board=node32s
+# [aug.22] we keep node32s variant
+neOSensor-airquality.build.variant=nodemcu-32s
+neOSensor-airquality.build.board=nodeMCU_32S
 
 # [aug.20] seems to have some startup problems at 160MHz ... thus switching to 240MHz
 neOSensor-airquality.build.f_cpu=240000000L
diff --git a/arduinoIDE_esp32_boards/liblwip.a b/arduinoIDE_esp32_boards/liblwip.a
index be77d65b60de28548b32f515b9d2df5e19d01981..dc71f5280b572b40256fdb5ec07490dd2ed67312 100644
Binary files a/arduinoIDE_esp32_boards/liblwip.a and b/arduinoIDE_esp32_boards/liblwip.a differ
diff --git a/arduinoIDE_esp32_boards/local_deploy.sh b/arduinoIDE_esp32_boards/local_deploy.sh
index 671ff26d5cb5823ce151fa00fcc84d9c506581f4..5d9d9ec8ed7dfced53e8f8444268f2e70070caab 100755
--- a/arduinoIDE_esp32_boards/local_deploy.sh
+++ b/arduinoIDE_esp32_boards/local_deploy.sh
@@ -4,6 +4,8 @@
 #
 # Deploying specific settings for board
 #
+# F.Thiebolt    aug.22  update for 2.0.4 sdk with esp32 target only
+#                       i.e does not apply to esp32 derivatives like esp32c3
 # F.Thiebolt    aug.21  initial release
 #
 
@@ -16,13 +18,13 @@
 echo -e "Copying additional board files ..."
 
 # copying files
-cp -af opt.h $1/include/lwip/lwip/
-[ $? -ne 0 ] && { echo -e "\n###ERROR copying some files to '$1/include/lwip/lwip/'" >&2; exit 1; }
-chmod a+r $1/include/lwip/lwip/opt.h
+cp -af opt.h $1/esp32/include/lwip/lwip/src/include/lwip/
+[ $? -ne 0 ] && { echo -e "\n###ERROR copying some files to '$1/esp32/include/lwip/lwip/src/include/lwip/'" >&2; exit 1; }
+chmod a+r $1/esp32/include/lwip/lwip/src/include/lwip/opt.h
 
-cp -af *.a $1/lib/
-[ $? -ne 0 ] && { echo -e "\n###ERROR copying some files to '$1/lib/'" >&2; exit 1; }
-chmod a+r $1/lib/*.a
+cp -af *.a $1/esp32/lib/
+[ $? -ne 0 ] && { echo -e "\n###ERROR copying some files to '$1/esp32/lib/'" >&2; exit 1; }
+chmod a+r $1/esp32/lib/*.a
 
 #set +x
 
diff --git a/arduinoIDE_esp32_boards/opt.h b/arduinoIDE_esp32_boards/opt.h
index eafc670575db5118d2e12c68d1d6592875a135c1..0433126eb4c6563ea30488fa9680ca5327fdcc56 100644
--- a/arduinoIDE_esp32_boards/opt.h
+++ b/arduinoIDE_esp32_boards/opt.h
@@ -144,6 +144,15 @@
 #if !defined SMEMCPY || defined __DOXYGEN__
 #define SMEMCPY(dst,src,len)            memcpy(dst,src,len)
 #endif
+
+/**
+ * MEMMOVE: override this if you have a faster implementation at hand than the
+ * one included in your C library.  lwIP currently uses MEMMOVE only when IPv6
+ * fragmentation support is enabled.
+ */
+#if !defined MEMMOVE || defined __DOXYGEN__
+#define MEMMOVE(dst,src,len)            memmove(dst,src,len)
+#endif
 /**
  * @}
  */
@@ -203,6 +212,29 @@
 #if !defined SYS_LIGHTWEIGHT_PROT || defined __DOXYGEN__
 #define SYS_LIGHTWEIGHT_PROT            1
 #endif
+
+/**
+ * Macro/function to check whether lwIP's threading/locking
+ * requirements are satisfied during current function call.
+ * This macro usually calls a function that is implemented in the OS-dependent
+ * sys layer and performs the following checks:
+ * - Not in ISR (this should be checked for NO_SYS==1, too!)
+ * - If @ref LWIP_TCPIP_CORE_LOCKING = 1: TCPIP core lock is held
+ * - If @ref LWIP_TCPIP_CORE_LOCKING = 0: function is called from TCPIP thread
+ * @see @ref multithreading
+ */
+#if !defined LWIP_ASSERT_CORE_LOCKED || defined __DOXYGEN__
+#define LWIP_ASSERT_CORE_LOCKED()
+#endif
+
+/**
+ * Called as first thing in the lwIP TCPIP thread. Can be used in conjunction
+ * with @ref LWIP_ASSERT_CORE_LOCKED to check core locking.
+ * @see @ref multithreading
+ */
+#if !defined LWIP_MARK_TCPIP_THREAD || defined __DOXYGEN__
+#define LWIP_MARK_TCPIP_THREAD()
+#endif
 /**
  * @}
  */
@@ -239,6 +271,15 @@
 #define MEMP_MEM_MALLOC                 0
 #endif
 
+/**
+ * MEMP_MEM_INIT==1: Force use of memset to initialize pool memory.
+ * Useful if pool are moved in uninitialized section of memory. This will ensure
+ * default values in pcbs struct are well initialized in all conditions.
+ */
+#if !defined MEMP_MEM_INIT || defined __DOXYGEN__
+#define MEMP_MEM_INIT                   0
+#endif
+
 /**
  * MEM_ALIGNMENT: should be set to the alignment of the CPU
  *    4 byte alignment -> \#define MEM_ALIGNMENT 4
@@ -277,6 +318,27 @@
 #define MEMP_SANITY_CHECK               0
 #endif
 
+/**
+ * MEM_OVERFLOW_CHECK: mem overflow protection reserves a configurable
+ * amount of bytes before and after each heap allocation chunk and fills
+ * it with a prominent default value.
+ *    MEM_OVERFLOW_CHECK == 0 no checking
+ *    MEM_OVERFLOW_CHECK == 1 checks each element when it is freed
+ *    MEM_OVERFLOW_CHECK >= 2 checks all heap elements every time
+ *      mem_malloc() or mem_free() is called (useful but slow!)
+ */
+#if !defined MEM_OVERFLOW_CHECK || defined __DOXYGEN__
+#define MEM_OVERFLOW_CHECK              0
+#endif
+
+/**
+ * MEM_SANITY_CHECK==1: run a sanity check after each mem_free() to make
+ * sure that the linked list of heap elements is not corrupted.
+ */
+#if !defined MEM_SANITY_CHECK || defined __DOXYGEN__
+#define MEM_SANITY_CHECK                0
+#endif
+
 /**
  * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set
  * of memory pools of various sizes. When mem_malloc is called, an element of
@@ -390,6 +452,16 @@
 #define MEMP_NUM_TCP_SEG                16
 #endif
 
+/**
+ * MEMP_NUM_ALTCP_PCB: the number of simultaneously active altcp layer pcbs.
+ * (requires the LWIP_ALTCP option)
+ * Connections with multiple layers require more than one altcp_pcb (e.g. TLS
+ * over TCP requires 2 altcp_pcbs, one for TLS and one for TCP).
+ */
+#if !defined MEMP_NUM_ALTCP_PCB || defined __DOXYGEN__
+#define MEMP_NUM_ALTCP_PCB              MEMP_NUM_TCP_PCB
+#endif
+
 /**
  * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for
  * reassembly (whole packets, not fragments!)
@@ -430,16 +502,21 @@
 #endif
 
 /**
- * MEMP_NUM_SYS_TIMEOUT: the number of simultaneously active timeouts.
+ * The number of sys timeouts used by the core stack (not apps)
  * The default number of timeouts is calculated here for all enabled modules.
- * The formula expects settings to be either '0' or '1'.
  */
-#if !defined MEMP_NUM_SYS_TIMEOUT || defined __DOXYGEN__
 #if ESP_LWIP
-#define MEMP_NUM_SYS_TIMEOUT            (LWIP_TCP + IP_REASSEMBLY + (LWIP_ARP + (ESP_GRATUITOUS_ARP ? 1 : 0)) + (2*LWIP_DHCP + (ESP_DHCPS_TIMER ? 1 : 0)) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + (PPP_SUPPORT*6*MEMP_NUM_PPP_PCB) + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0))
+#define LWIP_NUM_SYS_TIMEOUT_INTERNAL   (LWIP_TCP + IP_REASSEMBLY + (LWIP_ARP + (ESP_GRATUITOUS_ARP ? 1 : 0)) + (2*LWIP_DHCP + (ESP_DHCPS_TIMER ? 1 : 0)) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_NUM_TIMEOUTS + (LWIP_IPV6 * (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD)))
 #else
-#define MEMP_NUM_SYS_TIMEOUT            (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + (PPP_SUPPORT*6*MEMP_NUM_PPP_PCB) + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0))
+#define LWIP_NUM_SYS_TIMEOUT_INTERNAL   (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_NUM_TIMEOUTS + (LWIP_IPV6 * (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD)))
 #endif
+/**
+ * MEMP_NUM_SYS_TIMEOUT: the number of simultaneously active timeouts.
+ * The default number of timeouts is calculated here for all enabled modules.
+ * The formula expects settings to be either '0' or '1'.
+ */
+#if !defined MEMP_NUM_SYS_TIMEOUT || defined __DOXYGEN__
+#define MEMP_NUM_SYS_TIMEOUT            LWIP_NUM_SYS_TIMEOUT_INTERNAL
 #endif
 
 /**
@@ -458,6 +535,15 @@
 #define MEMP_NUM_NETCONN                4
 #endif
 
+/**
+ * MEMP_NUM_SELECT_CB: the number of struct lwip_select_cb.
+ * (Only needed if you have LWIP_MPU_COMPATIBLE==1 and use the socket API.
+ * In that case, you need one per thread calling lwip_select.)
+ */
+#if !defined MEMP_NUM_SELECT_CB || defined __DOXYGEN__
+#define MEMP_NUM_SELECT_CB              4
+#endif
+
 /**
  * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used
  * for callback/timeout API communication.
@@ -621,7 +707,7 @@
  * (but this should only occur for AutoIP).
  */
 #if !defined ETHARP_TABLE_MATCH_NETIF || defined __DOXYGEN__
-#define ETHARP_TABLE_MATCH_NETIF        0
+#define ETHARP_TABLE_MATCH_NETIF        !LWIP_SINGLE_NETIF
 #endif
 /**
  * @}
@@ -681,6 +767,14 @@
 #define IP_FRAG                         0
 #endif /* !LWIP_IPV4 */
 
+/**
+ * IP_NAPT==1: Enables IPv4 Network Address and Port Translation
+ * Note that IP_FORWARD needs to be enabled for NAPT to work
+ */
+#if !defined IP_NAPT || defined __DOXYGEN__
+#define IP_NAPT                      0
+#endif
+
 /**
  * IP_OPTIONS_ALLOWED: Defines the behavior for IP options.
  *      IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped.
@@ -696,7 +790,7 @@
  * in this time, the whole packet is discarded.
  */
 #if !defined IP_REASS_MAXAGE || defined __DOXYGEN__
-#define IP_REASS_MAXAGE                 3
+#define IP_REASS_MAXAGE                 15
 #endif
 
 /**
@@ -704,6 +798,8 @@
  * Since the received pbufs are enqueued, be sure to configure
  * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive
  * packets even if the maximum amount of fragments is enqueued for reassembly!
+ * When IPv4 *and* IPv6 are enabled, this even changes to
+ * (PBUF_POOL_SIZE > 2 * IP_REASS_MAX_PBUFS)!
  */
 #if !defined IP_REASS_MAX_PBUFS || defined __DOXYGEN__
 #define IP_REASS_MAX_PBUFS              10
@@ -743,15 +839,6 @@
 #if !defined IP_FORWARD_ALLOW_TX_ON_RX_NETIF || defined __DOXYGEN__
 #define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0
 #endif
-
-/**
- * LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first
- * local TCP/UDP pcb (default==0). This can prevent creating predictable port
- * numbers after booting a device.
- */
-#if !defined LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS || defined __DOXYGEN__
-#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 0
-#endif
 /**
  * @}
  */
@@ -778,7 +865,7 @@
  * ICMP_TTL: Default value for Time-To-Live used by ICMP packets.
  */
 #if !defined ICMP_TTL || defined __DOXYGEN__
-#define ICMP_TTL                       (IP_DEFAULT_TTL)
+#define ICMP_TTL                        IP_DEFAULT_TTL
 #endif
 
 /**
@@ -819,7 +906,7 @@
  * LWIP_RAW==1: Enable application layer to hook into the IP layer itself.
  */
 #if !defined RAW_TTL || defined __DOXYGEN__
-#define RAW_TTL                        (IP_DEFAULT_TTL)
+#define RAW_TTL                         IP_DEFAULT_TTL
 #endif
 /**
  * @}
@@ -851,17 +938,7 @@
  * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address.
  */
 #if !defined DHCP_DOES_ARP_CHECK || defined __DOXYGEN__
-#define DHCP_DOES_ARP_CHECK             ((LWIP_DHCP) && (LWIP_ARP))
-#endif
-
-/**
- * LWIP_DHCP_CHECK_LINK_UP==1: dhcp_start() only really starts if the netif has
- * NETIF_FLAG_LINK_UP set in its flags. As this is only an optimization and
- * netif drivers might not set this flag, the default is off. If enabled,
- * netif_set_link_up() must be called to continue dhcp starting.
- */
-#if !defined LWIP_DHCP_CHECK_LINK_UP
-#define LWIP_DHCP_CHECK_LINK_UP         0
+#define DHCP_DOES_ARP_CHECK             (LWIP_DHCP && LWIP_ARP)
 #endif
 
 /**
@@ -889,7 +966,7 @@
 
 /**
  * LWIP_DHCP_MAX_DNS_SERVERS > 0: Request DNS servers with discover/select.
- * DHCP servers received in the response are passed to DNS via @ref dns_setserver()
+ * DNS servers received in the response are passed to DNS via @ref dns_setserver()
  * (up to the maximum limit defined here).
  */
 #if !defined LWIP_DHCP_MAX_DNS_SERVERS || defined __DOXYGEN__
@@ -908,7 +985,7 @@
 #endif
 
 #ifndef LWIP_DHCP_IP_ADDR_ERASE
-#define LWIP_DHCP_IP_ADDR_ERASE()
+#define LWIP_DHCP_IP_ADDR_ERASE(esp_netif)
 #endif
 
 /*
@@ -941,6 +1018,13 @@
 #define LWIP_DHCP_AUTOIP_COOP           0
 #endif
 
+/**
+ * ESP_IPV6_AUTOCONFIG==1: Enable stateless address autoconfiguration as per RFC 4862.
+ */
+#if !defined ESP_IPV6_AUTOCONFIG
+#define ESP_IPV6_AUTOCONFIG 0
+#endif
+
 /**
  * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes
  * that should be sent before falling back on AUTOIP (the DHCP client keeps
@@ -979,7 +1063,29 @@
 
 /*
    ----------------------------------
-   ----- Multicast/IGMP options -----
+   -------- Multicast options -------
+   ----------------------------------
+*/
+/**
+ * @defgroup lwip_opts_multicast Multicast
+ * @ingroup lwip_opts_infrastructure
+ * @{
+ */
+/**
+ * LWIP_MULTICAST_TX_OPTIONS==1: Enable multicast TX support like the socket options
+ * IP_MULTICAST_TTL/IP_MULTICAST_IF/IP_MULTICAST_LOOP, as well as (currently only)
+ * core support for the corresponding IPv6 options.
+ */
+#if !defined LWIP_MULTICAST_TX_OPTIONS || defined __DOXYGEN__
+#define LWIP_MULTICAST_TX_OPTIONS       ((LWIP_IGMP || LWIP_IPV6_MLD) && (LWIP_UDP || LWIP_RAW))
+#endif
+/**
+ * @}
+ */
+
+/*
+   ----------------------------------
+   ---------- IGMP options ----------
    ----------------------------------
 */
 /**
@@ -997,14 +1103,6 @@
 #undef LWIP_IGMP
 #define LWIP_IGMP                       0
 #endif
-
-/**
- * LWIP_MULTICAST_TX_OPTIONS==1: Enable multicast TX support like the socket options
- * IP_MULTICAST_TTL/IP_MULTICAST_IF/IP_MULTICAST_LOOP
- */
-#if !defined LWIP_MULTICAST_TX_OPTIONS || defined __DOXYGEN__
-#define LWIP_MULTICAST_TX_OPTIONS       (LWIP_IGMP && LWIP_UDP)
-#endif
 /**
  * @}
  */
@@ -1045,6 +1143,11 @@
 #define DNS_MAX_SERVERS                 2
 #endif
 
+/** DNS maximum number of retries when asking for a name, before "timeout". */
+#if !defined DNS_MAX_RETRIES || defined __DOXYGEN__
+#define DNS_MAX_RETRIES                 4
+#endif
+
 /** DNS do a name checking between the query and the response. */
 #if !defined DNS_DOES_NAME_CHECK || defined __DOXYGEN__
 #define DNS_DOES_NAME_CHECK             1
@@ -1084,7 +1187,7 @@
 /** Set this to 1 to enable querying ".local" names via mDNS
  *  using a One-Shot Multicast DNS Query */
 #if !defined LWIP_DNS_SUPPORT_MDNS_QUERIES || defined __DOXYGEN__
-#define LWIP_DNS_SUPPORT_MDNS_QUERIES  0
+#define LWIP_DNS_SUPPORT_MDNS_QUERIES   0
 #endif
 /**
  * @}
@@ -1118,7 +1221,7 @@
  * UDP_TTL: Default Time-To-Live value.
  */
 #if !defined UDP_TTL || defined __DOXYGEN__
-#define UDP_TTL                         (IP_DEFAULT_TTL)
+#define UDP_TTL                         IP_DEFAULT_TTL
 #endif
 
 /**
@@ -1152,7 +1255,7 @@
  * TCP_TTL: Default Time-To-Live value.
  */
 #if !defined TCP_TTL || defined __DOXYGEN__
-#define TCP_TTL                         (IP_DEFAULT_TTL)
+#define TCP_TTL                         IP_DEFAULT_TTL
 #endif
 
 /**
@@ -1185,7 +1288,28 @@
  * Define to 0 if your device is low on memory.
  */
 #if !defined TCP_QUEUE_OOSEQ || defined __DOXYGEN__
-#define TCP_QUEUE_OOSEQ                 (LWIP_TCP)
+#define TCP_QUEUE_OOSEQ                 LWIP_TCP
+#endif
+
+/**
+ * LWIP_TCP_SACK_OUT==1: TCP will support sending selective acknowledgements (SACKs).
+ */
+#if !defined LWIP_TCP_SACK_OUT || defined __DOXYGEN__
+#define LWIP_TCP_SACK_OUT               0
+#endif
+
+/**
+ * LWIP_TCP_MAX_SACK_NUM: The maximum number of SACK values to include in TCP segments.
+ * Must be at least 1, but is only used if LWIP_TCP_SACK_OUT is enabled.
+ * NOTE: Even though we never send more than 3 or 4 SACK ranges in a single segment
+ * (depending on other options), setting this option to values greater than 4 is not pointless.
+ * This is basically the max number of SACK ranges we want to keep track of.
+ * As new data is delivered, some of the SACK ranges may be removed or merged.
+ * In that case some of those older SACK ranges may be used again.
+ * The amount of memory used to store SACK ranges is LWIP_TCP_MAX_SACK_NUM * 8 bytes for each TCP PCB.
+ */
+#if !defined LWIP_TCP_MAX_SACK_NUM || defined __DOXYGEN__
+#define LWIP_TCP_MAX_SACK_NUM           4
 #endif
 
 /**
@@ -1247,21 +1371,51 @@
 #endif
 
 /**
- * TCP_OOSEQ_MAX_BYTES: The maximum number of bytes queued on ooseq per pcb.
- * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==1.
+ * TCP_OOSEQ_MAX_BYTES: The default maximum number of bytes queued on ooseq per
+ * pcb if TCP_OOSEQ_BYTES_LIMIT is not defined. Default is 0 (no limit).
+ * Only valid for TCP_QUEUE_OOSEQ==1.
  */
 #if !defined TCP_OOSEQ_MAX_BYTES || defined __DOXYGEN__
 #define TCP_OOSEQ_MAX_BYTES             0
 #endif
 
 /**
- * TCP_OOSEQ_MAX_PBUFS: The maximum number of pbufs queued on ooseq per pcb.
- * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==1.
+ * TCP_OOSEQ_BYTES_LIMIT(pcb): Return the maximum number of bytes to be queued
+ * on ooseq per pcb, given the pcb. Only valid for TCP_QUEUE_OOSEQ==1 &&
+ * TCP_OOSEQ_MAX_BYTES==1.
+ * Use this to override TCP_OOSEQ_MAX_BYTES to a dynamic value per pcb.
+ */
+#if !defined TCP_OOSEQ_BYTES_LIMIT
+#if TCP_OOSEQ_MAX_BYTES
+#define TCP_OOSEQ_BYTES_LIMIT(pcb)      TCP_OOSEQ_MAX_BYTES
+#elif defined __DOXYGEN__
+#define TCP_OOSEQ_BYTES_LIMIT(pcb)
+#endif
+#endif
+
+/**
+ * TCP_OOSEQ_MAX_PBUFS: The default maximum number of pbufs queued on ooseq per
+ * pcb if TCP_OOSEQ_BYTES_LIMIT is not defined. Default is 0 (no limit).
+ * Only valid for TCP_QUEUE_OOSEQ==1.
  */
 #if !defined TCP_OOSEQ_MAX_PBUFS || defined __DOXYGEN__
 #define TCP_OOSEQ_MAX_PBUFS             0
 #endif
 
+/**
+ * TCP_OOSEQ_PBUFS_LIMIT(pcb): Return the maximum number of pbufs to be queued
+ * on ooseq per pcb, given the pcb.  Only valid for TCP_QUEUE_OOSEQ==1 &&
+ * TCP_OOSEQ_MAX_PBUFS==1.
+ * Use this to override TCP_OOSEQ_MAX_PBUFS to a dynamic value per pcb.
+ */
+#if !defined TCP_OOSEQ_PBUFS_LIMIT
+#if TCP_OOSEQ_MAX_PBUFS
+#define TCP_OOSEQ_PBUFS_LIMIT(pcb)      TCP_OOSEQ_MAX_PBUFS
+#elif defined __DOXYGEN__
+#define TCP_OOSEQ_PBUFS_LIMIT(pcb)
+#endif
+#endif
+
 /**
  * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb.
  */
@@ -1311,7 +1465,7 @@
  * explicit window update
  */
 #if !defined TCP_WND_UPDATE_THRESHOLD || defined __DOXYGEN__
-#define TCP_WND_UPDATE_THRESHOLD   LWIP_MIN((TCP_WND / 4), (TCP_MSS * 4))
+#define TCP_WND_UPDATE_THRESHOLD        LWIP_MIN((TCP_WND / 4), (TCP_MSS * 4))
 #endif
 
 /**
@@ -1346,6 +1500,40 @@
 #define TCP_RCV_SCALE                   0
 #endif
 
+/**
+ * LWIP_TCP_PCB_NUM_EXT_ARGS:
+ * When this is > 0, every tcp pcb (including listen pcb) includes a number of
+ * additional argument entries in an array (see tcp_ext_arg_alloc_id)
+ */
+#if !defined LWIP_TCP_PCB_NUM_EXT_ARGS || defined __DOXYGEN__
+#define LWIP_TCP_PCB_NUM_EXT_ARGS       0
+#endif
+
+/** LWIP_ALTCP==1: enable the altcp API.
+ * altcp is an abstraction layer that prevents applications linking against the
+ * tcp.h functions but provides the same functionality. It is used to e.g. add
+ * SSL/TLS or proxy-connect support to an application written for the tcp callback
+ * API without that application knowing the protocol details.
+ *
+ * With LWIP_ALTCP==0, applications written against the altcp API can still be
+ * compiled but are directly linked against the tcp.h callback API and then
+ * cannot use layered protocols.
+ *
+ * See @ref altcp_api
+ */
+#if !defined LWIP_ALTCP || defined __DOXYGEN__
+#define LWIP_ALTCP                      0
+#endif
+
+/** LWIP_ALTCP_TLS==1: enable TLS support for altcp API.
+ * This needs a port of the functions in altcp_tls.h to a TLS library.
+ * A port to ARM mbedtls is provided with lwIP, see apps/altcp_tls/ directory
+ * and LWIP_ALTCP_TLS_MBEDTLS option.
+ */
+#if !defined LWIP_ALTCP_TLS || defined __DOXYGEN__
+#define LWIP_ALTCP_TLS                  0
+#endif
+
 #if ESP_LWIP
 #if !defined LWIP_TCP_RTO_TIME || defined __DOXYGEN__
 #define LWIP_TCP_RTO_TIME             3000
@@ -1383,7 +1571,7 @@
  * for an additional encapsulation header before ethernet headers (e.g. 802.11)
  */
 #if !defined PBUF_LINK_ENCAPSULATION_HLEN || defined __DOXYGEN__
-#define PBUF_LINK_ENCAPSULATION_HLEN    0u
+#define PBUF_LINK_ENCAPSULATION_HLEN    0
 #endif
 
 /**
@@ -1394,6 +1582,22 @@
 #if !defined PBUF_POOL_BUFSIZE || defined __DOXYGEN__
 #define PBUF_POOL_BUFSIZE               LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN)
 #endif
+
+/**
+ * LWIP_PBUF_REF_T: Refcount type in pbuf.
+ * Default width of u8_t can be increased if 255 refs are not enough for you.
+ */
+#if !defined LWIP_PBUF_REF_T || defined __DOXYGEN__
+#define LWIP_PBUF_REF_T                 u8_t
+#endif
+
+/**
+ * LWIP_PBUF_CUSTOM_DATA: Store private data on pbufs (e.g. timestamps)
+ * This extends struct pbuf so user can store custom data on every pbuf.
+ */
+#if !defined LWIP_PBUF_CUSTOM_DATA || defined __DOXYGEN__
+#define LWIP_PBUF_CUSTOM_DATA
+#endif
 /**
  * @}
  */
@@ -1408,6 +1612,14 @@
  * @ingroup lwip_opts
  * @{
  */
+/**
+ * LWIP_SINGLE_NETIF==1: use a single netif only. This is the common case for
+ * small real-life targets. Some code like routing etc. can be left out.
+ */
+#if !defined LWIP_SINGLE_NETIF || defined __DOXYGEN__
+#define LWIP_SINGLE_NETIF               0
+#endif
+
 /**
  * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname
  * field.
@@ -1431,6 +1643,15 @@
 #define LWIP_NETIF_STATUS_CALLBACK      0
 #endif
 
+/**
+ * LWIP_NETIF_EXT_STATUS_CALLBACK==1: Support an extended callback function 
+ * for several netif related event that supports multiple subscribers.
+ * @see netif_ext_status_callback
+ */
+#if !defined LWIP_NETIF_EXT_STATUS_CALLBACK || defined __DOXYGEN__
+#define LWIP_NETIF_EXT_STATUS_CALLBACK  0
+#endif
+
 /**
  * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface
  * whenever the link changes (i.e., link down)
@@ -1459,24 +1680,33 @@
 #endif
 
 /**
- * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data
+ * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP *tries* to put all data
  * to be sent into one single pbuf. This is for compatibility with DMA-enabled
  * MACs that do not support scatter-gather.
  * Beware that this might involve CPU-memcpy before transmitting that would not
  * be needed without this flag! Use this only if you need to!
  *
- * @todo: TCP and IP-frag do not work with this, yet:
+ * ATTENTION: a driver should *NOT* rely on getting single pbufs but check TX
+ * pbufs for being in one piece. If not, @ref pbuf_clone can be used to get
+ * a single pbuf:
+ *   if (p->next != NULL) {
+ *     struct pbuf *q = pbuf_clone(PBUF_RAW, PBUF_RAM, p);
+ *     if (q == NULL) {
+ *       return ERR_MEM;
+ *     }
+ *     p = q; ATTENTION: do NOT free the old 'p' as the ref belongs to the caller!
+ *   }
  */
 #if !defined LWIP_NETIF_TX_SINGLE_PBUF || defined __DOXYGEN__
-#define LWIP_NETIF_TX_SINGLE_PBUF             0
+#define LWIP_NETIF_TX_SINGLE_PBUF       0
 #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
 
 /**
  * LWIP_NUM_NETIF_CLIENT_DATA: Number of clients that may store
- * data in client_data member array of struct netif.
+ * data in client_data member array of struct netif (max. 256).
  */
 #if !defined LWIP_NUM_NETIF_CLIENT_DATA || defined __DOXYGEN__
-#define LWIP_NUM_NETIF_CLIENT_DATA            0
+#define LWIP_NUM_NETIF_CLIENT_DATA      0
 #endif
 /**
  * @}
@@ -1498,14 +1728,14 @@
  * netif is available, loopback traffic uses this netif.
  */
 #if !defined LWIP_HAVE_LOOPIF || defined __DOXYGEN__
-#define LWIP_HAVE_LOOPIF                LWIP_NETIF_LOOPBACK
+#define LWIP_HAVE_LOOPIF                (LWIP_NETIF_LOOPBACK && !LWIP_SINGLE_NETIF)
 #endif
 
 /**
  * LWIP_LOOPIF_MULTICAST==1: Support multicast/IGMP on loop interface (127.0.0.1).
  */
 #if !defined LWIP_LOOPIF_MULTICAST || defined __DOXYGEN__
-#define LWIP_LOOPIF_MULTICAST               0
+#define LWIP_LOOPIF_MULTICAST           0
 #endif
 
 /**
@@ -1558,7 +1788,7 @@
  * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread.
  */
 #if !defined TCPIP_THREAD_NAME || defined __DOXYGEN__
-#define TCPIP_THREAD_NAME              "tcpip_thread"
+#define TCPIP_THREAD_NAME               "tcpip_thread"
 #endif
 
 /**
@@ -1600,7 +1830,7 @@
  * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread.
  */
 #if !defined SLIPIF_THREAD_NAME || defined __DOXYGEN__
-#define SLIPIF_THREAD_NAME             "slipif_loop"
+#define SLIPIF_THREAD_NAME              "slipif_loop"
 #endif
 
 /**
@@ -1625,7 +1855,7 @@
  * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread.
  */
 #if !defined DEFAULT_THREAD_NAME || defined __DOXYGEN__
-#define DEFAULT_THREAD_NAME            "lwIP"
+#define DEFAULT_THREAD_NAME             "lwIP"
 #endif
 
 /**
@@ -1755,13 +1985,6 @@
 #define LWIP_SOCKET                     1
 #endif
 
-/* LWIP_SOCKET_SET_ERRNO==1: Set errno when socket functions cannot complete
- * successfully, as required by POSIX. Default is POSIX-compliant.
- */
-#if !defined LWIP_SOCKET_SET_ERRNO || defined __DOXYGEN__
-#define LWIP_SOCKET_SET_ERRNO           1
-#endif
-
 /**
  * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names through defines.
  * LWIP_COMPAT_SOCKETS==2: Same as ==1 but correctly named functions are created.
@@ -1880,6 +2103,24 @@
 #if !defined LWIP_FIONREAD_LINUXMODE || defined __DOXYGEN__
 #define LWIP_FIONREAD_LINUXMODE         0
 #endif
+
+/**
+ * LWIP_SOCKET_SELECT==1 (default): enable select() for sockets (uses a netconn
+ * callback to keep track of events).
+ * This saves RAM (counters per socket) and code (netconn event callback), which
+ * should improve performance a bit).
+ */
+#if !defined LWIP_SOCKET_SELECT || defined __DOXYGEN__
+#define LWIP_SOCKET_SELECT              1
+#endif
+
+/**
+ * LWIP_SOCKET_POLL==1 (default): enable poll() for sockets (including
+ * struct pollfd, nfds_t, and constants)
+ */
+#if !defined LWIP_SOCKET_POLL || defined __DOXYGEN__
+#define LWIP_SOCKET_POLL                1
+#endif
 /**
  * @}
  */
@@ -2175,6 +2416,46 @@
 #define LWIP_IPV6                       0
 #endif
 
+/**
+ * IPV6_REASS_MAXAGE: Maximum time (in multiples of IP6_REASS_TMR_INTERVAL - so seconds, normally)
+ * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived
+ * in this time, the whole packet is discarded.
+ */
+#if !defined IPV6_REASS_MAXAGE || defined __DOXYGEN__
+#define IPV6_REASS_MAXAGE               60
+#endif
+
+/**
+ * LWIP_IPV6_SCOPES==1: Enable support for IPv6 address scopes, ensuring that
+ * e.g. link-local addresses are really treated as link-local. Disable this
+ * setting only for single-interface configurations.
+ * All addresses that have a scope according to the default policy (link-local
+ * unicast addresses, interface-local and link-local multicast addresses) should
+ * now have a zone set on them before being passed to the core API, although
+ * lwIP will currently attempt to select a zone on the caller's behalf when 
+ * necessary. Applications that directly assign IPv6 addresses to interfaces
+ * (which is NOT recommended) must now ensure that link-local addresses carry
+ * the netif's zone. See the new ip6_zone.h header file for more information and
+ * relevant macros. For now it is still possible to turn off scopes support
+ * through the new LWIP_IPV6_SCOPES option. When upgrading an implementation that
+ * uses the core API directly, it is highly recommended to enable
+ * LWIP_IPV6_SCOPES_DEBUG at least for a while, to ensure e.g. proper address
+ * initialization.
+ */
+#if !defined LWIP_IPV6_SCOPES || defined __DOXYGEN__
+#define LWIP_IPV6_SCOPES                (LWIP_IPV6 && !LWIP_SINGLE_NETIF)
+#endif
+
+/**
+ * LWIP_IPV6_SCOPES_DEBUG==1: Perform run-time checks to verify that addresses
+ * are properly zoned (see ip6_zone.h on what that means) where it matters.
+ * Enabling this setting is highly recommended when upgrading from an existing
+ * installation that is not yet scope-aware; otherwise it may be too expensive.
+ */
+#if !defined LWIP_IPV6_SCOPES_DEBUG || defined __DOXYGEN__
+#define LWIP_IPV6_SCOPES_DEBUG          0
+#endif
+
 /**
  * LWIP_IPV6_NUM_ADDRESSES: Number of IPv6 addresses per netif.
  */
@@ -2193,14 +2474,14 @@
  * LWIP_IPV6_FRAG==1: Fragment outgoing IPv6 packets that are too big.
  */
 #if !defined LWIP_IPV6_FRAG || defined __DOXYGEN__
-#define LWIP_IPV6_FRAG                  0
+#define LWIP_IPV6_FRAG                  1
 #endif
 
 /**
  * LWIP_IPV6_REASS==1: reassemble incoming IPv6 packets that fragmented
  */
 #if !defined LWIP_IPV6_REASS || defined __DOXYGEN__
-#define LWIP_IPV6_REASS                 (LWIP_IPV6)
+#define LWIP_IPV6_REASS                 LWIP_IPV6
 #endif
 
 /**
@@ -2215,7 +2496,18 @@
  * LWIP_IPV6_AUTOCONFIG==1: Enable stateless address autoconfiguration as per RFC 4862.
  */
 #if !defined LWIP_IPV6_AUTOCONFIG || defined __DOXYGEN__
-#define LWIP_IPV6_AUTOCONFIG            (LWIP_IPV6)
+#define LWIP_IPV6_AUTOCONFIG            LWIP_IPV6
+#endif
+
+/**
+ * LWIP_IPV6_ADDRESS_LIFETIMES==1: Keep valid and preferred lifetimes for each
+ * IPv6 address. Required for LWIP_IPV6_AUTOCONFIG. May still be enabled
+ * otherwise, in which case the application may assign address lifetimes with
+ * the appropriate macros. Addresses with no lifetime are assumed to be static.
+ * If this option is disabled, all addresses are assumed to be static.
+ */
+#if !defined LWIP_IPV6_ADDRESS_LIFETIMES || defined __DOXYGEN__
+#define LWIP_IPV6_ADDRESS_LIFETIMES     LWIP_IPV6_AUTOCONFIG
 #endif
 
 /**
@@ -2237,15 +2529,17 @@
  * LWIP_ICMP6==1: Enable ICMPv6 (mandatory per RFC)
  */
 #if !defined LWIP_ICMP6 || defined __DOXYGEN__
-#define LWIP_ICMP6                      (LWIP_IPV6)
+#define LWIP_ICMP6                      LWIP_IPV6
 #endif
 
 /**
  * LWIP_ICMP6_DATASIZE: bytes from original packet to send back in
- * ICMPv6 error messages.
+ * ICMPv6 error messages (0 = default of IP6_MIN_MTU_LENGTH)
+ * ATTENTION: RFC4443 section 2.4 says IP6_MIN_MTU_LENGTH is a MUST,
+ * so override this only if you absolutely have to!
  */
 #if !defined LWIP_ICMP6_DATASIZE || defined __DOXYGEN__
-#define LWIP_ICMP6_DATASIZE             8
+#define LWIP_ICMP6_DATASIZE             0
 #endif
 
 /**
@@ -2269,7 +2563,7 @@
  * indiscriminately pass all inbound IPv6 multicast traffic to lwIP.
  */
 #if !defined LWIP_IPV6_MLD || defined __DOXYGEN__
-#define LWIP_IPV6_MLD                   (LWIP_IPV6)
+#define LWIP_IPV6_MLD                   LWIP_IPV6
 #endif
 
 /**
@@ -2295,7 +2589,7 @@
  * is being resolved.
  */
 #if !defined LWIP_ND6_QUEUEING || defined __DOXYGEN__
-#define LWIP_ND6_QUEUEING               (LWIP_IPV6)
+#define LWIP_ND6_QUEUEING               LWIP_IPV6
 #endif
 
 /**
@@ -2424,12 +2718,60 @@
  */
 
 /**
- * LWIP_IPV6_DHCP6==1: enable DHCPv6 stateful address autoconfiguration.
+ * @defgroup lwip_opts_dhcpv6 DHCPv6
+ * @ingroup lwip_opts_ipv6
+ * @{
+ */
+/**
+ * LWIP_IPV6_DHCP6==1: enable DHCPv6 stateful/stateless address autoconfiguration.
  */
 #if !defined LWIP_IPV6_DHCP6 || defined __DOXYGEN__
 #define LWIP_IPV6_DHCP6                 0
 #endif
 
+/**
+ * LWIP_IPV6_DHCP6_STATEFUL==1: enable DHCPv6 stateful address autoconfiguration.
+ * (not supported, yet!)
+ */
+#if !defined LWIP_IPV6_DHCP6_STATEFUL || defined __DOXYGEN__
+#define LWIP_IPV6_DHCP6_STATEFUL        0
+#endif
+
+/**
+ * LWIP_IPV6_DHCP6_STATELESS==1: enable DHCPv6 stateless address autoconfiguration.
+ */
+#if !defined LWIP_IPV6_DHCP6_STATELESS || defined __DOXYGEN__
+#define LWIP_IPV6_DHCP6_STATELESS       LWIP_IPV6_DHCP6
+#endif
+
+/**
+ * LWIP_DHCP6_GETS_NTP==1: Request NTP servers via DHCPv6. For each
+ * response packet, a callback is called, which has to be provided by the port:
+ * void dhcp6_set_ntp_servers(u8_t num_ntp_servers, ip_addr_t* ntp_server_addrs);
+*/
+#if !defined LWIP_DHCP6_GET_NTP_SRV || defined __DOXYGEN__
+#define LWIP_DHCP6_GET_NTP_SRV          0
+#endif
+
+/**
+ * The maximum of NTP servers requested
+ */
+#if !defined LWIP_DHCP6_MAX_NTP_SERVERS || defined __DOXYGEN__
+#define LWIP_DHCP6_MAX_NTP_SERVERS      1
+#endif
+
+/**
+ * LWIP_DHCP6_MAX_DNS_SERVERS > 0: Request DNS servers via DHCPv6.
+ * DNS servers received in the response are passed to DNS via @ref dns_setserver()
+ * (up to the maximum limit defined here).
+ */
+#if !defined LWIP_DHCP6_MAX_DNS_SERVERS || defined __DOXYGEN__
+#define LWIP_DHCP6_MAX_DNS_SERVERS      DNS_MAX_SERVERS
+#endif
+/**
+ * @}
+ */
+
 /*
    ---------------------------------------
    ---------- Hook options ---------------
@@ -2444,8 +2786,8 @@
  */
 
 /**
- * LWIP_HOOK_FILENAME: Custom filename to #include in files that provide hooks.
- * Declare your hook function prototypes in there, you may also #include all headers
+ * LWIP_HOOK_FILENAME: Custom filename to \#include in files that provide hooks.
+ * Declare your hook function prototypes in there, you may also \#include all headers
  * providing data types that are need in this file.
  */
 #ifdef __DOXYGEN__
@@ -2461,7 +2803,9 @@
  * or any other desired algorithm as a replacement.
  * Called from tcp_connect() and tcp_listen_input() when an ISN is needed for
  * a new TCP connection, if TCP support (@ref LWIP_TCP) is enabled.\n
- * Signature: u32_t my_hook_tcp_isn(const ip_addr_t* local_ip, u16_t local_port, const ip_addr_t* remote_ip, u16_t remote_port);
+ * Signature:\code{.c}
+ * u32_t my_hook_tcp_isn(const ip_addr_t* local_ip, u16_t local_port, const ip_addr_t* remote_ip, u16_t remote_port);
+ * \endcode
  * - it may be necessary to use "struct ip_addr" (ip4_addr, ip6_addr) instead of "ip_addr_t" in function declarations\n
  * Arguments:
  * - local_ip: pointer to the local IP address of the connection
@@ -2475,9 +2819,89 @@
 #define LWIP_HOOK_TCP_ISN(local_ip, local_port, remote_ip, remote_port)
 #endif
 
+/**
+ * LWIP_HOOK_TCP_INPACKET_PCB:
+ * Hook for intercepting incoming packets before they are passed to a pcb. This
+ * allows updating some state or even dropping a packet.
+ * Signature:\code{.c}
+ * err_t my_hook_tcp_inpkt(struct tcp_pcb *pcb, struct tcp_hdr *hdr, u16_t optlen, u16_t opt1len, u8_t *opt2, struct pbuf *p);
+ * \endcode
+ * Arguments:
+ * - pcb: tcp_pcb selected for input of this packet (ATTENTION: this may be
+ *        struct tcp_pcb_listen if pcb->state == LISTEN)
+ * - hdr: pointer to tcp header (ATTENTION: tcp options may not be in one piece!)
+ * - optlen: tcp option length
+ * - opt1len: tcp option length 1st part
+ * - opt2: if this is != NULL, tcp options are split among 2 pbufs. In that case,
+ *         options start at right after the tcp header ('(u8_t*)(hdr + 1)') for
+ *         the first 'opt1len' bytes and the rest starts at 'opt2'. opt2len can
+ *         be simply calculated: 'opt2len = optlen - opt1len;'
+ * - p: input packet, p->payload points to application data (that's why tcp hdr
+ *      and options are passed in seperately)
+ * Return value:
+ * - ERR_OK: continue input of this packet as normal
+ * - != ERR_OK: drop this packet for input (don't continue input processing)
+ *
+ * ATTENTION: don't call any tcp api functions that might change tcp state (pcb
+ * state or any pcb lists) from this callback!
+ */
+#ifdef __DOXYGEN__
+#define LWIP_HOOK_TCP_INPACKET_PCB(pcb, hdr, optlen, opt1len, opt2, p)
+#endif
+
+/**
+ * LWIP_HOOK_TCP_OUT_TCPOPT_LENGTH:
+ * Hook for increasing the size of the options allocated with a tcp header.
+ * Together with LWIP_HOOK_TCP_OUT_ADD_TCPOPTS, this can be used to add custom
+ * options to outgoing tcp segments.
+ * Signature:\code{.c}
+ * u8_t my_hook_tcp_out_tcpopt_length(const struct tcp_pcb *pcb, u8_t internal_option_length);
+ * \endcode
+ * Arguments:
+ * - pcb: tcp_pcb that transmits (ATTENTION: this may be NULL or
+ *        struct tcp_pcb_listen if pcb->state == LISTEN)
+ * - internal_option_length: tcp option length used by the stack internally
+ * Return value:
+ * - a number of bytes to allocate for tcp options (internal_option_length <= ret <= 40)
+ *
+ * ATTENTION: don't call any tcp api functions that might change tcp state (pcb
+ * state or any pcb lists) from this callback!
+ */
+#ifdef __DOXYGEN__
+#define LWIP_HOOK_TCP_OUT_TCPOPT_LENGTH(pcb, internal_len)
+#endif
+
+/**
+ * LWIP_HOOK_TCP_OUT_ADD_TCPOPTS:
+ * Hook for adding custom options to outgoing tcp segments.
+ * Space for these custom options has to be reserved via LWIP_HOOK_TCP_OUT_TCPOPT_LENGTH.
+ * Signature:\code{.c}
+ * u32_t *my_hook_tcp_out_add_tcpopts(struct pbuf *p, struct tcp_hdr *hdr, const struct tcp_pcb *pcb, u32_t *opts);
+ * \endcode
+ * Arguments:
+ * - p: output packet, p->payload pointing to tcp header, data follows
+ * - hdr: tcp header
+ * - pcb: tcp_pcb that transmits (ATTENTION: this may be NULL or
+ *        struct tcp_pcb_listen if pcb->state == LISTEN)
+ * - opts: pointer where to add the custom options (there may already be options
+ *         between the header and these)
+ * Return value:
+ * - pointer pointing directly after the inserted options
+ *
+ * ATTENTION: don't call any tcp api functions that might change tcp state (pcb
+ * state or any pcb lists) from this callback!
+ */
+#ifdef __DOXYGEN__
+#define LWIP_HOOK_TCP_OUT_ADD_TCPOPTS(p, hdr, pcb, opts)
+#endif
+
 /**
  * LWIP_HOOK_IP4_INPUT(pbuf, input_netif):
- * - called from ip_input() (IPv4)
+ * Called from ip_input() (IPv4)
+ * Signature:\code{.c}
+ *   int my_hook(struct pbuf *pbuf, struct netif *input_netif);
+ * \endcode
+ * Arguments:
  * - pbuf: received struct pbuf passed to ip_input()
  * - input_netif: struct netif on which the packet has been received
  * Return values:
@@ -2492,30 +2916,71 @@
 
 /**
  * LWIP_HOOK_IP4_ROUTE(dest):
- * - called from ip_route() (IPv4)
+ * Called from ip_route() (IPv4)
+ * Signature:\code{.c}
+ *   struct netif *my_hook(const ip4_addr_t *dest);
+ * \endcode
+ * Arguments:
  * - dest: destination IPv4 address
- * Returns the destination netif or NULL if no destination netif is found. In
- * that case, ip_route() continues as normal.
+ * Returns values:
+ * - the destination netif
+ * - NULL if no destination netif is found. In that case, ip_route() continues as normal.
  */
 #ifdef __DOXYGEN__
 #define LWIP_HOOK_IP4_ROUTE()
 #endif
 
 /**
- * LWIP_HOOK_IP4_ROUTE_SRC(dest, src):
- * - source-based routing for IPv4 (see LWIP_HOOK_IP4_ROUTE(), src may be NULL)
+ * LWIP_HOOK_IP4_ROUTE_SRC(src, dest):
+ * Source-based routing for IPv4 - called from ip_route() (IPv4)
+ * Signature:\code{.c}
+ *   struct netif *my_hook(const ip4_addr_t *src, const ip4_addr_t *dest);
+ * \endcode
+ * Arguments:
+ * - src: local/source IPv4 address
+ * - dest: destination IPv4 address
+ * Returns values:
+ * - the destination netif
+ * - NULL if no destination netif is found. In that case, ip_route() continues as normal.
+ */
+#ifdef __DOXYGEN__
+#define LWIP_HOOK_IP4_ROUTE_SRC(src, dest)
+#endif
+
+/**
+ * LWIP_HOOK_IP4_CANFORWARD(src, dest):
+ * Check if an IPv4 can be forwarded - called from:
+ * ip4_input() -> ip4_forward() -> ip4_canforward() (IPv4)
+ * - source address is available via ip4_current_src_addr()
+ * - calling an output function in this context (e.g. multicast router) is allowed
+ * Signature:\code{.c}
+ *   int my_hook(struct pbuf *p, u32_t dest_addr_hostorder);
+ * \endcode
+ * Arguments:
+ * - p: packet to forward
+ * - dest: destination IPv4 address
+ * Returns values:
+ * - 1: forward
+ * - 0: don't forward
+ * - -1: no decision. In that case, ip4_canforward() continues as normal.
  */
 #ifdef __DOXYGEN__
-#define LWIP_HOOK_IP4_ROUTE_SRC(dest, src)
+#define LWIP_HOOK_IP4_CANFORWARD(src, dest)
 #endif
 
 /**
  * LWIP_HOOK_ETHARP_GET_GW(netif, dest):
- * - called from etharp_output() (IPv4)
+ * Called from etharp_output() (IPv4)
+ * Signature:\code{.c}
+ *   const ip4_addr_t *my_hook(struct netif *netif, const ip4_addr_t *dest);
+ * \endcode
+ * Arguments:
  * - netif: the netif used for sending
  * - dest: the destination IPv4 address
- * Returns the IPv4 address of the gateway to handle the specified destination
- * IPv4 address. If NULL is returned, the netif's default gateway is used.
+ * Return values:
+ * - the IPv4 address of the gateway to handle the specified destination IPv4 address
+ * - NULL, in which case the netif's default gateway is used
+ *
  * The returned address MUST be directly reachable on the specified netif!
  * This function is meant to implement advanced IPv4 routing together with
  * LWIP_HOOK_IP4_ROUTE(). The actual routing/gateway table implementation is
@@ -2527,7 +2992,11 @@
 
 /**
  * LWIP_HOOK_IP6_INPUT(pbuf, input_netif):
- * - called from ip6_input() (IPv6)
+ * Called from ip6_input() (IPv6)
+ * Signature:\code{.c}
+ *   int my_hook(struct pbuf *pbuf, struct netif *input_netif);
+ * \endcode
+ * Arguments:
  * - pbuf: received struct pbuf passed to ip6_input()
  * - input_netif: struct netif on which the packet has been received
  * Return values:
@@ -2542,11 +3011,16 @@
 
 /**
  * LWIP_HOOK_IP6_ROUTE(src, dest):
- * - called from ip6_route() (IPv6)
- * - src: sourc IPv6 address
+ * Called from ip_route() (IPv6)
+ * Signature:\code{.c}
+ *   struct netif *my_hook(const ip6_addr_t *dest, const ip6_addr_t *src);
+ * \endcode
+ * Arguments:
+ * - src: source IPv6 address
  * - dest: destination IPv6 address
- * Returns the destination netif or NULL if no destination netif is found. In
- * that case, ip6_route() continues as normal.
+ * Return values:
+ * - the destination netif
+ * - NULL if no destination netif is found. In that case, ip6_route() continues as normal.
  */
 #ifdef __DOXYGEN__
 #define LWIP_HOOK_IP6_ROUTE(src, dest)
@@ -2554,11 +3028,17 @@
 
 /**
  * LWIP_HOOK_ND6_GET_GW(netif, dest):
- * - called from nd6_get_next_hop_entry() (IPv6)
+ * Called from nd6_get_next_hop_entry() (IPv6)
+ * Signature:\code{.c}
+ *   const ip6_addr_t *my_hook(struct netif *netif, const ip6_addr_t *dest);
+ * \endcode
+ * Arguments:
  * - netif: the netif used for sending
  * - dest: the destination IPv6 address
- * Returns the IPv6 address of the next hop to handle the specified destination
- * IPv6 address. If NULL is returned, a NDP-discovered router is used instead.
+ * Return values:
+ * - the IPv6 address of the next hop to handle the specified destination IPv6 address
+ * - NULL, in which case a NDP-discovered router is used instead
+ *
  * The returned address MUST be directly reachable on the specified netif!
  * This function is meant to implement advanced IPv6 routing together with
  * LWIP_HOOK_IP6_ROUTE(). The actual routing/gateway table implementation is
@@ -2570,7 +3050,11 @@
 
 /**
  * LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr):
- * - called from ethernet_input() if VLAN support is enabled
+ * Called from ethernet_input() if VLAN support is enabled
+ * Signature:\code{.c}
+ *   int my_hook(struct netif *netif, struct eth_hdr *eth_hdr, struct eth_vlan_hdr *vlan_hdr);
+ * \endcode
+ * Arguments:
  * - netif: struct netif on which the packet has been received
  * - eth_hdr: struct eth_hdr of the packet
  * - vlan_hdr: struct eth_vlan_hdr of the packet
@@ -2587,7 +3071,9 @@
  * Hook can be used to set prio_vid field of vlan_hdr. If you need to store data
  * on per-netif basis to implement this callback, see @ref netif_cd.
  * Called from ethernet_output() if VLAN support (@ref ETHARP_SUPPORT_VLAN) is enabled.\n
- * Signature: s32_t my_hook_vlan_set(struct netif* netif, struct pbuf* pbuf, const struct eth_addr* src, const struct eth_addr* dst, u16_t eth_type);\n
+ * Signature:\code{.c}
+ *   s32_t my_hook_vlan_set(struct netif* netif, struct pbuf* pbuf, const struct eth_addr* src, const struct eth_addr* dst, u16_t eth_type);\n
+ * \endcode
  * Arguments:
  * - netif: struct netif that the packet will be sent through
  * - p: struct pbuf packet to be sent
@@ -2606,7 +3092,10 @@
 
 /**
  * LWIP_HOOK_MEMP_AVAILABLE(memp_t_type):
- * - called from memp_free() when a memp pool was empty and an item is now available
+ * Called from memp_free() when a memp pool was empty and an item is now available
+ * Signature:\code{.c}
+ *   void my_hook(memp_t type);
+ * \endcode
  */
 #ifdef __DOXYGEN__
 #define LWIP_HOOK_MEMP_AVAILABLE(memp_t_type)
@@ -2615,12 +3104,175 @@
 /**
  * LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(pbuf, netif):
  * Called from ethernet_input() when an unknown eth type is encountered.
- * Return ERR_OK if packet is accepted, any error code otherwise.
+ * Signature:\code{.c}
+ *   err_t my_hook(struct pbuf* pbuf, struct netif* netif);
+ * \endcode
+ * Arguments:
+ * - p: rx packet with unknown eth type
+ * - netif: netif on which the packet has been received
+ * Return values:
+ * - ERR_OK if packet is accepted (hook function now owns the pbuf)
+ * - any error code otherwise (pbuf is freed)
+ *
  * Payload points to ethernet header!
  */
 #ifdef __DOXYGEN__
 #define LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(pbuf, netif)
 #endif
+
+/**
+ * LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, state, msg, msg_type, options_len_ptr):
+ * Called from various dhcp functions when sending a DHCP message.
+ * This hook is called just before the DHCP message trailer is added, so the
+ * options are at the end of a DHCP message.
+ * Signature:\code{.c}
+ *   void my_hook(struct netif *netif, struct dhcp *dhcp, u8_t state, struct dhcp_msg *msg,
+ *                u8_t msg_type, u16_t *options_len_ptr);
+ * \endcode
+ * Arguments:
+ * - netif: struct netif that the packet will be sent through
+ * - dhcp: struct dhcp on that netif
+ * - state: current dhcp state (dhcp_state_enum_t as an u8_t)
+ * - msg: struct dhcp_msg that will be sent
+ * - msg_type: dhcp message type to be sent (u8_t)
+ * - options_len_ptr: pointer to the current length of options in the dhcp_msg "msg"
+ *                    (must be increased when options are added!)
+ *
+ * Options need to appended like this:
+ *   LWIP_ASSERT("dhcp option overflow", *options_len_ptr + option_len + 2 <= DHCP_OPTIONS_LEN);
+ *   msg->options[(*options_len_ptr)++] = &lt;option_number&gt;;
+ *   msg->options[(*options_len_ptr)++] = &lt;option_len&gt;;
+ *   msg->options[(*options_len_ptr)++] = &lt;option_bytes&gt;;
+ *   [...]
+ */
+#ifdef __DOXYGEN__
+#define LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, state, msg, msg_type, options_len_ptr)
+#endif
+
+/**
+ * LWIP_HOOK_DHCP_PARSE_OPTION(netif, dhcp, state, msg, msg_type, option, len, pbuf, option_value_offset):
+ * Called from dhcp_parse_reply when receiving a DHCP message.
+ * This hook is called for every option in the received message that is not handled internally.
+ * Signature:\code{.c}
+ *   void my_hook(struct netif *netif, struct dhcp *dhcp, u8_t state, struct dhcp_msg *msg,
+ *                u8_t msg_type, u8_t option, u8_t option_len, struct pbuf *pbuf, u16_t option_value_offset);
+ * \endcode
+ * Arguments:
+ * - netif: struct netif that the packet will be sent through
+ * - dhcp: struct dhcp on that netif
+ * - state: current dhcp state (dhcp_state_enum_t as an u8_t)
+ * - msg: struct dhcp_msg that was received
+ * - msg_type: dhcp message type received (u8_t, ATTENTION: only valid after
+ *             the message type option has been parsed!)
+ * - option: option value (u8_t)
+ * - len: option data length (u8_t)
+ * - pbuf: pbuf where option data is contained
+ * - option_value_offset: offset in pbuf where option data begins
+ *
+ * A nice way to get the option contents is pbuf_get_contiguous():
+ *  u8_t buf[32];
+ *  u8_t *ptr = (u8_t*)pbuf_get_contiguous(p, buf, sizeof(buf), LWIP_MIN(option_len, sizeof(buf)), offset);
+ */
+#ifdef __DOXYGEN__
+#define LWIP_HOOK_DHCP_PARSE_OPTION(netif, dhcp, state, msg, msg_type, option, len, pbuf, offset)
+#endif
+
+/**
+ * LWIP_HOOK_DHCP6_APPEND_OPTIONS(netif, dhcp6, state, msg, msg_type, options_len_ptr, max_len):
+ * Called from various dhcp6 functions when sending a DHCP6 message.
+ * This hook is called just before the DHCP6 message is sent, so the
+ * options are at the end of a DHCP6 message.
+ * Signature:\code{.c}
+ *   void my_hook(struct netif *netif, struct dhcp6 *dhcp, u8_t state, struct dhcp6_msg *msg,
+ *                u8_t msg_type, u16_t *options_len_ptr);
+ * \endcode
+ * Arguments:
+ * - netif: struct netif that the packet will be sent through
+ * - dhcp6: struct dhcp6 on that netif
+ * - state: current dhcp6 state (dhcp6_state_enum_t as an u8_t)
+ * - msg: struct dhcp6_msg that will be sent
+ * - msg_type: dhcp6 message type to be sent (u8_t)
+ * - options_len_ptr: pointer to the current length of options in the dhcp6_msg "msg"
+ *                    (must be increased when options are added!)
+ *
+ * Options need to appended like this:
+ *   u8_t *options = (u8_t *)(msg + 1);
+ *   LWIP_ASSERT("dhcp option overflow", sizeof(struct dhcp6_msg) + *options_len_ptr + newoptlen <= max_len);
+ *   options[(*options_len_ptr)++] = &lt;option_data&gt;;
+ *   [...]
+ */
+#ifdef __DOXYGEN__
+#define LWIP_HOOK_DHCP6_APPEND_OPTIONS(netif, dhcp6, state, msg, msg_type, options_len_ptr, max_len)
+#endif
+
+/**
+ * LWIP_HOOK_SOCKETS_SETSOCKOPT(s, sock, level, optname, optval, optlen, err)
+ * Called from socket API to implement setsockopt() for options not provided by lwIP.
+ * Core lock is held when this hook is called.
+ * Signature:\code{.c}
+ *   int my_hook(int s, struct lwip_sock *sock, int level, int optname, const void *optval, socklen_t optlen, int *err)
+ * \endcode
+ * Arguments:
+ * - s: socket file descriptor
+ * - sock: internal socket descriptor (see lwip/priv/sockets_priv.h)
+ * - level: protocol level at which the option resides
+ * - optname: option to set
+ * - optval: value to set
+ * - optlen: size of optval
+ * - err: output error
+ * Return values:
+ * - 0: Hook has not consumed the option, code continues as normal (to internal options)
+ * - != 0: Hook has consumed the option, 'err' is returned
+ */
+#ifdef __DOXYGEN__
+#define LWIP_HOOK_SOCKETS_SETSOCKOPT(s, sock, level, optname, optval, optlen, err)
+#endif
+
+/**
+ * LWIP_HOOK_SOCKETS_GETSOCKOPT(s, sock, level, optname, optval, optlen, err)
+ * Called from socket API to implement getsockopt() for options not provided by lwIP.
+ * Core lock is held when this hook is called.
+ * Signature:\code{.c}
+ *   int my_hook(int s, struct lwip_sock *sock, int level, int optname, void *optval, socklen_t *optlen, int *err)
+ * \endcode
+ * Arguments:
+ * - s: socket file descriptor
+ * - sock: internal socket descriptor (see lwip/priv/sockets_priv.h)
+ * - level: protocol level at which the option resides
+ * - optname: option to get
+ * - optval: value to get
+ * - optlen: size of optval
+ * - err: output error
+ * Return values:
+ * - 0: Hook has not consumed the option, code continues as normal (to internal options)
+ * - != 0: Hook has consumed the option, 'err' is returned
+ */
+#ifdef __DOXYGEN__
+#define LWIP_HOOK_SOCKETS_GETSOCKOPT(s, sock, level, optname, optval, optlen, err)
+#endif
+
+/**
+ * LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE(name, addr, addrtype, err)
+ * Called from netconn APIs (not usable with callback apps) allowing an
+ * external DNS resolver (which uses sequential API) to handle the query.
+ * Signature:\code{.c}
+ *   int my_hook(const char *name, ip_addr_t *addr, u8_t addrtype, err_t *err)
+ * \endcode
+ * Arguments:
+ * - name: hostname to resolve
+ * - addr: output host address
+ * - addrtype: type of address to query
+ * - err: output error
+ * Return values:
+ * - 0: Hook has not consumed hostname query, query continues into DNS module
+ * - != 0: Hook has consumed the query
+ *
+ * err must also be checked to determine if the hook consumed the query, but
+ * the query failed
+ */
+#ifdef __DOXYGEN__
+#define LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE(name, addr, addrtype, err)
+#endif
 /**
  * @}
  */
@@ -2878,10 +3530,31 @@
 #if !defined IP6_DEBUG || defined __DOXYGEN__
 #define IP6_DEBUG                       LWIP_DBG_OFF
 #endif
+
+/**
+ * DHCP6_DEBUG: Enable debugging in dhcp6.c.
+ */
+#if !defined DHCP6_DEBUG || defined __DOXYGEN__
+#define DHCP6_DEBUG                     LWIP_DBG_OFF
+#endif
 /**
  * @}
  */
 
+/**
+ * LWIP_TESTMODE: Changes to make unit test possible
+ */
+#if !defined LWIP_TESTMODE
+#define LWIP_TESTMODE                   0
+#endif
+
+/**
+ * NAPT_DEBUG: Enable debugging for NAPT.
+ */
+#ifndef NAPT_DEBUG
+#define NAPT_DEBUG                       LWIP_DBG_OFF
+#endif
+
 /*
    --------------------------------------------------
    ---------- Performance tracking options ----------
diff --git a/deploy.sh b/deploy.sh
index b064e42a35d6e12d3b6585b9ace29170bad98738..2b8ca0f457b7992e385f3f776acabf194a4a900a 100755
--- a/deploy.sh
+++ b/deploy.sh
@@ -2,6 +2,7 @@
 #
 # Deployment script for neOCampus / neOSensor boards
 #
+# F.Thiebolt    aug.22  upgrades esp* SDKs
 # F.Thiebolt    feb.21  added CubeCell support
 # F.Thiebolt    sep.20  force SDK 2.7.1 for esp8266 (2.7.4 exhibits WiFi failures
 #                       in higly degraded WiFi environment).
@@ -10,8 +11,8 @@
 
 #
 # Global defs
-ESP32_REV=${ESP32_REV:-"1.0.6"}
-ESP8266_REV=${ESP8266_REV:-"2.7.1"}
+ESP32_REV=${ESP32_REV:-"2.0.4"}
+ESP8266_REV=${ESP8266_REV:-"3.0.2"}
 CUBECELL_REV=${CUBECELL_REV:-"1.3.0"}