WIP ipv6 works(-ish)
* metro esp32s2 only, because that's what I had handy
* nothing is started at boot; I hung it on `start_dhcp()` which is dubious
* I get a stateless address (which doesn't seem to work) and a dhcpv6 address (which does)
```
>>> wifi.radio.ipv6_addresses
('FE80::7EDF:A1FF:FE00:518C', 'FD5F:3F5C:FE50:0:7EDF:A1FF:FE00:518C')
```
* depending whether a v4 or v6 dns server is configured, DNS resolution breaks
wrong ipv4_dns is first 4 bytes of the v6 dns server address:
```
>>> wifi.radio.ipv4_dns
253.95.63.92
```
* I can connect to a v4 or v6 SSH server on the local network and read its banner
>>> s.close(); s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM); s.connect(("fd5f:3f5c:fe50:0:6d9:f5ff:fe1f:ce10", 22))
*** len[0]=28
*** len=28 family=10 port=5632
>>> s.recv_into(buf)
40
>>> bytes(buf)
b'SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u3\r\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
This commit is contained in:
parent
3b30f0cc36
commit
9088488d1c
7 changed files with 83 additions and 51 deletions
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
CONFIG_LWIP_IPV6_AUTOCONFIG=y
|
||||
CONFIG_LWIP_IPV6_RDNSS_MAX_DNS_SERVERS=2
|
||||
CONFIG_LWIP_IPV6_DHCP6=y
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
#include "py/mperrno.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/socketpool/SocketPool.h"
|
||||
#include "common-hal/socketpool/__init__.h"
|
||||
#if CIRCUITPY_SSL
|
||||
#include "shared-bindings/ssl/SSLSocket.h"
|
||||
#include "shared-module/ssl/SSLSocket.h"
|
||||
|
|
@ -25,6 +26,20 @@
|
|||
#include "components/lwip/lwip/src/include/lwip/netdb.h"
|
||||
#include "components/vfs/include/esp_vfs_eventfd.h"
|
||||
|
||||
static void resolve_host_or_throw(socketpool_socket_obj_t *self, const char *hostname, struct sockaddr_storage *addr, int port) {
|
||||
struct addrinfo *result_i;
|
||||
const struct addrinfo hints = {
|
||||
.ai_family = self->family,
|
||||
.ai_socktype = self->type,
|
||||
};
|
||||
int error = socketpool_getaddrinfo_common(hostname, port, &hints, &result_i);
|
||||
if (error != 0 || result_i == NULL) {
|
||||
common_hal_socketpool_socketpool_raise_gaierror_noname();
|
||||
}
|
||||
memcpy(addr, result_i->ai_addr, sizeof(struct sockaddr_storage));
|
||||
lwip_freeaddrinfo(result_i);
|
||||
}
|
||||
|
||||
StackType_t socket_select_stack[2 * configMINIMAL_STACK_SIZE];
|
||||
|
||||
/* Socket state table:
|
||||
|
|
@ -339,7 +354,7 @@ size_t common_hal_socketpool_socket_bind(socketpool_socket_obj_t *self,
|
|||
ip = inet_addr(host);
|
||||
}
|
||||
bind_addr.sin_addr.s_addr = ip;
|
||||
bind_addr.sin_family = AF_INET;
|
||||
bind_addr.sin_family = self->family;
|
||||
bind_addr.sin_port = htons(port);
|
||||
|
||||
int result = lwip_bind(self->num, (struct sockaddr *)&bind_addr, sizeof(bind_addr));
|
||||
|
|
@ -382,26 +397,8 @@ void common_hal_socketpool_socket_close(socketpool_socket_obj_t *self) {
|
|||
|
||||
void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self,
|
||||
const char *host, size_t hostlen, uint32_t port) {
|
||||
const struct addrinfo hints = {
|
||||
.ai_family = self->family,
|
||||
.ai_socktype = self->type,
|
||||
};
|
||||
struct addrinfo *result_i;
|
||||
int error = lwip_getaddrinfo(host, NULL, &hints, &result_i);
|
||||
if (error != 0 || result_i == NULL) {
|
||||
common_hal_socketpool_socketpool_raise_gaierror_noname();
|
||||
}
|
||||
|
||||
// Set parameters
|
||||
struct sockaddr_in dest_addr;
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
dest_addr.sin_addr.s_addr = ((struct sockaddr_in *)result_i->ai_addr)->sin_addr.s_addr;
|
||||
#pragma GCC diagnostic pop
|
||||
lwip_freeaddrinfo(result_i);
|
||||
|
||||
dest_addr.sin_family = AF_INET;
|
||||
dest_addr.sin_port = htons(port);
|
||||
struct sockaddr_storage addr;
|
||||
resolve_host_or_throw(self, host, &addr, port);
|
||||
|
||||
// Replace above with function call -----
|
||||
|
||||
|
|
@ -409,7 +406,7 @@ void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self,
|
|||
// All our sockets are non-blocking, so we check the timeout ourselves.
|
||||
|
||||
int result = -1;
|
||||
result = lwip_connect(self->num, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in));
|
||||
result = lwip_connect(self->num, (struct sockaddr *)&addr, addr.s2_len);
|
||||
|
||||
if (result == 0) {
|
||||
// Connected immediately.
|
||||
|
|
@ -611,29 +608,10 @@ mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t *self, const
|
|||
mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t *self,
|
||||
const char *host, size_t hostlen, uint32_t port, const uint8_t *buf, uint32_t len) {
|
||||
|
||||
// Set parameters
|
||||
const struct addrinfo hints = {
|
||||
.ai_family = self->family,
|
||||
.ai_socktype = self->type,
|
||||
};
|
||||
struct addrinfo *result_i;
|
||||
int error = lwip_getaddrinfo(host, NULL, &hints, &result_i);
|
||||
if (error != 0 || result_i == NULL) {
|
||||
common_hal_socketpool_socketpool_raise_gaierror_noname();
|
||||
}
|
||||
struct sockaddr_storage addr;
|
||||
resolve_host_or_throw(self, host, &addr, port);
|
||||
|
||||
// Set parameters
|
||||
struct sockaddr_in dest_addr;
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
dest_addr.sin_addr.s_addr = ((struct sockaddr_in *)result_i->ai_addr)->sin_addr.s_addr;
|
||||
#pragma GCC diagnostic pop
|
||||
lwip_freeaddrinfo(result_i);
|
||||
|
||||
dest_addr.sin_family = AF_INET;
|
||||
dest_addr.sin_port = htons(port);
|
||||
|
||||
int bytes_sent = lwip_sendto(self->num, buf, len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
|
||||
int bytes_sent = lwip_sendto(self->num, buf, len, 0, (struct sockaddr *)&addr, addr.s2_len);
|
||||
if (bytes_sent < 0) {
|
||||
mp_raise_BrokenPipeError();
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/wifi/__init__.h"
|
||||
#include "common-hal/socketpool/__init__.h"
|
||||
|
||||
#include "components/lwip/lwip/src/include/lwip/netdb.h"
|
||||
|
||||
|
|
@ -22,7 +23,7 @@ void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t *sel
|
|||
|
||||
// common_hal_socketpool_socket is in socketpool/Socket.c to centralize open socket tracking.
|
||||
|
||||
static int getaddrinfo_common(const char *host, int service, const struct addrinfo *hints, struct addrinfo **res) {
|
||||
int socketpool_getaddrinfo_common(const char *host, int service, const struct addrinfo *hints, struct addrinfo **res) {
|
||||
// As of 2022, the version of lwip in esp-idf does not handle the
|
||||
// trailing-dot syntax of domain names, so emulate it.
|
||||
// Remove this once https://github.com/espressif/esp-idf/issues/10013 has
|
||||
|
|
@ -67,7 +68,7 @@ mp_obj_t common_hal_socketpool_socketpool_gethostbyname(socketpool_socketpool_ob
|
|||
.ai_socktype = SOCK_STREAM,
|
||||
};
|
||||
struct addrinfo *res = NULL;
|
||||
int err = getaddrinfo_common(host, 0, &hints, &res);
|
||||
int err = socketpool_getaddrinfo_common(host, 0, &hints, &res);
|
||||
if (err != 0 || res == NULL) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
|
@ -121,7 +122,7 @@ mp_obj_t common_hal_socketpool_getaddrinfo_raise(socketpool_socketpool_obj_t *se
|
|||
};
|
||||
|
||||
struct addrinfo *res = NULL;
|
||||
int err = getaddrinfo_common(host, port, &hints, &res);
|
||||
int err = socketpool_getaddrinfo_common(host, port, &hints, &res);
|
||||
if (err != 0 || res == NULL) {
|
||||
common_hal_socketpool_socketpool_raise_gaierror_noname();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_SOCKETPOOL___INIT___H
|
||||
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_SOCKETPOOL___INIT___H
|
||||
struct addrinfo;
|
||||
|
||||
|
||||
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_SOCKETPOOL___INIT___H
|
||||
int socketpool_getaddrinfo_common(const char *host, int service, const struct addrinfo *hints, struct addrinfo **res);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include "common-hal/wifi/__init__.h"
|
||||
#include "shared/runtime/interrupt_char.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/ipaddress/IPv4Address.h"
|
||||
#include "shared-bindings/wifi/ScannedNetworks.h"
|
||||
|
|
@ -20,8 +21,14 @@
|
|||
#include "shared-bindings/time/__init__.h"
|
||||
#include "shared-module/ipaddress/__init__.h"
|
||||
|
||||
#include "components/esp_netif/include/esp_netif_net_stack.h"
|
||||
#include "components/esp_wifi/include/esp_wifi.h"
|
||||
#include "components/lwip/include/apps/ping/ping_sock.h"
|
||||
#include "lwip/sockets.h"
|
||||
|
||||
#if LWIP_IPV6_DHCP6
|
||||
#include "lwip/dhcp6.h"
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_MDNS
|
||||
#include "common-hal/mdns/Server.h"
|
||||
|
|
@ -445,6 +452,24 @@ mp_obj_t common_hal_wifi_radio_get_ipv4_subnet_ap(wifi_radio_obj_t *self) {
|
|||
return common_hal_ipaddress_new_ipv4address(self->ap_ip_info.netmask.addr);
|
||||
}
|
||||
|
||||
mp_obj_t common_hal_wifi_radio_get_ipv6_addresses(wifi_radio_obj_t *self) {
|
||||
if (!esp_netif_is_netif_up(self->netif)) {
|
||||
return mp_const_none;
|
||||
}
|
||||
esp_ip6_addr_t addresses[LWIP_IPV6_NUM_ADDRESSES];
|
||||
int n_addresses = esp_netif_get_all_ip6(self->netif, &addresses[0]);
|
||||
if (!n_addresses) {
|
||||
return mp_const_none;
|
||||
}
|
||||
mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_addresses, NULL));
|
||||
for (int i = 0; i < n_addresses; i++) {
|
||||
char buf[IP6ADDR_STRLEN_MAX];
|
||||
inet_ntop(AF_INET6, &addresses[i], buf, sizeof(buf));
|
||||
result->items[i] = mp_obj_new_str(buf, strlen(buf));
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(result);
|
||||
}
|
||||
|
||||
uint32_t wifi_radio_get_ipv4_address(wifi_radio_obj_t *self) {
|
||||
if (!esp_netif_is_netif_up(self->netif)) {
|
||||
return 0;
|
||||
|
|
@ -491,10 +516,17 @@ void common_hal_wifi_radio_set_ipv4_dns(wifi_radio_obj_t *self, mp_obj_t ipv4_dn
|
|||
|
||||
void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self) {
|
||||
esp_netif_dhcpc_start(self->netif);
|
||||
#if LWIP_IPV6_DHCP6
|
||||
esp_netif_create_ip6_linklocal(self->netif);
|
||||
dhcp6_enable_stateless(esp_netif_get_netif_impl(self->netif));
|
||||
#endif
|
||||
}
|
||||
|
||||
void common_hal_wifi_radio_stop_dhcp_client(wifi_radio_obj_t *self) {
|
||||
esp_netif_dhcpc_stop(self->netif);
|
||||
#if LWIP_IPV6_DHCP6
|
||||
dhcp6_disable(esp_netif_get_netif_impl(self->netif));
|
||||
#endif
|
||||
}
|
||||
|
||||
void common_hal_wifi_radio_start_dhcp_server(wifi_radio_obj_t *self) {
|
||||
|
|
|
|||
|
|
@ -596,6 +596,22 @@ static mp_obj_t wifi_radio_set_ipv4_address_ap(size_t n_args, const mp_obj_t *po
|
|||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_KW(wifi_radio_set_ipv4_address_ap_obj, 1, wifi_radio_set_ipv4_address_ap);
|
||||
|
||||
//| ipv6_addresses: Sequence[str]
|
||||
//| """IPv6 address(es) of the station when connected to an access point. None otherwise. (read-only)"""
|
||||
static mp_obj_t _wifi_radio_get_ipv6_addresses(mp_obj_t self) {
|
||||
return common_hal_wifi_radio_get_ipv6_addresses(self);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ipv6_addresses_obj, _wifi_radio_get_ipv6_addresses);
|
||||
|
||||
MP_PROPERTY_GETTER(wifi_radio_ipv6_addresses_obj,
|
||||
(mp_obj_t)&wifi_radio_get_ipv6_addresses_obj);
|
||||
|
||||
#if 0
|
||||
MP_WEAK mp_obj_t common_hal_wifi_radio_get_ipv6_addresses(wifi_radio_obj_t *self) {
|
||||
return mp_const_none;
|
||||
}
|
||||
#endif
|
||||
|
||||
//| ipv4_address: Optional[ipaddress.IPv4Address]
|
||||
//| """IP v4 Address of the station when connected to an access point. None otherwise. (read-only)"""
|
||||
static mp_obj_t _wifi_radio_get_ipv4_address(mp_obj_t self) {
|
||||
|
|
@ -768,6 +784,7 @@ static const mp_rom_map_elem_t wifi_radio_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_ipv4_subnet_ap), MP_ROM_PTR(&wifi_radio_ipv4_subnet_ap_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ipv4_address), MP_ROM_PTR(&wifi_radio_ipv4_address_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ipv4_address_ap), MP_ROM_PTR(&wifi_radio_ipv4_address_ap_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ipv6_addresses), MP_ROM_PTR(&wifi_radio_ipv6_addresses_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_ipv4_address), MP_ROM_PTR(&wifi_radio_set_ipv4_address_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_ipv4_address_ap), MP_ROM_PTR(&wifi_radio_set_ipv4_address_ap_obj) },
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@ uint32_t wifi_radio_get_ipv4_address(wifi_radio_obj_t *self);
|
|||
extern mp_obj_t common_hal_wifi_radio_get_ipv4_address(wifi_radio_obj_t *self);
|
||||
extern mp_obj_t common_hal_wifi_radio_get_ipv4_address_ap(wifi_radio_obj_t *self);
|
||||
|
||||
mp_obj_t common_hal_wifi_radio_get_ipv6_addresses(wifi_radio_obj_t *self);
|
||||
|
||||
extern void common_hal_wifi_radio_set_ipv4_address(wifi_radio_obj_t *self, mp_obj_t ipv4, mp_obj_t netmask, mp_obj_t gateway, mp_obj_t ipv4_dns_addr);
|
||||
extern void common_hal_wifi_radio_set_ipv4_address_ap(wifi_radio_obj_t *self, mp_obj_t ipv4, mp_obj_t netmask, mp_obj_t gateway);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue