diff --git a/cores/esp8266/LwipIntf.h b/cores/esp8266/LwipIntf.h
index 43941c4f28..8d0bb1dce7 100644
--- a/cores/esp8266/LwipIntf.h
+++ b/cores/esp8266/LwipIntf.h
@@ -41,7 +41,7 @@ class LwipIntf
     // ----     + ---------  -------------
     // local_ip | local_ip   local_ip
     // arg1     | gateway    dns1
-    // arg2     | netmask    [Agateway
+    // arg2     | netmask    gateway
     // arg3     | dns1       netmask
     //
     // result stored into gateway/netmask/dns1
diff --git a/cores/esp8266/LwipIntfDev.h b/cores/esp8266/LwipIntfDev.h
index 15f3f033b1..00f29e9dfe 100644
--- a/cores/esp8266/LwipIntfDev.h
+++ b/cores/esp8266/LwipIntfDev.h
@@ -104,7 +104,6 @@ class LwipIntfDev: public LwipIntf, public RawDev
     }
 
     // ESP8266WiFi API compatibility
-
     wl_status_t status();
 
 protected:
diff --git a/libraries/lwIP_Ethernet/examples/LegacyAdvancedChatServer/LegacyAdvancedChatServer.ino b/libraries/lwIP_Ethernet/examples/LegacyAdvancedChatServer/LegacyAdvancedChatServer.ino
new file mode 100644
index 0000000000..74b580308f
--- /dev/null
+++ b/libraries/lwIP_Ethernet/examples/LegacyAdvancedChatServer/LegacyAdvancedChatServer.ino
@@ -0,0 +1,126 @@
+/*
+ Advanced Chat Server
+
+ A more advanced server that distributes any incoming messages
+ to all connected clients but the client the message comes from.
+ To use, telnet to your device's IP address and type.
+ You can see the client's input in the serial monitor as well.
+ Using an Arduino Wiznet Ethernet shield.
+
+ Circuit:
+ * Ethernet Wiznet5500/Wiznet5100/ENC28J60 on esp8266
+
+ created 18 Dec 2009
+ by David A. Mellis
+ modified 9 Apr 2012
+ by Tom Igoe
+ redesigned to make use of operator== 25 Nov 2013
+ by Norbert Truchsess
+
+ */
+
+// specific to esp8266 w/lwIP
+#include <EthernetCompat.h>
+ArduinoWiznet5500lwIP Ethernet(/*SS*/ 16);  // <== adapt to your hardware
+// ArduinoWiznet5100lwIP Ethernet(/*SS*/ 16);  // <== adapt to your hardware
+// ArduinoENC28J60lwIP Ethernet(/*SS*/ 16);  // <== adapt to your hardware
+
+
+
+// Enter a MAC address and IP address for your controller below.
+// The IP address will be dependent on your local network.
+// gateway and subnet are optional:
+byte notNeededButAllowed_mac[] = {
+  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
+};
+byte* mac = nullptr;  // automatic mac
+IPAddress ip(192, 168, 1, 177);
+IPAddress myDns(192, 168, 1, 1);
+IPAddress gateway(192, 168, 1, 1);
+IPAddress subnet(255, 255, 0, 0);
+
+
+// telnet defaults to port 23
+EthernetServer server(23);
+
+EthernetClient clients[8];
+
+void setup() {
+  // You can use Ethernet.init(pin) to configure the CS pin
+  // Ethernet.init(10);  // Most Arduino shields
+  // Ethernet.init(5);   // MKR ETH shield
+  // Ethernet.init(0);   // Teensy 2.0
+  // Ethernet.init(20);  // Teensy++ 2.0
+  // Ethernet.init(15);  // ESP8266 with Adafruit Featherwing Ethernet
+  // Ethernet.init(33);  // ESP32 with Adafruit Featherwing Ethernet
+  //                     // esp8266 w/lwIP: SS set in Ethernet constructor
+
+  // initialize the Ethernet device
+  Ethernet.begin(mac, ip, myDns, gateway, subnet);
+
+  // Open serial communications and wait for port to open:
+  Serial.begin(9600);
+  while (!Serial) {
+    ;  // wait for serial port to connect. Needed for native USB port only
+  }
+
+  // Check for Ethernet hardware present
+  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
+    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
+    while (true) {
+      delay(1);  // do nothing, no point running without Ethernet hardware
+    }
+  }
+  if (Ethernet.linkStatus() == LinkOFF) {
+    Serial.println("Ethernet cable is not connected.");
+  }
+
+  // start listening for clients
+  server.begin();
+
+  Serial.print("Chat server address:");
+  Serial.println(Ethernet.localIP());
+}
+
+void loop() {
+  // check for any new client connecting, and say hello (before any incoming data)
+  EthernetClient newClient = server.accept();
+  if (newClient) {
+    for (byte i = 0; i < 8; i++) {
+      if (!clients[i]) {
+        Serial.print("We have a new client #");
+        Serial.println(i);
+        newClient.print("Hello, client number: ");
+        newClient.println(i);
+        // Once we "accept", the client is no longer tracked by EthernetServer
+        // so we must store it into our list of clients
+        clients[i] = newClient;
+        break;
+      }
+    }
+  }
+
+  // check for incoming data from all clients
+  for (byte i = 0; i < 8; i++) {
+    if (clients[i] && clients[i].available() > 0) {
+      // read bytes from a client
+      byte buffer[80];
+      int count = clients[i].read(buffer, 80);
+      // write the bytes to all other connected clients
+      for (byte j = 0; j < 8; j++) {
+        if (j != i && clients[j].connected()) {
+          clients[j].write(buffer, count);
+        }
+      }
+    }
+  }
+
+  // stop any clients which disconnect
+  for (byte i = 0; i < 8; i++) {
+    if (clients[i] && !clients[i].connected()) {
+      Serial.print("disconnect client #");
+      Serial.println(i);
+      clients[i].stop();
+    }
+  }
+}
diff --git a/libraries/lwIP_Ethernet/examples/LegacyChatServer/LegacyChatServer.ino b/libraries/lwIP_Ethernet/examples/LegacyChatServer/LegacyChatServer.ino
new file mode 100644
index 0000000000..1c6ee9e2a5
--- /dev/null
+++ b/libraries/lwIP_Ethernet/examples/LegacyChatServer/LegacyChatServer.ino
@@ -0,0 +1,105 @@
+/*
+ Chat Server
+
+ A simple server that distributes any incoming messages to all
+ connected clients.  To use, telnet to your device's IP address and type.
+ You can see the client's input in the serial monitor as well.
+ Using an Arduino Wiznet Ethernet shield.
+
+ Circuit:
+ * Ethernet Wiznet5500/Wiznet5100/ENC28J60 on esp8266
+
+ created 18 Dec 2009
+ by David A. Mellis
+ modified 9 Apr 2012
+ by Tom Igoe
+
+ */
+
+
+// specific to esp8266 w/lwIP
+#include <EthernetCompat.h>
+ArduinoWiznet5500lwIP Ethernet(/*SS*/ 16);  // <== adapt to your hardware
+// ArduinoWiznet5100lwIP Ethernet(/*SS*/ 16);  // <== adapt to your hardware
+// ArduinoENC28J60lwIP Ethernet(/*SS*/ 16);  // <== adapt to your hardware
+
+
+
+// Enter a MAC address and IP address for your controller below.
+// The IP address will be dependent on your local network.
+// gateway and subnet are optional:
+byte notNeededButAllowed_mac[] = {
+  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
+};
+byte* mac = nullptr;  // automatic mac
+IPAddress ip(192, 168, 1, 177);
+IPAddress myDns(192, 168, 1, 1);
+IPAddress gateway(192, 168, 1, 1);
+IPAddress subnet(255, 255, 0, 0);
+
+
+// telnet defaults to port 23
+EthernetServer server(23);
+bool alreadyConnected = false;  // whether or not the client was connected previously
+
+void setup() {
+  // You can use Ethernet.init(pin) to configure the CS pin
+  // Ethernet.init(10);  // Most Arduino shields
+  // Ethernet.init(5);   // MKR ETH shield
+  // Ethernet.init(0);   // Teensy 2.0
+  // Ethernet.init(20);  // Teensy++ 2.0
+  // Ethernet.init(15);  // ESP8266 with Adafruit Featherwing Ethernet
+  // Ethernet.init(33);  // ESP32 with Adafruit Featherwing Ethernet
+  //                     // esp8266 w/lwIP: SS set in Ethernet constructor
+
+  // initialize the ethernet device
+  Ethernet.begin(mac, ip, myDns, gateway, subnet);
+
+  // Open serial communications and wait for port to open:
+  Serial.begin(9600);
+  while (!Serial) {
+    ;  // wait for serial port to connect. Needed for native USB port only
+  }
+
+  // Check for Ethernet hardware present
+  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
+    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
+    while (true) {
+      delay(1);  // do nothing, no point running without Ethernet hardware
+    }
+  }
+  if (Ethernet.linkStatus() == LinkOFF) {
+    Serial.println("Ethernet cable is not connected.");
+  }
+
+  // start listening for clients
+  server.begin();
+
+  Serial.print("Chat server address:");
+  Serial.println(Ethernet.localIP());
+}
+
+void loop() {
+  // wait for a new client:
+  EthernetClient client = server.available();
+
+  // when the client sends the first byte, say hello:
+  if (client) {
+    if (!alreadyConnected) {
+      // clear out the input buffer:
+      client.flush();
+      Serial.println("We have a new client");
+      client.println("Hello, client!");
+      alreadyConnected = true;
+    }
+
+    if (client.available() > 0) {
+      // read the bytes incoming from the client:
+      char thisChar = client.read();
+      // echo the bytes back to the client:
+      server.write(thisChar);
+      // echo the bytes to the server as well:
+      Serial.write(thisChar);
+    }
+  }
+}
diff --git a/libraries/lwIP_Ethernet/examples/LegacyDhcpAddressPrinter/LegacyDhcpAddressPrinter.ino b/libraries/lwIP_Ethernet/examples/LegacyDhcpAddressPrinter/LegacyDhcpAddressPrinter.ino
new file mode 100644
index 0000000000..e7ab75075b
--- /dev/null
+++ b/libraries/lwIP_Ethernet/examples/LegacyDhcpAddressPrinter/LegacyDhcpAddressPrinter.ino
@@ -0,0 +1,101 @@
+/*
+  DHCP-based IP printer
+
+  This sketch uses the DHCP extensions to the Ethernet library
+  to get an IP address via DHCP and print the address obtained.
+  using an Arduino Wiznet Ethernet shield.
+
+  Circuit:
+  * Ethernet Wiznet5500/Wiznet5100/ENC28J60 on esp8266
+
+  created 12 April 2011
+  modified 9 Apr 2012
+  by Tom Igoe
+  modified 02 Sept 2015
+  by Arturo Guadalupi
+
+ */
+
+// specific to esp8266 w/lwIP
+#include <EthernetCompat.h>
+ArduinoWiznet5500lwIP Ethernet(/*SS*/ 16);  // <== adapt to your hardware
+// ArduinoWiznet5100lwIP Ethernet(/*SS*/ 16);  // <== adapt to your hardware
+// ArduinoENC28J60lwIP Ethernet(/*SS*/ 16);  // <== adapt to your hardware
+
+
+// Enter a MAC address for your controller below.
+// Newer Ethernet shields have a MAC address printed on a sticker on the shield
+byte notNeededButAllowed_mac[] = {
+  0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02
+};
+byte* mac = nullptr;  // automatic mac
+
+void setup() {
+  // You can use Ethernet.init(pin) to configure the CS pin
+  // Ethernet.init(10);  // Most Arduino shields
+  // Ethernet.init(5);   // MKR ETH shield
+  // Ethernet.init(0);   // Teensy 2.0
+  // Ethernet.init(20);  // Teensy++ 2.0
+  // Ethernet.init(15);  // ESP8266 with Adafruit Featherwing Ethernet
+  // Ethernet.init(33);  // ESP32 with Adafruit Featherwing Ethernet
+  //                     // esp8266 w/lwIP: SS set in Ethernet constructor
+
+
+  // Open serial communications and wait for port to open:
+  Serial.begin(9600);
+  while (!Serial) {
+    ;  // wait for serial port to connect. Needed for native USB port only
+  }
+
+  // start the Ethernet connection:
+  Serial.println("Initialize Ethernet with DHCP:");
+  if (Ethernet.begin(mac) == 0) {
+    Serial.println("Failed to configure Ethernet using DHCP");
+    if (Ethernet.hardwareStatus() == EthernetNoHardware) {
+      Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
+    } else if (Ethernet.linkStatus() == LinkOFF) {
+      Serial.println("Ethernet cable is not connected.");
+    }
+    // no point in carrying on, so do nothing forevermore:
+    while (true) {
+      delay(1);
+    }
+  }
+  // print your local IP address:
+  Serial.print("My IP address: ");
+  Serial.println(Ethernet.localIP());
+}
+
+void loop() {
+  switch (Ethernet.maintain()) {
+    case 1:
+      // renewed fail
+      Serial.println("Error: renewed fail");
+      break;
+
+    case 2:
+      // renewed success
+      Serial.println("Renewed success");
+      // print your local IP address:
+      Serial.print("My IP address: ");
+      Serial.println(Ethernet.localIP());
+      break;
+
+    case 3:
+      // rebind fail
+      Serial.println("Error: rebind fail");
+      break;
+
+    case 4:
+      // rebind success
+      Serial.println("Rebind success");
+      // print your local IP address:
+      Serial.print("My IP address: ");
+      Serial.println(Ethernet.localIP());
+      break;
+
+    default:
+      // nothing happened
+      break;
+  }
+}
diff --git a/libraries/lwIP_Ethernet/examples/LegacyUDPSendReceiveString/LegacyUDPSendReceiveString.ino b/libraries/lwIP_Ethernet/examples/LegacyUDPSendReceiveString/LegacyUDPSendReceiveString.ino
new file mode 100644
index 0000000000..bee4a1f801
--- /dev/null
+++ b/libraries/lwIP_Ethernet/examples/LegacyUDPSendReceiveString/LegacyUDPSendReceiveString.ino
@@ -0,0 +1,156 @@
+/*
+ UDPSendReceiveString:
+ This sketch receives UDP message strings, prints them to the serial port
+ and sends an "acknowledge" string back to the sender
+
+ A Processing sketch is included at the end of file that can be used to send
+ and received messages for testing with a computer.
+
+ Circuit:
+ * Ethernet Wiznet5500/Wiznet5100/ENC28J60 on esp8266
+
+ created 21 Aug 2010
+ by Michael Margolis
+
+ This code is in the public domain.
+ */
+
+// specific to esp8266 w/lwIP
+#include <EthernetCompat.h>
+ArduinoWiznet5500lwIP Ethernet(/*SS*/ 16);  // <== adapt to your hardware
+// ArduinoWiznet5100lwIP Ethernet(/*SS*/ 16);  // <== adapt to your hardware
+// ArduinoENC28J60lwIP Ethernet(/*SS*/ 16);  // <== adapt to your hardware
+
+// Enter a MAC address for your controller below.
+// Newer Ethernet shields have a MAC address printed on a sticker on the shield
+byte notNeededButAllowed_mac[] = {
+  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
+};
+byte* mac = nullptr;  // automatic mac
+IPAddress ip(192, 168, 1, 177);
+
+unsigned int localPort = 8888;  // local port to listen on
+
+// buffers for receiving and sending data
+char packetBuffer[UDP_TX_PACKET_MAX_SIZE];  // buffer to hold incoming packet,
+char ReplyBuffer[] = "acknowledged";        // a string to send back
+
+// An EthernetUDP instance to let us send and receive packets over UDP
+EthernetUDP Udp;
+
+void setup() {
+  // You can use Ethernet.init(pin) to configure the CS pin
+  // Ethernet.init(10);  // Most Arduino shields
+  // Ethernet.init(5);   // MKR ETH shield
+  // Ethernet.init(0);   // Teensy 2.0
+  // Ethernet.init(20);  // Teensy++ 2.0
+  // Ethernet.init(15);  // ESP8266 with Adafruit Featherwing Ethernet
+  // Ethernet.init(33);  // ESP32 with Adafruit Featherwing Ethernet
+  //                    // esp8266 w/lwIP: SS set in Ethernet constructor
+
+  // Open serial communications and wait for port to open:
+  Serial.begin(9600);
+  while (!Serial) {
+    ;  // wait for serial port to connect. Needed for native USB port only
+  }
+
+  // start the Ethernet
+  // Ethernet.begin(mac, ip);
+  if (Ethernet.begin(mac) == 0) {
+    Serial.println("Failed to configure Ethernet using DHCP");
+    while (true) {
+      delay(1000);  // do nothing, no point running without Ethernet hardware
+    }
+  }
+
+  // Check for Ethernet hardware present
+  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
+    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
+    while (true) {
+      delay(1000);  // do nothing, no point running without Ethernet hardware
+    }
+  }
+  if (Ethernet.linkStatus() == LinkOFF) {
+    Serial.println("Ethernet cable is not connected.");
+  }
+
+  Serial.println("Started and waiting");
+  Serial.print("IP Address: ");
+  Serial.println(Ethernet.localIP());
+  Serial.print("UDP port: ");
+  Serial.println(localPort);
+
+  // start UDP
+  Udp.begin(localPort);
+}
+
+void loop() {
+  // if there's data available, read a packet
+  int packetSize = Udp.parsePacket();
+  if (packetSize) {
+    Serial.print("Received packet of size ");
+    Serial.println(packetSize);
+    Serial.print("From ");
+    IPAddress remote = Udp.remoteIP();
+    for (int i = 0; i < 4; i++) {
+      Serial.print(remote[i], DEC);
+      if (i < 3) {
+        Serial.print(".");
+      }
+    }
+    Serial.print(", port ");
+    Serial.println(Udp.remotePort());
+
+    // read the packet into packetBufffer
+    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
+    Serial.println("Contents:");
+    Serial.println(packetBuffer);
+
+    // send a reply to the IP address and port that sent us the packet we received
+    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
+    Udp.write(ReplyBuffer);
+    Udp.endPacket();
+  }
+  delay(10);
+}
+
+
+/*
+  Processing sketch to run with this example
+ =====================================================
+
+ // Processing UDP example to send and receive string data from Arduino
+ // press any key to send the "Hello Arduino" message
+
+
+ import hypermedia.net.*;
+
+ UDP udp;  // define the UDP object
+
+
+ void setup() {
+ udp = new UDP( this, 6000 );  // create a new datagram connection on port 6000
+ //udp.log( true ); 		// <-- printout the connection activity
+ udp.listen( true );           // and wait for incoming message
+ }
+
+ void draw()
+ {
+ }
+
+ void keyPressed() {
+ String ip       = "192.168.1.177";	// the remote IP address
+ int port        = 8888;		// the destination port
+
+ udp.send("Hello World", ip, port );   // the message to send
+
+ }
+
+ void receive( byte[] data ) { 			// <-- default handler
+ //void receive( byte[] data, String ip, int port ) {	// <-- extended handler
+
+ for(int i=0; i < data.length; i++)
+ print(char(data[i]));
+ println();
+ }
+ */
diff --git a/libraries/lwIP_Ethernet/src/EthernetCompat.h b/libraries/lwIP_Ethernet/src/EthernetCompat.h
new file mode 100644
index 0000000000..e398d5719d
--- /dev/null
+++ b/libraries/lwIP_Ethernet/src/EthernetCompat.h
@@ -0,0 +1,101 @@
+
+#pragma once
+
+#include <LwipEthernet.h>
+#include <WiFiUdp.h>
+#include <WiFiClient.h>
+#include <ArduinoWiFiServer.h>
+
+using EthernetUDP    = WiFiUDP;
+using EthernetClient = WiFiClient;
+using EthernetServer = ArduinoWiFiServer;
+
+enum EthernetLinkStatus
+{
+    Unknown,
+    LinkON,
+    LinkOFF
+};
+
+enum
+{
+    DHCP_CHECK_NONE        = 0,
+    DHCP_CHECK_RENEW_FAIL  = 1,
+    DHCP_CHECK_RENEW_OK    = 2,
+    DHCP_CHECK_REBIND_FAIL = 3,
+    DHCP_CHECK_REBIND_OK   = 4,
+};
+
+enum HardwareStatus
+{
+    EthernetNoHardware,
+    EthernetHardwareFound,
+};
+
+template<class RawDev>
+class ArduinoEthernet: public LwipIntfDev<RawDev>
+{
+public:
+    ArduinoEthernet(int8_t cs = SS, SPIClass& spi = SPI, int8_t intr = -1) :
+        LwipIntfDev<RawDev>(cs, spi, intr)
+    {
+        _hardwareStatus = EthernetNoHardware;
+        _linkStatus     = Unknown;
+    }
+
+    // Arduino-Ethernet API compatibility, order can be either:
+    // mac, ip, gateway, netmask, dns (esp8266 or natural order)
+    // mac, ip, dns, gateway, netmask (Arduino legacy)
+    boolean begin(const uint8_t* macAddress, const IPAddress& local_ip = IPADDR_NONE,
+                  const IPAddress& arg1 = IPADDR_NONE, const IPAddress& arg2 = IPADDR_NONE,
+                  const IPAddress& arg3 = IPADDR_NONE)
+    {
+        SPI4EthInit();  // Arduino Ethernet self-initializes SPI
+        bool ret = true;
+        if (local_ip.isSet())
+            ret = LwipIntfDev<RawDev>::config(local_ip, arg1, arg2, arg3);
+        if (ret)
+        {
+            ret = LwipIntfDev<RawDev>::begin(macAddress);
+            if (!local_ip.isSet())
+            {
+                // Arduino API waits for DHCP answer
+                while (!LwipIntfDev<RawDev>::connected())
+                {
+                    delay(100);
+                }
+            }
+        }
+
+        if (ret)
+        {
+            _hardwareStatus = EthernetHardwareFound;
+            _linkStatus     = LinkON;
+        }
+
+        return ret;
+    }
+
+    HardwareStatus hardwareStatus() const
+    {
+        return _hardwareStatus;
+    }
+
+    EthernetLinkStatus linkStatus() const
+    {
+        return _linkStatus;
+    }
+
+    int maintain() const
+    {
+        return DHCP_CHECK_NONE;
+    }
+
+protected:
+    HardwareStatus     _hardwareStatus;
+    EthernetLinkStatus _linkStatus;
+};
+
+using ArduinoWiznet5500lwIP = ArduinoEthernet<Wiznet5500>;
+using ArduinoWiznet5100lwIP = ArduinoEthernet<Wiznet5100>;
+using ArduinoENC28J60lwIP   = ArduinoEthernet<ENC28J60>;