2 * Copyright (C) 2006-2009 Tobias Brunner
3 * Copyright (C) 2006 Daniel Roethlisberger
4 * Copyright (C) 2005-2010 Martin Willi
5 * Copyright (C) 2005 Jan Hutter
6 * Hochschule fuer Technik Rapperswil
7 * Copyright (C) 2010 revosec AG
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 /* for struct in6_pktinfo */
23 #include "socket_dynamic_socket.h"
25 #include <sys/types.h>
26 #include <sys/socket.h>
32 #include <sys/ioctl.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/in.h>
35 #include <netinet/ip.h>
36 #include <netinet/udp.h>
40 #include <threading/thread.h>
41 #include <utils/hashtable.h>
43 /* Maximum size of a packet */
44 #define MAX_PACKET 5000
46 /* length of non-esp marker */
47 #define MARKER_LEN sizeof(u_int32_t)
49 /* from linux/udp.h */
54 #ifndef UDP_ENCAP_ESPINUDP
55 #define UDP_ENCAP_ESPINUDP 2
56 #endif /*UDP_ENCAP_ESPINUDP*/
58 /* these are not defined on some platforms */
60 #define SOL_IP IPPROTO_IP
63 #define SOL_IPV6 IPPROTO_IPV6
66 #define SOL_UDP IPPROTO_UDP
69 /* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that
70 * previously defined IPV6_PKTINFO */
71 #ifndef IPV6_RECVPKTINFO
72 #define IPV6_RECVPKTINFO IPV6_PKTINFO
75 typedef struct private_socket_dynamic_socket_t private_socket_dynamic_socket_t
;
76 typedef struct dynsock_t dynsock_t
;
79 * Private data of an socket_t object
81 struct private_socket_dynamic_socket_t
{
86 socket_dynamic_socket_t
public;
89 * Hashtable of bound sockets
94 * Notification pipe to signal receiver
100 * Struct for a dynamically allocated socket
105 * File descriptor of socket
121 * Hash function for hashtable
123 static u_int
hash(dynsock_t
*key
)
125 return (key
->family
<< 16) | key
->port
;
129 * Equals function for hashtable
131 static bool equals(dynsock_t
*a
, dynsock_t
*b
)
133 return a
->family
== b
->family
&& a
->port
== b
->port
;
137 * Create a fd_set from all bound sockets
139 static int build_fds(private_socket_dynamic_socket_t
*this, fd_set
*fds
)
141 enumerator_t
*enumerator
;
142 dynsock_t
*key
, *value
;
146 FD_SET(this->notify
[0], fds
);
147 maxfd
= this->notify
[0];
149 enumerator
= this->sockets
->create_enumerator(this->sockets
);
150 while (enumerator
->enumerate(enumerator
, &key
, &value
))
152 FD_SET(value
->fd
, fds
);
153 maxfd
= max(maxfd
, value
->fd
);
155 enumerator
->destroy(enumerator
);
161 * Find the socket select()ed
163 static dynsock_t
* scan_fds(private_socket_dynamic_socket_t
*this, fd_set
*fds
)
165 enumerator_t
*enumerator
;
166 dynsock_t
*key
, *value
, *selected
= NULL
;
168 enumerator
= this->sockets
->create_enumerator(this->sockets
);
169 while (enumerator
->enumerate(enumerator
, &key
, &value
))
171 if (FD_ISSET(value
->fd
, fds
))
177 enumerator
->destroy(enumerator
);
182 * Receive a packet from a given socket fd
184 static packet_t
*receive_packet(private_socket_dynamic_socket_t
*this,
187 host_t
*source
= NULL
, *dest
= NULL
;
189 char buffer
[MAX_PACKET
];
193 struct cmsghdr
*cmsgptr
;
197 struct sockaddr_in in4
;
198 struct sockaddr_in6 in6
;
202 msg
.msg_namelen
= sizeof(src
);
203 iov
.iov_base
= buffer
;
204 iov
.iov_len
= sizeof(buffer
);
207 msg
.msg_control
= ancillary
;
208 msg
.msg_controllen
= sizeof(ancillary
);
210 len
= recvmsg(skt
->fd
, &msg
, 0);
213 DBG1(DBG_NET
, "error reading socket: %s", strerror(errno
));
216 DBG3(DBG_NET
, "received packet %b", buffer
, len
);
218 if (len
< MARKER_LEN
)
220 DBG3(DBG_NET
, "received packet too short (%d bytes)", len
);
224 /* read ancillary data to get destination address */
225 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
226 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
))
228 if (cmsgptr
->cmsg_len
== 0)
230 DBG1(DBG_NET
, "error reading ancillary data");
234 if (cmsgptr
->cmsg_level
== SOL_IPV6
&&
235 cmsgptr
->cmsg_type
== IPV6_PKTINFO
)
237 struct in6_pktinfo
*pktinfo
;
238 struct sockaddr_in6 dst
;
240 pktinfo
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
241 memset(&dst
, 0, sizeof(dst
));
242 memcpy(&dst
.sin6_addr
, &pktinfo
->ipi6_addr
, sizeof(dst
.sin6_addr
));
243 dst
.sin6_family
= AF_INET6
;
244 dst
.sin6_port
= htons(skt
->port
);
245 dest
= host_create_from_sockaddr((sockaddr_t
*)&dst
);
247 if (cmsgptr
->cmsg_level
== SOL_IP
&&
248 cmsgptr
->cmsg_type
== IP_PKTINFO
)
250 struct in_pktinfo
*pktinfo
;
251 struct sockaddr_in dst
;
253 pktinfo
= (struct in_pktinfo
*)CMSG_DATA(cmsgptr
);
254 memset(&dst
, 0, sizeof(dst
));
255 memcpy(&dst
.sin_addr
, &pktinfo
->ipi_addr
, sizeof(dst
.sin_addr
));
257 dst
.sin_family
= AF_INET
;
258 dst
.sin_port
= htons(skt
->port
);
259 dest
= host_create_from_sockaddr((sockaddr_t
*)&dst
);
268 DBG1(DBG_NET
, "error reading IP header");
271 source
= host_create_from_sockaddr((sockaddr_t
*)&src
);
272 DBG2(DBG_NET
, "received packet: from %#H to %#H", source
, dest
);
273 data
= chunk_create(buffer
, len
);
275 packet
= packet_create();
276 packet
->set_source(packet
, source
);
277 packet
->set_destination(packet
, dest
);
278 /* we assume a non-ESP marker if none of the ports is on 500 */
279 if (dest
->get_port(dest
) != IKEV2_UDP_PORT
&&
280 source
->get_port(source
) != IKEV2_UDP_PORT
)
282 data
= chunk_skip(data
, MARKER_LEN
);
284 packet
->set_data(packet
, chunk_clone(data
));
288 METHOD(socket_t
, receiver
, status_t
,
289 private_socket_dynamic_socket_t
*this, packet_t
**packet
)
299 maxfd
= build_fds(this, &fds
);
301 DBG2(DBG_NET
, "waiting for data on sockets");
302 oldstate
= thread_cancelability(TRUE
);
303 if (select(maxfd
, &fds
, NULL
, NULL
, NULL
) <= 0)
305 thread_cancelability(oldstate
);
308 thread_cancelability(oldstate
);
310 if (FD_ISSET(this->notify
[0], &fds
))
311 { /* got notified, read garbage, rebuild fdset */
314 ignore_result(read(this->notify
[0], buf
, sizeof(buf
)));
315 DBG2(DBG_NET
, "rebuilding fdset due to newly bound ports");
318 selected
= scan_fds(this, &fds
);
324 pkt
= receive_packet(this, selected
);
334 * open a socket to send and receive packets
336 static int open_socket(private_socket_dynamic_socket_t
*this,
337 int family
, u_int16_t port
, bool first
)
339 int on
= TRUE
, type
= UDP_ENCAP_ESPINUDP
;
340 struct sockaddr_storage addr
;
342 u_int sol
, pktinfo
= 0;
345 memset(&addr
, 0, sizeof(addr
));
346 /* precalculate constants depending on address family */
351 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&addr
;
352 sin
->sin_family
= AF_INET
;
353 sin
->sin_addr
.s_addr
= INADDR_ANY
;
354 sin
->sin_port
= htons(port
);
355 addrlen
= sizeof(struct sockaddr_in
);
357 pktinfo
= IP_PKTINFO
;
362 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)&addr
;
363 sin6
->sin6_family
= AF_INET6
;
364 memset(&sin6
->sin6_addr
, 0, sizeof(sin6
->sin6_addr
));
365 sin6
->sin6_port
= htons(port
);
366 addrlen
= sizeof(struct sockaddr_in6
);
368 pktinfo
= IPV6_RECVPKTINFO
;
375 fd
= socket(family
, SOCK_DGRAM
, IPPROTO_UDP
);
378 DBG1(DBG_NET
, "could not open socket: %s", strerror(errno
));
381 if (setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, (void*)&on
, sizeof(on
)) < 0)
383 DBG1(DBG_NET
, "unable to set SO_REUSEADDR on socket: %s", strerror(errno
));
388 /* bind the socket */
389 if (bind(fd
, (struct sockaddr
*)&addr
, addrlen
) < 0)
391 DBG1(DBG_NET
, "unable to bind socket: %s", strerror(errno
));
396 /* get additional packet info on receive */
397 if (setsockopt(fd
, sol
, pktinfo
, &on
, sizeof(on
)) < 0)
399 DBG1(DBG_NET
, "unable to set IP_PKTINFO on socket: %s", strerror(errno
));
404 if (!charon
->kernel_interface
->bypass_socket(charon
->kernel_interface
,
407 DBG1(DBG_NET
, "installing IKE bypass policy failed");
410 /* enable UDP decapsulation globally, only for one socket needed */
411 if (first
&& setsockopt(fd
, SOL_UDP
, UDP_ENCAP
, &type
, sizeof(type
)) < 0)
413 DBG1(DBG_NET
, "unable to set UDP_ENCAP: %s", strerror(errno
));
419 * Find/Create a socket to send from host
421 static dynsock_t
*find_socket(private_socket_dynamic_socket_t
*this,
422 int family
, u_int16_t port
)
424 dynsock_t
*skt
, lookup
= {
431 skt
= this->sockets
->get(this->sockets
, &lookup
);
436 fd
= open_socket(this, family
, port
,
437 this->sockets
->get_count(this->sockets
));
447 this->sockets
->put(this->sockets
, skt
, skt
);
448 /* notify receiver thread to reread socket list */
449 ignore_result(write(this->notify
[1], buf
, sizeof(buf
)));
454 METHOD(socket_t
, sender
, status_t
,
455 private_socket_dynamic_socket_t
*this, packet_t
*packet
)
461 chunk_t data
, marked
;
463 struct cmsghdr
*cmsg
;
466 src
= packet
->get_source(packet
);
467 dst
= packet
->get_destination(packet
);
468 family
= src
->get_family(src
);
469 port
= src
->get_port(src
);
470 skt
= find_socket(this, family
, port
);
476 data
= packet
->get_data(packet
);
477 DBG2(DBG_NET
, "sending packet: from %#H to %#H", src
, dst
);
479 /* use non-ESP marker if none of the ports is 500, not for keep alives */
480 if (port
!= IKEV2_UDP_PORT
&& dst
->get_port(dst
) != IKEV2_UDP_PORT
&&
481 !(data
.len
== 1 && data
.ptr
[0] == 0xFF))
483 /* add non esp marker to packet */
484 if (data
.len
> MAX_PACKET
- MARKER_LEN
)
486 DBG1(DBG_NET
, "unable to send packet: it's too big (%d bytes)",
490 marked
= chunk_alloc(data
.len
+ MARKER_LEN
);
491 memset(marked
.ptr
, 0, MARKER_LEN
);
492 memcpy(marked
.ptr
+ MARKER_LEN
, data
.ptr
, data
.len
);
493 /* let the packet do the clean up for us */
494 packet
->set_data(packet
, marked
);
498 memset(&msg
, 0, sizeof(struct msghdr
));
499 msg
.msg_name
= dst
->get_sockaddr(dst
);;
500 msg
.msg_namelen
= *dst
->get_sockaddr_len(dst
);
501 iov
.iov_base
= data
.ptr
;
502 iov
.iov_len
= data
.len
;
507 if (!src
->is_anyaddr(src
))
509 if (family
== AF_INET
)
511 struct in_addr
*addr
;
512 struct sockaddr_in
*sin
;
513 char buf
[CMSG_SPACE(sizeof(struct in_pktinfo
))];
514 struct in_pktinfo
*pktinfo
;
516 msg
.msg_control
= buf
;
517 msg
.msg_controllen
= sizeof(buf
);
518 cmsg
= CMSG_FIRSTHDR(&msg
);
519 cmsg
->cmsg_level
= SOL_IP
;
520 cmsg
->cmsg_type
= IP_PKTINFO
;
521 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct in_pktinfo
));
522 pktinfo
= (struct in_pktinfo
*)CMSG_DATA(cmsg
);
523 memset(pktinfo
, 0, sizeof(struct in_pktinfo
));
524 addr
= &pktinfo
->ipi_spec_dst
;
525 sin
= (struct sockaddr_in
*)src
->get_sockaddr(src
);
526 memcpy(addr
, &sin
->sin_addr
, sizeof(struct in_addr
));
530 char buf
[CMSG_SPACE(sizeof(struct in6_pktinfo
))];
531 struct in6_pktinfo
*pktinfo
;
532 struct sockaddr_in6
*sin
;
534 msg
.msg_control
= buf
;
535 msg
.msg_controllen
= sizeof(buf
);
536 cmsg
= CMSG_FIRSTHDR(&msg
);
537 cmsg
->cmsg_level
= SOL_IPV6
;
538 cmsg
->cmsg_type
= IPV6_PKTINFO
;
539 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
540 pktinfo
= (struct in6_pktinfo
*)CMSG_DATA(cmsg
);
541 memset(pktinfo
, 0, sizeof(struct in6_pktinfo
));
542 sin
= (struct sockaddr_in6
*)src
->get_sockaddr(src
);
543 memcpy(&pktinfo
->ipi6_addr
, &sin
->sin6_addr
, sizeof(struct in6_addr
));
547 len
= sendmsg(skt
->fd
, &msg
, 0);
550 DBG1(DBG_NET
, "error writing to socket: %s", strerror(errno
));
556 METHOD(socket_dynamic_socket_t
, destroy
, void,
557 private_socket_dynamic_socket_t
*this)
559 enumerator_t
*enumerator
;
560 dynsock_t
*key
, *value
;
562 enumerator
= this->sockets
->create_enumerator(this->sockets
);
563 while (enumerator
->enumerate(enumerator
, &key
, &value
))
568 enumerator
->destroy(enumerator
);
569 this->sockets
->destroy(this->sockets
);
571 close(this->notify
[0]);
572 close(this->notify
[1]);
577 * See header for description
579 socket_dynamic_socket_t
*socket_dynamic_socket_create()
581 private_socket_dynamic_socket_t
*this;
587 .receive
= _receiver
,
593 if (pipe(this->notify
) != 0)
595 DBG1(DBG_NET
, "creating notify pipe for dynamic socket failed");
600 this->sockets
= hashtable_create((void*)hash
, (void*)equals
, 8);
602 return &this->public;