2 * Copyright (C) 2006-2013 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
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 /* for struct in6_pktinfo */
23 #define __EXTENSIONS__
25 /* make sure to use the proper defs on Mac OS X */
26 #define __APPLE_USE_RFC_3542
28 #include "socket_default_socket.h"
30 #include <sys/types.h>
31 #include <sys/socket.h>
37 #include <sys/ioctl.h>
38 #include <netinet/in_systm.h>
39 #include <netinet/in.h>
40 #include <netinet/ip.h>
41 #include <netinet/udp.h>
46 #include <threading/thread.h>
48 /* Maximum size of a packet */
49 #define MAX_PACKET 10000
51 /* these are not defined on some platforms */
53 #define SOL_IP IPPROTO_IP
56 #define SOL_IPV6 IPPROTO_IPV6
59 #define IPV6_TCLASS 67
62 /* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that
63 * previously defined IPV6_PKTINFO */
64 #ifndef IPV6_RECVPKTINFO
65 #define IPV6_RECVPKTINFO IPV6_PKTINFO
68 #ifndef IN6ADDR_ANY_INIT
69 #define IN6ADDR_ANY_INIT {{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}
72 #ifndef HAVE_IN6ADDR_ANY
73 static const struct in6_addr in6addr_any
= IN6ADDR_ANY_INIT
;
76 typedef struct private_socket_default_socket_t private_socket_default_socket_t
;
79 * Private data of an socket_t object
81 struct private_socket_default_socket_t
{
86 socket_default_socket_t
public;
89 * Configured port (or random, if initially 0)
94 * Configured port for NAT-T (or random, if initially 0)
99 * IPv4 socket (500 or port)
104 * IPv4 socket for NAT-T (4500 or natt)
109 * IPv6 socket (500 or port)
114 * IPv6 socket for NAT-T (4500 or natt)
119 * DSCP value set on IPv4 socket
124 * DSCP value set on IPv4 socket for NAT-T (4500 or natt)
129 * DSCP value set on IPv6 socket (500 or port)
134 * DSCP value set on IPv6 socket for NAT-T (4500 or natt)
139 * Maximum packet size to receive
144 * TRUE if the source address should be set on outbound packets
149 METHOD(socket_t
, receiver
, status_t
,
150 private_socket_default_socket_t
*this, packet_t
**packet
)
152 char buffer
[this->max_packet
];
155 host_t
*source
= NULL
, *dest
= NULL
;
160 int max_fd
= 0, selected
= 0;
165 if (this->ipv4
!= -1)
167 FD_SET(this->ipv4
, &rfds
);
168 max_fd
= max(max_fd
, this->ipv4
);
170 if (this->ipv4_natt
!= -1)
172 FD_SET(this->ipv4_natt
, &rfds
);
173 max_fd
= max(max_fd
, this->ipv4_natt
);
175 if (this->ipv6
!= -1)
177 FD_SET(this->ipv6
, &rfds
);
178 max_fd
= max(max_fd
, this->ipv6
);
180 if (this->ipv6_natt
!= -1)
182 FD_SET(this->ipv6_natt
, &rfds
);
183 max_fd
= max(max_fd
, this->ipv6_natt
);
186 DBG2(DBG_NET
, "waiting for data on sockets");
187 oldstate
= thread_cancelability(TRUE
);
188 if (select(max_fd
+ 1, &rfds
, NULL
, NULL
, NULL
) <= 0)
190 thread_cancelability(oldstate
);
193 thread_cancelability(oldstate
);
195 if (this->ipv4
!= -1 && FD_ISSET(this->ipv4
, &rfds
))
198 selected
= this->ipv4
;
200 if (this->ipv4_natt
!= -1 && FD_ISSET(this->ipv4_natt
, &rfds
))
203 selected
= this->ipv4_natt
;
205 if (this->ipv6
!= -1 && FD_ISSET(this->ipv6
, &rfds
))
208 selected
= this->ipv6
;
210 if (this->ipv6_natt
!= -1 && FD_ISSET(this->ipv6_natt
, &rfds
))
213 selected
= this->ipv6_natt
;
218 struct cmsghdr
*cmsgptr
;
222 struct sockaddr_in in4
;
223 struct sockaddr_in6 in6
;
227 msg
.msg_namelen
= sizeof(src
);
228 iov
.iov_base
= buffer
;
229 iov
.iov_len
= this->max_packet
;
232 msg
.msg_control
= ancillary
;
233 msg
.msg_controllen
= sizeof(ancillary
);
235 bytes_read
= recvmsg(selected
, &msg
, 0);
238 DBG1(DBG_NET
, "error reading socket: %s", strerror(errno
));
241 if (msg
.msg_flags
& MSG_TRUNC
)
243 DBG1(DBG_NET
, "receive buffer too small, packet discarded");
246 DBG3(DBG_NET
, "received packet %b", buffer
, bytes_read
);
248 /* read ancillary data to get destination address */
249 for (cmsgptr
= CMSG_FIRSTHDR(&msg
); cmsgptr
!= NULL
;
250 cmsgptr
= CMSG_NXTHDR(&msg
, cmsgptr
))
252 if (cmsgptr
->cmsg_len
== 0)
254 DBG1(DBG_NET
, "error reading ancillary data");
258 #ifdef HAVE_IN6_PKTINFO
259 if (cmsgptr
->cmsg_level
== SOL_IPV6
&&
260 cmsgptr
->cmsg_type
== IPV6_PKTINFO
)
262 struct in6_pktinfo
*pktinfo
;
263 pktinfo
= (struct in6_pktinfo
*)CMSG_DATA(cmsgptr
);
264 struct sockaddr_in6 dst
;
266 memset(&dst
, 0, sizeof(dst
));
267 memcpy(&dst
.sin6_addr
, &pktinfo
->ipi6_addr
, sizeof(dst
.sin6_addr
));
268 dst
.sin6_family
= AF_INET6
;
269 dst
.sin6_port
= htons(port
);
270 dest
= host_create_from_sockaddr((sockaddr_t
*)&dst
);
272 #endif /* HAVE_IN6_PKTINFO */
273 if (cmsgptr
->cmsg_level
== SOL_IP
&&
275 cmsgptr
->cmsg_type
== IP_PKTINFO
276 #elif defined(IP_RECVDSTADDR)
277 cmsgptr
->cmsg_type
== IP_RECVDSTADDR
283 struct in_addr
*addr
;
284 struct sockaddr_in dst
;
287 struct in_pktinfo
*pktinfo
;
288 pktinfo
= (struct in_pktinfo
*)CMSG_DATA(cmsgptr
);
289 addr
= &pktinfo
->ipi_addr
;
290 #elif defined(IP_RECVDSTADDR)
291 addr
= (struct in_addr
*)CMSG_DATA(cmsgptr
);
293 memset(&dst
, 0, sizeof(dst
));
294 memcpy(&dst
.sin_addr
, addr
, sizeof(dst
.sin_addr
));
296 dst
.sin_family
= AF_INET
;
297 dst
.sin_port
= htons(port
);
298 dest
= host_create_from_sockaddr((sockaddr_t
*)&dst
);
307 DBG1(DBG_NET
, "error reading IP header");
310 source
= host_create_from_sockaddr((sockaddr_t
*)&src
);
312 pkt
= packet_create();
313 pkt
->set_source(pkt
, source
);
314 pkt
->set_destination(pkt
, dest
);
315 DBG2(DBG_NET
, "received packet: from %#H to %#H", source
, dest
);
316 data
= chunk_create(buffer
, bytes_read
);
317 pkt
->set_data(pkt
, chunk_clone(data
));
321 /* oops, shouldn't happen */
329 METHOD(socket_t
, sender
, status_t
,
330 private_socket_default_socket_t
*this, packet_t
*packet
)
332 int sport
, skt
= -1, family
;
337 struct cmsghdr
*cmsg
;
341 src
= packet
->get_source(packet
);
342 dst
= packet
->get_destination(packet
);
343 data
= packet
->get_data(packet
);
345 DBG2(DBG_NET
, "sending packet: from %#H to %#H", src
, dst
);
348 sport
= src
->get_port(src
);
349 family
= dst
->get_family(dst
);
350 if (sport
== 0 || sport
== this->port
)
366 else if (sport
== this->natt
)
371 skt
= this->ipv4_natt
;
372 dscp
= &this->dscp4_natt
;
375 skt
= this->ipv6_natt
;
376 dscp
= &this->dscp6_natt
;
384 DBG1(DBG_NET
, "no socket found to send IPv%d packet from port %d",
385 family
== AF_INET ?
4 : 6, sport
);
389 /* setting DSCP values per-packet in a cmsg seems not to be supported
390 * on Linux. We instead setsockopt() before sending it, this should be
391 * safe as only a single thread calls send(). */
392 if (*dscp
!= packet
->get_dscp(packet
))
394 if (family
== AF_INET
)
398 ds4
= packet
->get_dscp(packet
) << 2;
399 if (setsockopt(skt
, SOL_IP
, IP_TOS
, &ds4
, sizeof(ds4
)) == 0)
401 *dscp
= packet
->get_dscp(packet
);
405 DBG1(DBG_NET
, "unable to set IP_TOS on socket: %s",
413 ds6
= packet
->get_dscp(packet
) << 2;
414 if (setsockopt(skt
, SOL_IPV6
, IPV6_TCLASS
, &ds6
, sizeof(ds6
)) == 0)
416 *dscp
= packet
->get_dscp(packet
);
420 DBG1(DBG_NET
, "unable to set IPV6_TCLASS on socket: %s",
426 memset(&msg
, 0, sizeof(struct msghdr
));
427 msg
.msg_name
= dst
->get_sockaddr(dst
);;
428 msg
.msg_namelen
= *dst
->get_sockaddr_len(dst
);
429 iov
.iov_base
= data
.ptr
;
430 iov
.iov_len
= data
.len
;
435 if (this->set_source
&& !src
->is_anyaddr(src
))
437 if (family
== AF_INET
)
439 #if defined(IP_PKTINFO) || defined(IP_SENDSRCADDR)
440 struct in_addr
*addr
;
441 struct sockaddr_in
*sin
;
443 char buf
[CMSG_SPACE(sizeof(struct in_pktinfo
))];
444 struct in_pktinfo
*pktinfo
;
445 #elif defined(IP_SENDSRCADDR)
446 char buf
[CMSG_SPACE(sizeof(struct in_addr
))];
448 msg
.msg_control
= buf
;
449 msg
.msg_controllen
= sizeof(buf
);
450 cmsg
= CMSG_FIRSTHDR(&msg
);
451 cmsg
->cmsg_level
= SOL_IP
;
453 cmsg
->cmsg_type
= IP_PKTINFO
;
454 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct in_pktinfo
));
455 pktinfo
= (struct in_pktinfo
*)CMSG_DATA(cmsg
);
456 memset(pktinfo
, 0, sizeof(struct in_pktinfo
));
457 addr
= &pktinfo
->ipi_spec_dst
;
458 #elif defined(IP_SENDSRCADDR)
459 cmsg
->cmsg_type
= IP_SENDSRCADDR
;
460 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct in_addr
));
461 addr
= (struct in_addr
*)CMSG_DATA(cmsg
);
463 sin
= (struct sockaddr_in
*)src
->get_sockaddr(src
);
464 memcpy(addr
, &sin
->sin_addr
, sizeof(struct in_addr
));
465 #endif /* IP_PKTINFO || IP_SENDSRCADDR */
467 #ifdef HAVE_IN6_PKTINFO
470 char buf
[CMSG_SPACE(sizeof(struct in6_pktinfo
))];
471 struct in6_pktinfo
*pktinfo
;
472 struct sockaddr_in6
*sin
;
474 msg
.msg_control
= buf
;
475 msg
.msg_controllen
= sizeof(buf
);
476 cmsg
= CMSG_FIRSTHDR(&msg
);
477 cmsg
->cmsg_level
= SOL_IPV6
;
478 cmsg
->cmsg_type
= IPV6_PKTINFO
;
479 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct in6_pktinfo
));
480 pktinfo
= (struct in6_pktinfo
*)CMSG_DATA(cmsg
);
481 memset(pktinfo
, 0, sizeof(struct in6_pktinfo
));
482 sin
= (struct sockaddr_in6
*)src
->get_sockaddr(src
);
483 memcpy(&pktinfo
->ipi6_addr
, &sin
->sin6_addr
, sizeof(struct in6_addr
));
485 #endif /* HAVE_IN6_PKTINFO */
488 bytes_sent
= sendmsg(skt
, &msg
, 0);
490 if (bytes_sent
!= data
.len
)
492 DBG1(DBG_NET
, "error writing to socket: %s", strerror(errno
));
498 METHOD(socket_t
, get_port
, u_int16_t
,
499 private_socket_default_socket_t
*this, bool nat_t
)
501 return nat_t ?
this->natt
: this->port
;
504 METHOD(socket_t
, supported_families
, socket_family_t
,
505 private_socket_default_socket_t
*this)
507 socket_family_t families
= SOCKET_FAMILY_NONE
;
509 if (this->ipv4
!= -1 || this->ipv4_natt
!= -1)
511 families
|= SOCKET_FAMILY_IPV4
;
513 if (this->ipv6
!= -1 || this->ipv6_natt
!= -1)
515 families
|= SOCKET_FAMILY_IPV6
;
521 * open a socket to send and receive packets
523 static int open_socket(private_socket_default_socket_t
*this,
524 int family
, u_int16_t
*port
)
528 struct sockaddr sockaddr
;
529 struct sockaddr_in sin
;
530 struct sockaddr_in6 sin6
;
533 u_int sol
, pktinfo
= 0;
536 memset(&addr
, 0, sizeof(addr
));
537 addr
.sockaddr
.sa_family
= family
;
538 /* precalculate constants depending on address family */
542 addr
.sin
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
543 addr
.sin
.sin_port
= htons(*port
);
544 addrlen
= sizeof(addr
.sin
);
547 pktinfo
= IP_PKTINFO
;
548 #elif defined(IP_RECVDSTADDR)
549 pktinfo
= IP_RECVDSTADDR
;
553 memcpy(&addr
.sin6
.sin6_addr
, &in6addr_any
, sizeof(in6addr_any
));
554 addr
.sin6
.sin6_port
= htons(*port
);
555 addrlen
= sizeof(addr
.sin6
);
557 pktinfo
= IPV6_RECVPKTINFO
;
563 skt
= socket(family
, SOCK_DGRAM
, IPPROTO_UDP
);
566 DBG1(DBG_NET
, "could not open socket: %s", strerror(errno
));
569 if (setsockopt(skt
, SOL_SOCKET
, SO_REUSEADDR
, (void*)&on
, sizeof(on
)) < 0)
571 DBG1(DBG_NET
, "unable to set SO_REUSEADDR on socket: %s", strerror(errno
));
576 /* bind the socket */
577 if (bind(skt
, &addr
.sockaddr
, addrlen
) < 0)
579 DBG1(DBG_NET
, "unable to bind socket: %s", strerror(errno
));
584 /* retrieve randomly allocated port if needed */
587 if (getsockname(skt
, &addr
.sockaddr
, &addrlen
) < 0)
589 DBG1(DBG_NET
, "unable to determine port: %s", strerror(errno
));
596 *port
= ntohs(addr
.sin
.sin_port
);
599 *port
= ntohs(addr
.sin6
.sin6_port
);
604 /* get additional packet info on receive */
607 if (setsockopt(skt
, sol
, pktinfo
, &on
, sizeof(on
)) < 0)
609 DBG1(DBG_NET
, "unable to set IP_PKTINFO on socket: %s", strerror(errno
));
615 if (!hydra
->kernel_interface
->bypass_socket(hydra
->kernel_interface
,
618 DBG1(DBG_NET
, "installing IKE bypass policy failed");
621 /* enable UDP decapsulation for NAT-T sockets */
622 if (port
== &this->natt
&&
623 !hydra
->kernel_interface
->enable_udp_decap(hydra
->kernel_interface
,
624 skt
, family
, this->natt
))
626 DBG1(DBG_NET
, "enabling UDP decapsulation for %s on port %d failed",
627 family
== AF_INET ?
"IPv4" : "IPv6", this->natt
);
634 * Open a socket pair (normal and NAT traversal) for a given address family
636 static void open_socketpair(private_socket_default_socket_t
*this, int family
,
637 int *skt
, int *skt_natt
, char *label
)
639 *skt
= open_socket(this, family
, &this->port
);
643 DBG1(DBG_NET
, "could not open %s socket, %s disabled", label
, label
);
647 *skt_natt
= open_socket(this, family
, &this->natt
);
650 DBG1(DBG_NET
, "could not open %s NAT-T socket", label
);
655 METHOD(socket_t
, destroy
, void,
656 private_socket_default_socket_t
*this)
658 if (this->ipv4
!= -1)
662 if (this->ipv4_natt
!= -1)
664 close(this->ipv4_natt
);
666 if (this->ipv6
!= -1)
670 if (this->ipv6_natt
!= -1)
672 close(this->ipv6_natt
);
678 * See header for description
680 socket_default_socket_t
*socket_default_socket_create()
682 private_socket_default_socket_t
*this;
688 .receive
= _receiver
,
689 .get_port
= _get_port
,
690 .supported_families
= _supported_families
,
694 .port
= lib
->settings
->get_int(lib
->settings
,
695 "%s.port", CHARON_UDP_PORT
, charon
->name
),
696 .natt
= lib
->settings
->get_int(lib
->settings
,
697 "%s.port_nat_t", CHARON_NATT_PORT
, charon
->name
),
698 .max_packet
= lib
->settings
->get_int(lib
->settings
,
699 "%s.max_packet", MAX_PACKET
, charon
->name
),
700 .set_source
= lib
->settings
->get_bool(lib
->settings
,
701 "%s.plugins.socket-default.set_source", TRUE
,
705 if (this->port
&& this->port
== this->natt
)
707 DBG1(DBG_NET
, "IKE ports can't be equal, will allocate NAT-T "
712 if ((this->port
&& this->port
< 1024) || (this->natt
&& this->natt
< 1024))
714 if (!lib
->caps
->keep(lib
->caps
, CAP_NET_BIND_SERVICE
))
716 /* required to bind ports < 1024 */
717 DBG1(DBG_NET
, "socket-default plugin requires CAP_NET_BIND_SERVICE "
724 /* we allocate IPv6 sockets first as that will reserve randomly allocated
725 * ports also for IPv4. On OS X, we have to do it the other way round
726 * for the same effect. */
728 open_socketpair(this, AF_INET
, &this->ipv4
, &this->ipv4_natt
, "IPv4");
729 open_socketpair(this, AF_INET6
, &this->ipv6
, &this->ipv6_natt
, "IPv6");
730 #else /* !__APPLE__ */
731 open_socketpair(this, AF_INET6
, &this->ipv6
, &this->ipv6_natt
, "IPv6");
732 open_socketpair(this, AF_INET
, &this->ipv4
, &this->ipv4_natt
, "IPv4");
733 #endif /* __APPLE__ */
735 if (this->ipv4
== -1 && this->ipv6
== -1)
737 DBG1(DBG_NET
, "could not create any sockets");
742 return &this->public;