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