added raw socket filter for IPv6
[strongswan.git] / src / charon / network / socket.c
1 /**
2 * @file socket.c
3 *
4 * @brief Implementation of socket_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
10 * Copyright (C) 2005-2006 Martin Willi
11 * Copyright (C) 2005 Jan Hutter
12 * Hochschule fuer Technik Rapperswil
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 */
24
25 #include <pthread.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <fcntl.h>
33 #include <sys/ioctl.h>
34 #include <netinet/in.h>
35 #include <netinet/ip.h>
36 #include <netinet/ip6.h>
37 #include <netinet/udp.h>
38 #include <linux/ipsec.h>
39 #include <linux/filter.h>
40 #include <net/if.h>
41 #include <ifaddrs.h>
42
43 #include "socket.h"
44
45 #include <daemon.h>
46 #include <utils/logger_manager.h>
47
48 /* constants for packet handling */
49 #define IP_LEN sizeof(struct iphdr)
50 #define IP6_LEN sizeof(struct ip6_hdr)
51 #define UDP_LEN sizeof(struct udphdr)
52 #define MARKER_LEN sizeof(u_int32_t)
53
54 /* offsets for packet handling */
55 #define IP_PROTO_OFFSET 9
56 #define IP6_PROTO_OFFSET 6
57 #define IKE_VERSION_OFFSET 17
58 #define IKE_LENGTH_OFFSET 24
59
60 /* from linux/in.h */
61 #ifndef IP_IPSEC_POLICY
62 #define IP_IPSEC_POLICY 16
63 #endif /*IP_IPSEC_POLICY*/
64
65 /* from linux/udp.h */
66 #ifndef UDP_ENCAP
67 #define UDP_ENCAP 100
68 #endif /*UDP_ENCAP*/
69
70 #ifndef UDP_ENCAP_ESPINUDP
71 #define UDP_ENCAP_ESPINUDP 2
72 #endif /*UDP_ENCAP_ESPINUDP*/
73
74 typedef struct private_socket_t private_socket_t;
75
76 /**
77 * Private data of an socket_t object
78 */
79 struct private_socket_t{
80 /**
81 * public functions
82 */
83 socket_t public;
84
85 /**
86 * regular port
87 */
88 int port;
89
90 /**
91 * port used for nat-t
92 */
93 int natt_port;
94
95 /**
96 * raw receiver socket for IPv4
97 */
98 int recv4;
99
100 /**
101 * raw receiver socket for IPv6
102 */
103 int recv6;
104
105 /**
106 * send socket on regular port for IPv4
107 */
108 int send4;
109
110 /**
111 * send socket on regular port for IPv6
112 */
113 int send6;
114
115 /**
116 * send socket on nat-t port for IPv4
117 */
118 int send4_natt;
119
120 /**
121 * send socket on nat-t port for IPv6
122 */
123 int send6_natt;
124
125 /**
126 * logger for this socket
127 */
128 logger_t *logger;
129 };
130
131 /**
132 * implementation of socket_t.receive
133 */
134 static status_t receiver(private_socket_t *this, packet_t **packet)
135 {
136 char buffer[MAX_PACKET];
137 chunk_t data;
138 packet_t *pkt;
139 struct udphdr *udp;
140 host_t *source = NULL, *dest = NULL;
141 int bytes_read = 0;
142 int data_offset, oldstate;
143 fd_set rfds;
144
145 FD_ZERO(&rfds);
146 FD_SET(this->recv4, &rfds);
147 FD_SET(this->recv6, &rfds);
148
149 this->logger->log(this->logger, CONTROL|LEVEL1,
150 "waiting for data on raw sockets");
151
152 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
153 if (select(max(this->recv4, this->recv6) + 1, &rfds, NULL, NULL, NULL) <= 0)
154 {
155 pthread_setcancelstate(oldstate, NULL);
156 return FAILED;
157 }
158 pthread_setcancelstate(oldstate, NULL);
159
160 if (FD_ISSET(this->recv4, &rfds))
161 {
162 /* IPv4 raw sockets return the IP header. We read src/dest
163 * information directly from the raw header */
164 struct iphdr *ip;
165 struct sockaddr_in src, dst;
166
167 bytes_read = recv(this->recv4, buffer, MAX_PACKET, 0);
168 if (bytes_read < 0)
169 {
170 this->logger->log(this->logger, ERROR,
171 "error reading from IPv4 socket: %s",
172 strerror(errno));
173 return FAILED;
174 }
175 this->logger->log_bytes(this->logger, RAW,
176 "received IPv4 packet", buffer, bytes_read);
177
178 /* read source/dest from raw IP/UDP header */
179 if (bytes_read < IP_LEN + UDP_LEN + MARKER_LEN)
180 {
181 this->logger->log(this->logger, ERROR,
182 "received IPv4 packet too short");
183 return FAILED;
184 }
185 ip = (struct iphdr*) buffer;
186 udp = (struct udphdr*) (buffer + IP_LEN);
187 src.sin_family = AF_INET;
188 src.sin_addr.s_addr = ip->saddr;
189 src.sin_port = udp->source;
190 dst.sin_family = AF_INET;
191 dst.sin_addr.s_addr = ip->daddr;
192 dst.sin_port = udp->dest;
193 source = host_create_from_sockaddr((sockaddr_t*)&src);
194 dest = host_create_from_sockaddr((sockaddr_t*)&dst);
195
196 pkt = packet_create();
197 pkt->set_source(pkt, source);
198 pkt->set_destination(pkt, dest);
199 this->logger->log(this->logger, CONTROL|LEVEL1,
200 "received packet: from %s[%d] to %s[%d]",
201 source->get_string(source), source->get_port(source),
202 dest->get_string(dest), dest->get_port(dest));
203 data_offset = IP_LEN + UDP_LEN;
204 /* remove non esp marker */
205 if (dest->get_port(dest) == this->natt_port)
206 {
207 data_offset += MARKER_LEN;
208 }
209 /* fill in packet */
210 data.len = bytes_read - data_offset;
211 data.ptr = malloc(data.len);
212 memcpy(data.ptr, buffer + data_offset, data.len);
213 pkt->set_data(pkt, data);
214 }
215 else if (FD_ISSET(this->recv6, &rfds))
216 {
217 /* IPv6 raw sockets return no IP header. We must query
218 * src/dest via socket options/ancillary data */
219 struct msghdr msg;
220 struct cmsghdr *cmsgptr;
221 struct sockaddr_in6 src, dst;
222 struct iovec iov;
223 char ancillary[64];
224
225 msg.msg_name = &src;
226 msg.msg_namelen = sizeof(src);
227 iov.iov_base = buffer;
228 iov.iov_len = sizeof(buffer);
229 msg.msg_iov = &iov;
230 msg.msg_iovlen = 1;
231 msg.msg_control = ancillary;
232 msg.msg_controllen = sizeof(ancillary);
233 msg.msg_flags = 0;
234
235 bytes_read = recvmsg(this->recv6, &msg, 0);
236 if (bytes_read < 0)
237 {
238 this->logger->log(this->logger, ERROR,
239 "error reading from IPv6 socket: %s",
240 strerror(errno));
241 return FAILED;
242 }
243 this->logger->log_bytes(this->logger, RAW,
244 "received IPv6 packet", buffer, bytes_read);
245
246 if (bytes_read < IP_LEN + UDP_LEN + MARKER_LEN)
247 {
248 this->logger->log(this->logger, ERROR,
249 "received IPv6 packet too short");
250 return FAILED;
251 }
252
253 /* read ancillary data to get destination address */
254 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
255 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
256 {
257 if (cmsgptr->cmsg_len == 0)
258 {
259 this->logger->log(this->logger, ERROR,
260 "error reading IPv6 ancillary data: %s",
261 strerror(errno));
262 return FAILED;
263 }
264 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
265 cmsgptr->cmsg_type == IPV6_PKTINFO)
266 {
267 struct in6_pktinfo *pktinfo;
268 pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsgptr);
269
270 memset(&dst, 0, sizeof(dst));
271 memcpy(&dst.sin6_addr, &pktinfo->ipi6_addr, sizeof(dst.sin6_addr));
272 dst.sin6_family = AF_INET6;
273 udp = (struct udphdr*) (buffer);
274 dst.sin6_port = udp->dest;
275 src.sin6_port = udp->source;
276 dest = host_create_from_sockaddr((sockaddr_t*)&dst);
277 }
278 }
279 /* ancillary data missing? */
280 if (dest == NULL)
281 {
282 this->logger->log(this->logger, ERROR,
283 "error reading IPv6 packet header");
284 return FAILED;
285 }
286
287 source = host_create_from_sockaddr((sockaddr_t*)&src);
288
289 pkt = packet_create();
290 pkt->set_source(pkt, source);
291 pkt->set_destination(pkt, dest);
292 this->logger->log(this->logger, CONTROL|LEVEL1,
293 "received packet: from %s[%d] to %s[%d]",
294 source->get_string(source), source->get_port(source),
295 dest->get_string(dest), dest->get_port(dest));
296 data_offset = UDP_LEN;
297 /* remove non esp marker */
298 if (dest->get_port(dest) == this->natt_port)
299 {
300 data_offset += MARKER_LEN;
301 }
302 /* fill in packet */
303 data.len = bytes_read - data_offset;
304 data.ptr = malloc(data.len);
305 memcpy(data.ptr, buffer + data_offset, data.len);
306 pkt->set_data(pkt, data);
307 }
308 else
309 {
310 /* oops, shouldn't happen */
311 return FAILED;
312 }
313
314 /* return packet */
315 *packet = pkt;
316 return SUCCESS;
317 }
318
319 /**
320 * implementation of socket_t.send
321 */
322 status_t sender(private_socket_t *this, packet_t *packet)
323 {
324 int sport, skt, family;
325 ssize_t bytes_sent;
326 chunk_t data, marked;
327 host_t *src, *dst;
328
329 src = packet->get_source(packet);
330 dst = packet->get_destination(packet);
331 data = packet->get_data(packet);
332
333 this->logger->log(this->logger, CONTROL|LEVEL1, "sending packet: from %s[%d] to %s[%d]",
334 src->get_string(src), src->get_port(src),
335 dst->get_string(dst), dst->get_port(dst));
336
337 /* send data */
338 sport = src->get_port(src);
339 family = dst->get_family(dst);
340 if (sport == this->port)
341 {
342 if (family == AF_INET)
343 {
344 skt = this->send4;
345 }
346 else
347 {
348 skt = this->send6;
349 }
350 }
351 else if (sport == this->natt_port)
352 {
353 if (family == AF_INET)
354 {
355 skt = this->send4_natt;
356 }
357 else
358 {
359 skt = this->send6_natt;
360 }
361 /* NAT keepalives without marker */
362 if (data.len != 1 || data.ptr[0] != 0xFF)
363 {
364 /* add non esp marker to packet */
365 if (data.len > MAX_PACKET - MARKER_LEN)
366 {
367 this->logger->log(this->logger, ERROR,
368 "unable to send packet: it's too big");
369 return FAILED;
370 }
371 marked = chunk_alloc(data.len + MARKER_LEN);
372 memset(marked.ptr, 0, MARKER_LEN);
373 memcpy(marked.ptr + MARKER_LEN, data.ptr, data.len);
374 /* let the packet do the clean up for us */
375 packet->set_data(packet, marked);
376 data = marked;
377 }
378 }
379 else
380 {
381 this->logger->log(this->logger, ERROR,
382 "unable to locate a send socket for port %d", sport);
383 return FAILED;
384 }
385
386 bytes_sent = sendto(skt, data.ptr, data.len, 0,
387 dst->get_sockaddr(dst), *(dst->get_sockaddr_len(dst)));
388
389 if (bytes_sent != data.len)
390 {
391 this->logger->log(this->logger, ERROR,
392 "error writing to socket: %s", strerror(errno));
393 return FAILED;
394 }
395 return SUCCESS;
396 }
397
398 /**
399 * implements socket_t.is_local_address
400 */
401 static bool is_local_address(private_socket_t *this, host_t *host)
402 {
403 struct ifaddrs *list;
404 struct ifaddrs *cur;
405 bool found = FALSE;
406
407 if (getifaddrs(&list) < 0)
408 {
409 return FALSE;
410 }
411
412 for (cur = list; cur != NULL; cur = cur->ifa_next)
413 {
414 if (!(cur->ifa_flags & IFF_UP))
415 {
416 /* ignore interface which are down */
417 continue;
418 }
419
420 if (cur->ifa_addr == NULL ||
421 cur->ifa_addr->sa_family != host->get_family(host))
422 {
423 /* no match in family */
424 continue;
425 }
426
427 switch (cur->ifa_addr->sa_family)
428 {
429 case AF_INET:
430 {
431 struct sockaddr_in *listed, *requested;
432 listed = (struct sockaddr_in*)cur->ifa_addr;
433 requested = (struct sockaddr_in*)host->get_sockaddr(host);
434 if (listed->sin_addr.s_addr == requested->sin_addr.s_addr)
435 {
436 found = TRUE;
437 }
438 break;
439 }
440 case AF_INET6:
441 {
442 struct sockaddr_in6 *listed, *requested;
443 listed = (struct sockaddr_in6*)cur->ifa_addr;
444 requested = (struct sockaddr_in6*)host->get_sockaddr(host);
445 if (memcmp(&listed->sin6_addr, &requested->sin6_addr,
446 sizeof(listed->sin6_addr)) == 0)
447 {
448 found = TRUE;
449 }
450 break;
451 }
452 default:
453 break;
454 }
455
456 if (found)
457 {
458 break;
459 }
460 }
461 freeifaddrs(list);
462 return found;
463 }
464
465
466 /**
467 * implements socket_t.create_local_address_list
468 */
469 static linked_list_t* create_local_address_list(private_socket_t *this)
470 {
471 struct ifaddrs *list;
472 struct ifaddrs *cur;
473 host_t *host;
474 linked_list_t *result = linked_list_create();
475
476 if (getifaddrs(&list) < 0)
477 {
478 return result;
479 }
480
481 for (cur = list; cur != NULL; cur = cur->ifa_next)
482 {
483 if (!(cur->ifa_flags & IFF_UP))
484 {
485 /* ignore interface which are down */
486 continue;
487 }
488
489 host = host_create_from_sockaddr(cur->ifa_addr);
490 if (host)
491 {
492 /* we use always the IKEv2 port. This is relevant for
493 * natd payload hashing. */
494 host->set_port(host, this->port);
495 result->insert_last(result, host);
496 }
497 }
498 freeifaddrs(list);
499 return result;
500 }
501
502 /**
503 * open a socket to send packets
504 */
505 static int open_send_socket(private_socket_t *this, int family, u_int16_t port)
506 {
507 int on = TRUE;
508 int type = UDP_ENCAP_ESPINUDP;
509 struct sockaddr_storage addr;
510 u_int ip_proto, ipsec_policy;
511 struct sadb_x_policy policy;
512 int skt;
513
514 memset(&addr, 0, sizeof(addr));
515 /* precalculate constants depending on address family */
516 switch (family)
517 {
518 case AF_INET:
519 {
520 struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
521 sin->sin_family = AF_INET;
522 sin->sin_addr.s_addr = INADDR_ANY;
523 sin->sin_port = htons(port);
524 ip_proto = IPPROTO_IP;
525 ipsec_policy = IP_IPSEC_POLICY;
526 break;
527 }
528 case AF_INET6:
529 {
530 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
531 sin6->sin6_family = AF_INET6;
532 memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any));
533 sin6->sin6_port = htons(port);
534 ip_proto = IPPROTO_IPV6;
535 ipsec_policy = IPV6_IPSEC_POLICY;
536 break;
537 }
538 default:
539 return 0;
540 }
541
542 skt = socket(family, SOCK_DGRAM, IPPROTO_UDP);
543 if (skt < 0)
544 {
545 this->logger->log(this->logger, ERROR, "could not open send socket: %s",
546 strerror(errno));
547 return 0;
548 }
549
550 if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
551 {
552 this->logger->log(this->logger, ERROR,
553 "unable to set SO_REUSEADDR on send socket: %s",
554 strerror(errno));
555 close(skt);
556 return 0;
557 }
558
559 /* bypass outgoung IKE traffic on send socket */
560 policy.sadb_x_policy_len = sizeof(policy) / sizeof(u_int64_t);
561 policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
562 policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS;
563 policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
564 policy.sadb_x_policy_reserved = 0;
565 policy.sadb_x_policy_id = 0;
566
567 if (setsockopt(skt, ip_proto, ipsec_policy, &policy, sizeof(policy)) < 0)
568 {
569 this->logger->log(this->logger, ERROR,
570 "unable to set IPSEC_POLICY on send socket: %s",
571 strerror(errno));
572 close(skt);
573 return 0;
574 }
575
576 /* We don't receive packets on the send socket, but we need a INBOUND policy.
577 * Otherwise, UDP decapsulation does not work!!! */
578 policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
579 if (setsockopt(skt, ip_proto, ipsec_policy, &policy, sizeof(policy)) < 0)
580 {
581 this->logger->log(this->logger, ERROR,
582 "unable to set IPSEC_POLICY on send socket: %s",
583 strerror(errno));
584 close(skt);
585 return 0;
586 }
587
588 /* bind the send socket */
589 if (bind(skt, (struct sockaddr *)&addr, sizeof(addr)) < 0)
590 {
591 this->logger->log(this->logger, ERROR, "unable to bind send socket: %s",
592 strerror(errno));
593 close(skt);
594 return 0;
595 }
596
597 /* enable UDP decapsulation globally */
598 if (setsockopt(skt, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
599 {
600 this->logger->log(this->logger, ERROR,
601 "unable to set UDP_ENCAP: %s; NAT-T may fail",
602 strerror(errno));
603 }
604
605 return skt;
606 }
607
608 /**
609 * open a socket to receive packets
610 */
611 static int open_recv_socket(private_socket_t *this, int family)
612 {
613 int skt;
614 int on = TRUE;
615 u_int proto_offset, ip_len, ip_proto, ipsec_policy, ip_pktinfo, udp_header, ike_header;
616 struct sadb_x_policy policy;
617
618 /* precalculate constants depending on address family */
619 switch (family)
620 {
621 case AF_INET:
622 proto_offset = IP_PROTO_OFFSET;
623 ip_len = IP_LEN;
624 ip_proto = IPPROTO_IP;
625 ip_pktinfo = IP_PKTINFO;
626 ipsec_policy = IP_IPSEC_POLICY;
627 break;
628 case AF_INET6:
629 proto_offset = IP6_PROTO_OFFSET;
630 ip_len = 0; /* IPv6 raw sockets contain no IP header */
631 ip_proto = IPPROTO_IPV6;
632 ip_pktinfo = IPV6_PKTINFO;
633 ipsec_policy = IPV6_IPSEC_POLICY;
634 break;
635 default:
636 return 0;
637 }
638 udp_header = ip_len;
639 ike_header = ip_len + UDP_LEN;
640
641 /* This filter code filters out all non-IKEv2 traffic on
642 * a SOCK_RAW IP_PROTP_UDP socket. Handling of other
643 * IKE versions is done in pluto.
644 */
645 struct sock_filter ikev2_filter_code[] =
646 {
647 /* Destination Port must be either port or natt_port */
648 BPF_STMT(BPF_LD+BPF_H+BPF_ABS, udp_header + 2),
649 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, this->port, 1, 0),
650 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, this->natt_port, 5, 12),
651 /* port */
652 /* IKE version must be 2.0 */
653 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, ike_header + IKE_VERSION_OFFSET),
654 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x20, 0, 10),
655 /* packet length is length in IKEv2 header + ip header + udp header */
656 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ike_header + IKE_LENGTH_OFFSET),
657 BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, ip_len + UDP_LEN),
658 BPF_STMT(BPF_RET+BPF_A, 0),
659 /* natt_port */
660 /* nat-t: check for marker */
661 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ike_header),
662 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 5),
663 /* nat-t: IKE version must be 2.0 */
664 BPF_STMT(BPF_LD+BPF_B+BPF_ABS, ike_header + MARKER_LEN + IKE_VERSION_OFFSET),
665 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x20, 0, 3),
666 /* nat-t: packet length is length in IKEv2 header + ip header + udp header + non esp marker */
667 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ike_header + MARKER_LEN + IKE_LENGTH_OFFSET),
668 BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, ip_len + UDP_LEN + MARKER_LEN),
669 BPF_STMT(BPF_RET+BPF_A, 0),
670 /* packet doesn't match, ignore */
671 BPF_STMT(BPF_RET+BPF_K, 0),
672 };
673
674 /* Filter struct to use with setsockopt */
675 struct sock_fprog ikev2_filter = {
676 sizeof(ikev2_filter_code) / sizeof(struct sock_filter),
677 ikev2_filter_code
678 };
679
680 /* set up a raw socket */
681 skt = socket(family, SOCK_RAW, IPPROTO_UDP);
682 if (skt < 0)
683 {
684 this->logger->log(this->logger, ERROR,
685 "unable to create raw socket: %s",
686 strerror(errno));
687 return 0;
688 }
689
690 if (setsockopt(skt, SOL_SOCKET, SO_ATTACH_FILTER,
691 &ikev2_filter, sizeof(ikev2_filter)) < 0)
692 {
693 this->logger->log(this->logger, ERROR,
694 "unable to attach IKEv2 filter to raw socket: %s",
695 strerror(errno));
696 close(skt);
697 return 0;
698 }
699
700 else if (setsockopt(skt, ip_proto, ip_pktinfo, &on, sizeof(on)) < 0)
701 {
702 this->logger->log(this->logger, ERROR,
703 "unable to set IPV6_PKTINFO on raw socket: %s",
704 strerror(errno));
705 close(skt);
706 return 0;
707 }
708
709 /* bypass incomining IKE traffic on this socket */
710 policy.sadb_x_policy_len = sizeof(policy) / sizeof(u_int64_t);
711 policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
712 policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS;
713 policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
714 policy.sadb_x_policy_reserved = 0;
715 policy.sadb_x_policy_id = 0;
716
717 if (setsockopt(skt, ip_proto, ipsec_policy, &policy, sizeof(policy)) < 0)
718 {
719 this->logger->log(this->logger, ERROR,
720 "unable to set IPSEC_POLICY on raw socket: %s",
721 strerror(errno));
722 close(skt);
723 return 0;
724 }
725
726 return skt;
727 }
728
729 /**
730 * implementation of socket_t.destroy
731 */
732 static void destroy(private_socket_t *this)
733 {
734 if (this->recv4)
735 {
736 close(this->recv4);
737 }
738 if (this->recv6)
739 {
740 close(this->recv6);
741 }
742 if (this->send4)
743 {
744 close(this->send4);
745 }
746 if (this->send6)
747 {
748 close(this->send6);
749 }
750 if (this->send4_natt)
751 {
752 close(this->send4_natt);
753 }
754 if (this->send6_natt)
755 {
756 close(this->send6_natt);
757 }
758 free(this);
759 }
760
761 /*
762 * See header for description
763 */
764 socket_t *socket_create(u_int16_t port, u_int16_t natt_port)
765 {
766 private_socket_t *this = malloc_thing(private_socket_t);
767
768 /* public functions */
769 this->public.send = (status_t(*)(socket_t*, packet_t*))sender;
770 this->public.receive = (status_t(*)(socket_t*, packet_t**))receiver;
771 this->public.is_local_address = (bool(*)(socket_t*, host_t*))is_local_address;
772 this->public.create_local_address_list = (linked_list_t*(*)(socket_t*))create_local_address_list;
773 this->public.destroy = (void(*)(socket_t*)) destroy;
774
775 this->logger = logger_manager->get_logger(logger_manager, SOCKET);
776
777 this->port = port;
778 this->natt_port = natt_port;
779 this->recv4 = 0;
780 this->recv6 = 0;
781 this->send4 = 0;
782 this->send6 = 0;
783 this->send4_natt = 0;
784 this->send6_natt = 0;
785
786 this->recv4 = open_recv_socket(this, AF_INET);
787 if (this->recv4 == 0)
788 {
789 this->logger->log(this->logger, ERROR,
790 "could not open IPv4 receive socket, IPv4 disabled");
791 }
792 else
793 {
794 this->send4 = open_send_socket(this, AF_INET, this->port);
795 if (this->send4 == 0)
796 {
797 this->logger->log(this->logger, ERROR,
798 "could not open IPv4 send socket, IPv4 disabled");
799 close(this->recv4);
800 }
801 else
802 {
803 this->send4_natt = open_send_socket(this, AF_INET, this->natt_port);
804 if (this->send4_natt == 0)
805 {
806 this->logger->log(this->logger, ERROR,
807 "could not open IPv4 NAT-T send socket");
808 }
809 }
810 }
811
812 this->recv6 = open_recv_socket(this, AF_INET6);
813 if (this->recv6 == 0)
814 {
815 this->logger->log(this->logger, ERROR,
816 "could not open IPv6 receive socket, IPv6 disabled");
817 }
818 else
819 {
820 this->send6 = open_send_socket(this, AF_INET6, this->port);
821 if (this->send4 == 0)
822 {
823 this->logger->log(this->logger, ERROR,
824 "could not open IPv6 send socket, IPv6 disabled");
825 close(this->recv6);
826 }
827 else
828 {
829 this->send6_natt = open_send_socket(this, AF_INET, this->natt_port);
830 if (this->send6_natt == 0)
831 {
832 this->logger->log(this->logger, ERROR,
833 "could not open IPv6 NAT-T send socket");
834 }
835 }
836 }
837
838 if (!(this->send4 || this->send6) || !(this->recv4 || this->recv6))
839 {
840 this->logger->log(this->logger, ERROR,
841 "could not create any sockets");
842 destroy(this);
843 charon->kill(charon, "socket initialization failed");
844 }
845
846 return (socket_t*)this;
847 }