diff --git a/esphome/components/socket/bsd_sockets_impl.h b/esphome/components/socket/bsd_sockets_impl.h index 1b5ea9ebcd..e2b5de6f10 100644 --- a/esphome/components/socket/bsd_sockets_impl.h +++ b/esphome/components/socket/bsd_sockets_impl.h @@ -144,6 +144,9 @@ class BSDSocketImpl { int get_fd() const { return this->fd_; } + /// UDP rx drop counter parity with LWIPRawUDPImpl; drops are not counted here. + uint16_t get_rx_dropped() const { return 0; } + protected: // fd_ < 0 means "not open" — used both pre-open (initial state) and post-close. This // replaces a separate closed_ flag: close() sets fd_ = -1 after ::close(), and the diff --git a/esphome/components/socket/lwip_raw_common_impl.cpp b/esphome/components/socket/lwip_raw_common_impl.cpp index d9ffbfb54a..77e896f535 100644 --- a/esphome/components/socket/lwip_raw_common_impl.cpp +++ b/esphome/components/socket/lwip_raw_common_impl.cpp @@ -51,6 +51,8 @@ bool sockaddr_to_lwip(const struct sockaddr *addr, socklen_t addrlen, ip_addr_t // headers.h defines sockaddr and sockaddr_in with the same size, so this covers AF_INET if (addrlen < sizeof(struct sockaddr)) return false; + // Zero the whole struct — the IPv6 zone byte would otherwise be stack garbage + memset(ip, 0, sizeof(*ip)); if (addr->sa_family == AF_INET) { auto *addr4 = reinterpret_cast(addr); *port = ntohs(addr4->sin_port); @@ -77,7 +79,8 @@ bool sockaddr_to_lwip_bind(sa_family_t family, const struct sockaddr *addr, sock if (!sockaddr_to_lwip(addr, addrlen, ip, port)) return false; #if LWIP_IPV6 - if (family == AF_INET6) + // Only promote wildcard binds — a specific address must keep filtering + if (family == AF_INET6 && ip_addr_isany_val(*ip)) IP_SET_TYPE_VAL(*ip, IPADDR_TYPE_ANY); #endif return true; diff --git a/esphome/components/socket/lwip_raw_common_impl.h b/esphome/components/socket/lwip_raw_common_impl.h index dca882cdf0..749b149e43 100644 --- a/esphome/components/socket/lwip_raw_common_impl.h +++ b/esphome/components/socket/lwip_raw_common_impl.h @@ -31,10 +31,7 @@ namespace esphome::socket { // This is a per-TU convenience macro, not defined here to avoid macro leaking. /// Convert lwip ip_addr_t + host-order port to sockaddr, based on the socket's address family. -/// @param port_host Port in host byte order. TCP callers must convert from network order first -/// (tcp_pcb stores ports in network byte order); UDP callers can pass directly -/// (lwip udp_recv callback provides port in host byte order). -/// Shared by both TCP (LWIPRawCommon) and UDP (LWIPRawUDPImpl) implementations. +/// TCP callers pass ntohs(pcb port) to preserve historical getpeername/getsockname output. int lwip_ip_to_sockaddr(sa_family_t family, const ip_addr_t *ip, uint16_t port_host, struct sockaddr *name, socklen_t *addrlen); diff --git a/esphome/components/socket/lwip_sockets_impl.h b/esphome/components/socket/lwip_sockets_impl.h index 7f3b706cd8..9cba164716 100644 --- a/esphome/components/socket/lwip_sockets_impl.h +++ b/esphome/components/socket/lwip_sockets_impl.h @@ -84,6 +84,9 @@ class LwIPSocketImpl { int get_fd() const { return this->fd_; } + /// UDP rx drop counter parity with LWIPRawUDPImpl; drops are not counted here. + uint16_t get_rx_dropped() const { return 0; } + protected: // fd_ < 0 means "not open" — used both pre-open (initial state) and post-close. This // replaces a separate closed_ flag: close() sets fd_ = -1 after lwip_close(), and the