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 : #include <config.h>
35 :
36 : #include "roken.h"
37 : #include <err.h>
38 :
39 : /*
40 : * Set `sa' to the unitialized address of address family `af'
41 : */
42 :
43 : ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
44 : socket_set_any (struct sockaddr *sa, int af)
45 0 : {
46 0 : switch (af) {
47 : case AF_INET : {
48 0 : struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
49 :
50 0 : memset (sin4, 0, sizeof(*sin4));
51 0 : sin4->sin_family = AF_INET;
52 0 : sin4->sin_port = 0;
53 0 : sin4->sin_addr.s_addr = INADDR_ANY;
54 0 : break;
55 : }
56 : #ifdef HAVE_IPV6
57 : case AF_INET6 : {
58 0 : struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
59 :
60 0 : memset (sin6, 0, sizeof(*sin6));
61 0 : sin6->sin6_family = AF_INET6;
62 0 : sin6->sin6_port = 0;
63 0 : sin6->sin6_addr = in6addr_any;
64 0 : break;
65 : }
66 : #endif
67 : default :
68 0 : errx (1, "unknown address family %d", sa->sa_family);
69 : break;
70 : }
71 0 : }
72 :
73 : /*
74 : * set `sa' to (`ptr', `port')
75 : */
76 :
77 : ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
78 : socket_set_address_and_port (struct sockaddr *sa, const void *ptr, int port)
79 0 : {
80 0 : switch (sa->sa_family) {
81 : case AF_INET : {
82 0 : struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
83 :
84 0 : memset (sin4, 0, sizeof(*sin4));
85 0 : sin4->sin_family = AF_INET;
86 0 : sin4->sin_port = port;
87 0 : memcpy (&sin4->sin_addr, ptr, sizeof(struct in_addr));
88 0 : break;
89 : }
90 : #ifdef HAVE_IPV6
91 : case AF_INET6 : {
92 0 : struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
93 :
94 0 : memset (sin6, 0, sizeof(*sin6));
95 0 : sin6->sin6_family = AF_INET6;
96 0 : sin6->sin6_port = port;
97 0 : memcpy (&sin6->sin6_addr, ptr, sizeof(struct in6_addr));
98 0 : break;
99 : }
100 : #endif
101 : default :
102 0 : errx (1, "unknown address family %d", sa->sa_family);
103 : break;
104 : }
105 0 : }
106 :
107 : /*
108 : * Return the size of an address of the type in `sa'
109 : */
110 :
111 : ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL
112 : socket_addr_size (const struct sockaddr *sa)
113 0 : {
114 0 : switch (sa->sa_family) {
115 : case AF_INET :
116 0 : return sizeof(struct in_addr);
117 : #ifdef HAVE_IPV6
118 : case AF_INET6 :
119 0 : return sizeof(struct in6_addr);
120 : #endif
121 : default :
122 0 : errx (1, "unknown address family %d", sa->sa_family);
123 : UNREACHABLE(return 0);
124 : }
125 : }
126 :
127 : /*
128 : * Return the size of a `struct sockaddr' in `sa'.
129 : */
130 :
131 : ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL
132 : socket_sockaddr_size (const struct sockaddr *sa)
133 0 : {
134 0 : switch (sa->sa_family) {
135 : case AF_INET :
136 0 : return sizeof(struct sockaddr_in);
137 : #ifdef HAVE_IPV6
138 : case AF_INET6 :
139 0 : return sizeof(struct sockaddr_in6);
140 : #endif
141 : default :
142 0 : errx (1, "unknown address family %d", sa->sa_family);
143 : UNREACHABLE(return 0);
144 : }
145 : }
146 :
147 : /*
148 : * Return the binary address of `sa'.
149 : */
150 :
151 : ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL
152 : socket_get_address (const struct sockaddr *sa)
153 0 : {
154 0 : switch (sa->sa_family) {
155 : case AF_INET : {
156 0 : const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;
157 0 : return rk_UNCONST(&sin4->sin_addr);
158 : }
159 : #ifdef HAVE_IPV6
160 : case AF_INET6 : {
161 0 : const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
162 0 : return rk_UNCONST(&sin6->sin6_addr);
163 : }
164 : #endif
165 : default :
166 0 : errx (1, "unknown address family %d", sa->sa_family);
167 : UNREACHABLE(return NULL);
168 : }
169 : }
170 :
171 : /*
172 : * Return the port number from `sa'.
173 : */
174 :
175 : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
176 : socket_get_port (const struct sockaddr *sa)
177 0 : {
178 0 : switch (sa->sa_family) {
179 : case AF_INET : {
180 0 : const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;
181 0 : return sin4->sin_port;
182 : }
183 : #ifdef HAVE_IPV6
184 : case AF_INET6 : {
185 0 : const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
186 0 : return sin6->sin6_port;
187 : }
188 : #endif
189 : default :
190 0 : errx (1, "unknown address family %d", sa->sa_family);
191 : UNREACHABLE(return 0);
192 : }
193 : }
194 :
195 : /*
196 : * Set the port in `sa' to `port'.
197 : */
198 :
199 : ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
200 : socket_set_port (struct sockaddr *sa, int port)
201 0 : {
202 0 : switch (sa->sa_family) {
203 : case AF_INET : {
204 0 : struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
205 0 : sin4->sin_port = port;
206 0 : break;
207 : }
208 : #ifdef HAVE_IPV6
209 : case AF_INET6 : {
210 0 : struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
211 0 : sin6->sin6_port = port;
212 0 : break;
213 : }
214 : #endif
215 : default :
216 0 : errx (1, "unknown address family %d", sa->sa_family);
217 : break;
218 : }
219 0 : }
220 :
221 : /*
222 : * Set the range of ports to use when binding with port = 0.
223 : */
224 : ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
225 : socket_set_portrange (rk_socket_t sock, int restr, int af)
226 0 : {
227 : #if defined(IP_PORTRANGE)
228 : if (af == AF_INET) {
229 : int on = restr ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
230 : if (setsockopt (sock, IPPROTO_IP, IP_PORTRANGE, &on,
231 : sizeof(on)) < 0)
232 : warn ("setsockopt IP_PORTRANGE (ignored)");
233 : }
234 : #endif
235 : #if defined(IPV6_PORTRANGE)
236 : if (af == AF_INET6) {
237 : int on = restr ? IPV6_PORTRANGE_HIGH :
238 : IPV6_PORTRANGE_DEFAULT;
239 : if (setsockopt (sock, IPPROTO_IPV6, IPV6_PORTRANGE, &on,
240 : sizeof(on)) < 0)
241 : warn ("setsockopt IPV6_PORTRANGE (ignored)");
242 : }
243 : #endif
244 0 : }
245 :
246 : /*
247 : * Enable debug on `sock'.
248 : */
249 :
250 : ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
251 : socket_set_debug (rk_socket_t sock)
252 0 : {
253 : #if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT)
254 : int on = 1;
255 :
256 : if (setsockopt (sock, SOL_SOCKET, SO_DEBUG, (void *) &on, sizeof (on)) < 0)
257 : warn ("setsockopt SO_DEBUG (ignored)");
258 : #endif
259 0 : }
260 :
261 : /*
262 : * Set the type-of-service of `sock' to `tos'.
263 : */
264 :
265 : ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
266 : socket_set_tos (rk_socket_t sock, int tos)
267 0 : {
268 : #if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
269 : if (setsockopt (sock, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof (int)) < 0)
270 : if (errno != EINVAL)
271 : warn ("setsockopt TOS (ignored)");
272 : #endif
273 0 : }
274 :
275 : /*
276 : * set the reuse of addresses on `sock' to `val'.
277 : */
278 :
279 : ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
280 : socket_set_reuseaddr (rk_socket_t sock, int val)
281 0 : {
282 : #if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT)
283 : if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val,
284 : sizeof(val)) < 0)
285 : err (1, "setsockopt SO_REUSEADDR");
286 : #endif
287 0 : }
288 :
289 : /*
290 : * Set the that the `sock' should bind to only IPv6 addresses.
291 : */
292 :
293 : ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
294 : socket_set_ipv6only (rk_socket_t sock, int val)
295 0 : {
296 : #if defined(IPV6_V6ONLY) && defined(HAVE_SETSOCKOPT)
297 : setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&val, sizeof(val));
298 : #endif
299 0 : }
300 :
301 : /**
302 : * Create a file descriptor from a socket
303 : *
304 : * While the socket handle in \a sock can be used with WinSock
305 : * functions after calling socket_to_fd(), it should not be closed
306 : * with rk_closesocket(). The socket will be closed when the associated
307 : * file descriptor is closed.
308 : */
309 : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
310 : socket_to_fd(rk_socket_t sock, int flags)
311 0 : {
312 : #ifndef _WIN32
313 0 : return sock;
314 : #else
315 : return _open_osfhandle((intptr_t) sock, flags);
316 : #endif
317 : }
318 :
319 : #ifndef HEIMDAL_SMALLER
320 : #undef socket
321 :
322 : int rk_socket(int, int, int);
323 :
324 : int
325 : rk_socket(int domain, int type, int protocol)
326 0 : {
327 : int s;
328 0 : s = socket (domain, type, protocol);
329 : #ifdef SOCK_CLOEXEC
330 : if ((SOCK_CLOEXEC & type) && s < 0 && errno == EINVAL) {
331 : type &= ~SOCK_CLOEXEC;
332 : s = socket (domain, type, protocol);
333 : }
334 : #endif
335 0 : return s;
336 : }
337 :
338 : #endif /* HEIMDAL_SMALLER */
|