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