1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * SPDX-License-Identifier: MPL-2.0
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9  *
10  * See the COPYRIGHT file distributed with this work for additional
11  * information regarding copyright ownership.
12  */
13 
14 #ifndef ISC_NET_H
15 #define ISC_NET_H 1
16 
17 /*****
18 ***** Module Info
19 *****/
20 
21 /*! \file
22  * \brief
23  * Basic Networking Types
24  *
25  * This module is responsible for defining the following basic networking
26  * types:
27  *
28  *\li		struct in_addr
29  *\li		struct in6_addr
30  *\li		struct in6_pktinfo
31  *\li		struct sockaddr
32  *\li		struct sockaddr_in
33  *\li		struct sockaddr_in6
34  *\li		struct sockaddr_storage
35  *\li		in_port_t
36  *
37  * It ensures that the AF_ and PF_ macros are defined.
38  *
39  * It declares ntoh[sl]() and hton[sl]().
40  *
41  * It declares inet_ntop(), and inet_pton().
42  *
43  * It ensures that #INADDR_LOOPBACK, #INADDR_ANY, #IN6ADDR_ANY_INIT,
44  * IN6ADDR_V4MAPPED_INIT, in6addr_any, and in6addr_loopback are available.
45  *
46  * It ensures that IN_MULTICAST() is available to check for multicast
47  * addresses.
48  *
49  * MP:
50  *\li	No impact.
51  *
52  * Reliability:
53  *\li	No anticipated impact.
54  *
55  * Resources:
56  *\li	N/A.
57  *
58  * Security:
59  *\li	No anticipated impact.
60  *
61  * Standards:
62  *\li	BSD Socket API
63  *\li	RFC2553
64  */
65 
66 /***
67  *** Imports.
68  ***/
69 #include <inttypes.h>
70 
71 #include <isc/lang.h>
72 #include <isc/platform.h>
73 #include <isc/types.h>
74 
75 #include <arpa/inet.h> /* Contractual promise. */
76 #include <net/if.h>
77 #include <netinet/in.h> /* Contractual promise. */
78 #include <sys/socket.h> /* Contractual promise. */
79 #include <sys/types.h>
80 
81 #ifndef IN6ADDR_LOOPBACK_INIT
82 #ifdef s6_addr
83 /*% IPv6 address loopback init */
84 #define IN6ADDR_LOOPBACK_INIT                                                  \
85 	{                                                                      \
86 		{                                                              \
87 			{                                                      \
88 				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 \
89 			}                                                      \
90 		}                                                              \
91 	}
92 #else /* ifdef s6_addr */
93 #define IN6ADDR_LOOPBACK_INIT                                          \
94 	{                                                              \
95 		{                                                      \
96 			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 \
97 		}                                                      \
98 	}
99 #endif /* ifdef s6_addr */
100 #endif /* ifndef IN6ADDR_LOOPBACK_INIT */
101 
102 #ifndef IN6ADDR_V4MAPPED_INIT
103 #ifdef s6_addr
104 /*% IPv6 v4mapped prefix init */
105 #define IN6ADDR_V4MAPPED_INIT                                                \
106 	{                                                                    \
107 		{                                                            \
108 			{                                                    \
109 				0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, \
110 					0, 0, 0                              \
111 			}                                                    \
112 		}                                                            \
113 	}
114 #else /* ifdef s6_addr */
115 #define IN6ADDR_V4MAPPED_INIT                                                \
116 	{                                                                    \
117 		{                                                            \
118 			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0 \
119 		}                                                            \
120 	}
121 #endif /* ifdef s6_addr */
122 #endif /* ifndef IN6ADDR_V4MAPPED_INIT */
123 
124 #ifndef IN6_IS_ADDR_V4MAPPED
125 /*% Is IPv6 address V4 mapped? */
126 #define IN6_IS_ADDR_V4MAPPED(x)                                \
127 	(memcmp((x)->s6_addr, in6addr_any.s6_addr, 10) == 0 && \
128 	 (x)->s6_addr[10] == 0xff && (x)->s6_addr[11] == 0xff)
129 #endif /* ifndef IN6_IS_ADDR_V4MAPPED */
130 
131 #ifndef IN6_IS_ADDR_V4COMPAT
132 /*% Is IPv6 address V4 compatible? */
133 #define IN6_IS_ADDR_V4COMPAT(x)                                \
134 	(memcmp((x)->s6_addr, in6addr_any.s6_addr, 12) == 0 && \
135 	 ((x)->s6_addr[12] != 0 || (x)->s6_addr[13] != 0 ||    \
136 	  (x)->s6_addr[14] != 0 ||                             \
137 	  ((x)->s6_addr[15] != 0 && (x)->s6_addr[15] != 1)))
138 #endif /* ifndef IN6_IS_ADDR_V4COMPAT */
139 
140 #ifndef IN6_IS_ADDR_MULTICAST
141 /*% Is IPv6 address multicast? */
142 #define IN6_IS_ADDR_MULTICAST(a) ((a)->s6_addr[0] == 0xff)
143 #endif /* ifndef IN6_IS_ADDR_MULTICAST */
144 
145 #ifndef IN6_IS_ADDR_LINKLOCAL
146 /*% Is IPv6 address linklocal? */
147 #define IN6_IS_ADDR_LINKLOCAL(a) \
148 	(((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0x80))
149 #endif /* ifndef IN6_IS_ADDR_LINKLOCAL */
150 
151 #ifndef IN6_IS_ADDR_SITELOCAL
152 /*% is IPv6 address sitelocal? */
153 #define IN6_IS_ADDR_SITELOCAL(a) \
154 	(((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0))
155 #endif /* ifndef IN6_IS_ADDR_SITELOCAL */
156 
157 #ifndef IN6_IS_ADDR_LOOPBACK
158 /*% is IPv6 address loopback? */
159 #define IN6_IS_ADDR_LOOPBACK(x) \
160 	(memcmp((x)->s6_addr, in6addr_loopback.s6_addr, 16) == 0)
161 #endif /* ifndef IN6_IS_ADDR_LOOPBACK */
162 
163 #ifndef AF_INET6
164 /*% IPv6 */
165 #define AF_INET6 99
166 #endif /* ifndef AF_INET6 */
167 
168 #ifndef PF_INET6
169 /*% IPv6 */
170 #define PF_INET6 AF_INET6
171 #endif /* ifndef PF_INET6 */
172 
173 #ifndef INADDR_ANY
174 /*% inaddr any */
175 #define INADDR_ANY 0x00000000UL
176 #endif /* ifndef INADDR_ANY */
177 
178 #ifndef INADDR_LOOPBACK
179 /*% inaddr loopback */
180 #define INADDR_LOOPBACK 0x7f000001UL
181 #endif /* ifndef INADDR_LOOPBACK */
182 
183 #ifndef MSG_TRUNC
184 /*%
185  * If this system does not have MSG_TRUNC (as returned from recvmsg())
186  * ISC_PLATFORM_RECVOVERFLOW will be defined.  This will enable the MSG_TRUNC
187  * faking code in socket.c.
188  */
189 #define ISC_PLATFORM_RECVOVERFLOW
190 #endif /* ifndef MSG_TRUNC */
191 
192 /*% IP address. */
193 #define ISC__IPADDR(x) ((uint32_t)htonl((uint32_t)(x)))
194 
195 /*% Is IP address multicast? */
196 #define ISC_IPADDR_ISMULTICAST(i) \
197 	(((uint32_t)(i)&ISC__IPADDR(0xf0000000)) == ISC__IPADDR(0xe0000000))
198 
199 #define ISC_IPADDR_ISEXPERIMENTAL(i) \
200 	(((uint32_t)(i)&ISC__IPADDR(0xf0000000)) == ISC__IPADDR(0xf0000000))
201 
202 /***
203  *** Functions.
204  ***/
205 
206 ISC_LANG_BEGINDECLS
207 
208 isc_result_t
209 isc_net_probeipv4(void);
210 /*%<
211  * Check if the system's kernel supports IPv4.
212  *
213  * Returns:
214  *
215  *\li	#ISC_R_SUCCESS		IPv4 is supported.
216  *\li	#ISC_R_NOTFOUND		IPv4 is not supported.
217  *\li	#ISC_R_DISABLED		IPv4 is disabled.
218  *\li	#ISC_R_UNEXPECTED
219  */
220 
221 isc_result_t
222 isc_net_probeipv6(void);
223 /*%<
224  * Check if the system's kernel supports IPv6.
225  *
226  * Returns:
227  *
228  *\li	#ISC_R_SUCCESS		IPv6 is supported.
229  *\li	#ISC_R_NOTFOUND		IPv6 is not supported.
230  *\li	#ISC_R_DISABLED		IPv6 is disabled.
231  *\li	#ISC_R_UNEXPECTED
232  */
233 
234 isc_result_t
235 isc_net_probe_ipv6only(void);
236 /*%<
237  * Check if the system's kernel supports the IPV6_V6ONLY socket option.
238  *
239  * Returns:
240  *
241  *\li	#ISC_R_SUCCESS		the option is supported for both TCP and UDP.
242  *\li	#ISC_R_NOTFOUND		IPv6 itself or the option is not supported.
243  *\li	#ISC_R_UNEXPECTED
244  */
245 
246 isc_result_t
247 isc_net_probe_ipv6pktinfo(void);
248 /*
249  * Check if the system's kernel supports the IPV6_(RECV)PKTINFO socket option
250  * for UDP sockets.
251  *
252  * Returns:
253  *
254  * \li	#ISC_R_SUCCESS		the option is supported.
255  * \li	#ISC_R_NOTFOUND		IPv6 itself or the option is not supported.
256  * \li	#ISC_R_UNEXPECTED
257  */
258 
259 void
260 isc_net_disableipv4(void);
261 
262 void
263 isc_net_disableipv6(void);
264 
265 void
266 isc_net_enableipv4(void);
267 
268 void
269 isc_net_enableipv6(void);
270 
271 isc_result_t
272 isc_net_probeunix(void);
273 /*
274  * Returns whether UNIX domain sockets are supported.
275  */
276 
277 #define ISC_NET_DSCPRECVV4 0x01 /* Can receive sent DSCP value IPv4 */
278 #define ISC_NET_DSCPRECVV6 0x02 /* Can receive sent DSCP value IPv6 */
279 #define ISC_NET_DSCPSETV4  0x04 /* Can set DSCP on socket IPv4 */
280 #define ISC_NET_DSCPSETV6  0x08 /* Can set DSCP on socket IPv6 */
281 #define ISC_NET_DSCPPKTV4  0x10 /* Can set DSCP on per packet IPv4 */
282 #define ISC_NET_DSCPPKTV6  0x20 /* Can set DSCP on per packet IPv6 */
283 #define ISC_NET_DSCPALL	   0x3f /* All valid flags */
284 
285 unsigned int
286 isc_net_probedscp(void);
287 /*%<
288  * Probe the level of DSCP support.
289  */
290 
291 isc_result_t
292 isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high);
293 /*%<
294  * Returns system's default range of ephemeral UDP ports, if defined.
295  * If the range is not available or unknown, ISC_NET_PORTRANGELOW and
296  * ISC_NET_PORTRANGEHIGH will be returned.
297  *
298  * Requires:
299  *
300  *\li	'low' and 'high' must be non NULL.
301  *
302  * Returns:
303  *
304  *\li	*low and *high will be the ports specifying the low and high ends of
305  *	the range.
306  */
307 
308 ISC_LANG_ENDDECLS
309 
310 #endif /* ISC_NET_H */
311