155682Smarkm/*
2233294Sstas * Copyright (c) 1999 - 2000 Kungliga Tekniska H��gskolan
355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden).
455682Smarkm * All rights reserved.
5233294Sstas *
655682Smarkm * Redistribution and use in source and binary forms, with or without
755682Smarkm * modification, are permitted provided that the following conditions
855682Smarkm * are met:
9233294Sstas *
1055682Smarkm * 1. Redistributions of source code must retain the above copyright
1155682Smarkm *    notice, this list of conditions and the following disclaimer.
12233294Sstas *
1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1455682Smarkm *    notice, this list of conditions and the following disclaimer in the
1555682Smarkm *    documentation and/or other materials provided with the distribution.
16233294Sstas *
1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors
1855682Smarkm *    may be used to endorse or promote products derived from this software
1955682Smarkm *    without specific prior written permission.
20233294Sstas *
2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2455682Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3155682Smarkm * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#include <config.h>
3555682Smarkm
36178825Sdfr#include "roken.h"
3755682Smarkm#include <err.h>
3855682Smarkm
3955682Smarkm/*
4055682Smarkm * Set `sa' to the unitialized address of address family `af'
4155682Smarkm */
4255682Smarkm
43233294SstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
4455682Smarkmsocket_set_any (struct sockaddr *sa, int af)
4555682Smarkm{
4655682Smarkm    switch (af) {
4755682Smarkm    case AF_INET : {
48178825Sdfr	struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
4955682Smarkm
50178825Sdfr	memset (sin4, 0, sizeof(*sin4));
51178825Sdfr	sin4->sin_family = AF_INET;
52178825Sdfr	sin4->sin_port   = 0;
53178825Sdfr	sin4->sin_addr.s_addr = INADDR_ANY;
5455682Smarkm	break;
5555682Smarkm    }
5655682Smarkm#ifdef HAVE_IPV6
5755682Smarkm    case AF_INET6 : {
5855682Smarkm	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
5955682Smarkm
6055682Smarkm	memset (sin6, 0, sizeof(*sin6));
6155682Smarkm	sin6->sin6_family = AF_INET6;
6255682Smarkm	sin6->sin6_port   = 0;
6355682Smarkm	sin6->sin6_addr   = in6addr_any;
6455682Smarkm	break;
6555682Smarkm    }
6655682Smarkm#endif
6755682Smarkm    default :
6855682Smarkm	errx (1, "unknown address family %d", sa->sa_family);
6955682Smarkm	break;
7055682Smarkm    }
7155682Smarkm}
7255682Smarkm
7355682Smarkm/*
7455682Smarkm * set `sa' to (`ptr', `port')
7555682Smarkm */
7655682Smarkm
77233294SstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
7855682Smarkmsocket_set_address_and_port (struct sockaddr *sa, const void *ptr, int port)
7955682Smarkm{
8055682Smarkm    switch (sa->sa_family) {
8155682Smarkm    case AF_INET : {
82178825Sdfr	struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
8355682Smarkm
84178825Sdfr	memset (sin4, 0, sizeof(*sin4));
85178825Sdfr	sin4->sin_family = AF_INET;
86178825Sdfr	sin4->sin_port   = port;
87178825Sdfr	memcpy (&sin4->sin_addr, ptr, sizeof(struct in_addr));
8855682Smarkm	break;
8955682Smarkm    }
9055682Smarkm#ifdef HAVE_IPV6
9155682Smarkm    case AF_INET6 : {
9255682Smarkm	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
9355682Smarkm
9455682Smarkm	memset (sin6, 0, sizeof(*sin6));
9555682Smarkm	sin6->sin6_family = AF_INET6;
9655682Smarkm	sin6->sin6_port   = port;
9755682Smarkm	memcpy (&sin6->sin6_addr, ptr, sizeof(struct in6_addr));
9855682Smarkm	break;
9955682Smarkm    }
10055682Smarkm#endif
10155682Smarkm    default :
10255682Smarkm	errx (1, "unknown address family %d", sa->sa_family);
10355682Smarkm	break;
10455682Smarkm    }
10555682Smarkm}
10655682Smarkm
10755682Smarkm/*
10855682Smarkm * Return the size of an address of the type in `sa'
10955682Smarkm */
11055682Smarkm
111233294SstasROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL
11255682Smarkmsocket_addr_size (const struct sockaddr *sa)
11355682Smarkm{
11455682Smarkm    switch (sa->sa_family) {
11555682Smarkm    case AF_INET :
11655682Smarkm	return sizeof(struct in_addr);
11755682Smarkm#ifdef HAVE_IPV6
11855682Smarkm    case AF_INET6 :
11955682Smarkm	return sizeof(struct in6_addr);
12055682Smarkm#endif
12155682Smarkm    default :
122233294Sstas	return 0;
12355682Smarkm    }
12455682Smarkm}
12555682Smarkm
12655682Smarkm/*
12755682Smarkm * Return the size of a `struct sockaddr' in `sa'.
12855682Smarkm */
12955682Smarkm
130233294SstasROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL
13155682Smarkmsocket_sockaddr_size (const struct sockaddr *sa)
13255682Smarkm{
13355682Smarkm    switch (sa->sa_family) {
13455682Smarkm    case AF_INET :
13555682Smarkm	return sizeof(struct sockaddr_in);
13655682Smarkm#ifdef HAVE_IPV6
13755682Smarkm    case AF_INET6 :
13855682Smarkm	return sizeof(struct sockaddr_in6);
13955682Smarkm#endif
140233294Sstas    default:
141233294Sstas	return 0;
14255682Smarkm    }
14355682Smarkm}
14455682Smarkm
14555682Smarkm/*
14655682Smarkm * Return the binary address of `sa'.
14755682Smarkm */
14855682Smarkm
149233294SstasROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL
150233294Sstassocket_get_address (const struct sockaddr *sa)
15155682Smarkm{
15255682Smarkm    switch (sa->sa_family) {
15355682Smarkm    case AF_INET : {
154233294Sstas	const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;
155233294Sstas	return rk_UNCONST(&sin4->sin_addr);
15655682Smarkm    }
15755682Smarkm#ifdef HAVE_IPV6
15855682Smarkm    case AF_INET6 : {
159233294Sstas	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
160233294Sstas	return rk_UNCONST(&sin6->sin6_addr);
16155682Smarkm    }
16255682Smarkm#endif
163233294Sstas    default:
164233294Sstas	return NULL;
16555682Smarkm    }
16655682Smarkm}
16755682Smarkm
16855682Smarkm/*
16955682Smarkm * Return the port number from `sa'.
17055682Smarkm */
17155682Smarkm
172233294SstasROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
17355682Smarkmsocket_get_port (const struct sockaddr *sa)
17455682Smarkm{
17555682Smarkm    switch (sa->sa_family) {
17655682Smarkm    case AF_INET : {
177178825Sdfr	const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;
178178825Sdfr	return sin4->sin_port;
17955682Smarkm    }
18055682Smarkm#ifdef HAVE_IPV6
18155682Smarkm    case AF_INET6 : {
18255682Smarkm	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
18355682Smarkm	return sin6->sin6_port;
18455682Smarkm    }
18555682Smarkm#endif
18655682Smarkm    default :
187233294Sstas	return 0;
18855682Smarkm    }
18955682Smarkm}
19055682Smarkm
19155682Smarkm/*
19255682Smarkm * Set the port in `sa' to `port'.
19355682Smarkm */
19455682Smarkm
195233294SstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
19655682Smarkmsocket_set_port (struct sockaddr *sa, int port)
19755682Smarkm{
19855682Smarkm    switch (sa->sa_family) {
19955682Smarkm    case AF_INET : {
200178825Sdfr	struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
201178825Sdfr	sin4->sin_port = port;
20255682Smarkm	break;
20355682Smarkm    }
20455682Smarkm#ifdef HAVE_IPV6
20555682Smarkm    case AF_INET6 : {
20655682Smarkm	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
20755682Smarkm	sin6->sin6_port = port;
20855682Smarkm	break;
20955682Smarkm    }
21055682Smarkm#endif
21155682Smarkm    default :
21255682Smarkm	errx (1, "unknown address family %d", sa->sa_family);
21355682Smarkm	break;
21455682Smarkm    }
21555682Smarkm}
21655682Smarkm
21755682Smarkm/*
21890926Snectar * Set the range of ports to use when binding with port = 0.
21990926Snectar */
220233294SstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
221233294Sstassocket_set_portrange (rk_socket_t sock, int restr, int af)
22290926Snectar{
22390926Snectar#if defined(IP_PORTRANGE)
22490926Snectar	if (af == AF_INET) {
22590926Snectar		int on = restr ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
226233294Sstas		setsockopt (sock, IPPROTO_IP, IP_PORTRANGE, &on, sizeof(on));
22790926Snectar	}
22890926Snectar#endif
22990926Snectar#if defined(IPV6_PORTRANGE)
23090926Snectar	if (af == AF_INET6) {
231233294Sstas		int on = restr ? IPV6_PORTRANGE_HIGH : IPV6_PORTRANGE_DEFAULT;
232233294Sstas		setsockopt (sock, IPPROTO_IPV6, IPV6_PORTRANGE, &on, sizeof(on));
23390926Snectar	}
23490926Snectar#endif
23590926Snectar}
236233294Sstas
23790926Snectar/*
23855682Smarkm * Enable debug on `sock'.
23955682Smarkm */
24055682Smarkm
241233294SstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
242233294Sstassocket_set_debug (rk_socket_t sock)
24355682Smarkm{
24472445Sassar#if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT)
24555682Smarkm    int on = 1;
246233294Sstas    setsockopt (sock, SOL_SOCKET, SO_DEBUG, (void *) &on, sizeof (on));
24755682Smarkm#endif
24855682Smarkm}
24955682Smarkm
25055682Smarkm/*
25155682Smarkm * Set the type-of-service of `sock' to `tos'.
25255682Smarkm */
25355682Smarkm
254233294SstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
255233294Sstassocket_set_tos (rk_socket_t sock, int tos)
25655682Smarkm{
25755682Smarkm#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
258233294Sstas    setsockopt (sock, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(int));
25955682Smarkm#endif
26055682Smarkm}
26155682Smarkm
26255682Smarkm/*
26355682Smarkm * set the reuse of addresses on `sock' to `val'.
26455682Smarkm */
26555682Smarkm
266233294SstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
267233294Sstassocket_set_reuseaddr (rk_socket_t sock, int val)
26855682Smarkm{
26955682Smarkm#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT)
270233294Sstas    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(val));
27155682Smarkm#endif
27255682Smarkm}
273178825Sdfr
274178825Sdfr/*
275178825Sdfr * Set the that the `sock' should bind to only IPv6 addresses.
276178825Sdfr */
277178825Sdfr
278233294SstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
279233294Sstassocket_set_ipv6only (rk_socket_t sock, int val)
280178825Sdfr{
281178825Sdfr#if defined(IPV6_V6ONLY) && defined(HAVE_SETSOCKOPT)
282178825Sdfr    setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&val, sizeof(val));
283178825Sdfr#endif
284178825Sdfr}
285233294Sstas
286233294Sstas/**
287233294Sstas * Create a file descriptor from a socket
288233294Sstas *
289233294Sstas * While the socket handle in \a sock can be used with WinSock
290233294Sstas * functions after calling socket_to_fd(), it should not be closed
291233294Sstas * with rk_closesocket().  The socket will be closed when the associated
292233294Sstas * file descriptor is closed.
293233294Sstas */
294233294SstasROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
295233294Sstassocket_to_fd(rk_socket_t sock, int flags)
296233294Sstas{
297233294Sstas#ifndef _WIN32
298233294Sstas    return sock;
299233294Sstas#else
300233294Sstas    return _open_osfhandle((intptr_t) sock, flags);
301233294Sstas#endif
302233294Sstas}
303233294Sstas
304233294Sstas#ifdef HAVE_WINSOCK
305233294SstasROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
306233294Sstasrk_SOCK_IOCTL(SOCKET s, long cmd, int * argp) {
307233294Sstas    u_long ul = (argp)? *argp : 0;
308233294Sstas    int rv;
309233294Sstas
310233294Sstas    rv = ioctlsocket(s, cmd, &ul);
311233294Sstas    if (argp)
312233294Sstas	*argp = (int) ul;
313233294Sstas    return rv;
314233294Sstas}
315233294Sstas#endif
316233294Sstas
317233294Sstas#ifndef HEIMDAL_SMALLER
318233294Sstas#undef socket
319233294Sstas
320233294Sstasint rk_socket(int, int, int);
321233294Sstas
322233294Sstasint
323233294Sstasrk_socket(int domain, int type, int protocol)
324233294Sstas{
325233294Sstas    int s;
326233294Sstas    s = socket (domain, type, protocol);
327233294Sstas#ifdef SOCK_CLOEXEC
328233294Sstas    if ((SOCK_CLOEXEC & type) && s < 0 && errno == EINVAL) {
329233294Sstas	type &= ~SOCK_CLOEXEC;
330233294Sstas	s = socket (domain, type, protocol);
331233294Sstas    }
332233294Sstas#endif
333233294Sstas    return s;
334233294Sstas}
335233294Sstas
336233294Sstas#endif /* HEIMDAL_SMALLER */
337