mirror of
https://github.com/esp8266/Arduino.git
synced 2025-07-30 16:24:09 +03:00
more lwIP physical interfaces (#6680)
This commit adds W5500 W5100 and ENC28j60 drivers from @njh with credits They are available in libraries/ An example is added in W5500 examples directory plus: * Extract dhcp server from lwip2 and add it to the core as a class. It must always be present, it is linked and can be called by fw on boot. So it cannot be stored in a library. * ethernet: static or dhcp works * PPPServer: example * bring WiFi.config() to the lwIP generic interface (argument reorder common function) * move hostname() from WiFI-STA to generic interface * remove non readable characters from dhcp-server comments * dhcp-server: magic_cookie is part of bootp rfc * fixes from https://github.com/d-a-v/W5500lwIP/issues/17 * enable lwip_hook_dhcp_parse_option() * +ethernet tcp client example in w5500 library examples
This commit is contained in:
111
libraries/lwIP_PPP/examples/PPPServer/PPPServer.ino
Normal file
111
libraries/lwIP_PPP/examples/PPPServer/PPPServer.ino
Normal file
@ -0,0 +1,111 @@
|
||||
|
||||
// This is still beta / a work in progress
|
||||
|
||||
// To run this sketch an (other) USB-serial converter is needed connected to RX-TX ports (below)
|
||||
// hardware serial is used for logging
|
||||
// software serial is used for the PPP link
|
||||
// this example is subject for changes once everything is stabilized
|
||||
|
||||
// testing on linux:
|
||||
// sudo /usr/sbin/pppd /dev/ttyUSB1 38400 noipdefault nocrtscts local defaultroute noauth nodetach debug dump
|
||||
// sudo /usr/sbin/pppd /dev/ttyUSB1 38400 noipdefault nocrtscts local defaultroute noauth
|
||||
|
||||
// proxy arp is needed but we don't have it
|
||||
// http://lwip.100.n7.nabble.com/PPP-proxy-arp-support-tp33286p33345.html
|
||||
// using NAT instead
|
||||
|
||||
#if LWIP_FEATURES && !LWIP_IPV6
|
||||
|
||||
#include <lwip/napt.h>
|
||||
#include <lwip/dns.h>
|
||||
#include <PPPServer.h>
|
||||
#include <dhcpserver.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <SoftwareSerial.h>
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
#define LOGGERBAUD 115200
|
||||
#define PPPLINKBAUD 38400
|
||||
|
||||
#define NAPT 200
|
||||
#define NAPT_PORT 3
|
||||
|
||||
#define RX 13 // d1mini D7
|
||||
#define TX 15 // d1mini D8
|
||||
|
||||
SoftwareSerial ppplink(RX, TX);
|
||||
HardwareSerial& logger = Serial;
|
||||
PPPServer ppp(&ppplink);
|
||||
|
||||
void PPPConnectedCallback(netif* nif) {
|
||||
logger.printf("ppp: ip=%s/mask=%s/gw=%s\n",
|
||||
IPAddress(&nif->ip_addr).toString().c_str(),
|
||||
IPAddress(&nif->netmask).toString().c_str(),
|
||||
IPAddress(&nif->gw).toString().c_str());
|
||||
|
||||
logger.printf("Heap before: %d\n", ESP.getFreeHeap());
|
||||
err_t ret = ip_napt_init(NAPT, NAPT_PORT);
|
||||
logger.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(nif->num, 1);
|
||||
logger.printf("ip_napt_enable(nif): ret=%d (OK=%d)\n", (int)ret, (int)ERR_OK);
|
||||
if (ret == ERR_OK) {
|
||||
logger.printf("PPP client is NATed\n");
|
||||
}
|
||||
|
||||
// could not make this work yet,
|
||||
// but packets are arriving on ppp client (= linux host)
|
||||
logger.printf("redirect22=%d\n", ip_portmap_add(IP_PROTO_TCP, ip_2_ip4(&nif->ip_addr)->addr, 22, ip_2_ip4(&nif->gw)->addr, 22));
|
||||
logger.printf("redirect80=%d\n", ip_portmap_add(IP_PROTO_TCP, ip_2_ip4(&nif->ip_addr)->addr, 80, ip_2_ip4(&nif->gw)->addr, 80));
|
||||
logger.printf("redirect443=%d\n", ip_portmap_add(IP_PROTO_TCP, ip_2_ip4(&nif->ip_addr)->addr, 443, ip_2_ip4(&nif->gw)->addr, 443));
|
||||
}
|
||||
logger.printf("Heap after napt init: %d\n", ESP.getFreeHeap());
|
||||
if (ret != ERR_OK) {
|
||||
logger.printf("NAPT initialization failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
logger.begin(LOGGERBAUD);
|
||||
|
||||
WiFi.persistent(false);
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(STASSID, STAPSK);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
logger.print('.');
|
||||
delay(500);
|
||||
}
|
||||
logger.printf("\nSTA: %s (dns: %s / %s)\n",
|
||||
WiFi.localIP().toString().c_str(),
|
||||
WiFi.dnsIP(0).toString().c_str(),
|
||||
WiFi.dnsIP(1).toString().c_str());
|
||||
|
||||
ppplink.begin(PPPLINKBAUD);
|
||||
ppplink.enableIntTx(true);
|
||||
logger.println();
|
||||
logger.printf("\n\nhey, trying to be a PPP server here\n\n");
|
||||
logger.printf("Now try this on your linux host:\n\n");
|
||||
logger.printf("connect a serial<->usb module (e.g. to /dev/ttyUSB1) and link it to the ESP (esprx=%d esptx=%d), then run:\n\n", RX, TX);
|
||||
logger.printf("sudo /usr/sbin/pppd /dev/ttyUSB1 %d noipdefault nocrtscts local defaultroute noauth nodetach debug dump\n\n", PPPLINKBAUD);
|
||||
|
||||
ppp.ifUpCb(PPPConnectedCallback);
|
||||
bool ret = ppp.begin(WiFi.localIP());
|
||||
logger.printf("ppp: %d\n", ret);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.printf("\n\nPPP/NAPT not supported in this configuration\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void loop() {
|
||||
}
|
10
libraries/lwIP_PPP/library.properties
Normal file
10
libraries/lwIP_PPP/library.properties
Normal file
@ -0,0 +1,10 @@
|
||||
name=lwIP_PPP
|
||||
version=1
|
||||
author=lwIP
|
||||
maintainer=esp8266/Arduino
|
||||
sentence=PPP interface
|
||||
paragraph=PPP interface for esp8266 arduino
|
||||
category=Network
|
||||
url=https://github.com/esp8266/Arduino
|
||||
architectures=esp8266
|
||||
dot_a_linkage=true
|
196
libraries/lwIP_PPP/src/PPPServer.cpp
Normal file
196
libraries/lwIP_PPP/src/PPPServer.cpp
Normal file
@ -0,0 +1,196 @@
|
||||
|
||||
// This is still beta / a work in progress
|
||||
|
||||
// testing on linux:
|
||||
// sudo /usr/sbin/pppd /dev/ttyUSB1 38400 noipdefault nocrtscts local defaultroute noauth nodetach debug dump
|
||||
// sudo /usr/sbin/pppd /dev/ttyUSB1 38400 noipdefault nocrtscts local defaultroute noauth
|
||||
|
||||
// proxy arp is needed but we don't have it
|
||||
// http://lwip.100.n7.nabble.com/PPP-proxy-arp-support-tp33286p33345.html
|
||||
// using NAT instead (see in example)
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Schedule.h>
|
||||
#include <IPAddress.h>
|
||||
#include <lwip/dns.h>
|
||||
|
||||
#include "PPPServer.h"
|
||||
|
||||
PPPServer::PPPServer(Stream* sio): _sio(sio), _cb(netif_status_cb_s), _enabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool PPPServer::handlePackets()
|
||||
{
|
||||
size_t avail;
|
||||
if ((avail = _sio->available()) > 0)
|
||||
{
|
||||
// XXX block peeking would be useful here
|
||||
if (avail > _bufsize)
|
||||
{
|
||||
avail = _bufsize;
|
||||
}
|
||||
avail = _sio->readBytes(_buf, avail);
|
||||
pppos_input(_ppp, _buf, avail);
|
||||
}
|
||||
return _enabled;
|
||||
}
|
||||
|
||||
void PPPServer::link_status_cb_s(ppp_pcb* pcb, int err_code, void* ctx)
|
||||
{
|
||||
bool stop = true;
|
||||
netif* nif = ppp_netif(pcb);
|
||||
|
||||
switch (err_code)
|
||||
{
|
||||
case PPPERR_NONE: /* No error. */
|
||||
{
|
||||
#if LWIP_DNS
|
||||
const ip_addr_t *ns;
|
||||
#endif /* LWIP_DNS */
|
||||
ets_printf("ppp_link_status_cb: PPPERR_NONE\n\r");
|
||||
#if LWIP_IPV4
|
||||
ets_printf(" our_ip4addr = %s\n\r", ip4addr_ntoa(netif_ip4_addr(nif)));
|
||||
ets_printf(" his_ipaddr = %s\n\r", ip4addr_ntoa(netif_ip4_gw(nif)));
|
||||
ets_printf(" netmask = %s\n\r", ip4addr_ntoa(netif_ip4_netmask(nif)));
|
||||
#endif /* LWIP_IPV4 */
|
||||
#if LWIP_IPV6
|
||||
ets_printf(" our_ip6addr = %s\n\r", ip6addr_ntoa(netif_ip6_addr(nif, 0)));
|
||||
#endif /* LWIP_IPV6 */
|
||||
|
||||
#if LWIP_DNS
|
||||
ns = dns_getserver(0);
|
||||
ets_printf(" dns1 = %s\n\r", ipaddr_ntoa(ns));
|
||||
ns = dns_getserver(1);
|
||||
ets_printf(" dns2 = %s\n\r", ipaddr_ntoa(ns));
|
||||
#endif /* LWIP_DNS */
|
||||
#if PPP_IPV6_SUPPORT
|
||||
ets_printf(" our6_ipaddr = %s\n\r", ip6addr_ntoa(netif_ip6_addr(nif, 0)));
|
||||
#endif /* PPP_IPV6_SUPPORT */
|
||||
}
|
||||
stop = false;
|
||||
break;
|
||||
|
||||
case PPPERR_PARAM: /* Invalid parameter. */
|
||||
ets_printf("ppp_link_status_cb: PPPERR_PARAM\n");
|
||||
break;
|
||||
|
||||
case PPPERR_OPEN: /* Unable to open PPP session. */
|
||||
ets_printf("ppp_link_status_cb: PPPERR_OPEN\n");
|
||||
break;
|
||||
|
||||
case PPPERR_DEVICE: /* Invalid I/O device for PPP. */
|
||||
ets_printf("ppp_link_status_cb: PPPERR_DEVICE\n");
|
||||
break;
|
||||
|
||||
case PPPERR_ALLOC: /* Unable to allocate resources. */
|
||||
ets_printf("ppp_link_status_cb: PPPERR_ALLOC\n");
|
||||
break;
|
||||
|
||||
case PPPERR_USER: /* User interrupt. */
|
||||
ets_printf("ppp_link_status_cb: PPPERR_USER\n");
|
||||
break;
|
||||
|
||||
case PPPERR_CONNECT: /* Connection lost. */
|
||||
ets_printf("ppp_link_status_cb: PPPERR_CONNECT\n");
|
||||
break;
|
||||
|
||||
case PPPERR_AUTHFAIL: /* Failed authentication challenge. */
|
||||
ets_printf("ppp_link_status_cb: PPPERR_AUTHFAIL\n");
|
||||
break;
|
||||
|
||||
case PPPERR_PROTOCOL: /* Failed to meet protocol. */
|
||||
ets_printf("ppp_link_status_cb: PPPERR_PROTOCOL\n");
|
||||
break;
|
||||
|
||||
case PPPERR_PEERDEAD: /* Connection timeout. */
|
||||
ets_printf("ppp_link_status_cb: PPPERR_PEERDEAD\n");
|
||||
break;
|
||||
|
||||
case PPPERR_IDLETIMEOUT: /* Idle Timeout. */
|
||||
ets_printf("ppp_link_status_cb: PPPERR_IDLETIMEOUT\n");
|
||||
break;
|
||||
|
||||
case PPPERR_CONNECTTIME: /* PPPERR_CONNECTTIME. */
|
||||
ets_printf("ppp_link_status_cb: PPPERR_CONNECTTIME\n");
|
||||
break;
|
||||
|
||||
case PPPERR_LOOPBACK: /* Connection timeout. */
|
||||
ets_printf("ppp_link_status_cb: PPPERR_LOOPBACK\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
ets_printf("ppp_link_status_cb: unknown errCode %d\n", err_code);
|
||||
break;
|
||||
}
|
||||
|
||||
if (stop)
|
||||
{
|
||||
netif_remove(&static_cast<PPPServer*>(ctx)->_netif);
|
||||
}
|
||||
}
|
||||
|
||||
u32_t PPPServer::output_cb_s(ppp_pcb* pcb, u8_t* data, u32_t len, void* ctx)
|
||||
{
|
||||
(void)pcb;
|
||||
(void)ctx;
|
||||
return static_cast<PPPServer*>(ctx)->_sio->write(data, len);
|
||||
}
|
||||
|
||||
void PPPServer::netif_status_cb_s(netif* nif)
|
||||
{
|
||||
ets_printf("PPPNETIF: %c%c%d is %s\n", nif->name[0], nif->name[1], nif->num,
|
||||
netif_is_up(nif) ? "UP" : "DOWN");
|
||||
#if LWIP_IPV4
|
||||
ets_printf("IPV4: Host at %s ", ip4addr_ntoa(netif_ip4_addr(nif)));
|
||||
ets_printf("mask %s ", ip4addr_ntoa(netif_ip4_netmask(nif)));
|
||||
ets_printf("gateway %s\n", ip4addr_ntoa(netif_ip4_gw(nif)));
|
||||
#endif /* LWIP_IPV4 */
|
||||
#if LWIP_IPV6
|
||||
ets_printf("IPV6: Host at %s\n", ip6addr_ntoa(netif_ip6_addr(nif, 0)));
|
||||
#endif /* LWIP_IPV6 */
|
||||
ets_printf("FQDN: %s\n", netif_get_hostname(nif));
|
||||
}
|
||||
|
||||
bool PPPServer::begin(const IPAddress& ourAddress, const IPAddress& peer)
|
||||
{
|
||||
// lwip2-src/doc/ppp.txt
|
||||
|
||||
_ppp = pppos_create(&_netif, PPPServer::output_cb_s, PPPServer::link_status_cb_s, this);
|
||||
if (!_ppp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ppp_set_ipcp_ouraddr(_ppp, ip_2_ip4((const ip_addr_t*)ourAddress));
|
||||
ppp_set_ipcp_hisaddr(_ppp, ip_2_ip4((const ip_addr_t*)peer));
|
||||
|
||||
//ip4_addr_t addr;
|
||||
//IP4_ADDR(&addr, 10,0,1,254);
|
||||
//ppp_set_ipcp_dnsaddr(_ppp, 0, &addr);
|
||||
|
||||
//ppp_set_auth(_ppp, PPPAUTHTYPE_ANY, "login", "password");
|
||||
//ppp_set_auth_required(_ppp, 1);
|
||||
|
||||
ppp_set_silent(_ppp, 1);
|
||||
ppp_listen(_ppp);
|
||||
netif_set_status_callback(&_netif, _cb);
|
||||
|
||||
_enabled = true;
|
||||
if (!schedule_recurrent_function_us([&]()
|
||||
{
|
||||
return this->handlePackets();
|
||||
}, 1000))
|
||||
{
|
||||
netif_remove(&_netif);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PPPServer::stop()
|
||||
{
|
||||
_enabled = false;
|
||||
ppp_close(_ppp, 0);
|
||||
}
|
77
libraries/lwIP_PPP/src/PPPServer.h
Normal file
77
libraries/lwIP_PPP/src/PPPServer.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
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.
|
||||
|
||||
Author: Dirk Ziegelmeier <dziegel@gmx.de>
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __PPPSERVER_H
|
||||
#define __PPPSERVER_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <IPAddress.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <netif/ppp/ppp.h>
|
||||
#include <netif/ppp/pppos.h>
|
||||
|
||||
class PPPServer
|
||||
{
|
||||
public:
|
||||
|
||||
PPPServer(Stream* sio);
|
||||
|
||||
bool begin(const IPAddress& ourAddress, const IPAddress& peer = IPAddress(172, 31, 255, 254));
|
||||
void stop();
|
||||
|
||||
void ifUpCb(void (*cb)(netif*))
|
||||
{
|
||||
_cb = cb;
|
||||
}
|
||||
const ip_addr_t* getPeerAddress() const
|
||||
{
|
||||
return &_netif.gw;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
static constexpr size_t _bufsize = 128;
|
||||
Stream* _sio;
|
||||
ppp_pcb* _ppp;
|
||||
netif _netif;
|
||||
void (*_cb)(netif*);
|
||||
uint8_t _buf[_bufsize];
|
||||
bool _enabled;
|
||||
|
||||
// feed ppp from stream - to call on a regular basis or on interrupt
|
||||
bool handlePackets();
|
||||
|
||||
static u32_t output_cb_s(ppp_pcb* pcb, u8_t* data, u32_t len, void* ctx);
|
||||
static void link_status_cb_s(ppp_pcb* pcb, int err_code, void* ctx);
|
||||
static void netif_status_cb_s(netif* nif);
|
||||
|
||||
};
|
||||
|
||||
#endif // __PPPSERVER_H
|
Reference in New Issue
Block a user