[socket] Zero lwip address struct and narrow dual-stack bind promotion

This commit is contained in:
J. Nick Koston
2026-08-28 10:31:20 -05:00
parent 7cbc81ad66
commit a4d2a4ad4b
4 changed files with 11 additions and 5 deletions
@@ -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
@@ -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<const sockaddr_in *>(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;
@@ -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);
@@ -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