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