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> 36 RCSID("$Id: socket.c,v 1.8 2003/04/15 03:26:51 lha Exp $"); 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 46 void 47 socket_set_any (struct sockaddr *sa, int af) 48 { 49 switch (af) { 50 case AF_INET : { 51 struct sockaddr_in *sin = (struct sockaddr_in *)sa; 52 53 memset (sin, 0, sizeof(*sin)); 54 sin->sin_family = AF_INET; 55 sin->sin_port = 0; 56 sin->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 80 void 81 socket_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 *sin = (struct sockaddr_in *)sa; 86 87 memset (sin, 0, sizeof(*sin)); 88 sin->sin_family = AF_INET; 89 sin->sin_port = port; 90 memcpy (&sin->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 114 size_t 115 socket_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 134 size_t 135 socket_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 154 void * 155 socket_get_address (struct sockaddr *sa) 156 { 157 switch (sa->sa_family) { 158 case AF_INET : { 159 struct sockaddr_in *sin = (struct sockaddr_in *)sa; 160 return &sin->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 178 int 179 socket_get_port (const struct sockaddr *sa) 180 { 181 switch (sa->sa_family) { 182 case AF_INET : { 183 const struct sockaddr_in *sin = (const struct sockaddr_in *)sa; 184 return sin->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 202 void 203 socket_set_port (struct sockaddr *sa, int port) 204 { 205 switch (sa->sa_family) { 206 case AF_INET : { 207 struct sockaddr_in *sin = (struct sockaddr_in *)sa; 208 sin->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 */ 227 void 228 socket_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 253 void 254 socket_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 268 void 269 socket_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 282 void 283 socket_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