Merge pull request #17230 from s-hadinger/ipv6_preview

IPv6 preview for ESP32, also working for ESP8266
This commit is contained in:
s-hadinger 2022-11-30 20:01:14 +01:00 committed by GitHub
commit baed1e06a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 575 additions and 97 deletions

View File

@ -24,6 +24,7 @@ All notable changes to this project will be documented in this file.
- Teleinfo TEMPO (BBR) contract (#17160)
- Support for HLK-LD2410 24GHz smart wave motion sensor
- Berry ``mdns`` module (#17202)
- IPv6 preview for ESP32, also working for ESP8266
### Changed
- Serial Bridge default internal serial rx buffer size from 64 to 256 (#17120)

View File

@ -77,6 +77,7 @@
#include <IPAddress.h>
#include <lwip/netif.h>
#include "IPAddress46.h"
#if LWIP_IPV6
#define IF_NUM_ADDRESSES (1 + LWIP_IPV6_NUM_ADDRESSES)
@ -84,80 +85,63 @@
#define IF_NUM_ADDRESSES (1)
#endif
namespace esp8266
{
namespace AddressListImplementation
{
struct netifWrapper
{
netifWrapper (netif* netif) : _netif(netif), _num(-1) {}
netifWrapper (const netifWrapper& o) : _netif(o._netif), _num(o._num) {}
netifWrapper (netif* netif) : _netif(netif), _num(-1) {}
netifWrapper (const netifWrapper& o) : _netif(o._netif), _num(o._num) {}
netifWrapper& operator= (const netifWrapper& o)
{
_netif = o._netif;
_num = o._num;
return *this;
}
netifWrapper& operator= (const netifWrapper& o)
{
_netif = o._netif;
_num = o._num;
return *this;
}
bool equal(const netifWrapper& o)
{
return _netif == o._netif && (!_netif || _num == o._num);
}
bool equal(const netifWrapper& o)
{
return _netif == o._netif && (!_netif || _num == o._num);
}
// address properties
class IPAddress4 : public IPAddress
{
public:
bool isV6() const
{
return false;
}
bool isLocal() const
{
return false;
}
};
IPAddress4 addr () const { return ipFromNetifNum(); }
bool isLegacy () const { return _num == 0; }
//bool isLocal () const { return addr().isLocal(); }
bool isV4 () const { return addr().isV4(); }
bool isV6 () const { return !addr().isV4(); }
String toString() const { return addr().toString(); }
IPAddress46 addr () const { return ipFromNetifNum(); }
bool isLegacy () const { return _num == 0; }
bool isLocal () const { return addr().isLocal(); }
bool isV4 () const { return addr().isV4(); }
bool isV6 () const { return !addr().isV4(); }
String toString() const { return addr().toString(); }
// related to legacy address (_num=0, ipv4)
IPAddress ipv4 () const { return _netif->ip_addr; }
IPAddress netmask () const { return _netif->netmask; }
IPAddress gw () const { return _netif->gw; }
// related to legacy address (_num=0, ipv4)
IPAddress46 ipv4 () const { return _netif->ip_addr; }
IPAddress46 netmask () const { return _netif->netmask; }
IPAddress46 gw () const { return _netif->gw; }
// common to all addresses of this interface
String ifname () const { return String(_netif->name[0]) + _netif->name[1]; }
const char* ifhostname () const { return _netif->hostname?: emptyString.c_str(); }
const char* ifmac () const { return (const char*)_netif->hwaddr; }
int ifnumber () const { return _netif->num; }
bool ifUp () const { return !!(_netif->flags & NETIF_FLAG_UP); }
const netif* interface () const { return _netif; }
// common to all addresses of this interface
String ifname () const { return String(_netif->name[0]) + _netif->name[1]; }
const char* ifhostname () const { return _netif->hostname?: emptyString.c_str(); }
const char* ifmac () const { return (const char*)_netif->hwaddr; }
int ifnumber () const { return _netif->num; }
bool ifUp () const { return !!(_netif->flags & NETIF_FLAG_UP); }
const netif* interface () const { return _netif; }
const ip_addr_t* ipFromNetifNum () const
{
const ip_addr_t* ipFromNetifNum () const
{
#if LWIP_IPV6
return _num ? &_netif->ip6_addr[_num - 1] : &_netif->ip_addr;
return _num ? &_netif->ip6_addr[_num - 1] : &_netif->ip_addr;
#else
return &_netif->ip_addr;
return &_netif->ip_addr;
#endif
}
}
// lwIP interface
netif* _netif;
// lwIP interface
netif* _netif;
// address index within interface
// 0: legacy address (IPv4)
// n>0: (_num-1) is IPv6 index for netif->ip6_addr[]
int _num;
// address index within interface
// 0: legacy address (IPv4)
// n>0: (_num-1) is IPv6 index for netif->ip6_addr[]
int _num;
};
@ -223,11 +207,10 @@ inline AddressList::const_iterator begin (const AddressList& a) { return a.begin
inline AddressList::const_iterator end (const AddressList& a) { return a.end(); }
} // AddressListImplementation
} // namespace AddressListImplementation
} // namespace esp8266
} // esp8266
extern AddressList addrList;
extern esp8266::AddressListImplementation::AddressList addrList;
#endif

View File

@ -19,9 +19,6 @@
#pragma once
#include <WiFi.h>
// sorry, no <AddrList.h>
#undef LWIP_IPV6
#define ENC_TYPE_NONE WIFI_AUTH_OPEN
#define ENC_TYPE_WEP WIFI_AUTH_WEP
#define ENC_TYPE_CCMP WIFI_AUTH_WPA2_PSK

View File

@ -0,0 +1,270 @@
/*
IPAddress46.cpp - IPv6 support for ESP32
This class is copied from ESP8266 Arduino framework and provides
temporary support for IPv6 on ESP32.
Copyright (C) 2021 Theo Arends and Stephan Hadinger
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
IPAddress.cpp - Base class that provides IPAddress
Copyright (c) 2011 Adrian McEwen. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Arduino.h>
#include <IPAddress46.h>
#include <Print.h>
#include <StreamString.h>
IPAddress46::IPAddress46(const IPAddress46& from)
{
ip_addr_copy(_ip, from._ip);
}
IPAddress46::IPAddress46() {
_ip = *IP_ANY_TYPE; // lwIP's v4-or-v6 generic address
}
bool IPAddress46::isSet () const {
return !ip_addr_isany(&_ip) && ((*this) != IPADDR_NONE);
}
IPAddress46::IPAddress46(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) {
setV4();
(*this)[0] = first_octet;
(*this)[1] = second_octet;
(*this)[2] = third_octet;
(*this)[3] = fourth_octet;
}
void IPAddress46::ctor32(uint32_t address) {
setV4();
v4() = address;
}
IPAddress46::IPAddress46(const uint8_t *address) {
setV4();
(*this)[0] = address[0];
(*this)[1] = address[1];
(*this)[2] = address[2];
(*this)[3] = address[3];
}
bool IPAddress46::fromString(const char *address) {
if (!fromString4(address)) {
#if LWIP_IPV6
return fromString6(address);
#else
return false;
#endif
}
return true;
}
bool IPAddress46::fromString4(const char *address) {
// TODO: (IPv4) add support for "a", "a.b", "a.b.c" formats
uint16_t acc = 0; // Accumulator
uint8_t dots = 0;
while (*address)
{
char c = *address++;
if (c >= '0' && c <= '9')
{
acc = acc * 10 + (c - '0');
if (acc > 255) {
// Value out of [0..255] range
return false;
}
}
else if (c == '.')
{
if (dots == 3) {
// Too much dots (there must be 3 dots)
return false;
}
(*this)[dots++] = acc;
acc = 0;
}
else
{
// Invalid char
return false;
}
}
if (dots != 3) {
// Too few dots (there must be 3 dots)
return false;
}
(*this)[3] = acc;
setV4();
return true;
}
IPAddress46& IPAddress46::operator=(const uint8_t *address) {
setV4();
v4() = *reinterpret_cast<const uint32_t*>(address);
return *this;
}
IPAddress46& IPAddress46::operator=(uint32_t address) {
setV4();
v4() = address;
return *this;
}
bool IPAddress46::operator==(const uint8_t* addr) const {
return isV4() && v4() == *reinterpret_cast<const uint32_t*>(addr);
}
size_t IPAddress46::printTo(Print& p) const {
size_t n = 0;
if (!isSet())
return p.print(F("(IP unset)"));
#if LWIP_IPV6
if (isV6()) {
int count0 = 0;
for (int i = 0; i < 8; i++) {
uint16_t bit = PP_NTOHS(raw6()[i]);
if (bit || count0 < 0) {
n += p.printf("%x", bit);
if (count0 > 0)
// no more hiding 0
count0 = -8;
} else
count0++;
if ((i != 7 && count0 < 2) || count0 == 7)
n += p.print(':');
}
return n;
}
#endif
for(int i = 0; i < 4; i++) {
n += p.print((*this)[i], DEC);
if (i != 3)
n += p.print('.');
}
return n;
}
String IPAddress46::toString() const
{
StreamString sstr;
#if LWIP_IPV6
if (isV6())
sstr.reserve(40); // 8 shorts x 4 chars each + 7 colons + nullterm
else
#endif
sstr.reserve(16); // 4 bytes with 3 chars max + 3 dots + nullterm, or '(IP unset)'
printTo(sstr);
return sstr;
}
bool IPAddress46::isValid(const String& arg) {
return IPAddress46().fromString(arg);
}
bool IPAddress46::isValid(const char* arg) {
return IPAddress46().fromString(arg);
}
const IPAddress46 INADDR46_ANY; // generic "0.0.0.0" for IPv4 & IPv6
const IPAddress46 INADDR46_NONE(255,255,255,255);
void IPAddress46::clear() {
(*this) = INADDR46_ANY;
}
/**************************************/
#if LWIP_IPV6
bool IPAddress46::fromString6(const char *address) {
// TODO: test test test
uint32_t acc = 0; // Accumulator
int dots = 0, doubledots = -1;
while (*address)
{
char c = tolower(*address++);
if (isalnum(c)) {
if (c >= 'a')
c -= 'a' - '0' - 10;
acc = acc * 16 + (c - '0');
if (acc > 0xffff)
// Value out of range
return false;
}
else if (c == ':') {
if (*address == ':') {
if (doubledots >= 0)
// :: allowed once
return false;
// remember location
doubledots = dots + !!acc;
address++;
}
if (dots == 7)
// too many separators
return false;
raw6()[dots++] = PP_HTONS(acc);
acc = 0;
}
else
// Invalid char
return false;
}
if (doubledots == -1 && dots != 7)
// Too few separators
return false;
raw6()[dots++] = PP_HTONS(acc);
if (doubledots != -1) {
for (int i = dots - doubledots - 1; i >= 0; i--)
raw6()[8 - dots + doubledots + i] = raw6()[doubledots + i];
for (int i = doubledots; i < 8 - dots + doubledots; i++)
raw6()[i] = 0;
}
setV6();
return true;
}
#endif

View File

@ -0,0 +1,184 @@
/*
IPAddress46.h - IPv6 support for ESP32
This class is copied from ESP8266 Arduino framework and provides
temporary support for IPv6 on ESP32.
Copyright (C) 2021 Theo Arends and Stephan Hadinger
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __IPADDRESS46_H
#define __IPADDRESS46_H
#include <Printable.h>
#include <WString.h>
#include <lwip/netif.h>
class IPAddress46: public Printable {
private:
ip_addr_t _ip;
// Access the raw byte array containing the address. Because this returns a pointer
// to the internal structure rather than a copy of the address this function should only
// be used when you know that the usage of the returned uint8_t* will be transient and not
// stored.
uint8_t* raw_address() {
return reinterpret_cast<uint8_t*>(&v4());
}
const uint8_t* raw_address() const {
return reinterpret_cast<const uint8_t*>(&v4());
}
void ctor32 (uint32_t);
public:
// Constructors
IPAddress46();
IPAddress46(const IPAddress46& from);
IPAddress46(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
IPAddress46(uint32_t address) { ctor32(address); }
IPAddress46(unsigned long address) { ctor32(address); }
IPAddress46(int address) { ctor32(address); }
IPAddress46(const uint8_t *address);
bool fromString(const char *address);
bool fromString(const String &address) { return fromString(address.c_str()); }
// Overloaded cast operator to allow IPAddress46 objects to be used where a pointer
// to a four-byte uint8_t array is expected
operator uint32_t() const { return isV4()? v4(): (uint32_t)0; }
operator uint32_t() { return isV4()? v4(): (uint32_t)0; }
bool isSet () const;
operator bool () const { return isSet(); } // <-
operator bool () { return isSet(); } // <- both are needed
// generic IPv4 wrapper to uint32-view like arduino loves to see it
const uint32_t& v4() const { return ip_2_ip4(&_ip)->addr; } // for raw_address(const)
uint32_t& v4() { return ip_2_ip4(&_ip)->addr; }
bool operator==(const IPAddress46& addr) const {
return ip_addr_cmp(&_ip, &addr._ip);
}
bool operator!=(const IPAddress46& addr) const {
return !ip_addr_cmp(&_ip, &addr._ip);
}
bool operator==(uint32_t addr) const {
return isV4() && v4() == addr;
}
bool operator==(unsigned long addr) const {
return isV4() && v4() == (uint32_t)addr;
}
bool operator!=(uint32_t addr) const {
return !(isV4() && v4() == addr);
}
bool operator!=(unsigned long addr) const {
return isV4() && v4() != (uint32_t)addr;
}
bool operator==(const uint8_t* addr) const;
int operator>>(int n) const {
return isV4()? v4() >> n: 0;
}
// Overloaded index operator to allow getting and setting individual octets of the address
uint8_t operator[](int index) const {
return isV4()? *(raw_address() + index): 0;
}
uint8_t& operator[](int index) {
setV4();
return *(raw_address() + index);
}
// Overloaded copy operators to allow initialisation of IPAddress46 objects from other types
IPAddress46& operator=(const uint8_t *address);
IPAddress46& operator=(uint32_t address);
IPAddress46& operator=(const IPAddress46&) = default;
virtual size_t printTo(Print& p) const;
String toString() const;
void clear();
/*
check if input string(arg) is a valid IPV4 address or not.
return true on valid.
return false on invalid.
*/
static bool isValid(const String& arg);
static bool isValid(const char* arg);
friend class EthernetClass;
friend class UDP;
friend class Client;
friend class Server;
friend class DhcpClass;
friend class DNSClient;
operator ip_addr_t () const { return _ip; }
operator const ip_addr_t*() const { return &_ip; }
operator ip_addr_t*() { return &_ip; }
bool isV4() const { return IP_IS_V4_VAL(_ip); }
void setV4() { IP_SET_TYPE_VAL(_ip, IPADDR_TYPE_V4); }
bool isLocal () const { return ip_addr_islinklocal(&_ip); }
#if LWIP_IPV6
IPAddress46(const ip_addr_t& lwip_addr) { ip_addr_copy(_ip, lwip_addr); }
IPAddress46(const ip_addr_t* lwip_addr) { ip_addr_copy(_ip, *lwip_addr); }
IPAddress46& operator=(const ip_addr_t& lwip_addr) { ip_addr_copy(_ip, lwip_addr); return *this; }
IPAddress46& operator=(const ip_addr_t* lwip_addr) { ip_addr_copy(_ip, *lwip_addr); return *this; }
uint16_t* raw6()
{
setV6();
return reinterpret_cast<uint16_t*>(ip_2_ip6(&_ip));
}
const uint16_t* raw6() const
{
return isV6()? reinterpret_cast<const uint16_t*>(ip_2_ip6(&_ip)): nullptr;
}
// when not IPv6, ip_addr_t == ip4_addr_t so this one would be ambiguous
// required otherwise
operator const ip4_addr_t*() const { return isV4()? ip_2_ip4(&_ip): nullptr; }
bool isV6() const { return IP_IS_V6_VAL(_ip); }
void setV6() { IP_SET_TYPE_VAL(_ip, IPADDR_TYPE_V6); }
protected:
bool fromString6(const char *address);
#else
// allow portable code when IPv6 is not enabled
uint16_t* raw6() { return nullptr; }
const uint16_t* raw6() const { return nullptr; }
bool isV6() const { return false; }
void setV6() { }
#endif
protected:
bool fromString4(const char *address);
};
#endif // __IPADDRESS46_H

View File

@ -99,6 +99,7 @@ build_flags = ${esp_defaults.build_flags}
; NONOSDK22x_190703 = 2.2.2-dev(38a443e)
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH ; enables IPv6
; VTABLES in Flash
-DVTABLES_IN_FLASH
; remove the 4-bytes alignment for PSTR()

View File

@ -110,6 +110,8 @@
#define D_JSON_IMPORT_REACTIVE "ImportReactive"
#define D_JSON_INFRARED "Infrared"
#define D_JSON_INVALID_FILE_TYPE "Invalid filetype or buffer"
#define D_JSON_IP6_GLOBAL "IP6Global"
#define D_JSON_IP6_LOCAL "IP6Local"
#define D_JSON_UNKNOWN "Unknown"
#define D_JSON_LIGHT "Light"
#define D_JSON_LINK_COUNT "LinkCount"

View File

@ -801,14 +801,23 @@ void CmndStatus(void)
}
if ((0 == payload) || (5 == payload)) {
// WifiDumpAddressesIPv6();
Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS5_NETWORK "\":{\"" D_CMND_HOSTNAME "\":\"%s\",\""
D_CMND_IPADDRESS "\":\"%_I\",\"" D_JSON_GATEWAY "\":\"%_I\",\"" D_JSON_SUBNETMASK "\":\"%_I\",\""
D_JSON_DNSSERVER "1\":\"%_I\",\"" D_JSON_DNSSERVER "2\":\"%_I\",\""
D_JSON_MAC "\":\"%s\""),
D_JSON_MAC "\":\"%s\""
#if LWIP_IPV6
",\"" D_JSON_IP6_GLOBAL "\":\"%s\",\"" D_JSON_IP6_LOCAL "\":\"%s\""
#endif // LWIP_IPV6
),
TasmotaGlobal.hostname,
(uint32_t)WiFi.localIP(), Settings->ipv4_address[1], Settings->ipv4_address[2],
Settings->ipv4_address[3], Settings->ipv4_address[4],
WiFi.macAddress().c_str());
WiFi.macAddress().c_str()
#if LWIP_IPV6
,WifiGetIPv6().c_str(), WifiGetIPv6LinkLocal().c_str()
#endif // LWIP_IPV6
);
#ifdef USE_TASMESH
ResponseAppend_P(PSTR(",\"SoftAPMac\":\"%s\""), WiFi.softAPmacAddress().c_str());
#endif // USE_TASMESH

