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

This commit is contained in:
s-hadinger 2024-05-25 19:51:00 +02:00 committed by GitHub
parent 662b84947b
commit 25a2a46917
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 50 additions and 0 deletions

View File

@ -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)

View File

@ -83,6 +83,13 @@ public:
// 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);
};

View File

@ -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
@ -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

View File

@ -77,4 +77,6 @@ String WiFiHelper::macAddress(void) {
return WiFi.macAddress();
}
void WiFiHelper::IPv6ZoneAutoFix(IPAddress &addr, const char* aHostname) {
}
#endif // ESP8266

View File

@ -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