Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | /* * Copyright (c) 2019 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ #include <zephyr/logging/log.h> LOG_MODULE_REGISTER(net_mgmt_sock_sample, LOG_LEVEL_DBG); #include <zephyr/kernel.h> #include <errno.h> #include <stdio.h> #include <zephyr/net/socket.h> #include <zephyr/net/socket_net_mgmt.h> #include <zephyr/net/net_if.h> #define MAX_BUF_LEN 64 #define STACK_SIZE 1024 #if defined(CONFIG_NET_TC_THREAD_COOPERATIVE) #define THREAD_PRIORITY K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1) #else #define THREAD_PRIORITY K_PRIO_PREEMPT(8) #endif /* A test thread that spits out events that we can catch and show to user */ static void trigger_events(void) { int operation = 0; struct net_if_addr *ifaddr_v6; struct net_if *iface; struct in6_addr addr_v6; int ret; iface = net_if_get_default(); net_ipv6_addr_create(&addr_v6, 0x2001, 0x0db8, 0, 0, 0, 0, 0, 0x0003); while (1) { switch (operation) { case 0: ifaddr_v6 = net_if_ipv6_addr_add(iface, &addr_v6, NET_ADDR_MANUAL, 0); if (!ifaddr_v6) { LOG_ERR("Cannot add IPv%c address", '6'); break; } break; case 1: ret = net_if_ipv6_addr_rm(iface, &addr_v6); if (!ret) { LOG_ERR("Cannot del IPv%c address", '6'); break; } break; default: operation = -1; break; } operation++; k_sleep(K_SECONDS(1)); } } K_THREAD_DEFINE(trigger_events_thread_id, STACK_SIZE, trigger_events, NULL, NULL, NULL, THREAD_PRIORITY, 0, -1); static char *get_ip_addr(char *ipaddr, size_t len, sa_family_t family, struct net_mgmt_msghdr *hdr) { char *buf; buf = net_addr_ntop(family, hdr->nm_msg, ipaddr, len); if (!buf) { return "?"; } return buf; } static void listener(void) { struct sockaddr_nm sockaddr; struct sockaddr_nm event_addr; socklen_t event_addr_len; char ipaddr[INET6_ADDRSTRLEN]; uint8_t buf[MAX_BUF_LEN]; int fd, ret; fd = socket(AF_NET_MGMT, SOCK_DGRAM, NET_MGMT_EVENT_PROTO); if (fd < 0) { printk("Cannot create net_mgmt socket (%d)\n", errno); exit(1); } memset(&sockaddr, 0, sizeof(sockaddr)); sockaddr.nm_family = AF_NET_MGMT; sockaddr.nm_ifindex = 0; /* Any network interface */ sockaddr.nm_pid = (uintptr_t)k_current_get(); sockaddr.nm_mask = NET_EVENT_IPV6_DAD_SUCCEED | NET_EVENT_IPV6_ADDR_ADD | NET_EVENT_IPV6_ADDR_DEL; ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)); if (ret < 0) { printk("Cannot bind net_mgmt socket (%d)\n", errno); exit(1); } while (1) { struct net_mgmt_msghdr *hdr; memset(buf, 0, sizeof(buf)); event_addr_len = sizeof(event_addr); ret = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&event_addr, &event_addr_len); if (ret < 0) { continue; } hdr = (struct net_mgmt_msghdr *)buf; if (hdr->nm_msg_version != NET_MGMT_SOCKET_VERSION_1) { /* Do not know how to parse the message */ continue; } switch (event_addr.nm_mask) { case NET_EVENT_IPV6_DAD_SUCCEED: printk("DAD succeed for interface %d (%s)\n", event_addr.nm_ifindex, get_ip_addr(ipaddr, sizeof(ipaddr), AF_INET6, hdr)); break; case NET_EVENT_IPV6_ADDR_ADD: printk("IPv6 address added to interface %d (%s)\n", event_addr.nm_ifindex, get_ip_addr(ipaddr, sizeof(ipaddr), AF_INET6, hdr)); break; case NET_EVENT_IPV6_ADDR_DEL: printk("IPv6 address removed from interface %d (%s)\n", event_addr.nm_ifindex, get_ip_addr(ipaddr, sizeof(ipaddr), AF_INET6, hdr)); break; } } } int main(void) { /* The thread start to trigger network management events that * we then can catch. */ k_thread_start(trigger_events_thread_id); if (IS_ENABLED(CONFIG_USERSPACE)) { k_thread_user_mode_enter((k_thread_entry_t)listener, NULL, NULL, NULL); } else { listener(); } return 0; } |