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