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