Skip to content

Commit

Permalink
Matter auto-fix IPv6 link-local zone id when network reconnects (#21494)
Browse files Browse the repository at this point in the history
  • Loading branch information
s-hadinger authored May 25, 2024
1 parent 662b849 commit 25a2a46
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ All notable changes to this project will be documented in this file.
- Webradio crash with invalid url (#21446)
- Zigbee crash when removing `ZbName` (#21449)
- ESP32 BLE fix scanning (#21451)
- Matter auto-fix IPv6 link-local zone id when network reconnects

### Removed
- Support of old insecure fingerprint algorithm. Deprecated since v8.4.0 (#21417)
Expand Down
7 changes: 7 additions & 0 deletions lib/default/WiFiHelper/src/WiFiHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ class WiFiHelper {
// With ESP32 Core3, the WiFi mac address is not valid until the wifi is actually started
// this helper function always provide a valid mac address
static String macAddress(void);

// Auto-fix zone
//
// After a reconnect, the zone id may not be valid anymore
// In such case we detect any "%st<n>" or "%en<n>" zone identifier
// and replace with the current zone id
static void IPv6ZoneAutoFix(IPAddress &addr, const char* aHostname);
};


Expand Down
39 changes: 39 additions & 0 deletions lib/default/WiFiHelper/src/WiFiHelper_ESP32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,44 @@ static void wifi32_dns_found_callback(const char *name, const ip_addr_t *ipaddr,
// AddLog(LOG_LEVEL_DEBUG, "WIF: dns_found=%s", ipaddr ? IPAddress(*ipaddr).toString().c_str() : "<null>");
}

// Auto-fix zone
//
// After a reconnect, the zone id may not be valid anymore
// In such case we detect any "%st<n>" or "%en<n>" zone identifier
// and replace with the current zone id
extern bool WifiGetIPv6LinkLocal(IPAddress *ip);
extern bool EthernetGetIPv6LinkLocal(IPAddress *ip);
void WiFiHelper::IPv6ZoneAutoFix(IPAddress &addr, const char* aHostname) {
#ifdef USE_IPV6
if ((addr.type() == IPv6) && (addr.zone() == 0)) {
// check if hostname contains '%'
const char *zone_identifier = strchr(aHostname, '%');
if (zone_identifier != nullptr) {
uint8_t zone_id = 0;
// check if zone id is valid
if (strncmp(zone_identifier, "%st", 3) == 0) {
IPAddress wifi_link_local;
if (WifiGetIPv6LinkLocal(&wifi_link_local)) {
zone_id = wifi_link_local.zone();
}
} else if (strncmp(zone_identifier, "%en", 3) == 0) {
IPAddress eth_link_local;
if (EthernetGetIPv6LinkLocal(&eth_link_local)) {
zone_id = eth_link_local.zone();
}
}
if (zone_id) {
// convert to ip_addr_t which is currently the only way to change the zone_id
ip_addr_t ip_addr;
addr.to_ip_addr_t(&ip_addr);
ip_addr.u_addr.ip6.zone = zone_id;
addr = IPAddress(&ip_addr);
}
}
}
#endif
}

/**
* Resolve the given hostname to an IP address.
* @param aHostname Name to be resolved
Expand Down Expand Up @@ -281,6 +319,7 @@ int WiFiHelper::hostByName(const char* aHostname, IPAddress& aResult, int32_t ti
if (!ip_addr_isany_val(dns_ipaddr)) {
#ifdef USE_IPV6
aResult.from_ip_addr_t(&dns_ipaddr);
WiFiHelper::IPv6ZoneAutoFix(aResult, aHostname);
#else // USE_IPV6
aResult = ip_addr_get_ip4_u32(&dns_ipaddr);
#endif // USE_IPV6
Expand Down
2 changes: 2 additions & 0 deletions lib/default/WiFiHelper/src/WiFiHelper_ESP8266.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,6 @@ String WiFiHelper::macAddress(void) {
return WiFi.macAddress();
}

void WiFiHelper::IPv6ZoneAutoFix(IPAddress &addr, const char* aHostname) {
}
#endif // ESP8266
1 change: 1 addition & 0 deletions tasmota/tasmota_support/support_wifi.ino
Original file line number Diff line number Diff line change
Expand Up @@ -1278,6 +1278,7 @@ bool WifiHostByName(const char* aHostname, IPAddress& aResult) {
#if ESP_IDF_VERSION_MAJOR >= 5
// try converting directly to IP
if (aResult.fromString(aHostname)) {
WiFiHelper::IPv6ZoneAutoFix(aResult, aHostname);
return true; // we're done
}
#endif
Expand Down

0 comments on commit 25a2a46

Please sign in to comment.