1 /** @file
2  * @brief IPv6 and IPv4 definitions
3  *
4  * Generic IPv6 and IPv4 address definitions.
5  */
6 
7 /*
8  * Copyright (c) 2016 Intel Corporation
9  *
10  * SPDX-License-Identifier: Apache-2.0
11  */
12 
13 #ifndef ZEPHYR_INCLUDE_NET_NET_IP_H_
14 #define ZEPHYR_INCLUDE_NET_NET_IP_H_
15 
16 /**
17  * @brief IPv4/IPv6 primitives and helpers
18  * @defgroup ip_4_6 IPv4/IPv6 primitives and helpers
19  * @since 1.0
20  * @version 1.0.0
21  * @ingroup networking
22  * @{
23  */
24 
25 #include <string.h>
26 #include <zephyr/types.h>
27 #include <stdbool.h>
28 #include <zephyr/sys/util.h>
29 #include <zephyr/sys/byteorder.h>
30 #include <zephyr/toolchain.h>
31 
32 #include <zephyr/net/net_linkaddr.h>
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 /** @cond INTERNAL_HIDDEN */
39 /* Specifying VLAN tag here in order to avoid circular dependencies */
40 #define NET_VLAN_TAG_UNSPEC 0x0fff
41 /** @endcond */
42 
43 /* Protocol families. */
44 #define PF_UNSPEC       0          /**< Unspecified protocol family.  */
45 #define PF_INET         1          /**< IP protocol family version 4. */
46 #define PF_INET6        2          /**< IP protocol family version 6. */
47 #define PF_PACKET       3          /**< Packet family.                */
48 #define PF_CAN          4          /**< Controller Area Network.      */
49 #define PF_NET_MGMT     5          /**< Network management info.      */
50 #define PF_LOCAL        6          /**< Inter-process communication   */
51 #define PF_UNIX         PF_LOCAL   /**< Inter-process communication   */
52 
53 /* Address families. */
54 #define AF_UNSPEC      PF_UNSPEC   /**< Unspecified address family.   */
55 #define AF_INET        PF_INET     /**< IP protocol family version 4. */
56 #define AF_INET6       PF_INET6    /**< IP protocol family version 6. */
57 #define AF_PACKET      PF_PACKET   /**< Packet family.                */
58 #define AF_CAN         PF_CAN      /**< Controller Area Network.      */
59 #define AF_NET_MGMT    PF_NET_MGMT /**< Network management info.      */
60 #define AF_LOCAL       PF_LOCAL    /**< Inter-process communication   */
61 #define AF_UNIX        PF_UNIX     /**< Inter-process communication   */
62 
63 /** Protocol numbers from IANA/BSD */
64 enum net_ip_protocol {
65 	IPPROTO_IP = 0,            /**< IP protocol (pseudo-val for setsockopt() */
66 	IPPROTO_ICMP = 1,          /**< ICMP protocol   */
67 	IPPROTO_IGMP = 2,          /**< IGMP protocol   */
68 	IPPROTO_ETH_P_ALL = 3,     /**< Every packet. from linux if_ether.h   */
69 	IPPROTO_IPIP = 4,          /**< IPIP tunnels    */
70 	IPPROTO_TCP = 6,           /**< TCP protocol    */
71 	IPPROTO_UDP = 17,          /**< UDP protocol    */
72 	IPPROTO_IPV6 = 41,         /**< IPv6 protocol   */
73 	IPPROTO_ICMPV6 = 58,       /**< ICMPv6 protocol */
74 	IPPROTO_RAW = 255,         /**< RAW IP packets  */
75 };
76 
77 /** Protocol numbers for TLS protocols */
78 enum net_ip_protocol_secure {
79 	IPPROTO_TLS_1_0 = 256,     /**< TLS 1.0 protocol */
80 	IPPROTO_TLS_1_1 = 257,     /**< TLS 1.1 protocol */
81 	IPPROTO_TLS_1_2 = 258,     /**< TLS 1.2 protocol */
82 	IPPROTO_TLS_1_3 = 259,     /**< TLS 1.3 protocol */
83 	IPPROTO_DTLS_1_0 = 272,    /**< DTLS 1.0 protocol */
84 	IPPROTO_DTLS_1_2 = 273,    /**< DTLS 1.2 protocol */
85 };
86 
87 /** Socket type */
88 enum net_sock_type {
89 	SOCK_STREAM = 1,           /**< Stream socket type   */
90 	SOCK_DGRAM,                /**< Datagram socket type */
91 	SOCK_RAW                   /**< RAW socket type      */
92 };
93 
94 /** @brief Convert 16-bit value from network to host byte order.
95  *
96  * @param x The network byte order value to convert.
97  *
98  * @return Host byte order value.
99  */
100 #define ntohs(x) sys_be16_to_cpu(x)
101 
102 /** @brief Convert 32-bit value from network to host byte order.
103  *
104  * @param x The network byte order value to convert.
105  *
106  * @return Host byte order value.
107  */
108 #define ntohl(x) sys_be32_to_cpu(x)
109 
110 /** @brief Convert 64-bit value from network to host byte order.
111  *
112  * @param x The network byte order value to convert.
113  *
114  * @return Host byte order value.
115  */
116 #define ntohll(x) sys_be64_to_cpu(x)
117 
118 /** @brief Convert 16-bit value from host to network byte order.
119  *
120  * @param x The host byte order value to convert.
121  *
122  * @return Network byte order value.
123  */
124 #define htons(x) sys_cpu_to_be16(x)
125 
126 /** @brief Convert 32-bit value from host to network byte order.
127  *
128  * @param x The host byte order value to convert.
129  *
130  * @return Network byte order value.
131  */
132 #define htonl(x) sys_cpu_to_be32(x)
133 
134 /** @brief Convert 64-bit value from host to network byte order.
135  *
136  * @param x The host byte order value to convert.
137  *
138  * @return Network byte order value.
139  */
140 #define htonll(x) sys_cpu_to_be64(x)
141 
142 /** IPv6 address struct */
143 struct in6_addr {
144 	union {
145 		uint8_t s6_addr[16];   /**< IPv6 address buffer */
146 		uint16_t s6_addr16[8]; /**< In big endian */
147 		uint32_t s6_addr32[4]; /**< In big endian */
148 	};
149 };
150 
151 /** Binary size of the IPv6 address */
152 #define NET_IPV6_ADDR_SIZE 16
153 
154 /** IPv4 address struct */
155 struct in_addr {
156 	union {
157 		uint8_t s4_addr[4];    /**< IPv4 address buffer */
158 		uint16_t s4_addr16[2]; /**< In big endian */
159 		uint32_t s4_addr32[1]; /**< In big endian */
160 		uint32_t s_addr; /**< In big endian, for POSIX compatibility. */
161 	};
162 };
163 
164 /** Binary size of the IPv4 address */
165 #define NET_IPV4_ADDR_SIZE 4
166 
167 /** Socket address family type */
168 typedef unsigned short int sa_family_t;
169 
170 /** Length of a socket address */
171 #ifndef __socklen_t_defined
172 typedef size_t socklen_t;
173 #define __socklen_t_defined
174 #endif
175 
176 /*
177  * Note that the sin_port and sin6_port are in network byte order
178  * in various sockaddr* structs.
179  */
180 
181 /** Socket address struct for IPv6. */
182 struct sockaddr_in6 {
183 	sa_family_t		sin6_family;   /**< AF_INET6               */
184 	uint16_t		sin6_port;     /**< Port number            */
185 	struct in6_addr		sin6_addr;     /**< IPv6 address           */
186 	uint8_t			sin6_scope_id; /**< Interfaces for a scope */
187 };
188 
189 /** Socket address struct for IPv4. */
190 struct sockaddr_in {
191 	sa_family_t		sin_family;    /**< AF_INET      */
192 	uint16_t		sin_port;      /**< Port number  */
193 	struct in_addr		sin_addr;      /**< IPv4 address */
194 };
195 
196 /** Socket address struct for packet socket. */
197 struct sockaddr_ll {
198 	sa_family_t sll_family;   /**< Always AF_PACKET                   */
199 	uint16_t    sll_protocol; /**< Physical-layer protocol            */
200 	int         sll_ifindex;  /**< Interface number                   */
201 	uint16_t    sll_hatype;   /**< ARP hardware type                  */
202 	uint8_t     sll_pkttype;  /**< Packet type                        */
203 	uint8_t     sll_halen;    /**< Length of address                  */
204 	uint8_t     sll_addr[8];  /**< Physical-layer address, big endian */
205 };
206 
207 /** @cond INTERNAL_HIDDEN */
208 
209 /** Socket address struct for IPv6 where address is a pointer */
210 struct sockaddr_in6_ptr {
211 	sa_family_t		sin6_family;   /**< AF_INET6               */
212 	uint16_t		sin6_port;     /**< Port number            */
213 	struct in6_addr		*sin6_addr;    /**< IPv6 address           */
214 	uint8_t			sin6_scope_id; /**< interfaces for a scope */
215 };
216 
217 /** Socket address struct for IPv4 where address is a pointer */
218 struct sockaddr_in_ptr {
219 	sa_family_t		sin_family;    /**< AF_INET      */
220 	uint16_t		sin_port;      /**< Port number  */
221 	struct in_addr		*sin_addr;     /**< IPv4 address */
222 };
223 
224 /** Socket address struct for packet socket where address is a pointer */
225 struct sockaddr_ll_ptr {
226 	sa_family_t sll_family;   /**< Always AF_PACKET                   */
227 	uint16_t    sll_protocol; /**< Physical-layer protocol            */
228 	int         sll_ifindex;  /**< Interface number                   */
229 	uint16_t    sll_hatype;   /**< ARP hardware type                  */
230 	uint8_t     sll_pkttype;  /**< Packet type                        */
231 	uint8_t     sll_halen;    /**< Length of address                  */
232 	uint8_t     *sll_addr;    /**< Physical-layer address, big endian */
233 };
234 
235 /** Socket address struct for unix socket where address is a pointer */
236 struct sockaddr_un_ptr {
237 	sa_family_t sun_family;    /**< Always AF_UNIX */
238 	char        *sun_path;     /**< pathname */
239 };
240 
241 struct sockaddr_can_ptr {
242 	sa_family_t can_family;
243 	int         can_ifindex;
244 };
245 
246 /** @endcond */
247 
248 #if !defined(HAVE_IOVEC)
249 /** IO vector array element */
250 struct iovec {
251 	void  *iov_base; /**< Pointer to data */
252 	size_t iov_len;  /**< Length of the data */
253 };
254 #endif
255 
256 /** Message struct */
257 struct msghdr {
258 	void         *msg_name;       /**< Optional socket address, big endian */
259 	socklen_t     msg_namelen;    /**< Size of socket address */
260 	struct iovec *msg_iov;        /**< Scatter/gather array */
261 	size_t        msg_iovlen;     /**< Number of elements in msg_iov */
262 	void         *msg_control;    /**< Ancillary data */
263 	size_t        msg_controllen; /**< Ancillary data buffer len */
264 	int           msg_flags;      /**< Flags on received message */
265 };
266 
267 /** Control message ancillary data */
268 struct cmsghdr {
269 	socklen_t cmsg_len;    /**< Number of bytes, including header */
270 	int       cmsg_level;  /**< Originating protocol */
271 	int       cmsg_type;   /**< Protocol-specific type */
272 	z_max_align_t cmsg_data[]; /**< Flexible array member to force alignment of cmsghdr */
273 };
274 
275 /** @cond INTERNAL_HIDDEN */
276 
277 /* Alignment for headers and data. These are arch specific but define
278  * them here atm if not found already.
279  */
280 #if !defined(ALIGN_H)
281 #define ALIGN_H(x) ROUND_UP(x, __alignof__(struct cmsghdr))
282 #endif
283 #if !defined(ALIGN_D)
284 #define ALIGN_D(x) ROUND_UP(x, __alignof__(z_max_align_t))
285 #endif
286 
287 /** @endcond */
288 
289 #if !defined(CMSG_FIRSTHDR)
290 /**
291  * Returns a pointer to the first cmsghdr in the ancillary data buffer
292  * associated with the passed msghdr.  It returns NULL if there isn't
293  * enough space for a cmsghdr in the buffer.
294  */
295 #define CMSG_FIRSTHDR(msghdr)					\
296 	((msghdr)->msg_controllen >= sizeof(struct cmsghdr) ?	\
297 	 (struct cmsghdr *)((msghdr)->msg_control) : NULL)
298 #endif
299 
300 #if !defined(CMSG_NXTHDR)
301 /**
302  * Returns the next valid cmsghdr after the passed cmsghdr. It returns NULL
303  * when there isn't enough space left in the buffer.
304  */
305 #define CMSG_NXTHDR(msghdr, cmsg)					 \
306 	(((cmsg) == NULL) ? CMSG_FIRSTHDR(msghdr) :			 \
307 	 (((uint8_t *)(cmsg) + ALIGN_H((cmsg)->cmsg_len) +		 \
308 	   ALIGN_D(sizeof(struct cmsghdr)) >				 \
309 	   (uint8_t *)((msghdr)->msg_control) + (msghdr)->msg_controllen) ? \
310 	  NULL :							 \
311 	  (struct cmsghdr *)((uint8_t *)(cmsg) +			 \
312 			     ALIGN_H((cmsg)->cmsg_len))))
313 #endif
314 
315 #if !defined(CMSG_DATA)
316 /**
317  * Returns a pointer to the data portion of a cmsghdr.  The pointer returned
318  * cannot be assumed to be suitably aligned for accessing arbitrary payload
319  * data types. Applications should not cast it to a pointer type matching
320  * the payload, but should instead use memcpy(3) to copy data to or from a
321  * suitably declared object.
322  */
323 #define CMSG_DATA(cmsg) ((uint8_t *)(cmsg) + ALIGN_D(sizeof(struct cmsghdr)))
324 #endif
325 
326 #if !defined(CMSG_SPACE)
327 /**
328  * Returns the number of bytes an ancillary element with payload of the passed
329  * data length occupies.
330  */
331 #define CMSG_SPACE(length) (ALIGN_D(sizeof(struct cmsghdr)) + ALIGN_H(length))
332 #endif
333 
334 #if !defined(CMSG_LEN)
335 /**
336  * Returns the value to store in the cmsg_len member of the cmsghdr structure,
337  * taking into account any necessary alignment.
338  * It takes the data length as an argument.
339  */
340 #define CMSG_LEN(length) (ALIGN_D(sizeof(struct cmsghdr)) + length)
341 #endif
342 
343 /** @cond INTERNAL_HIDDEN */
344 
345 /* Packet types.  */
346 #define PACKET_HOST         0     /* To us            */
347 #define PACKET_BROADCAST    1     /* To all           */
348 #define PACKET_MULTICAST    2     /* To group         */
349 #define PACKET_OTHERHOST    3     /* To someone else  */
350 #define PACKET_OUTGOING     4     /* Originated by us */
351 #define PACKET_LOOPBACK     5
352 #define PACKET_FASTROUTE    6
353 
354 /* ARP protocol HARDWARE identifiers. */
355 #define ARPHRD_ETHER 1
356 
357 /* Note: These macros are defined in a specific order.
358  * The largest sockaddr size is the last one.
359  */
360 #if defined(CONFIG_NET_IPV4)
361 #undef NET_SOCKADDR_MAX_SIZE
362 #undef NET_SOCKADDR_PTR_MAX_SIZE
363 #define NET_SOCKADDR_MAX_SIZE (sizeof(struct sockaddr_in))
364 #define NET_SOCKADDR_PTR_MAX_SIZE (sizeof(struct sockaddr_in_ptr))
365 #endif
366 
367 #if defined(CONFIG_NET_SOCKETS_PACKET)
368 #undef NET_SOCKADDR_MAX_SIZE
369 #undef NET_SOCKADDR_PTR_MAX_SIZE
370 #define NET_SOCKADDR_MAX_SIZE (sizeof(struct sockaddr_ll))
371 #define NET_SOCKADDR_PTR_MAX_SIZE (sizeof(struct sockaddr_ll_ptr))
372 #endif
373 
374 #if defined(CONFIG_NET_IPV6)
375 #undef NET_SOCKADDR_MAX_SIZE
376 #define NET_SOCKADDR_MAX_SIZE (sizeof(struct sockaddr_in6))
377 #if !defined(CONFIG_NET_SOCKETS_PACKET)
378 #undef NET_SOCKADDR_PTR_MAX_SIZE
379 #define NET_SOCKADDR_PTR_MAX_SIZE (sizeof(struct sockaddr_in6_ptr))
380 #endif
381 #endif
382 
383 #if defined(CONFIG_NET_NATIVE_OFFLOADED_SOCKETS)
384 #define UNIX_PATH_MAX 108
385 #undef NET_SOCKADDR_MAX_SIZE
386 /* Define NET_SOCKADDR_MAX_SIZE to be struct of sa_family_t + char[UNIX_PATH_MAX] */
387 #define NET_SOCKADDR_MAX_SIZE (UNIX_PATH_MAX+sizeof(sa_family_t))
388 #if !defined(CONFIG_NET_SOCKETS_PACKET)
389 #undef NET_SOCKADDR_PTR_MAX_SIZE
390 #define NET_SOCKADDR_PTR_MAX_SIZE (sizeof(struct sockaddr_un_ptr))
391 #endif
392 #endif
393 
394 #if !defined(CONFIG_NET_IPV4)
395 #if !defined(CONFIG_NET_IPV6)
396 #if !defined(CONFIG_NET_SOCKETS_PACKET)
397 #if !defined(CONFIG_NET_NATIVE_OFFLOADED_SOCKETS)
398 #define NET_SOCKADDR_MAX_SIZE (sizeof(struct sockaddr_in6))
399 #define NET_SOCKADDR_PTR_MAX_SIZE (sizeof(struct sockaddr_in6_ptr))
400 #endif
401 #endif
402 #endif
403 #endif
404 
405 /** @endcond */
406 
407 /** Generic sockaddr struct. Must be cast to proper type. */
408 struct sockaddr {
409 	sa_family_t sa_family; /**< Address family */
410 /** @cond INTERNAL_HIDDEN */
411 	char data[NET_SOCKADDR_MAX_SIZE - sizeof(sa_family_t)];
412 /** @endcond */
413 };
414 
415 /** @cond INTERNAL_HIDDEN */
416 
417 struct sockaddr_ptr {
418 	sa_family_t family;
419 	char data[NET_SOCKADDR_PTR_MAX_SIZE - sizeof(sa_family_t)];
420 };
421 
422 /* Same as sockaddr in our case */
423 struct sockaddr_storage {
424 	sa_family_t ss_family;
425 	char data[NET_SOCKADDR_MAX_SIZE - sizeof(sa_family_t)];
426 };
427 
428 /* Socket address struct for UNIX domain sockets */
429 struct sockaddr_un {
430 	sa_family_t sun_family;    /* AF_UNIX */
431 	char        sun_path[NET_SOCKADDR_MAX_SIZE - sizeof(sa_family_t)];
432 };
433 
434 struct net_addr {
435 	sa_family_t family;
436 	union {
437 		struct in6_addr in6_addr;
438 		struct in_addr in_addr;
439 	};
440 };
441 
442 /** A pointer to IPv6 any address (all values zero) */
443 extern const struct in6_addr in6addr_any;
444 
445 /** A pointer to IPv6 loopback address (::1) */
446 extern const struct in6_addr in6addr_loopback;
447 
448 /** @endcond */
449 
450 /** IPv6 address initializer */
451 #define IN6ADDR_ANY_INIT { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, \
452 				0, 0, 0, 0, 0, 0, 0 } } }
453 
454 /** IPv6 loopback address initializer */
455 #define IN6ADDR_LOOPBACK_INIT { { { 0, 0, 0, 0, 0, 0, 0, \
456 				0, 0, 0, 0, 0, 0, 0, 0, 1 } } }
457 
458 /** IPv4 any address */
459 #define INADDR_ANY 0
460 
461 /** IPv4 broadcast address */
462 #define INADDR_BROADCAST 0xffffffff
463 
464 /** IPv4 address initializer */
465 #define INADDR_ANY_INIT { { { INADDR_ANY } } }
466 
467 /** IPv6 loopback address initializer */
468 #define INADDR_LOOPBACK_INIT  { { { 127, 0, 0, 1 } } }
469 
470 /** Max length of the IPv4 address as a string. Defined by POSIX. */
471 #define INET_ADDRSTRLEN 16
472 /** Max length of the IPv6 address as a string. Takes into account possible
473  * mapped IPv4 addresses.
474  */
475 #define INET6_ADDRSTRLEN 46
476 
477 /** @cond INTERNAL_HIDDEN */
478 
479 /* These are for internal usage of the stack */
480 #define NET_IPV6_ADDR_LEN sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")
481 #define NET_IPV4_ADDR_LEN sizeof("xxx.xxx.xxx.xxx")
482 
483 /** @endcond */
484 
485 /** @brief IP Maximum Transfer Unit */
486 enum net_ip_mtu {
487 	/** IPv6 MTU length. We must be able to receive this size IPv6 packet
488 	 * without fragmentation.
489 	 */
490 #if defined(CONFIG_NET_NATIVE_IPV6)
491 	NET_IPV6_MTU = CONFIG_NET_IPV6_MTU,
492 #else
493 	NET_IPV6_MTU = 1280,
494 #endif
495 
496 	/** IPv4 MTU length. We must be able to receive this size IPv4 packet
497 	 * without fragmentation.
498 	 */
499 	NET_IPV4_MTU = 576,
500 };
501 
502 /** @brief Network packet priority settings described in IEEE 802.1Q Annex I.1 */
503 enum net_priority {
504 	NET_PRIORITY_BK = 1, /**< Background (lowest)                */
505 	NET_PRIORITY_BE = 0, /**< Best effort (default)              */
506 	NET_PRIORITY_EE = 2, /**< Excellent effort                   */
507 	NET_PRIORITY_CA = 3, /**< Critical applications              */
508 	NET_PRIORITY_VI = 4, /**< Video, < 100 ms latency and jitter */
509 	NET_PRIORITY_VO = 5, /**< Voice, < 10 ms latency and jitter  */
510 	NET_PRIORITY_IC = 6, /**< Internetwork control               */
511 	NET_PRIORITY_NC = 7  /**< Network control (highest)          */
512 } __packed;
513 
514 #define NET_MAX_PRIORITIES 8 /**< How many priority values there are */
515 
516 /** @brief IPv6/IPv4 network connection tuple */
517 struct net_tuple {
518 	struct net_addr *remote_addr;  /**< IPv6/IPv4 remote address */
519 	struct net_addr *local_addr;   /**< IPv6/IPv4 local address  */
520 	uint16_t remote_port;          /**< UDP/TCP remote port      */
521 	uint16_t local_port;           /**< UDP/TCP local port       */
522 	enum net_ip_protocol ip_proto; /**< IP protocol              */
523 };
524 
525 /** @brief What is the current state of the network address */
526 enum net_addr_state {
527 	NET_ADDR_ANY_STATE = -1, /**< Default (invalid) address type */
528 	NET_ADDR_TENTATIVE = 0,  /**< Tentative address              */
529 	NET_ADDR_PREFERRED,      /**< Preferred address              */
530 	NET_ADDR_DEPRECATED,     /**< Deprecated address             */
531 } __packed;
532 
533 /** @brief How the network address is assigned to network interface */
534 enum net_addr_type {
535 	/** Default value. This is not a valid value. */
536 	NET_ADDR_ANY = 0,
537 	/** Auto configured address */
538 	NET_ADDR_AUTOCONF,
539 	/** Address is from DHCP */
540 	NET_ADDR_DHCP,
541 	/** Manually set address */
542 	NET_ADDR_MANUAL,
543 	/** Manually set address which is overridable by DHCP */
544 	NET_ADDR_OVERRIDABLE,
545 } __packed;
546 
547 /** @cond INTERNAL_HIDDEN */
548 
549 struct net_ipv6_hdr {
550 	uint8_t vtc;
551 	uint8_t tcflow;
552 	uint16_t flow;
553 	uint16_t len;
554 	uint8_t nexthdr;
555 	uint8_t hop_limit;
556 	uint8_t src[NET_IPV6_ADDR_SIZE];
557 	uint8_t dst[NET_IPV6_ADDR_SIZE];
558 } __packed;
559 
560 struct net_ipv6_frag_hdr {
561 	uint8_t nexthdr;
562 	uint8_t reserved;
563 	uint16_t offset;
564 	uint32_t id;
565 } __packed;
566 
567 struct net_ipv4_hdr {
568 	uint8_t vhl;
569 	uint8_t tos;
570 	uint16_t len;
571 	uint8_t id[2];
572 	uint8_t offset[2];
573 	uint8_t ttl;
574 	uint8_t proto;
575 	uint16_t chksum;
576 	uint8_t src[NET_IPV4_ADDR_SIZE];
577 	uint8_t dst[NET_IPV4_ADDR_SIZE];
578 } __packed;
579 
580 struct net_icmp_hdr {
581 	uint8_t type;
582 	uint8_t code;
583 	uint16_t chksum;
584 } __packed;
585 
586 struct net_udp_hdr {
587 	uint16_t src_port;
588 	uint16_t dst_port;
589 	uint16_t len;
590 	uint16_t chksum;
591 } __packed;
592 
593 struct net_tcp_hdr {
594 	uint16_t src_port;
595 	uint16_t dst_port;
596 	uint8_t seq[4];
597 	uint8_t ack[4];
598 	uint8_t offset;
599 	uint8_t flags;
600 	uint8_t wnd[2];
601 	uint16_t chksum;
602 	uint8_t urg[2];
603 	uint8_t optdata[0];
604 } __packed;
605 
net_addr_type2str(enum net_addr_type type)606 static inline const char *net_addr_type2str(enum net_addr_type type)
607 {
608 	switch (type) {
609 	case NET_ADDR_AUTOCONF:
610 		return "AUTO";
611 	case NET_ADDR_DHCP:
612 		return "DHCP";
613 	case NET_ADDR_MANUAL:
614 		return "MANUAL";
615 	case NET_ADDR_OVERRIDABLE:
616 		return "OVERRIDE";
617 	case NET_ADDR_ANY:
618 	default:
619 		break;
620 	}
621 
622 	return "<unknown>";
623 }
624 
625 /* IPv6 extension headers types */
626 #define NET_IPV6_NEXTHDR_HBHO        0
627 #define NET_IPV6_NEXTHDR_DESTO       60
628 #define NET_IPV6_NEXTHDR_ROUTING     43
629 #define NET_IPV6_NEXTHDR_FRAG        44
630 #define NET_IPV6_NEXTHDR_NONE        59
631 
632 /**
633  * This 2 unions are here temporarily, as long as net_context.h will
634  * be still public and not part of the core only.
635  */
636 union net_ip_header {
637 	struct net_ipv4_hdr *ipv4;
638 	struct net_ipv6_hdr *ipv6;
639 };
640 
641 union net_proto_header {
642 	struct net_udp_hdr *udp;
643 	struct net_tcp_hdr *tcp;
644 };
645 
646 #define NET_UDPH_LEN	8			/* Size of UDP header */
647 #define NET_TCPH_LEN	20			/* Size of TCP header */
648 #define NET_ICMPH_LEN	4			/* Size of ICMP header */
649 
650 #define NET_IPV6H_LEN	   40			/* Size of IPv6 header */
651 #define NET_ICMPV6H_LEN	   NET_ICMPH_LEN	/* Size of ICMPv6 header */
652 #define NET_IPV6UDPH_LEN   (NET_UDPH_LEN + NET_IPV6H_LEN) /* IPv6 + UDP */
653 #define NET_IPV6TCPH_LEN   (NET_TCPH_LEN + NET_IPV6H_LEN) /* IPv6 + TCP */
654 #define NET_IPV6ICMPH_LEN  (NET_IPV6H_LEN + NET_ICMPH_LEN) /* ICMPv6 + IPv6 */
655 #define NET_IPV6_FRAGH_LEN 8
656 
657 #define NET_IPV4H_LEN	   20			/* Size of IPv4 header */
658 #define NET_ICMPV4H_LEN	   NET_ICMPH_LEN	/* Size of ICMPv4 header */
659 #define NET_IPV4UDPH_LEN   (NET_UDPH_LEN + NET_IPV4H_LEN) /* IPv4 + UDP */
660 #define NET_IPV4TCPH_LEN   (NET_TCPH_LEN + NET_IPV4H_LEN) /* IPv4 + TCP */
661 #define NET_IPV4ICMPH_LEN  (NET_IPV4H_LEN + NET_ICMPH_LEN) /* ICMPv4 + IPv4 */
662 
663 #define NET_IPV6H_LENGTH_OFFSET		0x04	/* Offset of the Length field in the IPv6 header */
664 
665 #define NET_IPV6_FRAGH_OFFSET_MASK	0xfff8	/* Mask for the 13-bit Fragment Offset field */
666 #define NET_IPV4_FRAGH_OFFSET_MASK	0x1fff	/* Mask for the 13-bit Fragment Offset field */
667 #define NET_IPV4_MORE_FRAG_MASK		0x2000	/* Mask for the 1-bit More Fragments field */
668 #define NET_IPV4_DO_NOT_FRAG_MASK	0x4000	/* Mask for the 1-bit Do Not Fragment field */
669 
670 /** @endcond */
671 
672 /**
673  * @brief Check if the IPv6 address is a loopback address (::1).
674  *
675  * @param addr IPv6 address
676  *
677  * @return True if address is a loopback address, False otherwise.
678  */
net_ipv6_is_addr_loopback(struct in6_addr * addr)679 static inline bool net_ipv6_is_addr_loopback(struct in6_addr *addr)
680 {
681 	return UNALIGNED_GET(&addr->s6_addr32[0]) == 0 &&
682 		UNALIGNED_GET(&addr->s6_addr32[1]) == 0 &&
683 		UNALIGNED_GET(&addr->s6_addr32[2]) == 0 &&
684 		ntohl(UNALIGNED_GET(&addr->s6_addr32[3])) == 1;
685 }
686 
687 /**
688  * @brief Check if the IPv6 address is a multicast address.
689  *
690  * @param addr IPv6 address
691  *
692  * @return True if address is multicast address, False otherwise.
693  */
net_ipv6_is_addr_mcast(const struct in6_addr * addr)694 static inline bool net_ipv6_is_addr_mcast(const struct in6_addr *addr)
695 {
696 	return addr->s6_addr[0] == 0xFF;
697 }
698 
699 struct net_if;
700 struct net_if_config;
701 
702 extern struct net_if_addr *net_if_ipv6_addr_lookup(const struct in6_addr *addr,
703 						   struct net_if **iface);
704 
705 /**
706  * @brief Check if IPv6 address is found in one of the network interfaces.
707  *
708  * @param addr IPv6 address
709  *
710  * @return True if address was found, False otherwise.
711  */
net_ipv6_is_my_addr(struct in6_addr * addr)712 static inline bool net_ipv6_is_my_addr(struct in6_addr *addr)
713 {
714 	return net_if_ipv6_addr_lookup(addr, NULL) != NULL;
715 }
716 
717 extern struct net_if_mcast_addr *net_if_ipv6_maddr_lookup(
718 	const struct in6_addr *addr, struct net_if **iface);
719 
720 /**
721  * @brief Check if IPv6 multicast address is found in one of the
722  * network interfaces.
723  *
724  * @param maddr Multicast IPv6 address
725  *
726  * @return True if address was found, False otherwise.
727  */
net_ipv6_is_my_maddr(struct in6_addr * maddr)728 static inline bool net_ipv6_is_my_maddr(struct in6_addr *maddr)
729 {
730 	return net_if_ipv6_maddr_lookup(maddr, NULL) != NULL;
731 }
732 
733 /**
734  * @brief Check if two IPv6 addresses are same when compared after prefix mask.
735  *
736  * @param addr1 First IPv6 address.
737  * @param addr2 Second IPv6 address.
738  * @param length Prefix length (max length is 128).
739  *
740  * @return True if IPv6 prefixes are the same, False otherwise.
741  */
net_ipv6_is_prefix(const uint8_t * addr1,const uint8_t * addr2,uint8_t length)742 static inline bool net_ipv6_is_prefix(const uint8_t *addr1,
743 				      const uint8_t *addr2,
744 				      uint8_t length)
745 {
746 	uint8_t bits = 128 - length;
747 	uint8_t bytes = length / 8U;
748 	uint8_t remain = bits % 8;
749 	uint8_t mask;
750 
751 	if (length > 128) {
752 		return false;
753 	}
754 
755 	if (memcmp(addr1, addr2, bytes)) {
756 		return false;
757 	}
758 
759 	if (!remain) {
760 		/* No remaining bits, the prefixes are the same as first
761 		 * bytes are the same.
762 		 */
763 		return true;
764 	}
765 
766 	/* Create a mask that has remaining most significant bits set */
767 	mask = (uint8_t)((0xff << (8 - remain)) ^ 0xff) << remain;
768 
769 	return (addr1[bytes] & mask) == (addr2[bytes] & mask);
770 }
771 
772 
773 /**
774  * @brief Get the IPv6 network address via the unicast address and the prefix mask.
775  *
776  * @param inaddr Unicast IPv6 address.
777  * @param outaddr Prefix masked IPv6 address (network address).
778  * @param prefix_len Prefix length (max length is 128).
779  */
net_ipv6_addr_prefix_mask(const uint8_t * inaddr,uint8_t * outaddr,uint8_t prefix_len)780 static inline void net_ipv6_addr_prefix_mask(const uint8_t *inaddr,
781 					     uint8_t *outaddr,
782 					     uint8_t prefix_len)
783 {
784 	uint8_t bits = 128 - prefix_len;
785 	uint8_t bytes = prefix_len / 8U;
786 	uint8_t remain = bits % 8;
787 	uint8_t mask;
788 
789 	memset(outaddr, 0, 16U);
790 	memcpy(outaddr, inaddr, bytes);
791 
792 	if (!remain) {
793 		/* No remaining bits, the prefixes are the same as first
794 		 * bytes are the same.
795 		 */
796 		return;
797 	}
798 
799 	/* Create a mask that has remaining most significant bits set */
800 	mask = (uint8_t)((0xff << (8 - remain)) ^ 0xff) << remain;
801 	outaddr[bytes] = inaddr[bytes] & mask;
802 }
803 
804 /**
805  * @brief Check if the IPv4 address is a loopback address (127.0.0.0/8).
806  *
807  * @param addr IPv4 address
808  *
809  * @return True if address is a loopback address, False otherwise.
810  */
net_ipv4_is_addr_loopback(struct in_addr * addr)811 static inline bool net_ipv4_is_addr_loopback(struct in_addr *addr)
812 {
813 	return addr->s4_addr[0] == 127U;
814 }
815 
816 /**
817  *  @brief Check if the IPv4 address is unspecified (all bits zero)
818  *
819  *  @param addr IPv4 address.
820  *
821  *  @return True if the address is unspecified, false otherwise.
822  */
net_ipv4_is_addr_unspecified(const struct in_addr * addr)823 static inline bool net_ipv4_is_addr_unspecified(const struct in_addr *addr)
824 {
825 	return UNALIGNED_GET(&addr->s_addr) == 0;
826 }
827 
828 /**
829  * @brief Check if the IPv4 address is a multicast address.
830  *
831  * @param addr IPv4 address
832  *
833  * @return True if address is multicast address, False otherwise.
834  */
net_ipv4_is_addr_mcast(const struct in_addr * addr)835 static inline bool net_ipv4_is_addr_mcast(const struct in_addr *addr)
836 {
837 	return (ntohl(UNALIGNED_GET(&addr->s_addr)) & 0xF0000000) == 0xE0000000;
838 }
839 
840 /**
841  * @brief Check if the given IPv4 address is a link local address.
842  *
843  * @param addr A valid pointer on an IPv4 address
844  *
845  * @return True if it is, false otherwise.
846  */
net_ipv4_is_ll_addr(const struct in_addr * addr)847 static inline bool net_ipv4_is_ll_addr(const struct in_addr *addr)
848 {
849 	return (ntohl(UNALIGNED_GET(&addr->s_addr)) & 0xFFFF0000) == 0xA9FE0000;
850 }
851 
852 /**
853  * @brief Check if the given IPv4 address is from a private address range.
854  *
855  * See https://en.wikipedia.org/wiki/Reserved_IP_addresses for details.
856  *
857  * @param addr A valid pointer on an IPv4 address
858  *
859  * @return True if it is, false otherwise.
860  */
net_ipv4_is_private_addr(const struct in_addr * addr)861 static inline bool net_ipv4_is_private_addr(const struct in_addr *addr)
862 {
863 	uint32_t masked_24, masked_16, masked_12, masked_10, masked_8;
864 
865 	masked_24 = ntohl(UNALIGNED_GET(&addr->s_addr)) & 0xFFFFFF00;
866 	masked_16 = masked_24 & 0xFFFF0000;
867 	masked_12 = masked_24 & 0xFFF00000;
868 	masked_10 = masked_24 & 0xFFC00000;
869 	masked_8 = masked_24 & 0xFF000000;
870 
871 	return masked_8  == 0x0A000000 || /* 10.0.0.0/8      */
872 	       masked_10 == 0x64400000 || /* 100.64.0.0/10   */
873 	       masked_12 == 0xAC100000 || /* 172.16.0.0/12   */
874 	       masked_16 == 0xC0A80000 || /* 192.168.0.0/16  */
875 	       masked_24 == 0xC0000200 || /* 192.0.2.0/24    */
876 	       masked_24 == 0xC0336400 || /* 192.51.100.0/24 */
877 	       masked_24 == 0xCB007100;   /* 203.0.113.0/24  */
878 }
879 
880 /**
881  *  @brief Copy an IPv4 or IPv6 address
882  *
883  *  @param dest Destination IP address.
884  *  @param src Source IP address.
885  *
886  *  @return Destination address.
887  */
888 #define net_ipaddr_copy(dest, src) \
889 	UNALIGNED_PUT(UNALIGNED_GET(src), dest)
890 
891 /**
892  *  @brief Copy an IPv4 address raw buffer
893  *
894  *  @param dest Destination IP address.
895  *  @param src Source IP address.
896  */
net_ipv4_addr_copy_raw(uint8_t * dest,const uint8_t * src)897 static inline void net_ipv4_addr_copy_raw(uint8_t *dest,
898 					  const uint8_t *src)
899 {
900 	net_ipaddr_copy((struct in_addr *)dest, (const struct in_addr *)src);
901 }
902 
903 /**
904  *  @brief Copy an IPv6 address raw buffer
905  *
906  *  @param dest Destination IP address.
907  *  @param src Source IP address.
908  */
net_ipv6_addr_copy_raw(uint8_t * dest,const uint8_t * src)909 static inline void net_ipv6_addr_copy_raw(uint8_t *dest,
910 					  const uint8_t *src)
911 {
912 	memcpy(dest, src, sizeof(struct in6_addr));
913 }
914 
915 /**
916  *  @brief Compare two IPv4 addresses
917  *
918  *  @param addr1 Pointer to IPv4 address.
919  *  @param addr2 Pointer to IPv4 address.
920  *
921  *  @return True if the addresses are the same, false otherwise.
922  */
net_ipv4_addr_cmp(const struct in_addr * addr1,const struct in_addr * addr2)923 static inline bool net_ipv4_addr_cmp(const struct in_addr *addr1,
924 				     const struct in_addr *addr2)
925 {
926 	return UNALIGNED_GET(&addr1->s_addr) == UNALIGNED_GET(&addr2->s_addr);
927 }
928 
929 /**
930  *  @brief Compare two raw IPv4 address buffers
931  *
932  *  @param addr1 Pointer to IPv4 address buffer.
933  *  @param addr2 Pointer to IPv4 address buffer.
934  *
935  *  @return True if the addresses are the same, false otherwise.
936  */
net_ipv4_addr_cmp_raw(const uint8_t * addr1,const uint8_t * addr2)937 static inline bool net_ipv4_addr_cmp_raw(const uint8_t *addr1,
938 					 const uint8_t *addr2)
939 {
940 	return net_ipv4_addr_cmp((const struct in_addr *)addr1,
941 				 (const struct in_addr *)addr2);
942 }
943 
944 /**
945  *  @brief Compare two IPv6 addresses
946  *
947  *  @param addr1 Pointer to IPv6 address.
948  *  @param addr2 Pointer to IPv6 address.
949  *
950  *  @return True if the addresses are the same, false otherwise.
951  */
net_ipv6_addr_cmp(const struct in6_addr * addr1,const struct in6_addr * addr2)952 static inline bool net_ipv6_addr_cmp(const struct in6_addr *addr1,
953 				     const struct in6_addr *addr2)
954 {
955 	return !memcmp(addr1, addr2, sizeof(struct in6_addr));
956 }
957 
958 /**
959  *  @brief Compare two raw IPv6 address buffers
960  *
961  *  @param addr1 Pointer to IPv6 address buffer.
962  *  @param addr2 Pointer to IPv6 address buffer.
963  *
964  *  @return True if the addresses are the same, false otherwise.
965  */
net_ipv6_addr_cmp_raw(const uint8_t * addr1,const uint8_t * addr2)966 static inline bool net_ipv6_addr_cmp_raw(const uint8_t *addr1,
967 					 const uint8_t *addr2)
968 {
969 	return net_ipv6_addr_cmp((const struct in6_addr *)addr1,
970 				 (const struct in6_addr *)addr2);
971 }
972 
973 /**
974  * @brief Check if the given IPv6 address is a link local address.
975  *
976  * @param addr A valid pointer on an IPv6 address
977  *
978  * @return True if it is, false otherwise.
979  */
net_ipv6_is_ll_addr(const struct in6_addr * addr)980 static inline bool net_ipv6_is_ll_addr(const struct in6_addr *addr)
981 {
982 	return UNALIGNED_GET(&addr->s6_addr16[0]) == htons(0xFE80);
983 }
984 
985 /**
986  * @brief Check if the given IPv6 address is a site local address.
987  *
988  * @param addr A valid pointer on an IPv6 address
989  *
990  * @return True if it is, false otherwise.
991  */
net_ipv6_is_sl_addr(const struct in6_addr * addr)992 static inline bool net_ipv6_is_sl_addr(const struct in6_addr *addr)
993 {
994 	return UNALIGNED_GET(&addr->s6_addr16[0]) == htons(0xFEC0);
995 }
996 
997 
998 /**
999  * @brief Check if the given IPv6 address is a unique local address.
1000  *
1001  * @param addr A valid pointer on an IPv6 address
1002  *
1003  * @return True if it is, false otherwise.
1004  */
net_ipv6_is_ula_addr(const struct in6_addr * addr)1005 static inline bool net_ipv6_is_ula_addr(const struct in6_addr *addr)
1006 {
1007 	return addr->s6_addr[0] == 0xFD;
1008 }
1009 
1010 /**
1011  * @brief Check if the given IPv6 address is a global address.
1012  *
1013  * @param addr A valid pointer on an IPv6 address
1014  *
1015  * @return True if it is, false otherwise.
1016  */
net_ipv6_is_global_addr(const struct in6_addr * addr)1017 static inline bool net_ipv6_is_global_addr(const struct in6_addr *addr)
1018 {
1019 	return (addr->s6_addr[0] & 0xE0) == 0x20;
1020 }
1021 
1022 /**
1023  * @brief Check if the given IPv6 address is from a private/local address range.
1024  *
1025  * See https://en.wikipedia.org/wiki/Reserved_IP_addresses for details.
1026  *
1027  * @param addr A valid pointer on an IPv6 address
1028  *
1029  * @return True if it is, false otherwise.
1030  */
net_ipv6_is_private_addr(const struct in6_addr * addr)1031 static inline bool net_ipv6_is_private_addr(const struct in6_addr *addr)
1032 {
1033 	uint32_t masked_32, masked_7;
1034 
1035 	masked_32 = ntohl(UNALIGNED_GET(&addr->s6_addr32[0]));
1036 	masked_7 = masked_32 & 0xfc000000;
1037 
1038 	return masked_32 == 0x20010db8 || /* 2001:db8::/32 */
1039 	       masked_7  == 0xfc000000;   /* fc00::/7      */
1040 }
1041 
1042 /**
1043  * @brief Return pointer to any (all bits zeros) IPv6 address.
1044  *
1045  * @return Any IPv6 address.
1046  */
1047 const struct in6_addr *net_ipv6_unspecified_address(void);
1048 
1049 /**
1050  * @brief Return pointer to any (all bits zeros) IPv4 address.
1051  *
1052  * @return Any IPv4 address.
1053  */
1054 const struct in_addr *net_ipv4_unspecified_address(void);
1055 
1056 /**
1057  * @brief Return pointer to broadcast (all bits ones) IPv4 address.
1058  *
1059  * @return Broadcast IPv4 address.
1060  */
1061 const struct in_addr *net_ipv4_broadcast_address(void);
1062 
1063 struct net_if;
1064 extern bool net_if_ipv4_addr_mask_cmp(struct net_if *iface,
1065 				      const struct in_addr *addr);
1066 
1067 /**
1068  * @brief Check if the given address belongs to same subnet that
1069  * has been configured for the interface.
1070  *
1071  * @param iface A valid pointer on an interface
1072  * @param addr IPv4 address
1073  *
1074  * @return True if address is in same subnet, false otherwise.
1075  */
net_ipv4_addr_mask_cmp(struct net_if * iface,const struct in_addr * addr)1076 static inline bool net_ipv4_addr_mask_cmp(struct net_if *iface,
1077 					  const struct in_addr *addr)
1078 {
1079 	return net_if_ipv4_addr_mask_cmp(iface, addr);
1080 }
1081 
1082 extern bool net_if_ipv4_is_addr_bcast(struct net_if *iface,
1083 				      const struct in_addr *addr);
1084 
1085 /**
1086  * @brief Check if the given IPv4 address is a broadcast address.
1087  *
1088  * @param iface Interface to use. Must be a valid pointer to an interface.
1089  * @param addr IPv4 address
1090  *
1091  * @return True if address is a broadcast address, false otherwise.
1092  */
1093 #if defined(CONFIG_NET_NATIVE_IPV4)
net_ipv4_is_addr_bcast(struct net_if * iface,const struct in_addr * addr)1094 static inline bool net_ipv4_is_addr_bcast(struct net_if *iface,
1095 					  const struct in_addr *addr)
1096 {
1097 	if (net_ipv4_addr_cmp(addr, net_ipv4_broadcast_address())) {
1098 		return true;
1099 	}
1100 
1101 	return net_if_ipv4_is_addr_bcast(iface, addr);
1102 }
1103 #else
net_ipv4_is_addr_bcast(struct net_if * iface,const struct in_addr * addr)1104 static inline bool net_ipv4_is_addr_bcast(struct net_if *iface,
1105 					  const struct in_addr *addr)
1106 {
1107 	ARG_UNUSED(iface);
1108 	ARG_UNUSED(addr);
1109 
1110 	return false;
1111 }
1112 #endif
1113 
1114 extern struct net_if_addr *net_if_ipv4_addr_lookup(const struct in_addr *addr,
1115 						   struct net_if **iface);
1116 
1117 /**
1118  * @brief Check if the IPv4 address is assigned to any network interface
1119  * in the system.
1120  *
1121  * @param addr A valid pointer on an IPv4 address
1122  *
1123  * @return True if IPv4 address is found in one of the network interfaces,
1124  * False otherwise.
1125  */
net_ipv4_is_my_addr(const struct in_addr * addr)1126 static inline bool net_ipv4_is_my_addr(const struct in_addr *addr)
1127 {
1128 	bool ret;
1129 
1130 	ret = net_if_ipv4_addr_lookup(addr, NULL) != NULL;
1131 	if (!ret) {
1132 		ret = net_ipv4_is_addr_bcast(NULL, addr);
1133 	}
1134 
1135 	return ret;
1136 }
1137 
1138 /**
1139  *  @brief Check if the IPv6 address is unspecified (all bits zero)
1140  *
1141  *  @param addr IPv6 address.
1142  *
1143  *  @return True if the address is unspecified, false otherwise.
1144  */
net_ipv6_is_addr_unspecified(const struct in6_addr * addr)1145 static inline bool net_ipv6_is_addr_unspecified(const struct in6_addr *addr)
1146 {
1147 	return UNALIGNED_GET(&addr->s6_addr32[0]) == 0 &&
1148 		UNALIGNED_GET(&addr->s6_addr32[1]) == 0 &&
1149 		UNALIGNED_GET(&addr->s6_addr32[2]) == 0 &&
1150 		UNALIGNED_GET(&addr->s6_addr32[3]) == 0;
1151 }
1152 
1153 /**
1154  *  @brief Check if the IPv6 address is solicited node multicast address
1155  *  FF02:0:0:0:0:1:FFXX:XXXX defined in RFC 3513
1156  *
1157  *  @param addr IPv6 address.
1158  *
1159  *  @return True if the address is solicited node address, false otherwise.
1160  */
net_ipv6_is_addr_solicited_node(const struct in6_addr * addr)1161 static inline bool net_ipv6_is_addr_solicited_node(const struct in6_addr *addr)
1162 {
1163 	return UNALIGNED_GET(&addr->s6_addr32[0]) == htonl(0xff020000) &&
1164 		UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00000000 &&
1165 		UNALIGNED_GET(&addr->s6_addr32[2]) == htonl(0x00000001) &&
1166 		((UNALIGNED_GET(&addr->s6_addr32[3]) & htonl(0xff000000)) ==
1167 		 htonl(0xff000000));
1168 }
1169 
1170 /**
1171  * @brief Check if the IPv6 address is a given scope multicast
1172  * address (FFyx::).
1173  *
1174  * @param addr IPv6 address
1175  * @param scope Scope to check
1176  *
1177  * @return True if the address is in given scope multicast address,
1178  * false otherwise.
1179  */
net_ipv6_is_addr_mcast_scope(const struct in6_addr * addr,int scope)1180 static inline bool net_ipv6_is_addr_mcast_scope(const struct in6_addr *addr,
1181 						int scope)
1182 {
1183 	return (addr->s6_addr[0] == 0xff) && ((addr->s6_addr[1] & 0xF) == scope);
1184 }
1185 
1186 /**
1187  * @brief Check if the IPv6 addresses have the same multicast scope (FFyx::).
1188  *
1189  * @param addr_1 IPv6 address 1
1190  * @param addr_2 IPv6 address 2
1191  *
1192  * @return True if both addresses have same multicast scope,
1193  * false otherwise.
1194  */
net_ipv6_is_same_mcast_scope(const struct in6_addr * addr_1,const struct in6_addr * addr_2)1195 static inline bool net_ipv6_is_same_mcast_scope(const struct in6_addr *addr_1,
1196 						const struct in6_addr *addr_2)
1197 {
1198 	return (addr_1->s6_addr[0] == 0xff) && (addr_2->s6_addr[0] == 0xff) &&
1199 			(addr_1->s6_addr[1] == addr_2->s6_addr[1]);
1200 }
1201 
1202 /**
1203  * @brief Check if the IPv6 address is a global multicast address (FFxE::/16).
1204  *
1205  * @param addr IPv6 address.
1206  *
1207  * @return True if the address is global multicast address, false otherwise.
1208  */
net_ipv6_is_addr_mcast_global(const struct in6_addr * addr)1209 static inline bool net_ipv6_is_addr_mcast_global(const struct in6_addr *addr)
1210 {
1211 	return net_ipv6_is_addr_mcast_scope(addr, 0x0e);
1212 }
1213 
1214 /**
1215  * @brief Check if the IPv6 address is a interface scope multicast
1216  * address (FFx1::).
1217  *
1218  * @param addr IPv6 address.
1219  *
1220  * @return True if the address is a interface scope multicast address,
1221  * false otherwise.
1222  */
net_ipv6_is_addr_mcast_iface(const struct in6_addr * addr)1223 static inline bool net_ipv6_is_addr_mcast_iface(const struct in6_addr *addr)
1224 {
1225 	return net_ipv6_is_addr_mcast_scope(addr, 0x01);
1226 }
1227 
1228 /**
1229  * @brief Check if the IPv6 address is a link local scope multicast
1230  * address (FFx2::).
1231  *
1232  * @param addr IPv6 address.
1233  *
1234  * @return True if the address is a link local scope multicast address,
1235  * false otherwise.
1236  */
net_ipv6_is_addr_mcast_link(const struct in6_addr * addr)1237 static inline bool net_ipv6_is_addr_mcast_link(const struct in6_addr *addr)
1238 {
1239 	return net_ipv6_is_addr_mcast_scope(addr, 0x02);
1240 }
1241 
1242 /**
1243  * @brief Check if the IPv6 address is a mesh-local scope multicast
1244  * address (FFx3::).
1245  *
1246  * @param addr IPv6 address.
1247  *
1248  * @return True if the address is a mesh-local scope multicast address,
1249  * false otherwise.
1250  */
net_ipv6_is_addr_mcast_mesh(const struct in6_addr * addr)1251 static inline bool net_ipv6_is_addr_mcast_mesh(const struct in6_addr *addr)
1252 {
1253 	return net_ipv6_is_addr_mcast_scope(addr, 0x03);
1254 }
1255 
1256 /**
1257  * @brief Check if the IPv6 address is a site scope multicast
1258  * address (FFx5::).
1259  *
1260  * @param addr IPv6 address.
1261  *
1262  * @return True if the address is a site scope multicast address,
1263  * false otherwise.
1264  */
net_ipv6_is_addr_mcast_site(const struct in6_addr * addr)1265 static inline bool net_ipv6_is_addr_mcast_site(const struct in6_addr *addr)
1266 {
1267 	return net_ipv6_is_addr_mcast_scope(addr, 0x05);
1268 }
1269 
1270 /**
1271  * @brief Check if the IPv6 address is an organization scope multicast
1272  * address (FFx8::).
1273  *
1274  * @param addr IPv6 address.
1275  *
1276  * @return True if the address is an organization scope multicast address,
1277  * false otherwise.
1278  */
net_ipv6_is_addr_mcast_org(const struct in6_addr * addr)1279 static inline bool net_ipv6_is_addr_mcast_org(const struct in6_addr *addr)
1280 {
1281 	return net_ipv6_is_addr_mcast_scope(addr, 0x08);
1282 }
1283 
1284 /**
1285  * @brief Check if the IPv6 address belongs to certain multicast group
1286  *
1287  * @param addr IPv6 address.
1288  * @param group Group id IPv6 address, the values must be in network
1289  * byte order
1290  *
1291  * @return True if the IPv6 multicast address belongs to given multicast
1292  * group, false otherwise.
1293  */
net_ipv6_is_addr_mcast_group(const struct in6_addr * addr,const struct in6_addr * group)1294 static inline bool net_ipv6_is_addr_mcast_group(const struct in6_addr *addr,
1295 						const struct in6_addr *group)
1296 {
1297 	return UNALIGNED_GET(&addr->s6_addr16[1]) == group->s6_addr16[1] &&
1298 		UNALIGNED_GET(&addr->s6_addr16[2]) == group->s6_addr16[2] &&
1299 		UNALIGNED_GET(&addr->s6_addr16[3]) == group->s6_addr16[3] &&
1300 		UNALIGNED_GET(&addr->s6_addr32[1]) == group->s6_addr32[1] &&
1301 		UNALIGNED_GET(&addr->s6_addr32[2]) == group->s6_addr32[1] &&
1302 		UNALIGNED_GET(&addr->s6_addr32[3]) == group->s6_addr32[3];
1303 }
1304 
1305 /**
1306  * @brief Check if the IPv6 address belongs to the all nodes multicast group
1307  *
1308  * @param addr IPv6 address
1309  *
1310  * @return True if the IPv6 multicast address belongs to the all nodes multicast
1311  * group, false otherwise
1312  */
1313 static inline bool
net_ipv6_is_addr_mcast_all_nodes_group(const struct in6_addr * addr)1314 net_ipv6_is_addr_mcast_all_nodes_group(const struct in6_addr *addr)
1315 {
1316 	static const struct in6_addr all_nodes_mcast_group = {
1317 		{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1318 		    0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1319 	};
1320 
1321 	return net_ipv6_is_addr_mcast_group(addr, &all_nodes_mcast_group);
1322 }
1323 
1324 /**
1325  * @brief Check if the IPv6 address is a interface scope all nodes multicast
1326  * address (FF01::1).
1327  *
1328  * @param addr IPv6 address.
1329  *
1330  * @return True if the address is a interface scope all nodes multicast address,
1331  * false otherwise.
1332  */
1333 static inline bool
net_ipv6_is_addr_mcast_iface_all_nodes(const struct in6_addr * addr)1334 net_ipv6_is_addr_mcast_iface_all_nodes(const struct in6_addr *addr)
1335 {
1336 	return net_ipv6_is_addr_mcast_iface(addr) &&
1337 	       net_ipv6_is_addr_mcast_all_nodes_group(addr);
1338 }
1339 
1340 /**
1341  * @brief Check if the IPv6 address is a link local scope all nodes multicast
1342  * address (FF02::1).
1343  *
1344  * @param addr IPv6 address.
1345  *
1346  * @return True if the address is a link local scope all nodes multicast
1347  * address, false otherwise.
1348  */
1349 static inline bool
net_ipv6_is_addr_mcast_link_all_nodes(const struct in6_addr * addr)1350 net_ipv6_is_addr_mcast_link_all_nodes(const struct in6_addr *addr)
1351 {
1352 	return net_ipv6_is_addr_mcast_link(addr) &&
1353 	       net_ipv6_is_addr_mcast_all_nodes_group(addr);
1354 }
1355 
1356 /**
1357  *  @brief Create solicited node IPv6 multicast address
1358  *  FF02:0:0:0:0:1:FFXX:XXXX defined in RFC 3513
1359  *
1360  *  @param src IPv6 address.
1361  *  @param dst IPv6 address.
1362  */
1363 static inline
net_ipv6_addr_create_solicited_node(const struct in6_addr * src,struct in6_addr * dst)1364 void net_ipv6_addr_create_solicited_node(const struct in6_addr *src,
1365 					 struct in6_addr *dst)
1366 {
1367 	dst->s6_addr[0]   = 0xFF;
1368 	dst->s6_addr[1]   = 0x02;
1369 	UNALIGNED_PUT(0, &dst->s6_addr16[1]);
1370 	UNALIGNED_PUT(0, &dst->s6_addr16[2]);
1371 	UNALIGNED_PUT(0, &dst->s6_addr16[3]);
1372 	UNALIGNED_PUT(0, &dst->s6_addr16[4]);
1373 	dst->s6_addr[10]  = 0U;
1374 	dst->s6_addr[11]  = 0x01;
1375 	dst->s6_addr[12]  = 0xFF;
1376 	dst->s6_addr[13]  = src->s6_addr[13];
1377 	UNALIGNED_PUT(UNALIGNED_GET(&src->s6_addr16[7]), &dst->s6_addr16[7]);
1378 }
1379 
1380 /** @brief Construct an IPv6 address from eight 16-bit words.
1381  *
1382  *  @param addr IPv6 address
1383  *  @param addr0 16-bit word which is part of the address
1384  *  @param addr1 16-bit word which is part of the address
1385  *  @param addr2 16-bit word which is part of the address
1386  *  @param addr3 16-bit word which is part of the address
1387  *  @param addr4 16-bit word which is part of the address
1388  *  @param addr5 16-bit word which is part of the address
1389  *  @param addr6 16-bit word which is part of the address
1390  *  @param addr7 16-bit word which is part of the address
1391  */
net_ipv6_addr_create(struct in6_addr * addr,uint16_t addr0,uint16_t addr1,uint16_t addr2,uint16_t addr3,uint16_t addr4,uint16_t addr5,uint16_t addr6,uint16_t addr7)1392 static inline void net_ipv6_addr_create(struct in6_addr *addr,
1393 					uint16_t addr0, uint16_t addr1,
1394 					uint16_t addr2, uint16_t addr3,
1395 					uint16_t addr4, uint16_t addr5,
1396 					uint16_t addr6, uint16_t addr7)
1397 {
1398 	UNALIGNED_PUT(htons(addr0), &addr->s6_addr16[0]);
1399 	UNALIGNED_PUT(htons(addr1), &addr->s6_addr16[1]);
1400 	UNALIGNED_PUT(htons(addr2), &addr->s6_addr16[2]);
1401 	UNALIGNED_PUT(htons(addr3), &addr->s6_addr16[3]);
1402 	UNALIGNED_PUT(htons(addr4), &addr->s6_addr16[4]);
1403 	UNALIGNED_PUT(htons(addr5), &addr->s6_addr16[5]);
1404 	UNALIGNED_PUT(htons(addr6), &addr->s6_addr16[6]);
1405 	UNALIGNED_PUT(htons(addr7), &addr->s6_addr16[7]);
1406 }
1407 
1408 /**
1409  *  @brief Create link local allnodes multicast IPv6 address
1410  *
1411  *  @param addr IPv6 address
1412  */
net_ipv6_addr_create_ll_allnodes_mcast(struct in6_addr * addr)1413 static inline void net_ipv6_addr_create_ll_allnodes_mcast(struct in6_addr *addr)
1414 {
1415 	net_ipv6_addr_create(addr, 0xff02, 0, 0, 0, 0, 0, 0, 0x0001);
1416 }
1417 
1418 /**
1419  *  @brief Create link local allrouters multicast IPv6 address
1420  *
1421  *  @param addr IPv6 address
1422  */
net_ipv6_addr_create_ll_allrouters_mcast(struct in6_addr * addr)1423 static inline void net_ipv6_addr_create_ll_allrouters_mcast(struct in6_addr *addr)
1424 {
1425 	net_ipv6_addr_create(addr, 0xff02, 0, 0, 0, 0, 0, 0, 0x0002);
1426 }
1427 
1428 /**
1429  *  @brief Create IPv4 mapped IPv6 address
1430  *
1431  *  @param addr4 IPv4 address
1432  *  @param addr6 IPv6 address to be created
1433  */
net_ipv6_addr_create_v4_mapped(const struct in_addr * addr4,struct in6_addr * addr6)1434 static inline void net_ipv6_addr_create_v4_mapped(const struct in_addr *addr4,
1435 						  struct in6_addr *addr6)
1436 {
1437 	net_ipv6_addr_create(addr6, 0, 0, 0, 0, 0, 0xffff,
1438 			     ntohs(addr4->s4_addr16[0]),
1439 			     ntohs(addr4->s4_addr16[1]));
1440 }
1441 
1442 /**
1443  *  @brief Is the IPv6 address an IPv4 mapped one. The v4 mapped addresses
1444  *         look like \::ffff:a.b.c.d
1445  *
1446  *  @param addr IPv6 address
1447  *
1448  *  @return True if IPv6 address is a IPv4 mapped address, False otherwise.
1449  */
net_ipv6_addr_is_v4_mapped(const struct in6_addr * addr)1450 static inline bool net_ipv6_addr_is_v4_mapped(const struct in6_addr *addr)
1451 {
1452 	if (UNALIGNED_GET(&addr->s6_addr32[0]) == 0 &&
1453 	    UNALIGNED_GET(&addr->s6_addr32[1]) == 0 &&
1454 	    UNALIGNED_GET(&addr->s6_addr16[5]) == 0xffff) {
1455 		return true;
1456 	}
1457 
1458 	return false;
1459 }
1460 
1461 /**
1462  *  @brief Generate IPv6 address using a prefix and interface identifier.
1463  *         Interface identifier is either generated from EUI-64 (MAC) defined
1464  *         in RFC 4291 or from randomized value defined in RFC 7217.
1465  *
1466  *  @param iface Network interface
1467  *  @param prefix IPv6 prefix, can be left out in which case fe80::/64 is used
1468  *  @param network_id Network identifier (for example SSID in WLAN), this is
1469  *         optional can be set to NULL
1470  *  @param network_id_len Network identifier length, if set to 0 then the
1471  *         network id is ignored.
1472  *  @param dad_counter Duplicate Address Detection counter value, can be set to 0
1473  *         if it is not known.
1474  *  @param addr IPv6 address
1475  *  @param lladdr Link local address
1476  *
1477  *  @return 0 if ok, < 0 if error
1478  */
1479 int net_ipv6_addr_generate_iid(struct net_if *iface,
1480 			       const struct in6_addr *prefix,
1481 			       uint8_t *network_id, size_t network_id_len,
1482 			       uint8_t dad_counter,
1483 			       struct in6_addr *addr,
1484 			       struct net_linkaddr *lladdr);
1485 
1486 /**
1487  *  @brief Create IPv6 address interface identifier.
1488  *
1489  *  @param addr IPv6 address
1490  *  @param lladdr Link local address
1491  */
net_ipv6_addr_create_iid(struct in6_addr * addr,struct net_linkaddr * lladdr)1492 static inline void net_ipv6_addr_create_iid(struct in6_addr *addr,
1493 					    struct net_linkaddr *lladdr)
1494 {
1495 	(void)net_ipv6_addr_generate_iid(NULL, NULL, NULL, 0, 0, addr, lladdr);
1496 }
1497 
1498 /**
1499  *  @brief Check if given address is based on link layer address
1500  *
1501  *  @return True if it is, False otherwise
1502  */
net_ipv6_addr_based_on_ll(const struct in6_addr * addr,const struct net_linkaddr * lladdr)1503 static inline bool net_ipv6_addr_based_on_ll(const struct in6_addr *addr,
1504 					     const struct net_linkaddr *lladdr)
1505 {
1506 	if (!addr || !lladdr) {
1507 		return false;
1508 	}
1509 
1510 	switch (lladdr->len) {
1511 	case 2:
1512 		if (!memcmp(&addr->s6_addr[14], lladdr->addr, lladdr->len) &&
1513 		    addr->s6_addr[8]  == 0U &&
1514 		    addr->s6_addr[9]  == 0U &&
1515 		    addr->s6_addr[10] == 0U &&
1516 		    addr->s6_addr[11] == 0xff &&
1517 		    addr->s6_addr[12] == 0xfe) {
1518 			return true;
1519 		}
1520 
1521 		break;
1522 	case 6:
1523 		if (lladdr->type == NET_LINK_ETHERNET) {
1524 			if (!memcmp(&addr->s6_addr[9], &lladdr->addr[1], 2) &&
1525 			    !memcmp(&addr->s6_addr[13], &lladdr->addr[3], 3) &&
1526 			    addr->s6_addr[11] == 0xff &&
1527 			    addr->s6_addr[12] == 0xfe &&
1528 			    (addr->s6_addr[8] ^ 0x02) == lladdr->addr[0]) {
1529 				return true;
1530 			}
1531 		}
1532 
1533 		break;
1534 	case 8:
1535 		if (!memcmp(&addr->s6_addr[9], &lladdr->addr[1],
1536 			    lladdr->len - 1) &&
1537 		    (addr->s6_addr[8] ^ 0x02) == lladdr->addr[0]) {
1538 			return true;
1539 		}
1540 
1541 		break;
1542 	}
1543 
1544 	return false;
1545 }
1546 
1547 /**
1548  * @brief Get sockaddr_in6 from sockaddr. This is a helper so that
1549  * the code calling this function can be made shorter.
1550  *
1551  * @param addr Socket address
1552  *
1553  * @return Pointer to IPv6 socket address
1554  */
net_sin6(const struct sockaddr * addr)1555 static inline struct sockaddr_in6 *net_sin6(const struct sockaddr *addr)
1556 {
1557 	return (struct sockaddr_in6 *)addr;
1558 }
1559 
1560 /**
1561  * @brief Get sockaddr_in from sockaddr. This is a helper so that
1562  * the code calling this function can be made shorter.
1563  *
1564  * @param addr Socket address
1565  *
1566  * @return Pointer to IPv4 socket address
1567  */
net_sin(const struct sockaddr * addr)1568 static inline struct sockaddr_in *net_sin(const struct sockaddr *addr)
1569 {
1570 	return (struct sockaddr_in *)addr;
1571 }
1572 
1573 /**
1574  * @brief Get sockaddr_in6_ptr from sockaddr_ptr. This is a helper so that
1575  * the code calling this function can be made shorter.
1576  *
1577  * @param addr Socket address
1578  *
1579  * @return Pointer to IPv6 socket address
1580  */
1581 static inline
net_sin6_ptr(const struct sockaddr_ptr * addr)1582 struct sockaddr_in6_ptr *net_sin6_ptr(const struct sockaddr_ptr *addr)
1583 {
1584 	return (struct sockaddr_in6_ptr *)addr;
1585 }
1586 
1587 /**
1588  * @brief Get sockaddr_in_ptr from sockaddr_ptr. This is a helper so that
1589  * the code calling this function can be made shorter.
1590  *
1591  * @param addr Socket address
1592  *
1593  * @return Pointer to IPv4 socket address
1594  */
1595 static inline
net_sin_ptr(const struct sockaddr_ptr * addr)1596 struct sockaddr_in_ptr *net_sin_ptr(const struct sockaddr_ptr *addr)
1597 {
1598 	return (struct sockaddr_in_ptr *)addr;
1599 }
1600 
1601 /**
1602  * @brief Get sockaddr_ll_ptr from sockaddr_ptr. This is a helper so that
1603  * the code calling this function can be made shorter.
1604  *
1605  * @param addr Socket address
1606  *
1607  * @return Pointer to linklayer socket address
1608  */
1609 static inline
net_sll_ptr(const struct sockaddr_ptr * addr)1610 struct sockaddr_ll_ptr *net_sll_ptr(const struct sockaddr_ptr *addr)
1611 {
1612 	return (struct sockaddr_ll_ptr *)addr;
1613 }
1614 
1615 /**
1616  * @brief Get sockaddr_can_ptr from sockaddr_ptr. This is a helper so that
1617  * the code needing this functionality can be made shorter.
1618  *
1619  * @param addr Socket address
1620  *
1621  * @return Pointer to CAN socket address
1622  */
1623 static inline
net_can_ptr(const struct sockaddr_ptr * addr)1624 struct sockaddr_can_ptr *net_can_ptr(const struct sockaddr_ptr *addr)
1625 {
1626 	return (struct sockaddr_can_ptr *)addr;
1627 }
1628 
1629 /**
1630  * @brief Convert a string to IP address.
1631  *
1632  * @param family IP address family (AF_INET or AF_INET6)
1633  * @param src IP address in a null terminated string
1634  * @param dst Pointer to struct in_addr if family is AF_INET or
1635  * pointer to struct in6_addr if family is AF_INET6
1636  *
1637  * @note This function doesn't do precise error checking,
1638  * do not use for untrusted strings.
1639  *
1640  * @return 0 if ok, < 0 if error
1641  */
1642 __syscall int net_addr_pton(sa_family_t family, const char *src, void *dst);
1643 
1644 /**
1645  * @brief Convert IP address to string form.
1646  *
1647  * @param family IP address family (AF_INET or AF_INET6)
1648  * @param src Pointer to struct in_addr if family is AF_INET or
1649  *        pointer to struct in6_addr if family is AF_INET6
1650  * @param dst Buffer for IP address as a null terminated string
1651  * @param size Number of bytes available in the buffer
1652  *
1653  * @return dst pointer if ok, NULL if error
1654  */
1655 __syscall char *net_addr_ntop(sa_family_t family, const void *src,
1656 			      char *dst, size_t size);
1657 
1658 /**
1659  * @brief Parse a string that contains either IPv4 or IPv6 address
1660  * and optional port, and store the information in user supplied
1661  * sockaddr struct.
1662  *
1663  * @details Syntax of the IP address string:
1664  *   192.0.2.1:80
1665  *   192.0.2.42
1666  *   [2001:db8::1]:8080
1667  *   [2001:db8::2]
1668  *   2001:db::42
1669  * Note that the str_len parameter is used to restrict the amount of
1670  * characters that are checked. If the string does not contain port
1671  * number, then the port number in sockaddr is not modified.
1672  *
1673  * @param str String that contains the IP address.
1674  * @param str_len Length of the string to be parsed.
1675  * @param addr Pointer to user supplied struct sockaddr.
1676  *
1677  * @return True if parsing could be done, false otherwise.
1678  */
1679 bool net_ipaddr_parse(const char *str, size_t str_len,
1680 		      struct sockaddr *addr);
1681 
1682 /**
1683  * @brief Set the default port in the sockaddr structure.
1684  * If the port is already set, then do nothing.
1685  *
1686  * @param addr Pointer to user supplied struct sockaddr.
1687  * @param default_port Default port number to set.
1688  *
1689  * @return 0 if ok, <0 if error
1690  */
1691 int net_port_set_default(struct sockaddr *addr, uint16_t default_port);
1692 
1693 /**
1694  * @brief Compare TCP sequence numbers.
1695  *
1696  * @details This function compares TCP sequence numbers,
1697  *          accounting for wraparound effects.
1698  *
1699  * @param seq1 First sequence number
1700  * @param seq2 Seconds sequence number
1701  *
1702  * @return < 0 if seq1 < seq2, 0 if seq1 == seq2, > 0 if seq > seq2
1703  */
net_tcp_seq_cmp(uint32_t seq1,uint32_t seq2)1704 static inline int32_t net_tcp_seq_cmp(uint32_t seq1, uint32_t seq2)
1705 {
1706 	return (int32_t)(seq1 - seq2);
1707 }
1708 
1709 /**
1710  * @brief Check that one TCP sequence number is greater.
1711  *
1712  * @details This is convenience function on top of net_tcp_seq_cmp().
1713  *
1714  * @param seq1 First sequence number
1715  * @param seq2 Seconds sequence number
1716  *
1717  * @return True if seq > seq2
1718  */
net_tcp_seq_greater(uint32_t seq1,uint32_t seq2)1719 static inline bool net_tcp_seq_greater(uint32_t seq1, uint32_t seq2)
1720 {
1721 	return net_tcp_seq_cmp(seq1, seq2) > 0;
1722 }
1723 
1724 /**
1725  * @brief Convert a string of hex values to array of bytes.
1726  *
1727  * @details The syntax of the string is "ab:02:98:fa:42:01"
1728  *
1729  * @param buf Pointer to memory where the bytes are written.
1730  * @param buf_len Length of the memory area.
1731  * @param src String of bytes.
1732  *
1733  * @return 0 if ok, <0 if error
1734  */
1735 int net_bytes_from_str(uint8_t *buf, int buf_len, const char *src);
1736 
1737 /**
1738  * @brief Convert Tx network packet priority to traffic class so we can place
1739  * the packet into correct Tx queue.
1740  *
1741  * @param prio Network priority
1742  *
1743  * @return Tx traffic class that handles that priority network traffic.
1744  */
1745 int net_tx_priority2tc(enum net_priority prio);
1746 
1747 /**
1748  * @brief Convert Rx network packet priority to traffic class so we can place
1749  * the packet into correct Rx queue.
1750  *
1751  * @param prio Network priority
1752  *
1753  * @return Rx traffic class that handles that priority network traffic.
1754  */
1755 int net_rx_priority2tc(enum net_priority prio);
1756 
1757 /**
1758  * @brief Convert network packet VLAN priority to network packet priority so we
1759  * can place the packet into correct queue.
1760  *
1761  * @param priority VLAN priority
1762  *
1763  * @return Network priority
1764  */
net_vlan2priority(uint8_t priority)1765 static inline enum net_priority net_vlan2priority(uint8_t priority)
1766 {
1767 	/* Map according to IEEE 802.1Q */
1768 	static const uint8_t vlan2priority[] = {
1769 		NET_PRIORITY_BE,
1770 		NET_PRIORITY_BK,
1771 		NET_PRIORITY_EE,
1772 		NET_PRIORITY_CA,
1773 		NET_PRIORITY_VI,
1774 		NET_PRIORITY_VO,
1775 		NET_PRIORITY_IC,
1776 		NET_PRIORITY_NC
1777 	};
1778 
1779 	if (priority >= ARRAY_SIZE(vlan2priority)) {
1780 		/* Use Best Effort as the default priority */
1781 		return NET_PRIORITY_BE;
1782 	}
1783 
1784 	return (enum net_priority)vlan2priority[priority];
1785 }
1786 
1787 /**
1788  * @brief Convert network packet priority to network packet VLAN priority.
1789  *
1790  * @param priority Packet priority
1791  *
1792  * @return VLAN priority (PCP)
1793  */
net_priority2vlan(enum net_priority priority)1794 static inline uint8_t net_priority2vlan(enum net_priority priority)
1795 {
1796 	/* The conversion works both ways */
1797 	return (uint8_t)net_vlan2priority(priority);
1798 }
1799 
1800 /**
1801  * @brief Return network address family value as a string. This is only usable
1802  * for debugging.
1803  *
1804  * @param family Network address family code
1805  *
1806  * @return Network address family as a string, or NULL if family is unknown.
1807  */
1808 const char *net_family2str(sa_family_t family);
1809 
1810 /**
1811  * @brief Add IPv6 prefix as a privacy extension filter.
1812  *
1813  * @details Note that the filters can either allow or deny listing.
1814  *
1815  * @param addr IPv6 prefix
1816  * @param is_denylist Tells if this filter is for allowing or denying listing.
1817  *
1818  * @return 0 if ok, <0 if error
1819  */
1820 #if defined(CONFIG_NET_IPV6_PE)
1821 int net_ipv6_pe_add_filter(struct in6_addr *addr, bool is_denylist);
1822 #else
net_ipv6_pe_add_filter(struct in6_addr * addr,bool is_denylist)1823 static inline int net_ipv6_pe_add_filter(struct in6_addr *addr,
1824 					 bool is_denylist)
1825 {
1826 	ARG_UNUSED(addr);
1827 	ARG_UNUSED(is_denylist);
1828 
1829 	return -ENOTSUP;
1830 }
1831 #endif /* CONFIG_NET_IPV6_PE */
1832 
1833 /**
1834  * @brief Delete IPv6 prefix from privacy extension filter list.
1835  *
1836  * @param addr IPv6 prefix
1837  *
1838  * @return 0 if ok, <0 if error
1839  */
1840 #if defined(CONFIG_NET_IPV6_PE)
1841 int net_ipv6_pe_del_filter(struct in6_addr *addr);
1842 #else
net_ipv6_pe_del_filter(struct in6_addr * addr)1843 static inline int net_ipv6_pe_del_filter(struct in6_addr *addr)
1844 {
1845 	ARG_UNUSED(addr);
1846 
1847 	return -ENOTSUP;
1848 }
1849 #endif /* CONFIG_NET_IPV6_PE */
1850 
1851 #ifdef __cplusplus
1852 }
1853 #endif
1854 
1855 #include <zephyr/syscalls/net_ip.h>
1856 
1857 /**
1858  * @}
1859  */
1860 
1861 
1862 #endif /* ZEPHYR_INCLUDE_NET_NET_IP_H_ */
1863