1160814Ssimon/*
2160814Ssimon * Copyright (c) 1999 - 2000 Kungliga Tekniska H��gskolan
3160814Ssimon * (Royal Institute of Technology, Stockholm, Sweden).
4160814Ssimon * All rights reserved.
5160814Ssimon *
6160814Ssimon * Redistribution and use in source and binary forms, with or without
7160814Ssimon * modification, are permitted provided that the following conditions
8160814Ssimon * are met:
9160814Ssimon *
10280304Sjkim * 1. Redistributions of source code must retain the above copyright
11160814Ssimon *    notice, this list of conditions and the following disclaimer.
12160814Ssimon *
13160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright
14160814Ssimon *    notice, this list of conditions and the following disclaimer in the
15160814Ssimon *    documentation and/or other materials provided with the distribution.
16160814Ssimon *
17160814Ssimon * 3. Neither the name of the Institute nor the names of its contributors
18160814Ssimon *    may be used to endorse or promote products derived from this software
19160814Ssimon *    without specific prior written permission.
20160814Ssimon *
21160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22160814Ssimon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24160814Ssimon * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25160814Ssimon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26160814Ssimon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27160814Ssimon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29160814Ssimon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30160814Ssimon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31160814Ssimon * SUCH DAMAGE.
32160814Ssimon */
33160814Ssimon
34160814Ssimon#include <config.h>
35160814Ssimon
36160814Ssimon#include "roken.h"
37160814Ssimon#include <err.h>
38160814Ssimon
39160814Ssimon/*
40160814Ssimon * Set `sa' to the unitialized address of address family `af'
41160814Ssimon */
42160814Ssimon
43160814SsimonROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
44160814Ssimonsocket_set_any (struct sockaddr *sa, int af)
45160814Ssimon{
46160814Ssimon    switch (af) {
47160814Ssimon    case AF_INET : {
48160814Ssimon	struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
49160814Ssimon
50160814Ssimon	memset (sin4, 0, sizeof(*sin4));
51160814Ssimon	sin4->sin_family = AF_INET;
52160814Ssimon	sin4->sin_port   = 0;
53160814Ssimon	sin4->sin_addr.s_addr = INADDR_ANY;
54160814Ssimon	break;
55160814Ssimon    }
56160814Ssimon#ifdef HAVE_IPV6
57160814Ssimon    case AF_INET6 : {
58160814Ssimon	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
59280304Sjkim
60280304Sjkim	memset (sin6, 0, sizeof(*sin6));
61160814Ssimon	sin6->sin6_family = AF_INET6;
62280304Sjkim	sin6->sin6_port   = 0;
63280304Sjkim	sin6->sin6_addr   = in6addr_any;
64280304Sjkim	break;
65280304Sjkim    }
66160814Ssimon#endif
67280304Sjkim    default :
68280304Sjkim	errx (1, "unknown address family %d", sa->sa_family);
69280304Sjkim	break;
70160814Ssimon    }
71280304Sjkim}
72280304Sjkim
73160814Ssimon/*
74280304Sjkim * set `sa' to (`ptr', `port')
75280304Sjkim */
76280304Sjkim
77280304SjkimROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
78160814Ssimonsocket_set_address_and_port (struct sockaddr *sa, const void *ptr, int port)
79280304Sjkim{
80160814Ssimon    switch (sa->sa_family) {
81280304Sjkim    case AF_INET : {
82160814Ssimon	struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
83280304Sjkim
84160814Ssimon	memset (sin4, 0, sizeof(*sin4));
85160814Ssimon	sin4->sin_family = AF_INET;
86160814Ssimon	sin4->sin_port   = port;
87280304Sjkim	memcpy (&sin4->sin_addr, ptr, sizeof(struct in_addr));
88280304Sjkim	break;
89280304Sjkim    }
90280304Sjkim#ifdef HAVE_IPV6
91280304Sjkim    case AF_INET6 : {
92160814Ssimon	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
93280304Sjkim
94280304Sjkim	memset (sin6, 0, sizeof(*sin6));
95280304Sjkim	sin6->sin6_family = AF_INET6;
96280304Sjkim	sin6->sin6_port   = port;
97280304Sjkim	memcpy (&sin6->sin6_addr, ptr, sizeof(struct in6_addr));
98160814Ssimon	break;
99280304Sjkim    }
100280304Sjkim#endif
101280304Sjkim    default :
102280304Sjkim	errx (1, "unknown address family %d", sa->sa_family);
103160814Ssimon	break;
104280304Sjkim    }
105280304Sjkim}
106280304Sjkim
107280304Sjkim/*
108280304Sjkim * Return the size of an address of the type in `sa'
109280304Sjkim */
110280304Sjkim
111160814SsimonROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL
112280304Sjkimsocket_addr_size (const struct sockaddr *sa)
113280304Sjkim{
114280304Sjkim    switch (sa->sa_family) {
115280304Sjkim    case AF_INET :
116280304Sjkim	return sizeof(struct in_addr);
117280304Sjkim#ifdef HAVE_IPV6
118160814Ssimon    case AF_INET6 :
119280304Sjkim	return sizeof(struct in6_addr);
120280304Sjkim#endif
121280304Sjkim    default :
122160814Ssimon	return 0;
123160814Ssimon    }
124160814Ssimon}
125160814Ssimon
126160814Ssimon/*
127160814Ssimon * Return the size of a `struct sockaddr' in `sa'.
128280304Sjkim */
129280304Sjkim
130280304SjkimROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL
131280304Sjkimsocket_sockaddr_size (const struct sockaddr *sa)
132280304Sjkim{
133160814Ssimon    switch (sa->sa_family) {
134280304Sjkim    case AF_INET :
135280304Sjkim	return sizeof(struct sockaddr_in);
136280304Sjkim#ifdef HAVE_IPV6
137160814Ssimon    case AF_INET6 :
138280304Sjkim	return sizeof(struct sockaddr_in6);
139280304Sjkim#endif
140160814Ssimon    default:
141280304Sjkim	return 0;
142280304Sjkim    }
143280304Sjkim}
144280304Sjkim
145160814Ssimon/*
146280304Sjkim * Return the binary address of `sa'.
147280304Sjkim */
148280304Sjkim
149280304SjkimROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL
150280304Sjkimsocket_get_address (const struct sockaddr *sa)
151280304Sjkim{
152280304Sjkim    switch (sa->sa_family) {
153280304Sjkim    case AF_INET : {
154280304Sjkim	const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;
155280304Sjkim	return rk_UNCONST(&sin4->sin_addr);
156280304Sjkim    }
157280304Sjkim#ifdef HAVE_IPV6
158280304Sjkim    case AF_INET6 : {
159160814Ssimon	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
160280304Sjkim	return rk_UNCONST(&sin6->sin6_addr);
161160814Ssimon    }
162280304Sjkim#endif
163280304Sjkim    default:
164160814Ssimon	return NULL;
165160814Ssimon    }
166280304Sjkim}
167280304Sjkim
168280304Sjkim/*
169280304Sjkim * Return the port number from `sa'.
170160814Ssimon */
171280304Sjkim
172280304SjkimROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
173160814Ssimonsocket_get_port (const struct sockaddr *sa)
174280304Sjkim{
175160814Ssimon    switch (sa->sa_family) {
176280304Sjkim    case AF_INET : {
177160814Ssimon	const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;
178280304Sjkim	return sin4->sin_port;
179280304Sjkim    }
180#ifdef HAVE_IPV6
181    case AF_INET6 : {
182	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
183	return sin6->sin6_port;
184    }
185#endif
186    default :
187	return 0;
188    }
189}
190
191/*
192 * Set the port in `sa' to `port'.
193 */
194
195ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
196socket_set_port (struct sockaddr *sa, int port)
197{
198    switch (sa->sa_family) {
199    case AF_INET : {
200	struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
201	sin4->sin_port = port;
202	break;
203    }
204#ifdef HAVE_IPV6
205    case AF_INET6 : {
206	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
207	sin6->sin6_port = port;
208	break;
209    }
210#endif
211    default :
212	errx (1, "unknown address family %d", sa->sa_family);
213	break;
214    }
215}
216
217/*
218 * Set the range of ports to use when binding with port = 0.
219 */
220ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
221socket_set_portrange (rk_socket_t sock, int restr, int af)
222{
223#if defined(IP_PORTRANGE)
224	if (af == AF_INET) {
225		int on = restr ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
226		setsockopt (sock, IPPROTO_IP, IP_PORTRANGE, &on, sizeof(on));
227	}
228#endif
229#if defined(IPV6_PORTRANGE)
230	if (af == AF_INET6) {
231		int on = restr ? IPV6_PORTRANGE_HIGH : IPV6_PORTRANGE_DEFAULT;
232		setsockopt (sock, IPPROTO_IPV6, IPV6_PORTRANGE, &on, sizeof(on));
233	}
234#endif
235}
236
237/*
238 * Enable debug on `sock'.
239 */
240
241ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
242socket_set_debug (rk_socket_t sock)
243{
244#if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT)
245    int on = 1;
246    setsockopt (sock, SOL_SOCKET, SO_DEBUG, (void *) &on, sizeof (on));
247#endif
248}
249
250/*
251 * Set the type-of-service of `sock' to `tos'.
252 */
253
254ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
255socket_set_tos (rk_socket_t sock, int tos)
256{
257#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
258    setsockopt (sock, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(int));
259#endif
260}
261
262/*
263 * set the reuse of addresses on `sock' to `val'.
264 */
265
266ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
267socket_set_reuseaddr (rk_socket_t sock, int val)
268{
269#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT)
270    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(val));
271#endif
272}
273
274/*
275 * Set the that the `sock' should bind to only IPv6 addresses.
276 */
277
278ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
279socket_set_ipv6only (rk_socket_t sock, int val)
280{
281#if defined(IPV6_V6ONLY) && defined(HAVE_SETSOCKOPT)
282    setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&val, sizeof(val));
283#endif
284}
285
286/**
287 * Create a file descriptor from a socket
288 *
289 * While the socket handle in \a sock can be used with WinSock
290 * functions after calling socket_to_fd(), it should not be closed
291 * with rk_closesocket().  The socket will be closed when the associated
292 * file descriptor is closed.
293 */
294ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
295socket_to_fd(rk_socket_t sock, int flags)
296{
297#ifndef _WIN32
298    return sock;
299#else
300    return _open_osfhandle((intptr_t) sock, flags);
301#endif
302}
303
304#ifdef HAVE_WINSOCK
305ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
306rk_SOCK_IOCTL(SOCKET s, long cmd, int * argp) {
307    u_long ul = (argp)? *argp : 0;
308    int rv;
309
310    rv = ioctlsocket(s, cmd, &ul);
311    if (argp)
312	*argp = (int) ul;
313    return rv;
314}
315#endif
316
317#ifndef HEIMDAL_SMALLER
318#undef socket
319
320int rk_socket(int, int, int);
321
322int
323rk_socket(int domain, int type, int protocol)
324{
325    int s;
326    s = socket (domain, type, protocol);
327#ifdef SOCK_CLOEXEC
328    if ((SOCK_CLOEXEC & type) && s < 0 && errno == EINVAL) {
329	type &= ~SOCK_CLOEXEC;
330	s = socket (domain, type, protocol);
331    }
332#endif
333    return s;
334}
335
336#endif /* HEIMDAL_SMALLER */
337