796cd04a8f3ff2c1863e7d6959cb3b64e748bfe8
[strongswan.git] / src / charon / threads / kernel_interface.c
1 /**
2 * @file kernel_interface.c
3 *
4 * @brief Implementation of kernel_interface_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 * Copyright (C) 2003 Herbert Xu.
14 *
15 * Contains modified parts from pluto.
16 *
17 * This program is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License as published by the
19 * Free Software Foundation; either version 2 of the License, or (at your
20 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
21 *
22 * This program is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 * for more details.
26 */
27
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <linux/netlink.h>
31 #include <linux/rtnetlink.h>
32 #include <linux/xfrm.h>
33 #include <linux/udp.h>
34 #include <pthread.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 #include <string.h>
39
40 #include "kernel_interface.h"
41
42 #include <daemon.h>
43 #include <utils/linked_list.h>
44 #include <queues/jobs/delete_child_sa_job.h>
45 #include <queues/jobs/rekey_child_sa_job.h>
46 #include <queues/jobs/acquire_job.h>
47
48 /** kernel level protocol identifiers */
49 #define KERNEL_ESP 50
50 #define KERNEL_AH 51
51
52 /** default priority of installed policies */
53 #define SPD_PRIORITY 1024
54
55 #define BUFFER_SIZE 1024
56
57 /**
58 * returns a pointer to the first rtattr following the nlmsghdr *nlh and the
59 * 'usual' netlink data x like 'struct xfrm_usersa_info'
60 */
61 #define XFRM_RTA(nlh, x) ((struct rtattr*)(NLMSG_DATA(nlh) + NLMSG_ALIGN(sizeof(x))))
62 /**
63 * returns a pointer to the next rtattr following rta.
64 * !!! do not use this to parse messages. use RTA_NEXT and RTA_OK instead !!!
65 */
66 #define XFRM_RTA_NEXT(rta) ((struct rtattr*)(((char*)(rta)) + RTA_ALIGN((rta)->rta_len)))
67 /**
68 * returns the total size of attached rta data
69 * (after 'usual' netlink data x like 'struct xfrm_usersa_info')
70 */
71 #define XFRM_PAYLOAD(nlh, x) NLMSG_PAYLOAD(nlh, sizeof(x))
72
73 typedef struct kernel_algorithm_t kernel_algorithm_t;
74
75 /**
76 * Mapping from the algorithms defined in IKEv2 to
77 * kernel level algorithm names and their key length
78 */
79 struct kernel_algorithm_t {
80 /**
81 * Identifier specified in IKEv2
82 */
83 int ikev2_id;
84
85 /**
86 * Name of the algorithm, as used as kernel identifier
87 */
88 char *name;
89
90 /**
91 * Key length in bits, if fixed size
92 */
93 u_int key_size;
94 };
95 #define END_OF_LIST -1
96
97 /**
98 * Algorithms for encryption
99 */
100 kernel_algorithm_t encryption_algs[] = {
101 /* {ENCR_DES_IV64, "***", 0}, */
102 {ENCR_DES, "des", 64},
103 {ENCR_3DES, "des3_ede", 192},
104 /* {ENCR_RC5, "***", 0}, */
105 /* {ENCR_IDEA, "***", 0}, */
106 {ENCR_CAST, "cast128", 0},
107 {ENCR_BLOWFISH, "blowfish", 0},
108 /* {ENCR_3IDEA, "***", 0}, */
109 /* {ENCR_DES_IV32, "***", 0}, */
110 {ENCR_NULL, "cipher_null", 0},
111 {ENCR_AES_CBC, "aes", 0},
112 /* {ENCR_AES_CTR, "***", 0}, */
113 {END_OF_LIST, NULL, 0},
114 };
115
116 /**
117 * Algorithms for integrity protection
118 */
119 kernel_algorithm_t integrity_algs[] = {
120 {AUTH_HMAC_MD5_96, "md5", 128},
121 {AUTH_HMAC_SHA1_96, "sha1", 160},
122 /* {AUTH_DES_MAC, "***", 0}, */
123 /* {AUTH_KPDK_MD5, "***", 0}, */
124 /* {AUTH_AES_XCBC_96, "***", 0}, */
125 {END_OF_LIST, NULL, 0},
126 };
127
128 /**
129 * Look up a kernel algorithm name and its key size
130 */
131 char* lookup_algorithm(kernel_algorithm_t *kernel_algo,
132 algorithm_t *ikev2_algo, u_int *key_size)
133 {
134 while (kernel_algo->ikev2_id != END_OF_LIST)
135 {
136 if (ikev2_algo->algorithm == kernel_algo->ikev2_id)
137 {
138 /* match, evaluate key length */
139 if (ikev2_algo->key_size)
140 { /* variable length */
141 *key_size = ikev2_algo->key_size;
142 }
143 else
144 { /* fixed length */
145 *key_size = kernel_algo->key_size;
146 }
147 return kernel_algo->name;
148 }
149 kernel_algo++;
150 }
151 return NULL;
152 }
153
154
155
156 typedef struct kernel_policy_t kernel_policy_t;
157
158 /**
159 * Installed kernel policy.
160 */
161 struct kernel_policy_t {
162
163 /** direction of this policy: in, out, forward */
164 u_int8_t direction;
165
166 /** reqid of the policy */
167 u_int32_t reqid;
168
169 /** parameters of installed policy */
170 struct xfrm_selector sel;
171
172 /** by how many CHILD_SA's this policy is used */
173 u_int refcount;
174 };
175
176
177 typedef struct private_kernel_interface_t private_kernel_interface_t;
178
179 /**
180 * Private Variables and Functions of kernel_interface class.
181 */
182 struct private_kernel_interface_t {
183 /**
184 * Public part of the kernel_interface_t object.
185 */
186 kernel_interface_t public;
187
188 /**
189 * List of installed policies (kernel_policy_t)
190 */
191 linked_list_t *policies;
192
193 /**
194 * Mutex locks access to policies list.
195 */
196 pthread_mutex_t pol_mutex;
197
198 /**
199 * Netlink communication socket.
200 */
201 int socket;
202
203 /**
204 * Process id of kernel thread
205 */
206 pid_t pid;
207
208 /**
209 * Sequence number for messages.
210 */
211 u_int32_t seq;
212
213 /**
214 * List of responded messages.
215 */
216 linked_list_t *responses;
217
218 /**
219 * Thread which receives messages.
220 */
221 pthread_t thread;
222
223 /**
224 * Mutex locks access to replies list.
225 */
226 pthread_mutex_t rep_mutex;
227
228 /**
229 * Condvar allows signaling of threads waiting for a reply.
230 */
231 pthread_cond_t condvar;
232
233 /**
234 * Logger for XFRM stuff
235 */
236 logger_t *logger;
237 };
238
239
240 /**
241 * Send a message down to the kernel and wait for its response
242 */
243 static status_t send_message(private_kernel_interface_t *this,
244 struct nlmsghdr *request, struct nlmsghdr **response)
245 {
246 size_t length;
247 struct sockaddr_nl addr;
248
249 request->nlmsg_seq = ++this->seq;
250 request->nlmsg_pid = 0;
251
252 memset(&addr, 0, sizeof(struct sockaddr_nl));
253 addr.nl_family = AF_NETLINK;
254 addr.nl_pid = 0;
255 addr.nl_groups = 0;
256
257 length = sendto(this->socket,(void *)request, request->nlmsg_len, 0,
258 (struct sockaddr *)&addr, sizeof(addr));
259
260 if (length < 0)
261 {
262 return FAILED;
263 }
264 else if (length != request->nlmsg_len)
265 {
266 return FAILED;
267 }
268
269 pthread_mutex_lock(&(this->rep_mutex));
270
271 while (TRUE)
272 {
273 iterator_t *iterator;
274 bool found = FALSE;
275 /* search list, break if found */
276 iterator = this->responses->create_iterator(this->responses, TRUE);
277 while (iterator->has_next(iterator))
278 {
279 struct nlmsghdr *listed_response;
280 iterator->current(iterator, (void**)&listed_response);
281 if (listed_response->nlmsg_seq == request->nlmsg_seq)
282 {
283 /* matches our request, this is the reply */
284 *response = listed_response;
285 iterator->remove(iterator);
286 found = TRUE;
287 break;
288 }
289 }
290 iterator->destroy(iterator);
291
292 if (found)
293 {
294 break;
295 }
296 /* TODO: we should time out, if something goes wrong!??? */
297 pthread_cond_wait(&(this->condvar), &(this->rep_mutex));
298 }
299
300 pthread_mutex_unlock(&(this->rep_mutex));
301
302 return SUCCESS;
303 }
304
305 /**
306 * Implementation of private_kernel_interface_t.receive_messages.
307 */
308 static void receive_messages(private_kernel_interface_t *this)
309 {
310 while(TRUE)
311 {
312 unsigned char response[BUFFER_SIZE];
313 struct nlmsghdr *hdr, *listed_response;
314 while (TRUE)
315 {
316 struct sockaddr_nl addr;
317 socklen_t addr_length;
318 size_t length;
319
320 addr_length = sizeof(addr);
321
322 length = recvfrom(this->socket, &response, sizeof(response), 0, (struct sockaddr*)&addr, &addr_length);
323 if (length < 0)
324 {
325 if (errno == EINTR)
326 {
327 /* interrupted, try again */
328 continue;
329 }
330 charon->kill(charon, "receiving from netlink socket failed");
331 }
332 if (!NLMSG_OK((struct nlmsghdr *)response, length))
333 {
334 /* bad netlink message */
335 continue;
336 }
337 if (addr.nl_pid != 0)
338 {
339 /* not from kernel. not interested, try another one */
340 continue;
341 }
342 /* good message, handle it */
343 break;
344 }
345
346 /* we handle ACQUIRE and EXPIRE messages directly */
347 hdr = (struct nlmsghdr*)response;
348 if (hdr->nlmsg_type == XFRM_MSG_ACQUIRE)
349 {
350 u_int32_t reqid = 0;
351 job_t *job;
352 struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_user_acquire);
353 size_t rtsize = XFRM_PAYLOAD(hdr, struct xfrm_user_tmpl);
354 if (RTA_OK(rthdr, rtsize))
355 {
356 if (rthdr->rta_type == XFRMA_TMPL)
357 {
358 struct xfrm_user_tmpl* tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rthdr);
359 reqid = tmpl->reqid;
360 }
361 }
362 if (reqid == 0)
363 {
364 this->logger->log(this->logger, ERROR,
365 "Received a XFRM_MSG_ACQUIRE, but no reqid found");
366 }
367 else
368 {
369 this->logger->log(this->logger, CONTROL|LEVEL1,
370 "Received a XFRM_MSG_ACQUIRE");
371 this->logger->log(this->logger, CONTROL,
372 "creating acquire job for CHILD_SA with reqid %d",
373 reqid);
374 job = (job_t*)acquire_job_create(reqid);
375 charon->job_queue->add(charon->job_queue, job);
376 }
377 }
378 else if (hdr->nlmsg_type == XFRM_MSG_EXPIRE)
379 {
380 job_t *job;
381 protocol_id_t protocol;
382 u_int32_t spi, reqid;
383 struct xfrm_user_expire *expire;
384
385 expire = (struct xfrm_user_expire*)NLMSG_DATA(hdr);
386 protocol = expire->state.id.proto == KERNEL_ESP ?
387 PROTO_ESP : PROTO_AH;
388 spi = expire->state.id.spi;
389 reqid = expire->state.reqid;
390
391 this->logger->log(this->logger, CONTROL|LEVEL1,
392 "Received a XFRM_MSG_EXPIRE");
393 this->logger->log(this->logger, CONTROL,
394 "creating %s job for %s CHILD_SA 0x%x (reqid %d)",
395 expire->hard ? "delete" : "rekey",
396 mapping_find(protocol_id_m, protocol), ntohl(spi),
397 reqid);
398 if (expire->hard)
399 {
400 job = (job_t*)delete_child_sa_job_create(reqid, protocol, spi);
401 }
402 else
403 {
404 job = (job_t*)rekey_child_sa_job_create(reqid, protocol, spi);
405 }
406 charon->job_queue->add(charon->job_queue, job);
407 }
408 /* NLMSG_ERROR is sent back for acknowledge (or on error), an
409 * XFRM_MSG_NEWSA is returned when we alloc spis and when
410 * updating SAs.
411 * XFRM_MSG_NEWPOLICY is returned when we query a policy.
412 * list these responses for the sender
413 */
414 else if (hdr->nlmsg_type == NLMSG_ERROR ||
415 hdr->nlmsg_type == XFRM_MSG_NEWSA ||
416 hdr->nlmsg_type == XFRM_MSG_NEWPOLICY)
417 {
418 /* add response to queue */
419 listed_response = malloc(hdr->nlmsg_len);
420 memcpy(listed_response, &response, hdr->nlmsg_len);
421
422 pthread_mutex_lock(&(this->rep_mutex));
423 this->responses->insert_last(this->responses, (void*)listed_response);
424 pthread_mutex_unlock(&(this->rep_mutex));
425 /* signal ALL waiting threads */
426 pthread_cond_broadcast(&(this->condvar));
427 }
428 /* we are not interested in anything other.
429 * anyway, move on to the next message */
430 continue;
431 }
432 }
433
434 /**
435 * convert a host_t to a struct xfrm_address
436 */
437 static void host2xfrm(host_t *host, xfrm_address_t *xfrm)
438 {
439 chunk_t chunk = host->get_address(host);
440 memcpy(xfrm, chunk.ptr, max(chunk.len, sizeof(xfrm_address_t)));
441 }
442
443 /**
444 * Implementation of kernel_interface_t.get_spi.
445 */
446 static status_t get_spi(private_kernel_interface_t *this,
447 host_t *src, host_t *dst,
448 protocol_id_t protocol, u_int32_t reqid,
449 u_int32_t *spi)
450 {
451 unsigned char request[BUFFER_SIZE];
452 struct nlmsghdr *response;
453 struct nlmsghdr *hdr;
454 struct xfrm_userspi_info *userspi;
455
456 memset(&request, 0, sizeof(request));
457 status_t status = SUCCESS;
458
459 this->logger->log(this->logger, CONTROL|LEVEL2, "getting spi");
460
461 hdr = (struct nlmsghdr*)request;
462 hdr->nlmsg_flags = NLM_F_REQUEST;
463 hdr->nlmsg_type = XFRM_MSG_ALLOCSPI;
464 hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userspi_info));
465
466 userspi = (struct xfrm_userspi_info*)NLMSG_DATA(hdr);
467 host2xfrm(src, &userspi->info.saddr);
468 host2xfrm(dst, &userspi->info.id.daddr);
469 userspi->info.id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
470 userspi->info.mode = TRUE; /* tunnel mode */
471 userspi->info.reqid = reqid;
472 userspi->info.family = src->get_family(src);
473 userspi->min = 0xc0000000;
474 userspi->max = 0xcFFFFFFF;
475
476 if (send_message(this, hdr, &response) != SUCCESS)
477 {
478 this->logger->log(this->logger, ERROR, "netlink communication failed");
479 return FAILED;
480 }
481 else if (response->nlmsg_type == NLMSG_ERROR)
482 {
483 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_ALLOCSPI got an error: %s",
484 strerror(-((struct nlmsgerr*)NLMSG_DATA(response))->error));
485 status = FAILED;
486 }
487 else if (response->nlmsg_type != XFRM_MSG_NEWSA)
488 {
489 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_ALLOCSPI got a unknown reply");
490 status = FAILED;
491 }
492 else if (response->nlmsg_len < NLMSG_LENGTH(sizeof(struct xfrm_usersa_info)))
493 {
494 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_ALLOCSPI got an invalid reply");
495 status = FAILED;
496 }
497 else
498 {
499 *spi = ((struct xfrm_usersa_info*)NLMSG_DATA(response))->id.spi;
500 this->logger->log(this->logger, CONTROL|LEVEL1, "SPI is 0x%x", *spi);
501 }
502 free(response);
503
504 return status;
505 }
506
507 /**
508 * Implementation of kernel_interface_t.add_sa.
509 */
510 static status_t add_sa(private_kernel_interface_t *this,
511 host_t *src, host_t *dst, u_int32_t spi,
512 protocol_id_t protocol, u_int32_t reqid,
513 u_int64_t expire_soft, u_int64_t expire_hard,
514 algorithm_t *enc_alg, algorithm_t *int_alg,
515 prf_plus_t *prf_plus, natt_conf_t *natt,
516 bool replace)
517 {
518 unsigned char request[BUFFER_SIZE];
519 struct nlmsghdr *response;
520 char *alg_name;
521 size_t key_size;
522 struct nlmsghdr *hdr;
523 struct xfrm_usersa_info *sa;
524
525 memset(&request, 0, sizeof(request));
526 status_t status = SUCCESS;
527
528 this->logger->log(this->logger, CONTROL|LEVEL2, "adding SA");
529
530 hdr = (struct nlmsghdr*)request;
531 hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
532 hdr->nlmsg_type = replace ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
533 hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
534
535 sa = (struct xfrm_usersa_info*)NLMSG_DATA(hdr);
536 host2xfrm(src, &sa->saddr);
537 host2xfrm(dst, &sa->id.daddr);
538 sa->id.spi = spi;
539 sa->id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
540 sa->family = src->get_family(src);
541 sa->mode = TRUE; /* tunnel mode */
542 sa->replay_window = 32;
543 sa->reqid = reqid;
544 /* we currently do not expire SAs by volume/packet count */
545 sa->lft.soft_byte_limit = XFRM_INF;
546 sa->lft.hard_byte_limit = XFRM_INF;
547 sa->lft.soft_packet_limit = XFRM_INF;
548 sa->lft.hard_packet_limit = XFRM_INF;
549 /* we use lifetimes since added, not since used */
550 sa->lft.soft_add_expires_seconds = expire_soft;
551 sa->lft.hard_add_expires_seconds = expire_hard;
552 sa->lft.soft_use_expires_seconds = 0;
553 sa->lft.hard_use_expires_seconds = 0;
554
555 struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_info);
556
557 if (enc_alg->algorithm != ENCR_UNDEFINED)
558 {
559 rthdr->rta_type = XFRMA_ALG_CRYPT;
560 alg_name = lookup_algorithm(encryption_algs, enc_alg, &key_size);
561 if (alg_name == NULL)
562 {
563 this->logger->log(this->logger, ERROR, "Algorithm %s not supported by kernel!",
564 mapping_find(encryption_algorithm_m, enc_alg->algorithm));
565 return FAILED;
566 }
567 this->logger->log(this->logger, CONTROL|LEVEL2, " using encryption algorithm %s with key size %d",
568 mapping_find(encryption_algorithm_m, enc_alg->algorithm), key_size);
569
570 rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + key_size);
571 hdr->nlmsg_len += rthdr->rta_len;
572 if (hdr->nlmsg_len > sizeof(request))
573 {
574 return FAILED;
575 }
576
577 struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr);
578 algo->alg_key_len = key_size;
579 strcpy(algo->alg_name, alg_name);
580 prf_plus->get_bytes(prf_plus, key_size / 8, algo->alg_key);
581
582 rthdr = XFRM_RTA_NEXT(rthdr);
583 }
584
585 if (int_alg->algorithm != AUTH_UNDEFINED)
586 {
587 rthdr->rta_type = XFRMA_ALG_AUTH;
588 alg_name = lookup_algorithm(integrity_algs, int_alg, &key_size);
589 if (alg_name == NULL)
590 {
591 this->logger->log(this->logger, ERROR, "Algorithm %s not supported by kernel!",
592 mapping_find(integrity_algorithm_m, int_alg->algorithm));
593 return FAILED;
594 }
595 this->logger->log(this->logger, CONTROL|LEVEL2, " using integrity algorithm %s with key size %d",
596 mapping_find(integrity_algorithm_m, int_alg->algorithm), key_size);
597
598 rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + key_size);
599 hdr->nlmsg_len += rthdr->rta_len;
600 if (hdr->nlmsg_len > sizeof(request))
601 {
602 return FAILED;
603 }
604
605 struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr);
606 algo->alg_key_len = key_size;
607 strcpy(algo->alg_name, alg_name);
608 prf_plus->get_bytes(prf_plus, key_size / 8, algo->alg_key);
609
610 rthdr = XFRM_RTA_NEXT(rthdr);
611 }
612
613 /* TODO: add IPComp here */
614
615 if (natt)
616 {
617 rthdr->rta_type = XFRMA_ENCAP;
618 rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl));
619
620 hdr->nlmsg_len += rthdr->rta_len;
621 if (hdr->nlmsg_len > sizeof(request))
622 {
623 return FAILED;
624 }
625
626 struct xfrm_encap_tmpl* encap = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr);
627 encap->encap_type = UDP_ENCAP_ESPINUDP;
628 encap->encap_sport = htons(natt->sport);
629 encap->encap_dport = htons(natt->dport);
630 memset(&encap->encap_oa, 0, sizeof (xfrm_address_t));
631 /* encap_oa could probably be derived from the
632 * traffic selectors [rfc4306, p39]. In the netlink kernel implementation
633 * pluto does the same as we do here but it uses encap_oa in the
634 * pfkey implementation. BUT as /usr/src/linux/net/key/af_key.c indicates
635 * the kernel ignores it anyway
636 * -> does that mean that NAT-T encap doesn't work in transport mode?
637 * No. The reason the kernel ignores NAT-OA is that it recomputes
638 * (or, rather, just ignores) the checksum. If packets pass
639 * the IPSec checks it marks them "checksum ok" so OA isn't needed. */
640
641 rthdr = XFRM_RTA_NEXT(rthdr);
642 }
643
644 if (send_message(this, hdr, &response) != SUCCESS)
645 {
646 this->logger->log(this->logger, ERROR, "netlink communication failed");
647 return FAILED;
648 }
649 else if (response->nlmsg_type != NLMSG_ERROR)
650 {
651 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWSA not acknowledged");
652 status = FAILED;
653 }
654 else if (((struct nlmsgerr*)NLMSG_DATA(response))->error)
655 {
656 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWSA got an error: %s",
657 strerror(-((struct nlmsgerr*)NLMSG_DATA(response))->error));
658 status = FAILED;
659 }
660
661 free(response);
662 return status;
663 }
664
665 /**
666 * Implementation of kernel_interface_t.update_sa.
667 */
668 static status_t update_sa(
669 private_kernel_interface_t *this,
670 host_t *src, host_t *dst,
671 host_t *new_src, host_t *new_dst,
672 host_diff_t src_changes, host_diff_t dst_changes,
673 u_int32_t spi, protocol_id_t protocol)
674 {
675 unsigned char request[BUFFER_SIZE];
676 struct nlmsghdr *update, *response;
677 struct nlmsghdr *hdr;
678 struct xfrm_usersa_id *sa_id;
679
680 memset(&request, 0, sizeof(request));
681 status_t status = SUCCESS;
682
683 this->logger->log(this->logger, CONTROL|LEVEL2, "getting SA");
684
685 hdr = (struct nlmsghdr*)request;
686 hdr->nlmsg_flags = NLM_F_REQUEST;
687 hdr->nlmsg_type = XFRM_MSG_GETSA;
688 hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
689
690 sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
691 host2xfrm(dst, &sa_id->daddr);
692 sa_id->spi = spi;
693 sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
694 sa_id->family = dst->get_family(dst);
695
696 if (send_message(this, hdr, &update) != SUCCESS)
697 {
698 this->logger->log(this->logger, ERROR, "netlink communication failed");
699 return FAILED;
700 }
701 else if (update->nlmsg_type == NLMSG_ERROR)
702 {
703 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_GETSA got an error: %s",
704 strerror(-((struct nlmsgerr*)NLMSG_DATA(update))->error));
705 free(update);
706 return FAILED;
707 }
708 else if (update->nlmsg_type != XFRM_MSG_NEWSA)
709 {
710 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_GETSA got a unknown reply");
711 free(update);
712 return FAILED;
713 }
714 else if (update->nlmsg_len < NLMSG_LENGTH(sizeof(struct xfrm_usersa_info)))
715 {
716 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_GETSA got an invalid reply");
717 free(update);
718 return FAILED;
719 }
720
721 this->logger->log(this->logger, CONTROL|LEVEL2, "updating SA");
722 update->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
723 update->nlmsg_type = XFRM_MSG_UPDSA;
724
725 struct xfrm_usersa_info *sa = (struct xfrm_usersa_info*)NLMSG_DATA(update);
726 if (src_changes & HOST_DIFF_ADDR)
727 {
728 host2xfrm(new_src, &sa->saddr);
729 }
730
731 if (dst_changes & HOST_DIFF_ADDR)
732 {
733 this->logger->log(this->logger, CONTROL|LEVEL2, "destination address changed! replacing SA");
734
735 update->nlmsg_type = XFRM_MSG_NEWSA;
736 host2xfrm(new_dst, &sa->id.daddr);
737 }
738
739 if (src_changes & HOST_DIFF_PORT || dst_changes & HOST_DIFF_PORT)
740 {
741 struct rtattr *rthdr = XFRM_RTA(update, struct xfrm_usersa_info);
742 size_t rtsize = XFRM_PAYLOAD(update, struct xfrm_usersa_info);
743 while (RTA_OK(rthdr, rtsize))
744 {
745 if (rthdr->rta_type == XFRMA_ENCAP)
746 {
747 struct xfrm_encap_tmpl* encap = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr);
748 encap->encap_sport = ntohs(new_src->get_port(new_src));
749 encap->encap_dport = ntohs(new_dst->get_port(new_dst));
750 break;
751 }
752 rthdr = RTA_NEXT(rthdr, rtsize);
753 }
754 }
755
756 if (send_message(this, update, &response) != SUCCESS)
757 {
758 this->logger->log(this->logger, ERROR, "netlink communication failed");
759 free(update);
760 return FAILED;
761 }
762 else if (response->nlmsg_type != NLMSG_ERROR)
763 {
764 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_XXXSA not acknowledged");
765 status = FAILED;
766 }
767 else if (((struct nlmsgerr*)NLMSG_DATA(response))->error)
768 {
769 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_XXXSA got an error: %s",
770 strerror(-((struct nlmsgerr*)NLMSG_DATA(response))->error));
771 status = FAILED;
772 }
773 else if (dst_changes & HOST_DIFF_ADDR)
774 {
775 this->logger->log(this->logger, CONTROL|LEVEL2, "deleting old SA");
776 status = this->public.del_sa(&this->public, dst, spi, protocol);
777 }
778
779 free(update);
780 free(response);
781 return status;
782 }
783
784 /**
785 * Implementation of kernel_interface_t.query_sa.
786 */
787 static status_t query_sa(private_kernel_interface_t *this, host_t *dst,
788 u_int32_t spi, protocol_id_t protocol, u_int32_t *use_time)
789 {
790 unsigned char request[BUFFER_SIZE];
791 struct nlmsghdr *response;
792 struct nlmsghdr *hdr;
793 struct xfrm_usersa_id *sa_id;
794 struct xfrm_usersa_info *sa_info;
795
796 this->logger->log(this->logger, CONTROL|LEVEL2, "querying SA");
797 memset(&request, 0, sizeof(request));
798
799 hdr = (struct nlmsghdr*)request;
800 hdr->nlmsg_flags = NLM_F_REQUEST;
801 hdr->nlmsg_type = XFRM_MSG_GETSA;
802 hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
803
804 sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
805 host2xfrm(dst, &sa_id->daddr);
806 sa_id->spi = spi;
807 sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
808 sa_id->family = dst->get_family(dst);
809
810 if (send_message(this, hdr, &response) != SUCCESS)
811 {
812 this->logger->log(this->logger, ERROR, "netlink communication failed");
813 return FAILED;
814 }
815 else if (response->nlmsg_type != XFRM_MSG_NEWSA)
816 {
817 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_GETSA not acknowledged");
818 free(response);
819 return FAILED;
820 }
821 else if (response->nlmsg_len < NLMSG_LENGTH(sizeof(struct xfrm_usersa_info)))
822 {
823 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_GETSA got an invalid reply");
824 free(response);
825 return FAILED;
826 }
827
828 sa_info = (struct xfrm_usersa_info*)NLMSG_DATA(response);
829 *use_time = sa_info->curlft.use_time;
830
831 free(response);
832 return SUCCESS;
833 }
834
835 /**
836 * Implementation of kernel_interface_t.del_sa.
837 */
838 static status_t del_sa(private_kernel_interface_t *this, host_t *dst,
839 u_int32_t spi, protocol_id_t protocol)
840 {
841 unsigned char request[BUFFER_SIZE];
842 struct nlmsghdr *response;
843 struct nlmsghdr *hdr;
844 struct xfrm_usersa_id *sa_id;
845
846 memset(&request, 0, sizeof(request));
847 status_t status = SUCCESS;
848
849 this->logger->log(this->logger, CONTROL|LEVEL2, "deleting SA");
850
851 hdr = (struct nlmsghdr*)request;
852 hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
853 hdr->nlmsg_type = XFRM_MSG_DELSA;
854 hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
855
856 sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
857 host2xfrm(dst, &sa_id->daddr);
858 sa_id->spi = spi;
859 sa_id->proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
860 sa_id->family = dst->get_family(dst);
861
862 if (send_message(this, hdr, &response) != SUCCESS)
863 {
864 this->logger->log(this->logger, ERROR, "netlink communication failed");
865 return FAILED;
866 }
867 else if (response->nlmsg_type != NLMSG_ERROR)
868 {
869 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_DELSA not acknowledged");
870 status = FAILED;
871 }
872 else if (((struct nlmsgerr*)NLMSG_DATA(response))->error)
873 {
874 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_DELSA got an error: %s",
875 strerror(-((struct nlmsgerr*)NLMSG_DATA(response))->error));
876 status = FAILED;
877 }
878
879 free(response);
880 return status;
881 }
882
883 /**
884 * convert a traffic selector address range to subnet and its mask.
885 */
886 static void ts2subnet(traffic_selector_t* ts,
887 xfrm_address_t *net, u_int8_t *mask)
888 {
889 /* there is no way to do this cleanly, as the address range may
890 * be anything else but a subnet. We use from_addr as subnet
891 * and try to calculate a usable subnet mask.
892 */
893 int byte, bit;
894 bool found = FALSE;
895 chunk_t from, to;
896 size_t size = (ts->get_type(ts) == TS_IPV4_ADDR_RANGE) ? 4 : 16;
897
898 from = ts->get_from_address(ts);
899 to = ts->get_to_address(ts);
900
901 *mask = (size * 8);
902 /* go trough all bits of the addresses, beginning in the front.
903 * As longer as they equal, the subnet gets larger */
904 for (byte = 0; byte < size; byte++)
905 {
906 for (bit = 7; bit >= 0; bit--)
907 {
908 if ((1<<bit & from.ptr[byte]) != (1<<bit & to.ptr[byte]))
909 {
910 *mask = ((7 - bit) + (byte * 8));
911 found = TRUE;
912 break;
913 }
914 }
915 if (found)
916 {
917 break;
918 }
919 }
920 memcpy(net, from.ptr, from.len);
921 chunk_free(&from);
922 chunk_free(&to);
923 }
924
925 /**
926 * convert a traffic selector port range to port/portmask
927 */
928 static void ts2ports(traffic_selector_t* ts,
929 u_int16_t *port, u_int16_t *mask)
930 {
931 /* linux does not seem to accept complex portmasks. Only
932 * any or a specific port is allowed. We set to any, if we have
933 * a port range, or to a specific, if we have one port only.
934 */
935 u_int16_t from, to;
936
937 from = ts->get_from_port(ts);
938 to = ts->get_to_port(ts);
939
940 if (from == to)
941 {
942 *port = htons(from);
943 *mask = ~0;
944 }
945 else
946 {
947 *port = 0;
948 *mask = 0;
949 }
950 }
951
952 /**
953 * convert a pair of traffic_selectors to a xfrm_selector
954 */
955 static struct xfrm_selector ts2selector(traffic_selector_t *src,
956 traffic_selector_t *dst)
957 {
958 struct xfrm_selector sel;
959
960 memset(&sel, 0, sizeof(sel));
961 sel.family = src->get_type(src) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6;
962 /* src or dest proto may be "any" (0), use more restrictive one */
963 sel.proto = max(src->get_protocol(src), dst->get_protocol(dst));
964 ts2subnet(dst, &sel.daddr, &sel.prefixlen_d);
965 ts2subnet(src, &sel.saddr, &sel.prefixlen_s);
966 ts2ports(dst, &sel.dport, &sel.dport_mask);
967 ts2ports(src, &sel.sport, &sel.sport_mask);
968 sel.ifindex = 0;
969 sel.user = 0;
970
971 return sel;
972 }
973
974 /**
975 * Implementation of kernel_interface_t.add_policy.
976 */
977 static status_t add_policy(private_kernel_interface_t *this,
978 host_t *src, host_t *dst,
979 traffic_selector_t *src_ts,
980 traffic_selector_t *dst_ts,
981 policy_dir_t direction, protocol_id_t protocol,
982 u_int32_t reqid, bool update)
983 {
984 iterator_t *iterator;
985 kernel_policy_t *current, *policy;
986 bool found = FALSE;
987 unsigned char request[BUFFER_SIZE];
988 struct nlmsghdr *response;
989 struct xfrm_userpolicy_info *policy_info;
990 struct nlmsghdr *hdr;
991 status_t status = SUCCESS;
992
993 /* create a policy */
994 policy = malloc_thing(kernel_policy_t);
995 memset(policy, 0, sizeof(kernel_policy_t));
996 policy->sel = ts2selector(src_ts, dst_ts);
997 policy->direction = direction;
998
999 /* find the policy, which matches EXACTLY */
1000 pthread_mutex_lock(&this->pol_mutex);
1001 iterator = this->policies->create_iterator(this->policies, TRUE);
1002 while (iterator->iterate(iterator, (void**)&current))
1003 {
1004 if (memcmp(current, policy, sizeof(struct xfrm_selector)) == 0 &&
1005 policy->direction == current->direction)
1006 {
1007 free(policy);
1008 /* use existing policy */
1009 if (!update)
1010 {
1011 current->refcount++;
1012 this->logger->log(this->logger, CONTROL|LEVEL1,
1013 "policy already exists, increasing refcount");
1014 }
1015 policy = current;
1016 found = TRUE;
1017 break;
1018 }
1019 }
1020 iterator->destroy(iterator);
1021 if (!found)
1022 { /* apply the new one, if we have no such policy */
1023 this->policies->insert_last(this->policies, policy);
1024 policy->refcount = 1;
1025 }
1026
1027 this->logger->log(this->logger, CONTROL|LEVEL2, "adding policy");
1028
1029 memset(&request, 0, sizeof(request));
1030 hdr = (struct nlmsghdr*)request;
1031 hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1032 hdr->nlmsg_type = XFRM_MSG_UPDPOLICY;
1033 hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info));
1034
1035 policy_info = (struct xfrm_userpolicy_info*)NLMSG_DATA(hdr);
1036 policy_info->sel = policy->sel;
1037 policy_info->dir = policy->direction;
1038 policy_info->priority = SPD_PRIORITY;
1039 policy_info->action = XFRM_POLICY_ALLOW;
1040 policy_info->share = XFRM_SHARE_ANY;
1041 pthread_mutex_unlock(&this->pol_mutex);
1042
1043 /* policies don't expire */
1044 policy_info->lft.soft_byte_limit = XFRM_INF;
1045 policy_info->lft.soft_packet_limit = XFRM_INF;
1046 policy_info->lft.hard_byte_limit = XFRM_INF;
1047 policy_info->lft.hard_packet_limit = XFRM_INF;
1048 policy_info->lft.soft_add_expires_seconds = 0;
1049 policy_info->lft.hard_add_expires_seconds = 0;
1050 policy_info->lft.soft_use_expires_seconds = 0;
1051 policy_info->lft.hard_use_expires_seconds = 0;
1052
1053 struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_info);
1054 rthdr->rta_type = XFRMA_TMPL;
1055
1056 rthdr->rta_len = sizeof(struct xfrm_user_tmpl);
1057 rthdr->rta_len = RTA_LENGTH(rthdr->rta_len);
1058
1059 hdr->nlmsg_len += rthdr->rta_len;
1060 if (hdr->nlmsg_len > sizeof(request))
1061 {
1062 return FAILED;
1063 }
1064
1065 struct xfrm_user_tmpl *tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rthdr);
1066 tmpl->reqid = reqid;
1067 tmpl->id.proto = (protocol == PROTO_AH) ? KERNEL_AH : KERNEL_ESP;
1068 tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
1069 tmpl->mode = TRUE;
1070 tmpl->family = src->get_family(src);
1071
1072 host2xfrm(src, &tmpl->saddr);
1073 host2xfrm(dst, &tmpl->id.daddr);
1074
1075 if (send_message(this, hdr, &response) != SUCCESS)
1076 {
1077 this->logger->log(this->logger, ERROR, "netlink communication failed");
1078 return FAILED;
1079 }
1080 else if (response->nlmsg_type != NLMSG_ERROR)
1081 {
1082 this->logger->log(this->logger, ERROR,
1083 "netlink request XFRM_MSG_UPDPOLICY not acknowledged");
1084 status = FAILED;
1085 }
1086 else if (((struct nlmsgerr*)NLMSG_DATA(response))->error)
1087 {
1088 this->logger->log(this->logger, ERROR,
1089 "netlink request XFRM_MSG_UPDPOLICY got an error: %s",
1090 strerror(-((struct nlmsgerr*)NLMSG_DATA(response))->error));
1091 status = FAILED;
1092 }
1093
1094 free(response);
1095 return status;
1096 }
1097
1098 /**
1099 * Implementation of kernel_interface_t.query_policy.
1100 */
1101 static status_t query_policy(private_kernel_interface_t *this,
1102 traffic_selector_t *src_ts,
1103 traffic_selector_t *dst_ts,
1104 policy_dir_t direction, u_int32_t *use_time)
1105 {
1106 unsigned char request[BUFFER_SIZE];
1107 struct nlmsghdr *response;
1108 struct nlmsghdr *hdr;
1109 struct xfrm_userpolicy_id *policy_id;
1110 struct xfrm_userpolicy_info *policy;
1111
1112 memset(&request, 0, sizeof(request));
1113 status_t status = SUCCESS;
1114
1115 this->logger->log(this->logger, CONTROL|LEVEL2, "querying policy");
1116
1117 hdr = (struct nlmsghdr*)request;
1118 hdr->nlmsg_flags = NLM_F_REQUEST;
1119 hdr->nlmsg_type = XFRM_MSG_GETPOLICY;
1120 hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id));
1121
1122 policy_id = (struct xfrm_userpolicy_id*)NLMSG_DATA(hdr);
1123 policy_id->sel = ts2selector(src_ts, dst_ts);
1124 policy_id->dir = direction;
1125
1126 if (send_message(this, hdr, &response) != SUCCESS)
1127 {
1128 this->logger->log(this->logger, ERROR, "netlink communication failed");
1129 return FAILED;
1130 }
1131 else if (response->nlmsg_type == NLMSG_ERROR)
1132 {
1133 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_GETPOLICY got an error: %s",
1134 strerror(-((struct nlmsgerr*)NLMSG_DATA(response))->error));
1135 free(response);
1136 return FAILED;
1137 }
1138 else if (response->nlmsg_type != XFRM_MSG_NEWPOLICY)
1139 {
1140 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_GETPOLICY got an unknown reply");
1141 free(response);
1142 return FAILED;
1143 }
1144 else if (response->nlmsg_len < NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info)))
1145 {
1146 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_GETPOLICY got an invalid reply");
1147 free(response);
1148 return FAILED;
1149 }
1150
1151 policy = (struct xfrm_userpolicy_info*)NLMSG_DATA(response);
1152
1153 *use_time = (time_t)policy->curlft.use_time;
1154
1155 free(response);
1156 return status;
1157 }
1158
1159 /**
1160 * Implementation of kernel_interface_t.del_policy.
1161 */
1162 static status_t del_policy(private_kernel_interface_t *this,
1163 traffic_selector_t *src_ts,
1164 traffic_selector_t *dst_ts,
1165 policy_dir_t direction)
1166 {
1167 kernel_policy_t *current, policy, *to_delete = NULL;
1168 unsigned char request[BUFFER_SIZE];
1169 struct nlmsghdr *response;
1170 struct nlmsghdr *hdr;
1171 struct xfrm_userpolicy_id *policy_id;
1172 iterator_t *iterator;
1173 status_t status = SUCCESS;
1174
1175 this->logger->log(this->logger, CONTROL|LEVEL2, "deleting policy");
1176
1177 /* create a policy */
1178 memset(&policy, 0, sizeof(kernel_policy_t));
1179 policy.sel = ts2selector(src_ts, dst_ts);
1180 policy.direction = direction;
1181
1182 /* find the policy */
1183 pthread_mutex_lock(&this->pol_mutex);
1184 iterator = this->policies->create_iterator(this->policies, TRUE);
1185 while (iterator->iterate(iterator, (void**)&current))
1186 {
1187 if (memcmp(&current->sel, &policy.sel, sizeof(struct xfrm_selector)) == 0 &&
1188 policy.direction == current->direction)
1189 {
1190 to_delete = current;
1191 if (--to_delete->refcount > 0)
1192 {
1193 /* is used by more SAs, keep in kernel */
1194 this->logger->log(this->logger, CONTROL|LEVEL1,
1195 "is used by other SAs, not removed");
1196 iterator->destroy(iterator);
1197 pthread_mutex_unlock(&this->pol_mutex);
1198 return SUCCESS;
1199 }
1200 /* remove if last reference */
1201 iterator->remove(iterator);
1202 break;
1203 }
1204 }
1205 iterator->destroy(iterator);
1206 pthread_mutex_unlock(&this->pol_mutex);
1207 if (!to_delete)
1208 {
1209 this->logger->log(this->logger, CONTROL|LEVEL2,
1210 "no such policy found");
1211 return NOT_FOUND;
1212 }
1213
1214 memset(&request, 0, sizeof(request));
1215
1216 hdr = (struct nlmsghdr*)request;
1217 hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1218 hdr->nlmsg_type = XFRM_MSG_DELPOLICY;
1219 hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id));
1220
1221 policy_id = (struct xfrm_userpolicy_id*)NLMSG_DATA(hdr);
1222 policy_id->sel = to_delete->sel;
1223 policy_id->dir = direction;
1224
1225 free(to_delete);
1226
1227 if (send_message(this, hdr, &response) != SUCCESS)
1228 {
1229 this->logger->log(this->logger, ERROR, "netlink communication failed");
1230 return FAILED;
1231 }
1232 else if (response->nlmsg_type != NLMSG_ERROR)
1233 {
1234 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_DELPOLICY not acknowledged");
1235 status = FAILED;
1236 }
1237 else if (((struct nlmsgerr*)NLMSG_DATA(response))->error)
1238 {
1239 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_DELPOLICY got an error: %s",
1240 strerror(-((struct nlmsgerr*)NLMSG_DATA(response))->error));
1241 status = FAILED;
1242 }
1243
1244 free(response);
1245 return status;
1246 }
1247
1248 /**
1249 * Implementation of kernel_interface_t.destroy.
1250 */
1251 static void destroy(private_kernel_interface_t *this)
1252 {
1253 pthread_cancel(this->thread);
1254 pthread_join(this->thread, NULL);
1255 close(this->socket);
1256 this->responses->destroy(this->responses);
1257 this->policies->destroy(this->policies);
1258 free(this);
1259 }
1260
1261 /*
1262 * Described in header.
1263 */
1264 kernel_interface_t *kernel_interface_create()
1265 {
1266 struct sockaddr_nl addr;
1267 private_kernel_interface_t *this = malloc_thing(private_kernel_interface_t);
1268
1269 /* public functions */
1270 this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
1271 this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,algorithm_t*,algorithm_t*,prf_plus_t*,natt_conf_t*,bool))add_sa;
1272 this->public.update_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_diff_t,host_diff_t))update_sa;
1273 this->public.query_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t*))query_sa;
1274 this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
1275 this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool))add_policy;
1276 this->public.query_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,u_int32_t*))query_policy;
1277 this->public.del_policy = (status_t(*)(kernel_interface_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t))del_policy;
1278 this->public.destroy = (void(*)(kernel_interface_t*)) destroy;
1279
1280 /* private members */
1281 this->pid = getpid();
1282 this->responses = linked_list_create();
1283 this->policies = linked_list_create();
1284 this->logger = logger_manager->get_logger(logger_manager, XFRM);
1285 pthread_mutex_init(&(this->rep_mutex),NULL);
1286 pthread_mutex_init(&(this->pol_mutex),NULL);
1287 pthread_cond_init(&(this->condvar),NULL);
1288 this->seq = 0;
1289
1290 /* open netlink socket */
1291 this->socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_XFRM);
1292 if (this->socket <= 0)
1293 {
1294 this->responses->destroy(this->responses);
1295 free(this);
1296 charon->kill(charon, "Unable to create netlink socket");
1297 }
1298
1299 /* bind the socket and reqister for ACQUIRE & EXPIRE */
1300 addr.nl_family = AF_NETLINK;
1301 addr.nl_pid = getpid();
1302 addr.nl_groups = XFRMGRP_ACQUIRE | XFRMGRP_EXPIRE;
1303 if (bind(this->socket, (struct sockaddr*)&addr, sizeof(addr)) != 0)
1304 {
1305 this->responses->destroy(this->responses);
1306 close(this->socket);
1307 free(this);
1308 charon->kill(charon, "Unable to bind netlink socket");
1309 }
1310
1311 if (pthread_create(&this->thread, NULL, (void*(*)(void*))receive_messages, this) != 0)
1312 {
1313 this->responses->destroy(this->responses);
1314 close(this->socket);
1315 free(this);
1316 charon->kill(charon, "Unable to create netlink thread");
1317 }
1318
1319 return &this->public;
1320 }