diff --git a/components/esp_netif/Kconfig b/components/esp_netif/Kconfig index 4511bbeaaf..7704a2959a 100644 --- a/components/esp_netif/Kconfig +++ b/components/esp_netif/Kconfig @@ -84,4 +84,15 @@ menu "ESP NETIF Adapter" help Enable LwIP IEEE 802.1D bridge support in ESP-NETIF. Note that "Number of clients store data in netif" (LWIP_NUM_NETIF_CLIENT_DATA) option needs to be properly configured to be LwIP bridge available! + + config ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF + bool "Enable DNS server per interface" + default n + select LWIP_DNS_SETSERVER_WITH_NETIF + help + Enable this option to use the DNS server which belongs to the selected default network interface. + This feature collects DNS server and netif information from LWIP core modules. + Whenever a new default netif is selected, global DNS servers in LWIP are updated with the netif + related servers. + endmenu diff --git a/components/esp_netif/include/esp_netif.h b/components/esp_netif/include/esp_netif.h index d8d9918ce4..fed84aa335 100644 --- a/components/esp_netif/include/esp_netif.h +++ b/components/esp_netif/include/esp_netif.h @@ -769,6 +769,11 @@ esp_err_t esp_netif_dhcps_get_clients_by_mac(esp_netif_t *esp_netif, int num, es * and is designed to be set via this API. * If DHCP client is disabled, all DNS server types can be set via this API only. * + * Note that LWIP stores DNS server information globally, not per interface, so the first parameter is unused + * in the default LWIP configuration. + * If CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF=1 this API sets internal DNS server information per + * netif. It's also possible set the global DNS server info by supplying esp_netif=NULL + * * If DHCP server is enabled, the Main DNS Server setting is used by the DHCP server to provide a DNS Server option * to DHCP clients (Wi-Fi stations). * - The default Main DNS server is typically the IP of the DHCP server itself. @@ -794,6 +799,11 @@ esp_err_t esp_netif_set_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t ty * This may be result of a previous call to esp_netif_set_dns_info(). If the interface's DHCP client is enabled, * the Main or Backup DNS Server may be set by the current DHCP lease. * + * Note that LWIP stores DNS server information globally, not per interface, so the first parameter is unused + * in the default LWIP configuration. + * If CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF=1 this API returns internally saved DNS server information per + * netif. It's also possible to ask for the global DNS server info by supplying esp_netif=NULL + * * @param[in] esp_netif Handle to esp-netif instance * @param[in] type Type of DNS Server to get: ESP_NETIF_DNS_MAIN, ESP_NETIF_DNS_BACKUP, ESP_NETIF_DNS_FALLBACK * @param[out] dns DNS Server result is written here on success diff --git a/components/esp_netif/lwip/esp_netif_lwip.c b/components/esp_netif/lwip/esp_netif_lwip.c index e0cd05c6f0..62edeb69ea 100644 --- a/components/esp_netif/lwip/esp_netif_lwip.c +++ b/components/esp_netif/lwip/esp_netif_lwip.c @@ -114,16 +114,6 @@ do { action; \ } while(0) -// -// Internal types -// -typedef enum esp_netif_action { - ESP_NETIF_UNDEF, - ESP_NETIF_STARTED, - ESP_NETIF_STOPPED, - ESP_NETIF_SET_DEFAULT, -} esp_netif_action_t; - // // Internal variables for this module // @@ -307,6 +297,11 @@ static void esp_netif_set_default_netif_internal(esp_netif_t *esp_netif) } else { netif_set_default(esp_netif->lwip_netif); } +#ifdef CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF + for (int i = 0; i < DNS_MAX_SERVERS; ++i) { + dns_setserver(i, &esp_netif->dns[i]); + } +#endif } /** @@ -317,7 +312,7 @@ static void esp_netif_set_default_netif_internal(esp_netif_t *esp_netif) static esp_err_t esp_netif_update_default_netif_lwip(esp_netif_api_msg_t *msg) { esp_netif_t *esp_netif = msg->esp_netif; - esp_netif_action_t action = (esp_netif_action_t)msg->data; + esp_netif_route_prio_action_t action = (esp_netif_route_prio_action_t)msg->data; ESP_LOGD(TAG, "%s %p", __func__, esp_netif); @@ -337,6 +332,7 @@ static esp_err_t esp_netif_update_default_netif_lwip(esp_netif_api_msg_t *msg) esp_netif_set_default_netif_internal(s_last_default_esp_netif); break; case ESP_NETIF_STARTED: + case ESP_NETIF_GOT_IP: { // check if previously default interface hasn't been destroyed in the meantime s_last_default_esp_netif = esp_netif_is_active(s_last_default_esp_netif); @@ -352,6 +348,7 @@ static esp_err_t esp_netif_update_default_netif_lwip(esp_netif_api_msg_t *msg) default: case ESP_NETIF_STOPPED: + case ESP_NETIF_LOST_IP: { s_last_default_esp_netif = NULL; esp_netif_t *netif = esp_netif_next_unsafe(NULL); @@ -383,7 +380,7 @@ static esp_err_t esp_netif_update_default_netif_lwip(esp_netif_api_msg_t *msg) * @param esp_netif current interface which just updated state * @param action updating action (on-off) */ -static esp_err_t esp_netif_update_default_netif(esp_netif_t *esp_netif, esp_netif_action_t action) +esp_err_t esp_netif_update_default_netif(esp_netif_t *esp_netif, esp_netif_route_prio_action_t action) { return esp_netif_lwip_ipc_call(esp_netif_update_default_netif_lwip, esp_netif, (void*)action); } @@ -503,6 +500,24 @@ void* esp_netif_get_netif_impl(esp_netif_t *esp_netif) return NULL; } +#if CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF +static void store_dnsserver_info(struct netif* netif, u8_t numdns, const ip_addr_t *dnsserver) +{ + if (netif == NULL) { + return; + } + esp_netif_t *esp_netif = lwip_get_esp_netif(netif); + if (esp_netif == NULL || !esp_netif_is_netif_listed(esp_netif)) { + return; + } + if (!ip_addr_isany(dnsserver)) { + ip_addr_copy(esp_netif->dns[numdns], *dnsserver); + } else { + ip_addr_copy(esp_netif->dns[numdns], *IP_ADDR_ANY); + } +} +#endif + static void tcpip_init_done(void *arg) { sys_sem_t *init_sem = arg; @@ -546,6 +561,12 @@ esp_err_t esp_netif_init(void) sys_sem_wait(&init_sem); sys_sem_free(&init_sem); ESP_LOGD(TAG, "LwIP stack has been initialized"); +#if CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF + if (dns_setserver_callback(store_dnsserver_info) != ERR_OK) { + ESP_LOGE(TAG, "Feiled to configure DNS set server callback"); + return ESP_FAIL; + } +#endif } #if !LWIP_TCPIP_CORE_LOCKING @@ -1075,11 +1096,7 @@ static esp_err_t esp_netif_start_api(esp_netif_api_msg_t *msg) ESP_LOGD(TAG, "%s %p", __func__, esp_netif); if (ESP_NETIF_IS_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) { #if CONFIG_PPP_SUPPORT - esp_err_t ret = esp_netif_start_ppp(esp_netif); - if (ret == ESP_OK) { - esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED); - } - return ret; + return esp_netif_start_ppp(esp_netif); #endif } @@ -1156,8 +1173,10 @@ static esp_err_t esp_netif_start_api(esp_netif_api_msg_t *msg) LOG_NETIF_DISABLED_AND_DO("IPv4's DHCP Client", return ESP_ERR_NOT_SUPPORTED); #endif } - - esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED); + // For netifs with (active) DHCP client: we update the default netif after getting a valid IP + if (!((esp_netif->flags & ESP_NETIF_DHCP_CLIENT) && esp_netif->dhcpc_status != ESP_NETIF_DHCP_STOPPED)) { + esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED); + } return ESP_OK; } @@ -1371,7 +1390,7 @@ static void esp_netif_internal_dhcpc_cb(struct netif *netif) if (memcmp(ip_info, ip_info_old, sizeof(esp_netif_ip_info_t))) { evt.ip_changed = true; } - + esp_netif_update_default_netif(esp_netif, ESP_NETIF_GOT_IP); memcpy(&evt.ip_info, ip_info, sizeof(esp_netif_ip_info_t)); memcpy(ip_info_old, ip_info, sizeof(esp_netif_ip_info_t)); ESP_LOGD(TAG, "if%p ip changed=%d", esp_netif, evt.ip_changed); @@ -1412,7 +1431,7 @@ static void esp_netif_ip_lost_timer(void *arg) .esp_netif = esp_netif, }; int ret; - + esp_netif_update_default_netif(esp_netif, ESP_NETIF_LOST_IP); ESP_LOGD(TAG, "if%p ip lost tmr: raise ip lost event", esp_netif); memset(esp_netif->ip_info_old, 0, sizeof(esp_netif_ip_info_t)); if (esp_netif->lost_ip_event) { @@ -1731,7 +1750,10 @@ static esp_err_t esp_netif_up_api(esp_netif_api_msg_t *msg) netif_set_up(lwip_netif); netif_set_link_up(lwip_netif); - esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED); + // For netifs with (active) DHCP client: we update the default netif after getting a valid IP + if (!((esp_netif->flags & ESP_NETIF_DHCP_CLIENT) && esp_netif->dhcpc_status != ESP_NETIF_DHCP_STOPPED)) { + esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED); + } return ESP_OK; } @@ -1910,7 +1932,7 @@ static esp_err_t esp_netif_set_ip_info_api(esp_netif_api_msg_t *msg) if (memcmp(ip_info, esp_netif->ip_info_old, sizeof(esp_netif_ip_info_t))) { evt.ip_changed = true; } - + esp_netif_update_default_netif(esp_netif, ESP_NETIF_GOT_IP); memcpy(&evt.ip_info, ip_info, sizeof(esp_netif_ip_info_t)); memcpy(esp_netif->ip_info_old, ip_info, sizeof(esp_netif_ip_info_t)); ret = esp_event_post(IP_EVENT, evt_id, &evt, sizeof(evt), 0); @@ -1971,7 +1993,7 @@ static esp_err_t esp_netif_set_dns_info_api(esp_netif_api_msg_t *msg) ip_addr_t lwip_ip = {}; ESPIP_TO_IP(&dns->ip, &lwip_ip); - if (esp_netif->flags & ESP_NETIF_DHCP_SERVER) { + if (esp_netif && esp_netif->flags & ESP_NETIF_DHCP_SERVER) { #if ESP_DHCPS // if DHCP server configured to set DNS in dhcps API if (type != ESP_NETIF_DNS_MAIN) { @@ -1984,7 +2006,17 @@ static esp_err_t esp_netif_set_dns_info_api(esp_netif_api_msg_t *msg) LOG_NETIF_DISABLED_AND_DO("DHCP Server", return ESP_ERR_NOT_SUPPORTED); #endif } else { +#ifdef CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF + if (esp_netif) { + store_dnsserver_info(esp_netif->lwip_netif, type, &lwip_ip); + } + if (esp_netif == s_last_default_esp_netif || // if this is the default one -> need to update global DNS servers + esp_netif == NULL) { // if the netif ptr is set to NULL -> we explicitly require the update + dns_setserver(type, &lwip_ip); + } +#else dns_setserver(type, &lwip_ip); +#endif } return ESP_OK; @@ -1992,9 +2024,11 @@ static esp_err_t esp_netif_set_dns_info_api(esp_netif_api_msg_t *msg) esp_err_t esp_netif_set_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t type, esp_netif_dns_info_t *dns) { +#ifndef CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF if (esp_netif == NULL) { return ESP_ERR_ESP_NETIF_INVALID_PARAMS; } +#endif if (dns == NULL) { ESP_LOGD(TAG, "set dns null dns"); @@ -2022,7 +2056,7 @@ static esp_err_t esp_netif_get_dns_info_api(esp_netif_api_msg_t *msg) ESP_LOGD(TAG, "esp_netif_get_dns_info: esp_netif=%p type=%d", esp_netif, type); - if (esp_netif->flags & ESP_NETIF_DHCP_SERVER) { + if (esp_netif && esp_netif->flags & ESP_NETIF_DHCP_SERVER) { #if ESP_DHCPS ip4_addr_t dns_ip; dhcps_dns_getserver(esp_netif->dhcps, &dns_ip); @@ -2033,7 +2067,15 @@ static esp_err_t esp_netif_get_dns_info_api(esp_netif_api_msg_t *msg) #endif } else { const ip_addr_t* dns_ip = NULL; +#ifdef CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF + if (esp_netif == NULL) { // by setting esp_netif to NULL we require the global DNS server entry + dns_ip = dns_getserver(type); + } else { + dns_ip = &esp_netif->dns[type]; + } +#else dns_ip = dns_getserver(type); +#endif if(dns_ip != NULL) { IP_TO_ESPIP(dns_ip, &dns->ip); } @@ -2044,9 +2086,11 @@ static esp_err_t esp_netif_get_dns_info_api(esp_netif_api_msg_t *msg) esp_err_t esp_netif_get_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t type, esp_netif_dns_info_t *dns) { +#ifndef CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF if (esp_netif == NULL) { return ESP_ERR_ESP_NETIF_INVALID_PARAMS; } +#endif if (dns == NULL) { ESP_LOGE(TAG, "%s: dns_info cannot be NULL", __func__); @@ -2142,7 +2186,7 @@ static void esp_netif_internal_nd6_cb(struct netif *netif, uint8_t ip_index) ESP_LOGW(TAG,"CONFIG_LWIP_ESP_MLDV6_REPORT not enabled, but esp-netif configured with ESP_NETIF_FLAG_MLDV6_REPORT"); #endif } - + esp_netif_update_default_netif(esp_netif, ESP_NETIF_GOT_IP); memcpy(&evt.ip6_info, &ip6_info, sizeof(esp_netif_ip6_info_t)); int ret = esp_event_post(IP_EVENT, IP_EVENT_GOT_IP6, &evt, sizeof(evt), 0); if (ESP_OK != ret) { @@ -2685,7 +2729,7 @@ static esp_err_t esp_netif_add_ip6_address_api(esp_netif_api_msg_t *msg) err_t err = netif_add_ip6_address(msg->esp_netif->lwip_netif, &ip6addr, &index); ESP_RETURN_ON_FALSE(err == ERR_OK && index >= 0, ESP_ERR_ESP_NETIF_IP6_ADDR_FAILED, TAG, "Failed to add ip6 address"); - + esp_netif_update_default_netif(msg->esp_netif, ESP_NETIF_GOT_IP); netif_ip6_addr_set_state(msg->esp_netif->lwip_netif, index, addr->preferred ? IP6_ADDR_PREFERRED : IP6_ADDR_DEPRECATED); ip_event_got_ip6_t evt = {.esp_netif = msg->esp_netif, .ip_index = index}; diff --git a/components/esp_netif/lwip/esp_netif_lwip_internal.h b/components/esp_netif/lwip/esp_netif_lwip_internal.h index 955dd19f9d..7881348ff2 100644 --- a/components/esp_netif/lwip/esp_netif_lwip_internal.h +++ b/components/esp_netif/lwip/esp_netif_lwip_internal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -117,4 +117,19 @@ struct esp_netif_obj { #endif // CONFIG_ESP_NETIF_BRIDGE_EN // mldv6 timer bool mldv6_report_timer_started; + +#ifdef CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF + ip_addr_t dns[DNS_MAX_SERVERS]; +#endif }; + +typedef enum esp_netif_set_default_state { + ESP_NETIF_UNDEF, + ESP_NETIF_STARTED, + ESP_NETIF_GOT_IP, + ESP_NETIF_STOPPED, + ESP_NETIF_LOST_IP, + ESP_NETIF_SET_DEFAULT, +} esp_netif_route_prio_action_t; + +esp_err_t esp_netif_update_default_netif(esp_netif_t *esp_netif, esp_netif_route_prio_action_t action); diff --git a/components/esp_netif/lwip/esp_netif_lwip_ppp.c b/components/esp_netif/lwip/esp_netif_lwip_ppp.c index 1c5e91d3f6..d3f37c7fb5 100644 --- a/components/esp_netif/lwip/esp_netif_lwip_ppp.c +++ b/components/esp_netif/lwip/esp_netif_lwip_ppp.c @@ -75,6 +75,7 @@ static void on_ppp_status_changed(ppp_pcb *pcb, int err_code, void *ctx) break; case PPPERR_CONNECT: /* Connection lost */ ESP_LOGI(TAG, "Connection lost"); + esp_netif_update_default_netif(netif, ESP_NETIF_LOST_IP); err = esp_event_post(IP_EVENT, netif->lost_ip_event, &evt, sizeof(evt), 0); if (ESP_OK != err) { diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index 5d80561043..c3588ef1f4 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -1130,6 +1130,15 @@ menu "LWIP" help This option allows you to config dns fallback server address. + config LWIP_DNS_SETSERVER_WITH_NETIF + bool "Enable DNS server settings with netif" + default n + help + This option allows collecting DNS server settings per netif using + configurable callback function. + It's typically used with CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF + which configures a callback to collect the DNS info on esp_netif layer. + endmenu # DNS config LWIP_BRIDGEIF_MAX_PORTS diff --git a/components/lwip/lwip b/components/lwip/lwip index aa4f6e780f..3a3d1fb3e3 160000 --- a/components/lwip/lwip +++ b/components/lwip/lwip @@ -1 +1 @@ -Subproject commit aa4f6e780f374af5e10730960fe0262a916166d1 +Subproject commit 3a3d1fb3e3bc23cf86cf653ce5928eda47e2c15d diff --git a/components/lwip/port/include/lwipopts.h b/components/lwip/port/include/lwipopts.h index 48feeb16c3..b20b07479b 100644 --- a/components/lwip/port/include/lwipopts.h +++ b/components/lwip/port/include/lwipopts.h @@ -503,6 +503,17 @@ static inline uint32_t timeout_from_offered(uint32_t lease, uint32_t min) #define LWIP_DNS_SUPPORT_MDNS_QUERIES 0 #endif +/** + * LWIP_DNS_SETSERVER_WITH_NETIF: If this is turned on, the dns_setserver_with_netif() is enabled and called + * from all internal modules (instead of dns_setserver()) allowing to setup a user callback to collect DNS server + * information acquired by the related network interface. + */ +#ifdef CONFIG_LWIP_DNS_SETSERVER_WITH_NETIF +#define LWIP_DNS_SETSERVER_WITH_NETIF 1 +#else +#define LWIP_DNS_SETSERVER_WITH_NETIF 0 +#endif + /* --------------------------------- ---------- UDP options ----------