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 <zephyr/logging/log.h>
13 LOG_MODULE_REGISTER(net_utils, CONFIG_NET_UTILS_LOG_LEVEL);
14
15 #include <zephyr/kernel.h>
16 #include <stdlib.h>
17 #include <zephyr/internal/syscall_handler.h>
18 #include <zephyr/types.h>
19 #include <stdbool.h>
20 #include <string.h>
21 #include <ctype.h>
22 #include <errno.h>
23
24 #include <zephyr/sys/byteorder.h>
25 #include <zephyr/net/net_ip.h>
26 #include <zephyr/net/net_pkt.h>
27 #include <zephyr/net/net_core.h>
28 #include <zephyr/net/socketcan.h>
29
net_sprint_addr(net_sa_family_t af,const void * addr)30 char *net_sprint_addr(net_sa_family_t af, const void *addr)
31 {
32 #define NBUFS 3
33 static char buf[NBUFS][NET_IPV6_ADDR_LEN];
34 static int i;
35 char *s = buf[++i % NBUFS];
36
37 return net_addr_ntop(af, addr, s, NET_IPV6_ADDR_LEN);
38 }
39
net_verdict2str(enum net_verdict verdict)40 const char *net_verdict2str(enum net_verdict verdict)
41 {
42 if (verdict == NET_OK) {
43 return "NET_OK";
44 } else if (verdict == NET_CONTINUE) {
45 return "NET_CONTINUE";
46 } else if (verdict == NET_DROP) {
47 return "NET_DROP";
48 }
49
50 return "<unknown>";
51 }
52
net_proto2str(int family,int proto)53 const char *net_proto2str(int family, int proto)
54 {
55 if (family == NET_AF_INET || family == NET_AF_INET6) {
56 switch (proto) {
57 case NET_IPPROTO_ICMP:
58 return "ICMPv4";
59 case NET_IPPROTO_TCP:
60 return "TCP";
61 case NET_IPPROTO_UDP:
62 return "UDP";
63 case NET_IPPROTO_ICMPV6:
64 return "ICMPv6";
65 default:
66 break;
67 }
68 } else if (family == NET_AF_CAN) {
69 switch (proto) {
70 case NET_CAN_RAW:
71 return "CAN_RAW";
72 default:
73 break;
74 }
75 }
76
77 return "UNK_PROTO";
78 }
79
net_byte_to_hex(char * ptr,uint8_t byte,char base,bool pad)80 char *net_byte_to_hex(char *ptr, uint8_t byte, char base, bool pad)
81 {
82 uint8_t high = (byte >> 4) & 0x0f;
83 uint8_t low = byte & 0x0f;
84
85 if (pad || (high > 0)) {
86 *ptr++ = (high < 10) ? (char) (high + '0') : (char) (high - 10 + base);
87 }
88
89 *ptr++ = (low < 10) ? (char) (low + '0') : (char) (low - 10 + base);
90
91 *ptr = '\0';
92
93 return ptr;
94 }
95
net_sprint_ll_addr_buf(const uint8_t * ll,uint8_t ll_len,char * buf,int buflen)96 char *net_sprint_ll_addr_buf(const uint8_t *ll, uint8_t ll_len,
97 char *buf, int buflen)
98 {
99 uint8_t i, len, blen;
100 char *ptr = buf;
101
102 if (ll == NULL) {
103 return "<unknown>";
104 }
105
106 switch (ll_len) {
107 case 8:
108 len = 8U;
109 break;
110 case 6:
111 len = 6U;
112 break;
113 case 2:
114 len = 2U;
115 break;
116 default:
117 len = 6U;
118 break;
119 }
120
121 for (i = 0U, blen = buflen; i < len && blen > 0; i++) {
122 ptr = net_byte_to_hex(ptr, (char)ll[i], 'A', true);
123 *ptr++ = ':';
124 blen -= 3U;
125 }
126
127 if (!(ptr - buf)) {
128 return NULL;
129 }
130
131 *(ptr - 1) = '\0';
132 return buf;
133 }
134
net_value_to_udec(char * buf,uint32_t value,int precision)135 static int net_value_to_udec(char *buf, uint32_t value, int precision)
136 {
137 uint32_t divisor;
138 int i;
139 int temp;
140 char *start = buf;
141
142 divisor = 1000000000U;
143 if (precision < 0) {
144 precision = 1;
145 }
146
147 for (i = 9; i >= 0; i--, divisor /= 10U) {
148 temp = value / divisor;
149 value = value % divisor;
150 if ((precision > i) || (temp != 0)) {
151 precision = i;
152 *buf++ = (char) (temp + '0');
153 }
154 }
155 *buf = 0;
156
157 return buf - start;
158 }
159
z_impl_net_addr_ntop(net_sa_family_t family,const void * src,char * dst,size_t size)160 char *z_impl_net_addr_ntop(net_sa_family_t family, const void *src,
161 char *dst, size_t size)
162 {
163 struct net_in_addr addr = { 0 };
164 struct net_in6_addr addr6 = { 0 };
165 uint16_t *w = NULL;
166 int i;
167 uint8_t longest = 1U;
168 int pos = -1;
169 char delim = ':';
170 uint8_t zeros[8] = { 0 };
171 char *ptr = dst;
172 int len = -1;
173 uint16_t value;
174 bool needcolon = false;
175 bool mapped = false;
176
177 switch (family) {
178 case NET_AF_INET6:
179 if (size < NET_INET6_ADDRSTRLEN) {
180 /* POSIX definition is the size - includes nil */
181 return NULL;
182 }
183
184 net_ipv6_addr_copy_raw(addr6.s6_addr, src);
185 w = (uint16_t *)addr6.s6_addr16;
186 len = 8;
187
188 if (net_ipv6_addr_is_v4_mapped(&addr6)) {
189 mapped = true;
190 }
191
192 for (i = 0; i < 8; i++) {
193 for (int j = i; j < 8; j++) {
194 if (w[j] != 0) {
195 break;
196 }
197
198 zeros[i]++;
199 }
200 }
201
202 for (i = 0; i < 8; i++) {
203 if (zeros[i] > longest) {
204 longest = zeros[i];
205 pos = i;
206 }
207 }
208
209 if (longest == 1U) {
210 pos = -1;
211 }
212 break;
213
214 case NET_AF_INET:
215 if (size < NET_INET_ADDRSTRLEN) {
216 /* POSIX definition is the size - includes nil */
217 return NULL;
218 }
219
220 net_ipv4_addr_copy_raw(addr.s4_addr, src);
221 len = 4;
222 delim = '.';
223 break;
224
225 default:
226 return NULL;
227 }
228
229 print_mapped:
230 for (i = 0; i < len; i++) {
231 /* IPv4 address a.b.c.d */
232 if (len == 4) {
233 uint8_t l;
234
235 value = (uint16_t)addr.s4_addr[i];
236
237 /* net_byte_to_udec() eats 0 */
238 if (value == 0U) {
239 *ptr++ = '0';
240 *ptr++ = delim;
241 continue;
242 }
243
244 l = net_value_to_udec(ptr, value, 0);
245
246 ptr += l;
247 *ptr++ = delim;
248
249 continue;
250 }
251
252 if (mapped && (i > 5)) {
253 delim = '.';
254 len = 4;
255 addr.s_addr = addr6.s6_addr32[3];
256 *ptr++ = ':';
257 family = NET_AF_INET;
258 goto print_mapped;
259 }
260
261 /* IPv6 address */
262 if (i == pos) {
263 if (needcolon || i == 0U) {
264 *ptr++ = ':';
265 }
266
267 *ptr++ = ':';
268 needcolon = false;
269 i += (int)longest - 1;
270
271 continue;
272 }
273
274 if (needcolon) {
275 *ptr++ = ':';
276 }
277
278 value = sys_be16_to_cpu(UNALIGNED_GET(&w[i]));
279 uint8_t bh = value >> 8;
280 uint8_t bl = value & 0xff;
281
282 if (bh) {
283 /* Convert high byte to hex without padding */
284 ptr = net_byte_to_hex(ptr, bh, 'a', false);
285
286 /* Always pad the low byte, since high byte is non - zero */
287 ptr = net_byte_to_hex(ptr, bl, 'a', true);
288 } else {
289 /* For the case where the high byte is zero, only process the low byte
290 * Do not pad the low byte, since high byte is zero
291 */
292 ptr = net_byte_to_hex(ptr, bl, 'a', false);
293 }
294
295 needcolon = true;
296 }
297
298 if (family == NET_AF_INET) {
299 *(ptr - 1) = '\0';
300 } else {
301 *ptr = '\0';
302 }
303
304 return dst;
305 }
306
307 #if defined(CONFIG_USERSPACE)
z_vrfy_net_addr_ntop(net_sa_family_t family,const void * src,char * dst,size_t size)308 char *z_vrfy_net_addr_ntop(net_sa_family_t family, const void *src,
309 char *dst, size_t size)
310 {
311 char str[NET_INET6_ADDRSTRLEN];
312 struct net_in6_addr addr6;
313 struct net_in_addr addr4;
314 char *out;
315 const void *addr;
316
317 K_OOPS(K_SYSCALL_MEMORY_WRITE(dst, size));
318
319 if (family == NET_AF_INET) {
320 K_OOPS(k_usermode_from_copy(&addr4, (const void *)src,
321 sizeof(addr4)));
322 addr = &addr4;
323 } else if (family == NET_AF_INET6) {
324 K_OOPS(k_usermode_from_copy(&addr6, (const void *)src,
325 sizeof(addr6)));
326 addr = &addr6;
327 } else {
328 return 0;
329 }
330
331 out = z_impl_net_addr_ntop(family, addr, str, sizeof(str));
332 if (!out) {
333 return 0;
334 }
335
336 K_OOPS(k_usermode_to_copy((void *)dst, str, MIN(size, sizeof(str))));
337
338 return dst;
339 }
340 #include <zephyr/syscalls/net_addr_ntop_mrsh.c>
341 #endif /* CONFIG_USERSPACE */
342
z_impl_net_addr_pton(net_sa_family_t family,const char * src,void * dst)343 int z_impl_net_addr_pton(net_sa_family_t family, const char *src,
344 void *dst)
345 {
346 if (family == NET_AF_INET) {
347 struct net_in_addr *addr = (struct net_in_addr *)dst;
348 uint8_t index = 0, digits = 0;
349 uint16_t value = 0, count = 0;
350
351 (void)memset(addr, 0, sizeof(struct net_in_addr));
352
353 /* A valid IPv4 address that can be used with inet_pton
354 * must be in the standard dotted-decimal notation:
355 *
356 * - Four octets, each ranging from 0 to 255
357 * - Separated by dots (.)
358 * - No leading zeros in each octet
359 */
360
361 while (index < sizeof(struct net_in_addr)) {
362 if (*src == '\0' || *src == '.') {
363 if (*src == '.') {
364 count++;
365 }
366
367 if ((digits > 1 && value < 10) ||
368 (digits > 2 && value < 100)) {
369 /* Preceding zeroes */
370 return -EINVAL;
371 }
372
373 if (digits == 0 || value > UINT8_MAX) {
374 return -EINVAL;
375 }
376
377 addr->s4_addr[index] = value;
378
379 if (*src == '\0') {
380 break;
381 }
382
383 index++;
384 digits = 0;
385 value = 0;
386 } else if ('0' <= *src && *src <= '9') {
387 if (++digits > 3) {
388 /* Number too large */
389 return -EINVAL;
390 }
391
392 value *= 10;
393 value += *src - '0';
394 } else {
395 /* Invalid character */
396 return -EINVAL;
397 }
398
399 src++;
400 }
401
402 if (count != 3) {
403 /* Three dots needed */
404 return -EINVAL;
405 }
406
407 } else if (family == NET_AF_INET6) {
408 /* If the string contains a '.', it means it's of the form
409 * X:X:X:X:X:X:x.x.x.x, and contains only 6 16-bit pieces
410 */
411 int expected_groups = strchr(src, '.') ? 6 : 8;
412 struct net_in6_addr *addr = (struct net_in6_addr *)dst;
413 int i, len;
414
415 if (*src == ':') {
416 /* Ignore a leading colon, makes parsing neater */
417 src++;
418 }
419
420 len = strlen(src);
421 for (i = 0; i < len; i++) {
422 if (!(src[i] >= '0' && src[i] <= '9') &&
423 !(src[i] >= 'A' && src[i] <= 'F') &&
424 !(src[i] >= 'a' && src[i] <= 'f') &&
425 src[i] != '.' && src[i] != ':') {
426 return -EINVAL;
427 }
428 }
429
430 for (i = 0; i < expected_groups; i++) {
431 char *tmp;
432
433 if (!src || *src == '\0') {
434 return -EINVAL;
435 }
436
437 if (*src != ':') {
438 /* Normal IPv6 16-bit piece */
439 UNALIGNED_PUT(net_htons(strtol(src, NULL, 16)),
440 &addr->s6_addr16[i]);
441 src = strchr(src, ':');
442 if (src) {
443 src++;
444 } else {
445 if (i < expected_groups - 1) {
446 return -EINVAL;
447 }
448 }
449
450 continue;
451 }
452
453 /* Two colons in a row */
454
455 for (; i < expected_groups; i++) {
456 UNALIGNED_PUT(0, &addr->s6_addr16[i]);
457 }
458
459 tmp = strrchr(src, ':');
460 if (src == tmp && (expected_groups == 6 || !src[1])) {
461 src++;
462 break;
463 }
464
465 if (expected_groups == 6) {
466 /* we need to drop the trailing
467 * colon since it's between the
468 * ipv6 and ipv4 addresses, rather than being
469 * a part of the ipv6 address
470 */
471 tmp--;
472 }
473
474 /* Calculate the amount of skipped zeros */
475 i = expected_groups - 1;
476 do {
477 if (*tmp == ':') {
478 i--;
479 }
480
481 if (i < 0) {
482 return -EINVAL;
483 }
484 } while (tmp-- != src);
485
486 src++;
487 }
488
489 if (expected_groups == 6) {
490 /* Parse the IPv4 part */
491 for (i = 0; i < 4; i++) {
492 if (!src || !*src) {
493 return -EINVAL;
494 }
495
496 addr->s6_addr[12 + i] = strtol(src, NULL, 10);
497
498 src = strchr(src, '.');
499 if (src) {
500 src++;
501 } else {
502 if (i < 3) {
503 return -EINVAL;
504 }
505 }
506 }
507 }
508 } else {
509 return -EINVAL;
510 }
511
512 return 0;
513 }
514
515 #if defined(CONFIG_USERSPACE)
z_vrfy_net_addr_pton(net_sa_family_t family,const char * src,void * dst)516 int z_vrfy_net_addr_pton(net_sa_family_t family, const char *src,
517 void *dst)
518 {
519 char str[MAX(NET_INET_ADDRSTRLEN, NET_INET6_ADDRSTRLEN)] = {};
520 struct net_in6_addr addr6;
521 struct net_in_addr addr4;
522 void *addr;
523 size_t size;
524 int err;
525
526 if (family == NET_AF_INET) {
527 size = sizeof(struct net_in_addr);
528 addr = &addr4;
529 } else if (family == NET_AF_INET6) {
530 size = sizeof(struct net_in6_addr);
531 addr = &addr6;
532 } else {
533 return -EINVAL;
534 }
535
536 if (k_usermode_string_copy(str, (char *)src, sizeof(str)) != 0) {
537 return -EINVAL;
538 }
539
540 K_OOPS(K_SYSCALL_MEMORY_WRITE(dst, size));
541
542 err = z_impl_net_addr_pton(family, str, addr);
543 if (err) {
544 return err;
545 }
546
547 K_OOPS(k_usermode_to_copy((void *)dst, addr, size));
548
549 return 0;
550 }
551 #include <zephyr/syscalls/net_addr_pton_mrsh.c>
552 #endif /* CONFIG_USERSPACE */
553
554
555 #ifdef CONFIG_LITTLE_ENDIAN
556 #define CHECKSUM_BIG_ENDIAN 0
557 #else
558 #define CHECKSUM_BIG_ENDIAN 1
559 #endif
560
offset_based_swap8(const uint8_t * data)561 static uint16_t offset_based_swap8(const uint8_t *data)
562 {
563 uint16_t data16 = (uint16_t)*data;
564
565 if (((uintptr_t)(data) & 1) == CHECKSUM_BIG_ENDIAN) {
566 return data16;
567 } else {
568 return data16 << 8;
569 }
570 }
571
572 /* Word based checksum calculation based on:
573 * https://blogs.igalia.com/dpino/2018/06/14/fast-checksum-computation/
574 * It’s not necessary to add octets as 16-bit words. Due to the associative property of addition,
575 * it is possible to do parallel addition using larger word sizes such as 32-bit or 64-bit words.
576 * In those cases the variable that stores the accumulative sum has to be bigger too.
577 * Once the sum is computed a final step folds the sum to a 16-bit word (adding carry if any).
578 */
calc_chksum(uint16_t sum_in,const uint8_t * data,size_t len)579 uint16_t calc_chksum(uint16_t sum_in, const uint8_t *data, size_t len)
580 {
581 uint64_t sum;
582 uint32_t *p;
583 size_t i = 0;
584 size_t pending = len;
585 int odd_start = ((uintptr_t)data & 0x01);
586
587 /* Sum in is in host endianness, working order endianness is both dependent on endianness
588 * and the offset of starting
589 */
590 if (odd_start == CHECKSUM_BIG_ENDIAN) {
591 sum = BSWAP_16(sum_in);
592 } else {
593 sum = sum_in;
594 }
595
596 /* Process up to 3 data elements up front, so the data is aligned further down the line */
597 if ((((uintptr_t)data & 0x01) != 0) && (pending >= 1)) {
598 sum += offset_based_swap8(data);
599 data++;
600 pending--;
601 }
602 if ((((uintptr_t)data & 0x02) != 0) && (pending >= sizeof(uint16_t))) {
603 pending -= sizeof(uint16_t);
604 sum = sum + *((uint16_t *)data);
605 data += sizeof(uint16_t);
606 }
607 p = (uint32_t *)data;
608
609 /* Do loop unrolling for the very large data sets */
610 while (pending >= sizeof(uint32_t) * 4) {
611 uint64_t sum_a = p[i];
612 uint64_t sum_b = p[i + 1];
613
614 pending -= sizeof(uint32_t) * 4;
615 sum_a += p[i + 2];
616 sum_b += p[i + 3];
617 i += 4;
618 sum += sum_a + sum_b;
619 }
620 while (pending >= sizeof(uint32_t)) {
621 pending -= sizeof(uint32_t);
622 sum = sum + p[i++];
623 }
624 data = (uint8_t *)(p + i);
625 if (pending >= 2) {
626 pending -= sizeof(uint16_t);
627 sum = sum + *((uint16_t *)data);
628 data += sizeof(uint16_t);
629 }
630 if (pending == 1) {
631 sum += offset_based_swap8(data);
632 }
633
634 /* Fold sum into 16-bit word. */
635 while (sum >> 16) {
636 sum = (sum & 0xffff) + (sum >> 16);
637 }
638
639 /* Sum in is in host endianness, working order endianness is both dependent on endianness
640 * and the offset of starting
641 */
642 if (odd_start == CHECKSUM_BIG_ENDIAN) {
643 return BSWAP_16((uint16_t)sum);
644 } else {
645 return sum;
646 }
647 }
648
649 #if defined(CONFIG_NET_NATIVE_IP)
pkt_calc_chksum(struct net_pkt * pkt,uint16_t sum)650 static inline uint16_t pkt_calc_chksum(struct net_pkt *pkt, uint16_t sum)
651 {
652 struct net_pkt_cursor *cur = &pkt->cursor;
653 size_t len;
654
655 if (!cur->buf || !cur->pos) {
656 return sum;
657 }
658
659 len = cur->buf->len - (cur->pos - cur->buf->data);
660
661 while (cur->buf) {
662 sum = calc_chksum(sum, cur->pos, len);
663
664 cur->buf = cur->buf->frags;
665 if (!cur->buf || !cur->buf->len) {
666 break;
667 }
668
669 cur->pos = cur->buf->data;
670
671 if (len % 2) {
672 sum += *cur->pos;
673 if (sum < *cur->pos) {
674 sum++;
675 }
676
677 cur->pos++;
678 len = cur->buf->len - 1;
679 } else {
680 len = cur->buf->len;
681 }
682 }
683
684 return sum;
685 }
686
net_calc_chksum(struct net_pkt * pkt,uint8_t proto)687 uint16_t net_calc_chksum(struct net_pkt *pkt, uint8_t proto)
688 {
689 size_t len = 0U;
690 uint16_t sum = 0U;
691 struct net_pkt_cursor backup;
692 bool ow;
693
694 if (IS_ENABLED(CONFIG_NET_IPV4) &&
695 net_pkt_family(pkt) == NET_AF_INET) {
696 if (proto != NET_IPPROTO_ICMP && proto != NET_IPPROTO_IGMP) {
697 len = 2 * sizeof(struct net_in_addr);
698 sum = net_pkt_get_len(pkt) -
699 net_pkt_ip_hdr_len(pkt) -
700 net_pkt_ipv4_opts_len(pkt) + proto;
701 }
702 } else if (IS_ENABLED(CONFIG_NET_IPV6) &&
703 net_pkt_family(pkt) == NET_AF_INET6) {
704 len = 2 * sizeof(struct net_in6_addr);
705 sum = net_pkt_get_len(pkt) -
706 net_pkt_ip_hdr_len(pkt) -
707 net_pkt_ipv6_ext_len(pkt) + proto;
708 } else {
709 NET_DBG("Unknown protocol family %d", net_pkt_family(pkt));
710 return 0;
711 }
712
713 net_pkt_cursor_backup(pkt, &backup);
714 net_pkt_cursor_init(pkt);
715
716 ow = net_pkt_is_being_overwritten(pkt);
717 net_pkt_set_overwrite(pkt, true);
718
719 net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) - len);
720
721 sum = calc_chksum(sum, pkt->cursor.pos, len);
722 net_pkt_skip(pkt, len + net_pkt_ip_opts_len(pkt));
723
724 sum = pkt_calc_chksum(pkt, sum);
725
726 sum = (sum == 0U) ? 0xffff : net_htons(sum);
727
728 net_pkt_cursor_restore(pkt, &backup);
729
730 net_pkt_set_overwrite(pkt, ow);
731
732 return ~sum;
733 }
734 #endif
735
736 #if defined(CONFIG_NET_NATIVE_IPV4)
net_calc_chksum_ipv4(struct net_pkt * pkt)737 uint16_t net_calc_chksum_ipv4(struct net_pkt *pkt)
738 {
739 uint16_t sum;
740
741 sum = calc_chksum(0, pkt->buffer->data,
742 net_pkt_ip_hdr_len(pkt) +
743 net_pkt_ipv4_opts_len(pkt));
744
745 sum = (sum == 0U) ? 0xffff : net_htons(sum);
746
747 return ~sum;
748 }
749 #endif /* CONFIG_NET_NATIVE_IPV4 */
750
751 #if defined(CONFIG_NET_IPV4_IGMP)
net_calc_chksum_igmp(struct net_pkt * pkt)752 uint16_t net_calc_chksum_igmp(struct net_pkt *pkt)
753 {
754 return net_calc_chksum(pkt, NET_IPPROTO_IGMP);
755 }
756 #endif /* CONFIG_NET_IPV4_IGMP */
757
758 #if defined(CONFIG_NET_IP)
convert_port(const char * buf,uint16_t * port)759 static bool convert_port(const char *buf, uint16_t *port)
760 {
761 unsigned long tmp;
762 char *endptr;
763
764 tmp = strtoul(buf, &endptr, 10);
765 if ((endptr == buf && tmp == 0) ||
766 !(*buf != '\0' && *endptr == '\0') ||
767 ((unsigned long)(unsigned short)tmp != tmp)) {
768 return false;
769 }
770
771 *port = tmp;
772
773 return true;
774 }
775 #endif /* CONFIG_NET_IP */
776
777 #if defined(CONFIG_NET_IPV6)
parse_ipv6(const char * str,size_t str_len,struct net_sockaddr * addr,bool has_port)778 static bool parse_ipv6(const char *str, size_t str_len,
779 struct net_sockaddr *addr, bool has_port)
780 {
781 char *ptr = NULL;
782 struct net_in6_addr *addr6;
783 char ipaddr[NET_INET6_ADDRSTRLEN + 1];
784 int end, len, ret, i;
785 uint16_t port;
786
787 len = MIN(NET_INET6_ADDRSTRLEN, str_len);
788
789 for (i = 0; i < len; i++) {
790 if (!str[i]) {
791 len = i;
792 break;
793 }
794 }
795
796 if (has_port) {
797 /* IPv6 address with port number */
798 ptr = memchr(str, ']', len);
799 if (!ptr) {
800 return false;
801 }
802
803 end = MIN(len, ptr - (str + 1));
804 memcpy(ipaddr, str + 1, end);
805 } else {
806 end = len;
807 memcpy(ipaddr, str, end);
808 }
809
810 ipaddr[end] = '\0';
811
812 addr6 = &net_sin6(addr)->sin6_addr;
813
814 ret = net_addr_pton(NET_AF_INET6, ipaddr, addr6);
815 if (ret < 0) {
816 return false;
817 }
818
819 net_sin6(addr)->sin6_family = NET_AF_INET6;
820
821 if (!has_port) {
822 return true;
823 }
824
825 if ((ptr + 1) < (str + str_len) && *(ptr + 1) == ':') {
826 /* -1 as end does not contain first [
827 * -2 as pointer is advanced by 2, skipping ]:
828 */
829 len = str_len - end - 1 - 2;
830
831 ptr += 2;
832
833 for (i = 0; i < len; i++) {
834 if (!ptr[i]) {
835 len = i;
836 break;
837 }
838 }
839
840 /* Re-use the ipaddr buf for port conversion */
841 memcpy(ipaddr, ptr, len);
842 ipaddr[len] = '\0';
843
844 ret = convert_port(ipaddr, &port);
845 if (!ret) {
846 return false;
847 }
848
849 net_sin6(addr)->sin6_port = net_htons(port);
850
851 NET_DBG("IPv6 host %s port %d",
852 net_addr_ntop(NET_AF_INET6, addr6, ipaddr, sizeof(ipaddr) - 1),
853 port);
854 } else {
855 NET_DBG("IPv6 host %s",
856 net_addr_ntop(NET_AF_INET6, addr6, ipaddr, sizeof(ipaddr) - 1));
857 }
858
859 return true;
860 }
861 #else
parse_ipv6(const char * str,size_t str_len,struct net_sockaddr * addr,bool has_port)862 static inline bool parse_ipv6(const char *str, size_t str_len,
863 struct net_sockaddr *addr, bool has_port)
864 {
865 return false;
866 }
867 #endif /* CONFIG_NET_IPV6 */
868
869 #if defined(CONFIG_NET_IPV4)
parse_ipv4(const char * str,size_t str_len,struct net_sockaddr * addr,bool has_port)870 static bool parse_ipv4(const char *str, size_t str_len,
871 struct net_sockaddr *addr, bool has_port)
872 {
873 char *ptr = NULL;
874 char ipaddr[NET_IPV4_ADDR_LEN + 1];
875 struct net_in_addr *addr4;
876 int end, len, ret, i;
877 uint16_t port;
878
879 len = MIN(NET_IPV4_ADDR_LEN, str_len);
880
881 for (i = 0; i < len; i++) {
882 if (!str[i]) {
883 len = i;
884 break;
885 }
886 }
887
888 if (has_port) {
889 /* IPv4 address with port number */
890 ptr = memchr(str, ':', len);
891 if (!ptr) {
892 return false;
893 }
894
895 end = MIN(len, ptr - str);
896 } else {
897 end = len;
898 }
899
900 memcpy(ipaddr, str, end);
901 ipaddr[end] = '\0';
902
903 addr4 = &net_sin(addr)->sin_addr;
904
905 ret = net_addr_pton(NET_AF_INET, ipaddr, addr4);
906 if (ret < 0) {
907 return false;
908 }
909
910 net_sin(addr)->sin_family = NET_AF_INET;
911
912 if (!has_port) {
913 return true;
914 }
915
916 memcpy(ipaddr, ptr + 1, str_len - end - 1);
917 ipaddr[str_len - end - 1] = '\0';
918
919 ret = convert_port(ipaddr, &port);
920 if (!ret) {
921 return false;
922 }
923
924 net_sin(addr)->sin_port = net_htons(port);
925
926 NET_DBG("IPv4 host %s port %d",
927 net_addr_ntop(NET_AF_INET, addr4, ipaddr, sizeof(ipaddr) - 1),
928 port);
929 return true;
930 }
931 #else
parse_ipv4(const char * str,size_t str_len,struct net_sockaddr * addr,bool has_port)932 static inline bool parse_ipv4(const char *str, size_t str_len,
933 struct net_sockaddr *addr, bool has_port)
934 {
935 return false;
936 }
937 #endif /* CONFIG_NET_IPV4 */
938
net_ipaddr_parse(const char * str,size_t str_len,struct net_sockaddr * addr)939 bool net_ipaddr_parse(const char *str, size_t str_len, struct net_sockaddr *addr)
940 {
941 int i, count;
942
943 if (!str || str_len == 0) {
944 return false;
945 }
946
947 /* We cannot accept empty string here */
948 if (*str == '\0') {
949 return false;
950 }
951
952 if (*str == '[') {
953 return parse_ipv6(str, str_len, addr, true);
954 }
955
956 for (count = i = 0; i < str_len && str[i]; i++) {
957 if (str[i] == ':') {
958 count++;
959 }
960 }
961
962 if (count == 1) {
963 return parse_ipv4(str, str_len, addr, true);
964 }
965
966 #if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6)
967 if (!parse_ipv4(str, str_len, addr, false)) {
968 return parse_ipv6(str, str_len, addr, false);
969 }
970
971 return true;
972 #endif
973
974 #if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
975 return parse_ipv4(str, str_len, addr, false);
976 #endif
977
978 #if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
979 return parse_ipv6(str, str_len, addr, false);
980 #endif
981 return false;
982 }
983
net_ipaddr_parse_mask(const char * str,size_t str_len,struct net_sockaddr * addr,uint8_t * mask_len)984 const char *net_ipaddr_parse_mask(const char *str, size_t str_len,
985 struct net_sockaddr *addr, uint8_t *mask_len)
986 {
987 const char *next = NULL, *mask_ptr = NULL;
988 int parsed_mask_len = -1;
989 bool ret = false;
990
991 if (str == NULL || str_len == 0 || addr == NULL || mask_len == NULL) {
992 return NULL;
993 }
994
995 if (*str == '\0') {
996 return NULL;
997 }
998
999 for (int i = 0; i < str_len; i++) {
1000 if (str[i] == ',' || str[i] == ' ') {
1001 next = str + i + 1;
1002 str_len = next - str - 1;
1003 break;
1004 }
1005
1006 if (str[i] == '/') {
1007 mask_ptr = str + i;
1008 }
1009 }
1010
1011 if (mask_ptr != NULL) {
1012 char *endptr;
1013
1014 parsed_mask_len = strtoul(mask_ptr + 1, &endptr, 10);
1015 if (*endptr != '\0') {
1016 if (next == NULL) {
1017 return NULL;
1018 }
1019 }
1020
1021 str_len = mask_ptr - str;
1022 *mask_len = (uint8_t)parsed_mask_len;
1023 }
1024
1025 #if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6)
1026 ret = parse_ipv4(str, str_len, addr, false);
1027 if (!ret) {
1028 ret = parse_ipv6(str, str_len, addr, false);
1029 }
1030 #elif defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
1031 ret = parse_ipv4(str, str_len, addr, false);
1032
1033 #elif defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
1034 ret = parse_ipv6(str, str_len, addr, false);
1035 #endif
1036
1037 if (!ret) {
1038 return NULL;
1039 }
1040
1041 if (parsed_mask_len < 0) {
1042 if (addr->sa_family == NET_AF_INET) {
1043 *mask_len = 32;
1044 } else if (addr->sa_family == NET_AF_INET6) {
1045 *mask_len = 128;
1046 }
1047 }
1048
1049 if (next != NULL) {
1050 return next;
1051 }
1052
1053 return "";
1054 }
1055
net_mask_len_to_netmask(net_sa_family_t family,uint8_t mask_len,struct net_sockaddr * mask)1056 int net_mask_len_to_netmask(net_sa_family_t family, uint8_t mask_len, struct net_sockaddr *mask)
1057 {
1058 if (family == NET_AF_INET) {
1059 struct net_in_addr *addr4 = &net_sin(mask)->sin_addr;
1060 struct net_sockaddr_in *mask4 = (struct net_sockaddr_in *)mask;
1061
1062 if (mask_len > 32) {
1063 return -ERANGE;
1064 }
1065
1066 memset(mask4, 0, sizeof(struct net_sockaddr_in));
1067
1068 mask4->sin_family = NET_AF_INET;
1069 mask4->sin_port = 0;
1070 addr4->s_addr = net_htonl(UINT32_MAX << (32 - mask_len));
1071
1072 } else if (family == NET_AF_INET6) {
1073 struct net_in6_addr *addr6 = &net_sin6(mask)->sin6_addr;
1074 struct net_sockaddr_in6 *mask6 = (struct net_sockaddr_in6 *)mask;
1075 uint32_t mask_val[4] = { 0 };
1076
1077 if (mask_len > 128) {
1078 return -ERANGE;
1079 }
1080
1081 memset(mask6, 0, sizeof(struct net_sockaddr_in6));
1082
1083 mask6->sin6_family = NET_AF_INET6;
1084 mask6->sin6_port = 0;
1085
1086 for (int i = 0; i < 4; i++) {
1087 int bits = mask_len - i * 32;
1088
1089 if (bits >= 32) {
1090 mask_val[i] = UINT32_MAX;
1091 } else if (bits > 0) {
1092 mask_val[i] = net_htonl(UINT32_MAX << (32 - bits));
1093 }
1094 }
1095
1096 memcpy(addr6->s6_addr32, mask_val, sizeof(mask_val));
1097 } else {
1098 return -EINVAL;
1099 }
1100
1101 return 0;
1102 }
1103
net_netmask_to_mask_len(net_sa_family_t family,struct net_sockaddr * mask,uint8_t * mask_len)1104 int net_netmask_to_mask_len(net_sa_family_t family, struct net_sockaddr *mask, uint8_t *mask_len)
1105 {
1106 int zerobits = 0;
1107 int maxlen;
1108 uint8_t n;
1109
1110 if (mask_len == NULL || mask == NULL) {
1111 return -EINVAL;
1112 }
1113
1114 if (family != NET_AF_INET && family != NET_AF_INET6) {
1115 return -EINVAL;
1116 }
1117
1118 maxlen = family == NET_AF_INET ? sizeof(struct net_in_addr) :
1119 sizeof(struct net_in6_addr);
1120
1121 for (int i = maxlen - 1; i >= 0; i--) {
1122 n = net_sin6(mask)->sin6_addr.s6_addr[i];
1123
1124 for (int j = 0; j < 8; j++) {
1125 if ((n & 0x1) == 0) {
1126 zerobits++;
1127 } else {
1128 break;
1129 }
1130
1131 n = n >> 1;
1132 }
1133 }
1134
1135 *mask_len = maxlen * 8 - zerobits;
1136
1137 return 0;
1138 }
1139
net_port_set_default(struct net_sockaddr * addr,uint16_t default_port)1140 int net_port_set_default(struct net_sockaddr *addr, uint16_t default_port)
1141 {
1142 if (IS_ENABLED(CONFIG_NET_IPV4) && addr->sa_family == NET_AF_INET &&
1143 net_sin(addr)->sin_port == 0) {
1144 net_sin(addr)->sin_port = net_htons(default_port);
1145 } else if (IS_ENABLED(CONFIG_NET_IPV6) && addr->sa_family == NET_AF_INET6 &&
1146 net_sin6(addr)->sin6_port == 0) {
1147 net_sin6(addr)->sin6_port = net_htons(default_port);
1148 } else if ((IS_ENABLED(CONFIG_NET_IPV4) && addr->sa_family == NET_AF_INET) ||
1149 (IS_ENABLED(CONFIG_NET_IPV6) && addr->sa_family == NET_AF_INET6)) {
1150 ; /* Port is already set */
1151 } else {
1152 LOG_ERR("Unknown address family");
1153 return -EINVAL;
1154 }
1155
1156 return 0;
1157 }
1158
net_bytes_from_str(uint8_t * buf,int buf_len,const char * src)1159 int net_bytes_from_str(uint8_t *buf, int buf_len, const char *src)
1160 {
1161 size_t i;
1162 size_t src_len = strlen(src);
1163 char *endptr;
1164
1165 for (i = 0U; i < src_len; i++) {
1166 if (!isxdigit((unsigned char)src[i]) &&
1167 src[i] != ':') {
1168 return -EINVAL;
1169 }
1170 }
1171
1172 (void)memset(buf, 0, buf_len);
1173
1174 for (i = 0U; i < (size_t)buf_len; i++) {
1175 buf[i] = (uint8_t)strtol(src, &endptr, 16);
1176 src = ++endptr;
1177 }
1178
1179 return 0;
1180 }
1181
net_family2str(net_sa_family_t family)1182 const char *net_family2str(net_sa_family_t family)
1183 {
1184 switch (family) {
1185 case NET_AF_UNSPEC:
1186 return "AF_UNSPEC";
1187 case NET_AF_INET:
1188 return "AF_INET";
1189 case NET_AF_INET6:
1190 return "AF_INET6";
1191 case NET_AF_PACKET:
1192 return "AF_PACKET";
1193 case NET_AF_CAN:
1194 return "AF_CAN";
1195 }
1196
1197 return NULL;
1198 }
1199
net_ipv4_unspecified_address(void)1200 const struct net_in_addr *net_ipv4_unspecified_address(void)
1201 {
1202 static const struct net_in_addr addr;
1203
1204 return &addr;
1205 }
1206
net_ipv4_broadcast_address(void)1207 const struct net_in_addr *net_ipv4_broadcast_address(void)
1208 {
1209 static const struct net_in_addr addr = { { { 255, 255, 255, 255 } } };
1210
1211 return &addr;
1212 }
1213
1214 /* IPv6 wildcard and loopback address defined by RFC2553 */
1215 const struct net_in6_addr net_in6addr_any = NET_IN6ADDR_ANY_INIT;
1216 const struct net_in6_addr net_in6addr_loopback = NET_IN6ADDR_LOOPBACK_INIT;
1217
net_ipv6_unspecified_address(void)1218 const struct net_in6_addr *net_ipv6_unspecified_address(void)
1219 {
1220 return &net_in6addr_any;
1221 }
1222