View File

@ -42,7 +42,11 @@ const uint8_t WIFI_RETRY_OFFSET_SEC = WIFI_RETRY_SECONDS; // seconds
#include <ESP8266WiFi.h> // Wifi, MQTT, Ota, WifiManager
#if LWIP_IPV6
#include <AddrList.h> // IPv6 DualStack
#ifdef ESP8266
#include <AddrList.h> // IPv6 DualStack
#else
#include <AddrList46.h> // IPv6 DualStack
#endif
#endif // LWIP_IPV6=1
int WifiGetRssiAsQuality(int rssi) {
@ -263,20 +267,6 @@ void WifiBegin(uint8_t flag, uint8_t channel) {
if (Settings->flag5.wait_for_wifi_result) { // SetOption142 - (Wifi) Wait 1 second for wifi connection solving some FRITZ!Box modem issues (1)
WiFi.waitForConnectResult(1000); // https://github.com/arendst/Tasmota/issues/14985
}
#if LWIP_IPV6
for (bool configured = false; !configured;) {
uint16_t cfgcnt = 0;
for (auto addr : addrList) {
if ((configured = !addr.isLocal() && addr.isV6()) || cfgcnt==30) {
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI "Got IPv6 global address %s"), addr.toString().c_str());
break; // IPv6 is mandatory but stop after 15 seconds
}
delay(500); // Loop until real IPv6 address is aquired or too many tries failed
cfgcnt++;
}
}
#endif // LWIP_IPV6=1
}
void WifiBeginAfterScan(void)
@ -473,19 +463,55 @@ void WifiSetState(uint8_t state)
}
#if LWIP_IPV6
// Returns only IPv6 global address (no loopback and no link-local)
String WifiGetIPv6(void)
{
for (auto a : addrList) {
if(!a.isLocal() && a.isV6()) return a.toString();
if(!ip_addr_isloopback((ip_addr_t*)a.addr()) && !a.isLocal() && a.isV6()) return a.toString();
}
return "";
}
String WifiGetIPv6LinkLocal(void)
{
for (auto a : addrList) {
if(!ip_addr_isloopback((ip_addr_t*)a.addr()) && a.isLocal() && a.isV6()) return a.toString();
}
return "";
}
// add an IPv6 link-local address to all netif
void CreateLinkLocalIPv6(void)
{
#ifdef ESP32
for (auto intf = esp_netif_next(NULL); intf != NULL; intf = esp_netif_next(intf)) {
esp_netif_create_ip6_linklocal(intf);
}
#endif // ESP32
}
void WifiDumpAddressesIPv6(void)
{
for (auto a: addrList)
AddLog(LOG_LEVEL_DEBUG, PSTR("IF='%s' index=%d legacy=%d IPv4=%d local=%d addr='%s'"),
a.ifname().c_str(),
a.ifnumber(),
a.isLegacy(),
a.addr().isV4(),
a.addr().isLocal(),
a.toString().c_str());
}
#endif // LWIP_IPV6=1
// Check to see if we have any routable IP address
bool WifiHasIP(void) {
#ifdef LWIP2_IPV6
return !a.isLocal();
#if LWIP_IPV6
for (auto a : addrList) {
if(!ip_addr_isloopback((ip_addr_t*)a.addr()) && !a.isLocal()) {
return true;
}
}
return false;
#else
return (uint32_t)WiFi.localIP() != 0;
#endif
@ -504,6 +530,11 @@ void WifiCheckIp(void) {
Settings->ipv4_address[2] = (uint32_t)WiFi.subnetMask();
Settings->ipv4_address[3] = (uint32_t)WiFi.dnsIP();
Settings->ipv4_address[4] = (uint32_t)WiFi.dnsIP(1);
#if LWIP_IPV6
// create Link-local address
CreateLinkLocalIPv6();
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI "IPv6 Link-Local %s"), WifiGetIPv6LinkLocal().c_str());
#endif // LWIP_IPV6
// Save current AP parameters for quick reconnect
Settings->wifi_channel = WiFi.channel();

View File

@ -2362,7 +2362,11 @@ void HandleInformation(void)
#if LWIP_IPV6
String ipv6_addr = WifiGetIPv6();
if (ipv6_addr != "") {
WSContentSend_P(PSTR("}1 IPv6 Address }2%s"), ipv6_addr.c_str());
WSContentSend_P(PSTR("}1 IPv6 Global }2%s"), ipv6_addr.c_str());
}
ipv6_addr = WifiGetIPv6LinkLocal();
if (ipv6_addr != "") {
WSContentSend_P(PSTR("}1 IPv6 Link-Local }2%s"), ipv6_addr.c_str());
}
#endif // LWIP_IPV6 = 1
if (static_cast<uint32_t>(WiFi.localIP()) != 0) {

View File

@ -972,7 +972,8 @@ void MqttConnected(void) {
ResponseAppend_P(PSTR(",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%_I\""),
TasmotaGlobal.hostname, (uint32_t)WiFi.localIP());
#if LWIP_IPV6
ResponseAppend_P(PSTR(",\"IPv6Address\":\"%s\""), WifiGetIPv6().c_str());
ResponseAppend_P(PSTR(",\"" D_JSON_IP6_GLOBAL "\":\"%s\""), WifiGetIPv6().c_str());
ResponseAppend_P(PSTR(",\"" D_JSON_IP6_LOCAL "\":\"%s\""), WifiGetIPv6LinkLocal().c_str());
#endif // LWIP_IPV6 = 1
}
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)

