f0844ee5fa717d3da9c01c6cfef2d0184a7efe29
[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) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 * Copyright (C) 2003 Herbert Xu.
12 *
13 * Contains modified parts from pluto.
14 *
15 * This program is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License as published by the
17 * Free Software Foundation; either version 2 of the License, or (at your
18 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
19 *
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 * for more details.
24 */
25
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <linux/netlink.h>
29 #include <pthread.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 #include <string.h>
34
35 #include "kernel_interface.h"
36
37 #include <daemon.h>
38 #include <utils/linked_list.h>
39 #include <queues/jobs/delete_child_sa_job.h>
40 #include <queues/jobs/rekey_child_sa_job.h>
41
42
43 #define KERNEL_ESP 50
44 #define KERNEL_AH 51
45
46 #define SPD_PRIORITY 1024
47
48 #define XFRM_DATA_LENGTH 512
49
50
51 typedef struct xfrm_data_t xfrm_data_t;
52
53 /**
54 * Lenght/Type/data struct for userdata in xfrm
55 * We dont use the "I-don't-know-where-they-come-from"-structs
56 * used in the kernel.
57 */
58 struct xfrm_data_t {
59 /**
60 * length of the data
61 */
62 u_int16_t length;
63
64 /**
65 * type of data
66 */
67 u_int16_t type;
68
69 /**
70 * and the data itself, for different purposes
71 */
72 union {
73 /** algorithm */
74 struct xfrm_algo algo;
75 /** policy tmpl */
76 struct xfrm_user_tmpl tmpl[2];
77 };
78 };
79
80
81 typedef struct netlink_message_t netlink_message_t;
82
83 /**
84 * Representation of ANY netlink message used
85 */
86 struct netlink_message_t {
87
88 /**
89 * header of the netlink message
90 */
91 struct nlmsghdr hdr;
92
93 union {
94 /** error message */
95 struct nlmsgerr e;
96 /** message for spi allocation */
97 struct xfrm_userspi_info spi;
98 /** message for SA manipulation */
99 struct xfrm_usersa_id sa_id;
100 /** message for SA installation */
101 struct xfrm_usersa_info sa;
102 /** message for policy manipulation */
103 struct xfrm_userpolicy_id policy_id;
104 /** message for policy installation */
105 struct xfrm_userpolicy_info policy;
106 /** expire message sent from kernel */
107 struct xfrm_user_expire expire;
108 };
109 u_int8_t data[XFRM_DATA_LENGTH];
110 };
111
112
113 typedef struct private_kernel_interface_t private_kernel_interface_t;
114
115 /**
116 * @brief Private Variables and Functions of kernel_interface class.
117 *
118 */
119 struct private_kernel_interface_t {
120 /**
121 * Public part of the kernel_interface_t object.
122 */
123 kernel_interface_t public;
124
125 /**
126 * Netlink communication socket.
127 */
128 int socket;
129
130 /**
131 * Process id of kernel thread
132 */
133 pid_t pid;
134
135 /**
136 * Sequence number for messages.
137 */
138 u_int32_t seq;
139
140 /**
141 * List of responded messages.
142 */
143 linked_list_t *responses;
144
145 /**
146 * Thread which receives messages.
147 */
148 pthread_t thread;
149
150 /**
151 * Mutex locks access to replies list.
152 */
153 pthread_mutex_t mutex;
154
155 /**
156 * Condvar allows signaling of threads waiting for a reply.
157 */
158 pthread_cond_t condvar;
159
160 /**
161 * Logger for XFRM stuff
162 */
163 logger_t *logger;
164
165 /**
166 * Function for the thread, receives messages.
167 */
168 void (*receive_messages) (private_kernel_interface_t *this);
169
170 /**
171 * Sends a netlink_message_t down to the kernel and wait for reply.
172 */
173 status_t (*send_message) (private_kernel_interface_t *this, netlink_message_t *request, netlink_message_t **response);
174 };
175
176 /**
177 * In the kernel, algorithms are identified as strings, we use our
178 * mapping functions...
179 * Algorithms for encryption.
180 * TODO: Add missing algorithm strings
181 */
182 mapping_t kernel_encryption_algs_m[] = {
183 {ENCR_DES_IV64, ""},
184 {ENCR_DES, "des"},
185 {ENCR_3DES, "des3_ede"},
186 {ENCR_RC5, ""},
187 {ENCR_IDEA, "idea"},
188 {ENCR_CAST, "cast128"},
189 {ENCR_BLOWFISH, "blowfish"},
190 {ENCR_3IDEA, ""},
191 {ENCR_DES_IV32, ""},
192 {ENCR_NULL, ""},
193 {ENCR_AES_CBC, "aes"},
194 {ENCR_AES_CTR, ""},
195 {MAPPING_END, NULL}
196 };
197 /**
198 * In the kernel, algorithms are identified as strings, we use our
199 * mapping functions...
200 * Algorithms for integrity protection.
201 * TODO: Add missing algorithm strings
202 */
203 mapping_t kernel_integrity_algs_m[] = {
204 {AUTH_HMAC_MD5_96, "md5"},
205 {AUTH_HMAC_SHA1_96, "sha1"},
206 {AUTH_DES_MAC, ""},
207 {AUTH_KPDK_MD5, ""},
208 {AUTH_AES_XCBC_96, ""},
209 {MAPPING_END, NULL}
210 };
211
212 /**
213 * Implementation of kernel_interface_t.get_spi.
214 */
215 static status_t get_spi(private_kernel_interface_t *this,
216 host_t *src, host_t *dest,
217 protocol_id_t protocol, u_int32_t reqid,
218 u_int32_t *spi)
219 {
220 netlink_message_t request, *response;
221 status_t status = SUCCESS;
222
223
224 this->logger->log(this->logger, CONTROL|LEVEL2, "getting spi");
225
226 memset(&request, 0, sizeof(request));
227 request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.spi)));
228 request.hdr.nlmsg_flags = NLM_F_REQUEST;
229 request.hdr.nlmsg_type = XFRM_MSG_ALLOCSPI;
230 request.spi.info.saddr = src->get_xfrm_addr(src);
231 request.spi.info.id.daddr = dest->get_xfrm_addr(dest);
232 request.spi.info.mode = TRUE; /* tunnel mode */
233 request.spi.info.reqid = reqid;
234 request.spi.info.id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
235 request.spi.info.family = PF_INET;
236 request.spi.min = 0xc0000000;
237 request.spi.max = 0xcFFFFFFF;
238
239 if (this->send_message(this, &request, &response) != SUCCESS)
240 {
241 this->logger->log(this->logger, ERROR, "netlink communication failed");
242 return FAILED;
243 }
244 else if (response->hdr.nlmsg_type == NLMSG_ERROR)
245 {
246 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_ALLOCSPI got an error: %s",
247 strerror(-response->e.error));
248 status = FAILED;
249 }
250 else if (response->hdr.nlmsg_type != XFRM_MSG_NEWSA)
251 {
252 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_ALLOCSPI got a unknown reply");
253 status = FAILED;
254 }
255 else if (response->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(response->sa)))
256 {
257 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_ALLOCSPI got an invalid reply");
258 status = FAILED;
259 }
260 else
261 {
262 *spi = response->sa.id.spi;
263 }
264 free(response);
265
266 return status;
267 }
268
269 /**
270 * Implementation of kernel_interface_t.add_sa.
271 */
272 static status_t add_sa( private_kernel_interface_t *this,
273 host_t *me,
274 host_t *other,
275 u_int32_t spi,
276 int protocol,
277 u_int32_t reqid,
278 u_int64_t expire_soft,
279 u_int64_t expire_hard,
280 encryption_algorithm_t enc_alg,
281 chunk_t encryption_key,
282 integrity_algorithm_t int_alg,
283 chunk_t integrity_key,
284 bool replace)
285 {
286 netlink_message_t request, *response;
287 memset(&request, 0, sizeof(request));
288 status_t status = SUCCESS;
289
290 this->logger->log(this->logger, CONTROL|LEVEL2, "adding SA");
291
292 request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
293 request.hdr.nlmsg_type = replace ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
294
295 request.sa.saddr = me->get_xfrm_addr(me);
296 request.sa.id.daddr = other->get_xfrm_addr(other);
297
298 request.sa.id.spi = spi;
299 request.sa.id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
300 request.sa.family = me->get_family(me);
301 request.sa.mode = TRUE; /* tunnel mode */
302 request.sa.replay_window = 32;
303 request.sa.reqid = reqid;
304 /* we currently do not expire SAs by volume/packet count */
305 request.sa.lft.soft_byte_limit = XFRM_INF;
306 request.sa.lft.hard_byte_limit = XFRM_INF;
307 request.sa.lft.soft_packet_limit = XFRM_INF;
308 request.sa.lft.hard_packet_limit = XFRM_INF;
309 /* we use lifetimes since added, not since used */
310 request.sa.lft.soft_add_expires_seconds = expire_soft;
311 request.sa.lft.hard_add_expires_seconds = expire_hard;
312 request.sa.lft.soft_use_expires_seconds = 0;
313 request.sa.lft.hard_use_expires_seconds = 0;
314
315 request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.sa)));
316
317 if (enc_alg != ENCR_UNDEFINED)
318 {
319 xfrm_data_t *data = (xfrm_data_t*)(((u_int8_t*)&request) + request.hdr.nlmsg_len);
320
321 data->type = XFRMA_ALG_CRYPT;
322 data->length = 4 + sizeof(data->algo) + encryption_key.len;
323 data->algo.alg_key_len = encryption_key.len * 8;
324 request.hdr.nlmsg_len += data->length;
325 if (request.hdr.nlmsg_len > sizeof(request))
326 {
327 return FAILED;
328 }
329 strcpy(data->algo.alg_name, mapping_find(kernel_encryption_algs_m, enc_alg));
330 memcpy(data->algo.alg_key, encryption_key.ptr, encryption_key.len);
331 }
332
333 if (int_alg != AUTH_UNDEFINED)
334 {
335 xfrm_data_t *data = (xfrm_data_t*)(((u_int8_t*)&request) + request.hdr.nlmsg_len);
336
337 data->type = XFRMA_ALG_AUTH;
338 data->length = 4 + sizeof(data->algo) + integrity_key.len;
339 data->algo.alg_key_len = integrity_key.len * 8;
340 request.hdr.nlmsg_len += data->length;
341 if (request.hdr.nlmsg_len > sizeof(request))
342 {
343 return FAILED;
344 }
345 strcpy(data->algo.alg_name, mapping_find(kernel_integrity_algs_m, int_alg));
346 memcpy(data->algo.alg_key, integrity_key.ptr, integrity_key.len);
347 }
348
349 /* TODO: add IPComp here*/
350
351 if (this->send_message(this, &request, &response) != SUCCESS)
352 {
353 this->logger->log(this->logger, ERROR, "netlink communication failed");
354 return FAILED;
355 }
356 else if (response->hdr.nlmsg_type != NLMSG_ERROR)
357 {
358 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWSA not acknowledged");
359 status = FAILED;
360 }
361 else if (response->e.error)
362 {
363 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWSA got error %s",
364 strerror(-response->e.error));
365 status = FAILED;
366 }
367
368 free(response);
369 return status;
370 }
371
372 static status_t del_sa( private_kernel_interface_t *this,
373 host_t *dst,
374 u_int32_t spi,
375 protocol_id_t protocol)
376 {
377 netlink_message_t request, *response;
378 memset(&request, 0, sizeof(request));
379 status_t status = SUCCESS;
380
381 this->logger->log(this->logger, CONTROL|LEVEL2, "deleting SA");
382
383 request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
384 request.hdr.nlmsg_type = XFRM_MSG_DELSA;
385
386 request.sa_id.daddr = dst->get_xfrm_addr(dst);
387
388 request.sa_id.spi = spi;
389 request.sa_id.proto = (protocol == PROTO_ESP) ? KERNEL_ESP : KERNEL_AH;
390 request.sa_id.family = dst->get_family(dst);
391
392 request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.sa_id)));
393
394 if (this->send_message(this, &request, &response) != SUCCESS)
395 {
396 return FAILED;
397 }
398 else if (response->hdr.nlmsg_type != NLMSG_ERROR)
399 {
400 status = FAILED;
401 }
402 else if (response->e.error)
403 {
404 status = FAILED;
405 }
406
407 free(response);
408 return status;
409 }
410
411 /**
412 * Implementation of kernel_interface_t.add_policy.
413 */
414 static status_t add_policy(private_kernel_interface_t *this,
415 host_t *me, host_t *other,
416 host_t *src, host_t *dst,
417 u_int8_t src_hostbits, u_int8_t dst_hostbits,
418 int direction, int upper_proto,
419 bool ah, bool esp,
420 u_int32_t reqid)
421 {
422 netlink_message_t request, *response;
423 status_t status = SUCCESS;
424
425 this->logger->log(this->logger, CONTROL|LEVEL2, "adding policy");
426
427 memset(&request, 0, sizeof(request));
428 request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
429
430 request.policy.sel.sport = htons(src->get_port(src));
431 request.policy.sel.dport = htons(dst->get_port(dst));
432 request.policy.sel.sport_mask = (request.policy.sel.sport) ? ~0 : 0;
433 request.policy.sel.dport_mask = (request.policy.sel.dport) ? ~0 : 0;
434 request.policy.sel.saddr = src->get_xfrm_addr(src);
435 request.policy.sel.daddr = dst->get_xfrm_addr(dst);
436 request.policy.sel.prefixlen_s = src_hostbits;
437 request.policy.sel.prefixlen_d = dst_hostbits;
438 request.policy.sel.proto = upper_proto;
439 request.policy.sel.family = src->get_family(src);
440
441 request.hdr.nlmsg_type = XFRM_MSG_NEWPOLICY;
442 request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.policy)));
443
444 request.policy.dir = direction;
445 request.policy.priority = SPD_PRIORITY;
446 request.policy.action = XFRM_POLICY_ALLOW;
447 request.policy.share = XFRM_SHARE_ANY;
448
449 /* policies currently don't expire */
450 request.policy.lft.soft_byte_limit = XFRM_INF;
451 request.policy.lft.soft_packet_limit = XFRM_INF;
452 request.policy.lft.hard_byte_limit = XFRM_INF;
453 request.policy.lft.hard_packet_limit = XFRM_INF;
454 request.sa.lft.soft_add_expires_seconds = 0;
455 request.sa.lft.hard_add_expires_seconds = 0;
456 request.sa.lft.soft_use_expires_seconds = 0;
457 request.sa.lft.hard_use_expires_seconds = 0;
458
459 if (esp || ah)
460 {
461 xfrm_data_t *data;
462 int tmpl_pos = 0;
463 data = (xfrm_data_t*)(((u_int8_t*)&request) + request.hdr.nlmsg_len);
464 data->type = XFRMA_TMPL;
465 if (esp)
466 {
467 data->tmpl[tmpl_pos].reqid = reqid;
468 data->tmpl[tmpl_pos].id.proto = KERNEL_ESP;
469 data->tmpl[tmpl_pos].aalgos = data->tmpl[tmpl_pos].ealgos = data->tmpl[tmpl_pos].calgos = ~0;
470 data->tmpl[tmpl_pos].mode = TRUE;
471
472 data->tmpl[tmpl_pos].saddr = me->get_xfrm_addr(me);
473 data->tmpl[tmpl_pos].id.daddr = me->get_xfrm_addr(other);
474
475 tmpl_pos++;
476 }
477 if (ah)
478 {
479 data->tmpl[tmpl_pos].reqid = reqid;
480 data->tmpl[tmpl_pos].id.proto = KERNEL_AH;
481 data->tmpl[tmpl_pos].aalgos = data->tmpl[tmpl_pos].ealgos = data->tmpl[tmpl_pos].calgos = ~0;
482 data->tmpl[tmpl_pos].mode = TRUE;
483
484 data->tmpl[tmpl_pos].saddr = me->get_xfrm_addr(me);
485 data->tmpl[tmpl_pos].id.daddr = other->get_xfrm_addr(other);
486
487 tmpl_pos++;
488 }
489 data->length = 4 + sizeof(struct xfrm_user_tmpl) * tmpl_pos;
490 request.hdr.nlmsg_len += data->length;
491 }
492
493 if (this->send_message(this, &request, &response) != SUCCESS)
494 {
495 this->logger->log(this->logger, ERROR, "netlink communication failed");
496 return FAILED;
497 }
498 else if (response->hdr.nlmsg_type != NLMSG_ERROR)
499 {
500 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWPOLICY not acknowledged");
501 status = FAILED;
502 }
503 else if (response->e.error)
504 {
505 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWPOLICY got error %s",
506 strerror(-response->e.error));
507 status = FAILED;
508 }
509
510 free(response);
511 return status;
512 }
513
514 /**
515 * Implementation of kernel_interface_t.del_policy.
516 */
517 static status_t del_policy(private_kernel_interface_t *this,
518 host_t *me, host_t *other,
519 host_t *src, host_t *dst,
520 u_int8_t src_hostbits, u_int8_t dst_hostbits,
521 int direction, int upper_proto)
522 {
523 netlink_message_t request, *response;
524 status_t status = SUCCESS;
525
526
527 this->logger->log(this->logger, CONTROL|LEVEL2, "deleting policy");
528
529 memset(&request, 0, sizeof(request));
530 request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
531
532 request.policy_id.sel.sport = htons(src->get_port(src));
533 request.policy_id.sel.dport = htons(dst->get_port(dst));
534 request.policy_id.sel.sport_mask = (request.policy.sel.sport) ? ~0 : 0;
535 request.policy_id.sel.dport_mask = (request.policy.sel.dport) ? ~0 : 0;
536 request.policy_id.sel.saddr = src->get_xfrm_addr(src);
537 request.policy_id.sel.daddr = dst->get_xfrm_addr(dst);
538 request.policy_id.sel.prefixlen_s = src_hostbits;
539 request.policy_id.sel.prefixlen_d = dst_hostbits;
540 request.policy_id.sel.proto = upper_proto;
541 request.policy_id.sel.family = src->get_family(src);
542
543 request.policy_id.dir = direction;
544
545 request.hdr.nlmsg_type = XFRM_MSG_DELPOLICY;
546 request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.policy_id)));
547
548 if (this->send_message(this, &request, &response) != SUCCESS)
549 {
550 return FAILED;
551 }
552 else if (response->hdr.nlmsg_type != NLMSG_ERROR)
553 {
554 status = FAILED;
555 }
556 else if (response->e.error)
557 {
558 status = FAILED;
559 }
560
561 free(response);
562 return status;
563 }
564
565 /**
566 * Implementation of private_kernel_interface_t.send_message.
567 */
568 static status_t send_message(private_kernel_interface_t *this, netlink_message_t *request, netlink_message_t **response)
569 {
570 size_t length;
571 struct sockaddr_nl addr;
572
573 request->hdr.nlmsg_seq = ++this->seq;
574 request->hdr.nlmsg_pid = this->pid;
575
576 memset(&addr, 0, sizeof(struct sockaddr_nl));
577 addr.nl_family = AF_NETLINK;
578 addr.nl_pid = 0;
579 addr.nl_groups = 0;
580
581 length = sendto(this->socket,(void *)request, request->hdr.nlmsg_len, 0, (struct sockaddr *)&addr, sizeof(addr));
582
583 if (length < 0)
584 {
585 return FAILED;
586 }
587 else if (length != request->hdr.nlmsg_len)
588 {
589 return FAILED;
590 }
591
592 pthread_mutex_lock(&(this->mutex));
593
594 while (TRUE)
595 {
596 iterator_t *iterator;
597 bool found = FALSE;
598 /* search list, break if found */
599 iterator = this->responses->create_iterator(this->responses, TRUE);
600 while (iterator->has_next(iterator))
601 {
602 netlink_message_t *listed_response;
603 iterator->current(iterator, (void**)&listed_response);
604 if (listed_response->hdr.nlmsg_seq == request->hdr.nlmsg_seq)
605 {
606 /* matches our request, this is the reply */
607 *response = listed_response;
608 found = TRUE;
609 break;
610 }
611 }
612 iterator->destroy(iterator);
613
614 if (found)
615 {
616 break;
617 }
618 /* TODO: we should time out, if something goes wrong!??? */
619 pthread_cond_wait(&(this->condvar), &(this->mutex));
620 }
621
622 pthread_mutex_unlock(&(this->mutex));
623
624 return SUCCESS;
625 }
626
627 /**
628 * Implementation of private_kernel_interface_t.receive_messages.
629 */
630 static void receive_messages(private_kernel_interface_t *this)
631 {
632 while(TRUE)
633 {
634 netlink_message_t response, *listed_response;
635 while (TRUE)
636 {
637 struct sockaddr_nl addr;
638 socklen_t addr_length;
639 size_t length;
640
641 addr_length = sizeof(addr);
642
643 response.hdr.nlmsg_type = XFRM_MSG_NEWSA;
644 length = recvfrom(this->socket, &response, sizeof(response), 0, (struct sockaddr*)&addr, &addr_length);
645 if (length < 0)
646 {
647 if (errno == EINTR)
648 {
649 /* interrupted, try again */
650 continue;
651 }
652 charon->kill(charon, "receiving from netlink socket failed");
653 }
654 if (!NLMSG_OK(&response.hdr, length))
655 {
656 /* bad netlink message */
657 continue;
658 }
659 if (addr.nl_pid != 0)
660 {
661 /* not from kernel. not interested, try another one */
662 continue;
663 }
664 /* good message, handle it */
665 break;
666 }
667
668 /* we handle ACQUIRE and EXPIRE messages directly
669 */
670 if (response.hdr.nlmsg_type == XFRM_MSG_ACQUIRE)
671 {
672 this->logger->log(this->logger, CONTROL,
673 "Received a XFRM_MSG_ACQUIRE. Ignored");
674 }
675 else if (response.hdr.nlmsg_type == XFRM_MSG_EXPIRE)
676 {
677 job_t *job;
678 this->logger->log(this->logger, CONTROL|LEVEL1,
679 "Received a XFRM_MSG_EXPIRE");
680 if (response.expire.hard)
681 {
682 this->logger->log(this->logger, CONTROL|LEVEL0,
683 "creating delete job for CHILD_SA with reqid %d",
684 response.expire.state.reqid);
685 job = (job_t*)delete_child_sa_job_create(
686 response.expire.state.reqid);
687 }
688 else
689 {
690 this->logger->log(this->logger, CONTROL|LEVEL0,
691 "creating rekey job for CHILD_SA with reqid %d",
692 response.expire.state.reqid);
693 job = (job_t*)rekey_child_sa_job_create(
694 response.expire.state.reqid);
695 }
696 charon->job_queue->add(charon->job_queue, job);
697 }
698 /* NLMSG_ERROR is send back for acknowledge (or on error), an
699 * XFRM_MSG_NEWSA is returned when we alloc spis.
700 * list these responses for the sender
701 */
702 else if (response.hdr.nlmsg_type == NLMSG_ERROR ||
703 response.hdr.nlmsg_type == XFRM_MSG_NEWSA)
704 {
705 /* add response to queue */
706 listed_response = malloc(sizeof(response));
707 memcpy(listed_response, &response, sizeof(response));
708
709 pthread_mutex_lock(&(this->mutex));
710 this->responses->insert_last(this->responses, (void*)listed_response);
711 pthread_mutex_unlock(&(this->mutex));
712 /* signal ALL waiting threads */
713 pthread_cond_broadcast(&(this->condvar));
714 }
715 /* we are not interested in anything other.
716 * anyway, move on to the next message */
717 continue;
718 }
719 }
720
721 /**
722 * Implementation of kernel_interface_t.destroy.
723 */
724 static void destroy(private_kernel_interface_t *this)
725 {
726 pthread_cancel(this->thread);
727 pthread_join(this->thread, NULL);
728 close(this->socket);
729 this->responses->destroy(this->responses);
730 free(this);
731 }
732
733 /*
734 * Described in header.
735 */
736 kernel_interface_t *kernel_interface_create()
737 {
738 struct sockaddr_nl addr;
739 private_kernel_interface_t *this = malloc_thing(private_kernel_interface_t);
740
741 /* public functions */
742 this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
743 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,encryption_algorithm_t,chunk_t,integrity_algorithm_t,chunk_t,bool))add_sa;
744 this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*, host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int,bool,bool,u_int32_t))add_policy;
745 this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
746 this->public.del_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int))del_policy;
747
748 this->public.destroy = (void(*)(kernel_interface_t*)) destroy;
749
750 /* private members */
751 this->receive_messages = receive_messages;
752 this->send_message = send_message;
753 this->pid = getpid();
754 this->responses = linked_list_create();
755 this->logger = logger_manager->get_logger(logger_manager, XFRM);
756 pthread_mutex_init(&(this->mutex),NULL);
757 pthread_cond_init(&(this->condvar),NULL);
758 this->seq = 0;
759
760 /* open netlink socket */
761 this->socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_XFRM);
762 if (this->socket <= 0)
763 {
764 this->responses->destroy(this->responses);
765 free(this);
766 charon->kill(charon, "Unable to create netlink socket");
767 }
768 /* bind the socket and reqister for ACQUIRE & EXPIRE */
769 addr.nl_family = AF_NETLINK;
770 addr.nl_pid = getpid();
771 addr.nl_groups = XFRMGRP_ACQUIRE | XFRMGRP_EXPIRE;
772 if (bind(this->socket, (struct sockaddr*)&addr, sizeof(addr)) != 0)
773 {
774 this->responses->destroy(this->responses);
775 close(this->socket);
776 free(this);
777 charon->kill(charon, "Unable to bind netlink socket");
778 }
779
780 if (pthread_create(&(this->thread), NULL, (void*(*)(void*))this->receive_messages, this) != 0)
781 {
782 this->responses->destroy(this->responses);
783 close(this->socket);
784 free(this);
785 charon->kill(charon, "Unable to create netlink thread");
786 }
787
788 return (&this->public);
789 }