Home | History | Annotate | Line # | Download | only in roken
socket.c revision 1.1
      1 /*	$NetBSD: socket.c,v 1.1 2011/04/13 18:15:43 elric 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 reuse of addresses on `sock' to `val'.
    266  */
    267 
    268 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
    269 socket_set_reuseaddr (rk_socket_t sock, int val)
    270 {
    271 #if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT)
    272     setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(val));
    273 #endif
    274 }
    275 
    276 /*
    277  * Set the that the `sock' should bind to only IPv6 addresses.
    278  */
    279 
    280 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
    281 socket_set_ipv6only (rk_socket_t sock, int val)
    282 {
    283 #if defined(IPV6_V6ONLY) && defined(HAVE_SETSOCKOPT)
    284     setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&val, sizeof(val));
    285 #endif
    286 }
    287 
    288 /**
    289  * Create a file descriptor from a socket
    290  *
    291  * While the socket handle in \a sock can be used with WinSock
    292  * functions after calling socket_to_fd(), it should not be closed
    293  * with rk_closesocket().  The socket will be closed when the associated
    294  * file descriptor is closed.
    295  */
    296 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
    297 socket_to_fd(rk_socket_t sock, int flags)
    298 {
    299 #ifndef _WIN32
    300     return sock;
    301 #else
    302     return _open_osfhandle((intptr_t) sock, flags);
    303 #endif
    304 }
    305 
    306 #ifdef HAVE_WINSOCK
    307 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
    308 rk_SOCK_IOCTL(SOCKET s, long cmd, int * argp) {
    309     u_long ul = (argp)? *argp : 0;
    310     int rv;
    311 
    312     rv = ioctlsocket(s, cmd, &ul);
    313     if (argp)
    314 	*argp = (int) ul;
    315     return rv;
    316 }
    317 #endif
    318 
    319 #ifndef HEIMDAL_SMALLER
    320 #undef socket
    321 
    322 int rk_socket(int, int, int);
    323 
    324 int
    325 rk_socket(int domain, int type, int protocol)
    326 {
    327     int s;
    328     s = socket (domain, type, protocol);
    329 #ifdef SOCK_CLOEXEC
    330     if ((SOCK_CLOEXEC & type) && s < 0 && errno == EINVAL) {
    331 	type &= ~SOCK_CLOEXEC;
    332 	s = socket (domain, type, protocol);
    333     }
    334 #endif
    335     return s;
    336 }
    337 
    338 #endif /* HEIMDAL_SMALLER */
    339