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> 36 RCSID("$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 64 void 65 socket_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 98 void 99 socket_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 132 size_t 133 socket_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 152 size_t 153 socket_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 172 void * 173 socket_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 196 int 197 socket_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 220 void 221 socket_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 246 void 247 socket_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 261 void 262 socket_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 274 void 275 socket_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