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,uint32_t mgmt_event,struct net_if * iface)104 static void ipv4_addr_add_handler(struct net_mgmt_event_callback *cb,
105 uint32_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, ¶ms);
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,uint32_t mgmt_event,struct net_if * iface)246 static void ipv6_event_handler(struct net_mgmt_event_callback *cb,
247 uint32_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 uint32_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 /*
334 * check for CMD_ADDR_ADD bit here, NET_EVENT_IPV6_ADDR_ADD is
335 * a combination of _NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ADDR_ADD
336 * so it will always return != NET_EVENT_IPV6_CMD_ADDR_ADD if any other
337 * event is set (for instance NET_EVENT_IPV6_ROUTER_ADD)
338 */
339 if ((mask & NET_EVENT_IPV6_CMD_ADDR_ADD) ==
340 NET_EVENT_IPV6_CMD_ADDR_ADD) {
341 ifaddr = net_if_ipv6_addr_add(iface, &laddr,
342 NET_ADDR_MANUAL, 0);
343 if (!ifaddr) {
344 NET_ERR("Cannot add %s to interface",
345 CONFIG_NET_CONFIG_MY_IPV6_ADDR);
346 }
347 }
348
349 exit:
350
351 if (!IS_ENABLED(CONFIG_NET_IPV6_DAD) ||
352 net_if_flag_is_set(iface, NET_IF_IPV6_NO_ND)) {
353 services_notify_ready(NET_CONFIG_NEED_IPV6);
354 }
355
356 return;
357 }
358
359 #else
360 #define setup_ipv6(...)
361 #define setup_dhcpv6(...)
362 #endif /* CONFIG_NET_IPV6 */
363
364 #if defined(CONFIG_NET_NATIVE)
iface_up_handler(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)365 static void iface_up_handler(struct net_mgmt_event_callback *cb,
366 uint32_t mgmt_event, struct net_if *iface)
367 {
368 if (mgmt_event == NET_EVENT_IF_UP) {
369 NET_INFO("Interface %d (%p) coming up",
370 net_if_get_by_iface(iface), iface);
371
372 k_sem_reset(&counter);
373 k_sem_give(&waiter);
374 }
375 }
376
check_interface(struct net_if * iface)377 static bool check_interface(struct net_if *iface)
378 {
379 if (net_if_is_up(iface)) {
380 k_sem_reset(&counter);
381 k_sem_give(&waiter);
382 return true;
383 }
384
385 NET_INFO("Waiting interface %d (%p) to be up...",
386 net_if_get_by_iface(iface), iface);
387
388 net_mgmt_init_event_callback(&mgmt_iface_cb, iface_up_handler,
389 NET_EVENT_IF_UP);
390 net_mgmt_add_event_callback(&mgmt_iface_cb);
391
392 return false;
393 }
394 #else
check_interface(struct net_if * iface)395 static bool check_interface(struct net_if *iface)
396 {
397 k_sem_reset(&counter);
398 k_sem_give(&waiter);
399
400 return true;
401 }
402 #endif
403
net_config_init_by_iface(struct net_if * iface,const char * app_info,uint32_t flags,int32_t timeout)404 int net_config_init_by_iface(struct net_if *iface, const char *app_info,
405 uint32_t flags, int32_t timeout)
406 {
407 #define LOOP_DIVIDER 10
408 int loop = timeout / LOOP_DIVIDER;
409 int count;
410
411 if (app_info) {
412 NET_INFO("%s", app_info);
413 }
414
415 if (!iface) {
416 iface = net_if_get_default();
417 }
418
419 if (!iface) {
420 return -ENOENT;
421 }
422
423 if (net_if_flag_is_set(iface, NET_IF_NO_AUTO_START)) {
424 return -ENETDOWN;
425 }
426
427 if (timeout < 0) {
428 count = -1;
429 } else if (timeout == 0) {
430 count = 0;
431 } else {
432 count = LOOP_DIVIDER;
433 }
434
435 /* First make sure that network interface is up */
436 if (check_interface(iface) == false) {
437 k_sem_init(&counter, 1, K_SEM_MAX_LIMIT);
438
439 while (count-- > 0) {
440 if (!k_sem_count_get(&counter)) {
441 break;
442 }
443
444 if (k_sem_take(&waiter, K_MSEC(loop))) {
445 if (!k_sem_count_get(&counter)) {
446 break;
447 }
448 }
449 }
450
451 #if defined(CONFIG_NET_NATIVE)
452 net_mgmt_del_event_callback(&mgmt_iface_cb);
453 #endif
454 }
455
456 setup_vlan(iface);
457 setup_ipv4(iface);
458 setup_dhcpv4(iface);
459 setup_ipv6(iface, flags);
460 setup_dhcpv6(iface);
461
462 /* Network interface did not come up. */
463 if (timeout > 0 && count < 0) {
464 NET_ERR("Timeout while waiting network %s", "interface");
465 return -ENETDOWN;
466 }
467
468 /* Loop here until we are ready to continue. As we might need
469 * to wait multiple events, sleep smaller amounts of data.
470 */
471 while (!services_are_ready(flags) && count-- > 0) {
472 k_sem_take(&waiter, K_MSEC(loop));
473 }
474
475 if (count == -1 && timeout > 0) {
476 NET_ERR("Timeout while waiting network %s", "setup");
477 return -ETIMEDOUT;
478 }
479
480 return 0;
481 }
482
net_config_init(const char * app_info,uint32_t flags,int32_t timeout)483 int net_config_init(const char *app_info, uint32_t flags,
484 int32_t timeout)
485 {
486 return net_config_init_by_iface(NULL, app_info, flags, timeout);
487 }
488
iface_find_cb(struct net_if * iface,void * user_data)489 static void iface_find_cb(struct net_if *iface, void *user_data)
490 {
491 struct net_if **iface_to_use = user_data;
492
493 if (*iface_to_use == NULL &&
494 !net_if_flag_is_set(iface, NET_IF_NO_AUTO_START)) {
495 *iface_to_use = iface;
496 return;
497 }
498 }
499
net_config_init_app(const struct device * dev,const char * app_info)500 int net_config_init_app(const struct device *dev, const char *app_info)
501 {
502 struct net_if *iface = NULL;
503 uint32_t flags = 0U;
504 int ret;
505
506 if (dev) {
507 iface = net_if_lookup_by_dev(dev);
508 if (iface == NULL) {
509 NET_WARN("No interface for device %p, using default",
510 dev);
511 }
512 }
513
514 ret = z_net_config_ieee802154_setup(iface);
515 if (ret < 0) {
516 NET_ERR("Cannot setup IEEE 802.15.4 interface (%d)", ret);
517 }
518
519 /* Only try to use a network interface that is auto started */
520 if (iface == NULL) {
521 net_if_foreach(iface_find_cb, &iface);
522 }
523
524 if (!iface) {
525 NET_WARN("No auto-started network interface - "
526 "network-bound app initialization skipped.");
527 return 0;
528 }
529
530 if (IS_ENABLED(CONFIG_NET_CONFIG_NEED_IPV6)) {
531 flags |= NET_CONFIG_NEED_IPV6;
532 }
533
534 if (IS_ENABLED(CONFIG_NET_CONFIG_NEED_IPV6_ROUTER)) {
535 flags |= NET_CONFIG_NEED_ROUTER;
536 }
537
538 if (IS_ENABLED(CONFIG_NET_CONFIG_NEED_IPV4)) {
539 flags |= NET_CONFIG_NEED_IPV4;
540 }
541
542 /* Initialize the application automatically if needed */
543 ret = net_config_init_by_iface(iface, app_info, flags,
544 CONFIG_NET_CONFIG_INIT_TIMEOUT * MSEC_PER_SEC);
545 if (ret < 0) {
546 NET_ERR("Network initialization failed (%d)", ret);
547 }
548
549 if (IS_ENABLED(CONFIG_NET_CONFIG_CLOCK_SNTP_INIT)) {
550 net_init_clock_via_sntp();
551 }
552
553 /* This is activated late as it requires the network stack to be up
554 * and running before syslog messages can be sent to network.
555 */
556 if (IS_ENABLED(CONFIG_LOG_BACKEND_NET) &&
557 IS_ENABLED(CONFIG_LOG_BACKEND_NET_AUTOSTART)) {
558 const struct log_backend *backend = log_backend_net_get();
559
560 if (!log_backend_is_active(backend)) {
561 if (backend->api->init != NULL) {
562 backend->api->init(backend);
563 }
564
565 log_backend_activate(backend, NULL);
566 }
567 }
568
569 return ret;
570 }
571
572 #if defined(CONFIG_NET_CONFIG_AUTO_INIT)
init_app(void)573 static int init_app(void)
574 {
575
576 (void)net_config_init_app(NULL, "Initializing network");
577
578 return 0;
579 }
580
581 SYS_INIT(init_app, APPLICATION, CONFIG_NET_CONFIG_INIT_PRIO);
582 #endif /* CONFIG_NET_CONFIG_AUTO_INIT */
583