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 		    &eth_fake_data, NULL, CONFIG_ETH_INIT_PRIORITY,
210 		    &eth_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