1 /* main.c - Application main entry point */
2
3 /*
4 * Copyright (c) 2019 Intel Corporation
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #define NET_LOG_LEVEL CONFIG_NET_HOSTNAME_LOG_LEVEL
10
11 #include <zephyr/logging/log.h>
12 LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL);
13
14 #include <zephyr/types.h>
15 #include <stdbool.h>
16 #include <stddef.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <zephyr/random/random.h>
20 #include <zephyr/sys/printk.h>
21 #include <zephyr/linker/sections.h>
22
23 #include <zephyr/ztest.h>
24
25 #include <zephyr/net/ethernet.h>
26 #include <zephyr/net_buf.h>
27 #include <zephyr/net/net_ip.h>
28 #include <zephyr/net/net_if.h>
29
30 #define NET_LOG_ENABLED 1
31 #include "net_private.h"
32
33 #if defined(CONFIG_NET_HOSTNAME_LOG_LEVEL_DBG)
34 #define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
35 #else
36 #define DBG(fmt, ...)
37 #endif
38
39 /* Interface 1 addresses */
40 static struct in6_addr my_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0,
41 0, 0, 0, 0, 0, 0, 0, 0x1 } } };
42 static struct in_addr my_ipv4_addr1 = { { { 192, 0, 2, 1 } } };
43
44 /* Extra address is assigned to ll_addr */
45 static struct in6_addr ll_addr = { { { 0xfe, 0x80, 0x43, 0xb8, 0, 0, 0, 0,
46 0, 0, 0, 0xf2, 0xaa, 0x29, 0x02,
47 0x04 } } };
48
49 static struct in6_addr in6addr_mcast = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
50 0, 0, 0, 0, 0, 0, 0, 0x1 } } };
51
52 static struct net_if *iface1;
53
54 static bool test_started;
55 static struct k_sem wait_data;
56
57 #ifdef CONFIG_NET_MGMT_EVENT
58 static struct k_sem wait_hostname;
59 static struct net_mgmt_event_callback hostname_cb;
60 #endif
61
62 #define WAIT_TIME 250
63
64 #define EVENT_HANDLER_INIT_PRIO 55
65
66 BUILD_ASSERT(EVENT_HANDLER_INIT_PRIO < CONFIG_NET_INIT_PRIO);
67
68 struct net_if_test {
69 uint8_t idx;
70 uint8_t mac_addr[sizeof(struct net_eth_addr)];
71 struct net_linkaddr ll_addr;
72 };
73
net_iface_get_mac(const struct device * dev)74 static uint8_t *net_iface_get_mac(const struct device *dev)
75 {
76 struct net_if_test *data = dev->data;
77
78 if (data->mac_addr[2] == 0x00) {
79 /* 00-00-5E-00-53-xx Documentation RFC 7042 */
80 data->mac_addr[0] = 0x00;
81 data->mac_addr[1] = 0x00;
82 data->mac_addr[2] = 0x5E;
83 data->mac_addr[3] = 0x00;
84 data->mac_addr[4] = 0x53;
85 data->mac_addr[5] = sys_rand8_get();
86 }
87
88 data->ll_addr.addr = data->mac_addr;
89 data->ll_addr.len = 6U;
90
91 return data->mac_addr;
92 }
93
net_iface_init(struct net_if * iface)94 static void net_iface_init(struct net_if *iface)
95 {
96 uint8_t *mac = net_iface_get_mac(net_if_get_device(iface));
97
98 net_if_set_link_addr(iface, mac, sizeof(struct net_eth_addr),
99 NET_LINK_ETHERNET);
100 }
101
102 #ifdef CONFIG_NET_MGMT_EVENT
hostname_changed(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)103 static void hostname_changed(struct net_mgmt_event_callback *cb,
104 uint32_t mgmt_event, struct net_if *iface)
105 {
106 if (mgmt_event == NET_EVENT_HOSTNAME_CHANGED) {
107 #ifdef CONFIG_NET_MGMT_EVENT_INFO
108 const struct net_event_l4_hostname *info = cb->info;
109
110 if (strncmp(net_hostname_get(), info->hostname, sizeof(info->hostname))) {
111 /** Invalid value - do not give the semaphore **/
112 return;
113 }
114 #endif
115 k_sem_give(&wait_hostname);
116 }
117 }
118 #endif
119
sender_iface(const struct device * dev,struct net_pkt * pkt)120 static int sender_iface(const struct device *dev, struct net_pkt *pkt)
121 {
122 if (!pkt->buffer) {
123 DBG("No data to send!\n");
124 return -ENODATA;
125 }
126
127 k_sem_give(&wait_data);
128
129 return 0;
130 }
131
132 struct net_if_test net_iface1_data;
133
134 static struct ethernet_api net_iface_api = {
135 .iface_api.init = net_iface_init,
136 .send = sender_iface,
137 };
138
139 #define _ETH_L2_LAYER ETHERNET_L2
140 #define _ETH_L2_CTX_TYPE NET_L2_GET_CTX_TYPE(ETHERNET_L2)
141
142 NET_DEVICE_INIT_INSTANCE(net_iface1_test,
143 "iface1",
144 iface1,
145 NULL,
146 NULL,
147 &net_iface1_data,
148 NULL,
149 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
150 &net_iface_api,
151 _ETH_L2_LAYER,
152 _ETH_L2_CTX_TYPE,
153 127);
154
155 struct eth_fake_context {
156 struct net_if *iface;
157 uint8_t mac_address[6];
158 bool promisc_mode;
159 };
160
161 static struct eth_fake_context eth_fake_data;
162
eth_fake_iface_init(struct net_if * iface)163 static void eth_fake_iface_init(struct net_if *iface)
164 {
165 const struct device *dev = net_if_get_device(iface);
166 struct eth_fake_context *ctx = dev->data;
167
168 ctx->iface = iface;
169
170 /* 00-00-5E-00-53-xx Documentation RFC 7042 */
171 ctx->mac_address[0] = 0x00;
172 ctx->mac_address[1] = 0x00;
173 ctx->mac_address[2] = 0x5E;
174 ctx->mac_address[3] = 0x00;
175 ctx->mac_address[4] = 0x53;
176 ctx->mac_address[5] = sys_rand8_get();
177
178 net_if_set_link_addr(iface, ctx->mac_address,
179 sizeof(ctx->mac_address),
180 NET_LINK_ETHERNET);
181
182 ethernet_init(iface);
183 }
184
eth_fake_send(const struct device * dev,struct net_pkt * pkt)185 static int eth_fake_send(const struct device *dev,
186 struct net_pkt *pkt)
187 {
188 ARG_UNUSED(dev);
189 ARG_UNUSED(pkt);
190
191 return 0;
192 }
193
194 static struct ethernet_api eth_fake_api_funcs = {
195 .iface_api.init = eth_fake_iface_init,
196 .send = eth_fake_send,
197 };
198
eth_fake_init(const struct device * dev)199 static int eth_fake_init(const struct device *dev)
200 {
201 struct eth_fake_context *ctx = dev->data;
202
203 ctx->promisc_mode = false;
204
205 return 0;
206 }
207
208 ETH_NET_DEVICE_INIT(eth_fake, "eth_fake", eth_fake_init, NULL,
209 ð_fake_data, NULL, CONFIG_ETH_INIT_PRIORITY,
210 ð_fake_api_funcs, NET_ETH_MTU);
211
212 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
iface2str(struct net_if * iface)213 static const char *iface2str(struct net_if *iface)
214 {
215 if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
216 return "Ethernet";
217 }
218
219 return "<unknown type>";
220 }
221 #endif
222
iface_cb(struct net_if * iface,void * user_data)223 static void iface_cb(struct net_if *iface, void *user_data)
224 {
225 static int if_count;
226
227 DBG("Interface %p (%s) [%d]\n", iface, iface2str(iface),
228 net_if_get_by_iface(iface));
229
230 if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
231 switch (if_count) {
232 case 0:
233 iface1 = iface;
234 break;
235 }
236
237 if_count++;
238 }
239 }
240
test_iface_setup(void)241 static void *test_iface_setup(void)
242 {
243 struct net_if_mcast_addr *maddr;
244 struct net_if_addr *ifaddr;
245 int idx;
246
247 /* The semaphore is there to wait the data to be received. */
248 k_sem_init(&wait_data, 0, UINT_MAX);
249
250 net_if_foreach(iface_cb, NULL);
251
252 idx = net_if_get_by_iface(iface1);
253 ((struct net_if_test *)
254 net_if_get_device(iface1)->data)->idx = idx;
255
256 DBG("Interfaces: [%d] iface1 %p\n",
257 net_if_get_by_iface(iface1), iface1);
258
259 zassert_not_null(iface1, "Interface 1");
260
261 ifaddr = net_if_ipv6_addr_add(iface1, &my_addr1,
262 NET_ADDR_MANUAL, 0);
263 if (!ifaddr) {
264 DBG("Cannot add IPv6 address %s\n",
265 net_sprint_ipv6_addr(&my_addr1));
266 zassert_not_null(ifaddr, "addr1");
267 }
268
269 ifaddr = net_if_ipv4_addr_add(iface1, &my_ipv4_addr1,
270 NET_ADDR_MANUAL, 0);
271 if (!ifaddr) {
272 DBG("Cannot add IPv4 address %s\n",
273 net_sprint_ipv4_addr(&my_ipv4_addr1));
274 zassert_not_null(ifaddr, "ipv4 addr1");
275 }
276
277 /* For testing purposes we need to set the addresses preferred */
278 ifaddr->addr_state = NET_ADDR_PREFERRED;
279
280 ifaddr = net_if_ipv6_addr_add(iface1, &ll_addr,
281 NET_ADDR_MANUAL, 0);
282 if (!ifaddr) {
283 DBG("Cannot add IPv6 address %s\n",
284 net_sprint_ipv6_addr(&ll_addr));
285 zassert_not_null(ifaddr, "ll_addr");
286 }
287
288 ifaddr->addr_state = NET_ADDR_PREFERRED;
289
290 net_ipv6_addr_create(&in6addr_mcast, 0xff02, 0, 0, 0, 0, 0, 0, 0x0001);
291
292 maddr = net_if_ipv6_maddr_add(iface1, &in6addr_mcast);
293 if (!maddr) {
294 DBG("Cannot add multicast IPv6 address %s\n",
295 net_sprint_ipv6_addr(&in6addr_mcast));
296 zassert_not_null(maddr, "mcast");
297 }
298
299 net_if_up(iface1);
300
301 test_started = true;
302
303 return NULL;
304 }
305
bytes_from_hostname_unique(uint8_t * buf,int buf_len,const char * src)306 static int bytes_from_hostname_unique(uint8_t *buf, int buf_len, const char *src)
307 {
308 unsigned int i;
309
310 (void)memset(buf, 0, buf_len);
311
312 if ((2 * buf_len) < strlen(src)) {
313 return -ENOMEM;
314 }
315
316 for (i = 0U; i < strlen(src); i++) {
317 buf[i/2] <<= 4;
318
319 if (src[i] >= '0' && src[i] <= '9') {
320 buf[i/2] += (src[i] - '0');
321 continue;
322 }
323
324 if (src[i] >= 'A' && src[i] <= 'F') {
325 buf[i/2] += (10 + (src[i] - 'A'));
326 continue;
327 }
328
329 if (src[i] >= 'a' && src[i] <= 'f') {
330 buf[i/2] += (10 + (src[i] - 'a'));
331 continue;
332 }
333
334 return -EINVAL;
335 }
336
337 return 0;
338 }
339
340 #ifdef CONFIG_NET_MGMT_EVENT
init_event_handler(void)341 static int init_event_handler(void)
342 {
343 k_sem_init(&wait_hostname, 0, K_SEM_MAX_LIMIT);
344
345 net_mgmt_init_event_callback(&hostname_cb, hostname_changed,
346 NET_EVENT_HOSTNAME_CHANGED);
347 net_mgmt_add_event_callback(&hostname_cb);
348
349 return 0;
350 }
351 #endif
352
ZTEST(net_hostname,test_hostname_get)353 ZTEST(net_hostname, test_hostname_get)
354 {
355 const char *hostname;
356 const char *config_hostname = CONFIG_NET_HOSTNAME;
357
358 hostname = net_hostname_get();
359
360 zassert_mem_equal(hostname, config_hostname,
361 sizeof(CONFIG_NET_HOSTNAME) - 1, "");
362
363 if (IS_ENABLED(CONFIG_NET_HOSTNAME_UNIQUE)) {
364 char mac[6];
365 int ret;
366
367 ret = bytes_from_hostname_unique(mac, sizeof(mac),
368 hostname + sizeof(CONFIG_NET_HOSTNAME) - 1);
369 zassert_equal(ret, 0, "");
370 zassert_mem_equal(mac, net_if_get_link_addr(iface1)->addr,
371 net_if_get_link_addr(iface1)->len, "");
372 }
373 }
374
ZTEST(net_hostname,test_hostname_set)375 ZTEST(net_hostname, test_hostname_set)
376 {
377 if (IS_ENABLED(CONFIG_NET_HOSTNAME_UNIQUE)) {
378 int ret;
379
380 ret = net_hostname_set_postfix("foobar", sizeof("foobar") - 1);
381 zassert_equal(ret, -EALREADY,
382 "Could set hostname postfix (%d)", ret);
383 }
384
385 if (IS_ENABLED(CONFIG_NET_HOSTNAME_DYNAMIC)) {
386 int ret;
387
388 ret = net_hostname_set("foobar", sizeof("foobar") - 1);
389 zassert_equal(ret, 0, "Could not set hostname (%d)", ret);
390 zassert_mem_equal("foobar", net_hostname_get(), sizeof("foobar")-1);
391 }
392 }
393
394 #ifdef CONFIG_NET_MGMT_EVENT
ZTEST(net_hostname,test_hostname_event)395 ZTEST(net_hostname, test_hostname_event)
396 {
397 if (IS_ENABLED(CONFIG_NET_MGMT_EVENT)) {
398 int ret;
399
400 ret = k_sem_take(&wait_hostname, K_NO_WAIT);
401 zassert_equal(ret, 0, "");
402
403 if (IS_ENABLED(CONFIG_NET_HOSTNAME_UNIQUE)) {
404 ret = k_sem_take(&wait_hostname, K_NO_WAIT);
405 zassert_equal(ret, 0, "");
406 }
407 }
408 }
409
410 /** Make sure that hostname related events are caught from the beginning **/
411 SYS_INIT(init_event_handler, POST_KERNEL, EVENT_HANDLER_INIT_PRIO);
412 #endif
413
414 ZTEST_SUITE(net_hostname, NULL, test_iface_setup, NULL, NULL, NULL);
415