1 /* init.c */
2 
3 /*
4  * Copyright (c) 2017 Intel Corporation.
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <zephyr/logging/log.h>
10 LOG_MODULE_REGISTER(net_config, CONFIG_NET_CONFIG_LOG_LEVEL);
11 
12 #include <zephyr/kernel.h>
13 #include <zephyr/init.h>
14 #include <string.h>
15 #include <errno.h>
16 #include <stdlib.h>
17 
18 #include <zephyr/logging/log_backend.h>
19 #include <zephyr/logging/log_backend_net.h>
20 #include <zephyr/net/ethernet.h>
21 #include <zephyr/net/net_core.h>
22 #include <zephyr/net/net_ip.h>
23 #include <zephyr/net/net_if.h>
24 #include <zephyr/net/dhcpv4.h>
25 #include <zephyr/net/dhcpv6.h>
26 #include <zephyr/net/net_mgmt.h>
27 #include <zephyr/net/dns_resolve.h>
28 
29 #include <zephyr/net/net_config.h>
30 
31 #include "ieee802154_settings.h"
32 
33 extern int net_init_clock_via_sntp(void);
34 
35 static K_SEM_DEFINE(waiter, 0, 1);
36 static K_SEM_DEFINE(counter, 0, UINT_MAX);
37 static atomic_t services_flags;
38 
39 #if defined(CONFIG_NET_NATIVE)
40 static struct net_mgmt_event_callback mgmt_iface_cb;
41 #endif
42 
services_notify_ready(int flags)43 static inline void services_notify_ready(int flags)
44 {
45 	atomic_or(&services_flags, flags);
46 	k_sem_give(&waiter);
47 }
48 
services_are_ready(int flags)49 static inline bool services_are_ready(int flags)
50 {
51 	return (atomic_get(&services_flags) & flags) == flags;
52 }
53 
54 #if defined(CONFIG_NET_NATIVE_IPV4)
55 
56 #if defined(CONFIG_NET_DHCPV4)
57 
setup_dhcpv4(struct net_if * iface)58 static void setup_dhcpv4(struct net_if *iface)
59 {
60 	NET_INFO("Running dhcpv4 client...");
61 
62 	net_dhcpv4_start(iface);
63 }
64 
print_dhcpv4_info(struct net_if * iface)65 static void print_dhcpv4_info(struct net_if *iface)
66 {
67 #if CONFIG_NET_CONFIG_LOG_LEVEL >= LOG_LEVEL_INF
68 	char hr_addr[NET_IPV4_ADDR_LEN];
69 #endif
70 	ARRAY_FOR_EACH(iface->config.ip.ipv4->unicast, i) {
71 		struct net_if_addr *if_addr =
72 					&iface->config.ip.ipv4->unicast[i].ipv4;
73 
74 		if (if_addr->addr_type != NET_ADDR_DHCP ||
75 		    !if_addr->is_used) {
76 			continue;
77 		}
78 
79 #if CONFIG_NET_CONFIG_LOG_LEVEL >= LOG_LEVEL_INF
80 		NET_INFO("IPv4 address: %s",
81 			 net_addr_ntop(AF_INET, &if_addr->address.in_addr,
82 				       hr_addr, sizeof(hr_addr)));
83 		NET_INFO("Lease time: %u seconds",
84 			 iface->config.dhcpv4.lease_time);
85 		NET_INFO("Subnet: %s",
86 			 net_addr_ntop(AF_INET,
87 				       &iface->config.ip.ipv4->unicast[i].netmask,
88 				       hr_addr, sizeof(hr_addr)));
89 		NET_INFO("Router: %s",
90 			 net_addr_ntop(AF_INET, &iface->config.ip.ipv4->gw,
91 				       hr_addr, sizeof(hr_addr)));
92 #endif
93 		break;
94 	}
95 }
96 
97 #else
98 #define setup_dhcpv4(...)
99 #define print_dhcpv4_info(...)
100 #endif /* CONFIG_NET_DHCPV4 */
101 
102 static struct net_mgmt_event_callback mgmt4_cb;
103 
ipv4_addr_add_handler(struct net_mgmt_event_callback * cb,uint64_t mgmt_event,struct net_if * iface)104 static void ipv4_addr_add_handler(struct net_mgmt_event_callback *cb,
105 				  uint64_t mgmt_event,
106 				  struct net_if *iface)
107 {
108 	if (mgmt_event == NET_EVENT_IPV4_ADDR_ADD) {
109 		print_dhcpv4_info(iface);
110 
111 		if (!IS_ENABLED(CONFIG_NET_IPV4_ACD)) {
112 			services_notify_ready(NET_CONFIG_NEED_IPV4);
113 		}
114 	}
115 
116 	if (mgmt_event == NET_EVENT_IPV4_ACD_SUCCEED) {
117 		services_notify_ready(NET_CONFIG_NEED_IPV4);
118 	}
119 }
120 
121 #if defined(CONFIG_NET_VLAN) && (CONFIG_NET_CONFIG_MY_VLAN_ID > 0)
122 
setup_vlan(struct net_if * iface)123 static void setup_vlan(struct net_if *iface)
124 {
125 	int ret = net_eth_vlan_enable(iface, CONFIG_NET_CONFIG_MY_VLAN_ID);
126 
127 	if (ret < 0) {
128 		NET_ERR("Network interface %d (%p): cannot set VLAN tag (%d)",
129 			net_if_get_by_iface(iface), iface, ret);
130 	}
131 }
132 
133 #else
134 #define setup_vlan(...)
135 #endif /* CONFIG_NET_VLAN && (CONFIG_NET_CONFIG_MY_VLAN_ID > 0) */
136 
137 #if defined(CONFIG_NET_NATIVE_IPV4) && !defined(CONFIG_NET_DHCPV4) && \
138 	!defined(CONFIG_NET_CONFIG_MY_IPV4_ADDR)
139 #error "You need to define an IPv4 address or enable DHCPv4!"
140 #endif
141 
setup_ipv4(struct net_if * iface)142 static void setup_ipv4(struct net_if *iface)
143 {
144 #if CONFIG_NET_CONFIG_LOG_LEVEL >= LOG_LEVEL_INF
145 	char hr_addr[NET_IPV4_ADDR_LEN];
146 #endif
147 	struct in_addr addr, netmask;
148 
149 	if (IS_ENABLED(CONFIG_NET_IPV4_ACD) || IS_ENABLED(CONFIG_NET_DHCPV4)) {
150 		net_mgmt_init_event_callback(&mgmt4_cb, ipv4_addr_add_handler,
151 					     NET_EVENT_IPV4_ADDR_ADD |
152 					     NET_EVENT_IPV4_ACD_SUCCEED);
153 		net_mgmt_add_event_callback(&mgmt4_cb);
154 	}
155 
156 	if (sizeof(CONFIG_NET_CONFIG_MY_IPV4_ADDR) == 1) {
157 		/* Empty address, skip setting ANY address in this case */
158 		return;
159 	}
160 
161 	if (net_addr_pton(AF_INET, CONFIG_NET_CONFIG_MY_IPV4_ADDR, &addr)) {
162 		NET_ERR("Invalid address: %s", CONFIG_NET_CONFIG_MY_IPV4_ADDR);
163 		return;
164 	}
165 
166 #if defined(CONFIG_NET_DHCPV4)
167 	/* In case DHCP is enabled, make the static address tentative,
168 	 * to allow DHCP address to override it. This covers a usecase
169 	 * of "there should be a static IP address for DHCP-less setups",
170 	 * but DHCP should override it (to use it, NET_IF_MAX_IPV4_ADDR
171 	 * should be set to 1). There is another usecase: "there should
172 	 * always be static IP address, and optionally, DHCP address".
173 	 * For that to work, NET_IF_MAX_IPV4_ADDR should be 2 (or more).
174 	 * (In this case, an app will need to bind to the needed addr
175 	 * explicitly.)
176 	 */
177 	net_if_ipv4_addr_add(iface, &addr, NET_ADDR_OVERRIDABLE, 0);
178 #else
179 	net_if_ipv4_addr_add(iface, &addr, NET_ADDR_MANUAL, 0);
180 #endif
181 
182 #if CONFIG_NET_CONFIG_LOG_LEVEL >= LOG_LEVEL_INF
183 	NET_INFO("IPv4 address: %s",
184 		 net_addr_ntop(AF_INET, &addr, hr_addr, sizeof(hr_addr)));
185 #endif
186 
187 	if (sizeof(CONFIG_NET_CONFIG_MY_IPV4_NETMASK) > 1) {
188 		/* If not empty */
189 		if (net_addr_pton(AF_INET, CONFIG_NET_CONFIG_MY_IPV4_NETMASK,
190 				  &netmask)) {
191 			NET_ERR("Invalid netmask: %s",
192 				CONFIG_NET_CONFIG_MY_IPV4_NETMASK);
193 		} else {
194 			net_if_ipv4_set_netmask_by_addr(iface, &addr, &netmask);
195 		}
196 	}
197 
198 	if (sizeof(CONFIG_NET_CONFIG_MY_IPV4_GW) > 1) {
199 		/* If not empty */
200 		if (net_addr_pton(AF_INET, CONFIG_NET_CONFIG_MY_IPV4_GW,
201 				  &addr)) {
202 			NET_ERR("Invalid gateway: %s",
203 				CONFIG_NET_CONFIG_MY_IPV4_GW);
204 		} else {
205 			net_if_ipv4_set_gw(iface, &addr);
206 		}
207 	}
208 
209 	if (!IS_ENABLED(CONFIG_NET_IPV4_ACD)) {
210 		services_notify_ready(NET_CONFIG_NEED_IPV4);
211 	}
212 }
213 
214 #else
215 #define setup_ipv4(...)
216 #define setup_dhcpv4(...)
217 #define setup_vlan(...)
218 #endif /* CONFIG_NET_NATIVE_IPV4*/
219 
220 #if defined(CONFIG_NET_NATIVE_IPV6)
221 
222 #if defined(CONFIG_NET_DHCPV6)
setup_dhcpv6(struct net_if * iface)223 static void setup_dhcpv6(struct net_if *iface)
224 {
225 	struct net_dhcpv6_params params = {
226 		.request_addr = IS_ENABLED(CONFIG_NET_CONFIG_DHCPV6_REQUEST_ADDR),
227 		.request_prefix = IS_ENABLED(CONFIG_NET_CONFIG_DHCPV6_REQUEST_PREFIX),
228 	};
229 
230 	NET_INFO("Running dhcpv6 client...");
231 
232 	net_dhcpv6_start(iface, &params);
233 }
234 #else /* CONFIG_NET_DHCPV6 */
235 #define setup_dhcpv6(...)
236 #endif /* CONFIG_NET_DHCPV6 */
237 
238 #if !defined(CONFIG_NET_CONFIG_DHCPV6_REQUEST_ADDR) && \
239 	!defined(CONFIG_NET_CONFIG_MY_IPV6_ADDR)
240 #error "You need to define an IPv6 address or enable DHCPv6!"
241 #endif
242 
243 static struct net_mgmt_event_callback mgmt6_cb;
244 static struct in6_addr laddr;
245 
ipv6_event_handler(struct net_mgmt_event_callback * cb,uint64_t mgmt_event,struct net_if * iface)246 static void ipv6_event_handler(struct net_mgmt_event_callback *cb,
247 			       uint64_t mgmt_event, struct net_if *iface)
248 {
249 	struct net_if_ipv6 *ipv6 = iface->config.ip.ipv6;
250 	int i;
251 
252 	if (!ipv6) {
253 		return;
254 	}
255 
256 	if (mgmt_event == NET_EVENT_IPV6_ADDR_ADD) {
257 		/* save the last added IP address for this interface */
258 		for (i = NET_IF_MAX_IPV6_ADDR - 1; i >= 0; i--) {
259 			if (ipv6->unicast[i].is_used) {
260 				memcpy(&laddr,
261 				       &ipv6->unicast[i].address.in6_addr,
262 				       sizeof(laddr));
263 				break;
264 			}
265 		}
266 	}
267 
268 	if (mgmt_event == NET_EVENT_IPV6_DAD_SUCCEED) {
269 #if CONFIG_NET_CONFIG_LOG_LEVEL >= LOG_LEVEL_INF
270 		char hr_addr[NET_IPV6_ADDR_LEN];
271 #endif
272 		struct net_if_addr *ifaddr;
273 
274 		ifaddr = net_if_ipv6_addr_lookup(&laddr, &iface);
275 		if (!ifaddr ||
276 		    !(net_ipv6_addr_cmp(&ifaddr->address.in6_addr, &laddr) &&
277 		      ifaddr->addr_state == NET_ADDR_PREFERRED)) {
278 			/* Address is not yet properly setup */
279 			return;
280 		}
281 
282 #if CONFIG_NET_CONFIG_LOG_LEVEL >= LOG_LEVEL_INF
283 		NET_INFO("IPv6 address: %s",
284 			 net_addr_ntop(AF_INET6, &laddr, hr_addr, NET_IPV6_ADDR_LEN));
285 
286 		if (ifaddr->addr_type == NET_ADDR_DHCP) {
287 			char remaining_str[] = "infinite";
288 			uint32_t remaining;
289 
290 			remaining = net_timeout_remaining(&ifaddr->lifetime,
291 							  k_uptime_get_32());
292 
293 			if (!ifaddr->is_infinite) {
294 				snprintk(remaining_str, sizeof(remaining_str),
295 					 "%u", remaining);
296 			}
297 
298 			NET_INFO("Lifetime: %s seconds", remaining_str);
299 		}
300 #endif
301 
302 		services_notify_ready(NET_CONFIG_NEED_IPV6);
303 	}
304 
305 	if (mgmt_event == NET_EVENT_IPV6_ROUTER_ADD) {
306 		services_notify_ready(NET_CONFIG_NEED_ROUTER);
307 	}
308 }
309 
setup_ipv6(struct net_if * iface,uint32_t flags)310 static void setup_ipv6(struct net_if *iface, uint32_t flags)
311 {
312 	struct net_if_addr *ifaddr;
313 	uint64_t mask = NET_EVENT_IPV6_DAD_SUCCEED;
314 
315 	if (sizeof(CONFIG_NET_CONFIG_MY_IPV6_ADDR) == 1) {
316 		/* Empty address, skip setting ANY address in this case */
317 		goto exit;
318 	}
319 
320 	if (net_addr_pton(AF_INET6, CONFIG_NET_CONFIG_MY_IPV6_ADDR, &laddr)) {
321 		NET_ERR("Invalid address: %s", CONFIG_NET_CONFIG_MY_IPV6_ADDR);
322 		/* some interfaces may add IP address later */
323 		mask |= NET_EVENT_IPV6_ADDR_ADD;
324 	}
325 
326 	if (flags & NET_CONFIG_NEED_ROUTER) {
327 		mask |= NET_EVENT_IPV6_ROUTER_ADD;
328 	}
329 
330 	net_mgmt_init_event_callback(&mgmt6_cb, ipv6_event_handler, mask);
331 	net_mgmt_add_event_callback(&mgmt6_cb);
332 
333 	ifaddr = net_if_ipv6_addr_add(iface, &laddr, NET_ADDR_MANUAL, 0);
334 	if (!ifaddr) {
335 		NET_ERR("Cannot add %s to interface",
336 			CONFIG_NET_CONFIG_MY_IPV6_ADDR);
337 	}
338 
339 exit:
340 
341 	if (!IS_ENABLED(CONFIG_NET_IPV6_DAD) ||
342 	    net_if_flag_is_set(iface, NET_IF_IPV6_NO_ND)) {
343 		services_notify_ready(NET_CONFIG_NEED_IPV6);
344 	}
345 
346 	return;
347 }
348 
349 #else
350 #define setup_ipv6(...)
351 #define setup_dhcpv6(...)
352 #endif /* CONFIG_NET_IPV6 */
353 
354 #if defined(CONFIG_NET_NATIVE)
iface_up_handler(struct net_mgmt_event_callback * cb,uint64_t mgmt_event,struct net_if * iface)355 static void iface_up_handler(struct net_mgmt_event_callback *cb,
356 			     uint64_t mgmt_event, struct net_if *iface)
357 {
358 	if (mgmt_event == NET_EVENT_IF_UP) {
359 		NET_INFO("Interface %d (%p) coming up",
360 			 net_if_get_by_iface(iface), iface);
361 
362 		k_sem_reset(&counter);
363 		k_sem_give(&waiter);
364 	}
365 }
366 
check_interface(struct net_if * iface)367 static bool check_interface(struct net_if *iface)
368 {
369 	if (net_if_is_up(iface)) {
370 		k_sem_reset(&counter);
371 		k_sem_give(&waiter);
372 		return true;
373 	}
374 
375 	NET_INFO("Waiting interface %d (%p) to be up...",
376 		 net_if_get_by_iface(iface), iface);
377 
378 	net_mgmt_init_event_callback(&mgmt_iface_cb, iface_up_handler,
379 				     NET_EVENT_IF_UP);
380 	net_mgmt_add_event_callback(&mgmt_iface_cb);
381 
382 	return false;
383 }
384 #else
check_interface(struct net_if * iface)385 static bool check_interface(struct net_if *iface)
386 {
387 	k_sem_reset(&counter);
388 	k_sem_give(&waiter);
389 
390 	return true;
391 }
392 #endif
393 
net_config_init_by_iface(struct net_if * iface,const char * app_info,uint32_t flags,int32_t timeout)394 int net_config_init_by_iface(struct net_if *iface, const char *app_info,
395 			     uint32_t flags, int32_t timeout)
396 {
397 #define LOOP_DIVIDER 10
398 	int loop = timeout / LOOP_DIVIDER;
399 	int count;
400 
401 	if (app_info) {
402 		NET_INFO("%s", app_info);
403 	}
404 
405 	if (!iface) {
406 		iface = net_if_get_default();
407 	}
408 
409 	if (!iface) {
410 		return -ENOENT;
411 	}
412 
413 	if (net_if_flag_is_set(iface, NET_IF_NO_AUTO_START)) {
414 		return -ENETDOWN;
415 	}
416 
417 	if (timeout < 0) {
418 		count = -1;
419 	} else if (timeout == 0) {
420 		count = 0;
421 	} else {
422 		count = LOOP_DIVIDER;
423 	}
424 
425 	/* First make sure that network interface is up */
426 	if (check_interface(iface) == false) {
427 		k_sem_init(&counter, 1, K_SEM_MAX_LIMIT);
428 
429 		while (count-- > 0) {
430 			if (!k_sem_count_get(&counter)) {
431 				break;
432 			}
433 
434 			if (k_sem_take(&waiter, K_MSEC(loop))) {
435 				if (!k_sem_count_get(&counter)) {
436 					break;
437 				}
438 			}
439 		}
440 
441 #if defined(CONFIG_NET_NATIVE)
442 		net_mgmt_del_event_callback(&mgmt_iface_cb);
443 #endif
444 	}
445 
446 	setup_vlan(iface);
447 	setup_ipv4(iface);
448 	setup_dhcpv4(iface);
449 	setup_ipv6(iface, flags);
450 	setup_dhcpv6(iface);
451 
452 	/* Network interface did not come up. */
453 	if (timeout > 0 && count < 0) {
454 		NET_ERR("Timeout while waiting network %s", "interface");
455 		return -ENETDOWN;
456 	}
457 
458 	/* Loop here until we are ready to continue. As we might need
459 	 * to wait multiple events, sleep smaller amounts of data.
460 	 */
461 	while (!services_are_ready(flags) && count-- > 0) {
462 		k_sem_take(&waiter, K_MSEC(loop));
463 	}
464 
465 	if (count == -1 && timeout > 0) {
466 		NET_ERR("Timeout while waiting network %s", "setup");
467 		return -ETIMEDOUT;
468 	}
469 
470 	return 0;
471 }
472 
net_config_init(const char * app_info,uint32_t flags,int32_t timeout)473 int net_config_init(const char *app_info, uint32_t flags,
474 		    int32_t timeout)
475 {
476 	return net_config_init_by_iface(NULL, app_info, flags, timeout);
477 }
478 
iface_find_cb(struct net_if * iface,void * user_data)479 static void iface_find_cb(struct net_if *iface, void *user_data)
480 {
481 	struct net_if **iface_to_use = user_data;
482 
483 	if (*iface_to_use == NULL &&
484 	    !net_if_flag_is_set(iface, NET_IF_NO_AUTO_START)) {
485 		*iface_to_use = iface;
486 		return;
487 	}
488 }
489 
net_config_init_app(const struct device * dev,const char * app_info)490 int net_config_init_app(const struct device *dev, const char *app_info)
491 {
492 	struct net_if *iface = NULL;
493 	uint32_t flags = 0U;
494 	int ret;
495 
496 	if (dev) {
497 		iface = net_if_lookup_by_dev(dev);
498 		if (iface == NULL) {
499 			NET_WARN("No interface for device %p, using default",
500 				 dev);
501 		}
502 	}
503 
504 	ret = z_net_config_ieee802154_setup(iface);
505 	if (ret < 0) {
506 		NET_ERR("Cannot setup IEEE 802.15.4 interface (%d)", ret);
507 	}
508 
509 	/* Only try to use a network interface that is auto started */
510 	if (iface == NULL) {
511 		net_if_foreach(iface_find_cb, &iface);
512 	}
513 
514 	if (!iface) {
515 		NET_WARN("No auto-started network interface - "
516 			 "network-bound app initialization skipped.");
517 		return 0;
518 	}
519 
520 	if (IS_ENABLED(CONFIG_NET_CONFIG_NEED_IPV6)) {
521 		flags |= NET_CONFIG_NEED_IPV6;
522 	}
523 
524 	if (IS_ENABLED(CONFIG_NET_CONFIG_NEED_IPV6_ROUTER)) {
525 		flags |= NET_CONFIG_NEED_ROUTER;
526 	}
527 
528 	if (IS_ENABLED(CONFIG_NET_CONFIG_NEED_IPV4)) {
529 		flags |= NET_CONFIG_NEED_IPV4;
530 	}
531 
532 	/* Initialize the application automatically if needed */
533 	ret = net_config_init_by_iface(iface, app_info, flags,
534 				CONFIG_NET_CONFIG_INIT_TIMEOUT * MSEC_PER_SEC);
535 	if (ret < 0) {
536 		NET_ERR("Network initialization failed (%d)", ret);
537 	}
538 
539 	if (IS_ENABLED(CONFIG_NET_CONFIG_CLOCK_SNTP_INIT) &&
540 	    !IS_ENABLED(CONFIG_NET_CONFIG_SNTP_INIT_USE_CONNECTION_MANAGER)) {
541 		net_init_clock_via_sntp();
542 	}
543 
544 	/* This is activated late as it requires the network stack to be up
545 	 * and running before syslog messages can be sent to network.
546 	 */
547 	if (IS_ENABLED(CONFIG_LOG_BACKEND_NET_AUTOSTART) &&
548 	    !IS_ENABLED(CONFIG_LOG_BACKEND_NET_USE_CONNECTION_MANAGER)) {
549 		log_backend_net_start();
550 	}
551 
552 	return ret;
553 }
554 
555 #if defined(CONFIG_NET_CONFIG_AUTO_INIT)
init_app(void)556 static int init_app(void)
557 {
558 
559 	(void)net_config_init_app(NULL, "Initializing network");
560 
561 	return 0;
562 }
563 
564 SYS_INIT(init_app, APPLICATION, CONFIG_NET_CONFIG_INIT_PRIO);
565 #endif /* CONFIG_NET_CONFIG_AUTO_INIT */
566