1 /** @file
2 * @brief Misc network utility functions
3 *
4 */
5
6 /*
7 * Copyright (c) 2016 Intel Corporation
8 *
9 * SPDX-License-Identifier: Apache-2.0
10 */
11
12 #include <logging/log.h>
13 LOG_MODULE_REGISTER(net_utils, CONFIG_NET_UTILS_LOG_LEVEL);
14
15 #include <kernel.h>
16 #include <stdlib.h>
17 #include <syscall_handler.h>
18 #include <zephyr/types.h>
19 #include <stdbool.h>
20 #include <string.h>
21 #include <errno.h>
22
23 #include <net/net_ip.h>
24 #include <net/net_pkt.h>
25 #include <net/net_core.h>
26 #include <net/socket_can.h>
27
net_sprint_addr(sa_family_t af,const void * addr)28 char *net_sprint_addr(sa_family_t af, const void *addr)
29 {
30 #define NBUFS 3
31 static char buf[NBUFS][NET_IPV6_ADDR_LEN];
32 static int i;
33 char *s = buf[++i % NBUFS];
34
35 return net_addr_ntop(af, addr, s, NET_IPV6_ADDR_LEN);
36 }
37
net_proto2str(int family,int proto)38 const char *net_proto2str(int family, int proto)
39 {
40 if (family == AF_INET || family == AF_INET6) {
41 switch (proto) {
42 case IPPROTO_ICMP:
43 return "ICMPv4";
44 case IPPROTO_TCP:
45 return "TCP";
46 case IPPROTO_UDP:
47 return "UDP";
48 case IPPROTO_ICMPV6:
49 return "ICMPv6";
50 default:
51 break;
52 }
53 } else if (family == AF_CAN) {
54 switch (proto) {
55 case CAN_RAW:
56 return "CAN_RAW";
57 default:
58 break;
59 }
60 }
61
62 return "UNK_PROTO";
63 }
64
net_byte_to_hex(char * ptr,uint8_t byte,char base,bool pad)65 char *net_byte_to_hex(char *ptr, uint8_t byte, char base, bool pad)
66 {
67 int i, val;
68
69 for (i = 0, val = (byte & 0xf0) >> 4; i < 2; i++, val = byte & 0x0f) {
70 if (i == 0 && !pad && !val) {
71 continue;
72 }
73 if (val < 10) {
74 *ptr++ = (char) (val + '0');
75 } else {
76 *ptr++ = (char) (val - 10 + base);
77 }
78 }
79
80 *ptr = '\0';
81
82 return ptr;
83 }
84
net_sprint_ll_addr_buf(const uint8_t * ll,uint8_t ll_len,char * buf,int buflen)85 char *net_sprint_ll_addr_buf(const uint8_t *ll, uint8_t ll_len,
86 char *buf, int buflen)
87 {
88 uint8_t i, len, blen;
89 char *ptr = buf;
90
91 if (ll == NULL) {
92 return "<unknown>";
93 }
94
95 switch (ll_len) {
96 case 8:
97 len = 8U;
98 break;
99 case 6:
100 len = 6U;
101 break;
102 case 2:
103 len = 2U;
104 break;
105 default:
106 len = 6U;
107 break;
108 }
109
110 for (i = 0U, blen = buflen; i < len && blen > 0; i++) {
111 ptr = net_byte_to_hex(ptr, (char)ll[i], 'A', true);
112 *ptr++ = ':';
113 blen -= 3U;
114 }
115
116 if (!(ptr - buf)) {
117 return NULL;
118 }
119
120 *(ptr - 1) = '\0';
121 return buf;
122 }
123
net_value_to_udec(char * buf,uint32_t value,int precision)124 static int net_value_to_udec(char *buf, uint32_t value, int precision)
125 {
126 uint32_t divisor;
127 int i;
128 int temp;
129 char *start = buf;
130
131 divisor = 1000000000U;
132 if (precision < 0) {
133 precision = 1;
134 }
135
136 for (i = 9; i >= 0; i--, divisor /= 10U) {
137 temp = value / divisor;
138 value = value % divisor;
139 if ((precision > i) || (temp != 0)) {
140 precision = i;
141 *buf++ = (char) (temp + '0');
142 }
143 }
144 *buf = 0;
145
146 return buf - start;
147 }
148
z_impl_net_addr_ntop(sa_family_t family,const void * src,char * dst,size_t size)149 char *z_impl_net_addr_ntop(sa_family_t family, const void *src,
150 char *dst, size_t size)
151 {
152 struct in_addr *addr;
153 struct in6_addr *addr6;
154 uint16_t *w;
155 uint8_t i, bl, bh, longest = 1U;
156 int8_t pos = -1;
157 char delim = ':';
158 unsigned char zeros[8] = { 0 };
159 char *ptr = dst;
160 int len = -1;
161 uint16_t value;
162 bool needcolon = false;
163
164 if (family == AF_INET6) {
165 addr6 = (struct in6_addr *)src;
166 w = (uint16_t *)addr6->s6_addr16;
167 len = 8;
168
169 for (i = 0U; i < 8; i++) {
170 uint8_t j;
171
172 for (j = i; j < 8; j++) {
173 if (UNALIGNED_GET(&w[j]) != 0) {
174 break;
175 }
176
177 zeros[i]++;
178 }
179 }
180
181 for (i = 0U; i < 8; i++) {
182 if (zeros[i] > longest) {
183 longest = zeros[i];
184 pos = i;
185 }
186 }
187
188 if (longest == 1U) {
189 pos = -1;
190 }
191
192 } else if (family == AF_INET) {
193 addr = (struct in_addr *)src;
194 len = 4;
195 delim = '.';
196 } else {
197 return NULL;
198 }
199
200 for (i = 0U; i < len; i++) {
201 /* IPv4 address a.b.c.d */
202 if (len == 4) {
203 uint8_t l;
204
205 value = (uint32_t)addr->s4_addr[i];
206
207 /* net_byte_to_udec() eats 0 */
208 if (value == 0U) {
209 *ptr++ = '0';
210 *ptr++ = delim;
211 continue;
212 }
213
214 l = net_value_to_udec(ptr, value, 0);
215
216 ptr += l;
217 *ptr++ = delim;
218
219 continue;
220 }
221
222 /* IPv6 address */
223 if (i == pos) {
224 if (needcolon || i == 0U) {
225 *ptr++ = ':';
226 }
227
228 *ptr++ = ':';
229 needcolon = false;
230 i += longest - 1U;
231
232 continue;
233 }
234
235 if (needcolon) {
236 *ptr++ = ':';
237 needcolon = false;
238 }
239
240 value = (uint32_t)sys_be16_to_cpu(UNALIGNED_GET(&w[i]));
241 bh = value >> 8;
242 bl = value & 0xff;
243
244 if (bh) {
245 if (bh > 0x0f) {
246 ptr = net_byte_to_hex(ptr, bh, 'a', false);
247 } else {
248 if (bh < 10) {
249 *ptr++ = (char)(bh + '0');
250 } else {
251 *ptr++ = (char) (bh - 10 + 'a');
252 }
253 }
254
255 ptr = net_byte_to_hex(ptr, bl, 'a', true);
256 } else if (bl > 0x0f) {
257 ptr = net_byte_to_hex(ptr, bl, 'a', false);
258 } else {
259 if (bl < 10) {
260 *ptr++ = (char)(bl + '0');
261 } else {
262 *ptr++ = (char) (bl - 10 + 'a');
263 }
264 }
265
266 needcolon = true;
267 }
268
269 if (!(ptr - dst)) {
270 return NULL;
271 }
272
273 if (family == AF_INET) {
274 *(ptr - 1) = '\0';
275 } else {
276 *ptr = '\0';
277 }
278
279 return dst;
280 }
281
282 #if defined(CONFIG_USERSPACE)
z_vrfy_net_addr_ntop(sa_family_t family,const void * src,char * dst,size_t size)283 char *z_vrfy_net_addr_ntop(sa_family_t family, const void *src,
284 char *dst, size_t size)
285 {
286 char str[INET6_ADDRSTRLEN];
287 struct in6_addr addr6;
288 struct in_addr addr4;
289 char *out;
290 const void *addr;
291
292 Z_OOPS(Z_SYSCALL_MEMORY_WRITE(dst, size));
293
294 if (family == AF_INET) {
295 Z_OOPS(z_user_from_copy(&addr4, (const void *)src,
296 sizeof(addr4)));
297 addr = &addr4;
298 } else if (family == AF_INET6) {
299 Z_OOPS(z_user_from_copy(&addr6, (const void *)src,
300 sizeof(addr6)));
301 addr = &addr6;
302 } else {
303 return 0;
304 }
305
306 out = z_impl_net_addr_ntop(family, addr, str, sizeof(str));
307 if (!out) {
308 return 0;
309 }
310
311 Z_OOPS(z_user_to_copy((void *)dst, str, MIN(size, sizeof(str))));
312
313 return dst;
314 }
315 #include <syscalls/net_addr_ntop_mrsh.c>
316 #endif /* CONFIG_USERSPACE */
317
z_impl_net_addr_pton(sa_family_t family,const char * src,void * dst)318 int z_impl_net_addr_pton(sa_family_t family, const char *src,
319 void *dst)
320 {
321 if (family == AF_INET) {
322 struct in_addr *addr = (struct in_addr *)dst;
323 size_t i, len;
324
325 len = strlen(src);
326 for (i = 0; i < len; i++) {
327 if (!(src[i] >= '0' && src[i] <= '9') &&
328 src[i] != '.') {
329 return -EINVAL;
330 }
331 }
332
333 (void)memset(addr, 0, sizeof(struct in_addr));
334
335 for (i = 0; i < sizeof(struct in_addr); i++) {
336 char *endptr;
337
338 addr->s4_addr[i] = strtol(src, &endptr, 10);
339
340 src = ++endptr;
341 }
342
343 } else if (family == AF_INET6) {
344 /* If the string contains a '.', it means it's of the form
345 * X:X:X:X:X:X:x.x.x.x, and contains only 6 16-bit pieces
346 */
347 int expected_groups = strchr(src, '.') ? 6 : 8;
348 struct in6_addr *addr = (struct in6_addr *)dst;
349 int i, len;
350
351 if (*src == ':') {
352 /* Ignore a leading colon, makes parsing neater */
353 src++;
354 }
355
356 len = strlen(src);
357 for (i = 0; i < len; i++) {
358 if (!(src[i] >= '0' && src[i] <= '9') &&
359 !(src[i] >= 'A' && src[i] <= 'F') &&
360 !(src[i] >= 'a' && src[i] <= 'f') &&
361 src[i] != '.' && src[i] != ':') {
362 return -EINVAL;
363 }
364 }
365
366 for (i = 0; i < expected_groups; i++) {
367 char *tmp;
368
369 if (!src || *src == '\0') {
370 return -EINVAL;
371 }
372
373 if (*src != ':') {
374 /* Normal IPv6 16-bit piece */
375 UNALIGNED_PUT(htons(strtol(src, NULL, 16)),
376 &addr->s6_addr16[i]);
377 src = strchr(src, ':');
378 if (src) {
379 src++;
380 } else {
381 if (i < expected_groups - 1) {
382 return -EINVAL;
383 }
384 }
385
386 continue;
387 }
388
389 /* Two colons in a row */
390
391 for (; i < expected_groups; i++) {
392 UNALIGNED_PUT(0, &addr->s6_addr16[i]);
393 }
394
395 tmp = strrchr(src, ':');
396 if (src == tmp && (expected_groups == 6 || !src[1])) {
397 src++;
398 break;
399 }
400
401 if (expected_groups == 6) {
402 /* we need to drop the trailing
403 * colon since it's between the
404 * ipv6 and ipv4 addresses, rather than being
405 * a part of the ipv6 address
406 */
407 tmp--;
408 }
409
410 /* Calculate the amount of skipped zeros */
411 i = expected_groups - 1;
412 do {
413 if (*tmp == ':') {
414 i--;
415 }
416
417 if (i < 0) {
418 return -EINVAL;
419 }
420 } while (tmp-- != src);
421
422 src++;
423 }
424
425 if (expected_groups == 6) {
426 /* Parse the IPv4 part */
427 for (i = 0; i < 4; i++) {
428 if (!src || !*src) {
429 return -EINVAL;
430 }
431
432 addr->s6_addr[12 + i] = strtol(src, NULL, 10);
433
434 src = strchr(src, '.');
435 if (src) {
436 src++;
437 } else {
438 if (i < 3) {
439 return -EINVAL;
440 }
441 }
442 }
443 }
444 } else {
445 return -EINVAL;
446 }
447
448 return 0;
449 }
450
451 #if defined(CONFIG_USERSPACE)
z_vrfy_net_addr_pton(sa_family_t family,const char * src,void * dst)452 int z_vrfy_net_addr_pton(sa_family_t family, const char *src,
453 void *dst)
454 {
455 char str[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)] = {};
456 struct in6_addr addr6;
457 struct in_addr addr4;
458 void *addr;
459 size_t size;
460 int err;
461
462 if (family == AF_INET) {
463 size = sizeof(struct in_addr);
464 addr = &addr4;
465 } else if (family == AF_INET6) {
466 size = sizeof(struct in6_addr);
467 addr = &addr6;
468 } else {
469 return -EINVAL;
470 }
471
472 if (z_user_string_copy(str, (char *)src, sizeof(str)) != 0) {
473 return -EINVAL;
474 }
475
476 Z_OOPS(Z_SYSCALL_MEMORY_WRITE(dst, size));
477
478 err = z_impl_net_addr_pton(family, str, addr);
479 if (err) {
480 return err;
481 }
482
483 Z_OOPS(z_user_to_copy((void *)dst, addr, size));
484
485 return 0;
486 }
487 #include <syscalls/net_addr_pton_mrsh.c>
488 #endif /* CONFIG_USERSPACE */
489
calc_chksum(uint16_t sum,const uint8_t * data,size_t len)490 static uint16_t calc_chksum(uint16_t sum, const uint8_t *data, size_t len)
491 {
492 const uint8_t *end;
493 uint16_t tmp;
494
495 end = data + len - 1;
496
497 while (data < end) {
498 tmp = (data[0] << 8) + data[1];
499 sum += tmp;
500 if (sum < tmp) {
501 sum++;
502 }
503
504 data += 2;
505 }
506
507 if (data == end) {
508 tmp = data[0] << 8;
509 sum += tmp;
510 if (sum < tmp) {
511 sum++;
512 }
513 }
514
515 return sum;
516 }
517
pkt_calc_chksum(struct net_pkt * pkt,uint16_t sum)518 static inline uint16_t pkt_calc_chksum(struct net_pkt *pkt, uint16_t sum)
519 {
520 struct net_pkt_cursor *cur = &pkt->cursor;
521 size_t len;
522
523 if (!cur->buf || !cur->pos) {
524 return sum;
525 }
526
527 len = cur->buf->len - (cur->pos - cur->buf->data);
528
529 while (cur->buf) {
530 sum = calc_chksum(sum, cur->pos, len);
531
532 cur->buf = cur->buf->frags;
533 if (!cur->buf || !cur->buf->len) {
534 break;
535 }
536
537 cur->pos = cur->buf->data;
538
539 if (len % 2) {
540 sum += *cur->pos;
541 if (sum < *cur->pos) {
542 sum++;
543 }
544
545 cur->pos++;
546 len = cur->buf->len - 1;
547 } else {
548 len = cur->buf->len;
549 }
550 }
551
552 return sum;
553 }
554
net_calc_chksum(struct net_pkt * pkt,uint8_t proto)555 uint16_t net_calc_chksum(struct net_pkt *pkt, uint8_t proto)
556 {
557 size_t len = 0U;
558 uint16_t sum = 0U;
559 struct net_pkt_cursor backup;
560 bool ow;
561
562 if (IS_ENABLED(CONFIG_NET_IPV4) &&
563 net_pkt_family(pkt) == AF_INET) {
564 if (proto != IPPROTO_ICMP) {
565 len = 2 * sizeof(struct in_addr);
566 sum = net_pkt_get_len(pkt) -
567 net_pkt_ip_hdr_len(pkt) -
568 net_pkt_ipv4_opts_len(pkt) + proto;
569 }
570 } else if (IS_ENABLED(CONFIG_NET_IPV6) &&
571 net_pkt_family(pkt) == AF_INET6) {
572 len = 2 * sizeof(struct in6_addr);
573 sum = net_pkt_get_len(pkt) -
574 net_pkt_ip_hdr_len(pkt) -
575 net_pkt_ipv6_ext_len(pkt) + proto;
576 } else {
577 NET_DBG("Unknown protocol family %d", net_pkt_family(pkt));
578 return 0;
579 }
580
581 net_pkt_cursor_backup(pkt, &backup);
582 net_pkt_cursor_init(pkt);
583
584 ow = net_pkt_is_being_overwritten(pkt);
585 net_pkt_set_overwrite(pkt, true);
586
587 net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) - len);
588
589 sum = calc_chksum(sum, pkt->cursor.pos, len);
590 net_pkt_skip(pkt, len + net_pkt_ip_opts_len(pkt));
591
592 sum = pkt_calc_chksum(pkt, sum);
593
594 sum = (sum == 0U) ? 0xffff : htons(sum);
595
596 net_pkt_cursor_restore(pkt, &backup);
597
598 net_pkt_set_overwrite(pkt, ow);
599
600 return ~sum;
601 }
602
603 #if defined(CONFIG_NET_IPV4)
net_calc_chksum_ipv4(struct net_pkt * pkt)604 uint16_t net_calc_chksum_ipv4(struct net_pkt *pkt)
605 {
606 uint16_t sum;
607
608 sum = calc_chksum(0, pkt->buffer->data,
609 net_pkt_ip_hdr_len(pkt) +
610 net_pkt_ipv4_opts_len(pkt));
611
612 sum = (sum == 0U) ? 0xffff : htons(sum);
613
614 return ~sum;
615 }
616 #endif /* CONFIG_NET_IPV4 */
617
618 #if defined(CONFIG_NET_IPV4_IGMP)
net_calc_chksum_igmp(uint8_t * data,size_t len)619 uint16_t net_calc_chksum_igmp(uint8_t *data, size_t len)
620 {
621 uint16_t sum;
622
623 sum = calc_chksum(0, data, len);
624 sum = (sum == 0U) ? 0xffff : htons(sum);
625
626 return ~sum;
627 }
628 #endif /* CONFIG_NET_IPV4_IGMP */
629
630 #if defined(CONFIG_NET_IPV6) || defined(CONFIG_NET_IPV4)
convert_port(const char * buf,uint16_t * port)631 static bool convert_port(const char *buf, uint16_t *port)
632 {
633 unsigned long tmp;
634 char *endptr;
635
636 tmp = strtoul(buf, &endptr, 10);
637 if ((endptr == buf && tmp == 0) ||
638 !(*buf != '\0' && *endptr == '\0') ||
639 ((unsigned long)(unsigned short)tmp != tmp)) {
640 return false;
641 }
642
643 *port = tmp;
644
645 return true;
646 }
647 #endif /* CONFIG_NET_IPV6 || CONFIG_NET_IPV4 */
648
649 #if defined(CONFIG_NET_IPV6)
parse_ipv6(const char * str,size_t str_len,struct sockaddr * addr,bool has_port)650 static bool parse_ipv6(const char *str, size_t str_len,
651 struct sockaddr *addr, bool has_port)
652 {
653 char *ptr = NULL;
654 struct in6_addr *addr6;
655 char ipaddr[INET6_ADDRSTRLEN + 1];
656 int end, len, ret, i;
657 uint16_t port;
658
659 len = MIN(INET6_ADDRSTRLEN, str_len);
660
661 for (i = 0; i < len; i++) {
662 if (!str[i]) {
663 len = i;
664 break;
665 }
666 }
667
668 if (has_port) {
669 /* IPv6 address with port number */
670 ptr = memchr(str, ']', len);
671 if (!ptr) {
672 return false;
673 }
674
675 end = MIN(len, ptr - (str + 1));
676 memcpy(ipaddr, str + 1, end);
677 } else {
678 end = len;
679 memcpy(ipaddr, str, end);
680 }
681
682 ipaddr[end] = '\0';
683
684 addr6 = &net_sin6(addr)->sin6_addr;
685
686 ret = net_addr_pton(AF_INET6, ipaddr, addr6);
687 if (ret < 0) {
688 return false;
689 }
690
691 net_sin6(addr)->sin6_family = AF_INET6;
692
693 if (!has_port) {
694 return true;
695 }
696
697 if ((ptr + 1) < (str + str_len) && *(ptr + 1) == ':') {
698 /* -1 as end does not contain first [
699 * -2 as pointer is advanced by 2, skipping ]:
700 */
701 len = str_len - end - 1 - 2;
702
703 ptr += 2;
704
705 for (i = 0; i < len; i++) {
706 if (!ptr[i]) {
707 len = i;
708 break;
709 }
710 }
711
712 /* Re-use the ipaddr buf for port conversion */
713 memcpy(ipaddr, ptr, len);
714 ipaddr[len] = '\0';
715
716 ret = convert_port(ipaddr, &port);
717 if (!ret) {
718 return false;
719 }
720
721 net_sin6(addr)->sin6_port = htons(port);
722
723 NET_DBG("IPv6 host %s port %d",
724 log_strdup(net_addr_ntop(AF_INET6, addr6,
725 ipaddr, sizeof(ipaddr) - 1)),
726 port);
727 } else {
728 NET_DBG("IPv6 host %s",
729 log_strdup(net_addr_ntop(AF_INET6, addr6,
730 ipaddr, sizeof(ipaddr) - 1)));
731 }
732
733 return true;
734 }
735 #else
parse_ipv6(const char * str,size_t str_len,struct sockaddr * addr,bool has_port)736 static inline bool parse_ipv6(const char *str, size_t str_len,
737 struct sockaddr *addr, bool has_port)
738 {
739 return false;
740 }
741 #endif /* CONFIG_NET_IPV6 */
742
743 #if defined(CONFIG_NET_IPV4)
parse_ipv4(const char * str,size_t str_len,struct sockaddr * addr,bool has_port)744 static bool parse_ipv4(const char *str, size_t str_len,
745 struct sockaddr *addr, bool has_port)
746 {
747 char *ptr = NULL;
748 char ipaddr[NET_IPV4_ADDR_LEN + 1];
749 struct in_addr *addr4;
750 int end, len, ret, i;
751 uint16_t port;
752
753 len = MIN(NET_IPV4_ADDR_LEN, str_len);
754
755 for (i = 0; i < len; i++) {
756 if (!str[i]) {
757 len = i;
758 break;
759 }
760 }
761
762 if (has_port) {
763 /* IPv4 address with port number */
764 ptr = memchr(str, ':', len);
765 if (!ptr) {
766 return false;
767 }
768
769 end = MIN(len, ptr - str);
770 } else {
771 end = len;
772 }
773
774 memcpy(ipaddr, str, end);
775 ipaddr[end] = '\0';
776
777 addr4 = &net_sin(addr)->sin_addr;
778
779 ret = net_addr_pton(AF_INET, ipaddr, addr4);
780 if (ret < 0) {
781 return false;
782 }
783
784 net_sin(addr)->sin_family = AF_INET;
785
786 if (!has_port) {
787 return true;
788 }
789
790 memcpy(ipaddr, ptr + 1, str_len - end);
791 ipaddr[str_len - end] = '\0';
792
793 ret = convert_port(ipaddr, &port);
794 if (!ret) {
795 return false;
796 }
797
798 net_sin(addr)->sin_port = htons(port);
799
800 NET_DBG("IPv4 host %s port %d",
801 log_strdup(net_addr_ntop(AF_INET, addr4,
802 ipaddr, sizeof(ipaddr) - 1)),
803 port);
804 return true;
805 }
806 #else
parse_ipv4(const char * str,size_t str_len,struct sockaddr * addr,bool has_port)807 static inline bool parse_ipv4(const char *str, size_t str_len,
808 struct sockaddr *addr, bool has_port)
809 {
810 return false;
811 }
812 #endif /* CONFIG_NET_IPV4 */
813
net_ipaddr_parse(const char * str,size_t str_len,struct sockaddr * addr)814 bool net_ipaddr_parse(const char *str, size_t str_len, struct sockaddr *addr)
815 {
816 int i, count;
817
818 if (!str || str_len == 0) {
819 return false;
820 }
821
822 /* We cannot accept empty string here */
823 if (*str == '\0') {
824 return false;
825 }
826
827 if (*str == '[') {
828 return parse_ipv6(str, str_len, addr, true);
829 }
830
831 for (count = i = 0; str[i] && i < str_len; i++) {
832 if (str[i] == ':') {
833 count++;
834 }
835 }
836
837 if (count == 1) {
838 return parse_ipv4(str, str_len, addr, true);
839 }
840
841 #if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6)
842 if (!parse_ipv4(str, str_len, addr, false)) {
843 return parse_ipv6(str, str_len, addr, false);
844 }
845
846 return true;
847 #endif
848
849 #if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
850 return parse_ipv4(str, str_len, addr, false);
851 #endif
852
853 #if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
854 return parse_ipv6(str, str_len, addr, false);
855 #endif
856 return false;
857 }
858
net_bytes_from_str(uint8_t * buf,int buf_len,const char * src)859 int net_bytes_from_str(uint8_t *buf, int buf_len, const char *src)
860 {
861 unsigned int i;
862 char *endptr;
863
864 for (i = 0U; i < strlen(src); i++) {
865 if (!(src[i] >= '0' && src[i] <= '9') &&
866 !(src[i] >= 'A' && src[i] <= 'F') &&
867 !(src[i] >= 'a' && src[i] <= 'f') &&
868 src[i] != ':') {
869 return -EINVAL;
870 }
871 }
872
873 (void)memset(buf, 0, buf_len);
874
875 for (i = 0U; i < buf_len; i++) {
876 buf[i] = strtol(src, &endptr, 16);
877 src = ++endptr;
878 }
879
880 return 0;
881 }
882
net_family2str(sa_family_t family)883 const char *net_family2str(sa_family_t family)
884 {
885 switch (family) {
886 case AF_UNSPEC:
887 return "AF_UNSPEC";
888 case AF_INET:
889 return "AF_INET";
890 case AF_INET6:
891 return "AF_INET6";
892 case AF_PACKET:
893 return "AF_PACKET";
894 case AF_CAN:
895 return "AF_CAN";
896 }
897
898 return NULL;
899 }
900
net_ipv4_unspecified_address(void)901 const struct in_addr *net_ipv4_unspecified_address(void)
902 {
903 static const struct in_addr addr;
904
905 return &addr;
906 }
907
net_ipv4_broadcast_address(void)908 const struct in_addr *net_ipv4_broadcast_address(void)
909 {
910 static const struct in_addr addr = { { { 255, 255, 255, 255 } } };
911
912 return &addr;
913 }
914
915 /* IPv6 wildcard and loopback address defined by RFC2553 */
916 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
917 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
918
net_ipv6_unspecified_address(void)919 const struct in6_addr *net_ipv6_unspecified_address(void)
920 {
921 return &in6addr_any;
922 }
923