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 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