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