socket.c revision 4ecbd6db44d79348bc815f31096e53104f50838
14ecbd6dmarkm/*
24ecbd6dmarkm * Copyright (c) 1999 Kungliga Tekniska H�gskolan
34ecbd6dmarkm * (Royal Institute of Technology, Stockholm, Sweden).
44ecbd6dmarkm * All rights reserved.
54ecbd6dmarkm *
64ecbd6dmarkm * Redistribution and use in source and binary forms, with or without
74ecbd6dmarkm * modification, are permitted provided that the following conditions
84ecbd6dmarkm * are met:
94ecbd6dmarkm *
104ecbd6dmarkm * 1. Redistributions of source code must retain the above copyright
114ecbd6dmarkm *    notice, this list of conditions and the following disclaimer.
124ecbd6dmarkm *
134ecbd6dmarkm * 2. Redistributions in binary form must reproduce the above copyright
144ecbd6dmarkm *    notice, this list of conditions and the following disclaimer in the
154ecbd6dmarkm *    documentation and/or other materials provided with the distribution.
164ecbd6dmarkm *
174ecbd6dmarkm * 3. Neither the name of the Institute nor the names of its contributors
184ecbd6dmarkm *    may be used to endorse or promote products derived from this software
194ecbd6dmarkm *    without specific prior written permission.
204ecbd6dmarkm *
214ecbd6dmarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
224ecbd6dmarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
234ecbd6dmarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
244ecbd6dmarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
254ecbd6dmarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
264ecbd6dmarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
274ecbd6dmarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
284ecbd6dmarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
294ecbd6dmarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
304ecbd6dmarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
314ecbd6dmarkm * SUCH DAMAGE.
324ecbd6dmarkm */
334ecbd6dmarkm
344ecbd6dmarkm#ifdef HAVE_CONFIG_H
354ecbd6dmarkm#include <config.h>
364ecbd6dmarkmRCSID("$Id: socket.c,v 1.3 1999/12/02 16:58:52 joda Exp $");
374ecbd6dmarkm#endif
384ecbd6dmarkm
394ecbd6dmarkm#include <string.h>
404ecbd6dmarkm#ifdef HAVE_SYS_TYPES_H
414ecbd6dmarkm#include <sys/types.h>
424ecbd6dmarkm#endif
434ecbd6dmarkm#ifdef HAVE_SYS_SOCKET_H
444ecbd6dmarkm#include <sys/socket.h>
454ecbd6dmarkm#endif
464ecbd6dmarkm#ifdef HAVE_NETINET_IN_H
474ecbd6dmarkm#include <netinet/in.h>
484ecbd6dmarkm#endif
494ecbd6dmarkm#ifdef HAVE_NETINET_IN_SYSTM_H
504ecbd6dmarkm#include <netinet/in_systm.h>
514ecbd6dmarkm#endif
524ecbd6dmarkm#ifdef HAVE_NETINET_IP_H
534ecbd6dmarkm#include <netinet/ip.h>
544ecbd6dmarkm#endif
554ecbd6dmarkm
564ecbd6dmarkm#include <roken.h>
574ecbd6dmarkm
584ecbd6dmarkm#include <err.h>
594ecbd6dmarkm
604ecbd6dmarkm/*
614ecbd6dmarkm * Set `sa' to the unitialized address of address family `af'
624ecbd6dmarkm */
634ecbd6dmarkm
644ecbd6dmarkmvoid
654ecbd6dmarkmsocket_set_any (struct sockaddr *sa, int af)
664ecbd6dmarkm{
674ecbd6dmarkm    switch (af) {
684ecbd6dmarkm    case AF_INET : {
694ecbd6dmarkm	struct sockaddr_in *sin = (struct sockaddr_in *)sa;
704ecbd6dmarkm
714ecbd6dmarkm	memset (sin, 0, sizeof(*sin));
724ecbd6dmarkm	sin->sin_family = AF_INET;
734ecbd6dmarkm	sin->sin_port   = 0;
744ecbd6dmarkm	sin->sin_addr.s_addr = INADDR_ANY;
754ecbd6dmarkm	break;
764ecbd6dmarkm    }
774ecbd6dmarkm#ifdef HAVE_IPV6
784ecbd6dmarkm    case AF_INET6 : {
794ecbd6dmarkm	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
804ecbd6dmarkm
814ecbd6dmarkm	memset (sin6, 0, sizeof(*sin6));
824ecbd6dmarkm	sin6->sin6_family = AF_INET6;
834ecbd6dmarkm	sin6->sin6_port   = 0;
844ecbd6dmarkm	sin6->sin6_addr   = in6addr_any;
854ecbd6dmarkm	break;
864ecbd6dmarkm    }
874ecbd6dmarkm#endif
884ecbd6dmarkm    default :
894ecbd6dmarkm	errx (1, "unknown address family %d", sa->sa_family);
904ecbd6dmarkm	break;
914ecbd6dmarkm    }
924ecbd6dmarkm}
934ecbd6dmarkm
944ecbd6dmarkm/*
954ecbd6dmarkm * set `sa' to (`ptr', `port')
964ecbd6dmarkm */
974ecbd6dmarkm
984ecbd6dmarkmvoid
994ecbd6dmarkmsocket_set_address_and_port (struct sockaddr *sa, const void *ptr, int port)
1004ecbd6dmarkm{
1014ecbd6dmarkm    switch (sa->sa_family) {
1024ecbd6dmarkm    case AF_INET : {
1034ecbd6dmarkm	struct sockaddr_in *sin = (struct sockaddr_in *)sa;
1044ecbd6dmarkm
1054ecbd6dmarkm	memset (sin, 0, sizeof(*sin));
1064ecbd6dmarkm	sin->sin_family = AF_INET;
1074ecbd6dmarkm	sin->sin_port   = port;
1084ecbd6dmarkm	memcpy (&sin->sin_addr, ptr, sizeof(struct in_addr));
1094ecbd6dmarkm	break;
1104ecbd6dmarkm    }
1114ecbd6dmarkm#ifdef HAVE_IPV6
1124ecbd6dmarkm    case AF_INET6 : {
1134ecbd6dmarkm	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
1144ecbd6dmarkm
1154ecbd6dmarkm	memset (sin6, 0, sizeof(*sin6));
1164ecbd6dmarkm	sin6->sin6_family = AF_INET6;
1174ecbd6dmarkm	sin6->sin6_port   = port;
1184ecbd6dmarkm	memcpy (&sin6->sin6_addr, ptr, sizeof(struct in6_addr));
1194ecbd6dmarkm	break;
1204ecbd6dmarkm    }
1214ecbd6dmarkm#endif
1224ecbd6dmarkm    default :
1234ecbd6dmarkm	errx (1, "unknown address family %d", sa->sa_family);
1244ecbd6dmarkm	break;
1254ecbd6dmarkm    }
1264ecbd6dmarkm}
1274ecbd6dmarkm
1284ecbd6dmarkm/*
1294ecbd6dmarkm * Return the size of an address of the type in `sa'
1304ecbd6dmarkm */
1314ecbd6dmarkm
1324ecbd6dmarkmsize_t
1334ecbd6dmarkmsocket_addr_size (const struct sockaddr *sa)
1344ecbd6dmarkm{
1354ecbd6dmarkm    switch (sa->sa_family) {
1364ecbd6dmarkm    case AF_INET :
1374ecbd6dmarkm	return sizeof(struct in_addr);
1384ecbd6dmarkm#ifdef HAVE_IPV6
1394ecbd6dmarkm    case AF_INET6 :
1404ecbd6dmarkm	return sizeof(struct in6_addr);
1414ecbd6dmarkm#endif
1424ecbd6dmarkm    default :
1434ecbd6dmarkm	errx (1, "unknown address family %d", sa->sa_family);
1444ecbd6dmarkm	break;
1454ecbd6dmarkm    }
1464ecbd6dmarkm}
1474ecbd6dmarkm
1484ecbd6dmarkm/*
1494ecbd6dmarkm * Return the size of a `struct sockaddr' in `sa'.
1504ecbd6dmarkm */
1514ecbd6dmarkm
1524ecbd6dmarkmsize_t
1534ecbd6dmarkmsocket_sockaddr_size (const struct sockaddr *sa)
1544ecbd6dmarkm{
1554ecbd6dmarkm    switch (sa->sa_family) {
1564ecbd6dmarkm    case AF_INET :
1574ecbd6dmarkm	return sizeof(struct sockaddr_in);
1584ecbd6dmarkm#ifdef HAVE_IPV6
1594ecbd6dmarkm    case AF_INET6 :
1604ecbd6dmarkm	return sizeof(struct sockaddr_in6);
1614ecbd6dmarkm#endif
1624ecbd6dmarkm    default :
1634ecbd6dmarkm	errx (1, "unknown address family %d", sa->sa_family);
1644ecbd6dmarkm	break;
1654ecbd6dmarkm    }
1664ecbd6dmarkm}
1674ecbd6dmarkm
1684ecbd6dmarkm/*
1694ecbd6dmarkm * Return the binary address of `sa'.
1704ecbd6dmarkm */
1714ecbd6dmarkm
1724ecbd6dmarkmvoid *
1734ecbd6dmarkmsocket_get_address (struct sockaddr *sa)
1744ecbd6dmarkm{
1754ecbd6dmarkm    switch (sa->sa_family) {
1764ecbd6dmarkm    case AF_INET : {
1774ecbd6dmarkm	struct sockaddr_in *sin = (struct sockaddr_in *)sa;
1784ecbd6dmarkm	return &sin->sin_addr;
1794ecbd6dmarkm    }
1804ecbd6dmarkm#ifdef HAVE_IPV6
1814ecbd6dmarkm    case AF_INET6 : {
1824ecbd6dmarkm	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
1834ecbd6dmarkm	return &sin6->sin6_addr;
1844ecbd6dmarkm    }
1854ecbd6dmarkm#endif
1864ecbd6dmarkm    default :
1874ecbd6dmarkm	errx (1, "unknown address family %d", sa->sa_family);
1884ecbd6dmarkm	break;
1894ecbd6dmarkm    }
1904ecbd6dmarkm}
1914ecbd6dmarkm
1924ecbd6dmarkm/*
1934ecbd6dmarkm * Return the port number from `sa'.
1944ecbd6dmarkm */
1954ecbd6dmarkm
1964ecbd6dmarkmint
1974ecbd6dmarkmsocket_get_port (const struct sockaddr *sa)
1984ecbd6dmarkm{
1994ecbd6dmarkm    switch (sa->sa_family) {
2004ecbd6dmarkm    case AF_INET : {
2014ecbd6dmarkm	const struct sockaddr_in *sin = (const struct sockaddr_in *)sa;
2024ecbd6dmarkm	return sin->sin_port;
2034ecbd6dmarkm    }
2044ecbd6dmarkm#ifdef HAVE_IPV6
2054ecbd6dmarkm    case AF_INET6 : {
2064ecbd6dmarkm	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
2074ecbd6dmarkm	return sin6->sin6_port;
2084ecbd6dmarkm    }
2094ecbd6dmarkm#endif
2104ecbd6dmarkm    default :
2114ecbd6dmarkm	errx (1, "unknown address family %d", sa->sa_family);
2124ecbd6dmarkm	break;
2134ecbd6dmarkm    }
2144ecbd6dmarkm}
2154ecbd6dmarkm
2164ecbd6dmarkm/*
2174ecbd6dmarkm * Set the port in `sa' to `port'.
2184ecbd6dmarkm */
2194ecbd6dmarkm
2204ecbd6dmarkmvoid
2214ecbd6dmarkmsocket_set_port (struct sockaddr *sa, int port)
2224ecbd6dmarkm{
2234ecbd6dmarkm    switch (sa->sa_family) {
2244ecbd6dmarkm    case AF_INET : {
2254ecbd6dmarkm	struct sockaddr_in *sin = (struct sockaddr_in *)sa;
2264ecbd6dmarkm	sin->sin_port = port;
2274ecbd6dmarkm	break;
2284ecbd6dmarkm    }
2294ecbd6dmarkm#ifdef HAVE_IPV6
2304ecbd6dmarkm    case AF_INET6 : {
2314ecbd6dmarkm	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
2324ecbd6dmarkm	sin6->sin6_port = port;
2334ecbd6dmarkm	break;
2344ecbd6dmarkm    }
2354ecbd6dmarkm#endif
2364ecbd6dmarkm    default :
2374ecbd6dmarkm	errx (1, "unknown address family %d", sa->sa_family);
2384ecbd6dmarkm	break;
2394ecbd6dmarkm    }
2404ecbd6dmarkm}
2414ecbd6dmarkm
2424ecbd6dmarkm/*
2434ecbd6dmarkm * Enable debug on `sock'.
2444ecbd6dmarkm */
2454ecbd6dmarkm
2464ecbd6dmarkmvoid
2474ecbd6dmarkmsocket_set_debug (int sock)
2484ecbd6dmarkm{
2494ecbd6dmarkm    int on = 1;
2504ecbd6dmarkm
2514ecbd6dmarkm#if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT)
2524ecbd6dmarkm    if (setsockopt (sock, SOL_SOCKET, SO_DEBUG, (void *) &on, sizeof (on)) < 0)
2534ecbd6dmarkm	warn ("setsockopt SO_DEBUG (ignored)");
2544ecbd6dmarkm#endif
2554ecbd6dmarkm}
2564ecbd6dmarkm
2574ecbd6dmarkm/*
2584ecbd6dmarkm * Set the type-of-service of `sock' to `tos'.
2594ecbd6dmarkm */
2604ecbd6dmarkm
2614ecbd6dmarkmvoid
2624ecbd6dmarkmsocket_set_tos (int sock, int tos)
2634ecbd6dmarkm{
2644ecbd6dmarkm#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
2654ecbd6dmarkm    if (setsockopt (sock, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof (int)) < 0)
2664ecbd6dmarkm	warn ("setsockopt TOS (ignored)");
2674ecbd6dmarkm#endif
2684ecbd6dmarkm}
2694ecbd6dmarkm
2704ecbd6dmarkm/*
2714ecbd6dmarkm * set the reuse of addresses on `sock' to `val'.
2724ecbd6dmarkm */
2734ecbd6dmarkm
2744ecbd6dmarkmvoid
2754ecbd6dmarkmsocket_set_reuseaddr (int sock, int val)
2764ecbd6dmarkm{
2774ecbd6dmarkm#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT)
2784ecbd6dmarkm    if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val,
2794ecbd6dmarkm		  sizeof(val)) < 0)
2804ecbd6dmarkm	err (1, "setsockopt SO_REUSEADDR");
2814ecbd6dmarkm#endif
2824ecbd6dmarkm}
283