1/* $NetBSD: socket.c,v 1.2 2017/01/28 21:31:50 christos Exp $ */ 2 3/* 4 * Copyright (c) 1999 - 2000 Kungliga Tekniska H��gskolan 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 45ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 46socket_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 79ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 80socket_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 113ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL 114socket_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 132ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL 133socket_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 151ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL 152socket_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 174ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL 175socket_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 197ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 198socket_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 */ 222ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 223socket_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 243ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 244socket_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 256ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 257socket_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 268ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 269socket_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 290ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 291socket_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 302ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 303socket_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 */ 318ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL 319socket_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 329ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL 330rk_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 344int rk_socket(int, int, int); 345 346int 347rk_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