samples: net: echo-client: Check IPv6 address deprecation
If the IPv6 address that our socket is bound to deprecates, then re-create the socket so that we avoid using deprecated IPv6 address. Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
This commit is contained in:
parent
e2792c6509
commit
3046e95d85
3 changed files with 164 additions and 14 deletions
|
|
@ -24,6 +24,8 @@ LOG_MODULE_REGISTER(net_echo_client_sample, LOG_LEVEL_DBG);
|
|||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <zephyr/posix/sys/eventfd.h>
|
||||
|
||||
#include <zephyr/net/socket.h>
|
||||
#include <zephyr/net/tls_credentials.h>
|
||||
|
||||
|
|
@ -46,6 +48,8 @@ struct k_mem_domain app_domain;
|
|||
|
||||
#define EVENT_MASK (NET_EVENT_L4_CONNECTED | \
|
||||
NET_EVENT_L4_DISCONNECTED)
|
||||
#define IPV6_EVENT_MASK (NET_EVENT_IPV6_ADDR_ADD | \
|
||||
NET_EVENT_IPV6_ADDR_DEPRECATED)
|
||||
|
||||
/* Generated by http://www.lipsum.com/
|
||||
* 2 paragraphs, 179 words, 1160 bytes of Lorem Ipsum
|
||||
|
|
@ -87,16 +91,26 @@ APP_DMEM struct configs conf = {
|
|||
},
|
||||
};
|
||||
|
||||
static APP_BMEM struct pollfd fds[4];
|
||||
static APP_BMEM struct pollfd fds[1 + 4];
|
||||
static APP_BMEM int nfds;
|
||||
|
||||
static APP_BMEM bool connected;
|
||||
static APP_BMEM bool need_restart;
|
||||
|
||||
K_SEM_DEFINE(run_app, 0, 1);
|
||||
|
||||
static struct net_mgmt_event_callback mgmt_cb;
|
||||
static struct net_mgmt_event_callback ipv6_mgmt_cb;
|
||||
|
||||
static void prepare_fds(void)
|
||||
{
|
||||
nfds = 0;
|
||||
|
||||
/* eventfd is used to trigger restart */
|
||||
fds[nfds].fd = eventfd(0, 0);
|
||||
fds[nfds].events = POLLIN;
|
||||
nfds++;
|
||||
|
||||
if (conf.ipv4.udp.sock >= 0) {
|
||||
fds[nfds].fd = conf.ipv4.udp.sock;
|
||||
fds[nfds].events = POLLIN;
|
||||
|
|
@ -124,11 +138,29 @@ static void prepare_fds(void)
|
|||
|
||||
static void wait(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Wait for event on any socket used. Once event occurs,
|
||||
* we'll check them all.
|
||||
*/
|
||||
if (poll(fds, nfds, -1) < 0) {
|
||||
LOG_ERR("Error in poll:%d", errno);
|
||||
ret = poll(fds, nfds, -1);
|
||||
if (ret < 0) {
|
||||
static bool once;
|
||||
|
||||
if (!once) {
|
||||
once = true;
|
||||
LOG_ERR("Error in poll:%d", errno);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (ret > 0 && fds[0].revents) {
|
||||
eventfd_t value;
|
||||
|
||||
eventfd_read(fds[0].fd, &value);
|
||||
LOG_DBG("Received restart event.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -193,6 +225,99 @@ static void stop_udp_and_tcp(void)
|
|||
}
|
||||
}
|
||||
|
||||
static int check_our_ipv6_sockets(int sock,
|
||||
struct in6_addr *deprecated_addr)
|
||||
{
|
||||
struct sockaddr_in6 addr = { 0 };
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
int ret;
|
||||
|
||||
if (sock < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = getsockname(sock, (struct sockaddr *)&addr, &addrlen);
|
||||
if (ret != 0) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (!net_ipv6_addr_cmp(deprecated_addr, &addr.sin6_addr)) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
need_restart = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ipv6_event_handler(struct net_mgmt_event_callback *cb,
|
||||
uint32_t mgmt_event, struct net_if *iface)
|
||||
{
|
||||
static char addr_str[INET6_ADDRSTRLEN];
|
||||
|
||||
if (!IS_ENABLED(CONFIG_NET_IPV6_PE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((mgmt_event & IPV6_EVENT_MASK) != mgmt_event) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cb->info == NULL ||
|
||||
cb->info_length != sizeof(struct in6_addr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mgmt_event == NET_EVENT_IPV6_ADDR_ADD) {
|
||||
struct net_if_addr *ifaddr;
|
||||
struct in6_addr added_addr;
|
||||
|
||||
memcpy(&added_addr, cb->info, sizeof(struct in6_addr));
|
||||
|
||||
ifaddr = net_if_ipv6_addr_lookup(&added_addr, &iface);
|
||||
if (ifaddr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Wait until we get a temporary address before continuing after
|
||||
* boot.
|
||||
*/
|
||||
if (ifaddr->is_temporary) {
|
||||
static bool once;
|
||||
|
||||
LOG_INF("Temporary IPv6 address %s added",
|
||||
inet_ntop(AF_INET6, &added_addr, addr_str,
|
||||
sizeof(addr_str) - 1));
|
||||
|
||||
if (!once) {
|
||||
k_sem_give(&run_app);
|
||||
once = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mgmt_event == NET_EVENT_IPV6_ADDR_DEPRECATED) {
|
||||
struct in6_addr deprecated_addr;
|
||||
|
||||
memcpy(&deprecated_addr, cb->info, sizeof(struct in6_addr));
|
||||
|
||||
LOG_INF("IPv6 address %s deprecated",
|
||||
inet_ntop(AF_INET6, &deprecated_addr, addr_str,
|
||||
sizeof(addr_str) - 1));
|
||||
|
||||
(void)check_our_ipv6_sockets(conf.ipv6.tcp.sock,
|
||||
&deprecated_addr);
|
||||
(void)check_our_ipv6_sockets(conf.ipv6.udp.sock,
|
||||
&deprecated_addr);
|
||||
|
||||
if (need_restart) {
|
||||
eventfd_write(fds[0].fd, 1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void event_handler(struct net_mgmt_event_callback *cb,
|
||||
uint32_t mgmt_event, struct net_if *iface)
|
||||
{
|
||||
|
|
@ -206,7 +331,10 @@ static void event_handler(struct net_mgmt_event_callback *cb,
|
|||
connected = true;
|
||||
conf.ipv4.udp.mtu = net_if_get_mtu(iface);
|
||||
conf.ipv6.udp.mtu = conf.ipv4.udp.mtu;
|
||||
k_sem_give(&run_app);
|
||||
|
||||
if (!IS_ENABLED(CONFIG_NET_IPV6_PE)) {
|
||||
k_sem_give(&run_app);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -275,6 +403,10 @@ static void init_app(void)
|
|||
conn_mgr_mon_resend_status();
|
||||
}
|
||||
|
||||
net_mgmt_init_event_callback(&ipv6_mgmt_cb,
|
||||
ipv6_event_handler, IPV6_EVENT_MASK);
|
||||
net_mgmt_add_event_callback(&ipv6_mgmt_cb);
|
||||
|
||||
init_vlan();
|
||||
init_udp();
|
||||
}
|
||||
|
|
@ -293,19 +425,35 @@ static void start_client(void *p1, void *p2, void *p3)
|
|||
/* Wait for the connection. */
|
||||
k_sem_take(&run_app, K_FOREVER);
|
||||
|
||||
ret = start_udp_and_tcp();
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6_PE)) {
|
||||
/* Make sure that we have a temporary address */
|
||||
k_sleep(K_SECONDS(1));
|
||||
}
|
||||
|
||||
while (connected && (ret == 0)) {
|
||||
ret = run_udp_and_tcp();
|
||||
do {
|
||||
if (need_restart) {
|
||||
/* Close all sockets and get a fresh restart */
|
||||
stop_udp_and_tcp();
|
||||
need_restart = false;
|
||||
}
|
||||
|
||||
if (iterations > 0) {
|
||||
i++;
|
||||
if (i >= iterations) {
|
||||
ret = start_udp_and_tcp();
|
||||
|
||||
while (connected && (ret == 0)) {
|
||||
ret = run_udp_and_tcp();
|
||||
|
||||
if (iterations > 0) {
|
||||
i++;
|
||||
if (i >= iterations) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (need_restart) {
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (need_restart);
|
||||
|
||||
stop_udp_and_tcp();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -239,7 +239,8 @@ int start_tcp(void)
|
|||
inet_pton(AF_INET6, CONFIG_NET_CONFIG_PEER_IPV6_ADDR,
|
||||
&addr6.sin6_addr);
|
||||
|
||||
ret = start_tcp_proto(&conf.ipv6, (struct sockaddr *)&addr6,
|
||||
ret = start_tcp_proto(&conf.ipv6,
|
||||
(struct sockaddr *)&addr6,
|
||||
sizeof(addr6));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -308,7 +308,8 @@ int start_udp(void)
|
|||
inet_pton(AF_INET6, CONFIG_NET_CONFIG_PEER_IPV6_ADDR,
|
||||
&addr6.sin6_addr);
|
||||
|
||||
ret = start_udp_proto(&conf.ipv6, (struct sockaddr *)&addr6,
|
||||
ret = start_udp_proto(&conf.ipv6,
|
||||
(struct sockaddr *)&addr6,
|
||||
sizeof(addr6));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
|
|
|||
Loading…
Reference in a new issue