Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Matter auto-fix IPv6 link-local zone id when network reconnects #21494

Merged
merged 1 commit into from
May 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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