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 43void ROKEN_LIB_FUNCTION 44socket_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 77void ROKEN_LIB_FUNCTION 78socket_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 111size_t ROKEN_LIB_FUNCTION 112socket_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 errx (1, "unknown address family %d", sa->sa_family); 123 break; 124 } 125} 126 127/* 128 * Return the size of a `struct sockaddr' in `sa'. 129 */ 130 131size_t ROKEN_LIB_FUNCTION 132socket_sockaddr_size (const struct sockaddr *sa) 133{ 134 switch (sa->sa_family) { 135 case AF_INET : 136 return sizeof(struct sockaddr_in); 137#ifdef HAVE_IPV6 138 case AF_INET6 : 139 return sizeof(struct sockaddr_in6); 140#endif 141 default : 142 errx (1, "unknown address family %d", sa->sa_family); 143 break; 144 } 145} 146 147/* 148 * Return the binary address of `sa'. 149 */ 150 151void * ROKEN_LIB_FUNCTION 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 errx (1, "unknown address family %d", sa->sa_family); 167 break; 168 } 169} 170 171/* 172 * Return the port number from `sa'. 173 */ 174 175int ROKEN_LIB_FUNCTION 176socket_get_port (const struct sockaddr *sa) 177{ 178 switch (sa->sa_family) { 179 case AF_INET : { 180 const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; 181 return sin4->sin_port; 182 } 183#ifdef HAVE_IPV6 184 case AF_INET6 : { 185 const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; 186 return sin6->sin6_port; 187 } 188#endif 189 default : 190 errx (1, "unknown address family %d", sa->sa_family); 191 break; 192 } 193} 194 195/* 196 * Set the port in `sa' to `port'. 197 */ 198 199void ROKEN_LIB_FUNCTION 200socket_set_port (struct sockaddr *sa, int port) 201{ 202 switch (sa->sa_family) { 203 case AF_INET : { 204 struct sockaddr_in *sin4 = (struct sockaddr_in *)sa; 205 sin4->sin_port = port; 206 break; 207 } 208#ifdef HAVE_IPV6 209 case AF_INET6 : { 210 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 211 sin6->sin6_port = port; 212 break; 213 } 214#endif 215 default : 216 errx (1, "unknown address family %d", sa->sa_family); 217 break; 218 } 219} 220 221/* 222 * Set the range of ports to use when binding with port = 0. 223 */ 224void ROKEN_LIB_FUNCTION 225socket_set_portrange (int sock, int restr, int af) 226{ 227#if defined(IP_PORTRANGE) 228 if (af == AF_INET) { 229 int on = restr ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT; 230 if (setsockopt (sock, IPPROTO_IP, IP_PORTRANGE, &on, 231 sizeof(on)) < 0) 232 warn ("setsockopt IP_PORTRANGE (ignored)"); 233 } 234#endif 235#if defined(IPV6_PORTRANGE) 236 if (af == AF_INET6) { 237 int on = restr ? IPV6_PORTRANGE_HIGH : 238 IPV6_PORTRANGE_DEFAULT; 239 if (setsockopt (sock, IPPROTO_IPV6, IPV6_PORTRANGE, &on, 240 sizeof(on)) < 0) 241 warn ("setsockopt IPV6_PORTRANGE (ignored)"); 242 } 243#endif 244} 245 246/* 247 * Enable debug on `sock'. 248 */ 249 250void ROKEN_LIB_FUNCTION 251socket_set_debug (int sock) 252{ 253#if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT) 254 int on = 1; 255 256 if (setsockopt (sock, SOL_SOCKET, SO_DEBUG, (void *) &on, sizeof (on)) < 0) 257 warn ("setsockopt SO_DEBUG (ignored)"); 258#endif 259} 260 261/* 262 * Set the type-of-service of `sock' to `tos'. 263 */ 264 265void ROKEN_LIB_FUNCTION 266socket_set_tos (int sock, int tos) 267{ 268#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) 269 if (setsockopt (sock, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof (int)) < 0) 270 if (errno != EINVAL) 271 warn ("setsockopt TOS (ignored)"); 272#endif 273} 274 275/* 276 * set the reuse of addresses on `sock' to `val'. 277 */ 278 279void ROKEN_LIB_FUNCTION 280socket_set_reuseaddr (int sock, int val) 281{ 282#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT) 283 if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val, 284 sizeof(val)) < 0) 285 err (1, "setsockopt SO_REUSEADDR"); 286#endif 287} 288 289/* 290 * Set the that the `sock' should bind to only IPv6 addresses. 291 */ 292 293void ROKEN_LIB_FUNCTION 294socket_set_ipv6only (int sock, int val) 295{ 296#if defined(IPV6_V6ONLY) && defined(HAVE_SETSOCKOPT) 297 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&val, sizeof(val)); 298#endif 299} 300