1160814Ssimon/* 2160814Ssimon * Copyright (c) 1999 - 2000 Kungliga Tekniska H��gskolan 3160814Ssimon * (Royal Institute of Technology, Stockholm, Sweden). 4160814Ssimon * All rights reserved. 5160814Ssimon * 6160814Ssimon * Redistribution and use in source and binary forms, with or without 7160814Ssimon * modification, are permitted provided that the following conditions 8160814Ssimon * are met: 9160814Ssimon * 10280304Sjkim * 1. Redistributions of source code must retain the above copyright 11160814Ssimon * notice, this list of conditions and the following disclaimer. 12160814Ssimon * 13160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright 14160814Ssimon * notice, this list of conditions and the following disclaimer in the 15160814Ssimon * documentation and/or other materials provided with the distribution. 16160814Ssimon * 17160814Ssimon * 3. Neither the name of the Institute nor the names of its contributors 18160814Ssimon * may be used to endorse or promote products derived from this software 19160814Ssimon * without specific prior written permission. 20160814Ssimon * 21160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22160814Ssimon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24160814Ssimon * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25160814Ssimon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26160814Ssimon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27160814Ssimon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29160814Ssimon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30160814Ssimon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31160814Ssimon * SUCH DAMAGE. 32160814Ssimon */ 33160814Ssimon 34160814Ssimon#include <config.h> 35160814Ssimon 36160814Ssimon#include "roken.h" 37160814Ssimon#include <err.h> 38160814Ssimon 39160814Ssimon/* 40160814Ssimon * Set `sa' to the unitialized address of address family `af' 41160814Ssimon */ 42160814Ssimon 43160814SsimonROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 44160814Ssimonsocket_set_any (struct sockaddr *sa, int af) 45160814Ssimon{ 46160814Ssimon switch (af) { 47160814Ssimon case AF_INET : { 48160814Ssimon struct sockaddr_in *sin4 = (struct sockaddr_in *)sa; 49160814Ssimon 50160814Ssimon memset (sin4, 0, sizeof(*sin4)); 51160814Ssimon sin4->sin_family = AF_INET; 52160814Ssimon sin4->sin_port = 0; 53160814Ssimon sin4->sin_addr.s_addr = INADDR_ANY; 54160814Ssimon break; 55160814Ssimon } 56160814Ssimon#ifdef HAVE_IPV6 57160814Ssimon case AF_INET6 : { 58160814Ssimon struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 59280304Sjkim 60280304Sjkim memset (sin6, 0, sizeof(*sin6)); 61160814Ssimon sin6->sin6_family = AF_INET6; 62280304Sjkim sin6->sin6_port = 0; 63280304Sjkim sin6->sin6_addr = in6addr_any; 64280304Sjkim break; 65280304Sjkim } 66160814Ssimon#endif 67280304Sjkim default : 68280304Sjkim errx (1, "unknown address family %d", sa->sa_family); 69280304Sjkim break; 70160814Ssimon } 71280304Sjkim} 72280304Sjkim 73160814Ssimon/* 74280304Sjkim * set `sa' to (`ptr', `port') 75280304Sjkim */ 76280304Sjkim 77280304SjkimROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 78160814Ssimonsocket_set_address_and_port (struct sockaddr *sa, const void *ptr, int port) 79280304Sjkim{ 80160814Ssimon switch (sa->sa_family) { 81280304Sjkim case AF_INET : { 82160814Ssimon struct sockaddr_in *sin4 = (struct sockaddr_in *)sa; 83280304Sjkim 84160814Ssimon memset (sin4, 0, sizeof(*sin4)); 85160814Ssimon sin4->sin_family = AF_INET; 86160814Ssimon sin4->sin_port = port; 87280304Sjkim memcpy (&sin4->sin_addr, ptr, sizeof(struct in_addr)); 88280304Sjkim break; 89280304Sjkim } 90280304Sjkim#ifdef HAVE_IPV6 91280304Sjkim case AF_INET6 : { 92160814Ssimon struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 93280304Sjkim 94280304Sjkim memset (sin6, 0, sizeof(*sin6)); 95280304Sjkim sin6->sin6_family = AF_INET6; 96280304Sjkim sin6->sin6_port = port; 97280304Sjkim memcpy (&sin6->sin6_addr, ptr, sizeof(struct in6_addr)); 98160814Ssimon break; 99280304Sjkim } 100280304Sjkim#endif 101280304Sjkim default : 102280304Sjkim errx (1, "unknown address family %d", sa->sa_family); 103160814Ssimon break; 104280304Sjkim } 105280304Sjkim} 106280304Sjkim 107280304Sjkim/* 108280304Sjkim * Return the size of an address of the type in `sa' 109280304Sjkim */ 110280304Sjkim 111160814SsimonROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL 112280304Sjkimsocket_addr_size (const struct sockaddr *sa) 113280304Sjkim{ 114280304Sjkim switch (sa->sa_family) { 115280304Sjkim case AF_INET : 116280304Sjkim return sizeof(struct in_addr); 117280304Sjkim#ifdef HAVE_IPV6 118160814Ssimon case AF_INET6 : 119280304Sjkim return sizeof(struct in6_addr); 120280304Sjkim#endif 121280304Sjkim default : 122160814Ssimon return 0; 123160814Ssimon } 124160814Ssimon} 125160814Ssimon 126160814Ssimon/* 127160814Ssimon * Return the size of a `struct sockaddr' in `sa'. 128280304Sjkim */ 129280304Sjkim 130280304SjkimROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL 131280304Sjkimsocket_sockaddr_size (const struct sockaddr *sa) 132280304Sjkim{ 133160814Ssimon switch (sa->sa_family) { 134280304Sjkim case AF_INET : 135280304Sjkim return sizeof(struct sockaddr_in); 136280304Sjkim#ifdef HAVE_IPV6 137160814Ssimon case AF_INET6 : 138280304Sjkim return sizeof(struct sockaddr_in6); 139280304Sjkim#endif 140160814Ssimon default: 141280304Sjkim return 0; 142280304Sjkim } 143280304Sjkim} 144280304Sjkim 145160814Ssimon/* 146280304Sjkim * Return the binary address of `sa'. 147280304Sjkim */ 148280304Sjkim 149280304SjkimROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL 150280304Sjkimsocket_get_address (const struct sockaddr *sa) 151280304Sjkim{ 152280304Sjkim switch (sa->sa_family) { 153280304Sjkim case AF_INET : { 154280304Sjkim const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; 155280304Sjkim return rk_UNCONST(&sin4->sin_addr); 156280304Sjkim } 157280304Sjkim#ifdef HAVE_IPV6 158280304Sjkim case AF_INET6 : { 159160814Ssimon const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; 160280304Sjkim return rk_UNCONST(&sin6->sin6_addr); 161160814Ssimon } 162280304Sjkim#endif 163280304Sjkim default: 164160814Ssimon return NULL; 165160814Ssimon } 166280304Sjkim} 167280304Sjkim 168280304Sjkim/* 169280304Sjkim * Return the port number from `sa'. 170160814Ssimon */ 171280304Sjkim 172280304SjkimROKEN_LIB_FUNCTION int ROKEN_LIB_CALL 173160814Ssimonsocket_get_port (const struct sockaddr *sa) 174280304Sjkim{ 175160814Ssimon switch (sa->sa_family) { 176280304Sjkim case AF_INET : { 177160814Ssimon const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; 178280304Sjkim return sin4->sin_port; 179280304Sjkim } 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 195ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 196socket_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 */ 220ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 221socket_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 241ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 242socket_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 254ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 255socket_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 266ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 267socket_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 278ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL 279socket_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 */ 294ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL 295socket_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 305ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL 306rk_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 320int rk_socket(int, int, int); 321 322int 323rk_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