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 43 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 44 socket_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 break; 70 } 71 } 72 73 /* 74 * set `sa' to (`ptr', `port') 75 */ 76 77 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 78 socket_set_address_and_port (struct sockaddr *sa, const void *ptr, int port) 79 { 80 switch (sa->sa_family) { 81 case AF_INET : { 82 struct sockaddr_in *sin4 = (struct sockaddr_in *)sa; 83 84 memset (sin4, 0, sizeof(*sin4)); 85 sin4->sin_family = AF_INET; 86 sin4->sin_port = port; 87 memcpy (&sin4->sin_addr, ptr, sizeof(struct in_addr)); 88 break; 89 } 90 #ifdef HAVE_IPV6 91 case AF_INET6 : { 92 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 93 94 memset (sin6, 0, sizeof(*sin6)); 95 sin6->sin6_family = AF_INET6; 96 sin6->sin6_port = port; 97 memcpy (&sin6->sin6_addr, ptr, sizeof(struct in6_addr)); 98 break; 99 } 100 #endif 101 default : 102 errx (1, "unknown address family %d", sa->sa_family); 103 break; 104 } 105 } 106 107 /* 108 * Return the size of an address of the type in `sa' 109 */ 110 111 ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL 112 socket_addr_size (const struct sockaddr *sa) 113 { 114 switch (sa->sa_family) { 115 case AF_INET : 116 return sizeof(struct in_addr); 117 #ifdef HAVE_IPV6 118 case AF_INET6 : 119 return sizeof(struct in6_addr); 120 #endif 121 default : 122 return 0; 123 } 124 } 125 126 /* 127 * Return the size of a `struct sockaddr' in `sa'. 128 */ 129 130 ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL 131 socket_sockaddr_size (const struct sockaddr *sa) 132 { 133 switch (sa->sa_family) { 134 case AF_INET : 135 return sizeof(struct sockaddr_in); 136 #ifdef HAVE_IPV6 137 case AF_INET6 : 138 return sizeof(struct sockaddr_in6); 139 #endif 140 default: 141 return 0; 142 } 143 } 144 145 /* 146 * Return the binary address of `sa'. 147 */ 148 149 ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL 150 socket_get_address (const struct sockaddr *sa) 151 { 152 switch (sa->sa_family) { 153 case AF_INET : { 154 const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; 155 return rk_UNCONST(&sin4->sin_addr); 156 } 157 #ifdef HAVE_IPV6 158 case AF_INET6 : { 159 const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; 160 return rk_UNCONST(&sin6->sin6_addr); 161 } 162 #endif 163 default: 164 return NULL; 165 } 166 } 167 168 /* 169 * Return the port number from `sa'. 170 */ 171 172 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL 173 socket_get_port (const struct sockaddr *sa) 174 { 175 switch (sa->sa_family) { 176 case AF_INET : { 177 const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; 178 return sin4->sin_port; 179 } 180 #ifdef HAVE_IPV6 181 case AF_INET6 : { 182 const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; 183 return sin6->sin6_port; 184 } 185 #endif 186 default : 187 return 0; 188 } 189 } 190 191 /* 192 * Set the port in `sa' to `port'. 193 */ 194 195 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 196 socket_set_port (struct sockaddr *sa, int port) 197 { 198 switch (sa->sa_family) { 199 case AF_INET : { 200 struct sockaddr_in *sin4 = (struct sockaddr_in *)sa; 201 sin4->sin_port = port; 202 break; 203 } 204 #ifdef HAVE_IPV6 205 case AF_INET6 : { 206 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 207 sin6->sin6_port = port; 208 break; 209 } 210 #endif 211 default : 212 errx (1, "unknown address family %d", sa->sa_family); 213 break; 214 } 215 } 216 217 /* 218 * Set the range of ports to use when binding with port = 0. 219 */ 220 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 221 socket_set_portrange (rk_socket_t sock, int restr, int af) 222 { 223 #if defined(IP_PORTRANGE) 224 if (af == AF_INET) { 225 int on = restr ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT; 226 setsockopt (sock, IPPROTO_IP, IP_PORTRANGE, &on, sizeof(on)); 227 } 228 #endif 229 #if defined(IPV6_PORTRANGE) 230 if (af == AF_INET6) { 231 int on = restr ? IPV6_PORTRANGE_HIGH : IPV6_PORTRANGE_DEFAULT; 232 setsockopt (sock, IPPROTO_IPV6, IPV6_PORTRANGE, &on, sizeof(on)); 233 } 234 #endif 235 } 236 237 /* 238 * Enable debug on `sock'. 239 */ 240 241 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 242 socket_set_debug (rk_socket_t sock) 243 { 244 #if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT) 245 int on = 1; 246 setsockopt (sock, SOL_SOCKET, SO_DEBUG, (void *) &on, sizeof (on)); 247 #endif 248 } 249 250 /* 251 * Set the type-of-service of `sock' to `tos'. 252 */ 253 254 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 255 socket_set_tos (rk_socket_t sock, int tos) 256 { 257 #if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) 258 setsockopt (sock, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(int)); 259 #endif 260 } 261 262 /* 263 * set the reuse of addresses on `sock' to `val'. 264 */ 265 266 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 267 socket_set_reuseaddr (rk_socket_t sock, int val) 268 { 269 #if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT) 270 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(val)); 271 #endif 272 } 273 274 /* 275 * Set the that the `sock' should bind to only IPv6 addresses. 276 */ 277 278 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 279 socket_set_ipv6only (rk_socket_t sock, int val) 280 { 281 #if defined(IPV6_V6ONLY) && defined(HAVE_SETSOCKOPT) 282 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&val, sizeof(val)); 283 #endif 284 } 285 286 /** 287 * Create a file descriptor from a socket 288 * 289 * While the socket handle in \a sock can be used with WinSock 290 * functions after calling socket_to_fd(), it should not be closed 291 * with rk_closesocket(). The socket will be closed when the associated 292 * file descriptor is closed. 293 */ 294 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL 295 socket_to_fd(rk_socket_t sock, int flags) 296 { 297 #ifndef _WIN32 298 return sock; 299 #else 300 return _open_osfhandle((intptr_t) sock, flags); 301 #endif 302 } 303 304 #ifdef HAVE_WINSOCK 305 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL 306 rk_SOCK_IOCTL(SOCKET s, long cmd, int * argp) { 307 u_long ul = (argp)? *argp : 0; 308 int rv; 309 310 rv = ioctlsocket(s, cmd, &ul); 311 if (argp) 312 *argp = (int) ul; 313 return rv; 314 } 315 #endif 316 317 #ifndef HEIMDAL_SMALLER 318 #undef socket 319 320 int rk_socket(int, int, int); 321 322 int 323 rk_socket(int domain, int type, int protocol) 324 { 325 int s; 326 s = socket (domain, type, protocol); 327 #ifdef SOCK_CLOEXEC 328 if ((SOCK_CLOEXEC & type) && s < 0 && errno == EINVAL) { 329 type &= ~SOCK_CLOEXEC; 330 s = socket (domain, type, protocol); 331 } 332 #endif 333 return s; 334 } 335 336 #endif /* HEIMDAL_SMALLER */ 337