xref: /freebsd/crypto/heimdal/lib/roken/socket.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
1b528cefcSMark Murray /*
2*ae771770SStanislav Sedov  * Copyright (c) 1999 - 2000 Kungliga Tekniska Högskolan
3b528cefcSMark Murray  * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray  * All rights reserved.
5b528cefcSMark Murray  *
6b528cefcSMark Murray  * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray  * modification, are permitted provided that the following conditions
8b528cefcSMark Murray  * are met:
9b528cefcSMark Murray  *
10b528cefcSMark Murray  * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray  *
13b528cefcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray  *    documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray  *
17b528cefcSMark Murray  * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray  *    may be used to endorse or promote products derived from this software
19b528cefcSMark Murray  *    without specific prior written permission.
20b528cefcSMark Murray  *
21b528cefcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray  * SUCH DAMAGE.
32b528cefcSMark Murray  */
33b528cefcSMark Murray 
34b528cefcSMark Murray #include <config.h>
35b528cefcSMark Murray 
36c19800e8SDoug Rabson #include "roken.h"
37b528cefcSMark Murray #include <err.h>
38b528cefcSMark Murray 
39b528cefcSMark Murray /*
40b528cefcSMark Murray  * Set `sa' to the unitialized address of address family `af'
41b528cefcSMark Murray  */
42b528cefcSMark Murray 
43*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
socket_set_any(struct sockaddr * sa,int af)44b528cefcSMark Murray socket_set_any (struct sockaddr *sa, int af)
45b528cefcSMark Murray {
46b528cefcSMark Murray     switch (af) {
47b528cefcSMark Murray     case AF_INET : {
48c19800e8SDoug Rabson 	struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
49b528cefcSMark Murray 
50c19800e8SDoug Rabson 	memset (sin4, 0, sizeof(*sin4));
51c19800e8SDoug Rabson 	sin4->sin_family = AF_INET;
52c19800e8SDoug Rabson 	sin4->sin_port   = 0;
53c19800e8SDoug Rabson 	sin4->sin_addr.s_addr = INADDR_ANY;
54b528cefcSMark Murray 	break;
55b528cefcSMark Murray     }
56b528cefcSMark Murray #ifdef HAVE_IPV6
57b528cefcSMark Murray     case AF_INET6 : {
58b528cefcSMark Murray 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
59b528cefcSMark Murray 
60b528cefcSMark Murray 	memset (sin6, 0, sizeof(*sin6));
61b528cefcSMark Murray 	sin6->sin6_family = AF_INET6;
62b528cefcSMark Murray 	sin6->sin6_port   = 0;
63b528cefcSMark Murray 	sin6->sin6_addr   = in6addr_any;
64b528cefcSMark Murray 	break;
65b528cefcSMark Murray     }
66b528cefcSMark Murray #endif
67b528cefcSMark Murray     default :
68b528cefcSMark Murray 	errx (1, "unknown address family %d", sa->sa_family);
69b528cefcSMark Murray 	break;
70b528cefcSMark Murray     }
71b528cefcSMark Murray }
72b528cefcSMark Murray 
73b528cefcSMark Murray /*
74b528cefcSMark Murray  * set `sa' to (`ptr', `port')
75b528cefcSMark Murray  */
76b528cefcSMark Murray 
77*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
socket_set_address_and_port(struct sockaddr * sa,const void * ptr,int port)78b528cefcSMark Murray socket_set_address_and_port (struct sockaddr *sa, const void *ptr, int port)
79b528cefcSMark Murray {
80b528cefcSMark Murray     switch (sa->sa_family) {
81b528cefcSMark Murray     case AF_INET : {
82c19800e8SDoug Rabson 	struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
83b528cefcSMark Murray 
84c19800e8SDoug Rabson 	memset (sin4, 0, sizeof(*sin4));
85c19800e8SDoug Rabson 	sin4->sin_family = AF_INET;
86c19800e8SDoug Rabson 	sin4->sin_port   = port;
87c19800e8SDoug Rabson 	memcpy (&sin4->sin_addr, ptr, sizeof(struct in_addr));
88b528cefcSMark Murray 	break;
89b528cefcSMark Murray     }
90b528cefcSMark Murray #ifdef HAVE_IPV6
91b528cefcSMark Murray     case AF_INET6 : {
92b528cefcSMark Murray 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
93b528cefcSMark Murray 
94b528cefcSMark Murray 	memset (sin6, 0, sizeof(*sin6));
95b528cefcSMark Murray 	sin6->sin6_family = AF_INET6;
96b528cefcSMark Murray 	sin6->sin6_port   = port;
97b528cefcSMark Murray 	memcpy (&sin6->sin6_addr, ptr, sizeof(struct in6_addr));
98b528cefcSMark Murray 	break;
99b528cefcSMark Murray     }
100b528cefcSMark Murray #endif
101b528cefcSMark Murray     default :
102b528cefcSMark Murray 	errx (1, "unknown address family %d", sa->sa_family);
103b528cefcSMark Murray 	break;
104b528cefcSMark Murray     }
105b528cefcSMark Murray }
106b528cefcSMark Murray 
107b528cefcSMark Murray /*
108b528cefcSMark Murray  * Return the size of an address of the type in `sa'
109b528cefcSMark Murray  */
110b528cefcSMark Murray 
111*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL
socket_addr_size(const struct sockaddr * sa)112b528cefcSMark Murray socket_addr_size (const struct sockaddr *sa)
113b528cefcSMark Murray {
114b528cefcSMark Murray     switch (sa->sa_family) {
115b528cefcSMark Murray     case AF_INET :
116b528cefcSMark Murray 	return sizeof(struct in_addr);
117b528cefcSMark Murray #ifdef HAVE_IPV6
118b528cefcSMark Murray     case AF_INET6 :
119b528cefcSMark Murray 	return sizeof(struct in6_addr);
120b528cefcSMark Murray #endif
121b528cefcSMark Murray     default :
122*ae771770SStanislav Sedov 	return 0;
123b528cefcSMark Murray     }
124b528cefcSMark Murray }
125b528cefcSMark Murray 
126b528cefcSMark Murray /*
127b528cefcSMark Murray  * Return the size of a `struct sockaddr' in `sa'.
128b528cefcSMark Murray  */
129b528cefcSMark Murray 
130*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL
socket_sockaddr_size(const struct sockaddr * sa)131b528cefcSMark Murray socket_sockaddr_size (const struct sockaddr *sa)
132b528cefcSMark Murray {
133b528cefcSMark Murray     switch (sa->sa_family) {
134b528cefcSMark Murray     case AF_INET :
135b528cefcSMark Murray 	return sizeof(struct sockaddr_in);
136b528cefcSMark Murray #ifdef HAVE_IPV6
137b528cefcSMark Murray     case AF_INET6 :
138b528cefcSMark Murray 	return sizeof(struct sockaddr_in6);
139b528cefcSMark Murray #endif
140b528cefcSMark Murray     default:
141*ae771770SStanislav Sedov 	return 0;
142b528cefcSMark Murray     }
143b528cefcSMark Murray }
144b528cefcSMark Murray 
145b528cefcSMark Murray /*
146b528cefcSMark Murray  * Return the binary address of `sa'.
147b528cefcSMark Murray  */
148b528cefcSMark Murray 
149*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL
socket_get_address(const struct sockaddr * sa)150*ae771770SStanislav Sedov socket_get_address (const struct sockaddr *sa)
151b528cefcSMark Murray {
152b528cefcSMark Murray     switch (sa->sa_family) {
153b528cefcSMark Murray     case AF_INET : {
154*ae771770SStanislav Sedov 	const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;
155*ae771770SStanislav Sedov 	return rk_UNCONST(&sin4->sin_addr);
156b528cefcSMark Murray     }
157b528cefcSMark Murray #ifdef HAVE_IPV6
158b528cefcSMark Murray     case AF_INET6 : {
159*ae771770SStanislav Sedov 	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
160*ae771770SStanislav Sedov 	return rk_UNCONST(&sin6->sin6_addr);
161b528cefcSMark Murray     }
162b528cefcSMark Murray #endif
163b528cefcSMark Murray     default:
164*ae771770SStanislav Sedov 	return NULL;
165b528cefcSMark Murray     }
166b528cefcSMark Murray }
167b528cefcSMark Murray 
168b528cefcSMark Murray /*
169b528cefcSMark Murray  * Return the port number from `sa'.
170b528cefcSMark Murray  */
171b528cefcSMark Murray 
172*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
socket_get_port(const struct sockaddr * sa)173b528cefcSMark Murray socket_get_port (const struct sockaddr *sa)
174b528cefcSMark Murray {
175b528cefcSMark Murray     switch (sa->sa_family) {
176b528cefcSMark Murray     case AF_INET : {
177c19800e8SDoug Rabson 	const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;
178c19800e8SDoug Rabson 	return sin4->sin_port;
179b528cefcSMark Murray     }
180b528cefcSMark Murray #ifdef HAVE_IPV6
181b528cefcSMark Murray     case AF_INET6 : {
182b528cefcSMark Murray 	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
183b528cefcSMark Murray 	return sin6->sin6_port;
184b528cefcSMark Murray     }
185b528cefcSMark Murray #endif
186b528cefcSMark Murray     default :
187*ae771770SStanislav Sedov 	return 0;
188b528cefcSMark Murray     }
189b528cefcSMark Murray }
190b528cefcSMark Murray 
191b528cefcSMark Murray /*
192b528cefcSMark Murray  * Set the port in `sa' to `port'.
193b528cefcSMark Murray  */
194b528cefcSMark Murray 
195*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
socket_set_port(struct sockaddr * sa,int port)196b528cefcSMark Murray socket_set_port (struct sockaddr *sa, int port)
197b528cefcSMark Murray {
198b528cefcSMark Murray     switch (sa->sa_family) {
199b528cefcSMark Murray     case AF_INET : {
200c19800e8SDoug Rabson 	struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
201c19800e8SDoug Rabson 	sin4->sin_port = port;
202b528cefcSMark Murray 	break;
203b528cefcSMark Murray     }
204b528cefcSMark Murray #ifdef HAVE_IPV6
205b528cefcSMark Murray     case AF_INET6 : {
206b528cefcSMark Murray 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
207b528cefcSMark Murray 	sin6->sin6_port = port;
208b528cefcSMark Murray 	break;
209b528cefcSMark Murray     }
210b528cefcSMark Murray #endif
211b528cefcSMark Murray     default :
212b528cefcSMark Murray 	errx (1, "unknown address family %d", sa->sa_family);
213b528cefcSMark Murray 	break;
214b528cefcSMark Murray     }
215b528cefcSMark Murray }
216b528cefcSMark Murray 
217b528cefcSMark Murray /*
2184137ff4cSJacques Vidrine  * Set the range of ports to use when binding with port = 0.
2194137ff4cSJacques Vidrine  */
220*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
socket_set_portrange(rk_socket_t sock,int restr,int af)221*ae771770SStanislav Sedov socket_set_portrange (rk_socket_t sock, int restr, int af)
2224137ff4cSJacques Vidrine {
2234137ff4cSJacques Vidrine #if defined(IP_PORTRANGE)
2244137ff4cSJacques Vidrine 	if (af == AF_INET) {
2254137ff4cSJacques Vidrine 		int on = restr ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
226*ae771770SStanislav Sedov 		setsockopt (sock, IPPROTO_IP, IP_PORTRANGE, &on, sizeof(on));
2274137ff4cSJacques Vidrine 	}
2284137ff4cSJacques Vidrine #endif
2294137ff4cSJacques Vidrine #if defined(IPV6_PORTRANGE)
2304137ff4cSJacques Vidrine 	if (af == AF_INET6) {
231*ae771770SStanislav Sedov 		int on = restr ? IPV6_PORTRANGE_HIGH : IPV6_PORTRANGE_DEFAULT;
232*ae771770SStanislav Sedov 		setsockopt (sock, IPPROTO_IPV6, IPV6_PORTRANGE, &on, sizeof(on));
2334137ff4cSJacques Vidrine 	}
2344137ff4cSJacques Vidrine #endif
2354137ff4cSJacques Vidrine }
2364137ff4cSJacques Vidrine 
2374137ff4cSJacques Vidrine /*
238b528cefcSMark Murray  * Enable debug on `sock'.
239b528cefcSMark Murray  */
240b528cefcSMark Murray 
241*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
socket_set_debug(rk_socket_t sock)242*ae771770SStanislav Sedov socket_set_debug (rk_socket_t sock)
243b528cefcSMark Murray {
2445e9cd1aeSAssar Westerlund #if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT)
245b528cefcSMark Murray     int on = 1;
246*ae771770SStanislav Sedov     setsockopt (sock, SOL_SOCKET, SO_DEBUG, (void *) &on, sizeof (on));
247b528cefcSMark Murray #endif
248b528cefcSMark Murray }
249b528cefcSMark Murray 
250b528cefcSMark Murray /*
251b528cefcSMark Murray  * Set the type-of-service of `sock' to `tos'.
252b528cefcSMark Murray  */
253b528cefcSMark Murray 
254*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
socket_set_tos(rk_socket_t sock,int tos)255*ae771770SStanislav Sedov socket_set_tos (rk_socket_t sock, int tos)
256b528cefcSMark Murray {
257b528cefcSMark Murray #if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
258*ae771770SStanislav Sedov     setsockopt (sock, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(int));
259b528cefcSMark Murray #endif
260b528cefcSMark Murray }
261b528cefcSMark Murray 
262b528cefcSMark Murray /*
263b528cefcSMark Murray  * set the reuse of addresses on `sock' to `val'.
264b528cefcSMark Murray  */
265b528cefcSMark Murray 
266*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
socket_set_reuseaddr(rk_socket_t sock,int val)267*ae771770SStanislav Sedov socket_set_reuseaddr (rk_socket_t sock, int val)
268b528cefcSMark Murray {
269b528cefcSMark Murray #if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT)
270*ae771770SStanislav Sedov     setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(val));
271b528cefcSMark Murray #endif
272b528cefcSMark Murray }
273c19800e8SDoug Rabson 
274c19800e8SDoug Rabson /*
275c19800e8SDoug Rabson  * Set the that the `sock' should bind to only IPv6 addresses.
276c19800e8SDoug Rabson  */
277c19800e8SDoug Rabson 
278*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
socket_set_ipv6only(rk_socket_t sock,int val)279*ae771770SStanislav Sedov socket_set_ipv6only (rk_socket_t sock, int val)
280c19800e8SDoug Rabson {
281c19800e8SDoug Rabson #if defined(IPV6_V6ONLY) && defined(HAVE_SETSOCKOPT)
282c19800e8SDoug Rabson     setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&val, sizeof(val));
283c19800e8SDoug Rabson #endif
284c19800e8SDoug Rabson }
285*ae771770SStanislav Sedov 
286*ae771770SStanislav Sedov /**
287*ae771770SStanislav Sedov  * Create a file descriptor from a socket
288*ae771770SStanislav Sedov  *
289*ae771770SStanislav Sedov  * While the socket handle in \a sock can be used with WinSock
290*ae771770SStanislav Sedov  * functions after calling socket_to_fd(), it should not be closed
291*ae771770SStanislav Sedov  * with rk_closesocket().  The socket will be closed when the associated
292*ae771770SStanislav Sedov  * file descriptor is closed.
293*ae771770SStanislav Sedov  */
294*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
socket_to_fd(rk_socket_t sock,int flags)295*ae771770SStanislav Sedov socket_to_fd(rk_socket_t sock, int flags)
296*ae771770SStanislav Sedov {
297*ae771770SStanislav Sedov #ifndef _WIN32
298*ae771770SStanislav Sedov     return sock;
299*ae771770SStanislav Sedov #else
300*ae771770SStanislav Sedov     return _open_osfhandle((intptr_t) sock, flags);
301*ae771770SStanislav Sedov #endif
302*ae771770SStanislav Sedov }
303*ae771770SStanislav Sedov 
304*ae771770SStanislav Sedov #ifdef HAVE_WINSOCK
305*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
rk_SOCK_IOCTL(SOCKET s,long cmd,int * argp)306*ae771770SStanislav Sedov rk_SOCK_IOCTL(SOCKET s, long cmd, int * argp) {
307*ae771770SStanislav Sedov     u_long ul = (argp)? *argp : 0;
308*ae771770SStanislav Sedov     int rv;
309*ae771770SStanislav Sedov 
310*ae771770SStanislav Sedov     rv = ioctlsocket(s, cmd, &ul);
311*ae771770SStanislav Sedov     if (argp)
312*ae771770SStanislav Sedov 	*argp = (int) ul;
313*ae771770SStanislav Sedov     return rv;
314*ae771770SStanislav Sedov }
315*ae771770SStanislav Sedov #endif
316*ae771770SStanislav Sedov 
317*ae771770SStanislav Sedov #ifndef HEIMDAL_SMALLER
318*ae771770SStanislav Sedov #undef socket
319*ae771770SStanislav Sedov 
320*ae771770SStanislav Sedov int rk_socket(int, int, int);
321*ae771770SStanislav Sedov 
322*ae771770SStanislav Sedov int
rk_socket(int domain,int type,int protocol)323*ae771770SStanislav Sedov rk_socket(int domain, int type, int protocol)
324*ae771770SStanislav Sedov {
325*ae771770SStanislav Sedov     int s;
326*ae771770SStanislav Sedov     s = socket (domain, type, protocol);
327*ae771770SStanislav Sedov #ifdef SOCK_CLOEXEC
328*ae771770SStanislav Sedov     if ((SOCK_CLOEXEC & type) && s < 0 && errno == EINVAL) {
329*ae771770SStanislav Sedov 	type &= ~SOCK_CLOEXEC;
330*ae771770SStanislav Sedov 	s = socket (domain, type, protocol);
331*ae771770SStanislav Sedov     }
332*ae771770SStanislav Sedov #endif
333*ae771770SStanislav Sedov     return s;
334*ae771770SStanislav Sedov }
335*ae771770SStanislav Sedov 
336*ae771770SStanislav Sedov #endif /* HEIMDAL_SMALLER */
337