socket.c revision 178825
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#ifdef HAVE_CONFIG_H 35#include <config.h> 36RCSID("$Id: socket.c 21005 2007-06-08 01:54:35Z lha $"); 37#endif 38 39#include "roken.h" 40#include <err.h> 41 42/* 43 * Set `sa' to the unitialized address of address family `af' 44 */ 45 46void ROKEN_LIB_FUNCTION 47socket_set_any (struct sockaddr *sa, int af) 48{ 49 switch (af) { 50 case AF_INET : { 51 struct sockaddr_in *sin4 = (struct sockaddr_in *)sa; 52 53 memset (sin4, 0, sizeof(*sin4)); 54 sin4->sin_family = AF_INET; 55 sin4->sin_port = 0; 56 sin4->sin_addr.s_addr = INADDR_ANY; 57 break; 58 } 59#ifdef HAVE_IPV6 60 case AF_INET6 : { 61 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 62 63 memset (sin6, 0, sizeof(*sin6)); 64 sin6->sin6_family = AF_INET6; 65 sin6->sin6_port = 0; 66 sin6->sin6_addr = in6addr_any; 67 break; 68 } 69#endif 70 default : 71 errx (1, "unknown address family %d", sa->sa_family); 72 break; 73 } 74} 75 76/* 77 * set `sa' to (`ptr', `port') 78 */ 79 80void ROKEN_LIB_FUNCTION 81socket_set_address_and_port (struct sockaddr *sa, const void *ptr, int port) 82{ 83 switch (sa->sa_family) { 84 case AF_INET : { 85 struct sockaddr_in *sin4 = (struct sockaddr_in *)sa; 86 87 memset (sin4, 0, sizeof(*sin4)); 88 sin4->sin_family = AF_INET; 89 sin4->sin_port = port; 90 memcpy (&sin4->sin_addr, ptr, sizeof(struct in_addr)); 91 break; 92 } 93#ifdef HAVE_IPV6 94 case AF_INET6 : { 95 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 96 97 memset (sin6, 0, sizeof(*sin6)); 98 sin6->sin6_family = AF_INET6; 99 sin6->sin6_port = port; 100 memcpy (&sin6->sin6_addr, ptr, sizeof(struct in6_addr)); 101 break; 102 } 103#endif 104 default : 105 errx (1, "unknown address family %d", sa->sa_family); 106 break; 107 } 108} 109 110/* 111 * Return the size of an address of the type in `sa' 112 */ 113 114size_t ROKEN_LIB_FUNCTION 115socket_addr_size (const struct sockaddr *sa) 116{ 117 switch (sa->sa_family) { 118 case AF_INET : 119 return sizeof(struct in_addr); 120#ifdef HAVE_IPV6 121 case AF_INET6 : 122 return sizeof(struct in6_addr); 123#endif 124 default : 125 errx (1, "unknown address family %d", sa->sa_family); 126 break; 127 } 128} 129 130/* 131 * Return the size of a `struct sockaddr' in `sa'. 132 */ 133 134size_t ROKEN_LIB_FUNCTION 135socket_sockaddr_size (const struct sockaddr *sa) 136{ 137 switch (sa->sa_family) { 138 case AF_INET : 139 return sizeof(struct sockaddr_in); 140#ifdef HAVE_IPV6 141 case AF_INET6 : 142 return sizeof(struct sockaddr_in6); 143#endif 144 default : 145 errx (1, "unknown address family %d", sa->sa_family); 146 break; 147 } 148} 149 150/* 151 * Return the binary address of `sa'. 152 */ 153 154void * ROKEN_LIB_FUNCTION 155socket_get_address (struct sockaddr *sa) 156{ 157 switch (sa->sa_family) { 158 case AF_INET : { 159 struct sockaddr_in *sin4 = (struct sockaddr_in *)sa; 160 return &sin4->sin_addr; 161 } 162#ifdef HAVE_IPV6 163 case AF_INET6 : { 164 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 165 return &sin6->sin6_addr; 166 } 167#endif 168 default : 169 errx (1, "unknown address family %d", sa->sa_family); 170 break; 171 } 172} 173 174/* 175 * Return the port number from `sa'. 176 */ 177 178int ROKEN_LIB_FUNCTION 179socket_get_port (const struct sockaddr *sa) 180{ 181 switch (sa->sa_family) { 182 case AF_INET : { 183 const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; 184 return sin4->sin_port; 185 } 186#ifdef HAVE_IPV6 187 case AF_INET6 : { 188 const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; 189 return sin6->sin6_port; 190 } 191#endif 192 default : 193 errx (1, "unknown address family %d", sa->sa_family); 194 break; 195 } 196} 197 198/* 199 * Set the port in `sa' to `port'. 200 */ 201 202void ROKEN_LIB_FUNCTION 203socket_set_port (struct sockaddr *sa, int port) 204{ 205 switch (sa->sa_family) { 206 case AF_INET : { 207 struct sockaddr_in *sin4 = (struct sockaddr_in *)sa; 208 sin4->sin_port = port; 209 break; 210 } 211#ifdef HAVE_IPV6 212 case AF_INET6 : { 213 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 214 sin6->sin6_port = port; 215 break; 216 } 217#endif 218 default : 219 errx (1, "unknown address family %d", sa->sa_family); 220 break; 221 } 222} 223 224/* 225 * Set the range of ports to use when binding with port = 0. 226 */ 227void ROKEN_LIB_FUNCTION 228socket_set_portrange (int sock, int restr, int af) 229{ 230#if defined(IP_PORTRANGE) 231 if (af == AF_INET) { 232 int on = restr ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT; 233 if (setsockopt (sock, IPPROTO_IP, IP_PORTRANGE, &on, 234 sizeof(on)) < 0) 235 warn ("setsockopt IP_PORTRANGE (ignored)"); 236 } 237#endif 238#if defined(IPV6_PORTRANGE) 239 if (af == AF_INET6) { 240 int on = restr ? IPV6_PORTRANGE_HIGH : 241 IPV6_PORTRANGE_DEFAULT; 242 if (setsockopt (sock, IPPROTO_IPV6, IPV6_PORTRANGE, &on, 243 sizeof(on)) < 0) 244 warn ("setsockopt IPV6_PORTRANGE (ignored)"); 245 } 246#endif 247} 248 249/* 250 * Enable debug on `sock'. 251 */ 252 253void ROKEN_LIB_FUNCTION 254socket_set_debug (int sock) 255{ 256#if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT) 257 int on = 1; 258 259 if (setsockopt (sock, SOL_SOCKET, SO_DEBUG, (void *) &on, sizeof (on)) < 0) 260 warn ("setsockopt SO_DEBUG (ignored)"); 261#endif 262} 263 264/* 265 * Set the type-of-service of `sock' to `tos'. 266 */ 267 268void ROKEN_LIB_FUNCTION 269socket_set_tos (int sock, int tos) 270{ 271#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) 272 if (setsockopt (sock, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof (int)) < 0) 273 if (errno != EINVAL) 274 warn ("setsockopt TOS (ignored)"); 275#endif 276} 277 278/* 279 * set the reuse of addresses on `sock' to `val'. 280 */ 281 282void ROKEN_LIB_FUNCTION 283socket_set_reuseaddr (int sock, int val) 284{ 285#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT) 286 if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val, 287 sizeof(val)) < 0) 288 err (1, "setsockopt SO_REUSEADDR"); 289#endif 290} 291 292/* 293 * Set the that the `sock' should bind to only IPv6 addresses. 294 */ 295 296void ROKEN_LIB_FUNCTION 297socket_set_ipv6only (int sock, int val) 298{ 299#if defined(IPV6_V6ONLY) && defined(HAVE_SETSOCKOPT) 300 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&val, sizeof(val)); 301#endif 302} 303