diff --git a/components/esp_netif/include/esp_netif.h b/components/esp_netif/include/esp_netif.h index d0cda153a2..a8df60e674 100644 --- a/components/esp_netif/include/esp_netif.h +++ b/components/esp_netif/include/esp_netif.h @@ -402,6 +402,22 @@ esp_err_t esp_netif_set_old_ip_info(esp_netif_t *esp_netif, const esp_netif_ip_i */ int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif); +/** + * @brief Get net interface name from network stack implementation + * + * @note This name could be used in `setsockopt()` to bind socket with appropriate interface + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[out] name Interface name as specified in underlying TCP/IP stack. Note that the + * actual name will be copied to the specified buffer, which must be allocated to hold + * maximum interface name size (6 characters for lwIP) + * + * @return + * - ESP_OK + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS +*/ +esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name); + /** * @} */ diff --git a/components/esp_netif/lwip/esp_netif_lwip.c b/components/esp_netif/lwip/esp_netif_lwip.c index 0d57b66489..c55684162a 100644 --- a/components/esp_netif/lwip/esp_netif_lwip.c +++ b/components/esp_netif/lwip/esp_netif_lwip.c @@ -1736,4 +1736,15 @@ int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif) return netif_get_index(esp_netif->lwip_netif); } +esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name) +{ + ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); + + if (esp_netif == NULL || esp_netif->lwip_netif == NULL) { + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + netif_index_to_name(netif_get_index(esp_netif->lwip_netif), name); + return ESP_OK; +} + #endif /* CONFIG_ESP_NETIF_TCPIP_LWIP */ diff --git a/examples/protocols/sockets/tcp_client_multi_net/main/Kconfig.projbuild b/examples/protocols/sockets/tcp_client_multi_net/main/Kconfig.projbuild index af1a705526..680c485e15 100644 --- a/examples/protocols/sockets/tcp_client_multi_net/main/Kconfig.projbuild +++ b/examples/protocols/sockets/tcp_client_multi_net/main/Kconfig.projbuild @@ -13,4 +13,12 @@ menu "Example Configuration" help host port + config EXAMPLE_BIND_SOCKET_TO_NETIF_NAME + bool "Bind to interface by its name" + default y + help + By default example uses setsockopt() to bind the tcp-client's socket + to specific interface. Setting this option to true demonstrates binding + the socket to the local ip address of the network interface. + endmenu diff --git a/examples/protocols/sockets/tcp_client_multi_net/main/tcp_client_multiple.c b/examples/protocols/sockets/tcp_client_multi_net/main/tcp_client_multiple.c index f69262f2f8..d95e95445d 100644 --- a/examples/protocols/sockets/tcp_client_multi_net/main/tcp_client_multiple.c +++ b/examples/protocols/sockets/tcp_client_multi_net/main/tcp_client_multiple.c @@ -30,7 +30,6 @@ static const char *payload = "GET / HTTP/1.1\r\n\r\n"; static void app_multiple_handle(esp_ip4_addr_t *ip4_addr, esp_netif_t *esp_netif) { - esp_netif_ip_info_t ip; char rx_buffer[128] = {0}; const char *netif_name = esp_netif_get_desc(esp_netif); @@ -42,7 +41,20 @@ static void app_multiple_handle(esp_ip4_addr_t *ip4_addr, esp_netif_t *esp_netif } ESP_LOGI(TAG, "\"%s\" Socket created", netif_name); - /* Bind local IP of the network interface */ + /* Bind the socket to an interface (based on example config option) + * - using netif local IP address + * - using netif name + */ +#if CONFIG_EXAMPLE_BIND_SOCKET_TO_NETIF_NAME + struct ifreq ifr; + esp_netif_get_netif_impl_name(esp_netif, ifr.ifr_name); + int ret = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (void*)&ifr, sizeof(struct ifreq)); + if (ret < 0) { + ESP_LOGE(TAG, "\"%s\" Unable to bind socket to specified interface: errno %d", netif_name, errno); + goto app_multiple_handle_fail; + } +#else + esp_netif_ip_info_t ip; memset(&ip, 0, sizeof(esp_netif_ip_info_t)); ESP_ERROR_CHECK(esp_netif_get_ip_info(esp_netif, &ip)); @@ -51,12 +63,13 @@ static void app_multiple_handle(esp_ip4_addr_t *ip4_addr, esp_netif_t *esp_netif addr.sin_family = AF_INET; addr.sin_port = htons(0); addr.sin_addr.s_addr = ip.ip.addr; - + int ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr)); if (ret < 0) { ESP_LOGE(TAG, "\"%s\" Unable to bind socket: errno %d", netif_name, errno); goto app_multiple_handle_fail; } +#endif /* CONFIG_EXAMPLE_BIND_SOCKET_TO_NETIF_NAME */ /* Connect to the host by the network interface */ struct sockaddr_in destAddr;