fixed compile warnings when using -Wall
[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 received 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_UPDPOLICY;
442 request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.policy)));
443 request.policy.dir = direction;
444 request.policy.priority = SPD_PRIORITY;
445 request.policy.action = XFRM_POLICY_ALLOW;
446 request.policy.share = XFRM_SHARE_ANY;
447
448 /* policies currently don't expire */
449 request.policy.lft.soft_byte_limit = XFRM_INF;
450 request.policy.lft.soft_packet_limit = XFRM_INF;
451 request.policy.lft.hard_byte_limit = XFRM_INF;
452 request.policy.lft.hard_packet_limit = XFRM_INF;
453 request.sa.lft.soft_add_expires_seconds = 0;
454 request.sa.lft.hard_add_expires_seconds = 0;
455 request.sa.lft.soft_use_expires_seconds = 0;
456 request.sa.lft.hard_use_expires_seconds = 0;
457
458 if (esp || ah)
459 {
460 xfrm_data_t *data;
461 int tmpl_pos = 0;
462 data = (xfrm_data_t*)(((u_int8_t*)&request) + request.hdr.nlmsg_len);
463 data->type = XFRMA_TMPL;
464 if (esp)
465 {
466 data->tmpl[tmpl_pos].reqid = reqid;
467 data->tmpl[tmpl_pos].id.proto = KERNEL_ESP;
468 data->tmpl[tmpl_pos].aalgos = data->tmpl[tmpl_pos].ealgos = data->tmpl[tmpl_pos].calgos = ~0;
469 data->tmpl[tmpl_pos].mode = TRUE;
470
471 data->tmpl[tmpl_pos].saddr = me->get_xfrm_addr(me);
472 data->tmpl[tmpl_pos].id.daddr = me->get_xfrm_addr(other);
473
474 tmpl_pos++;
475 }
476 if (ah)
477 {
478 data->tmpl[tmpl_pos].reqid = reqid;
479 data->tmpl[tmpl_pos].id.proto = KERNEL_AH;
480 data->tmpl[tmpl_pos].aalgos = data->tmpl[tmpl_pos].ealgos = data->tmpl[tmpl_pos].calgos = ~0;
481 data->tmpl[tmpl_pos].mode = TRUE;
482
483 data->tmpl[tmpl_pos].saddr = me->get_xfrm_addr(me);
484 data->tmpl[tmpl_pos].id.daddr = other->get_xfrm_addr(other);
485
486 tmpl_pos++;
487 }
488 data->length = 4 + sizeof(struct xfrm_user_tmpl) * tmpl_pos;
489 request.hdr.nlmsg_len += data->length;
490 }
491
492 if (this->send_message(this, &request, &response) != SUCCESS)
493 {
494 this->logger->log(this->logger, ERROR, "netlink communication failed");
495 return FAILED;
496 }
497 else if (response->hdr.nlmsg_type != NLMSG_ERROR)
498 {
499 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWPOLICY not acknowledged");
500 status = FAILED;
501 }
502 else if (response->e.error)
503 {
504 this->logger->log(this->logger, ERROR, "netlink request XFRM_MSG_NEWPOLICY received error: %s",
505 strerror(-response->e.error));
506 status = FAILED;
507 }
508
509 free(response);
510 return status;
511 }
512
513 /**
514 * Implementation of kernel_interface_t.del_policy.
515 */
516 static status_t del_policy(private_kernel_interface_t *this,
517 host_t *me, host_t *other,
518 host_t *src, host_t *dst,
519 u_int8_t src_hostbits, u_int8_t dst_hostbits,
520 int direction, int upper_proto)
521 {
522 netlink_message_t request, *response;
523 status_t status = SUCCESS;
524
525
526 this->logger->log(this->logger, CONTROL|LEVEL2, "deleting policy");
527
528 memset(&request, 0, sizeof(request));
529 request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
530
531 request.policy_id.sel.sport = htons(src->get_port(src));
532 request.policy_id.sel.dport = htons(dst->get_port(dst));
533 request.policy_id.sel.sport_mask = (request.policy.sel.sport) ? ~0 : 0;
534 request.policy_id.sel.dport_mask = (request.policy.sel.dport) ? ~0 : 0;
535 request.policy_id.sel.saddr = src->get_xfrm_addr(src);
536 request.policy_id.sel.daddr = dst->get_xfrm_addr(dst);
537 request.policy_id.sel.prefixlen_s = src_hostbits;
538 request.policy_id.sel.prefixlen_d = dst_hostbits;
539 request.policy_id.sel.proto = upper_proto;
540 request.policy_id.sel.family = src->get_family(src);
541
542 request.policy_id.dir = direction;
543
544 request.hdr.nlmsg_type = XFRM_MSG_DELPOLICY;
545 request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.policy_id)));
546
547 if (this->send_message(this, &request, &response) != SUCCESS)
548 {
549 return FAILED;
550 }
551 else if (response->hdr.nlmsg_type != NLMSG_ERROR)
552 {
553 status = FAILED;
554 }
555 else if (response->e.error)
556 {
557 status = FAILED;
558 }
559
560 free(response);
561 return status;
562 }
563
564 /**
565 * Implementation of private_kernel_interface_t.send_message.
566 */
567 static status_t send_message(private_kernel_interface_t *this, netlink_message_t *request, netlink_message_t **response)
568 {
569 size_t length;
570 struct sockaddr_nl addr;
571
572 request->hdr.nlmsg_seq = ++this->seq;
573 request->hdr.nlmsg_pid = this->pid;
574
575 memset(&addr, 0, sizeof(struct sockaddr_nl));
576 addr.nl_family = AF_NETLINK;
577 addr.nl_pid = 0;
578 addr.nl_groups = 0;
579
580 length = sendto(this->socket,(void *)request, request->hdr.nlmsg_len, 0, (struct sockaddr *)&addr, sizeof(addr));
581
582 if (length < 0)
583 {
584 return FAILED;
585 }
586 else if (length != request->hdr.nlmsg_len)
587 {
588 return FAILED;
589 }
590
591 pthread_mutex_lock(&(this->mutex));
592
593 while (TRUE)
594 {
595 iterator_t *iterator;
596 bool found = FALSE;
597 /* search list, break if found */
598 iterator = this->responses->create_iterator(this->responses, TRUE);
599 while (iterator->has_next(iterator))
600 {
601 netlink_message_t *listed_response;
602 iterator->current(iterator, (void**)&listed_response);
603 if (listed_response->hdr.nlmsg_seq == request->hdr.nlmsg_seq)
604 {
605 /* matches our request, this is the reply */
606 *response = listed_response;
607 found = TRUE;
608 break;
609 }
610 }
611 iterator->destroy(iterator);
612
613 if (found)
614 {
615 break;
616 }
617 /* TODO: we should time out, if something goes wrong!??? */
618 pthread_cond_wait(&(this->condvar), &(this->mutex));
619 }
620
621 pthread_mutex_unlock(&(this->mutex));
622
623 return SUCCESS;
624 }
625
626 /**
627 * Implementation of private_kernel_interface_t.receive_messages.
628 */
629 static void receive_messages(private_kernel_interface_t *this)
630 {
631 while(TRUE)
632 {
633 netlink_message_t response, *listed_response;
634 while (TRUE)
635 {
636 struct sockaddr_nl addr;
637 socklen_t addr_length;
638 size_t length;
639
640 addr_length = sizeof(addr);
641
642 response.hdr.nlmsg_type = XFRM_MSG_NEWSA;
643 length = recvfrom(this->socket, &response, sizeof(response), 0, (struct sockaddr*)&addr, &addr_length);
644 if (length < 0)
645 {
646 if (errno == EINTR)
647 {
648 /* interrupted, try again */
649 continue;
650 }
651 charon->kill(charon, "receiving from netlink socket failed");
652 }
653 if (!NLMSG_OK(&response.hdr, length))
654 {
655 /* bad netlink message */
656 continue;
657 }
658 if (addr.nl_pid != 0)
659 {
660 /* not from kernel. not interested, try another one */
661 continue;
662 }
663 /* good message, handle it */
664 break;
665 }
666
667 /* we handle ACQUIRE and EXPIRE messages directly
668 */
669 if (response.hdr.nlmsg_type == XFRM_MSG_ACQUIRE)
670 {
671 this->logger->log(this->logger, CONTROL,
672 "Received a XFRM_MSG_ACQUIRE. Ignored");
673 }
674 else if (response.hdr.nlmsg_type == XFRM_MSG_EXPIRE)
675 {
676 job_t *job;
677 this->logger->log(this->logger, CONTROL|LEVEL1,
678 "Received a XFRM_MSG_EXPIRE");
679 if (response.expire.hard)
680 {
681 this->logger->log(this->logger, CONTROL|LEVEL0,
682 "creating delete job for CHILD_SA with reqid %d",
683 response.expire.state.reqid);
684 job = (job_t*)delete_child_sa_job_create(
685 response.expire.state.reqid);
686 }
687 else
688 {
689 this->logger->log(this->logger, CONTROL|LEVEL0,
690 "creating rekey job for CHILD_SA with reqid %d",
691 response.expire.state.reqid);
692 job = (job_t*)rekey_child_sa_job_create(
693 response.expire.state.reqid);
694 }
695 charon->job_queue->add(charon->job_queue, job);
696 }
697 /* NLMSG_ERROR is send back for acknowledge (or on error), an
698 * XFRM_MSG_NEWSA is returned when we alloc spis.
699 * list these responses for the sender
700 */
701 else if (response.hdr.nlmsg_type == NLMSG_ERROR ||
702 response.hdr.nlmsg_type == XFRM_MSG_NEWSA)
703 {
704 /* add response to queue */
705 listed_response = malloc(sizeof(response));
706 memcpy(listed_response, &response, sizeof(response));
707
708 pthread_mutex_lock(&(this->mutex));
709 this->responses->insert_last(this->responses, (void*)listed_response);
710 pthread_mutex_unlock(&(this->mutex));
711 /* signal ALL waiting threads */
712 pthread_cond_broadcast(&(this->condvar));
713 }
714 /* we are not interested in anything other.
715 * anyway, move on to the next message */
716 continue;
717 }
718 }
719
720 /**
721 * Implementation of kernel_interface_t.destroy.
722 */
723 static void destroy(private_kernel_interface_t *this)
724 {
725 pthread_cancel(this->thread);
726 pthread_join(this->thread, NULL);
727 close(this->socket);
728 this->responses->destroy(this->responses);
729 free(this);
730 }
731
732 /*
733 * Described in header.
734 */
735 kernel_interface_t *kernel_interface_create()
736 {
737 struct sockaddr_nl addr;
738 private_kernel_interface_t *this = malloc_thing(private_kernel_interface_t);
739
740 /* public functions */
741 this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
742 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;
743 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;
744 this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa;
745 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;
746
747 this->public.destroy = (void(*)(kernel_interface_t*)) destroy;
748
749 /* private members */
750 this->receive_messages = receive_messages;
751 this->send_message = send_message;
752 this->pid = getpid();
753 this->responses = linked_list_create();
754 this->logger = logger_manager->get_logger(logger_manager, XFRM);
755 pthread_mutex_init(&(this->mutex),NULL);
756 pthread_cond_init(&(this->condvar),NULL);
757 this->seq = 0;
758
759 /* open netlink socket */
760 this->socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_XFRM);
761 if (this->socket <= 0)
762 {
763 this->responses->destroy(this->responses);
764 free(this);
765 charon->kill(charon, "Unable to create netlink socket");
766 }
767 /* bind the socket and reqister for ACQUIRE & EXPIRE */
768 addr.nl_family = AF_NETLINK;
769 addr.nl_pid = getpid();
770 addr.nl_groups = XFRMGRP_ACQUIRE | XFRMGRP_EXPIRE;
771 if (bind(this->socket, (struct sockaddr*)&addr, sizeof(addr)) != 0)
772 {
773 this->responses->destroy(this->responses);
774 close(this->socket);
775 free(this);
776 charon->kill(charon, "Unable to bind netlink socket");
777 }
778
779 if (pthread_create(&(this->thread), NULL, (void*(*)(void*))this->receive_messages, this) != 0)
780 {
781 this->responses->destroy(this->responses);
782 close(this->socket);
783 free(this);
784 charon->kill(charon, "Unable to create netlink thread");
785 }
786
787 return (&this->public);
788 }