Skip to content

Commit 1b0f0d6

Browse files
committed
extmod/network: Implement IPv6 API to set and get nic configuration.
Signed-off-by: Felix Dörre <felix@dogcraft.de>
1 parent def6ad4 commit 1b0f0d6

File tree

3 files changed

+263
-1
lines changed

3 files changed

+263
-1
lines changed

extmod/modlwip.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1711,6 +1711,10 @@ STATIC void lwip_getaddrinfo_cb(const char *name, const ip_addr_t *ipaddr, void
17111711
}
17121712
}
17131713

1714+
#if LWIP_VERSION_MAJOR >= 2
1715+
extern int mp_mod_network_prefered_dns_ip;
1716+
#endif
1717+
17141718
// lwip.getaddrinfo
17151719
STATIC mp_obj_t lwip_getaddrinfo(size_t n_args, const mp_obj_t *args) {
17161720
mp_obj_t host_in = args[0], port_in = args[1];
@@ -1744,7 +1748,11 @@ STATIC mp_obj_t lwip_getaddrinfo(size_t n_args, const mp_obj_t *args) {
17441748
state.status = 0;
17451749

17461750
MICROPY_PY_LWIP_ENTER
1751+
#if LWIP_VERSION_MAJOR < 2
17471752
err_t ret = dns_gethostbyname(host, (ip_addr_t *)&state.ipaddr, lwip_getaddrinfo_cb, &state);
1753+
#else
1754+
err_t ret = dns_gethostbyname_addrtype(host, (ip_addr_t *)&state.ipaddr, lwip_getaddrinfo_cb, &state, mp_mod_network_prefered_dns_ip == 4 ? LWIP_DNS_ADDRTYPE_IPV4_IPV6 : LWIP_DNS_ADDRTYPE_IPV6_IPV4);
1755+
#endif
17481756
MICROPY_PY_LWIP_EXIT
17491757

17501758
switch (ret) {

extmod/network_cyw43.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,13 @@ STATIC mp_obj_t network_cyw43_ifconfig(size_t n_args, const mp_obj_t *args) {
321321
}
322322
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_cyw43_ifconfig_obj, 1, 2, network_cyw43_ifconfig);
323323

324+
mp_obj_t network_nic_config(struct netif *netif, size_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
325+
STATIC mp_obj_t network_cyw43_ipconfig(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
326+
network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]);
327+
return network_nic_config(&self->cyw->netif[self->itf], n_args - 1, args + 1, kwargs);
328+
}
329+
MP_DEFINE_CONST_FUN_OBJ_KW(network_cyw43_ipconfig_obj, 1, network_cyw43_ipconfig);
330+
324331
STATIC mp_obj_t network_cyw43_status(size_t n_args, const mp_obj_t *args) {
325332
network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]);
326333
(void)self;
@@ -535,6 +542,8 @@ STATIC const mp_rom_map_elem_t network_cyw43_locals_dict_table[] = {
535542
{ MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&network_cyw43_status_obj) },
536543
{ MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_cyw43_config_obj) },
537544

545+
{ MP_ROM_QSTR(MP_QSTR_ipconfig), MP_ROM_PTR(&network_cyw43_ipconfig_obj) },
546+
538547
// Class constants.
539548
{ MP_ROM_QSTR(MP_QSTR_PM_NONE), MP_ROM_INT(PM_NONE) },
540549
{ MP_ROM_QSTR(MP_QSTR_PM_PERFORMANCE), MP_ROM_INT(PM_PERFORMANCE) },

extmod/network_lwip.c

Lines changed: 246 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
#include "py/runtime.h"
2828
#include "py/mphal.h"
29-
29+
#include "py/parsenum.h"
3030
#if MICROPY_PY_NETWORK && MICROPY_PY_LWIP
3131

3232
#include "shared/netutils/netutils.h"
@@ -40,6 +40,16 @@
4040
#include "lwip/timeouts.h"
4141
#include "lwip/dns.h"
4242
#include "lwip/dhcp.h"
43+
#include "lwip/nd6.h"
44+
#include "lwip/dhcp6.h"
45+
#include "lwip/prot/dhcp.h"
46+
#include "lwip/prot/dhcp6.h"
47+
#include <string.h>
48+
#include <stdlib.h>
49+
50+
#if LWIP_VERSION_MAJOR >= 2
51+
int mp_mod_network_prefered_dns_ip = 4;
52+
#endif
4353

4454
// Implementations of network methods that can be used by any interface.
4555

@@ -90,6 +100,241 @@ mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_o
90100
}
91101
}
92102

