capabilities: Some plugins don't actually require capabilities at runtime
[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 <hydra.h>
45 #include <daemon.h>
46 #include <threading/thread.h>
47
48 /* Maximum size of a packet */
49 #define MAX_PACKET 10000
50
51 /* these are not defined on some platforms */
52 #ifndef SOL_IP
53 #define SOL_IP IPPROTO_IP
54 #endif
55 #ifndef SOL_IPV6
56 #define SOL_IPV6 IPPROTO_IPV6
57 #endif
58 #ifndef IPV6_TCLASS
59 #define IPV6_TCLASS 67
60 #endif
61
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
66 #endif
67
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}}}
70 #endif
71
72 #ifndef HAVE_IN6ADDR_ANY
73 static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
74 #endif
75
76 typedef struct private_socket_default_socket_t private_socket_default_socket_t;
77
78 /**
79 * Private data of an socket_t object
80 */
81 struct private_socket_default_socket_t {
82
83 /**
84 * public functions
85 */
86 socket_default_socket_t public;
87
88 /**
89 * Configured port (or random, if initially 0)
90 */
91 u_int16_t port;
92
93 /**
94 * Configured port for NAT-T (or random, if initially 0)
95 */
96 u_int16_t natt;
97
98 /**
99 * IPv4 socket (500 or port)
100 */
101 int ipv4;
102
103 /**
104 * IPv4 socket for NAT-T (4500 or natt)
105 */
106 int ipv4_natt;
107
108 /**
109 * IPv6 socket (500 or port)
110 */
111 int ipv6;
112
113 /**
114 * IPv6 socket for NAT-T (4500 or natt)
115 */
116 int ipv6_natt;
117
118 /**
119 * DSCP value set on IPv4 socket
120 */
121 u_int8_t dscp4;
122
123 /**
124 * DSCP value set on IPv4 socket for NAT-T (4500 or natt)
125 */
126 u_int8_t dscp4_natt;
127
128 /**
129 * DSCP value set on IPv6 socket (500 or port)
130 */
131 u_int8_t dscp6;
132
133 /**
134 * DSCP value set on IPv6 socket for NAT-T (4500 or natt)
135 */
136 u_int8_t dscp6_natt;
137
138 /**
139 * Maximum packet size to receive
140 */
141 int max_packet;
142
143 /**
144 * TRUE if the source address should be set on outbound packets
145 */
146 bool set_source;
147 };
148
149 METHOD(socket_t, receiver, status_t,
150 private_socket_default_socket_t *this, packet_t **packet)
151 {
152 char buffer[this->max_packet];
153 chunk_t data;
154 packet_t *pkt;
155 host_t *source = NULL, *dest = NULL;
156 int bytes_read = 0;
157 bool oldstate;
158
159 fd_set rfds;
160 int max_fd = 0, selected = 0;
161 u_int16_t port = 0;
162
163 FD_ZERO(&rfds);
164
165 if (this->ipv4 != -1)
166 {
167 FD_SET(this->ipv4, &rfds);
168 max_fd = max(max_fd, this->ipv4);
169 }
170 if (this->ipv4_natt != -1)
171 {
172 FD_SET(this->ipv4_natt, &rfds);
173 max_fd = max(max_fd, this->ipv4_natt);
174 }
175 if (this->ipv6 != -1)
176 {
177 FD_SET(this->ipv6, &rfds);
178 max_fd = max(max_fd, this->ipv6);
179 }
180 if (this->ipv6_natt != -1)
181 {
182 FD_SET(this->ipv6_natt, &rfds);
183 max_fd = max(max_fd, this->ipv6_natt);
184 }
185
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)
189 {
190 thread_cancelability(oldstate);
191 return FAILED;
192 }
193 thread_cancelability(oldstate);
194
195 if (this->ipv4 != -1 && FD_ISSET(this->ipv4, &rfds))
196 {
197 port = this->port;
198 selected = this->ipv4;
199 }
200 if (this->ipv4_natt != -1 && FD_ISSET(this->ipv4_natt, &rfds))
201 {
202 port = this->natt;
203 selected = this->ipv4_natt;
204 }
205 if (this->ipv6 != -1 && FD_ISSET(this->ipv6, &rfds))
206 {
207 port = this->port;
208 selected = this->ipv6;
209 }
210 if (this->ipv6_natt != -1 && FD_ISSET(this->ipv6_natt, &rfds))
211 {
212 port = this->natt;
213 selected = this->ipv6_natt;
214 }
215 if (selected)
216 {
217 struct msghdr msg;
218 struct cmsghdr *cmsgptr;
219 struct iovec iov;
220 char ancillary[64];
221 union {
222 struct sockaddr_in in4;
223 struct sockaddr_in6 in6;
224 } src;
225
226 msg.msg_name = &src;
227 msg.msg_namelen = sizeof(src);
228 iov.iov_base = buffer;
229 iov.iov_len = this->max_packet;
230 msg.msg_iov = &iov;
231 msg.msg_iovlen = 1;
232 msg.msg_control = ancillary;
233 msg.msg_controllen = sizeof(ancillary);
234 msg.msg_flags = 0;
235 bytes_read = recvmsg(selected, &msg, 0);
236 if (bytes_read < 0)
237 {
238 DBG1(DBG_NET, "error reading socket: %s", strerror(errno));
239 return FAILED;
240 }
241 if (msg.msg_flags & MSG_TRUNC)
242 {
243 DBG1(DBG_NET, "receive buffer too small, packet discarded");
244 return FAILED;
245 }
246 DBG3(DBG_NET, "received packet %b", buffer, bytes_read);
247
248 /* read ancillary data to get destination address */
249 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
250 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
251 {
252 if (cmsgptr->cmsg_len == 0)
253 {
254 DBG1(DBG_NET, "error reading ancillary data");
255 return FAILED;
256 }
257
258 #ifdef HAVE_IN6_PKTINFO
259 if (cmsgptr->cmsg_level == SOL_IPV6 &&
260 cmsgptr->cmsg_type == IPV6_PKTINFO)
261 {
262 struct in6_pktinfo *pktinfo;
263 pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsgptr);
264 struct sockaddr_in6 dst;
265
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);
271 }
272 #endif /* HAVE_IN6_PKTINFO */
273 if (cmsgptr->cmsg_level == SOL_IP &&
274 #ifdef IP_PKTINFO
275 cmsgptr->cmsg_type == IP_PKTINFO
276 #elif defined(IP_RECVDSTADDR)
277 cmsgptr->cmsg_type == IP_RECVDSTADDR
278 #else
279 FALSE
280 #endif
281 )
282 {
283 struct in_addr *addr;
284 struct sockaddr_in dst;
285
286 #ifdef IP_PKTINFO
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);
292 #endif
293 memset(&dst, 0, sizeof(dst));
294 memcpy(&dst.sin_addr, addr, sizeof(dst.sin_addr));
295
296 dst.sin_family = AF_INET;
297 dst.sin_port = htons(port);
298 dest = host_create_from_sockaddr((sockaddr_t*)&dst);
299 }
300 if (dest)
301 {
302 break;
303 }
304 }
305 if (dest == NULL)
306 {
307 DBG1(DBG_NET, "error reading IP header");
308 return FAILED;
309 }
310 source = host_create_from_sockaddr((sockaddr_t*)&src);
311
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));
318 }
319 else
320 {
321 /* oops, shouldn't happen */
322 return FAILED;
323 }
324 /* return packet */
325 *packet = pkt;
326 return SUCCESS;
327 }
328
329 METHOD(socket_t, sender, status_t,
330 private_socket_default_socket_t *this, packet_t *packet)
331 {
332 int sport, skt = -1, family;
333 ssize_t bytes_sent;
334 chunk_t data;
335 host_t *src, *dst;
336 struct msghdr msg;
337 struct cmsghdr *cmsg;
338 struct iovec iov;
339 u_int8_t *dscp;
340
341 src = packet->get_source(packet);
342 dst = packet->get_destination(packet);
343 data = packet->get_data(packet);
344
345 DBG2(DBG_NET, "sending packet: from %#H to %#H", src, dst);
346
347 /* send data */
348 sport = src->get_port(src);
349 family = dst->get_family(dst);
350 if (sport == 0 || sport == this->port)
351 {
352 switch (family)
353 {
354 case AF_INET:
355 skt = this->ipv4;
356 dscp = &this->dscp4;
357 break;
358 case AF_INET6:
359 skt = this->ipv6;
360 dscp = &this->dscp6;
361 break;
362 default:
363 return FAILED;
364 }
365 }
366 else if (sport == this->natt)
367 {
368 switch (family)
369 {
370 case AF_INET:
371 skt = this->ipv4_natt;
372 dscp = &this->dscp4_natt;
373 break;
374 case AF_INET6:
375 skt = this->ipv6_natt;
376 dscp = &this->dscp6_natt;
377 break;
378 default:
379 return FAILED;
380 }
381 }
382 if (skt == -1)
383 {
384 DBG1(DBG_NET, "no socket found to send IPv%d packet from port %d",
385 family == AF_INET ? 4 : 6, sport);
386 return FAILED;
387 }
388
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))
393 {
394 if (family == AF_INET)
395 {
396 u_int8_t ds4;
397
398 ds4 = packet->get_dscp(packet) << 2;
399 if (setsockopt(skt, SOL_IP, IP_TOS, &ds4, sizeof(ds4)) == 0)
400 {
401 *dscp = packet->get_dscp(packet);
402 }
403 else
404 {
405 DBG1(DBG_NET, "unable to set IP_TOS on socket: %s",
406 strerror(errno));
407 }
408 }
409 else
410 {
411 u_int ds6;
412
413 ds6 = packet->get_dscp(packet) << 2;
414 if (setsockopt(skt, SOL_IPV6, IPV6_TCLASS, &ds6, sizeof(ds6)) == 0)
415 {
416 *dscp = packet->get_dscp(packet);
417 }
418 else
419 {
420 DBG1(DBG_NET, "unable to set IPV6_TCLASS on socket: %s",
421 strerror(errno));
422 }
423 }
424 }
425
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;
431 msg.msg_iov = &iov;
432 msg.msg_iovlen = 1;
433 msg.msg_flags = 0;
434
435 if (this->set_source && !src->is_anyaddr(src))
436 {
437 if (family == AF_INET)
438 {
439 #if defined(IP_PKTINFO) || defined(IP_SENDSRCADDR)
440 struct in_addr *addr;
441 struct sockaddr_in *sin;
442 #ifdef IP_PKTINFO
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))];
447 #endif
448 msg.msg_control = buf;
449 msg.msg_controllen = sizeof(buf);
450 cmsg = CMSG_FIRSTHDR(&msg);
451 cmsg->cmsg_level = SOL_IP;
452 #ifdef IP_PKTINFO
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);
462 #endif
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 */
466 }
467 #ifdef HAVE_IN6_PKTINFO
468 else
469 {
470 char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
471 struct in6_pktinfo *pktinfo;
472 struct sockaddr_in6 *sin;
473
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));
484 }
485 #endif /* HAVE_IN6_PKTINFO */
486 }
487
488 bytes_sent = sendmsg(skt, &msg, 0);
489
490 if (bytes_sent != data.len)
491 {
492 DBG1(DBG_NET, "error writing to socket: %s", strerror(errno));
493 return FAILED;
494 }
495 return SUCCESS;
496 }
497
498 METHOD(socket_t, get_port, u_int16_t,
499 private_socket_default_socket_t *this, bool nat_t)
500 {
501 return nat_t ? this->natt : this->port;
502 }
503
504 METHOD(socket_t, supported_families, socket_family_t,
505 private_socket_default_socket_t *this)
506 {
507 socket_family_t families = SOCKET_FAMILY_NONE;
508
509 if (this->ipv4 != -1 || this->ipv4_natt != -1)
510 {
511 families |= SOCKET_FAMILY_IPV4;
512 }
513 if (this->ipv6 != -1 || this->ipv6_natt != -1)
514 {
515 families |= SOCKET_FAMILY_IPV6;
516 }
517 return families;
518 }
519
520 /**
521 * open a socket to send and receive packets
522 */
523 static int open_socket(private_socket_default_socket_t *this,
524 int family, u_int16_t *port)
525 {
526 int on = TRUE;
527 union {
528 struct sockaddr sockaddr;
529 struct sockaddr_in sin;
530 struct sockaddr_in6 sin6;
531 } addr;
532 socklen_t addrlen;
533 u_int sol, pktinfo = 0;
534 int skt;
535
536 memset(&addr, 0, sizeof(addr));
537 addr.sockaddr.sa_family = family;
538 /* precalculate constants depending on address family */
539 switch (family)
540 {
541 case AF_INET:
542 addr.sin.sin_addr.s_addr = htonl(INADDR_ANY);
543 addr.sin.sin_port = htons(*port);
544 addrlen = sizeof(addr.sin);
545 sol = SOL_IP;
546 #ifdef IP_PKTINFO
547 pktinfo = IP_PKTINFO;
548 #elif defined(IP_RECVDSTADDR)
549 pktinfo = IP_RECVDSTADDR;
550 #endif
551 break;
552 case AF_INET6:
553 memcpy(&addr.sin6.sin6_addr, &in6addr_any, sizeof(in6addr_any));
554 addr.sin6.sin6_port = htons(*port);
555 addrlen = sizeof(addr.sin6);
556 sol = SOL_IPV6;
557 pktinfo = IPV6_RECVPKTINFO;
558 break;
559 default:
560 return -1;
561 }
562
563 skt = socket(family, SOCK_DGRAM, IPPROTO_UDP);
564 if (skt < 0)
565 {
566 DBG1(DBG_NET, "could not open socket: %s", strerror(errno));
567 return -1;
568 }
569 if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
570 {
571 DBG1(DBG_NET, "unable to set SO_REUSEADDR on socket: %s", strerror(errno));
572 close(skt);
573 return -1;
574 }
575
576 /* bind the socket */
577 if (bind(skt, &addr.sockaddr, addrlen) < 0)
578 {
579 DBG1(DBG_NET, "unable to bind socket: %s", strerror(errno));
580 close(skt);
581 return -1;
582 }
583
584 /* retrieve randomly allocated port if needed */
585 if (*port == 0)
586 {
587 if (getsockname(skt, &addr.sockaddr, &addrlen) < 0)
588 {
589 DBG1(DBG_NET, "unable to determine port: %s", strerror(errno));
590 close(skt);
591 return -1;
592 }
593 switch (family)
594 {
595 case AF_INET:
596 *port = ntohs(addr.sin.sin_port);
597 break;
598 case AF_INET6:
599 *port = ntohs(addr.sin6.sin6_port);
600 break;
601 }
602 }
603
604 /* get additional packet info on receive */
605 if (pktinfo > 0)
606 {
607 if (setsockopt(skt, sol, pktinfo, &on, sizeof(on)) < 0)
608 {
609 DBG1(DBG_NET, "unable to set IP_PKTINFO on socket: %s", strerror(errno));
610 close(skt);
611 return -1;
612 }
613 }
614
615 if (!hydra->kernel_interface->bypass_socket(hydra->kernel_interface,
616 skt, family))
617 {
618 DBG1(DBG_NET, "installing IKE bypass policy failed");
619 }
620
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))
625 {
626 DBG1(DBG_NET, "enabling UDP decapsulation for %s on port %d failed",
627 family == AF_INET ? "IPv4" : "IPv6", this->natt);
628 }
629
630 return skt;
631 }
632
633 /**
634 * Check if we should use the given family
635 */
636 static bool use_family(int family)
637 {
638 switch (family)
639 {
640 case AF_INET:
641 return lib->settings->get_bool(lib->settings,
642 "%s.plugins.socket-default.use_ipv4", TRUE, charon->name);
643 case AF_INET6:
644 return lib->settings->get_bool(lib->settings,
645 "%s.plugins.socket-default.use_ipv6", TRUE, charon->name);
646 default:
647 return FALSE;
648 }
649 }
650
651 /**
652 * Open a socket pair (normal and NAT traversal) for a given address family
653 */
654 static void open_socketpair(private_socket_default_socket_t *this, int family,
655 int *skt, int *skt_natt, char *label)
656 {
657 if (!use_family(family))
658 {
659 *skt = -1;
660 *skt_natt = -1;
661 return;
662 }
663
664 *skt = open_socket(this, family, &this->port);
665 if (*skt == -1)
666 {
667 *skt_natt = -1;
668 DBG1(DBG_NET, "could not open %s socket, %s disabled", label, label);
669 }
670 else
671 {
672 *skt_natt = open_socket(this, family, &this->natt);
673 if (*skt_natt == -1)
674 {
675 DBG1(DBG_NET, "could not open %s NAT-T socket", label);
676 }
677 }
678 }
679
680 METHOD(socket_t, destroy, void,
681 private_socket_default_socket_t *this)
682 {
683 if (this->ipv4 != -1)
684 {
685 close(this->ipv4);
686 }
687 if (this->ipv4_natt != -1)
688 {
689 close(this->ipv4_natt);
690 }
691 if (this->ipv6 != -1)
692 {
693 close(this->ipv6);
694 }
695 if (this->ipv6_natt != -1)
696 {
697 close(this->ipv6_natt);
698 }
699 free(this);
700 }
701
702 /*
703 * See header for description
704 */
705 socket_default_socket_t *socket_default_socket_create()
706 {
707 private_socket_default_socket_t *this;
708
709 INIT(this,
710 .public = {
711 .socket = {
712 .send = _sender,
713 .receive = _receiver,
714 .get_port = _get_port,
715 .supported_families = _supported_families,
716 .destroy = _destroy,
717 },
718 },
719 .port = lib->settings->get_int(lib->settings,
720 "%s.port", CHARON_UDP_PORT, charon->name),
721 .natt = lib->settings->get_int(lib->settings,
722 "%s.port_nat_t", CHARON_NATT_PORT, charon->name),
723 .max_packet = lib->settings->get_int(lib->settings,
724 "%s.max_packet", MAX_PACKET, charon->name),
725 .set_source = lib->settings->get_bool(lib->settings,
726 "%s.plugins.socket-default.set_source", TRUE,
727 charon->name),
728 );
729
730 if (this->port && this->port == this->natt)
731 {
732 DBG1(DBG_NET, "IKE ports can't be equal, will allocate NAT-T "
733 "port randomly");
734 this->natt = 0;
735 }
736
737 if ((this->port && this->port < 1024) || (this->natt && this->natt < 1024))
738 {
739 if (!lib->caps->check(lib->caps, CAP_NET_BIND_SERVICE))
740 {
741 /* required to bind ports < 1024 */
742 DBG1(DBG_NET, "socket-default plugin requires CAP_NET_BIND_SERVICE "
743 "capability");
744 destroy(this);
745 return NULL;
746 }
747 }
748
749 /* we allocate IPv6 sockets first as that will reserve randomly allocated
750 * ports also for IPv4. On OS X, we have to do it the other way round
751 * for the same effect. */
752 #ifdef __APPLE__
753 open_socketpair(this, AF_INET, &this->ipv4, &this->ipv4_natt, "IPv4");
754 open_socketpair(this, AF_INET6, &this->ipv6, &this->ipv6_natt, "IPv6");
755 #else /* !__APPLE__ */
756 open_socketpair(this, AF_INET6, &this->ipv6, &this->ipv6_natt, "IPv6");
757 open_socketpair(this, AF_INET, &this->ipv4, &this->ipv4_natt, "IPv4");
758 #endif /* __APPLE__ */
759
760 if (this->ipv4 == -1 && this->ipv6 == -1)
761 {
762 DBG1(DBG_NET, "could not create any sockets");
763 destroy(this);
764 return NULL;
765 }
766
767 return &this->public;
768 }