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(sa_family_t af,const void * addr)30 char *net_sprint_addr(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 == AF_INET || family == AF_INET6) {
56 		switch (proto) {
57 		case IPPROTO_ICMP:
58 			return "ICMPv4";
59 		case IPPROTO_TCP:
60 			return "TCP";
61 		case IPPROTO_UDP:
62 			return "UDP";
63 		case IPPROTO_ICMPV6:
64 			return "ICMPv6";
65 		default:
66 			break;
67 		}
68 	} else if (family == AF_CAN) {
69 		switch (proto) {
70 		case 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 	int i, val;
83 
84 	for (i = 0, val = (byte & 0xf0) >> 4; i < 2; i++, val = byte & 0x0f) {
85 		if (i == 0 && !pad && !val) {
86 			continue;
87 		}
88 		if (val < 10) {
89 			*ptr++ = (char) (val + '0');
90 		} else {
91 			*ptr++ = (char) (val - 10 + base);
92 		}
93 	}
94 
95 	*ptr = '\0';
96 
97 	return ptr;
98 }
99 
net_sprint_ll_addr_buf(const uint8_t * ll,uint8_t ll_len,char * buf,int buflen)100 char *net_sprint_ll_addr_buf(const uint8_t *ll, uint8_t ll_len,
101 			     char *buf, int buflen)
102 {
103 	uint8_t i, len, blen;
104 	char *ptr = buf;
105 
106 	if (ll == NULL) {
107 		return "<unknown>";
108 	}
109 
110 	switch (ll_len) {
111 	case 8:
112 		len = 8U;
113 		break;
114 	case 6:
115 		len = 6U;
116 		break;
117 	case 2:
118 		len = 2U;
119 		break;
120 	default:
121 		len = 6U;
122 		break;
123 	}
124 
125 	for (i = 0U, blen = buflen; i < len && blen > 0; i++) {
126 		ptr = net_byte_to_hex(ptr, (char)ll[i], 'A', true);
127 		*ptr++ = ':';
128 		blen -= 3U;
129 	}
130 
131 	if (!(ptr - buf)) {
132 		return NULL;
133 	}
134 
135 	*(ptr - 1) = '\0';
136 	return buf;
137 }
138 
net_value_to_udec(char * buf,uint32_t value,int precision)139 static int net_value_to_udec(char *buf, uint32_t value, int precision)
140 {
141 	uint32_t divisor;
142 	int i;
143 	int temp;
144 	char *start = buf;
145 
146 	divisor = 1000000000U;
147 	if (precision < 0) {
148 		precision = 1;
149 	}
150 
151 	for (i = 9; i >= 0; i--, divisor /= 10U) {
152 		temp = value / divisor;
153 		value = value % divisor;
154 		if ((precision > i) || (temp != 0)) {
155 			precision = i;
156 			*buf++ = (char) (temp + '0');
157 		}
158 	}
159 	*buf = 0;
160 
161 	return buf - start;
162 }
163 
z_impl_net_addr_ntop(sa_family_t family,const void * src,char * dst,size_t size)164 char *z_impl_net_addr_ntop(sa_family_t family, const void *src,
165 			   char *dst, size_t size)
166 {
167 	struct in_addr *addr = NULL;
168 	struct in6_addr *addr6 = NULL;
169 	uint16_t *w = NULL;
170 	uint8_t i, bl, bh, longest = 1U;
171 	int8_t pos = -1;
172 	char delim = ':';
173 	unsigned char zeros[8] = { 0 };
174 	char *ptr = dst;
175 	int len = -1;
176 	uint16_t value;
177 	bool needcolon = false;
178 	bool mapped = false;
179 
180 	if (family == AF_INET6) {
181 		addr6 = (struct in6_addr *)src;
182 		w = (uint16_t *)addr6->s6_addr16;
183 		len = 8;
184 
185 		if (net_ipv6_addr_is_v4_mapped(addr6)) {
186 			mapped = true;
187 		}
188 
189 		for (i = 0U; i < 8; i++) {
190 			uint8_t j;
191 
192 			for (j = i; j < 8; j++) {
193 				if (UNALIGNED_GET(&w[j]) != 0) {
194 					break;
195 				}
196 
197 				zeros[i]++;
198 			}
199 		}
200 
201 		for (i = 0U; i < 8; i++) {
202 			if (zeros[i] > longest) {
203 				longest = zeros[i];
204 				pos = i;
205 			}
206 		}
207 
208 		if (longest == 1U) {
209 			pos = -1;
210 		}
211 
212 	} else if (family == AF_INET) {
213 		addr = (struct in_addr *)src;
214 		len = 4;
215 		delim = '.';
216 	} else {
217 		return NULL;
218 	}
219 
220 print_mapped:
221 	for (i = 0U; i < len; i++) {
222 		/* IPv4 address a.b.c.d */
223 		if (len == 4) {
224 			uint8_t l;
225 
226 			value = (uint32_t)addr->s4_addr[i];
227 
228 			/* net_byte_to_udec() eats 0 */
229 			if (value == 0U) {
230 				*ptr++ = '0';
231 				*ptr++ = delim;
232 				continue;
233 			}
234 
235 			l = net_value_to_udec(ptr, value, 0);
236 
237 			ptr += l;
238 			*ptr++ = delim;
239 
240 			continue;
241 		}
242 
243 		if (mapped && (i > 5)) {
244 			delim = '.';
245 			len = 4;
246 			addr = (struct in_addr *)(&addr6->s6_addr32[3]);
247 			*ptr++ = ':';
248 			family = AF_INET;
249 			goto print_mapped;
250 		}
251 
252 		/* IPv6 address */
253 		if (i == pos) {
254 			if (needcolon || i == 0U) {
255 				*ptr++ = ':';
256 			}
257 
258 			*ptr++ = ':';
259 			needcolon = false;
260 			i += longest - 1U;
261 
262 			continue;
263 		}
264 
265 		if (needcolon) {
266 			*ptr++ = ':';
267 		}
268 
269 		value = (uint32_t)sys_be16_to_cpu(UNALIGNED_GET(&w[i]));
270 		bh = value >> 8;
271 		bl = value & 0xff;
272 
273 		if (bh) {
274 			if (bh > 0x0f) {
275 				ptr = net_byte_to_hex(ptr, bh, 'a', false);
276 			} else {
277 				if (bh < 10) {
278 					*ptr++ = (char)(bh + '0');
279 				} else {
280 					*ptr++ = (char) (bh - 10 + 'a');
281 				}
282 			}
283 
284 			ptr = net_byte_to_hex(ptr, bl, 'a', true);
285 		} else if (bl > 0x0f) {
286 			ptr = net_byte_to_hex(ptr, bl, 'a', false);
287 		} else {
288 			if (bl < 10) {
289 				*ptr++ = (char)(bl + '0');
290 			} else {
291 				*ptr++ = (char) (bl - 10 + 'a');
292 			}
293 		}
294 
295 		needcolon = true;
296 	}
297 
298 	if (!(ptr - dst)) {
299 		return NULL;
300 	}
301 
302 	if (family == AF_INET) {
303 		*(ptr - 1) = '\0';
304 	} else {
305 		*ptr = '\0';
306 	}
307 
308 	return dst;
309 }
310 
311 #if defined(CONFIG_USERSPACE)
z_vrfy_net_addr_ntop(sa_family_t family,const void * src,char * dst,size_t size)312 char *z_vrfy_net_addr_ntop(sa_family_t family, const void *src,
313 			   char *dst, size_t size)
314 {
315 	char str[INET6_ADDRSTRLEN];
316 	struct in6_addr addr6;
317 	struct in_addr addr4;
318 	char *out;
319 	const void *addr;
320 
321 	K_OOPS(K_SYSCALL_MEMORY_WRITE(dst, size));
322 
323 	if (family == AF_INET) {
324 		K_OOPS(k_usermode_from_copy(&addr4, (const void *)src,
325 					sizeof(addr4)));
326 		addr = &addr4;
327 	} else if (family == AF_INET6) {
328 		K_OOPS(k_usermode_from_copy(&addr6, (const void *)src,
329 					sizeof(addr6)));
330 		addr = &addr6;
331 	} else {
332 		return 0;
333 	}
334 
335 	out = z_impl_net_addr_ntop(family, addr, str, sizeof(str));
336 	if (!out) {
337 		return 0;
338 	}
339 
340 	K_OOPS(k_usermode_to_copy((void *)dst, str, MIN(size, sizeof(str))));
341 
342 	return dst;
343 }
344 #include <zephyr/syscalls/net_addr_ntop_mrsh.c>
345 #endif /* CONFIG_USERSPACE */
346 
z_impl_net_addr_pton(sa_family_t family,const char * src,void * dst)347 int z_impl_net_addr_pton(sa_family_t family, const char *src,
348 			 void *dst)
349 {
350 	if (family == AF_INET) {
351 		struct in_addr *addr = (struct in_addr *)dst;
352 		size_t i, len;
353 
354 		len = strlen(src);
355 		for (i = 0; i < len; i++) {
356 			if (!(src[i] >= '0' && src[i] <= '9') &&
357 			    src[i] != '.') {
358 				return -EINVAL;
359 			}
360 		}
361 
362 		(void)memset(addr, 0, sizeof(struct in_addr));
363 
364 		for (i = 0; i < sizeof(struct in_addr); i++) {
365 			char *endptr;
366 
367 			addr->s4_addr[i] = strtol(src, &endptr, 10);
368 
369 			src = ++endptr;
370 		}
371 
372 	} else if (family == AF_INET6) {
373 		/* If the string contains a '.', it means it's of the form
374 		 * X:X:X:X:X:X:x.x.x.x, and contains only 6 16-bit pieces
375 		 */
376 		int expected_groups = strchr(src, '.') ? 6 : 8;
377 		struct in6_addr *addr = (struct in6_addr *)dst;
378 		int i, len;
379 
380 		if (*src == ':') {
381 			/* Ignore a leading colon, makes parsing neater */
382 			src++;
383 		}
384 
385 		len = strlen(src);
386 		for (i = 0; i < len; i++) {
387 			if (!(src[i] >= '0' && src[i] <= '9') &&
388 			    !(src[i] >= 'A' && src[i] <= 'F') &&
389 			    !(src[i] >= 'a' && src[i] <= 'f') &&
390 			    src[i] != '.' && src[i] != ':') {
391 				return -EINVAL;
392 			}
393 		}
394 
395 		for (i = 0; i < expected_groups; i++) {
396 			char *tmp;
397 
398 			if (!src || *src == '\0') {
399 				return -EINVAL;
400 			}
401 
402 			if (*src != ':') {
403 				/* Normal IPv6 16-bit piece */
404 				UNALIGNED_PUT(htons(strtol(src, NULL, 16)),
405 					      &addr->s6_addr16[i]);
406 				src = strchr(src, ':');
407 				if (src) {
408 					src++;
409 				} else {
410 					if (i < expected_groups - 1) {
411 						return -EINVAL;
412 					}
413 				}
414 
415 				continue;
416 			}
417 
418 			/* Two colons in a row */
419 
420 			for (; i < expected_groups; i++) {
421 				UNALIGNED_PUT(0, &addr->s6_addr16[i]);
422 			}
423 
424 			tmp = strrchr(src, ':');
425 			if (src == tmp && (expected_groups == 6 || !src[1])) {
426 				src++;
427 				break;
428 			}
429 
430 			if (expected_groups == 6) {
431 				/* we need to drop the trailing
432 				 * colon since it's between the
433 				 * ipv6 and ipv4 addresses, rather than being
434 				 * a part of the ipv6 address
435 				 */
436 				tmp--;
437 			}
438 
439 			/* Calculate the amount of skipped zeros */
440 			i = expected_groups - 1;
441 			do {
442 				if (*tmp == ':') {
443 					i--;
444 				}
445 
446 				if (i < 0) {
447 					return -EINVAL;
448 				}
449 			} while (tmp-- != src);
450 
451 			src++;
452 		}
453 
454 		if (expected_groups == 6) {
455 			/* Parse the IPv4 part */
456 			for (i = 0; i < 4; i++) {
457 				if (!src || !*src) {
458 					return -EINVAL;
459 				}
460 
461 				addr->s6_addr[12 + i] = strtol(src, NULL, 10);
462 
463 				src = strchr(src, '.');
464 				if (src) {
465 					src++;
466 				} else {
467 					if (i < 3) {
468 						return -EINVAL;
469 					}
470 				}
471 			}
472 		}
473 	} else {
474 		return -EINVAL;
475 	}
476 
477 	return 0;
478 }
479 
480 #if defined(CONFIG_USERSPACE)
z_vrfy_net_addr_pton(sa_family_t family,const char * src,void * dst)481 int z_vrfy_net_addr_pton(sa_family_t family, const char *src,
482 			 void *dst)
483 {
484 	char str[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)] = {};
485 	struct in6_addr addr6;
486 	struct in_addr addr4;
487 	void *addr;
488 	size_t size;
489 	int err;
490 
491 	if (family == AF_INET) {
492 		size = sizeof(struct in_addr);
493 		addr = &addr4;
494 	} else if (family == AF_INET6) {
495 		size = sizeof(struct in6_addr);
496 		addr = &addr6;
497 	} else {
498 		return -EINVAL;
499 	}
500 
501 	if (k_usermode_string_copy(str, (char *)src, sizeof(str)) != 0) {
502 		return -EINVAL;
503 	}
504 
505 	K_OOPS(K_SYSCALL_MEMORY_WRITE(dst, size));
506 
507 	err = z_impl_net_addr_pton(family, str, addr);
508 	if (err) {
509 		return err;
510 	}
511 
512 	K_OOPS(k_usermode_to_copy((void *)dst, addr, size));
513 
514 	return 0;
515 }
516 #include <zephyr/syscalls/net_addr_pton_mrsh.c>
517 #endif /* CONFIG_USERSPACE */
518 
519 
520 #ifdef CONFIG_LITTLE_ENDIAN
521 #define CHECKSUM_BIG_ENDIAN 0
522 #else
523 #define CHECKSUM_BIG_ENDIAN 1
524 #endif
525 
offset_based_swap8(const uint8_t * data)526 static uint16_t offset_based_swap8(const uint8_t *data)
527 {
528 	uint16_t data16 = (uint16_t)*data;
529 
530 	if (((uintptr_t)(data) & 1) == CHECKSUM_BIG_ENDIAN) {
531 		return data16;
532 	} else {
533 		return data16 << 8;
534 	}
535 }
536 
537 /* Word based checksum calculation based on:
538  * https://blogs.igalia.com/dpino/2018/06/14/fast-checksum-computation/
539  * It’s not necessary to add octets as 16-bit words. Due to the associative property of addition,
540  * it is possible to do parallel addition using larger word sizes such as 32-bit or 64-bit words.
541  * In those cases the variable that stores the accumulative sum has to be bigger too.
542  * Once the sum is computed a final step folds the sum to a 16-bit word (adding carry if any).
543  */
calc_chksum(uint16_t sum_in,const uint8_t * data,size_t len)544 uint16_t calc_chksum(uint16_t sum_in, const uint8_t *data, size_t len)
545 {
546 	uint64_t sum;
547 	uint32_t *p;
548 	size_t i = 0;
549 	size_t pending = len;
550 	int odd_start = ((uintptr_t)data & 0x01);
551 
552 	/* Sum in is in host endianness, working order endianness is both dependent on endianness
553 	 * and the offset of starting
554 	 */
555 	if (odd_start == CHECKSUM_BIG_ENDIAN) {
556 		sum = BSWAP_16(sum_in);
557 	} else {
558 		sum = sum_in;
559 	}
560 
561 	/* Process up to 3 data elements up front, so the data is aligned further down the line */
562 	if ((((uintptr_t)data & 0x01) != 0) && (pending >= 1)) {
563 		sum += offset_based_swap8(data);
564 		data++;
565 		pending--;
566 	}
567 	if ((((uintptr_t)data & 0x02) != 0) && (pending >= sizeof(uint16_t))) {
568 		pending -= sizeof(uint16_t);
569 		sum = sum + *((uint16_t *)data);
570 		data += sizeof(uint16_t);
571 	}
572 	p = (uint32_t *)data;
573 
574 	/* Do loop unrolling for the very large data sets */
575 	while (pending >= sizeof(uint32_t) * 4) {
576 		uint64_t sum_a = p[i];
577 		uint64_t sum_b = p[i + 1];
578 
579 		pending -= sizeof(uint32_t) * 4;
580 		sum_a += p[i + 2];
581 		sum_b += p[i + 3];
582 		i += 4;
583 		sum += sum_a + sum_b;
584 	}
585 	while (pending >= sizeof(uint32_t)) {
586 		pending -= sizeof(uint32_t);
587 		sum = sum + p[i++];
588 	}
589 	data = (uint8_t *)(p + i);
590 	if (pending >= 2) {
591 		pending -= sizeof(uint16_t);
592 		sum = sum + *((uint16_t *)data);
593 		data += sizeof(uint16_t);
594 	}
595 	if (pending == 1) {
596 		sum += offset_based_swap8(data);
597 	}
598 
599 	/* Fold sum into 16-bit word. */
600 	while (sum >> 16) {
601 		sum = (sum & 0xffff) + (sum >> 16);
602 	}
603 
604 	/* Sum in is in host endianness, working order endianness is both dependent on endianness
605 	 * and the offset of starting
606 	 */
607 	if (odd_start == CHECKSUM_BIG_ENDIAN) {
608 		return BSWAP_16((uint16_t)sum);
609 	} else {
610 		return sum;
611 	}
612 }
613 
pkt_calc_chksum(struct net_pkt * pkt,uint16_t sum)614 static inline uint16_t pkt_calc_chksum(struct net_pkt *pkt, uint16_t sum)
615 {
616 	struct net_pkt_cursor *cur = &pkt->cursor;
617 	size_t len;
618 
619 	if (!cur->buf || !cur->pos) {
620 		return sum;
621 	}
622 
623 	len = cur->buf->len - (cur->pos - cur->buf->data);
624 
625 	while (cur->buf) {
626 		sum = calc_chksum(sum, cur->pos, len);
627 
628 		cur->buf = cur->buf->frags;
629 		if (!cur->buf || !cur->buf->len) {
630 			break;
631 		}
632 
633 		cur->pos = cur->buf->data;
634 
635 		if (len % 2) {
636 			sum += *cur->pos;
637 			if (sum < *cur->pos) {
638 				sum++;
639 			}
640 
641 			cur->pos++;
642 			len = cur->buf->len - 1;
643 		} else {
644 			len = cur->buf->len;
645 		}
646 	}
647 
648 	return sum;
649 }
650 
651 #if defined(CONFIG_NET_IP)
net_calc_chksum(struct net_pkt * pkt,uint8_t proto)652 uint16_t net_calc_chksum(struct net_pkt *pkt, uint8_t proto)
653 {
654 	size_t len = 0U;
655 	uint16_t sum = 0U;
656 	struct net_pkt_cursor backup;
657 	bool ow;
658 
659 	if (IS_ENABLED(CONFIG_NET_IPV4) &&
660 	    net_pkt_family(pkt) == AF_INET) {
661 		if (proto != IPPROTO_ICMP && proto != IPPROTO_IGMP) {
662 			len = 2 * sizeof(struct in_addr);
663 			sum = net_pkt_get_len(pkt) -
664 				net_pkt_ip_hdr_len(pkt) -
665 				net_pkt_ipv4_opts_len(pkt) + proto;
666 		}
667 	} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
668 		   net_pkt_family(pkt) == AF_INET6) {
669 		len = 2 * sizeof(struct in6_addr);
670 		sum =  net_pkt_get_len(pkt) -
671 			net_pkt_ip_hdr_len(pkt) -
672 			net_pkt_ipv6_ext_len(pkt) + proto;
673 	} else {
674 		NET_DBG("Unknown protocol family %d", net_pkt_family(pkt));
675 		return 0;
676 	}
677 
678 	net_pkt_cursor_backup(pkt, &backup);
679 	net_pkt_cursor_init(pkt);
680 
681 	ow = net_pkt_is_being_overwritten(pkt);
682 	net_pkt_set_overwrite(pkt, true);
683 
684 	net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) - len);
685 
686 	sum = calc_chksum(sum, pkt->cursor.pos, len);
687 	net_pkt_skip(pkt, len + net_pkt_ip_opts_len(pkt));
688 
689 	sum = pkt_calc_chksum(pkt, sum);
690 
691 	sum = (sum == 0U) ? 0xffff : htons(sum);
692 
693 	net_pkt_cursor_restore(pkt, &backup);
694 
695 	net_pkt_set_overwrite(pkt, ow);
696 
697 	return ~sum;
698 }
699 #endif
700 
701 #if defined(CONFIG_NET_IPV4)
net_calc_chksum_ipv4(struct net_pkt * pkt)702 uint16_t net_calc_chksum_ipv4(struct net_pkt *pkt)
703 {
704 	uint16_t sum;
705 
706 	sum = calc_chksum(0, pkt->buffer->data,
707 			  net_pkt_ip_hdr_len(pkt) +
708 			  net_pkt_ipv4_opts_len(pkt));
709 
710 	sum = (sum == 0U) ? 0xffff : htons(sum);
711 
712 	return ~sum;
713 }
714 #endif /* CONFIG_NET_IPV4 */
715 
716 #if defined(CONFIG_NET_IPV4_IGMP)
net_calc_chksum_igmp(struct net_pkt * pkt)717 uint16_t net_calc_chksum_igmp(struct net_pkt *pkt)
718 {
719 	return net_calc_chksum(pkt, IPPROTO_IGMP);
720 }
721 #endif /* CONFIG_NET_IPV4_IGMP */
722 
723 #if defined(CONFIG_NET_IP)
convert_port(const char * buf,uint16_t * port)724 static bool convert_port(const char *buf, uint16_t *port)
725 {
726 	unsigned long tmp;
727 	char *endptr;
728 
729 	tmp = strtoul(buf, &endptr, 10);
730 	if ((endptr == buf && tmp == 0) ||
731 	    !(*buf != '\0' && *endptr == '\0') ||
732 	    ((unsigned long)(unsigned short)tmp != tmp)) {
733 		return false;
734 	}
735 
736 	*port = tmp;
737 
738 	return true;
739 }
740 #endif /* CONFIG_NET_IP */
741 
742 #if defined(CONFIG_NET_IPV6)
parse_ipv6(const char * str,size_t str_len,struct sockaddr * addr,bool has_port)743 static bool parse_ipv6(const char *str, size_t str_len,
744 		       struct sockaddr *addr, bool has_port)
745 {
746 	char *ptr = NULL;
747 	struct in6_addr *addr6;
748 	char ipaddr[INET6_ADDRSTRLEN + 1];
749 	int end, len, ret, i;
750 	uint16_t port;
751 
752 	len = MIN(INET6_ADDRSTRLEN, str_len);
753 
754 	for (i = 0; i < len; i++) {
755 		if (!str[i]) {
756 			len = i;
757 			break;
758 		}
759 	}
760 
761 	if (has_port) {
762 		/* IPv6 address with port number */
763 		ptr = memchr(str, ']', len);
764 		if (!ptr) {
765 			return false;
766 		}
767 
768 		end = MIN(len, ptr - (str + 1));
769 		memcpy(ipaddr, str + 1, end);
770 	} else {
771 		end = len;
772 		memcpy(ipaddr, str, end);
773 	}
774 
775 	ipaddr[end] = '\0';
776 
777 	addr6 = &net_sin6(addr)->sin6_addr;
778 
779 	ret = net_addr_pton(AF_INET6, ipaddr, addr6);
780 	if (ret < 0) {
781 		return false;
782 	}
783 
784 	net_sin6(addr)->sin6_family = AF_INET6;
785 
786 	if (!has_port) {
787 		return true;
788 	}
789 
790 	if ((ptr + 1) < (str + str_len) && *(ptr + 1) == ':') {
791 		/* -1 as end does not contain first [
792 		 * -2 as pointer is advanced by 2, skipping ]:
793 		 */
794 		len = str_len - end - 1 - 2;
795 
796 		ptr += 2;
797 
798 		for (i = 0; i < len; i++) {
799 			if (!ptr[i]) {
800 				len = i;
801 				break;
802 			}
803 		}
804 
805 		/* Re-use the ipaddr buf for port conversion */
806 		memcpy(ipaddr, ptr, len);
807 		ipaddr[len] = '\0';
808 
809 		ret = convert_port(ipaddr, &port);
810 		if (!ret) {
811 			return false;
812 		}
813 
814 		net_sin6(addr)->sin6_port = htons(port);
815 
816 		NET_DBG("IPv6 host %s port %d",
817 			net_addr_ntop(AF_INET6, addr6, ipaddr, sizeof(ipaddr) - 1),
818 			port);
819 	} else {
820 		NET_DBG("IPv6 host %s",
821 			net_addr_ntop(AF_INET6, addr6, ipaddr, sizeof(ipaddr) - 1));
822 	}
823 
824 	return true;
825 }
826 #else
parse_ipv6(const char * str,size_t str_len,struct sockaddr * addr,bool has_port)827 static inline bool parse_ipv6(const char *str, size_t str_len,
828 			      struct sockaddr *addr, bool has_port)
829 {
830 	return false;
831 }
832 #endif /* CONFIG_NET_IPV6 */
833 
834 #if defined(CONFIG_NET_IPV4)
parse_ipv4(const char * str,size_t str_len,struct sockaddr * addr,bool has_port)835 static bool parse_ipv4(const char *str, size_t str_len,
836 		       struct sockaddr *addr, bool has_port)
837 {
838 	char *ptr = NULL;
839 	char ipaddr[NET_IPV4_ADDR_LEN + 1];
840 	struct in_addr *addr4;
841 	int end, len, ret, i;
842 	uint16_t port;
843 
844 	len = MIN(NET_IPV4_ADDR_LEN, str_len);
845 
846 	for (i = 0; i < len; i++) {
847 		if (!str[i]) {
848 			len = i;
849 			break;
850 		}
851 	}
852 
853 	if (has_port) {
854 		/* IPv4 address with port number */
855 		ptr = memchr(str, ':', len);
856 		if (!ptr) {
857 			return false;
858 		}
859 
860 		end = MIN(len, ptr - str);
861 	} else {
862 		end = len;
863 	}
864 
865 	memcpy(ipaddr, str, end);
866 	ipaddr[end] = '\0';
867 
868 	addr4 = &net_sin(addr)->sin_addr;
869 
870 	ret = net_addr_pton(AF_INET, ipaddr, addr4);
871 	if (ret < 0) {
872 		return false;
873 	}
874 
875 	net_sin(addr)->sin_family = AF_INET;
876 
877 	if (!has_port) {
878 		return true;
879 	}
880 
881 	memcpy(ipaddr, ptr + 1, str_len - end);
882 	ipaddr[str_len - end] = '\0';
883 
884 	ret = convert_port(ipaddr, &port);
885 	if (!ret) {
886 		return false;
887 	}
888 
889 	net_sin(addr)->sin_port = htons(port);
890 
891 	NET_DBG("IPv4 host %s port %d",
892 		net_addr_ntop(AF_INET, addr4, ipaddr, sizeof(ipaddr) - 1),
893 		port);
894 	return true;
895 }
896 #else
parse_ipv4(const char * str,size_t str_len,struct sockaddr * addr,bool has_port)897 static inline bool parse_ipv4(const char *str, size_t str_len,
898 			      struct sockaddr *addr, bool has_port)
899 {
900 	return false;
901 }
902 #endif /* CONFIG_NET_IPV4 */
903 
net_ipaddr_parse(const char * str,size_t str_len,struct sockaddr * addr)904 bool net_ipaddr_parse(const char *str, size_t str_len, struct sockaddr *addr)
905 {
906 	int i, count;
907 
908 	if (!str || str_len == 0) {
909 		return false;
910 	}
911 
912 	/* We cannot accept empty string here */
913 	if (*str == '\0') {
914 		return false;
915 	}
916 
917 	if (*str == '[') {
918 		return parse_ipv6(str, str_len, addr, true);
919 	}
920 
921 	for (count = i = 0; i < str_len && str[i]; i++) {
922 		if (str[i] == ':') {
923 			count++;
924 		}
925 	}
926 
927 	if (count == 1) {
928 		return parse_ipv4(str, str_len, addr, true);
929 	}
930 
931 #if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6)
932 	if (!parse_ipv4(str, str_len, addr, false)) {
933 		return parse_ipv6(str, str_len, addr, false);
934 	}
935 
936 	return true;
937 #endif
938 
939 #if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
940 	return parse_ipv4(str, str_len, addr, false);
941 #endif
942 
943 #if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
944 	return parse_ipv6(str, str_len, addr, false);
945 #endif
946 	return false;
947 }
948 
net_port_set_default(struct sockaddr * addr,uint16_t default_port)949 int net_port_set_default(struct sockaddr *addr, uint16_t default_port)
950 {
951 	if (IS_ENABLED(CONFIG_NET_IPV4) && addr->sa_family == AF_INET &&
952 	    net_sin(addr)->sin_port == 0) {
953 		net_sin(addr)->sin_port = htons(default_port);
954 	} else if (IS_ENABLED(CONFIG_NET_IPV6) && addr->sa_family == AF_INET6 &&
955 		   net_sin6(addr)->sin6_port == 0) {
956 		net_sin6(addr)->sin6_port = htons(default_port);
957 	} else if ((IS_ENABLED(CONFIG_NET_IPV4) && addr->sa_family == AF_INET) ||
958 		   (IS_ENABLED(CONFIG_NET_IPV6) && addr->sa_family == AF_INET6)) {
959 		; /* Port is already set */
960 	} else {
961 		LOG_ERR("Unknown address family");
962 		return -EINVAL;
963 	}
964 
965 	return 0;
966 }
967 
net_bytes_from_str(uint8_t * buf,int buf_len,const char * src)968 int net_bytes_from_str(uint8_t *buf, int buf_len, const char *src)
969 {
970 	size_t i;
971 	size_t src_len = strlen(src);
972 	char *endptr;
973 
974 	for (i = 0U; i < src_len; i++) {
975 		if (!isxdigit((unsigned char)src[i]) &&
976 		    src[i] != ':') {
977 			return -EINVAL;
978 		}
979 	}
980 
981 	(void)memset(buf, 0, buf_len);
982 
983 	for (i = 0U; i < (size_t)buf_len; i++) {
984 		buf[i] = (uint8_t)strtol(src, &endptr, 16);
985 		src = ++endptr;
986 	}
987 
988 	return 0;
989 }
990 
net_family2str(sa_family_t family)991 const char *net_family2str(sa_family_t family)
992 {
993 	switch (family) {
994 	case AF_UNSPEC:
995 		return "AF_UNSPEC";
996 	case AF_INET:
997 		return "AF_INET";
998 	case AF_INET6:
999 		return "AF_INET6";
1000 	case AF_PACKET:
1001 		return "AF_PACKET";
1002 	case AF_CAN:
1003 		return "AF_CAN";
1004 	}
1005 
1006 	return NULL;
1007 }
1008 
net_ipv4_unspecified_address(void)1009 const struct in_addr *net_ipv4_unspecified_address(void)
1010 {
1011 	static const struct in_addr addr;
1012 
1013 	return &addr;
1014 }
1015 
net_ipv4_broadcast_address(void)1016 const struct in_addr *net_ipv4_broadcast_address(void)
1017 {
1018 	static const struct in_addr addr = { { { 255, 255, 255, 255 } } };
1019 
1020 	return &addr;
1021 }
1022 
1023 /* IPv6 wildcard and loopback address defined by RFC2553 */
1024 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
1025 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
1026 
net_ipv6_unspecified_address(void)1027 const struct in6_addr *net_ipv6_unspecified_address(void)
1028 {
1029 	return &in6addr_any;
1030 }
1031