103+
mp_obj_t network_nic_config(struct netif *netif, size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
104+
105+
if (kwargs->used == 0) {
106+
// Get config value
107+
if (n_args != 1) {
108+
mp_raise_TypeError(MP_ERROR_TEXT("must query one param"));
109+
}
110+
111+
switch (mp_obj_str_get_qstr(args[0])) {
112+
case MP_QSTR_dhcp4: {
113+
struct dhcp *dhcp = netif_dhcp_data(netif);
114+
return dhcp != NULL && dhcp->state != DHCP_STATE_OFF ? mp_const_true : mp_const_false;
115+
}
116+
#if LWIP_IPV6_DHCP6
117+
case MP_QSTR_dhcp6: {
118+
struct dhcp6 *dhcp = netif_dhcp6_data(netif);
119+
return dhcp != NULL && dhcp->state != DHCP6_STATE_OFF ? mp_const_true : mp_const_false;
120+
}
121+
#endif
122+
#if LWIP_IPV6_AUTOCONFIG
123+
case MP_QSTR_autoconf6: {
124+
return netif->ip6_autoconfig_enabled ? mp_const_true : mp_const_false;
125+
}
126+
#endif
127+
case MP_QSTR_dns: {
128+
const char *addr_str = ipaddr_ntoa(dns_getserver(0));
129+
return mp_obj_new_str(addr_str, strlen(addr_str));
130+
}
131+
#if LWIP_VERSION_MAJOR >= 2
132+
case MP_QSTR_prefer: {
133+
return MP_OBJ_NEW_SMALL_INT(mp_mod_network_prefered_dns_ip);
134+
}
135+
#endif
136+
case MP_QSTR_addr4: {
137+
mp_obj_t tuple[2] = {
138+
netutils_format_ipv4_addr((uint8_t *)&netif->ip_addr, NETUTILS_BIG),
139+
netutils_format_ipv4_addr((uint8_t *)&netif->netmask, NETUTILS_BIG),
140+
};
141+
return mp_obj_new_tuple(2, tuple);
142+
}
143+
#if LWIP_IPV6
144+
case MP_QSTR_addr6: {
145+
mp_obj_t addrs[LWIP_IPV6_NUM_ADDRESSES];
146+
size_t n_addrs = 0;
147+
for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
148+
if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
149+
const char *addr_str = ipaddr_ntoa(netif_ip_addr6(netif, i));
150+
mp_obj_t tuple[4] = {
151+
mp_obj_new_str(addr_str, strlen(addr_str)),
152+
MP_OBJ_NEW_SMALL_INT(netif_ip6_addr_state(netif, i)),
153+
MP_OBJ_NEW_SMALL_INT(netif_ip6_addr_pref_life(netif, i)), // preferred
154+
MP_OBJ_NEW_SMALL_INT(netif_ip6_addr_valid_life(netif, i))
155+
};
156+
addrs[n_addrs++] = mp_obj_new_tuple(4, tuple);
157+
}
158+
}
159+
return mp_obj_new_list(n_addrs, addrs);
160+
}
161+
#endif
162+
case MP_QSTR_gw4: {
163+
return netutils_format_ipv4_addr((uint8_t *)&netif->gw, NETUTILS_BIG);
164+
}
165+
default: {
166+
mp_raise_ValueError(MP_ERROR_TEXT("unexpected key"));
167+
break;
168+
}
169+
}
170+
return mp_const_none;
171+
} else {
172+
// Set config value(s)
173+
if (n_args != 0) {
174+
mp_raise_TypeError(MP_ERROR_TEXT("can't specify pos and kw args"));
175+
}
176+
177+
for (size_t i = 0; i < kwargs->alloc; ++i) {
178+
if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) {
179+
mp_map_elem_t *e = &kwargs->table[i];
180+
switch (mp_obj_str_get_qstr(e->key)) {
181+
case MP_QSTR_dhcp4: {
182+
if (e->value == mp_const_true) {
183+
if (dhcp_supplied_address(netif)) {
184+
dhcp_renew(netif);
185+
} else {
186+
dhcp_release_and_stop(netif);
187+
dhcp_start(netif);
188+
}
189+
uint32_t start = mp_hal_ticks_ms();
190+
while (!dhcp_supplied_address(netif)) {
191+
if (mp_hal_ticks_ms() - start > 10000) {
192+
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("timeout waiting for DHCP to get IP address"));
193+
}
194+
mp_hal_delay_ms(100);
195+
}
196+
} else {
197+
dhcp_release_and_stop(netif);
198+
}
199+
break;
200+
}
201+
#if LWIP_IPV6_DHCP6
202+
case MP_QSTR_dhcp6: {
203+
dhcp6_disable(netif);
204+
dhcp6_enable_stateless(netif);
205+
break;
206+
}
207+
#endif
208+
#if LWIP_IPV6_AUTOCONFIG
209+
case MP_QSTR_autoconf6: {
210+
netif_set_ip6_autoconfig_enabled(netif, e->value == mp_const_true);
211+
if (e->value == mp_const_true) {
212+
nd6_restart_netif(netif);
213+
uint32_t start = mp_hal_ticks_ms();
214+
while (1) {
215+
int found = 0;
216+
for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
217+
if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
218+
!netif_ip6_addr_isstatic(netif, i)) {
219+
found = 1;
220+
break;
221+
}
222+
}
223+
if (found) {
224+
break;
225+
}
226+
if (mp_hal_ticks_ms() - start > 10000) {
227+
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("timeout waiting for DHCP to get IP address"));
228+
}
229+
mp_hal_delay_ms(100);
230+
}
231+
} else {
232+
// Skip link-local address in slot 0
233+
for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
234+
if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
235+
!netif_ip6_addr_isstatic(netif, i)) {
236+
netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID);
237+
}
238+
}
239+
}
240+
break;
241+
}
242+
#endif
243+
case MP_QSTR_dns: {
244+
ip_addr_t dns;
245+
size_t addr_len;
246+
const char *addr_str = mp_obj_str_get_data(e->value, &addr_len);
247+
if (!ipaddr_aton(addr_str, &dns)) {
248+
mp_raise_ValueError(MP_ERROR_TEXT("invalid arguments as dns server"));
249+
}
250+
dns_setserver(0, &dns);
251+
break;
252+
}
253+
#if LWIP_VERSION_MAJOR >= 2
254+
case MP_QSTR_prefer: {
255+
int value = mp_obj_get_int(e->value);
256+
if (value != 4 && value != 6) {
257+
mp_raise_ValueError(MP_ERROR_TEXT("invalid prefer argument"));
258+
}
259+
mp_mod_network_prefered_dns_ip = value;
260+
break;
261+
}
262+
#endif
263+
case MP_QSTR_addr4:
264+
case MP_QSTR_addr6: {
265+
ip_addr_t ip_addr;
266+
int prefix = 32;
267+
if (e->value != mp_const_none) {
268+
size_t addr_len;
269+
const char *addr_str = mp_obj_str_get_data(e->value, &addr_len);
270+
char *split = strchr(addr_str, '/');
271+
if (split) {
272+
*split = 0;
273+
mp_obj_t prefix_obj = mp_parse_num_integer(split + 1, strlen(split + 1), 10, NULL);
274+
prefix = mp_obj_get_int(prefix_obj);
275+
}
276+
if (!ipaddr_aton(addr_str, &ip_addr)) {
277+
mp_raise_ValueError(MP_ERROR_TEXT("invalid arguments"));
278+
}
279+
if ((mp_obj_str_get_qstr(args[0]) == MP_QSTR_addr6) != IP_IS_V6(&ip_addr)
280+
|| (mp_obj_str_get_qstr(args[0]) == MP_QSTR_addr4) != IP_IS_V4(&ip_addr)) {
281+
mp_raise_ValueError(MP_ERROR_TEXT("invalid address type"));
282+
}
283+
}
284+
if (mp_obj_str_get_qstr(args[0]) == MP_QSTR_addr4) {
285+
if (e->value != mp_const_none) {
286+
netif->ip_addr = ip_addr;
287+
uint32_t mask = -(1u << (32 - prefix));
288+
ip_addr_set_ip4_u32_val(netif->netmask, ((mask & 0xFF) << 24) | ((mask & 0xFF00) << 8) | ((mask >> 8) & 0xFF00) | ((mask >> 24) & 0xFF));
289+
} else {
290+
ip4_addr_set_any(ip_2_ip4(&netif->ip_addr));
291+
}
292+
#if LWIP_IPV6
293+
} else if (mp_obj_str_get_qstr(args[0]) == MP_QSTR_addr6) {
294+
for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
295+
if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
296+
netif_ip6_addr_isstatic(netif, i)) {
297+
netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID);
298+
}
299+
}
300+
if (e->value != mp_const_none) {
301+
s8_t free_idx;
302+
netif_add_ip6_address(netif, ip_2_ip6(&ip_addr), &free_idx);
303+
netif_ip6_addr_set_valid_life(netif, free_idx, IP6_ADDR_LIFE_STATIC);
304+
netif_ip6_addr_set_pref_life(netif, free_idx, IP6_ADDR_LIFE_STATIC);
305+
netif_ip6_addr_set_state(netif, free_idx, IP6_ADDR_PREFERRED);
306+
}
307+
#endif
308+
}
309+
break;
310+
}
311+
case MP_QSTR_gw4: {
312+
ip_addr_t ip_addr;
313+
size_t addr_len;
314+
const char *addr_str = mp_obj_str_get_data(e->value, &addr_len);
315+
if (!ipaddr_aton(addr_str, &ip_addr)) {
316+
mp_raise_ValueError(MP_ERROR_TEXT("invalid arguments"));
317+
}
318+
if (IP_IS_V4(&ip_addr)) {
319+
netif->gw = ip_addr;
320+
} else {
321+
mp_raise_ValueError(MP_ERROR_TEXT("invalid address type"));
322+
}
323+
break;
324+
}
325+
default: {
326+
mp_raise_ValueError(MP_ERROR_TEXT("unexpected key"));
327+
break;
328+
}
329+
}
330+
}
331+
}
332+
}
333+
return mp_const_none;
334+
}
335+
336+
337+
93338
#endif // LWIP_VERSION_MAJOR >= 2
94339

95340
#endif // MICROPY_PY_NETWORK && MICROPY_PY_LWIP

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy