mirror of https://github.com/arendst/Tasmota.git
Support for IPv6 only networks on Ethernet (not yet Wifi) (#17527)
This commit is contained in:
parent
ef1211b51f
commit
ef4138bdaa
|
@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file.
|
||||||
- Berry crypto add ``HKDF_HMAC_SHA256``
|
- Berry crypto add ``HKDF_HMAC_SHA256``
|
||||||
- Support for up to 3 single phase modbus energy monitoring device using generic Energy Modbus driver
|
- Support for up to 3 single phase modbus energy monitoring device using generic Energy Modbus driver
|
||||||
- Berry crypto add ``SPAKE2P_Matter`` for Matter support
|
- Berry crypto add ``SPAKE2P_Matter`` for Matter support
|
||||||
|
- Support for IPv6 only networks on Ethernet (not yet Wifi)
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <esp_wifi.h>
|
#include <esp_wifi.h>
|
||||||
|
|
||||||
|
extern void AddLog(uint32_t loglevel, PGM_P formatP, ...);
|
||||||
|
enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Wifi
|
// Wifi
|
||||||
//
|
//
|
||||||
|
@ -32,49 +35,97 @@
|
||||||
#include "lwip/dns.h"
|
#include "lwip/dns.h"
|
||||||
|
|
||||||
wl_status_t WiFiClass32::begin(const char* wpa2_ssid, wpa2_auth_method_t method, const char* wpa2_identity, const char* wpa2_username, const char *wpa2_password, const char* ca_pem, const char* client_crt, const char* client_key, int32_t channel, const uint8_t* bssid, bool connect) {
|
wl_status_t WiFiClass32::begin(const char* wpa2_ssid, wpa2_auth_method_t method, const char* wpa2_identity, const char* wpa2_username, const char *wpa2_password, const char* ca_pem, const char* client_crt, const char* client_key, int32_t channel, const uint8_t* bssid, bool connect) {
|
||||||
saveDNS();
|
scrubDNS();
|
||||||
wl_status_t ret = WiFiClass::begin(wpa2_ssid, method, wpa2_identity, wpa2_username, wpa2_password, ca_pem, client_crt, client_key, channel, bssid, connect);
|
wl_status_t ret = WiFiClass::begin(wpa2_ssid, method, wpa2_identity, wpa2_username, wpa2_password, ca_pem, client_crt, client_key, channel, bssid, connect);
|
||||||
restoreDNS();
|
scrubDNS();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_status_t WiFiClass32::begin(const char* ssid, const char *passphrase, int32_t channel, const uint8_t* bssid, bool connect) {
|
wl_status_t WiFiClass32::begin(const char* ssid, const char *passphrase, int32_t channel, const uint8_t* bssid, bool connect) {
|
||||||
saveDNS();
|
scrubDNS();
|
||||||
wl_status_t ret = WiFiClass::begin(ssid, passphrase, channel, bssid, connect);
|
wl_status_t ret = WiFiClass::begin(ssid, passphrase, channel, bssid, connect);
|
||||||
restoreDNS();
|
scrubDNS();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_status_t WiFiClass32::begin(char* ssid, char *passphrase, int32_t channel, const uint8_t* bssid, bool connect) {
|
wl_status_t WiFiClass32::begin(char* ssid, char *passphrase, int32_t channel, const uint8_t* bssid, bool connect) {
|
||||||
saveDNS();
|
scrubDNS();
|
||||||
wl_status_t ret = WiFiClass::begin(ssid, passphrase, channel, bssid, connect);
|
wl_status_t ret = WiFiClass::begin(ssid, passphrase, channel, bssid, connect);
|
||||||
restoreDNS();
|
scrubDNS();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
wl_status_t WiFiClass32::begin() {
|
wl_status_t WiFiClass32::begin() {
|
||||||
saveDNS();
|
scrubDNS();
|
||||||
wl_status_t ret = WiFiClass::begin();
|
wl_status_t ret = WiFiClass::begin();
|
||||||
restoreDNS();
|
scrubDNS();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiFiClass32::saveDNS(void) {
|
// scrubDNS
|
||||||
// save the DNS servers
|
//
|
||||||
for (uint32_t i=0; i<DNS_MAX_SERVERS; i++) {
|
// LWIP has a single DNS table for all interfaces and for v4/v6
|
||||||
const ip_addr_t * ip = dns_getserver(i);
|
// Unfortunately when trying to connect to Wifi, the dns server table is erased.
|
||||||
if (!ip_addr_isany(ip)) {
|
//
|
||||||
dns_save[i] = *ip;
|
// We restore DNS previous values if they are empty
|
||||||
}
|
// We restore or erase DNS entries if they are unsupported (v4 vs v6)
|
||||||
}
|
extern bool WifiHasIPv4(void);
|
||||||
}
|
extern bool EthernetHasIPv4(void);
|
||||||
|
extern bool WifiHasIPv6(void);
|
||||||
|
extern bool EthernetHasIPv6(void);
|
||||||
|
|
||||||
void WiFiClass32::restoreDNS(void) {
|
void WiFiClass32::scrubDNS(void) {
|
||||||
// restore DNS server if it was removed
|
// String dns_entry0 = IPAddress(dns_getserver(0)).toString();
|
||||||
|
// String dns_entry1 = IPAddress(dns_getserver(1)).toString();
|
||||||
|
// scan DNS entries
|
||||||
|
bool has_v4 = WifiHasIPv4() || EthernetHasIPv4();
|
||||||
|
bool has_v6 = false;
|
||||||
|
#ifdef USE_IPV6
|
||||||
|
has_v6 = WifiHasIPv6() || EthernetHasIPv6();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// First pass, save values
|
||||||
for (uint32_t i=0; i<DNS_MAX_SERVERS; i++) {
|
for (uint32_t i=0; i<DNS_MAX_SERVERS; i++) {
|
||||||
if (ip_addr_isany(dns_getserver(i))) {
|
#ifdef USE_IPV6
|
||||||
dns_setserver(i, &dns_save[i]);
|
const IPAddress ip_dns = IPAddress(dns_getserver(i));
|
||||||
|
// Step 1. save valid values from DNS
|
||||||
|
if (!ip_addr_isany_val((const ip_addr_t &)ip_dns)) {
|
||||||
|
if (ip_dns.isV4() && has_v4) {
|
||||||
|
dns_save4[i] = (ip_addr_t) ip_dns; // dns entry is populated, save it in v4 slot
|
||||||
|
} else if (ip_dns.isV6() && has_v6) {
|
||||||
|
dns_save6[i] = (ip_addr_t) ip_dns; // dns entry is populated, save it in v6 slot
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Step 2. scrub addresses not supported
|
||||||
|
if (!has_v4) { dns_save4[i] = *IP4_ADDR_ANY; }
|
||||||
|
if (!has_v6) { dns_save6[i] = *IP_ADDR_ANY; }
|
||||||
|
|
||||||
|
// Step 3. restore saved value
|
||||||
|
if (has_v4 && has_v6) { // if both IPv4 and IPv6 are active, prefer IPv4
|
||||||
|
if (!ip_addr_isany_val(dns_save4[i])) { dns_setserver(i, &dns_save4[i]); }
|
||||||
|
else { dns_setserver(i, &dns_save6[i]); }
|
||||||
|
} else if (has_v4) {
|
||||||
|
dns_setserver(i, &dns_save4[i]);
|
||||||
|
} else if (has_v6) {
|
||||||
|
dns_setserver(i, &dns_save6[i]);
|
||||||
|
} else {
|
||||||
|
dns_setserver(i, IP4_ADDR_ANY);
|
||||||
|
}
|
||||||
|
#else // USE_IPV6
|
||||||
|
uint32_t ip_dns = ip_addr_get_ip4_u32(dns_getserver(i));
|
||||||
|
// Step 1. save valid values from DNS
|
||||||
|
if (has_v4 && (uint32_t)ip_dns != 0) {
|
||||||
|
ip_addr_set_ip4_u32_val(dns_save4[i], ip_dns);
|
||||||
|
}
|
||||||
|
// Step 2. scrub addresses not supported
|
||||||
|
if (!has_v4) {
|
||||||
|
ip_addr_set_ip4_u32_val(dns_save4[i], 0L);
|
||||||
|
}
|
||||||
|
// Step 3. restore saved value
|
||||||
|
dns_setserver(i, &dns_save4[i]);
|
||||||
|
#endif // USE_IPV6
|
||||||
}
|
}
|
||||||
|
// AddLog(LOG_LEVEL_DEBUG, "IP>: DNS: from(%s %s) to (%s %s) has4/6:%i-%i", dns_entry0.c_str(), dns_entry1.c_str(), IPAddress(dns_getserver(0)).toString().c_str(), IPAddress(dns_getserver(1)).toString().c_str(), has_v4, has_v6);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiFiClass32::setSleepMode(int iSleepMode) {
|
void WiFiClass32::setSleepMode(int iSleepMode) {
|
||||||
|
@ -190,6 +241,7 @@ int WiFiClass32::hostByName(const char* aHostname, IPAddress& aResult, int32_t t
|
||||||
aResult = (uint32_t) 0; // by default set to IPv4 0.0.0.0
|
aResult = (uint32_t) 0; // by default set to IPv4 0.0.0.0
|
||||||
dns_ipaddr = *IP4_ADDR_ANY; // by default set to IPv4 0.0.0.0
|
dns_ipaddr = *IP4_ADDR_ANY; // by default set to IPv4 0.0.0.0
|
||||||
|
|
||||||
|
scrubDNS(); // internal calls to reconnect can zero the DNS servers, save DNS for future use
|
||||||
ip_addr_counter++; // increase counter, from now ignore previous responses
|
ip_addr_counter++; // increase counter, from now ignore previous responses
|
||||||
clearStatusBits(WIFI_DNS_IDLE_BIT | WIFI_DNS_DONE_BIT);
|
clearStatusBits(WIFI_DNS_IDLE_BIT | WIFI_DNS_DONE_BIT);
|
||||||
uint8_t v4v6priority = LWIP_DNS_ADDRTYPE_IPV4;
|
uint8_t v4v6priority = LWIP_DNS_ADDRTYPE_IPV4;
|
||||||
|
|
|
@ -60,10 +60,12 @@ public:
|
||||||
int hostByName(const char* aHostname, IPAddress& aResult, int32_t timer_ms);
|
int hostByName(const char* aHostname, IPAddress& aResult, int32_t timer_ms);
|
||||||
int hostByName(const char* aHostname, IPAddress& aResult);
|
int hostByName(const char* aHostname, IPAddress& aResult);
|
||||||
|
|
||||||
void saveDNS(void);
|
void scrubDNS(void);
|
||||||
void restoreDNS(void);
|
|
||||||
protected:
|
protected:
|
||||||
ip_addr_t dns_save[DNS_MAX_SERVERS] = {};
|
ip_addr_t dns_save4[DNS_MAX_SERVERS] = {}; // IPv4 DNS servers
|
||||||
|
#ifdef USE_IPV6
|
||||||
|
ip_addr_t dns_save6[DNS_MAX_SERVERS] = {}; // IPv6 DNS servers
|
||||||
|
#endif // USE_IPV6
|
||||||
};
|
};
|
||||||
|
|
||||||
void wifi_station_disconnect();
|
void wifi_station_disconnect();
|
||||||
|
|
|
@ -804,44 +804,51 @@ void CmndStatus(void)
|
||||||
if ((0 == payload) || (5 == payload)) {
|
if ((0 == payload) || (5 == payload)) {
|
||||||
#ifdef USE_IPV6
|
#ifdef USE_IPV6
|
||||||
if (5 == payload) { WifiDumpAddressesIPv6(); }
|
if (5 == payload) { WifiDumpAddressesIPv6(); }
|
||||||
#endif // USE_IPV6
|
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\":\"%s\",\"" D_JSON_DNSSERVER "2\":\"%s\",\""
|
||||||
|
D_JSON_MAC "\":\"%s\""
|
||||||
|
",\"" D_JSON_IP6_GLOBAL "\":\"%s\",\"" D_JSON_IP6_LOCAL "\":\"%s\""),
|
||||||
|
TasmotaGlobal.hostname,
|
||||||
|
(uint32_t)WiFi.localIP(), Settings->ipv4_address[1], Settings->ipv4_address[2],
|
||||||
|
DNSGetIPStr(0).c_str(), DNSGetIPStr(1).c_str(),
|
||||||
|
WiFi.macAddress().c_str()
|
||||||
|
,WifiGetIPv6Str().c_str(), WifiGetIPv6LinkLocalStr().c_str());
|
||||||
|
#else // USE_IPV6
|
||||||
Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS5_NETWORK "\":{\"" D_CMND_HOSTNAME "\":\"%s\",\""
|
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_CMND_IPADDRESS "\":\"%_I\",\"" D_JSON_GATEWAY "\":\"%_I\",\"" D_JSON_SUBNETMASK "\":\"%_I\",\""
|
||||||
D_JSON_DNSSERVER "1\":\"%_I\",\"" D_JSON_DNSSERVER "2\":\"%_I\",\""
|
D_JSON_DNSSERVER "1\":\"%_I\",\"" D_JSON_DNSSERVER "2\":\"%_I\",\""
|
||||||
D_JSON_MAC "\":\"%s\""
|
D_JSON_MAC "\":\"%s\""),
|
||||||
#ifdef USE_IPV6
|
|
||||||
",\"" D_JSON_IP6_GLOBAL "\":\"%s\",\"" D_JSON_IP6_LOCAL "\":\"%s\""
|
|
||||||
#endif // USE_IPV6
|
|
||||||
),
|
|
||||||
TasmotaGlobal.hostname,
|
TasmotaGlobal.hostname,
|
||||||
(uint32_t)WiFi.localIP(), Settings->ipv4_address[1], Settings->ipv4_address[2],
|
(uint32_t)WiFi.localIP(), Settings->ipv4_address[1], Settings->ipv4_address[2],
|
||||||
Settings->ipv4_address[3], Settings->ipv4_address[4],
|
Settings->ipv4_address[3], Settings->ipv4_address[4],
|
||||||
WiFi.macAddress().c_str()
|
WiFi.macAddress().c_str());
|
||||||
#ifdef USE_IPV6
|
|
||||||
,WifiGetIPv6().c_str(), WifiGetIPv6LinkLocal().c_str()
|
|
||||||
#endif // USE_IPV6
|
#endif // USE_IPV6
|
||||||
);
|
|
||||||
#ifdef USE_TASMESH
|
#ifdef USE_TASMESH
|
||||||
ResponseAppend_P(PSTR(",\"SoftAPMac\":\"%s\""), WiFi.softAPmacAddress().c_str());
|
ResponseAppend_P(PSTR(",\"SoftAPMac\":\"%s\""), WiFi.softAPmacAddress().c_str());
|
||||||
#endif // USE_TASMESH
|
#endif // USE_TASMESH
|
||||||
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)
|
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)
|
||||||
|
#ifdef USE_IPV6
|
||||||
|
ResponseAppend_P(PSTR(",\"Ethernet\":{\"" D_CMND_HOSTNAME "\":\"%s\",\""
|
||||||
|
D_CMND_IPADDRESS "\":\"%_I\",\"" D_JSON_GATEWAY "\":\"%_I\",\"" D_JSON_SUBNETMASK "\":\"%_I\",\""
|
||||||
|
D_JSON_DNSSERVER "1\":\"%s\",\"" D_JSON_DNSSERVER "2\":\"%s\",\""
|
||||||
|
D_JSON_MAC "\":\"%s\",\"" D_JSON_IP6_GLOBAL "\":\"%s\",\"" D_JSON_IP6_LOCAL "\":\"%s\"}"),
|
||||||
|
EthernetHostname(),
|
||||||
|
(uint32_t)EthernetLocalIP(), Settings->eth_ipv4_address[1], Settings->eth_ipv4_address[2],
|
||||||
|
DNSGetIPStr(0).c_str(), DNSGetIPStr(1).c_str(),
|
||||||
|
EthernetMacAddress().c_str(),
|
||||||
|
EthernetGetIPv6Str().c_str(), EthernetGetIPv6LinkLocalStr().c_str());
|
||||||
|
#else // USE_IPV6
|
||||||
ResponseAppend_P(PSTR(",\"Ethernet\":{\"" D_CMND_HOSTNAME "\":\"%s\",\""
|
ResponseAppend_P(PSTR(",\"Ethernet\":{\"" D_CMND_HOSTNAME "\":\"%s\",\""
|
||||||
D_CMND_IPADDRESS "\":\"%_I\",\"" D_JSON_GATEWAY "\":\"%_I\",\"" D_JSON_SUBNETMASK "\":\"%_I\",\""
|
D_CMND_IPADDRESS "\":\"%_I\",\"" D_JSON_GATEWAY "\":\"%_I\",\"" D_JSON_SUBNETMASK "\":\"%_I\",\""
|
||||||
D_JSON_DNSSERVER "1\":\"%_I\",\"" D_JSON_DNSSERVER "2\":\"%_I\",\""
|
D_JSON_DNSSERVER "1\":\"%_I\",\"" D_JSON_DNSSERVER "2\":\"%_I\",\""
|
||||||
D_JSON_MAC "\":\"%s\""
|
D_JSON_MAC "\":\"%s\"}"),
|
||||||
|
|
||||||
#ifdef USE_IPV6
|
|
||||||
",\"" D_JSON_IP6_GLOBAL "\":\"%s\",\"" D_JSON_IP6_LOCAL "\":\"%s\""
|
|
||||||
#endif // USE_IPV6
|
|
||||||
"}"),
|
|
||||||
EthernetHostname(),
|
EthernetHostname(),
|
||||||
(uint32_t)EthernetLocalIP(), Settings->eth_ipv4_address[1], Settings->eth_ipv4_address[2],
|
(uint32_t)EthernetLocalIP(), Settings->eth_ipv4_address[1], Settings->eth_ipv4_address[2],
|
||||||
Settings->eth_ipv4_address[3], Settings->eth_ipv4_address[4],
|
Settings->eth_ipv4_address[3], Settings->eth_ipv4_address[4],
|
||||||
EthernetMacAddress().c_str()
|
EthernetMacAddress().c_str()
|
||||||
#ifdef USE_IPV6
|
|
||||||
,EthernetGetIPv6().c_str(), EthernetGetIPv6LinkLocal().c_str()
|
|
||||||
#endif // USE_IPV6
|
#endif // USE_IPV6
|
||||||
);
|
|
||||||
#endif // USE_ETHERNET
|
#endif // USE_ETHERNET
|
||||||
ResponseAppend_P(PSTR(",\"" D_CMND_WEBSERVER "\":%d,\"HTTP_API\":%d,\"" D_CMND_WIFICONFIG "\":%d,\"" D_CMND_WIFIPOWER "\":%s}}"),
|
ResponseAppend_P(PSTR(",\"" D_CMND_WEBSERVER "\":%d,\"HTTP_API\":%d,\"" D_CMND_WIFICONFIG "\":%d,\"" D_CMND_WIFIPOWER "\":%s}}"),
|
||||||
Settings->webserver, Settings->flag5.disable_referer_chk, Settings->sta_config, WifiGetOutputPower().c_str());
|
Settings->webserver, Settings->flag5.disable_referer_chk, Settings->sta_config, WifiGetOutputPower().c_str());
|
||||||
|
|
|
@ -1576,14 +1576,10 @@ void Every250mSeconds(void)
|
||||||
if (Settings->webserver) {
|
if (Settings->webserver) {
|
||||||
|
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
if (!WifiIsInManagerMode()) { StartWebserver(Settings->webserver, WiFi.localIP()); }
|
if (!WifiIsInManagerMode()) { StartWebserver(Settings->webserver); }
|
||||||
#endif // ESP8266
|
#endif // ESP8266
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
#ifdef USE_ETHERNET
|
StartWebserver(Settings->webserver);
|
||||||
StartWebserver(Settings->webserver, (EthernetLocalIP()) ? EthernetLocalIP() : WiFi.localIP());
|
|
||||||
#else
|
|
||||||
StartWebserver(Settings->webserver, WiFi.localIP());
|
|
||||||
#endif
|
|
||||||
#endif // ESP32
|
#endif // ESP32
|
||||||
|
|
||||||
#ifdef USE_DISCOVERY
|
#ifdef USE_DISCOVERY
|
||||||
|
|
|
@ -41,6 +41,7 @@ const uint8_t WIFI_CHECK_SEC = 20; // seconds
|
||||||
const uint8_t WIFI_RETRY_OFFSET_SEC = WIFI_RETRY_SECONDS; // seconds
|
const uint8_t WIFI_RETRY_OFFSET_SEC = WIFI_RETRY_SECONDS; // seconds
|
||||||
|
|
||||||
#include <ESP8266WiFi.h> // Wifi, MQTT, Ota, WifiManager
|
#include <ESP8266WiFi.h> // Wifi, MQTT, Ota, WifiManager
|
||||||
|
#include "lwip/dns.h"
|
||||||
|
|
||||||
int WifiGetRssiAsQuality(int rssi) {
|
int WifiGetRssiAsQuality(int rssi) {
|
||||||
int quality = 0;
|
int quality = 0;
|
||||||
|
@ -458,37 +459,110 @@ void WifiSetState(uint8_t state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************************************\
|
||||||
|
* IP detection revised for full IPv4 / IPv6 support
|
||||||
|
*
|
||||||
|
* In general, each interface (Wifi/Eth) can have 1x IPv4 and
|
||||||
|
* 2x IPv6 (Global routable address and Link-Local starting witn fe80:...)
|
||||||
|
*
|
||||||
|
* We always use an IPv4 address if one is assigned, and revert to
|
||||||
|
* IPv6 only on networks that are v6 only.
|
||||||
|
* Ethernet calls can be safely used even if the USE_ETHERNET is not enabled
|
||||||
|
*
|
||||||
|
* New APIs:
|
||||||
|
* - general form is:
|
||||||
|
* `bool XXXGetIPYYY(IPAddress*)` returns `true` if the address exists and copies the address
|
||||||
|
* if the pointer is non-null.
|
||||||
|
* `bool XXXHasIPYYY()` same as above but only returns `true` or `false`
|
||||||
|
* `String XXXGetIPYYYStr()` returns the IP as a `String` or empty `String` if none
|
||||||
|
*
|
||||||
|
* `XXX` can be `Wifi` or `Eth`
|
||||||
|
* `YYY` can be `` for any address, `v6` for IPv6 global address or `v6LinkLocal` for Link-local
|
||||||
|
*
|
||||||
|
* - Legacy `Wifi.localIP()` and `ETH.localIP()` always return IPv4 and nothing on IPv6 only networks
|
||||||
|
*
|
||||||
|
* - v4/v6:
|
||||||
|
* `WifiGetIP`, `WifiGetIPStr`, `WifiHasIP`: get preferred v4/v6 address for Wifi
|
||||||
|
* `EthernetGetIP`, `EthernetGetIPStr`, `EthernetHasIP`: get preferred v4/v6 for Ethernet
|
||||||
|
*
|
||||||
|
* - Main IP to be used dual stack v4/v6
|
||||||
|
* `hasIP`, `IPGetListeningAddress`, `IPGetListeningAddressStr`: any IP to listen to for Web Server
|
||||||
|
* IPv4 is always preferred, and Eth is preferred over Wifi.
|
||||||
|
* `IPForUrl`: converts v4/v6 to use in URL, enclosing v6 in []
|
||||||
|
*
|
||||||
|
* - v6 only:
|
||||||
|
* `WifiGetIPv6`, `WifiGetIPv6Str`, `WifiHasIPv6`
|
||||||
|
* `WifiGetIPv6LinkLocal`, `WifiGetIPv6LinkLocalStr`
|
||||||
|
* `EthernetGetIPv6, `EthernetHasIPv6`, `EthernetGetIPv6Str`
|
||||||
|
* `EthernetGetIPv6LinkLocal`, `EthernetGetIPv6LinkLocalStr`
|
||||||
|
*
|
||||||
|
* - v4 only:
|
||||||
|
* `WifiGetIPv4`, `WifiGetIPv4Str`, `WifiHasIPv4`
|
||||||
|
* `EthernetGetIPv4`, `EthernetGetIPv4Str`, `EthernetHasIPv4`
|
||||||
|
*
|
||||||
|
* - DNS reporting actual values used (not the Settings):
|
||||||
|
* `DNSGetIP(n)`, `DNSGetIPStr(n)` with n=`0`/`1` (same dns for Wifi and Eth)
|
||||||
|
\*****************************************************************************************************/
|
||||||
|
// IPv4 for Wifi
|
||||||
|
// Returns only IPv6 global address (no loopback and no link-local)
|
||||||
|
bool WifiGetIPv4(IPAddress *ip)
|
||||||
|
{
|
||||||
|
uint32_t wifi_uint = (uint32_t) WiFi.localIP();
|
||||||
|
if (ip != nullptr) { *ip = wifi_uint; }
|
||||||
|
return wifi_uint != 0;
|
||||||
|
}
|
||||||
|
bool WifiHasIPv4(void)
|
||||||
|
{
|
||||||
|
return WifiGetIPv4(nullptr);
|
||||||
|
}
|
||||||
|
String WifiGetIPv4Str(void)
|
||||||
|
{
|
||||||
|
IPAddress ip;
|
||||||
|
return WifiGetIPv4(&ip) ? ip.toString() : String();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EthernetGetIPv4(IPAddress *ip)
|
||||||
|
{
|
||||||
|
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)
|
||||||
|
uint32_t wifi_uint = (uint32_t) EthernetLocalIP();
|
||||||
|
if (ip != nullptr) { *ip = wifi_uint; }
|
||||||
|
return wifi_uint != 0;
|
||||||
|
#else
|
||||||
|
if (ip != nullptr) { *ip = (uint32_t)0; }
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
bool EthernetHasIPv4(void)
|
||||||
|
{
|
||||||
|
return EthernetGetIPv4(nullptr);
|
||||||
|
}
|
||||||
|
String EthernetGetIPv4Str(void)
|
||||||
|
{
|
||||||
|
IPAddress ip;
|
||||||
|
return EthernetGetIPv4(&ip) ? ip.toString() : String();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_IPV6
|
#ifdef USE_IPV6
|
||||||
//
|
//
|
||||||
// Scan through all interfaces to find a global or local IPv6 address
|
// Scan through all interfaces to find a global or local IPv6 address
|
||||||
// Arg:
|
// Arg:
|
||||||
// is_local: is the address Link-Local (true) or Global (false)
|
// is_local: is the address Link-Local (true) or Global (false)
|
||||||
// if_type: possible values are "st" for Wifi STA, "en" for Ethernet, "lo" for localhost (not useful)
|
// if_type: possible values are "st" for Wifi STA, "en" for Ethernet, "lo" for localhost (not useful)
|
||||||
static String WifiFindIPv6(bool is_local, const char * if_type = "st") {
|
// Returns `true` if found
|
||||||
|
bool WifiFindIPv6(IPAddress *ip, bool is_local, const char * if_type = "st") {
|
||||||
for (netif* intf = netif_list; intf != nullptr; intf = intf->next) {
|
for (netif* intf = netif_list; intf != nullptr; intf = intf->next) {
|
||||||
if (intf->name[0] == if_type[0] && intf->name[1] == if_type[1]) {
|
if (intf->name[0] == if_type[0] && intf->name[1] == if_type[1]) {
|
||||||
for (uint32_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
for (uint32_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||||
ip_addr_t *ipv6 = &intf->ip6_addr[i];
|
ip_addr_t *ipv6 = &intf->ip6_addr[i];
|
||||||
if (IP_IS_V6_VAL(*ipv6) && !ip_addr_isloopback(ipv6) && !ip_addr_isany(ipv6) && ((bool)ip_addr_islinklocal(ipv6) == is_local)) {
|
if (IP_IS_V6_VAL(*ipv6) && !ip_addr_isloopback(ipv6) && !ip_addr_isany(ipv6) && ((bool)ip_addr_islinklocal(ipv6) == is_local)) {
|
||||||
return IPAddress(ipv6).toString();
|
if (ip != nullptr) { *ip = *ipv6; }
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return String();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns only IPv6 global address (no loopback and no link-local)
|
|
||||||
String WifiGetIPv6(void)
|
|
||||||
{
|
|
||||||
return WifiFindIPv6(false, "st");
|
|
||||||
}
|
|
||||||
|
|
||||||
String WifiGetIPv6LinkLocal(void)
|
|
||||||
{
|
|
||||||
return WifiFindIPv6(true, "st");
|
|
||||||
}
|
|
||||||
|
|
||||||
// add an IPv6 link-local address to all netif
|
// add an IPv6 link-local address to all netif
|
||||||
void CreateLinkLocalIPv6(void)
|
void CreateLinkLocalIPv6(void)
|
||||||
{
|
{
|
||||||
|
@ -499,6 +573,81 @@ void CreateLinkLocalIPv6(void)
|
||||||
#endif // ESP32
|
#endif // ESP32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns only IPv6 global address (no loopback and no link-local)
|
||||||
|
bool WifiGetIPv6(IPAddress *ip)
|
||||||
|
{
|
||||||
|
return WifiFindIPv6(ip, false, "st");
|
||||||
|
}
|
||||||
|
bool WifiHasIPv6(void)
|
||||||
|
{
|
||||||
|
return WifiGetIPv6(nullptr);
|
||||||
|
}
|
||||||
|
String WifiGetIPv6Str(void)
|
||||||
|
{
|
||||||
|
IPAddress ip;
|
||||||
|
return WifiGetIPv6(&ip) ? ip.toString() : String();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WifiGetIPv6LinkLocal(IPAddress *ip)
|
||||||
|
{
|
||||||
|
return WifiFindIPv6(ip, true, "st");
|
||||||
|
}
|
||||||
|
String WifiGetIPv6LinkLocalStr(void)
|
||||||
|
{
|
||||||
|
IPAddress ip;
|
||||||
|
return WifiGetIPv6LinkLocal(&ip) ? ip.toString() : String();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns only IPv6 global address (no loopback and no link-local)
|
||||||
|
bool EthernetGetIPv6(IPAddress *ip)
|
||||||
|
{
|
||||||
|
return WifiFindIPv6(ip, false, "en");
|
||||||
|
}
|
||||||
|
bool EthernetHasIPv6(void)
|
||||||
|
{
|
||||||
|
return EthernetGetIPv6(nullptr);
|
||||||
|
}
|
||||||
|
String EthernetGetIPv6Str(void)
|
||||||
|
{
|
||||||
|
IPAddress ip;
|
||||||
|
return EthernetGetIPv6(&ip) ? ip.toString() : String();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EthernetGetIPv6LinkLocal(IPAddress *ip)
|
||||||
|
{
|
||||||
|
return WifiFindIPv6(ip, true, "en");
|
||||||
|
}
|
||||||
|
bool EthernetHasIPv6LinkLocal(void)
|
||||||
|
{
|
||||||
|
return EthernetGetIPv6LinkLocal(nullptr);
|
||||||
|
}
|
||||||
|
String EthernetGetIPv6LinkLocalStr(void)
|
||||||
|
{
|
||||||
|
IPAddress ip;
|
||||||
|
return EthernetGetIPv6LinkLocal(&ip) ? ip.toString() : String();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DNSGetIP(IPAddress *ip, uint32_t idx)
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
WiFi.scrubDNS(); // internal calls to reconnect can zero the DNS servers, restore the previous values
|
||||||
|
#endif
|
||||||
|
const ip_addr_t *ip_dns = dns_getserver(idx);
|
||||||
|
if (!ip_addr_isany(ip_dns)) {
|
||||||
|
if (ip != nullptr) { *ip = *ip_dns; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*ip = *IP4_ADDR_ANY;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String DNSGetIPStr(uint32_t idx)
|
||||||
|
{
|
||||||
|
IPAddress ip;
|
||||||
|
return DNSGetIP(&ip, idx) ? ip.toString() : String(F("0.0.0.0"));
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
#include "lwip/dns.h"
|
#include "lwip/dns.h"
|
||||||
void WifiDumpAddressesIPv6(void)
|
void WifiDumpAddressesIPv6(void)
|
||||||
|
@ -507,31 +656,144 @@ void WifiDumpAddressesIPv6(void)
|
||||||
if (!ip_addr_isany_val(intf->ip_addr)) AddLog(LOG_LEVEL_DEBUG, "WIF: '%c%c' IPv4 %s", intf->name[0], intf->name[1], IPAddress(intf->ip_addr).toString().c_str());
|
if (!ip_addr_isany_val(intf->ip_addr)) AddLog(LOG_LEVEL_DEBUG, "WIF: '%c%c' IPv4 %s", intf->name[0], intf->name[1], IPAddress(intf->ip_addr).toString().c_str());
|
||||||
for (uint32_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
for (uint32_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
|
||||||
if (!ip_addr_isany_val(intf->ip6_addr[i]))
|
if (!ip_addr_isany_val(intf->ip6_addr[i]))
|
||||||
AddLog(LOG_LEVEL_DEBUG, "WIF: '%c%c' IPv6 %s %s", intf->name[0], intf->name[1],
|
AddLog(LOG_LEVEL_DEBUG, "IP : '%c%c' IPv6 %s %s", intf->name[0], intf->name[1],
|
||||||
IPAddress(intf->ip6_addr[i]).toString().c_str(),
|
IPAddress(intf->ip6_addr[i]).toString().c_str(),
|
||||||
ip_addr_islinklocal(&intf->ip6_addr[i]) ? "local" : "");
|
ip_addr_islinklocal(&intf->ip6_addr[i]) ? "local" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AddLog(LOG_LEVEL_DEBUG, "WIF: DNS(0): %s", IPAddress(dns_getserver(0)).toString().c_str());
|
AddLog(LOG_LEVEL_DEBUG, "IP : DNS: %s %s", IPAddress(dns_getserver(0)).toString().c_str(), IPAddress(dns_getserver(1)).toString().c_str());
|
||||||
AddLog(LOG_LEVEL_DEBUG, "WIF: DNS(1): %s", IPAddress(dns_getserver(1)).toString().c_str());
|
AddLog(LOG_LEVEL_DEBUG, "WIF: v4IP: %_I v6IP: %s mainIP: %s", (uint32_t) WiFi.localIP(), WifiGetIPv6Str().c_str(), WifiGetIPStr().c_str());
|
||||||
|
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, "ETH: v4IP %_I v6IP: %s mainIP: %s", (uint32_t) EthernetLocalIP(), EthernetGetIPv6Str().c_str(), EthernetGetIPStr().c_str());
|
||||||
|
#endif
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, "IP : ListeningIP %s", IPGetListeningAddressStr().c_str());
|
||||||
}
|
}
|
||||||
#endif // USE_IPV6
|
#endif // USE_IPV6
|
||||||
|
|
||||||
// Check to see if we have any routable IP address
|
// Returns the IP address on which we listen (used for Web UI mainly)
|
||||||
bool WifiHasIP(void) {
|
//
|
||||||
|
// If IPv4 is set, it is preferred.
|
||||||
|
// If only IPv6, return the routable global address
|
||||||
|
bool IPGetListeningAddress(IPAddress * ip)
|
||||||
|
{
|
||||||
|
if (ip == nullptr) return HasIP(); // no value added for this method if no parameter
|
||||||
|
|
||||||
#ifdef USE_IPV6
|
#ifdef USE_IPV6
|
||||||
#ifdef ESP32
|
// collect both Wifi and Eth IPs and choose an IPv4 if any (Eth has priority)
|
||||||
return !WiFi.localIP().isAny();
|
IPAddress ip_wifi;
|
||||||
#else // ESP32
|
bool has_wifi = WifiGetIP(&ip_wifi);
|
||||||
const ip_addr_t &ipaddr = (ip_addr_t)WiFi.localIP();
|
|
||||||
return !ip_addr_isany_val(ipaddr);
|
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)
|
||||||
#endif // ESP32
|
IPAddress ip_eth;
|
||||||
|
bool has_eth = EthernetGetIP(&ip_eth);
|
||||||
|
if (has_wifi && has_eth) {
|
||||||
|
if (ip_eth.isV4()) { *ip = ip_eth; return true; }
|
||||||
|
if (ip_wifi.isV4()) { *ip = ip_wifi; return true; }
|
||||||
|
// both addresses are v6, return ETH
|
||||||
|
*ip = ip_eth;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// from here only wifi or eth may be valid
|
||||||
|
if (has_eth) { *ip = ip_eth; return true; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (has_wifi) { *ip = ip_wifi; return true; }
|
||||||
|
|
||||||
|
*ip = IPAddress();
|
||||||
|
return false;
|
||||||
|
#else // USE_IPV6
|
||||||
|
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)
|
||||||
|
if (EthernetGetIP(ip)) { return true; }
|
||||||
|
#endif
|
||||||
|
if (WifiGetIP(ip)) { return true; }
|
||||||
|
*ip = IPAddress();
|
||||||
|
return false;
|
||||||
|
#endif // USE_IPV6
|
||||||
|
}
|
||||||
|
|
||||||
|
String IPGetListeningAddressStr(void)
|
||||||
|
{
|
||||||
|
IPAddress ip;
|
||||||
|
if (IPGetListeningAddress(&ip)) {
|
||||||
|
return ip.toString();
|
||||||
|
} else {
|
||||||
|
return String();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because of IPv6, we can't test an IP address agains (uint32_t)0L anymore
|
||||||
|
// This test would work only for IPv4 assigned addresses.
|
||||||
|
// We must now use the following instead
|
||||||
|
inline bool IPIsValid(const IPAddress & ip)
|
||||||
|
{
|
||||||
|
#ifdef USE_IPV6
|
||||||
|
return !ip_addr_isany_val((const ip_addr_t &)ip);
|
||||||
|
#else
|
||||||
|
return static_cast<uint32_t>(ip) != 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because of IPv6, URL encoding of IP address needs to be adapted
|
||||||
|
// IPv4: address is "x.x.x.x"
|
||||||
|
// IPv6: address is enclosed in brackets "[x.x::x.x...]"
|
||||||
|
String IPForUrl(const IPAddress & ip)
|
||||||
|
{
|
||||||
|
#ifdef USE_IPV6
|
||||||
|
if (ip.isV4()) {
|
||||||
|
return ip.toString().c_str();
|
||||||
|
} else {
|
||||||
|
String s('[');
|
||||||
|
s += ip.toString().c_str();
|
||||||
|
s += ']';
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return ip.toString().c_str();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to see if we have any routable IP address
|
||||||
|
// IPv4 has always priority
|
||||||
|
// Copy the value of the IP if pointer provided (optional)
|
||||||
|
bool WifiGetIP(IPAddress *ip) {
|
||||||
|
#ifdef USE_IPV6
|
||||||
|
if ((uint32_t)WiFi.localIP() != 0) {
|
||||||
|
if (ip != nullptr) { *ip = WiFi.localIP(); }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
IPAddress lip;
|
||||||
|
if (WifiGetIPv6(&lip)) {
|
||||||
|
if (ip != nullptr) { *ip = lip; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (ip != nullptr) { *ip = IPAddress(); }
|
||||||
|
return false;
|
||||||
#else
|
#else
|
||||||
// IPv4 only
|
// IPv4 only
|
||||||
|
if (ip != nullptr) { *ip = WiFi.localIP(); }
|
||||||
return (uint32_t)WiFi.localIP() != 0;
|
return (uint32_t)WiFi.localIP() != 0;
|
||||||
#endif // USE_IPV6
|
#endif // USE_IPV6
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WifiHasIP(void) {
|
||||||
|
return WifiGetIP(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
String WifiGetIPStr(void)
|
||||||
|
{
|
||||||
|
IPAddress ip;
|
||||||
|
return WifiGetIP(&ip) ? ip.toString() : String();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has a routable IP, whether IPv4 or IPv6, Wifi or Ethernet
|
||||||
|
bool HasIP(void) {
|
||||||
|
if (WifiHasIP()) return true;
|
||||||
|
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)
|
||||||
|
if (EthernetHasIP()) return true;
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void WifiCheckIp(void) {
|
void WifiCheckIp(void) {
|
||||||
#ifdef USE_IPV6
|
#ifdef USE_IPV6
|
||||||
if (WL_CONNECTED == WiFi.status()) {
|
if (WL_CONNECTED == WiFi.status()) {
|
||||||
|
@ -904,20 +1166,14 @@ bool WifiDNSGetIPv6Priority(void) {
|
||||||
// Any change in logic needs to clear the DNS cache
|
// Any change in logic needs to clear the DNS cache
|
||||||
static bool had_v6prio = false;
|
static bool had_v6prio = false;
|
||||||
|
|
||||||
const ip_addr_t &local_ip = (ip_addr_t)WiFi.localIP();
|
bool has_v4 = WifiHasIPv4() || EthernetHasIPv4();
|
||||||
bool has_v4 = !ip_addr_isany_val(local_ip) && IP_IS_V4_VAL(local_ip);
|
bool has_v6 = WifiHasIPv6() || EthernetHasIPv6();
|
||||||
bool has_v6 = WifiGetIPv6().length() != 0;
|
|
||||||
#ifdef USE_ETHERNET
|
|
||||||
const ip_addr_t &local_ip_eth = (ip_addr_t)EthernetLocalIP();
|
|
||||||
has_v4 = has_v4 || (!ip_addr_isany_val(local_ip_eth) && IP_IS_V4_VAL(local_ip_eth));
|
|
||||||
has_v6 = has_v6 || EthernetGetIPv6().length() != 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool v6prio = Settings->flag6.dns_ipv6_priority;
|
bool v6prio = Settings->flag6.dns_ipv6_priority;
|
||||||
// AddLog(LOG_LEVEL_DEBUG, "WIF: v6 priority was %i, now is %i, has_v4=%i has_v6=%i", had_v6prio, v6prio, has_v4, has_v6);
|
|
||||||
|
|
||||||
if (has_v4 && !has_v6 && v6prio) {
|
if (has_v4 && !has_v6) {
|
||||||
v6prio = false; // revert to IPv4 first
|
v6prio = false; // revert to IPv4 first
|
||||||
|
} else if (has_v6 && !has_v4) {
|
||||||
|
v6prio = true; // only IPv6 is available
|
||||||
}
|
}
|
||||||
|
|
||||||
// any change of state requires a dns cache clear
|
// any change of state requires a dns cache clear
|
||||||
|
@ -1107,7 +1363,6 @@ void WifiEvents(arduino_event_t *event) {
|
||||||
|
|
||||||
#ifdef USE_IPV6
|
#ifdef USE_IPV6
|
||||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
|
||||||
case ARDUINO_EVENT_ETH_GOT_IP6:
|
|
||||||
{
|
{
|
||||||
ip_addr_t ip_addr6;
|
ip_addr_t ip_addr6;
|
||||||
ip_addr_copy_from_ip6(ip_addr6, event->event_info.got_ip6.ip6_info.ip);
|
ip_addr_copy_from_ip6(ip_addr6, event->event_info.got_ip6.ip6_info.ip);
|
||||||
|
@ -1115,21 +1370,17 @@ void WifiEvents(arduino_event_t *event) {
|
||||||
AddLog(LOG_LEVEL_DEBUG, PSTR("%s: IPv6 %s %s"),
|
AddLog(LOG_LEVEL_DEBUG, PSTR("%s: IPv6 %s %s"),
|
||||||
event->event_id == ARDUINO_EVENT_ETH_GOT_IP6 ? "ETH" : "WIF",
|
event->event_id == ARDUINO_EVENT_ETH_GOT_IP6 ? "ETH" : "WIF",
|
||||||
addr.isLocal() ? PSTR("Local") : PSTR("Global"), addr.toString().c_str());
|
addr.isLocal() ? PSTR("Local") : PSTR("Global"), addr.toString().c_str());
|
||||||
WiFi.saveDNS(); // internal calls to reconnect can zero the DNS servers, save DNS for future use
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif // USE_IPV6
|
#endif // USE_IPV6
|
||||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||||
case ARDUINO_EVENT_ETH_GOT_IP:
|
|
||||||
{
|
{
|
||||||
ip_addr_t ip_addr4;
|
ip_addr_t ip_addr4;
|
||||||
ip_addr_copy_from_ip4(ip_addr4, event->event_info.got_ip.ip_info.ip);
|
ip_addr_copy_from_ip4(ip_addr4, event->event_info.got_ip.ip_info.ip);
|
||||||
AddLog(LOG_LEVEL_DEBUG, PSTR("%s: IPv4 %_I, mask %_I, gateway %_I"),
|
AddLog(LOG_LEVEL_DEBUG, PSTR("WIF: IPv4 %_I, mask %_I, gateway %_I"),
|
||||||
event->event_id == ARDUINO_EVENT_ETH_GOT_IP ? "ETH" : "WIF",
|
|
||||||
event->event_info.got_ip.ip_info.ip.addr,
|
event->event_info.got_ip.ip_info.ip.addr,
|
||||||
event->event_info.got_ip.ip_info.netmask.addr,
|
event->event_info.got_ip.ip_info.netmask.addr,
|
||||||
event->event_info.got_ip.ip_info.gw.addr);
|
event->event_info.got_ip.ip_info.gw.addr);
|
||||||
WiFi.saveDNS(); // internal calls to reconnect can zero the DNS servers, save DNS for future use
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1139,12 +1390,12 @@ void WifiEvents(arduino_event_t *event) {
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||||
case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE:
|
case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE:
|
||||||
WiFi.restoreDNS(); // internal calls to reconnect can zero the DNS servers, restore the previous values
|
|
||||||
Wifi.ipv6_local_link_called = false;
|
Wifi.ipv6_local_link_called = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
WiFi.scrubDNS(); // internal calls to reconnect can zero the DNS servers, restore the previous values
|
||||||
}
|
}
|
||||||
#endif // ESP32
|
#endif // ESP32
|
||||||
|
|
|
@ -570,7 +570,8 @@ void WebServer_on(const char * prefix, void (*func)(void), uint8_t method = HTTP
|
||||||
#endif // ESP32
|
#endif // ESP32
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartWebserver(int type, IPAddress ipweb)
|
// Always listens to all interfaces, so we don't need an IP address anymore
|
||||||
|
void StartWebserver(int type)
|
||||||
{
|
{
|
||||||
if (!Settings->web_refresh) { Settings->web_refresh = HTTP_REFRESH_TIME; }
|
if (!Settings->web_refresh) { Settings->web_refresh = HTTP_REFRESH_TIME; }
|
||||||
if (!Web.state) {
|
if (!Web.state) {
|
||||||
|
@ -610,19 +611,8 @@ void StartWebserver(int type, IPAddress ipweb)
|
||||||
Webserver->begin(); // Web server start
|
Webserver->begin(); // Web server start
|
||||||
}
|
}
|
||||||
if (Web.state != type) {
|
if (Web.state != type) {
|
||||||
#ifdef USE_IPV6
|
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"),
|
||||||
String ipv6_addr = WifiGetIPv6();
|
NetworkHostname(), (Mdns.begun) ? PSTR(".local") : "", IPGetListeningAddressStr().c_str());
|
||||||
if (ipv6_addr!="") {
|
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %_I and IPv6 global address %s "),
|
|
||||||
NetworkHostname(), (Mdns.begun) ? PSTR(".local") : "", (uint32_t)ipweb, ipv6_addr.c_str());
|
|
||||||
} else {
|
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %_I"),
|
|
||||||
NetworkHostname(), (Mdns.begun) ? PSTR(".local") : "", (uint32_t)ipweb);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %_I"),
|
|
||||||
NetworkHostname(), (Mdns.begun) ? PSTR(".local") : "", (uint32_t)ipweb);
|
|
||||||
#endif // USE_IPV6
|
|
||||||
TasmotaGlobal.rules_flag.http_init = 1;
|
TasmotaGlobal.rules_flag.http_init = 1;
|
||||||
Web.state = type;
|
Web.state = type;
|
||||||
}
|
}
|
||||||
|
@ -663,7 +653,7 @@ void WifiManagerBegin(bool reset_only)
|
||||||
DnsServer->setErrorReplyCode(DNSReplyCode::NoError);
|
DnsServer->setErrorReplyCode(DNSReplyCode::NoError);
|
||||||
DnsServer->start(DNS_PORT, "*", WiFi.softAPIP());
|
DnsServer->start(DNS_PORT, "*", WiFi.softAPIP());
|
||||||
|
|
||||||
StartWebserver((reset_only ? HTTP_MANAGER_RESET_ONLY : HTTP_MANAGER), WiFi.softAPIP());
|
StartWebserver((reset_only ? HTTP_MANAGER_RESET_ONLY : HTTP_MANAGER));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PollDnsWebserver(void)
|
void PollDnsWebserver(void)
|
||||||
|
@ -700,12 +690,14 @@ bool HttpCheckPriviledgedAccess(bool autorequestauth = true)
|
||||||
referer.toUpperCase();
|
referer.toUpperCase();
|
||||||
String hostname = TasmotaGlobal.hostname;
|
String hostname = TasmotaGlobal.hostname;
|
||||||
hostname.toUpperCase();
|
hostname.toUpperCase();
|
||||||
|
// TODO rework if IPv6
|
||||||
if ((referer.indexOf(hostname) == 7) || (referer.indexOf(WiFi.localIP().toString()) == 7)) {
|
if ((referer.indexOf(hostname) == 7) || (referer.indexOf(WiFi.localIP().toString()) == 7)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)
|
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)
|
||||||
hostname = EthernetHostname();
|
hostname = EthernetHostname();
|
||||||
hostname.toUpperCase();
|
hostname.toUpperCase();
|
||||||
|
// TODO rework if IPv6
|
||||||
if ((referer.indexOf(hostname) == 7) || (referer.indexOf(EthernetLocalIP().toString()) == 7)) {
|
if ((referer.indexOf(hostname) == 7) || (referer.indexOf(EthernetLocalIP().toString()) == 7)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -898,7 +890,7 @@ void WSContentSendStyle_P(const char* formatP, ...) {
|
||||||
#else
|
#else
|
||||||
if ( Settings->flag3.gui_hostname_ip || ( (WiFi.getMode() == WIFI_AP_STA) && (!Web.initial_config) ) ) {
|
if ( Settings->flag3.gui_hostname_ip || ( (WiFi.getMode() == WIFI_AP_STA) && (!Web.initial_config) ) ) {
|
||||||
#endif
|
#endif
|
||||||
bool lip = (static_cast<uint32_t>(WiFi.localIP()) != 0);
|
bool lip = WifiHasIP();
|
||||||
bool sip = (static_cast<uint32_t>(WiFi.softAPIP()) != 0);
|
bool sip = (static_cast<uint32_t>(WiFi.softAPIP()) != 0);
|
||||||
bool eip = false;
|
bool eip = false;
|
||||||
if (lip || sip) {
|
if (lip || sip) {
|
||||||
|
@ -910,7 +902,7 @@ void WSContentSendStyle_P(const char* formatP, ...) {
|
||||||
(sip) ? WiFi.softAPIP().toString().c_str() : "");
|
(sip) ? WiFi.softAPIP().toString().c_str() : "");
|
||||||
}
|
}
|
||||||
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)
|
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)
|
||||||
eip = (static_cast<uint32_t>(EthernetLocalIP()) != 0);
|
eip = EthernetHasIP();
|
||||||
if (eip) {
|
if (eip) {
|
||||||
WSContentSend_P(PSTR("%s%s%s (%s)"), // tasmota-eth.local (192.168.2.13)
|
WSContentSend_P(PSTR("%s%s%s (%s)"), // tasmota-eth.local (192.168.2.13)
|
||||||
(lip || sip) ? PSTR("</br>") : PSTR("<h4>"),
|
(lip || sip) ? PSTR("</br>") : PSTR("<h4>"),
|
||||||
|
@ -1015,8 +1007,8 @@ void WebRestart(uint32_t type) {
|
||||||
#if ((RESTART_AFTER_INITIAL_WIFI_CONFIG) && (AFTER_INITIAL_WIFI_CONFIG_GO_TO_NEW_IP))
|
#if ((RESTART_AFTER_INITIAL_WIFI_CONFIG) && (AFTER_INITIAL_WIFI_CONFIG_GO_TO_NEW_IP))
|
||||||
// In case of type 3 (New network has been configured) go to the new device's IP in the new Network
|
// In case of type 3 (New network has been configured) go to the new device's IP in the new Network
|
||||||
if (3 == type) {
|
if (3 == type) {
|
||||||
WSContentSend_P("setTimeout(function(){location.href='http://%_I';},%d);",
|
WSContentSend_P("setTimeout(function(){location.href='http://%s';},%d);",
|
||||||
(uint32_t)WiFi.localIP(),
|
IPForUrl(WiFi.localIP()).c_str(),
|
||||||
HTTP_RESTART_RECONNECT_TIME
|
HTTP_RESTART_RECONNECT_TIME
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2360,11 +2352,11 @@ void HandleInformation(void)
|
||||||
WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm) 11%c"), Settings->sta_active +1, HtmlEscape(SettingsText(SET_STASSID1 + Settings->sta_active)).c_str(), WifiGetRssiAsQuality(rssi), rssi, pgm_read_byte(&kWifiPhyMode[WiFi.getPhyMode() & 0x3]) );
|
WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm) 11%c"), Settings->sta_active +1, HtmlEscape(SettingsText(SET_STASSID1 + Settings->sta_active)).c_str(), WifiGetRssiAsQuality(rssi), rssi, pgm_read_byte(&kWifiPhyMode[WiFi.getPhyMode() & 0x3]) );
|
||||||
WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), TasmotaGlobal.hostname, (Mdns.begun) ? PSTR(".local") : "");
|
WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), TasmotaGlobal.hostname, (Mdns.begun) ? PSTR(".local") : "");
|
||||||
#ifdef USE_IPV6
|
#ifdef USE_IPV6
|
||||||
String ipv6_addr = WifiGetIPv6();
|
String ipv6_addr = WifiGetIPv6Str();
|
||||||
if (ipv6_addr != "") {
|
if (ipv6_addr != "") {
|
||||||
WSContentSend_P(PSTR("}1 IPv6 Global (wifi)}2%s"), ipv6_addr.c_str());
|
WSContentSend_P(PSTR("}1 IPv6 Global (wifi)}2%s"), ipv6_addr.c_str());
|
||||||
}
|
}
|
||||||
ipv6_addr = WifiGetIPv6LinkLocal();
|
ipv6_addr = WifiGetIPv6LinkLocalStr();
|
||||||
if (ipv6_addr != "") {
|
if (ipv6_addr != "") {
|
||||||
WSContentSend_P(PSTR("}1 IPv6 Local (wifi)}2%s"), ipv6_addr.c_str());
|
WSContentSend_P(PSTR("}1 IPv6 Local (wifi)}2%s"), ipv6_addr.c_str());
|
||||||
}
|
}
|
||||||
|
@ -2378,21 +2370,26 @@ void HandleInformation(void)
|
||||||
if (!TasmotaGlobal.global_state.wifi_down) {
|
if (!TasmotaGlobal.global_state.wifi_down) {
|
||||||
WSContentSend_P(PSTR("}1" D_GATEWAY "}2%_I"), Settings->ipv4_address[1]);
|
WSContentSend_P(PSTR("}1" D_GATEWAY "}2%_I"), Settings->ipv4_address[1]);
|
||||||
WSContentSend_P(PSTR("}1" D_SUBNET_MASK "}2%_I"), Settings->ipv4_address[2]);
|
WSContentSend_P(PSTR("}1" D_SUBNET_MASK "}2%_I"), Settings->ipv4_address[2]);
|
||||||
|
#ifdef USE_IPV6
|
||||||
|
WSContentSend_P(PSTR("}1" D_DNS_SERVER "1}2%s"), DNSGetIPStr(0).c_str());
|
||||||
|
WSContentSend_P(PSTR("}1" D_DNS_SERVER "2}2%s"), DNSGetIPStr(1).c_str());
|
||||||
|
#else // USE_IPV6
|
||||||
WSContentSend_P(PSTR("}1" D_DNS_SERVER "1}2%_I"), Settings->ipv4_address[3]);
|
WSContentSend_P(PSTR("}1" D_DNS_SERVER "1}2%_I"), Settings->ipv4_address[3]);
|
||||||
WSContentSend_P(PSTR("}1" D_DNS_SERVER "2}2%_I"), Settings->ipv4_address[4]);
|
WSContentSend_P(PSTR("}1" D_DNS_SERVER "2}2%_I"), Settings->ipv4_address[4]);
|
||||||
|
#endif // USE_IPV6
|
||||||
}
|
}
|
||||||
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)
|
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)
|
||||||
if (static_cast<uint32_t>(EthernetLocalIP()) != 0) {
|
if (EthernetHasIP()) {
|
||||||
if (show_hr) {
|
if (show_hr) {
|
||||||
WSContentSend_P(PSTR("}1<hr/>}2<hr/>"));
|
WSContentSend_P(PSTR("}1<hr/>}2<hr/>"));
|
||||||
}
|
}
|
||||||
WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), EthernetHostname(), (Mdns.begun) ? PSTR(".local") : "");
|
WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), EthernetHostname(), (Mdns.begun) ? PSTR(".local") : "");
|
||||||
#ifdef USE_IPV6
|
#ifdef USE_IPV6
|
||||||
String ipv6_eth_addr = EthernetGetIPv6();
|
String ipv6_eth_addr = EthernetGetIPv6Str();
|
||||||
if (ipv6_eth_addr != "") {
|
if (ipv6_eth_addr != "") {
|
||||||
WSContentSend_P(PSTR("}1 IPv6 Global (eth)}2%s"), ipv6_eth_addr.c_str());
|
WSContentSend_P(PSTR("}1 IPv6 Global (eth)}2%s"), ipv6_eth_addr.c_str());
|
||||||
}
|
}
|
||||||
ipv6_eth_addr = EthernetGetIPv6LinkLocal();
|
ipv6_eth_addr = EthernetGetIPv6LinkLocalStr();
|
||||||
if (ipv6_eth_addr != "") {
|
if (ipv6_eth_addr != "") {
|
||||||
WSContentSend_P(PSTR("}1 IPv6 Local (eth)}2%s"), ipv6_eth_addr.c_str());
|
WSContentSend_P(PSTR("}1 IPv6 Local (eth)}2%s"), ipv6_eth_addr.c_str());
|
||||||
}
|
}
|
||||||
|
@ -2403,8 +2400,13 @@ void HandleInformation(void)
|
||||||
if (!TasmotaGlobal.global_state.eth_down) {
|
if (!TasmotaGlobal.global_state.eth_down) {
|
||||||
WSContentSend_P(PSTR("}1" D_GATEWAY "}2%_I"), Settings->eth_ipv4_address[1]);
|
WSContentSend_P(PSTR("}1" D_GATEWAY "}2%_I"), Settings->eth_ipv4_address[1]);
|
||||||
WSContentSend_P(PSTR("}1" D_SUBNET_MASK "}2%_I"), Settings->eth_ipv4_address[2]);
|
WSContentSend_P(PSTR("}1" D_SUBNET_MASK "}2%_I"), Settings->eth_ipv4_address[2]);
|
||||||
|
#ifdef USE_IPV6
|
||||||
|
WSContentSend_P(PSTR("}1" D_DNS_SERVER "1}2%s"), DNSGetIPStr(0).c_str());
|
||||||
|
WSContentSend_P(PSTR("}1" D_DNS_SERVER "2}2%s"), DNSGetIPStr(1).c_str());
|
||||||
|
#else // USE_IPV6
|
||||||
WSContentSend_P(PSTR("}1" D_DNS_SERVER "1}2%_I"), Settings->eth_ipv4_address[3]);
|
WSContentSend_P(PSTR("}1" D_DNS_SERVER "1}2%_I"), Settings->eth_ipv4_address[3]);
|
||||||
WSContentSend_P(PSTR("}1" D_DNS_SERVER "2}2%_I"), Settings->eth_ipv4_address[4]);
|
WSContentSend_P(PSTR("}1" D_DNS_SERVER "2}2%_I"), Settings->eth_ipv4_address[4]);
|
||||||
|
#endif // USE_IPV6
|
||||||
}
|
}
|
||||||
#endif // USE_ETHERNET
|
#endif // USE_ETHERNET
|
||||||
WSContentSend_P(PSTR("}1}2 ")); // Empty line
|
WSContentSend_P(PSTR("}1}2 ")); // Empty line
|
||||||
|
@ -3724,7 +3726,7 @@ bool Xdrv01(uint32_t function)
|
||||||
Wifi.wifi_test_AP_TIMEOUT = false;
|
Wifi.wifi_test_AP_TIMEOUT = false;
|
||||||
Wifi.wifi_test_counter = 0;
|
Wifi.wifi_test_counter = 0;
|
||||||
Wifi.wifiTest = WIFI_TEST_FINISHED;
|
Wifi.wifiTest = WIFI_TEST_FINISHED;
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_SSID " %s: " D_CONNECTED " - " D_IP_ADDRESS " %_I"), SettingsText(Wifi.wifi_Test_Save_SSID2 ? SET_STASSID2 : SET_STASSID1), (uint32_t)WiFi.localIP());
|
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_SSID " %s: " D_CONNECTED " - " D_IP_ADDRESS " %s"), SettingsText(Wifi.wifi_Test_Save_SSID2 ? SET_STASSID2 : SET_STASSID1), WiFi.localIP().toString().c_str());
|
||||||
// TasmotaGlobal.blinks = 255; // Signal wifi connection with blinks
|
// TasmotaGlobal.blinks = 255; // Signal wifi connection with blinks
|
||||||
if (MAX_WIFI_OPTION != Wifi.old_wificonfig) {
|
if (MAX_WIFI_OPTION != Wifi.old_wificonfig) {
|
||||||
TasmotaGlobal.wifi_state_flag = Settings->sta_config = Wifi.old_wificonfig;
|
TasmotaGlobal.wifi_state_flag = Settings->sta_config = Wifi.old_wificonfig;
|
||||||
|
|
|
@ -972,8 +972,8 @@ void MqttConnected(void) {
|
||||||
ResponseAppend_P(PSTR(",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%_I\""),
|
ResponseAppend_P(PSTR(",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%_I\""),
|
||||||
TasmotaGlobal.hostname, (uint32_t)WiFi.localIP());
|
TasmotaGlobal.hostname, (uint32_t)WiFi.localIP());
|
||||||
#ifdef USE_IPV6
|
#ifdef USE_IPV6
|
||||||
ResponseAppend_P(PSTR(",\"" D_JSON_IP6_GLOBAL "\":\"%s\""), WifiGetIPv6().c_str());
|
ResponseAppend_P(PSTR(",\"" D_JSON_IP6_GLOBAL "\":\"%s\""), WifiGetIPv6Str().c_str());
|
||||||
ResponseAppend_P(PSTR(",\"" D_JSON_IP6_LOCAL "\":\"%s\""), WifiGetIPv6LinkLocal().c_str());
|
ResponseAppend_P(PSTR(",\"" D_JSON_IP6_LOCAL "\":\"%s\""), WifiGetIPv6LinkLocalStr().c_str());
|
||||||
#endif // USE_IPV6
|
#endif // USE_IPV6
|
||||||
}
|
}
|
||||||
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)
|
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32 && defined(USE_ETHERNET)
|
||||||
|
|
|
@ -215,12 +215,12 @@ extern "C" {
|
||||||
int32_t rssi = WiFi.RSSI();
|
int32_t rssi = WiFi.RSSI();
|
||||||
bool show_rssi = false;
|
bool show_rssi = false;
|
||||||
#ifdef USE_IPV6
|
#ifdef USE_IPV6
|
||||||
String ipv6_addr = WifiGetIPv6();
|
String ipv6_addr = WifiGetIPv6Str();
|
||||||
if (ipv6_addr != "") {
|
if (ipv6_addr != "") {
|
||||||
be_map_insert_str(vm, "ip6", ipv6_addr.c_str());
|
be_map_insert_str(vm, "ip6", ipv6_addr.c_str());
|
||||||
show_rssi = true;
|
show_rssi = true;
|
||||||
}
|
}
|
||||||
ipv6_addr = WifiGetIPv6LinkLocal();
|
ipv6_addr = WifiGetIPv6LinkLocalStr();
|
||||||
if (ipv6_addr != "") {
|
if (ipv6_addr != "") {
|
||||||
be_map_insert_str(vm, "ip6local", ipv6_addr.c_str());
|
be_map_insert_str(vm, "ip6local", ipv6_addr.c_str());
|
||||||
show_rssi = true;
|
show_rssi = true;
|
||||||
|
@ -255,11 +255,11 @@ extern "C" {
|
||||||
be_map_insert_str(vm, "ip", IPAddress((uint32_t)EthernetLocalIP()).toString().c_str()); // quick fix for IPAddress bug
|
be_map_insert_str(vm, "ip", IPAddress((uint32_t)EthernetLocalIP()).toString().c_str()); // quick fix for IPAddress bug
|
||||||
}
|
}
|
||||||
#ifdef USE_IPV6
|
#ifdef USE_IPV6
|
||||||
String ipv6_addr = EthernetGetIPv6();
|
String ipv6_addr = EthernetGetIPv6Str();
|
||||||
if (ipv6_addr != "") {
|
if (ipv6_addr != "") {
|
||||||
be_map_insert_str(vm, "ip6", ipv6_addr.c_str());
|
be_map_insert_str(vm, "ip6", ipv6_addr.c_str());
|
||||||
}
|
}
|
||||||
ipv6_addr = EthernetGetIPv6LinkLocal();
|
ipv6_addr = EthernetGetIPv6LinkLocalStr();
|
||||||
if (ipv6_addr != "") {
|
if (ipv6_addr != "") {
|
||||||
be_map_insert_str(vm, "ip6local", ipv6_addr.c_str());
|
be_map_insert_str(vm, "ip6local", ipv6_addr.c_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,9 +116,31 @@ void EthernetEvent(arduino_event_t *event) {
|
||||||
}
|
}
|
||||||
TasmotaGlobal.rules_flag.eth_connected = 1;
|
TasmotaGlobal.rules_flag.eth_connected = 1;
|
||||||
TasmotaGlobal.global_state.eth_down = 0;
|
TasmotaGlobal.global_state.eth_down = 0;
|
||||||
WiFi.saveDNS(); // internal calls to reconnect can zero the DNS servers, save DNS for future use
|
AddLog(LOG_LEVEL_DEBUG, PSTR("ETH: IPv4 %_I, mask %_I, gateway %_I"),
|
||||||
|
event->event_info.got_ip.ip_info.ip.addr,
|
||||||
|
event->event_info.got_ip.ip_info.netmask.addr,
|
||||||
|
event->event_info.got_ip.ip_info.gw.addr);
|
||||||
|
WiFi.scrubDNS(); // internal calls to reconnect can zero the DNS servers, save DNS for future use
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef USE_IPV6
|
||||||
|
case ARDUINO_EVENT_ETH_GOT_IP6:
|
||||||
|
{
|
||||||
|
ip_addr_t ip_addr6;
|
||||||
|
ip_addr_copy_from_ip6(ip_addr6, event->event_info.got_ip6.ip6_info.ip);
|
||||||
|
IPAddress addr(ip_addr6);
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("%s: IPv6 %s %s"),
|
||||||
|
event->event_id == ARDUINO_EVENT_ETH_GOT_IP6 ? "ETH" : "WIF",
|
||||||
|
addr.isLocal() ? PSTR("Local") : PSTR("Global"), addr.toString().c_str());
|
||||||
|
if (!addr.isLocal()) { // declare network up on IPv6
|
||||||
|
TasmotaGlobal.rules_flag.eth_connected = 1;
|
||||||
|
TasmotaGlobal.global_state.eth_down = 0;
|
||||||
|
}
|
||||||
|
WiFi.scrubDNS(); // internal calls to reconnect can zero the DNS servers, save DNS for future use
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif // USE_IPV6
|
||||||
|
|
||||||
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_ETH "Disconnected"));
|
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_ETH "Disconnected"));
|
||||||
TasmotaGlobal.rules_flag.eth_disconnected = 1;
|
TasmotaGlobal.rules_flag.eth_disconnected = 1;
|
||||||
|
@ -144,19 +166,6 @@ void EthernetSetIp(void) {
|
||||||
Settings->eth_ipv4_address[4]); // IPAddress dns2
|
Settings->eth_ipv4_address[4]); // IPAddress dns2
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_IPV6
|
|
||||||
// Returns only IPv6 global address (no loopback and no link-local)
|
|
||||||
String EthernetGetIPv6(void)
|
|
||||||
{
|
|
||||||
return WifiFindIPv6(false, "en");
|
|
||||||
}
|
|
||||||
|
|
||||||
String EthernetGetIPv6LinkLocal(void)
|
|
||||||
{
|
|
||||||
return WifiFindIPv6(true, "en");
|
|
||||||
}
|
|
||||||
#endif // USE_IPV6
|
|
||||||
|
|
||||||
void EthernetInit(void) {
|
void EthernetInit(void) {
|
||||||
if (!Settings->flag4.network_ethernet) { return; }
|
if (!Settings->flag4.network_ethernet) { return; }
|
||||||
if (!PinUsed(GPIO_ETH_PHY_MDC) && !PinUsed(GPIO_ETH_PHY_MDIO)) {
|
if (!PinUsed(GPIO_ETH_PHY_MDC) && !PinUsed(GPIO_ETH_PHY_MDIO)) {
|
||||||
|
@ -220,6 +229,40 @@ IPAddress EthernetLocalIP(void) {
|
||||||
return ETH.localIP();
|
return ETH.localIP();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check to see if we have any routable IP address
|
||||||
|
// IPv4 has always priority
|
||||||
|
// Copy the value of the IP if pointer provided (optional)
|
||||||
|
bool EthernetGetIP(IPAddress *ip) {
|
||||||
|
#ifdef USE_IPV6
|
||||||
|
if ((uint32_t)ETH.localIP() != 0) {
|
||||||
|
if (ip != nullptr) { *ip = ETH.localIP(); }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
IPAddress lip;
|
||||||
|
if (EthernetGetIPv6(&lip)) {
|
||||||
|
if (ip != nullptr) { *ip = lip; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*ip = IPAddress();
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
// IPv4 only
|
||||||
|
if (ip != nullptr) { *ip = ETH.localIP(); }
|
||||||
|
return (uint32_t)ETH.localIP() != 0;
|
||||||
|
#endif // USE_IPV6
|
||||||
|
}
|
||||||
|
bool EthernetHasIP(void) {
|
||||||
|
return EthernetGetIP(nullptr);
|
||||||
|
}
|
||||||
|
String EthernetGetIPStr(void) {
|
||||||
|
IPAddress ip;
|
||||||
|
if (EthernetGetIP(&ip)) {
|
||||||
|
return ip.toString();
|
||||||
|
} else {
|
||||||
|
return String();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char* EthernetHostname(void) {
|
char* EthernetHostname(void) {
|
||||||
return eth_hostname;
|
return eth_hostname;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue