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