Skip to content

Commit

Permalink
Wrap ipv6 code a bit more (#4574)
Browse files Browse the repository at this point in the history
* Wrap ipv6 code a bit more for when ipv6 support should not be compiled in

* More checks

* More uses

* Fix
  • Loading branch information
jesserockz committed Mar 21, 2023
1 parent cd57469 commit d42f35d
Show file tree
Hide file tree
Showing 11 changed files with 112 additions and 20 deletions.
2 changes: 1 addition & 1 deletion esphome/components/api/api_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void APIServer::setup() {

struct sockaddr_storage server;

socklen_t sl = socket::set_sockaddr_any((struct sockaddr *) &server, sizeof(server), htons(this->port_));
socklen_t sl = socket::set_sockaddr_any((struct sockaddr *) &server, sizeof(server), this->port_);
if (sl == 0) {
ESP_LOGW(TAG, "Socket unable to set sockaddr: errno %d", errno);
this->mark_failed();
Expand Down
13 changes: 13 additions & 0 deletions esphome/components/ethernet/ethernet_component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,14 +255,22 @@ void EthernetComponent::start_connect_() {
if (this->manual_ip_.has_value()) {
if (uint32_t(this->manual_ip_->dns1) != 0) {
ip_addr_t d;
#if LWIP_IPV6
d.type = IPADDR_TYPE_V4;
d.u_addr.ip4.addr = static_cast<uint32_t>(this->manual_ip_->dns1);
#else
d.addr = static_cast<uint32_t>(this->manual_ip_->dns1);
#endif
dns_setserver(0, &d);
}
if (uint32_t(this->manual_ip_->dns1) != 0) {
ip_addr_t d;
#if LWIP_IPV6
d.type = IPADDR_TYPE_V4;
d.u_addr.ip4.addr = static_cast<uint32_t>(this->manual_ip_->dns2);
#else
d.addr = static_cast<uint32_t>(this->manual_ip_->dns2);
#endif
dns_setserver(1, &d);
}
} else {
Expand All @@ -289,8 +297,13 @@ void EthernetComponent::dump_connect_params_() {
const ip_addr_t *dns_ip1 = dns_getserver(0);
const ip_addr_t *dns_ip2 = dns_getserver(1);

#if LWIP_IPV6
ESP_LOGCONFIG(TAG, " DNS1: %s", network::IPAddress(dns_ip1->u_addr.ip4.addr).str().c_str());
ESP_LOGCONFIG(TAG, " DNS2: %s", network::IPAddress(dns_ip2->u_addr.ip4.addr).str().c_str());
#else
ESP_LOGCONFIG(TAG, " DNS1: %s", network::IPAddress(dns_ip1->addr).str().c_str());
ESP_LOGCONFIG(TAG, " DNS2: %s", network::IPAddress(dns_ip2->addr).str().c_str());
#endif

esp_err_t err;

Expand Down
14 changes: 11 additions & 3 deletions esphome/components/mqtt/mqtt_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

#ifdef USE_MQTT

#include <utility>
#include "esphome/components/network/util.h"
#include "esphome/core/application.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include "esphome/components/network/util.h"
#include <utility>
#ifdef USE_LOGGER
#include "esphome/components/logger/logger.h"
#endif
#include "lwip/err.h"
#include "lwip/dns.h"
#include "lwip/err.h"
#include "mqtt_component.h"

namespace esphome {
Expand Down Expand Up @@ -104,7 +104,11 @@ void MQTTClientComponent::start_dnslookup_() {
// Got IP immediately
this->dns_resolved_ = true;
#ifdef USE_ESP32
#if LWIP_IPV6
this->ip_ = addr.u_addr.ip4.addr;
#else
this->ip_ = addr.addr;
#endif
#endif
#ifdef USE_ESP8266
this->ip_ = addr.addr;
Expand Down Expand Up @@ -160,8 +164,12 @@ void MQTTClientComponent::dns_found_callback(const char *name, const ip_addr_t *
a_this->dns_resolve_error_ = true;
} else {
#ifdef USE_ESP32
#if LWIP_IPV6
a_this->ip_ = ipaddr->u_addr.ip4.addr;
#else
a_this->ip_ = ipaddr->addr;
#endif
#endif // USE_ESP32
#ifdef USE_ESP8266
a_this->ip_ = ipaddr->addr;
#endif
Expand Down
8 changes: 5 additions & 3 deletions esphome/components/network/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@


async def to_code(config):
if CONF_ENABLE_IPV6 in config and config[CONF_ENABLE_IPV6]:
add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", True)
add_idf_sdkconfig_option("CONFIG_LWIP_IPV6_AUTOCONFIG", True)
if CONF_ENABLE_IPV6 in config:
add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", config[CONF_ENABLE_IPV6])
add_idf_sdkconfig_option(
"CONFIG_LWIP_IPV6_AUTOCONFIG", config[CONF_ENABLE_IPV6]
)
2 changes: 1 addition & 1 deletion esphome/components/ota/ota_component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ void OTAComponent::setup() {

struct sockaddr_storage server;

socklen_t sl = socket::set_sockaddr_any((struct sockaddr *) &server, sizeof(server), htons(this->port_));
socklen_t sl = socket::set_sockaddr_any((struct sockaddr *) &server, sizeof(server), this->port_);
if (sl == 0) {
ESP_LOGW(TAG, "Socket unable to set sockaddr: errno %d", errno);
this->mark_failed();
Expand Down
5 changes: 4 additions & 1 deletion esphome/components/socket/bsd_sockets_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ std::string format_sockaddr(const struct sockaddr_storage &storage) {
char buf[INET_ADDRSTRLEN];
if (inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)) != nullptr)
return std::string{buf};
} else if (storage.ss_family == AF_INET6) {
}
#if LWIP_IPV6
else if (storage.ss_family == AF_INET6) {
const struct sockaddr_in6 *addr = reinterpret_cast<const struct sockaddr_in6 *>(&storage);
char buf[INET6_ADDRSTRLEN];
// Format IPv4-mapped IPv6 addresses as regular IPv4 addresses
Expand All @@ -32,6 +34,7 @@ std::string format_sockaddr(const struct sockaddr_storage &storage) {
if (inet_ntop(AF_INET6, &addr->sin6_addr, buf, sizeof(buf)) != nullptr)
return std::string{buf};
}
#endif
return {};
}

Expand Down
15 changes: 13 additions & 2 deletions esphome/components/socket/headers.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,28 @@
/* Address families. */
#define AF_UNSPEC 0
#define AF_INET 2
#define AF_INET6 10
#define PF_INET AF_INET
#define PF_INET6 AF_INET6
#define PF_UNSPEC AF_UNSPEC

#define IPPROTO_IP 0
#define IPPROTO_TCP 6

#if LWIP_IPV6
#define AF_INET6 10
#define PF_INET6 AF_INET6

#define IPPROTO_IPV6 41
#define IPPROTO_ICMPV6 58
#endif

#define TCP_NODELAY 0x01

#define F_GETFL 3
#define F_SETFL 4

#ifdef O_NONBLOCK
#undef O_NONBLOCK
#endif
#define O_NONBLOCK 1

#define SHUT_RD 0
Expand Down Expand Up @@ -58,6 +67,7 @@ struct sockaddr_in {
char sin_zero[SIN_ZERO_LEN];
};

#if LWIP_IPV6
// NOLINTNEXTLINE(readability-identifier-naming)
struct sockaddr_in6 {
uint8_t sin6_len; /* length of this structure */
Expand All @@ -67,6 +77,7 @@ struct sockaddr_in6 {
struct in6_addr sin6_addr; /* IPv6 address */
uint32_t sin6_scope_id; /* Set of interfaces for scope */
};
#endif

// NOLINTNEXTLINE(readability-identifier-naming)
struct sockaddr {
Expand Down
32 changes: 30 additions & 2 deletions esphome/components/socket/socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,34 @@ std::unique_ptr<Socket> socket_ip(int type, int protocol) {
#endif
}

socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const char *ip_address, uint16_t port) {
#if LWIP_IPV6
if (addrlen < sizeof(sockaddr_in6)) {
errno = EINVAL;
return 0;
}
auto *server = reinterpret_cast<sockaddr_in6 *>(addr);
memset(server, 0, sizeof(sockaddr_in6));
server->sin6_family = AF_INET6;
server->sin6_port = htons(port);
ip6_addr_t ip6;
inet6_aton(ip_address, &ip6);
memcpy(server->sin6_addr.un.u32_addr, ip6.addr, sizeof(ip6.addr));
return sizeof(sockaddr_in6);
#else
if (addrlen < sizeof(sockaddr_in)) {
errno = EINVAL;
return 0;
}
auto *server = reinterpret_cast<sockaddr_in *>(addr);
memset(server, 0, sizeof(sockaddr_in));
server->sin_family = AF_INET;
server->sin_addr.s_addr = inet_addr(ip_address);
server->sin_port = htons(port);
return sizeof(sockaddr_in);
#endif
}

socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t port) {
#if LWIP_IPV6
if (addrlen < sizeof(sockaddr_in6)) {
Expand All @@ -23,7 +51,7 @@ socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t po
auto *server = reinterpret_cast<sockaddr_in6 *>(addr);
memset(server, 0, sizeof(sockaddr_in6));
server->sin6_family = AF_INET6;
server->sin6_port = port;
server->sin6_port = htons(port);
server->sin6_addr = in6addr_any;
return sizeof(sockaddr_in6);
#else
Expand All @@ -35,7 +63,7 @@ socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t po
memset(server, 0, sizeof(sockaddr_in));
server->sin_family = AF_INET;
server->sin_addr.s_addr = ESPHOME_INADDR_ANY;
server->sin_port = port;
server->sin_port = htons(port);
return sizeof(sockaddr_in);
#endif
}
Expand Down
5 changes: 4 additions & 1 deletion esphome/components/socket/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ std::unique_ptr<Socket> socket(int domain, int type, int protocol);
/// Create a socket in the newest available IP domain (IPv6 or IPv4) of the given type and protocol.
std::unique_ptr<Socket> socket_ip(int type, int protocol);

/// Set a sockaddr to the any address for the IP version used by socket_ip().
/// Set a sockaddr to the specified address and port for the IP version used by socket_ip().
socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const char *ip_address, uint16_t port);

/// Set a sockaddr to the any address and specified port for the IP version used by socket_ip().
socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t port);

} // namespace socket
Expand Down
20 changes: 15 additions & 5 deletions esphome/components/wifi/wifi_component_esp32_arduino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@

#include <esp_wifi.h>

#include <utility>
#include <algorithm>
#include <utility>
#ifdef USE_WIFI_WPA2_EAP
#include <esp_wpa2.h>
#endif
#include "lwip/err.h"
#include "lwip/dns.h"
#include "lwip/apps/sntp.h"
#include "lwip/dns.h"
#include "lwip/err.h"

#include "esphome/core/application.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include "esphome/core/hal.h"
#include "esphome/core/application.h"
#include "esphome/core/util.h"

namespace esphome {
Expand Down Expand Up @@ -128,13 +128,23 @@ bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
}

ip_addr_t dns;
#if LWIP_IPV6
dns.type = IPADDR_TYPE_V4;
#endif
if (uint32_t(manual_ip->dns1) != 0) {
#if LWIP_IPV6
dns.u_addr.ip4.addr = static_cast<uint32_t>(manual_ip->dns1);
#else
dns.addr = static_cast<uint32_t>(manual_ip->dns1);
#endif
dns_setserver(0, &dns);
}
if (uint32_t(manual_ip->dns2) != 0) {
#if LWIP_IPV6
dns.u_addr.ip4.addr = static_cast<uint32_t>(manual_ip->dns2);
#else
dns.addr = static_cast<uint32_t>(manual_ip->dns2);
#endif
dns_setserver(1, &dns);
}

Expand Down
16 changes: 15 additions & 1 deletion esphome/components/wifi/wifi_component_esp_idf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,13 +451,23 @@ bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
}

ip_addr_t dns;
#if LWIP_IPV6
dns.type = IPADDR_TYPE_V4;
#endif
if (uint32_t(manual_ip->dns1) != 0) {
#if LWIP_IPV6
dns.u_addr.ip4.addr = static_cast<uint32_t>(manual_ip->dns1);
#else
dns.addr = static_cast<uint32_t>(manual_ip->dns1);
#endif
dns_setserver(0, &dns);
}
if (uint32_t(manual_ip->dns2) != 0) {
#if LWIP_IPV6
dns.u_addr.ip4.addr = static_cast<uint32_t>(manual_ip->dns2);
#else
dns.addr = static_cast<uint32_t>(manual_ip->dns2);
#endif
dns_setserver(1, &dns);
}

Expand Down Expand Up @@ -639,7 +649,7 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) {

} else if (data->event_base == IP_EVENT && data->event_id == IP_EVENT_STA_GOT_IP) {
const auto &it = data->data.ip_got_ip;
#ifdef LWIP_IPV6_AUTOCONFIG
#if LWIP_IPV6_AUTOCONFIG
tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA);
#endif
ESP_LOGV(TAG, "Event: Got IP static_ip=%s gateway=%s", format_ip4_addr(it.ip_info.ip).c_str(),
Expand Down Expand Up @@ -912,7 +922,11 @@ network::IPAddress WiFiComponent::wifi_gateway_ip_() {
}
network::IPAddress WiFiComponent::wifi_dns_ip_(int num) {
const ip_addr_t *dns_ip = dns_getserver(num);
#if LWIP_IPV6
return {dns_ip->u_addr.ip4.addr};
#else
return {dns_ip->addr};
#endif
}

} // namespace wifi
Expand Down

0 comments on commit d42f35d

Please sign in to comment.