1 /* $NetBSD: socket.c,v 1.1.1.1 2011/04/13 18:15:43 elric 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 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