View File

@ -131,12 +131,7 @@ extern "C" {
if ((p->len == p->tot_len) && (p->next == nullptr)) {
ip_addr_t ping_target;
struct icmp_echo_hdr *iecho;
#ifdef ESP8266
ping_target.addr = ping->ip;
#endif // ESP8266
#ifdef ESP32
ip_addr_set_ip4_u32(&ping_target, ping->ip);
#endif // ESP32
iecho = (struct icmp_echo_hdr *) p->payload;
t_ping_prepare_echo(iecho, ping_size, ping);
@ -171,12 +166,7 @@ extern "C" {
// Reveived packet
//
static uint8_t ICACHE_FLASH_ATTR t_ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr) {
#ifdef ESP8266
Ping_t *ping = t_ping_find(addr->addr);
#endif // ESP8266
#ifdef ESP32
Ping_t *ping = t_ping_find(addr->u_addr.ip4.addr);
#endif // ESP32
Ping_t *ping = t_ping_find(ip_addr_get_ip4_u32(addr));
if (nullptr == ping) { // unknown source address
return 0; // don't eat the packet and ignore it

View File

@ -220,6 +220,11 @@ extern "C" {
be_map_insert_str(vm, "ip6", ipv6_addr.c_str());
show_rssi = true;
}
ipv6_addr = WifiGetIPv6LinkLocal();
if (ipv6_addr != "") {
be_map_insert_str(vm, "ip6local", ipv6_addr.c_str());
show_rssi = true;
}
#endif
if (static_cast<uint32_t>(WiFi.localIP()) != 0) {
be_map_insert_str(vm, "mac", WiFi.macAddress().c_str());