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