diff --git a/components/esp_netif/include/esp_netif.h b/components/esp_netif/include/esp_netif.h index 0621d4eb6d2..2cb5763fb89 100644 --- a/components/esp_netif/include/esp_netif.h +++ b/components/esp_netif/include/esp_netif.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -692,6 +692,20 @@ esp_err_t esp_netif_dhcps_stop(esp_netif_t *esp_netif); */ esp_err_t esp_netif_dhcps_get_clients_by_mac(esp_netif_t *esp_netif, int num, esp_netif_pair_mac_ip_t *mac_ip_pair); +/** +* @brief Populate IP addresses of client from the lwIP ARP cache on this interface +* +* Walks the ARP table and fills in ip when the Ethernet address matches and the entry belongs to esp_netif. +* +* @param[in] esp_netif Handle to esp-netif instance +* @param[in,out] mac_ip_pair MAC/IP pair to fill in the IP +* @return +* - ESP_OK on success (including when nothing was found in ARP) +* - ESP_ERR_ESP_NETIF_INVALID_PARAMS on invalid params +* - ESP_ERR_NOT_SUPPORTED if ARP is disabled in lwIP +*/ +esp_err_t esp_netif_arp_get_client_by_mac(esp_netif_t *esp_netif, esp_netif_pair_mac_ip_t *mac_ip_pair); + /** * @} */ diff --git a/components/esp_netif/lwip/esp_netif_lwip.c b/components/esp_netif/lwip/esp_netif_lwip.c index 56078e94d53..a7188633e97 100644 --- a/components/esp_netif/lwip/esp_netif_lwip.c +++ b/components/esp_netif/lwip/esp_netif_lwip.c @@ -1918,6 +1918,52 @@ esp_err_t esp_netif_dhcps_get_clients_by_mac(esp_netif_t *esp_netif, int num, es #endif // CONFIG_LWIP_DHCPS } +#if CONFIG_LWIP_IPV4 && LWIP_ARP +static esp_err_t esp_netif_arp_get_client_by_mac_api(esp_netif_api_msg_t *msg) +{ + esp_netif_t *esp_netif = msg->esp_netif; + esp_netif_pair_mac_ip_t *mac_ip_pair = msg->data; + struct netif *lwip_netif = esp_netif ? esp_netif->lwip_netif : NULL; + + if (lwip_netif == NULL || mac_ip_pair == NULL) { + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + + mac_ip_pair->ip.addr = 0; + + for (size_t i = 0; i < ARP_TABLE_SIZE; i++) { + ip4_addr_t *ip_ptr = NULL; + struct netif *nif = NULL; + struct eth_addr *eth_ptr = NULL; + + if (!etharp_get_entry(i, &ip_ptr, &nif, ð_ptr)) { + continue; + } + if (nif != lwip_netif) { + continue; + } + if (memcmp(eth_ptr->addr, mac_ip_pair->mac, ETH_HWADDR_LEN) != 0) { + continue; + } + mac_ip_pair->ip.addr = ip_ptr->addr; + break; + } + return ESP_OK; +} +#endif /* CONFIG_LWIP_IPV4 && LWIP_ARP */ + +esp_err_t esp_netif_arp_get_client_by_mac(esp_netif_t *esp_netif, esp_netif_pair_mac_ip_t *mac_ip_pair) +{ +#if CONFIG_LWIP_IPV4 && LWIP_ARP + if (esp_netif == NULL || mac_ip_pair == NULL) { + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + return esp_netif_lwip_ipc_call(esp_netif_arp_get_client_by_mac_api, esp_netif, (void *)mac_ip_pair); +#else + return ESP_ERR_NOT_SUPPORTED; +#endif /* CONFIG_LWIP_IPV4 && LWIP_ARP */ +} + static esp_err_t esp_netif_set_dns_info_api(esp_netif_api_msg_t *msg) { esp_netif_t *esp_netif = msg->esp_netif; diff --git a/components/esp_wifi/include/esp_wifi_ap_get_sta_list.h b/components/esp_wifi/include/esp_wifi_ap_get_sta_list.h index 7a4d167b644..dd4adf95cd4 100644 --- a/components/esp_wifi/include/esp_wifi_ap_get_sta_list.h +++ b/components/esp_wifi/include/esp_wifi_ap_get_sta_list.h @@ -24,7 +24,8 @@ typedef struct { /** * @brief Get IP information for stations connected to the Wi-Fi AP interface * - * @note If `CONFIG_LWIP_DHCPS` is disabled then `ip` address field will not be populated in sta list + * @note If `CONFIG_LWIP_DHCPS` is disabled then DHCP lookup is skipped; IPv4 may still be filled from the lwIP ARP cache when available. + * After DHCP (when enabled), any station still without an IP is resolved via ARP table on the same interface. * * @warning This API works only for the default Wi-Fi AP interface, i.e. esp-netif with key="WIFI_AP_DEF" * diff --git a/components/esp_wifi/src/wifi_default_ap.c b/components/esp_wifi/src/wifi_default_ap.c index 66cab588378..ec068acbbd4 100644 --- a/components/esp_wifi/src/wifi_default_ap.c +++ b/components/esp_wifi/src/wifi_default_ap.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,5 +25,18 @@ esp_err_t esp_wifi_ap_get_sta_list_with_ip(const wifi_sta_list_t *wifi_sta_list, memcpy(wifi_sta_ip_mac_list->sta[i].mac, wifi_sta_list->sta[i].mac, 6); memset(&wifi_sta_ip_mac_list->sta[i].ip, 0, sizeof(esp_ip4_addr_t)); } - return esp_netif_dhcps_get_clients_by_mac(ap, num, wifi_sta_ip_mac_list->sta); + esp_err_t err = esp_netif_dhcps_get_clients_by_mac(ap, num, wifi_sta_ip_mac_list->sta); + if (err != ESP_OK && err != ESP_ERR_NOT_SUPPORTED) { + return err; + } + for (int i = 0; i < num; i++) { + if (wifi_sta_ip_mac_list->sta[i].ip.addr == 0) { + // Try to get the IP from the ARP table, and not care about the result + esp_netif_arp_get_client_by_mac(ap, &wifi_sta_ip_mac_list->sta[i]); + } + } + return ESP_OK; +#else + return ESP_ERR_NOT_SUPPORTED; +#endif } diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/main/ble50_sec_gattc_demo.c b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/main/ble50_sec_gattc_demo.c index 50299d80dc3..a5f041013de 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/main/ble50_sec_gattc_demo.c +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/main/ble50_sec_gattc_demo.c @@ -1,9 +1,5 @@ /* -<<<<<<< HEAD * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD -======= - * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD ->>>>>>> 2f524e27834... feat(examples/bluedroid): Add BLE time interval conversion macros for better readability * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */