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