14ecbd6dmarkm/*
233f661cstas * Copyright (c) 1999 - 2000 Kungliga Tekniska H��gskolan
34ecbd6dmarkm * (Royal Institute of Technology, Stockholm, Sweden).
44ecbd6dmarkm * All rights reserved.
533f661cstas *
64ecbd6dmarkm * Redistribution and use in source and binary forms, with or without
74ecbd6dmarkm * modification, are permitted provided that the following conditions
84ecbd6dmarkm * are met:
933f661cstas *
104ecbd6dmarkm * 1. Redistributions of source code must retain the above copyright
114ecbd6dmarkm *    notice, this list of conditions and the following disclaimer.
1233f661cstas *
134ecbd6dmarkm * 2. Redistributions in binary form must reproduce the above copyright
144ecbd6dmarkm *    notice, this list of conditions and the following disclaimer in the
154ecbd6dmarkm *    documentation and/or other materials provided with the distribution.
1633f661cstas *
174ecbd6dmarkm * 3. Neither the name of the Institute nor the names of its contributors
184ecbd6dmarkm *    may be used to endorse or promote products derived from this software
194ecbd6dmarkm *    without specific prior written permission.
2033f661cstas *
214ecbd6dmarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
224ecbd6dmarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
234ecbd6dmarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
244ecbd6dmarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
254ecbd6dmarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
264ecbd6dmarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
274ecbd6dmarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
284ecbd6dmarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
294ecbd6dmarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
304ecbd6dmarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
314ecbd6dmarkm * SUCH DAMAGE.
324ecbd6dmarkm */
334ecbd6dmarkm
344ecbd6dmarkm#include <config.h>
354ecbd6dmarkm
3651b6601dfr#include "roken.h"
374ecbd6dmarkm#include <err.h>
384ecbd6dmarkm
394ecbd6dmarkm/*
404ecbd6dmarkm * Set `sa' to the unitialized address of address family `af'
414ecbd6dmarkm */
424ecbd6dmarkm
4333f661cstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
444ecbd6dmarkmsocket_set_any (struct sockaddr *sa, int af)
454ecbd6dmarkm{
464ecbd6dmarkm    switch (af) {
474ecbd6dmarkm    case AF_INET : {
4851b6601dfr	struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
494ecbd6dmarkm
5051b6601dfr	memset (sin4, 0, sizeof(*sin4));
5151b6601dfr	sin4->sin_family = AF_INET;
5251b6601dfr	sin4->sin_port   = 0;
5351b6601dfr	sin4->sin_addr.s_addr = INADDR_ANY;
544ecbd6dmarkm	break;
554ecbd6dmarkm    }
564ecbd6dmarkm#ifdef HAVE_IPV6
574ecbd6dmarkm    case AF_INET6 : {
584ecbd6dmarkm	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
594ecbd6dmarkm
604ecbd6dmarkm	memset (sin6, 0, sizeof(*sin6));
614ecbd6dmarkm	sin6->sin6_family = AF_INET6;
624ecbd6dmarkm	sin6->sin6_port   = 0;
634ecbd6dmarkm	sin6->sin6_addr   = in6addr_any;
644ecbd6dmarkm	break;
654ecbd6dmarkm    }
664ecbd6dmarkm#endif
674ecbd6dmarkm    default :
684ecbd6dmarkm	errx (1, "unknown address family %d", sa->sa_family);
694ecbd6dmarkm	break;
704ecbd6dmarkm    }
714ecbd6dmarkm}
724ecbd6dmarkm
734ecbd6dmarkm/*
744ecbd6dmarkm * set `sa' to (`ptr', `port')
754ecbd6dmarkm */
764ecbd6dmarkm
7733f661cstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
784ecbd6dmarkmsocket_set_address_and_port (struct sockaddr *sa, const void *ptr, int port)
794ecbd6dmarkm{
804ecbd6dmarkm    switch (sa->sa_family) {
814ecbd6dmarkm    case AF_INET : {
8251b6601dfr	struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
834ecbd6dmarkm
8451b6601dfr	memset (sin4, 0, sizeof(*sin4));
8551b6601dfr	sin4->sin_family = AF_INET;
8651b6601dfr	sin4->sin_port   = port;
8751b6601dfr	memcpy (&sin4->sin_addr, ptr, sizeof(struct in_addr));
884ecbd6dmarkm	break;
894ecbd6dmarkm    }
904ecbd6dmarkm#ifdef HAVE_IPV6
914ecbd6dmarkm    case AF_INET6 : {
924ecbd6dmarkm	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
934ecbd6dmarkm
944ecbd6dmarkm	memset (sin6, 0, sizeof(*sin6));
954ecbd6dmarkm	sin6->sin6_family = AF_INET6;
964ecbd6dmarkm	sin6->sin6_port   = port;
974ecbd6dmarkm	memcpy (&sin6->sin6_addr, ptr, sizeof(struct in6_addr));
984ecbd6dmarkm	break;
994ecbd6dmarkm    }
1004ecbd6dmarkm#endif
1014ecbd6dmarkm    default :
1024ecbd6dmarkm	errx (1, "unknown address family %d", sa->sa_family);
1034ecbd6dmarkm	break;
1044ecbd6dmarkm    }
1054ecbd6dmarkm}
1064ecbd6dmarkm
1074ecbd6dmarkm/*
1084ecbd6dmarkm * Return the size of an address of the type in `sa'
1094ecbd6dmarkm */
1104ecbd6dmarkm
11133f661cstasROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL
1124ecbd6dmarkmsocket_addr_size (const struct sockaddr *sa)
1134ecbd6dmarkm{
1144ecbd6dmarkm    switch (sa->sa_family) {
1154ecbd6dmarkm    case AF_INET :
1164ecbd6dmarkm	return sizeof(struct in_addr);
1174ecbd6dmarkm#ifdef HAVE_IPV6
1184ecbd6dmarkm    case AF_INET6 :
1194ecbd6dmarkm	return sizeof(struct in6_addr);
1204ecbd6dmarkm#endif
1214ecbd6dmarkm    default :
12233f661cstas	return 0;
1234ecbd6dmarkm    }
1244ecbd6dmarkm}
1254ecbd6dmarkm
1264ecbd6dmarkm/*
1274ecbd6dmarkm * Return the size of a `struct sockaddr' in `sa'.
1284ecbd6dmarkm */
1294ecbd6dmarkm
13033f661cstasROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL
1314ecbd6dmarkmsocket_sockaddr_size (const struct sockaddr *sa)
1324ecbd6dmarkm{
1334ecbd6dmarkm    switch (sa->sa_family) {
1344ecbd6dmarkm    case AF_INET :
1354ecbd6dmarkm	return sizeof(struct sockaddr_in);
1364ecbd6dmarkm#ifdef HAVE_IPV6
1374ecbd6dmarkm    case AF_INET6 :
1384ecbd6dmarkm	return sizeof(struct sockaddr_in6);
1394ecbd6dmarkm#endif
14033f661cstas    default:
14133f661cstas	return 0;
1424ecbd6dmarkm    }
1434ecbd6dmarkm}
1444ecbd6dmarkm
1454ecbd6dmarkm/*
1464ecbd6dmarkm * Return the binary address of `sa'.
1474ecbd6dmarkm */
1484ecbd6dmarkm
14933f661cstasROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL
15033f661cstassocket_get_address (const struct sockaddr *sa)
1514ecbd6dmarkm{
1524ecbd6dmarkm    switch (sa->sa_family) {
1534ecbd6dmarkm    case AF_INET : {
15433f661cstas	const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;
15533f661cstas	return rk_UNCONST(&sin4->sin_addr);
1564ecbd6dmarkm    }
1574ecbd6dmarkm#ifdef HAVE_IPV6
1584ecbd6dmarkm    case AF_INET6 : {
15933f661cstas	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
16033f661cstas	return rk_UNCONST(&sin6->sin6_addr);
1614ecbd6dmarkm    }
1624ecbd6dmarkm#endif
16333f661cstas    default:
16433f661cstas	return NULL;
1654ecbd6dmarkm    }
1664ecbd6dmarkm}
1674ecbd6dmarkm
1684ecbd6dmarkm/*
1694ecbd6dmarkm * Return the port number from `sa'.
1704ecbd6dmarkm */
1714ecbd6dmarkm
17233f661cstasROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
1734ecbd6dmarkmsocket_get_port (const struct sockaddr *sa)
1744ecbd6dmarkm{
1754ecbd6dmarkm    switch (sa->sa_family) {
1764ecbd6dmarkm    case AF_INET : {
17751b6601dfr	const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;
17851b6601dfr	return sin4->sin_port;
1794ecbd6dmarkm    }
1804ecbd6dmarkm#ifdef HAVE_IPV6
1814ecbd6dmarkm    case AF_INET6 : {
1824ecbd6dmarkm	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
1834ecbd6dmarkm	return sin6->sin6_port;
1844ecbd6dmarkm    }
1854ecbd6dmarkm#endif
1864ecbd6dmarkm    default :
18733f661cstas	return 0;
1884ecbd6dmarkm    }
1894ecbd6dmarkm}
1904ecbd6dmarkm
1914ecbd6dmarkm/*
1924ecbd6dmarkm * Set the port in `sa' to `port'.
1934ecbd6dmarkm */
1944ecbd6dmarkm
19533f661cstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
1964ecbd6dmarkmsocket_set_port (struct sockaddr *sa, int port)
1974ecbd6dmarkm{
1984ecbd6dmarkm    switch (sa->sa_family) {
1994ecbd6dmarkm    case AF_INET : {
20051b6601dfr	struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
20151b6601dfr	sin4->sin_port = port;
2024ecbd6dmarkm	break;
2034ecbd6dmarkm    }
2044ecbd6dmarkm#ifdef HAVE_IPV6
2054ecbd6dmarkm    case AF_INET6 : {
2064ecbd6dmarkm	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
2074ecbd6dmarkm	sin6->sin6_port = port;
2084ecbd6dmarkm	break;
2094ecbd6dmarkm    }
2104ecbd6dmarkm#endif
2114ecbd6dmarkm    default :
2124ecbd6dmarkm	errx (1, "unknown address family %d", sa->sa_family);
2134ecbd6dmarkm	break;
2144ecbd6dmarkm    }
2154ecbd6dmarkm}
2164ecbd6dmarkm
2174ecbd6dmarkm/*
21869a91benectar * Set the range of ports to use when binding with port = 0.
21969a91benectar */
22033f661cstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
22133f661cstassocket_set_portrange (rk_socket_t sock, int restr, int af)
22269a91benectar{
22369a91benectar#if defined(IP_PORTRANGE)
22469a91benectar	if (af == AF_INET) {
22569a91benectar		int on = restr ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
22633f661cstas		setsockopt (sock, IPPROTO_IP, IP_PORTRANGE, &on, sizeof(on));
22769a91benectar	}
22869a91benectar#endif
22969a91benectar#if defined(IPV6_PORTRANGE)
23069a91benectar	if (af == AF_INET6) {
23133f661cstas		int on = restr ? IPV6_PORTRANGE_HIGH : IPV6_PORTRANGE_DEFAULT;
23233f661cstas		setsockopt (sock, IPPROTO_IPV6, IPV6_PORTRANGE, &on, sizeof(on));
23369a91benectar	}
23469a91benectar#endif
23569a91benectar}
23633f661cstas
23769a91benectar/*
2384ecbd6dmarkm * Enable debug on `sock'.
2394ecbd6dmarkm */
2404ecbd6dmarkm
24133f661cstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
24233f661cstassocket_set_debug (rk_socket_t sock)
2434ecbd6dmarkm{
244ebfe6dcassar#if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT)
2454ecbd6dmarkm    int on = 1;
24633f661cstas    setsockopt (sock, SOL_SOCKET, SO_DEBUG, (void *) &on, sizeof (on));
2474ecbd6dmarkm#endif
2484ecbd6dmarkm}
2494ecbd6dmarkm
2504ecbd6dmarkm/*
2514ecbd6dmarkm * Set the type-of-service of `sock' to `tos'.
2524ecbd6dmarkm */
2534ecbd6dmarkm
25433f661cstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
25533f661cstassocket_set_tos (rk_socket_t sock, int tos)
2564ecbd6dmarkm{
2574ecbd6dmarkm#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
25833f661cstas    setsockopt (sock, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(int));
2594ecbd6dmarkm#endif
2604ecbd6dmarkm}
2614ecbd6dmarkm
2624ecbd6dmarkm/*
2634ecbd6dmarkm * set the reuse of addresses on `sock' to `val'.
2644ecbd6dmarkm */
2654ecbd6dmarkm
26633f661cstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
26733f661cstassocket_set_reuseaddr (rk_socket_t sock, int val)
2684ecbd6dmarkm{
2694ecbd6dmarkm#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT)
27033f661cstas    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(val));
2714ecbd6dmarkm#endif
2724ecbd6dmarkm}
27351b6601dfr
27451b6601dfr/*
27551b6601dfr * Set the that the `sock' should bind to only IPv6 addresses.
27651b6601dfr */
27751b6601dfr
27833f661cstasROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
27933f661cstassocket_set_ipv6only (rk_socket_t sock, int val)
28051b6601dfr{
28151b6601dfr#if defined(IPV6_V6ONLY) && defined(HAVE_SETSOCKOPT)
28251b6601dfr    setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&val, sizeof(val));
28351b6601dfr#endif
28451b6601dfr}
28533f661cstas
28633f661cstas/**
28733f661cstas * Create a file descriptor from a socket
28833f661cstas *
28933f661cstas * While the socket handle in \a sock can be used with WinSock
29033f661cstas * functions after calling socket_to_fd(), it should not be closed
29133f661cstas * with rk_closesocket().  The socket will be closed when the associated
29233f661cstas * file descriptor is closed.
29333f661cstas */
29433f661cstasROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
29533f661cstassocket_to_fd(rk_socket_t sock, int flags)
29633f661cstas{
29733f661cstas#ifndef _WIN32
29833f661cstas    return sock;
29933f661cstas#else
30033f661cstas    return _open_osfhandle((intptr_t) sock, flags);
30133f661cstas#endif
30233f661cstas}
30333f661cstas
30433f661cstas#ifdef HAVE_WINSOCK
30533f661cstasROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
30633f661cstasrk_SOCK_IOCTL(SOCKET s, long cmd, int * argp) {
30733f661cstas    u_long ul = (argp)? *argp : 0;
30833f661cstas    int rv;
30933f661cstas
31033f661cstas    rv = ioctlsocket(s, cmd, &ul);
31133f661cstas    if (argp)
31233f661cstas	*argp = (int) ul;
31333f661cstas    return rv;
31433f661cstas}
31533f661cstas#endif
31633f661cstas
31733f661cstas#ifndef HEIMDAL_SMALLER
31833f661cstas#undef socket
31933f661cstas
32033f661cstasint rk_socket(int, int, int);
32133f661cstas
32233f661cstasint
32333f661cstasrk_socket(int domain, int type, int protocol)
32433f661cstas{
32533f661cstas    int s;
32633f661cstas    s = socket (domain, type, protocol);
32733f661cstas#ifdef SOCK_CLOEXEC
32833f661cstas    if ((SOCK_CLOEXEC & type) && s < 0 && errno == EINVAL) {
32933f661cstas	type &= ~SOCK_CLOEXEC;
33033f661cstas	s = socket (domain, type, protocol);
33133f661cstas    }
33233f661cstas#endif
33333f661cstas    return s;
33433f661cstas}
33533f661cstas
33633f661cstas#endif /* HEIMDAL_SMALLER */
337