libhydra: Move kernel interface to libcharon
[strongswan.git] / src / libcharon / plugins / socket_default / socket_default_socket.c
1 /*
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
7 *
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>.
12 *
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
16 * for more details.
17 */
18
19 /* for struct in6_pktinfo */
20 #define _GNU_SOURCE
21 #ifdef __sun
22 #define _XPG4_2
23 #define __EXTENSIONS__
24 #endif
25 /* make sure to use the proper defs on Mac OS X */
26 #define __APPLE_USE_RFC_3542
27
28 #include "socket_default_socket.h"
29
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <stdlib.h>
36 #include <fcntl.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>
42 #include <net/if.h>
43
44 #include <daemon.h>
45 #include <threading/thread.h>
46
47 /* these are not defined on some platforms */
48 #ifndef SOL_IP
49 #define SOL_IP IPPROTO_IP
50 #endif
51 #ifndef SOL_IPV6
52 #define SOL_IPV6 IPPROTO_IPV6
53 #endif
54 #ifndef IPV6_TCLASS
55 #define IPV6_TCLASS 67
56 #endif
57
58 /* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that
59 * previously defined IPV6_PKTINFO */
60 #ifndef IPV6_RECVPKTINFO
61 #define IPV6_RECVPKTINFO IPV6_PKTINFO
62 #endif
63
64 #ifndef IN6ADDR_ANY_INIT
65 #define IN6ADDR_ANY_INIT {{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}
66 #endif
67
68 #ifndef HAVE_IN6ADDR_ANY
69 static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
70 #endif
71
72 typedef struct private_socket_default_socket_t private_socket_default_socket_t;
73
74 /**
75 * Private data of an socket_t object
76 */
77 struct private_socket_default_socket_t {
78
79 /**
80 * public functions
81 */
82 socket_default_socket_t public;
83
84 /**
85 * Configured port (or random, if initially 0)
86 */
87 u_int16_t port;
88
89 /**
90 * Configured port for NAT-T (or random, if initially 0)
91 */
92 u_int16_t natt;
93
94 /**
95 * IPv4 socket (500 or port)
96 */
97 int ipv4;
98
99 /**
100 * IPv4 socket for NAT-T (4500 or natt)
101 */
102 int ipv4_natt;
103
104 /**
105 * IPv6 socket (500 or port)
106 */
107 int ipv6;
108
109 /**
110 * IPv6 socket for NAT-T (4500 or natt)
111 */
112 int ipv6_natt;
113
114 /**
115 * DSCP value set on IPv4 socket
116 */
117 u_int8_t dscp4;
118
119 /**
120 * DSCP value set on IPv4 socket for NAT-T (4500 or natt)
121 */
122 u_int8_t dscp4_natt;
123
124 /**
125 * DSCP value set on IPv6 socket (500 or port)
126 */
127 u_int8_t dscp6;
128
129 /**
130 * DSCP value set on IPv6 socket for NAT-T (4500 or natt)
131 */
132 u_int8_t dscp6_natt;
133
134 /**
135 * Maximum packet size to receive
136 */
137 int max_packet;
138
139 /**
140 * TRUE if the source address should be set on outbound packets
141 */
142 bool set_source;
143
144 /**
145 * A counter to implement round-robin selection of read sockets
146 */
147 u_int rr_counter;
148 };
149
150 /**
151 * Get the destination IPv4 address of a received packet, depending on the
152 * available mechanism.
153 */
154 #ifdef IP_PKTINFO
155
156 static host_t *get_dst_v4(struct cmsghdr *cmsgptr, u_int16_t port)
157 {
158 struct sockaddr_in dst = {
159 .sin_family = AF_INET,
160 .sin_port = htons(port),
161 };
162 struct in_pktinfo *pktinfo;
163 struct in_addr *addr;
164
165 if (cmsgptr->cmsg_type == IP_PKTINFO)
166 {
167 pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsgptr);
168 addr = &pktinfo->ipi_addr;
169 memcpy(&dst.sin_addr, addr, sizeof(dst.sin_addr));
170 return host_create_from_sockaddr((sockaddr_t*)&dst);
171 }
172 return NULL;
173 }
174
175 #elif defined(IP_RECVDSTADDR)
176
177 static host_t *get_dst_v4(struct cmsghdr *cmsgptr, u_int16_t port)
178 {
179 struct sockaddr_in dst = {
180 .sin_family = AF_INET,
181 .sin_port = htons(port),
182 };
183 struct in_addr *addr;
184
185 if (cmsgptr->cmsg_type == IP_RECVDSTADDR)
186 {
187 addr = (struct in_addr*)CMSG_DATA(cmsgptr);
188 memcpy(&dst.sin_addr, addr, sizeof(dst.sin_addr));
189 return host_create_from_sockaddr((sockaddr_t*)&dst);
190 }
191 return NULL;
192 }
193
194 #else /* IP_PKTINFO || IP_RECVDSTADDR */
195
196 static host_t *get_dst_v4(struct cmsghdr *cmsgptr, u_int16_t port)
197 {
198 return NULL;
199 }
200
201 #endif /* IP_PKTINFO || IP_RECVDSTADDR */
202
203 /**
204 * Get the destination IPv6 address of a received packet, depending on the
205 * available mechanism.
206 */
207 #ifdef HAVE_IN6_PKTINFO
208
209 static host_t *get_dst_v6(struct cmsghdr *cmsgptr, u_int16_t port)
210 {
211 struct in6_pktinfo *pktinfo;
212 struct sockaddr_in6 dst = {
213 .sin6_family = AF_INET6,
214 .sin6_port = htons(port),
215 };
216
217 if (cmsgptr->cmsg_type == IPV6_PKTINFO)
218 {
219 pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsgptr);
220 memcpy(&dst.sin6_addr, &pktinfo->ipi6_addr, sizeof(dst.sin6_addr));
221 return host_create_from_sockaddr((sockaddr_t*)&dst);
222 }
223 return NULL;
224 }
225
226 #else /* HAVE_IN6_PKTINFO */
227
228 static host_t *get_dst_v6(struct cmsghdr *cmsgptr, u_int16_t port)
229 {
230 return NULL;
231 }
232
233 #endif /* HAVE_IN6_PKTINFO */
234
235 METHOD(socket_t, receiver, status_t,
236 private_socket_default_socket_t *this, packet_t **packet)
237 {
238 char buffer[this->max_packet];
239 chunk_t data;
240 packet_t *pkt;
241 host_t *source = NULL, *dest = NULL;
242 int i, rr, index, bytes_read = 0, selected = -1;
243 bool oldstate;
244 u_int16_t port = 0;
245 struct pollfd pfd[] = {
246 { .fd = this->ipv4, .events = POLLIN },
247 { .fd = this->ipv4_natt, .events = POLLIN },
248 { .fd = this->ipv6, .events = POLLIN },
249 { .fd = this->ipv6_natt, .events = POLLIN },
250 };
251 int ports[] = {
252 /* port numbers associated to pollfds */
253 this->port, this->natt, this->port, this->natt,
254 };
255
256 DBG2(DBG_NET, "waiting for data on sockets");
257 oldstate = thread_cancelability(TRUE);
258 if (poll(pfd, countof(pfd), -1) <= 0)
259 {
260 thread_cancelability(oldstate);
261 return FAILED;
262 }
263 thread_cancelability(oldstate);
264
265 rr = this->rr_counter++;
266 for (i = 0; i < countof(pfd); i++)
267 {
268 /* To serve all ports with equal priority, we use a round-robin
269 * scheme to choose the one to process in this invocation */
270 index = (rr + i) % countof(pfd);
271 if (pfd[index].revents & POLLIN)
272 {
273 selected = pfd[index].fd;
274 port = ports[index];
275 break;
276 }
277 }
278 if (selected != -1)
279 {
280 struct msghdr msg;
281 struct cmsghdr *cmsgptr;
282 struct iovec iov;
283 char ancillary[64];
284 union {
285 struct sockaddr_in in4;
286 struct sockaddr_in6 in6;
287 } src;
288
289 msg.msg_name = &src;
290 msg.msg_namelen = sizeof(src);
291 iov.iov_base = buffer;
292 iov.iov_len = this->max_packet;
293 msg.msg_iov = &iov;
294 msg.msg_iovlen = 1;
295 msg.msg_control = ancillary;
296 msg.msg_controllen = sizeof(ancillary);
297 msg.msg_flags = 0;
298 bytes_read = recvmsg(selected, &msg, 0);
299 if (bytes_read < 0)
300 {
301 DBG1(DBG_NET, "error reading socket: %s", strerror(errno));
302 return FAILED;
303 }
304 if (msg.msg_flags & MSG_TRUNC)
305 {
306 DBG1(DBG_NET, "receive buffer too small, packet discarded");
307 return FAILED;
308 }
309 DBG3(DBG_NET, "received packet %b", buffer, bytes_read);
310
311 /* read ancillary data to get destination address */
312 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
313 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
314 {
315 if (cmsgptr->cmsg_len == 0)
316 {
317 DBG1(DBG_NET, "error reading ancillary data");
318 return FAILED;
319 }
320 if (cmsgptr->cmsg_level == SOL_IP)
321 {
322 dest = get_dst_v4(cmsgptr, port);
323 }
324 else if (cmsgptr->cmsg_level == SOL_IPV6)
325 {
326 dest = get_dst_v6(cmsgptr, port);
327 }
328 if (dest)
329 {
330 break;
331 }
332 }
333 if (dest == NULL)
334 {
335 DBG1(DBG_NET, "error reading IP header");
336 return FAILED;
337 }
338 source = host_create_from_sockaddr((sockaddr_t*)&src);
339
340 pkt = packet_create();
341 pkt->set_source(pkt, source);
342 pkt->set_destination(pkt, dest);
343 DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest);
344 data = chunk_create(buffer, bytes_read);
345 pkt->set_data(pkt, chunk_clone(data));
346 }
347 else
348 {
349 /* oops, shouldn't happen */
350 return FAILED;
351 }
352 /* return packet */
353 *packet = pkt;
354 return SUCCESS;
355 }
356
357 /**
358 * Generic function to send a message.
359 */
360 static ssize_t send_msg_generic(int skt, struct msghdr *msg)
361 {
362 return sendmsg(skt, msg, 0);
363 }
364
365 /**
366 * Send a message with the IPv4 source address set, if possible.
367 */
368 #ifdef IP_PKTINFO
369
370 static ssize_t send_msg_v4(int skt, struct msghdr *msg, host_t *src)
371 {
372 char buf[CMSG_SPACE(sizeof(struct in_pktinfo))] = {};
373 struct cmsghdr *cmsg;
374 struct in_addr *addr;
375 struct in_pktinfo *pktinfo;
376 struct sockaddr_in *sin;
377
378 msg->msg_control = buf;
379 msg->msg_controllen = sizeof(buf);
380 cmsg = CMSG_FIRSTHDR(msg);
381 cmsg->cmsg_level = SOL_IP;
382 cmsg->cmsg_type = IP_PKTINFO;
383 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
384
385 pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
386 addr = &pktinfo->ipi_spec_dst;
387
388 sin = (struct sockaddr_in*)src->get_sockaddr(src);
389 memcpy(addr, &sin->sin_addr, sizeof(struct in_addr));
390 return send_msg_generic(skt, msg);
391 }
392
393 #elif defined(IP_SENDSRCADDR)
394
395 static ssize_t send_msg_v4(int skt, struct msghdr *msg, host_t *src)
396 {
397 char buf[CMSG_SPACE(sizeof(struct in_addr))] = {};
398 struct cmsghdr *cmsg;
399 struct in_addr *addr;
400 struct sockaddr_in *sin;
401
402 msg->msg_control = buf;
403 msg->msg_controllen = sizeof(buf);
404 cmsg = CMSG_FIRSTHDR(msg);
405 cmsg->cmsg_level = SOL_IP;
406 cmsg->cmsg_type = IP_SENDSRCADDR;
407 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
408
409 addr = (struct in_addr*)CMSG_DATA(cmsg);
410
411 sin = (struct sockaddr_in*)src->get_sockaddr(src);
412 memcpy(addr, &sin->sin_addr, sizeof(struct in_addr));
413 return send_msg_generic(skt, msg);
414 }
415
416 #else /* IP_PKTINFO || IP_RECVDSTADDR */
417
418 static ssize_t send_msg_v4(int skt, struct msghdr *msg, host_t *src)
419 {
420 return send_msg_generic(skt, msg);
421 }
422
423 #endif /* IP_PKTINFO || IP_RECVDSTADDR */
424
425 /**
426 * Send a message with the IPv6 source address set, if possible.
427 */
428 #ifdef HAVE_IN6_PKTINFO
429
430 static ssize_t send_msg_v6(int skt, struct msghdr *msg, host_t *src)
431 {
432 char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))] = {};
433 struct cmsghdr *cmsg;
434 struct in6_pktinfo *pktinfo;
435 struct sockaddr_in6 *sin;
436
437 msg->msg_control = buf;
438 msg->msg_controllen = sizeof(buf);
439 cmsg = CMSG_FIRSTHDR(msg);
440 cmsg->cmsg_level = SOL_IPV6;
441 cmsg->cmsg_type = IPV6_PKTINFO;
442 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
443 pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
444 sin = (struct sockaddr_in6*)src->get_sockaddr(src);
445 memcpy(&pktinfo->ipi6_addr, &sin->sin6_addr, sizeof(struct in6_addr));
446 return send_msg_generic(skt, msg);
447 }
448
449 #else /* HAVE_IN6_PKTINFO */
450
451 static ssize_t send_msg_v6(int skt, struct msghdr *msg, host_t *src)
452 {
453 return send_msg_generic(skt, msg);
454 }
455
456 #endif /* HAVE_IN6_PKTINFO */
457
458 METHOD(socket_t, sender, status_t,
459 private_socket_default_socket_t *this, packet_t *packet)
460 {
461 int sport, skt = -1, family;
462 ssize_t bytes_sent;
463 chunk_t data;
464 host_t *src, *dst;
465 struct msghdr msg;
466 struct iovec iov;
467 u_int8_t *dscp;
468
469 src = packet->get_source(packet);
470 dst = packet->get_destination(packet);
471 data = packet->get_data(packet);
472
473 DBG2(DBG_NET, "sending packet: from %#H to %#H", src, dst);
474
475 /* send data */
476 sport = src->get_port(src);
477 family = dst->get_family(dst);
478 if (sport == 0 || sport == this->port)
479 {
480 switch (family)
481 {
482 case AF_INET:
483 skt = this->ipv4;
484 dscp = &this->dscp4;
485 break;
486 case AF_INET6:
487 skt = this->ipv6;
488 dscp = &this->dscp6;
489 break;
490 default:
491 return FAILED;
492 }
493 }
494 else if (sport == this->natt)
495 {
496 switch (family)
497 {
498 case AF_INET:
499 skt = this->ipv4_natt;
500 dscp = &this->dscp4_natt;
501 break;
502 case AF_INET6:
503 skt = this->ipv6_natt;
504 dscp = &this->dscp6_natt;
505 break;
506 default:
507 return FAILED;
508 }
509 }
510 if (skt == -1)
511 {
512 DBG1(DBG_NET, "no socket found to send IPv%d packet from port %d",
513 family == AF_INET ? 4 : 6, sport);
514 return FAILED;
515 }
516
517 /* setting DSCP values per-packet in a cmsg seems not to be supported
518 * on Linux. We instead setsockopt() before sending it, this should be
519 * safe as only a single thread calls send(). */
520 if (*dscp != packet->get_dscp(packet))
521 {
522 if (family == AF_INET)
523 {
524 u_int8_t ds4;
525
526 ds4 = packet->get_dscp(packet) << 2;
527 if (setsockopt(skt, SOL_IP, IP_TOS, &ds4, sizeof(ds4)) == 0)
528 {
529 *dscp = packet->get_dscp(packet);
530 }
531 else
532 {
533 DBG1(DBG_NET, "unable to set IP_TOS on socket: %s",
534 strerror(errno));
535 }
536 }
537 else
538 {
539 u_int ds6;
540
541 ds6 = packet->get_dscp(packet) << 2;
542 if (setsockopt(skt, SOL_IPV6, IPV6_TCLASS, &ds6, sizeof(ds6)) == 0)
543 {
544 *dscp = packet->get_dscp(packet);
545 }
546 else
547 {
548 DBG1(DBG_NET, "unable to set IPV6_TCLASS on socket: %s",
549 strerror(errno));
550 }
551 }
552 }
553
554 memset(&msg, 0, sizeof(struct msghdr));
555 msg.msg_name = dst->get_sockaddr(dst);;
556 msg.msg_namelen = *dst->get_sockaddr_len(dst);
557 iov.iov_base = data.ptr;
558 iov.iov_len = data.len;
559 msg.msg_iov = &iov;
560 msg.msg_iovlen = 1;
561 msg.msg_flags = 0;
562
563 if (this->set_source && !src->is_anyaddr(src))
564 {
565 if (family == AF_INET)
566 {
567 bytes_sent = send_msg_v4(skt, &msg, src);
568 }
569 else
570 {
571 bytes_sent = send_msg_v6(skt, &msg, src);
572 }
573 }
574 else
575 {
576 bytes_sent = send_msg_generic(skt, &msg);
577 }
578
579 if (bytes_sent != data.len)
580 {
581 DBG1(DBG_NET, "error writing to socket: %s", strerror(errno));
582 return FAILED;
583 }
584 return SUCCESS;
585 }
586
587 METHOD(socket_t, get_port, u_int16_t,
588 private_socket_default_socket_t *this, bool nat_t)
589 {
590 return nat_t ? this->natt : this->port;
591 }
592
593 METHOD(socket_t, supported_families, socket_family_t,
594 private_socket_default_socket_t *this)
595 {
596 socket_family_t families = SOCKET_FAMILY_NONE;
597
598 if (this->ipv4 != -1 || this->ipv4_natt != -1)
599 {
600 families |= SOCKET_FAMILY_IPV4;
601 }
602 if (this->ipv6 != -1 || this->ipv6_natt != -1)
603 {
604 families |= SOCKET_FAMILY_IPV6;
605 }
606 return families;
607 }
608
609 /**
610 * open a socket to send and receive packets
611 */
612 static int open_socket(private_socket_default_socket_t *this,
613 int family, u_int16_t *port)
614 {
615 int on = TRUE;
616 union {
617 struct sockaddr sockaddr;
618 struct sockaddr_in sin;
619 struct sockaddr_in6 sin6;
620 } addr;
621 socklen_t addrlen;
622 u_int sol, pktinfo = 0;
623 int skt;
624
625 memset(&addr, 0, sizeof(addr));
626 addr.sockaddr.sa_family = family;
627 /* precalculate constants depending on address family */
628 switch (family)
629 {
630 case AF_INET:
631 addr.sin.sin_addr.s_addr = htonl(INADDR_ANY);
632 addr.sin.sin_port = htons(*port);
633 addrlen = sizeof(addr.sin);
634 sol = SOL_IP;
635 #ifdef IP_PKTINFO
636 pktinfo = IP_PKTINFO;
637 #elif defined(IP_RECVDSTADDR)
638 pktinfo = IP_RECVDSTADDR;
639 #endif
640 break;
641 case AF_INET6:
642 memcpy(&addr.sin6.sin6_addr, &in6addr_any, sizeof(in6addr_any));
643 addr.sin6.sin6_port = htons(*port);
644 addrlen = sizeof(addr.sin6);
645 sol = SOL_IPV6;
646 pktinfo = IPV6_RECVPKTINFO;
647 break;
648 default:
649 return -1;
650 }
651
652 skt = socket(family, SOCK_DGRAM, IPPROTO_UDP);
653 if (skt < 0)
654 {
655 DBG1(DBG_NET, "could not open socket: %s", strerror(errno));
656 return -1;
657 }
658 if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
659 {
660 DBG1(DBG_NET, "unable to set SO_REUSEADDR on socket: %s", strerror(errno));
661 close(skt);
662 return -1;
663 }
664
665 /* bind the socket */
666 if (bind(skt, &addr.sockaddr, addrlen) < 0)
667 {
668 DBG1(DBG_NET, "unable to bind socket: %s", strerror(errno));
669 close(skt);
670 return -1;
671 }
672
673 /* retrieve randomly allocated port if needed */
674 if (*port == 0)
675 {
676 if (getsockname(skt, &addr.sockaddr, &addrlen) < 0)
677 {
678 DBG1(DBG_NET, "unable to determine port: %s", strerror(errno));
679 close(skt);
680 return -1;
681 }
682 switch (family)
683 {
684 case AF_INET:
685 *port = ntohs(addr.sin.sin_port);
686 break;
687 case AF_INET6:
688 *port = ntohs(addr.sin6.sin6_port);
689 break;
690 }
691 }
692
693 /* get additional packet info on receive */
694 if (pktinfo > 0)
695 {
696 if (setsockopt(skt, sol, pktinfo, &on, sizeof(on)) < 0)
697 {
698 DBG1(DBG_NET, "unable to set IP_PKTINFO on socket: %s", strerror(errno));
699 close(skt);
700 return -1;
701 }
702 }
703 #ifdef SO_MARK
704 { /* set optional MARK on socket (requires CAP_NET_ADMIN) */
705 char *fwmark;
706 mark_t mark;
707
708 fwmark = lib->settings->get_str(lib->settings,
709 "%s.plugins.socket-default.fwmark", NULL, lib->ns);
710 if (fwmark && mark_from_string(fwmark, &mark))
711 {
712 if (setsockopt(skt, SOL_SOCKET, SO_MARK, &mark.value,
713 sizeof(mark.value)) < 0)
714 {
715 DBG1(DBG_NET, "unable to set SO_MARK on socket: %s",
716 strerror(errno));
717 }
718 }
719 }
720 #endif
721
722 if (!charon->kernel->bypass_socket(charon->kernel, skt, family))
723 {
724 DBG1(DBG_NET, "installing IKE bypass policy failed");
725 }
726
727 /* enable UDP decapsulation for NAT-T sockets */
728 if (port == &this->natt &&
729 !charon->kernel->enable_udp_decap(charon->kernel, skt, family,
730 this->natt))
731 {
732 DBG1(DBG_NET, "enabling UDP decapsulation for %s on port %d failed",
733 family == AF_INET ? "IPv4" : "IPv6", this->natt);
734 }
735
736 return skt;
737 }
738
739 /**
740 * Check if we should use the given family
741 */
742 static bool use_family(int family)
743 {
744 switch (family)
745 {
746 case AF_INET:
747 return lib->settings->get_bool(lib->settings,
748 "%s.plugins.socket-default.use_ipv4", TRUE, lib->ns);
749 case AF_INET6:
750 return lib->settings->get_bool(lib->settings,
751 "%s.plugins.socket-default.use_ipv6", TRUE, lib->ns);
752 default:
753 return FALSE;
754 }
755 }
756
757 /**
758 * Open a socket pair (normal and NAT traversal) for a given address family
759 */
760 static void open_socketpair(private_socket_default_socket_t *this, int family,
761 int *skt, int *skt_natt, char *label)
762 {
763 if (!use_family(family))
764 {
765 *skt = -1;
766 *skt_natt = -1;
767 return;
768 }
769
770 *skt = open_socket(this, family, &this->port);
771 if (*skt == -1)
772 {
773 *skt_natt = -1;
774 DBG1(DBG_NET, "could not open %s socket, %s disabled", label, label);
775 }
776 else
777 {
778 *skt_natt = open_socket(this, family, &this->natt);
779 if (*skt_natt == -1)
780 {
781 DBG1(DBG_NET, "could not open %s NAT-T socket", label);
782 }
783 }
784 }
785
786 METHOD(socket_t, destroy, void,
787 private_socket_default_socket_t *this)
788 {
789 if (this->ipv4 != -1)
790 {
791 close(this->ipv4);
792 }
793 if (this->ipv4_natt != -1)
794 {
795 close(this->ipv4_natt);
796 }
797 if (this->ipv6 != -1)
798 {
799 close(this->ipv6);
800 }
801 if (this->ipv6_natt != -1)
802 {
803 close(this->ipv6_natt);
804 }
805 free(this);
806 }
807
808 /*
809 * See header for description
810 */
811 socket_default_socket_t *socket_default_socket_create()
812 {
813 private_socket_default_socket_t *this;
814
815 INIT(this,
816 .public = {
817 .socket = {
818 .send = _sender,
819 .receive = _receiver,
820 .get_port = _get_port,
821 .supported_families = _supported_families,
822 .destroy = _destroy,
823 },
824 },
825 .port = lib->settings->get_int(lib->settings,
826 "%s.port", CHARON_UDP_PORT, lib->ns),
827 .natt = lib->settings->get_int(lib->settings,
828 "%s.port_nat_t", CHARON_NATT_PORT, lib->ns),
829 .max_packet = lib->settings->get_int(lib->settings,
830 "%s.max_packet", PACKET_MAX_DEFAULT, lib->ns),
831 .set_source = lib->settings->get_bool(lib->settings,
832 "%s.plugins.socket-default.set_source", TRUE,
833 lib->ns),
834 );
835
836 if (this->port && this->port == this->natt)
837 {
838 DBG1(DBG_NET, "IKE ports can't be equal, will allocate NAT-T "
839 "port randomly");
840 this->natt = 0;
841 }
842
843 if ((this->port && this->port < 1024) || (this->natt && this->natt < 1024))
844 {
845 if (!lib->caps->check(lib->caps, CAP_NET_BIND_SERVICE))
846 {
847 /* required to bind ports < 1024 */
848 DBG1(DBG_NET, "socket-default plugin requires CAP_NET_BIND_SERVICE "
849 "capability");
850 destroy(this);
851 return NULL;
852 }
853 }
854
855 /* we allocate IPv6 sockets first as that will reserve randomly allocated
856 * ports also for IPv4. On OS X, we have to do it the other way round
857 * for the same effect. */
858 #ifdef __APPLE__
859 open_socketpair(this, AF_INET, &this->ipv4, &this->ipv4_natt, "IPv4");
860 open_socketpair(this, AF_INET6, &this->ipv6, &this->ipv6_natt, "IPv6");
861 #else /* !__APPLE__ */
862 open_socketpair(this, AF_INET6, &this->ipv6, &this->ipv6_natt, "IPv6");
863 open_socketpair(this, AF_INET, &this->ipv4, &this->ipv4_natt, "IPv4");
864 #endif /* __APPLE__ */
865
866 if (this->ipv4 == -1 && this->ipv6 == -1)
867 {
868 DBG1(DBG_NET, "could not create any sockets");
869 destroy(this);
870 return NULL;
871 }
872
873 return &this->public;
874 }