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, ¶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,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