2 * @file stroke_interface.c
4 * @brief Implementation of stroke_interface_t.
9 * Copyright (C) 2006-2007 Martin Willi
10 * Hochschule fuer Technik Rapperswil
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 #include <sys/types.h>
26 #include <sys/socket.h>
28 #include <sys/fcntl.h>
35 #include "stroke_interface.h"
40 #include <crypto/x509.h>
41 #include <crypto/ca.h>
42 #include <crypto/crl.h>
43 #include <processing/jobs/initiate_job.h>
44 #include <processing/jobs/route_job.h>
45 #include <utils/leak_detective.h>
49 #define STROKE_THREADS 3
51 struct sockaddr_un socket_addr
= { AF_UNIX
, STROKE_SOCKET
};
54 typedef struct private_stroke_interface_t private_stroke_interface_t
;
57 * Private data of an stroke_t object.
59 struct private_stroke_interface_t
{
62 * Public part of stroke_t object.
67 * backend to store configurations
69 local_backend_t
*backend
;
72 * Unix socket to listen for strokes
77 * Thread which reads from the Socket
79 pthread_t threads
[STROKE_THREADS
];
83 * Helper function which corrects the string pointers
84 * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
85 * contains RELATIVE addresses (relative to the beginning of the
86 * stroke_msg). They must be corrected if they reach our address
89 static void pop_string(stroke_msg_t
*msg
, char **string
)
94 /* check for sanity of string pointer and string */
95 if (string
< (char**)msg
96 || string
> (char**)msg
+ sizeof(stroke_msg_t
)
97 || (unsigned long)*string
< (unsigned long)((char*)msg
->buffer
- (char*)msg
)
98 || (unsigned long)*string
> msg
->length
)
100 *string
= "(invalid pointer in stroke msg)";
104 *string
= (char*)msg
+ (unsigned long)*string
;
109 * Load end entitity certificate
111 static x509_t
* load_end_certificate(const char *filename
, identification_t
**idp
)
116 if (*filename
== '/')
118 /* absolute path name */
119 snprintf(path
, sizeof(path
), "%s", filename
);
123 /* relative path name */
124 snprintf(path
, sizeof(path
), "%s/%s", CERTIFICATE_DIR
, filename
);
127 cert
= x509_create_from_file(path
, "end entity");
131 identification_t
*id
= *idp
;
132 identification_t
*subject
= cert
->get_subject(cert
);
134 err_t ugh
= cert
->is_valid(cert
, NULL
);
138 DBG1(DBG_CFG
, "warning: certificate %s", ugh
);
140 if (!id
->equals(id
, subject
) && !cert
->equals_subjectAltName(cert
, id
))
144 *idp
= id
->clone(id
);
146 return charon
->credentials
->add_end_certificate(charon
->credentials
, cert
);
152 * Load ca certificate
154 static x509_t
* load_ca_certificate(const char *filename
)
159 if (*filename
== '/')
161 /* absolute path name */
162 snprintf(path
, sizeof(path
), "%s", filename
);
166 /* relative path name */
167 snprintf(path
, sizeof(path
), "%s/%s", CA_CERTIFICATE_DIR
, filename
);
170 cert
= x509_create_from_file(path
, "ca");
174 if (cert
->is_ca(cert
))
176 return charon
->credentials
->add_auth_certificate(charon
->credentials
, cert
, AUTH_CA
);
180 DBG1(DBG_CFG
, " CA basic constraints flag not set, cert discarded");
188 * Add a connection to the configuration list
190 static void stroke_add_conn(private_stroke_interface_t
*this,
191 stroke_msg_t
*msg
, FILE *out
)
194 peer_cfg_t
*peer_cfg
;
195 child_cfg_t
*child_cfg
;
196 identification_t
*my_id
, *other_id
;
197 identification_t
*my_ca
= NULL
;
198 identification_t
*other_ca
= NULL
;
199 bool my_ca_same
= FALSE
;
200 bool other_ca_same
=FALSE
;
201 host_t
*my_host
, *other_host
, *my_subnet
, *other_subnet
;
202 host_t
*my_vip
= NULL
, *other_vip
= NULL
;
203 proposal_t
*proposal
;
204 traffic_selector_t
*my_ts
, *other_ts
;
206 bool use_existing
= FALSE
;
207 iterator_t
*iterator
;
209 pop_string(msg
, &msg
->add_conn
.name
);
210 pop_string(msg
, &msg
->add_conn
.me
.address
);
211 pop_string(msg
, &msg
->add_conn
.other
.address
);
212 pop_string(msg
, &msg
->add_conn
.me
.subnet
);
213 pop_string(msg
, &msg
->add_conn
.other
.subnet
);
214 pop_string(msg
, &msg
->add_conn
.me
.sourceip
);
215 pop_string(msg
, &msg
->add_conn
.other
.sourceip
);
216 pop_string(msg
, &msg
->add_conn
.me
.id
);
217 pop_string(msg
, &msg
->add_conn
.other
.id
);
218 pop_string(msg
, &msg
->add_conn
.me
.cert
);
219 pop_string(msg
, &msg
->add_conn
.other
.cert
);
220 pop_string(msg
, &msg
->add_conn
.me
.ca
);
221 pop_string(msg
, &msg
->add_conn
.other
.ca
);
222 pop_string(msg
, &msg
->add_conn
.me
.updown
);
223 pop_string(msg
, &msg
->add_conn
.other
.updown
);
224 pop_string(msg
, &msg
->add_conn
.algorithms
.ike
);
225 pop_string(msg
, &msg
->add_conn
.algorithms
.esp
);
227 DBG1(DBG_CFG
, "received stroke: add connection '%s'", msg
->add_conn
.name
);
229 DBG2(DBG_CFG
, "conn %s", msg
->add_conn
.name
);
230 DBG2(DBG_CFG
, " left=%s", msg
->add_conn
.me
.address
);
231 DBG2(DBG_CFG
, " right=%s", msg
->add_conn
.other
.address
);
232 DBG2(DBG_CFG
, " leftsubnet=%s", msg
->add_conn
.me
.subnet
);
233 DBG2(DBG_CFG
, " rightsubnet=%s", msg
->add_conn
.other
.subnet
);
234 DBG2(DBG_CFG
, " leftsourceip=%s", msg
->add_conn
.me
.sourceip
);
235 DBG2(DBG_CFG
, " rightsourceip=%s", msg
->add_conn
.other
.sourceip
);
236 DBG2(DBG_CFG
, " leftid=%s", msg
->add_conn
.me
.id
);
237 DBG2(DBG_CFG
, " rightid=%s", msg
->add_conn
.other
.id
);
238 DBG2(DBG_CFG
, " leftcert=%s", msg
->add_conn
.me
.cert
);
239 DBG2(DBG_CFG
, " rightcert=%s", msg
->add_conn
.other
.cert
);
240 DBG2(DBG_CFG
, " leftca=%s", msg
->add_conn
.me
.ca
);
241 DBG2(DBG_CFG
, " rightca=%s", msg
->add_conn
.other
.ca
);
242 DBG2(DBG_CFG
, " ike=%s", msg
->add_conn
.algorithms
.ike
);
243 DBG2(DBG_CFG
, " esp=%s", msg
->add_conn
.algorithms
.esp
);
245 my_host
= msg
->add_conn
.me
.address?
246 host_create_from_string(msg
->add_conn
.me
.address
, IKE_PORT
) : NULL
;
249 DBG1(DBG_CFG
, "invalid host: %s\n", msg
->add_conn
.me
.address
);
253 other_host
= msg
->add_conn
.other
.address ?
254 host_create_from_string(msg
->add_conn
.other
.address
, IKE_PORT
) : NULL
;
255 if (other_host
== NULL
)
257 DBG1(DBG_CFG
, "invalid host: %s\n", msg
->add_conn
.other
.address
);
258 my_host
->destroy(my_host
);
262 interface
= charon
->kernel_interface
->get_interface(charon
->kernel_interface
,
266 stroke_end_t tmp_end
;
269 DBG2(DBG_CFG
, "left is other host, swapping ends\n");
272 my_host
= other_host
;
273 other_host
= tmp_host
;
275 tmp_end
= msg
->add_conn
.me
;
276 msg
->add_conn
.me
= msg
->add_conn
.other
;
277 msg
->add_conn
.other
= tmp_end
;
282 interface
= charon
->kernel_interface
->get_interface(
283 charon
->kernel_interface
, my_host
);
286 DBG1(DBG_CFG
, "left nor right host is our side, aborting\n");
292 my_id
= identification_create_from_string(msg
->add_conn
.me
.id ?
293 msg
->add_conn
.me
.id
: msg
->add_conn
.me
.address
);
296 DBG1(DBG_CFG
, "invalid ID: %s\n", msg
->add_conn
.me
.id
);
300 other_id
= identification_create_from_string(msg
->add_conn
.other
.id ?
301 msg
->add_conn
.other
.id
: msg
->add_conn
.other
.address
);
302 if (other_id
== NULL
)
304 DBG1(DBG_CFG
, "invalid ID: %s\n", msg
->add_conn
.other
.id
);
305 my_id
->destroy(my_id
);
309 my_subnet
= host_create_from_string(msg
->add_conn
.me
.subnet ?
310 msg
->add_conn
.me
.subnet
: msg
->add_conn
.me
.address
, IKE_PORT
);
311 if (my_subnet
== NULL
)
313 DBG1(DBG_CFG
, "invalid subnet: %s\n", msg
->add_conn
.me
.subnet
);
317 other_subnet
= host_create_from_string(msg
->add_conn
.other
.subnet ?
318 msg
->add_conn
.other
.subnet
: msg
->add_conn
.other
.address
, IKE_PORT
);
319 if (other_subnet
== NULL
)
321 DBG1(DBG_CFG
, "invalid subnet: %s\n", msg
->add_conn
.me
.subnet
);
322 my_subnet
->destroy(my_subnet
);
326 if (msg
->add_conn
.me
.virtual_ip
)
328 my_vip
= host_create_from_string(msg
->add_conn
.me
.sourceip
, 0);
330 other_vip
= host_create_from_string(msg
->add_conn
.other
.sourceip
, 0);
332 if (msg
->add_conn
.me
.tohost
)
334 my_ts
= traffic_selector_create_dynamic(msg
->add_conn
.me
.protocol
,
335 my_host
->get_family(my_host
) == AF_INET ?
336 TS_IPV4_ADDR_RANGE
: TS_IPV6_ADDR_RANGE
,
337 msg
->add_conn
.me
.port ? msg
->add_conn
.me
.port
: 0,
338 msg
->add_conn
.me
.port ? msg
->add_conn
.me
.port
: 65535);
342 my_ts
= traffic_selector_create_from_subnet(my_subnet
,
343 msg
->add_conn
.me
.subnet ? msg
->add_conn
.me
.subnet_mask
: 0,
344 msg
->add_conn
.me
.protocol
, msg
->add_conn
.me
.port
);
346 my_subnet
->destroy(my_subnet
);
348 if (msg
->add_conn
.other
.tohost
)
350 other_ts
= traffic_selector_create_dynamic(msg
->add_conn
.other
.protocol
,
351 other_host
->get_family(other_host
) == AF_INET ?
352 TS_IPV4_ADDR_RANGE
: TS_IPV6_ADDR_RANGE
,
353 msg
->add_conn
.other
.port ? msg
->add_conn
.other
.port
: 0,
354 msg
->add_conn
.other
.port ? msg
->add_conn
.other
.port
: 65535);
358 other_ts
= traffic_selector_create_from_subnet(other_subnet
,
359 msg
->add_conn
.other
.subnet ? msg
->add_conn
.other
.subnet_mask
: 0,
360 msg
->add_conn
.other
.protocol
, msg
->add_conn
.other
.port
);
362 other_subnet
->destroy(other_subnet
);
364 if (msg
->add_conn
.me
.ca
)
366 if (streq(msg
->add_conn
.me
.ca
, "%same"))
372 my_ca
= identification_create_from_string(msg
->add_conn
.me
.ca
);
375 if (msg
->add_conn
.other
.ca
)
377 if (streq(msg
->add_conn
.other
.ca
, "%same"))
379 other_ca_same
= TRUE
;
383 other_ca
= identification_create_from_string(msg
->add_conn
.other
.ca
);
386 if (msg
->add_conn
.me
.cert
)
388 x509_t
*cert
= load_end_certificate(msg
->add_conn
.me
.cert
, &my_id
);
390 if (my_ca
== NULL
&& !my_ca_same
&& cert
)
392 identification_t
*issuer
= cert
->get_issuer(cert
);
394 my_ca
= issuer
->clone(issuer
);
397 if (msg
->add_conn
.other
.cert
)
399 x509_t
*cert
= load_end_certificate(msg
->add_conn
.other
.cert
, &other_id
);
401 if (other_ca
== NULL
&& !other_ca_same
&& cert
)
403 identification_t
*issuer
= cert
->get_issuer(cert
);
405 other_ca
= issuer
->clone(issuer
);
408 if (other_ca_same
&& my_ca
)
410 other_ca
= my_ca
->clone(my_ca
);
412 else if (my_ca_same
&& other_ca
)
414 my_ca
= other_ca
->clone(other_ca
);
418 my_ca
= identification_create_from_string("%any");
420 if (other_ca
== NULL
)
422 other_ca
= identification_create_from_string("%any");
424 DBG2(DBG_CFG
, " my ca: '%D'", my_ca
);
425 DBG2(DBG_CFG
, " other ca:'%D'", other_ca
);
426 DBG2(DBG_CFG
, " updown: '%s'", msg
->add_conn
.me
.updown
);
428 /* have a look for an (almost) identical peer config to reuse */
429 iterator
= this->backend
->create_peer_cfg_iterator(this->backend
);
430 while (iterator
->iterate(iterator
, (void**)&peer_cfg
))
432 ike_cfg
= peer_cfg
->get_ike_cfg(peer_cfg
);
433 if (my_id
->equals(my_id
, peer_cfg
->get_my_id(peer_cfg
)) &&
434 other_id
->equals(other_id
, peer_cfg
->get_other_id(peer_cfg
)) &&
435 my_host
->equals(my_host
, ike_cfg
->get_my_host(ike_cfg
)) &&
436 other_host
->equals(other_host
, ike_cfg
->get_other_host(ike_cfg
)) &&
437 peer_cfg
->get_ike_version(peer_cfg
) == (msg
->add_conn
.ikev2 ?
2 : 1) &&
438 peer_cfg
->get_auth_method(peer_cfg
) == msg
->add_conn
.auth_method
&&
439 peer_cfg
->get_eap_type(peer_cfg
) == msg
->add_conn
.eap_type
)
441 DBG1(DBG_CFG
, "reusing existing configuration '%s'",
442 peer_cfg
->get_name(peer_cfg
));
447 iterator
->destroy(iterator
);
452 DESTROY_IF(other_vip
);
453 my_host
->destroy(my_host
);
454 my_id
->destroy(my_id
);
455 my_ca
->destroy(my_ca
);
456 other_host
->destroy(other_host
);
457 other_id
->destroy(other_id
);
458 other_ca
->destroy(other_ca
);
462 ike_cfg
= ike_cfg_create(msg
->add_conn
.other
.sendcert
!= CERT_NEVER_SEND
,
463 my_host
, other_host
);
465 if (msg
->add_conn
.algorithms
.ike
)
467 char *proposal_string
;
468 char *strict
= msg
->add_conn
.algorithms
.ike
+ strlen(msg
->add_conn
.algorithms
.ike
) - 1;
475 while ((proposal_string
= strsep(&msg
->add_conn
.algorithms
.ike
, ",")))
477 proposal
= proposal_create_from_string(PROTO_IKE
, proposal_string
);
478 if (proposal
== NULL
)
480 DBG1(DBG_CFG
, "invalid IKE proposal string: %s", proposal_string
);
481 my_id
->destroy(my_id
);
482 other_id
->destroy(other_id
);
483 my_ts
->destroy(my_ts
);
484 other_ts
->destroy(other_ts
);
485 my_ca
->destroy(my_ca
);
486 other_ca
->destroy(other_ca
);
487 ike_cfg
->destroy(ike_cfg
);
490 ike_cfg
->add_proposal(ike_cfg
, proposal
);
494 proposal
= proposal_create_default(PROTO_IKE
);
495 ike_cfg
->add_proposal(ike_cfg
, proposal
);
500 proposal
= proposal_create_default(PROTO_IKE
);
501 ike_cfg
->add_proposal(ike_cfg
, proposal
);
505 peer_cfg
= peer_cfg_create(msg
->add_conn
.name
, msg
->add_conn
.ikev2 ?
2 : 1,
506 ike_cfg
, my_id
, other_id
, my_ca
, other_ca
, msg
->add_conn
.me
.sendcert
,
507 msg
->add_conn
.auth_method
, msg
->add_conn
.eap_type
,
508 msg
->add_conn
.rekey
.tries
, msg
->add_conn
.rekey
.ike_lifetime
,
509 msg
->add_conn
.rekey
.ike_lifetime
- msg
->add_conn
.rekey
.margin
,
510 msg
->add_conn
.rekey
.margin
* msg
->add_conn
.rekey
.fuzz
/ 100,
511 msg
->add_conn
.rekey
.reauth
, msg
->add_conn
.dpd
.delay
,
512 msg
->add_conn
.dpd
.action
,my_vip
, other_vip
);
515 child_cfg
= child_cfg_create(
516 msg
->add_conn
.name
, msg
->add_conn
.rekey
.ipsec_lifetime
,
517 msg
->add_conn
.rekey
.ipsec_lifetime
- msg
->add_conn
.rekey
.margin
,
518 msg
->add_conn
.rekey
.margin
* msg
->add_conn
.rekey
.fuzz
/ 100,
519 msg
->add_conn
.me
.updown
, msg
->add_conn
.me
.hostaccess
,
522 peer_cfg
->add_child_cfg(peer_cfg
, child_cfg
);
524 child_cfg
->add_traffic_selector(child_cfg
, TRUE
, my_ts
);
525 child_cfg
->add_traffic_selector(child_cfg
, FALSE
, other_ts
);
527 if (msg
->add_conn
.algorithms
.esp
)
529 char *proposal_string
;
530 char *strict
= msg
->add_conn
.algorithms
.esp
+ strlen(msg
->add_conn
.algorithms
.esp
) - 1;
537 while ((proposal_string
= strsep(&msg
->add_conn
.algorithms
.esp
, ",")))
539 proposal
= proposal_create_from_string(PROTO_ESP
, proposal_string
);
540 if (proposal
== NULL
)
542 DBG1(DBG_CFG
, "invalid ESP proposal string: %s", proposal_string
);
543 peer_cfg
->destroy(peer_cfg
);
546 child_cfg
->add_proposal(child_cfg
, proposal
);
550 proposal
= proposal_create_default(PROTO_ESP
);
551 child_cfg
->add_proposal(child_cfg
, proposal
);
556 proposal
= proposal_create_default(PROTO_ESP
);
557 child_cfg
->add_proposal(child_cfg
, proposal
);
562 /* add config to backend */
563 this->backend
->add_peer_cfg(this->backend
, peer_cfg
);
564 DBG1(DBG_CFG
, "added configuration '%s': %H[%D]...%H[%D]",
565 msg
->add_conn
.name
, my_host
, my_id
, other_host
, other_id
);
569 /* mopping up after parsing errors */
572 my_id
->destroy(my_id
);
573 other_id
->destroy(other_id
);
576 my_host
->destroy(my_host
);
577 other_host
->destroy(other_host
);
581 * Delete a connection from the list
583 static void stroke_del_conn(private_stroke_interface_t
*this,
584 stroke_msg_t
*msg
, FILE *out
)
586 iterator_t
*peer_iter
, *child_iter
;
587 peer_cfg_t
*peer
, *child
;
589 pop_string(msg
, &(msg
->del_conn
.name
));
590 DBG1(DBG_CFG
, "received stroke: delete connection '%s'", msg
->del_conn
.name
);
592 peer_iter
= this->backend
->create_peer_cfg_iterator(this->backend
);
593 while (peer_iter
->iterate(peer_iter
, (void**)&peer
))
595 /* remove peer config with such a name */
596 if (streq(peer
->get_name(peer
), msg
->del_conn
.name
))
598 peer_iter
->remove(peer_iter
);
602 /* remove any child with such a name */
603 child_iter
= peer
->create_child_cfg_iterator(peer
);
604 while (child_iter
->iterate(child_iter
, (void**)&child
))
606 if (streq(child
->get_name(child
), msg
->del_conn
.name
))
608 child_iter
->remove(child_iter
);
609 child
->destroy(child
);
612 child_iter
->destroy(child_iter
);
614 peer_iter
->destroy(peer_iter
);
616 fprintf(out
, "deleted connection '%s'\n", msg
->del_conn
.name
);
620 * get the child_cfg with the same name as the peer cfg
622 static child_cfg_t
* get_child_from_peer(peer_cfg_t
*peer_cfg
, char *name
)
624 child_cfg_t
*current
, *found
= NULL
;
625 iterator_t
*iterator
;
627 iterator
= peer_cfg
->create_child_cfg_iterator(peer_cfg
);
628 while (iterator
->iterate(iterator
, (void**)¤t
))
630 if (streq(current
->get_name(current
), name
))
633 found
->get_ref(found
);
637 iterator
->destroy(iterator
);
642 * initiate a connection by name
644 static void stroke_initiate(private_stroke_interface_t
*this,
645 stroke_msg_t
*msg
, FILE *out
)
648 peer_cfg_t
*peer_cfg
;
649 child_cfg_t
*child_cfg
;
650 ike_sa_t
*init_ike_sa
= NULL
;
653 pop_string(msg
, &(msg
->initiate
.name
));
654 DBG1(DBG_CFG
, "received stroke: initiate '%s'", msg
->initiate
.name
);
656 peer_cfg
= this->backend
->get_peer_cfg_by_name(this->backend
,
658 if (peer_cfg
== NULL
)
660 if (msg
->output_verbosity
>= 0)
662 fprintf(out
, "no config named '%s'\n", msg
->initiate
.name
);
666 if (peer_cfg
->get_ike_version(peer_cfg
) != 2)
668 DBG1(DBG_CFG
, "ignoring initiation request for IKEv%d config",
669 peer_cfg
->get_ike_version(peer_cfg
));
670 peer_cfg
->destroy(peer_cfg
);
674 child_cfg
= get_child_from_peer(peer_cfg
, msg
->initiate
.name
);
675 if (child_cfg
== NULL
)
677 if (msg
->output_verbosity
>= 0)
679 fprintf(out
, "no child config named '%s'\n", msg
->initiate
.name
);
681 peer_cfg
->destroy(peer_cfg
);
685 job
= initiate_job_create(peer_cfg
, child_cfg
);
686 charon
->bus
->set_listen_state(charon
->bus
, TRUE
);
687 charon
->job_queue
->add(charon
->job_queue
, (job_t
*)job
);
696 signal
= charon
->bus
->listen(charon
->bus
, &level
, &thread
, &ike_sa
, &format
, &args
);
698 if ((init_ike_sa
== NULL
|| ike_sa
== init_ike_sa
) &&
699 level
<= msg
->output_verbosity
)
701 if (vfprintf(out
, format
, args
) < 0 ||
702 fprintf(out
, "\n") < 0 ||
705 charon
->bus
->set_listen_state(charon
->bus
, FALSE
);
712 case CHILD_UP_SUCCESS
:
713 case CHILD_UP_FAILED
:
715 if (ike_sa
== init_ike_sa
)
717 charon
->bus
->set_listen_state(charon
->bus
, FALSE
);
723 if (init_ike_sa
== NULL
)
725 init_ike_sa
= ike_sa
;
735 * route/unroute a policy (install SPD entries)
737 static void stroke_route(private_stroke_interface_t
*this,
738 stroke_msg_t
*msg
, FILE *out
, bool route
)
741 peer_cfg_t
*peer_cfg
;
742 child_cfg_t
*child_cfg
;
744 pop_string(msg
, &(msg
->route
.name
));
745 DBG1(DBG_CFG
, "received stroke: %s '%s'",
746 route ?
"route" : "unroute", msg
->route
.name
);
748 peer_cfg
= this->backend
->get_peer_cfg_by_name(this->backend
, msg
->route
.name
);
749 if (peer_cfg
== NULL
)
751 fprintf(out
, "no config named '%s'\n", msg
->route
.name
);
754 if (peer_cfg
->get_ike_version(peer_cfg
) != 2)
756 peer_cfg
->destroy(peer_cfg
);
760 child_cfg
= get_child_from_peer(peer_cfg
, msg
->route
.name
);
761 if (child_cfg
== NULL
)
763 fprintf(out
, "no child config named '%s'\n", msg
->route
.name
);
764 peer_cfg
->destroy(peer_cfg
);
767 fprintf(out
, "%s policy '%s'\n",
768 route ?
"routing" : "unrouting", msg
->route
.name
);
769 job
= route_job_create(peer_cfg
, child_cfg
, route
);
770 charon
->job_queue
->add(charon
->job_queue
, (job_t
*)job
);
774 * terminate a connection by name
776 static void stroke_terminate(private_stroke_interface_t
*this,
777 stroke_msg_t
*msg
, FILE *out
)
779 char *string
, *pos
= NULL
, *name
= NULL
;
783 status_t status
= SUCCESS
;;
786 pop_string(msg
, &(msg
->terminate
.name
));
787 string
= msg
->terminate
.name
;
788 DBG1(DBG_CFG
, "received stroke: terminate '%s'", string
);
790 len
= strlen(string
);
793 DBG1(DBG_CFG
, "error parsing string");
796 switch (string
[len
-1])
800 pos
= strchr(string
, '{');
804 pos
= strchr(string
, '[');
813 { /* must be a single name */
814 DBG1(DBG_CFG
, "check out by single name '%s'", name
);
815 ike_sa
= charon
->ike_sa_manager
->checkout_by_name(charon
->ike_sa_manager
,
818 else if (pos
== string
+ len
- 2)
819 { /* must be name[] or name{} */
820 string
[len
-2] = '\0';
821 DBG1(DBG_CFG
, "check out by name '%s'", string
);
822 ike_sa
= charon
->ike_sa_manager
->checkout_by_name(charon
->ike_sa_manager
,
826 { /* must be name[123] or name{23} */
827 string
[len
-1] = '\0';
831 DBG1(DBG_CFG
, "error parsing string");
834 DBG1(DBG_CFG
, "check out by id '%d'", id
);
835 ike_sa
= charon
->ike_sa_manager
->checkout_by_id(charon
->ike_sa_manager
,
840 DBG1(DBG_CFG
, "no such IKE_SA found");
846 status
= ike_sa
->delete(ike_sa
);
850 child_sa_t
*child_sa
;
851 iterator_t
*iterator
= ike_sa
->create_child_sa_iterator(ike_sa
);
852 while (iterator
->iterate(iterator
, (void**)&child_sa
))
854 if ((id
&& id
== child_sa
->get_reqid(child_sa
)) ||
855 (string
&& streq(string
, child_sa
->get_name(child_sa
))))
857 u_int32_t spi
= child_sa
->get_spi(child_sa
, TRUE
);
858 protocol_id_t proto
= child_sa
->get_protocol(child_sa
);
860 status
= ike_sa
->delete_child_sa(ike_sa
, proto
, spi
);
864 iterator
->destroy(iterator
);
866 if (status
== DESTROY_ME
)
868 charon
->ike_sa_manager
->checkin_and_destroy(charon
->ike_sa_manager
,
872 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
876 * Add a ca information record to the cainfo list
878 static void stroke_add_ca(private_stroke_interface_t
*this,
879 stroke_msg_t
*msg
, FILE *out
)
884 pop_string(msg
, &msg
->add_ca
.name
);
885 pop_string(msg
, &msg
->add_ca
.cacert
);
886 pop_string(msg
, &msg
->add_ca
.crluri
);
887 pop_string(msg
, &msg
->add_ca
.crluri2
);
888 pop_string(msg
, &msg
->add_ca
.ocspuri
);
889 pop_string(msg
, &msg
->add_ca
.ocspuri2
);
891 DBG1(DBG_CFG
, "received stroke: add ca '%s'", msg
->add_ca
.name
);
893 DBG2(DBG_CFG
, "ca %s", msg
->add_ca
.name
);
894 DBG2(DBG_CFG
, " cacert=%s", msg
->add_ca
.cacert
);
895 DBG2(DBG_CFG
, " crluri=%s", msg
->add_ca
.crluri
);
896 DBG2(DBG_CFG
, " crluri2=%s", msg
->add_ca
.crluri2
);
897 DBG2(DBG_CFG
, " ocspuri=%s", msg
->add_ca
.ocspuri
);
898 DBG2(DBG_CFG
, " ocspuri2=%s", msg
->add_ca
.ocspuri2
);
900 if (msg
->add_ca
.cacert
== NULL
)
902 DBG1(DBG_CFG
, "missing cacert parameter\n");
906 cacert
= load_ca_certificate(msg
->add_ca
.cacert
);
912 ca_info
= ca_info_create(msg
->add_ca
.name
, cacert
);
914 if (msg
->add_ca
.crluri
)
916 chunk_t uri
= { msg
->add_ca
.crluri
, strlen(msg
->add_ca
.crluri
) };
918 ca_info
->add_crluri(ca_info
, uri
);
920 if (msg
->add_ca
.crluri2
)
922 chunk_t uri
= { msg
->add_ca
.crluri2
, strlen(msg
->add_ca
.crluri2
) };
924 ca_info
->add_crluri(ca_info
, uri
);
926 if (msg
->add_ca
.ocspuri
)
928 chunk_t uri
= { msg
->add_ca
.ocspuri
, strlen(msg
->add_ca
.ocspuri
) };
930 ca_info
->add_ocspuri(ca_info
, uri
);
932 if (msg
->add_ca
.ocspuri2
)
934 chunk_t uri
= { msg
->add_ca
.ocspuri2
, strlen(msg
->add_ca
.ocspuri2
) };
936 ca_info
->add_ocspuri(ca_info
, uri
);
938 charon
->credentials
->add_ca_info(charon
->credentials
, ca_info
);
939 DBG1(DBG_CFG
, "added ca '%s'", msg
->add_ca
.name
);
944 * Delete a ca information record from the cainfo list
946 static void stroke_del_ca(private_stroke_interface_t
*this,
947 stroke_msg_t
*msg
, FILE *out
)
951 pop_string(msg
, &(msg
->del_ca
.name
));
952 DBG1(DBG_CFG
, "received stroke: delete ca '%s'", msg
->del_ca
.name
);
954 status
= charon
->credentials
->release_ca_info(charon
->credentials
,
957 if (status
== SUCCESS
)
959 fprintf(out
, "deleted ca '%s'\n", msg
->del_ca
.name
);
963 fprintf(out
, "no ca named '%s'\n", msg
->del_ca
.name
);
968 * log an IKE_SA to out
970 static void log_ike_sa(FILE *out
, ike_sa_t
*ike_sa
, bool all
)
972 peer_cfg_t
*cfg
= ike_sa
->get_peer_cfg(ike_sa
);
973 ike_sa_id_t
*id
= ike_sa
->get_id(ike_sa
);
974 u_int32_t next
, now
= time(NULL
);
976 fprintf(out
, "%12s[%d]: %N, %H[%D]...%H[%D]\n",
977 ike_sa
->get_name(ike_sa
), ike_sa
->get_unique_id(ike_sa
),
978 ike_sa_state_names
, ike_sa
->get_state(ike_sa
),
979 ike_sa
->get_my_host(ike_sa
), ike_sa
->get_my_id(ike_sa
),
980 ike_sa
->get_other_host(ike_sa
), ike_sa
->get_other_id(ike_sa
));
984 fprintf(out
, "%12s[%d]: IKE SPIs: 0x%0llx_i%s 0x%0llx_r%s, ",
985 ike_sa
->get_name(ike_sa
), ike_sa
->get_unique_id(ike_sa
),
986 id
->get_initiator_spi(id
), id
->is_initiator(id
) ?
"*" : "",
987 id
->get_responder_spi(id
), id
->is_initiator(id
) ?
"" : "");
989 ike_sa
->get_stats(ike_sa
, &next
);
992 fprintf(out
, "%s in %V\n", cfg
->use_reauth(cfg
) ?
993 "reauthentication" : "rekeying", &now
, &next
);
997 fprintf(out
, "rekeying disabled\n");
1003 * log an CHILD_SA to out
1005 static void log_child_sa(FILE *out
, child_sa_t
*child_sa
, bool all
)
1007 u_int32_t rekey
, now
= time(NULL
);
1008 u_int32_t use_in
, use_out
, use_fwd
;
1009 encryption_algorithm_t encr_alg
;
1010 integrity_algorithm_t int_alg
;
1011 size_t encr_len
, int_len
;
1014 child_sa
->get_stats(child_sa
, &mode
, &encr_alg
, &encr_len
,
1015 &int_alg
, &int_len
, &rekey
, &use_in
, &use_out
,
1018 fprintf(out
, "%12s{%d}: %N, %N",
1019 child_sa
->get_name(child_sa
), child_sa
->get_reqid(child_sa
),
1020 child_sa_state_names
, child_sa
->get_state(child_sa
),
1023 if (child_sa
->get_state(child_sa
) == CHILD_INSTALLED
)
1025 fprintf(out
, ", %N SPIs: 0x%0x_i 0x%0x_o",
1026 protocol_id_names
, child_sa
->get_protocol(child_sa
),
1027 htonl(child_sa
->get_spi(child_sa
, TRUE
)),
1028 htonl(child_sa
->get_spi(child_sa
, FALSE
)));
1032 fprintf(out
, "\n%12s{%d}: ", child_sa
->get_name(child_sa
),
1033 child_sa
->get_reqid(child_sa
));
1036 if (child_sa
->get_protocol(child_sa
) == PROTO_ESP
)
1038 fprintf(out
, "%N", encryption_algorithm_names
, encr_alg
);
1042 fprintf(out
, "-%d", encr_len
);
1047 fprintf(out
, "%N", integrity_algorithm_names
, int_alg
);
1050 fprintf(out
, "-%d", int_len
);
1052 fprintf(out
, ", rekeying ");
1056 fprintf(out
, "in %V", &now
, &rekey
);
1060 fprintf(out
, "disabled");
1063 fprintf(out
, ", last use: ");
1064 use_in
= max(use_in
, use_fwd
);
1067 fprintf(out
, "%ds_i ", now
- use_in
);
1071 fprintf(out
, "no_i ");
1075 fprintf(out
, "%ds_o ", now
- use_out
);
1079 fprintf(out
, "no_o ");
1084 fprintf(out
, "\n%12s{%d}: %#R=== %#R\n",
1085 child_sa
->get_name(child_sa
), child_sa
->get_reqid(child_sa
),
1086 child_sa
->get_traffic_selectors(child_sa
, TRUE
),
1087 child_sa
->get_traffic_selectors(child_sa
, FALSE
));
1091 * show status of daemon
1093 static void stroke_status(private_stroke_interface_t
*this,
1094 stroke_msg_t
*msg
, FILE *out
, bool all
)
1096 iterator_t
*iterator
, *children
;
1097 linked_list_t
*list
;
1099 peer_cfg_t
*peer_cfg
;
1101 child_cfg_t
*child_cfg
;
1105 if (msg
->status
.name
)
1107 pop_string(msg
, &(msg
->status
.name
));
1108 name
= msg
->status
.name
;
1113 leak_detective_status(out
);
1115 fprintf(out
, "Performance:\n");
1116 fprintf(out
, " worker threads: %d idle of %d,",
1117 charon
->thread_pool
->get_idle_threads(charon
->thread_pool
),
1118 charon
->thread_pool
->get_pool_size(charon
->thread_pool
));
1119 fprintf(out
, " job queue load: %d,",
1120 charon
->job_queue
->get_count(charon
->job_queue
));
1121 fprintf(out
, " scheduled events: %d\n",
1122 charon
->event_queue
->get_count(charon
->event_queue
));
1123 list
= charon
->kernel_interface
->create_address_list(charon
->kernel_interface
);
1125 fprintf(out
, "Listening on %d IP addresses:\n", list
->get_count(list
));
1126 while (list
->remove_first(list
, (void**)&host
) == SUCCESS
)
1128 fprintf(out
, " %H\n", host
);
1129 host
->destroy(host
);
1131 list
->destroy(list
);
1133 fprintf(out
, "Connections:\n");
1134 iterator
= this->backend
->create_peer_cfg_iterator(this->backend
);
1135 while (iterator
->iterate(iterator
, (void**)&peer_cfg
))
1137 if (peer_cfg
->get_ike_version(peer_cfg
) != 2 ||
1138 (name
&& !streq(name
, peer_cfg
->get_name(peer_cfg
))))
1143 ike_cfg
= peer_cfg
->get_ike_cfg(peer_cfg
);
1144 fprintf(out
, "%12s: %H[%D]...%H[%D]\n", peer_cfg
->get_name(peer_cfg
),
1145 ike_cfg
->get_my_host(ike_cfg
), peer_cfg
->get_my_id(peer_cfg
),
1146 ike_cfg
->get_other_host(ike_cfg
), peer_cfg
->get_other_id(peer_cfg
));
1147 children
= peer_cfg
->create_child_cfg_iterator(peer_cfg
);
1148 while (children
->iterate(children
, (void**)&child_cfg
))
1150 linked_list_t
*my_ts
, *other_ts
;
1151 my_ts
= child_cfg
->get_traffic_selectors(child_cfg
, TRUE
, NULL
, NULL
);
1152 other_ts
= child_cfg
->get_traffic_selectors(child_cfg
, FALSE
, NULL
, NULL
);
1153 fprintf(out
, "%12s: %#R=== %#R\n", child_cfg
->get_name(child_cfg
),
1155 my_ts
->destroy_offset(my_ts
, offsetof(traffic_selector_t
, destroy
));
1156 other_ts
->destroy_offset(other_ts
, offsetof(traffic_selector_t
, destroy
));
1158 children
->destroy(children
);
1160 iterator
->destroy(iterator
);
1163 iterator
= charon
->ike_sa_manager
->create_iterator(charon
->ike_sa_manager
);
1164 if (all
&& iterator
->get_count(iterator
) > 0)
1166 fprintf(out
, "Security Associations:\n");
1168 while (iterator
->iterate(iterator
, (void**)&ike_sa
))
1170 bool ike_printed
= FALSE
;
1171 child_sa_t
*child_sa
;
1172 iterator_t
*children
= ike_sa
->create_child_sa_iterator(ike_sa
);
1174 if (name
== NULL
|| streq(name
, ike_sa
->get_name(ike_sa
)))
1176 log_ike_sa(out
, ike_sa
, all
);
1180 while (children
->iterate(children
, (void**)&child_sa
))
1182 if (name
== NULL
|| streq(name
, child_sa
->get_name(child_sa
)))
1186 log_ike_sa(out
, ike_sa
, all
);
1189 log_child_sa(out
, child_sa
, all
);
1192 children
->destroy(children
);
1194 iterator
->destroy(iterator
);
1198 * list all authority certificates matching a specified flag
1200 static void list_auth_certificates(private_stroke_interface_t
*this, u_int flag
,
1201 const char *label
, bool utc
, FILE *out
)
1206 iterator_t
*iterator
= charon
->credentials
->create_auth_cert_iterator(charon
->credentials
);
1208 while (iterator
->iterate(iterator
, (void**)&cert
))
1210 if (cert
->has_authority_flag(cert
, flag
))
1215 fprintf(out
, "List of X.509 %s Certificates:\n", label
);
1219 fprintf(out
, "%#Q\n", cert
, utc
);
1222 iterator
->destroy(iterator
);
1226 * list various information
1228 static void stroke_list(private_stroke_interface_t
*this,
1229 stroke_msg_t
*msg
, FILE *out
)
1231 iterator_t
*iterator
;
1233 if (msg
->list
.flags
& LIST_CERTS
)
1237 iterator
= charon
->credentials
->create_cert_iterator(charon
->credentials
);
1238 if (iterator
->get_count(iterator
))
1241 fprintf(out
, "List of X.509 End Entity Certificates:\n");
1244 while (iterator
->iterate(iterator
, (void**)&cert
))
1246 fprintf(out
, "%#Q", cert
, msg
->list
.utc
);
1247 if (charon
->credentials
->has_rsa_private_key(
1248 charon
->credentials
, cert
->get_public_key(cert
)))
1250 fprintf(out
, ", has private key");
1255 iterator
->destroy(iterator
);
1257 if (msg
->list
.flags
& LIST_CACERTS
)
1259 list_auth_certificates(this, AUTH_CA
, "CA", msg
->list
.utc
, out
);
1261 if (msg
->list
.flags
& LIST_CAINFOS
)
1265 iterator
= charon
->credentials
->create_cainfo_iterator(charon
->credentials
);
1266 if (iterator
->get_count(iterator
))
1269 fprintf(out
, "List of X.509 CA Information Records:\n");
1272 while (iterator
->iterate(iterator
, (void**)&ca_info
))
1274 fprintf(out
, "%#W", ca_info
, msg
->list
.utc
);
1276 iterator
->destroy(iterator
);
1278 if (msg
->list
.flags
& LIST_CRLS
)
1283 iterator
= charon
->credentials
->create_cainfo_iterator(charon
->credentials
);
1284 while (iterator
->iterate(iterator
, (void **)&ca_info
))
1286 if (ca_info
->has_crl(ca_info
))
1291 fprintf(out
, "List of X.509 CRLs:\n");
1295 ca_info
->list_crl(ca_info
, out
, msg
->list
.utc
);
1298 iterator
->destroy(iterator
);
1300 if (msg
->list
.flags
& LIST_OCSPCERTS
)
1302 list_auth_certificates(this, AUTH_OCSP
, "OCSP", msg
->list
.utc
, out
);
1304 if (msg
->list
.flags
& LIST_OCSP
)
1309 iterator
= charon
->credentials
->create_cainfo_iterator(charon
->credentials
);
1310 while (iterator
->iterate(iterator
, (void **)&ca_info
))
1312 if (ca_info
->has_certinfos(ca_info
))
1317 fprintf(out
, "List of OCSP responses:\n");
1321 ca_info
->list_certinfos(ca_info
, out
, msg
->list
.utc
);
1324 iterator
->destroy(iterator
);
1329 * reread various information
1331 static void stroke_reread(private_stroke_interface_t
*this,
1332 stroke_msg_t
*msg
, FILE *out
)
1334 if (msg
->reread
.flags
& REREAD_CACERTS
)
1336 charon
->credentials
->load_ca_certificates(charon
->credentials
);
1338 if (msg
->reread
.flags
& REREAD_OCSPCERTS
)
1340 charon
->credentials
->load_ocsp_certificates(charon
->credentials
);
1342 if (msg
->reread
.flags
& REREAD_CRLS
)
1344 charon
->credentials
->load_crls(charon
->credentials
);
1349 * purge various information
1351 static void stroke_purge(private_stroke_interface_t
*this,
1352 stroke_msg_t
*msg
, FILE *out
)
1354 if (msg
->purge
.flags
& PURGE_OCSP
)
1356 iterator_t
*iterator
= charon
->credentials
->create_cainfo_iterator(charon
->credentials
);
1359 while (iterator
->iterate(iterator
, (void**)&ca_info
))
1361 ca_info
->purge_ocsp(ca_info
);
1363 iterator
->destroy(iterator
);
1367 signal_t
get_signal_from_logtype(char *type
)
1369 if (strcasecmp(type
, "any") == 0) return SIG_ANY
;
1370 else if (strcasecmp(type
, "mgr") == 0) return DBG_MGR
;
1371 else if (strcasecmp(type
, "ike") == 0) return DBG_IKE
;
1372 else if (strcasecmp(type
, "chd") == 0) return DBG_CHD
;
1373 else if (strcasecmp(type
, "job") == 0) return DBG_JOB
;
1374 else if (strcasecmp(type
, "cfg") == 0) return DBG_CFG
;
1375 else if (strcasecmp(type
, "knl") == 0) return DBG_KNL
;
1376 else if (strcasecmp(type
, "net") == 0) return DBG_NET
;
1377 else if (strcasecmp(type
, "enc") == 0) return DBG_ENC
;
1378 else if (strcasecmp(type
, "lib") == 0) return DBG_LIB
;
1383 * set the verbosity debug output
1385 static void stroke_loglevel(private_stroke_interface_t
*this,
1386 stroke_msg_t
*msg
, FILE *out
)
1390 pop_string(msg
, &(msg
->loglevel
.type
));
1391 DBG1(DBG_CFG
, "received stroke: loglevel %d for %s",
1392 msg
->loglevel
.level
, msg
->loglevel
.type
);
1394 signal
= get_signal_from_logtype(msg
->loglevel
.type
);
1397 fprintf(out
, "invalid type (%s)!\n", msg
->loglevel
.type
);
1401 charon
->outlog
->set_level(charon
->outlog
, signal
, msg
->loglevel
.level
);
1402 charon
->syslog
->set_level(charon
->syslog
, signal
, msg
->loglevel
.level
);
1406 * process a stroke request from the socket pointed by "fd"
1408 static void stroke_process(private_stroke_interface_t
*this, int strokefd
)
1411 u_int16_t msg_length
;
1415 /* peek the length */
1416 bytes_read
= recv(strokefd
, &msg_length
, sizeof(msg_length
), MSG_PEEK
);
1417 if (bytes_read
!= sizeof(msg_length
))
1419 DBG1(DBG_CFG
, "reading length of stroke message failed");
1425 msg
= malloc(msg_length
);
1426 bytes_read
= recv(strokefd
, msg
, msg_length
, 0);
1427 if (bytes_read
!= msg_length
)
1429 DBG1(DBG_CFG
, "reading stroke message failed: %s", strerror(errno
));
1434 out
= fdopen(dup(strokefd
), "w");
1437 DBG1(DBG_CFG
, "opening stroke output channel failed: %s", strerror(errno
));
1443 DBG3(DBG_CFG
, "stroke message %b", (void*)msg
, msg_length
);
1448 stroke_initiate(this, msg
, out
);
1451 stroke_route(this, msg
, out
, TRUE
);
1454 stroke_route(this, msg
, out
, FALSE
);
1457 stroke_terminate(this, msg
, out
);
1460 stroke_status(this, msg
, out
, FALSE
);
1462 case STR_STATUS_ALL
:
1463 stroke_status(this, msg
, out
, TRUE
);
1466 stroke_add_conn(this, msg
, out
);
1469 stroke_del_conn(this, msg
, out
);
1472 stroke_add_ca(this, msg
, out
);
1475 stroke_del_ca(this, msg
, out
);
1478 stroke_loglevel(this, msg
, out
);
1481 stroke_list(this, msg
, out
);
1484 stroke_reread(this, msg
, out
);
1487 stroke_purge(this, msg
, out
);
1490 DBG1(DBG_CFG
, "received unknown stroke");
1498 * Implementation of private_stroke_interface_t.stroke_receive.
1500 static void stroke_receive(private_stroke_interface_t
*this)
1502 struct sockaddr_un strokeaddr
;
1503 int strokeaddrlen
= sizeof(strokeaddr
);
1507 /* ignore sigpipe. writing over the pipe back to the console
1508 * only fails if SIGPIPE is ignored. */
1509 signal(SIGPIPE
, SIG_IGN
);
1511 /* disable cancellation by default */
1512 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
1516 /* wait for connections, but allow thread to terminate */
1517 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, &oldstate
);
1518 strokefd
= accept(this->socket
, (struct sockaddr
*)&strokeaddr
, &strokeaddrlen
);
1519 pthread_setcancelstate(oldstate
, NULL
);
1523 DBG1(DBG_CFG
, "accepting stroke connection failed: %s", strerror(errno
));
1526 stroke_process(this, strokefd
);
1531 * Implementation of stroke_t.destroy.
1533 static void destroy(private_stroke_interface_t
*this)
1537 for (i
= 0; i
< STROKE_THREADS
; i
++)
1539 pthread_cancel(this->threads
[i
]);
1540 pthread_join(this->threads
[i
], NULL
);
1543 close(this->socket
);
1544 unlink(socket_addr
.sun_path
);
1549 * Described in header-file
1551 stroke_t
*stroke_create(local_backend_t
*backend
)
1553 private_stroke_interface_t
*this = malloc_thing(private_stroke_interface_t
);
1557 /* public functions */
1558 this->public.destroy
= (void (*)(stroke_t
*))destroy
;
1560 this->backend
= backend
;
1562 /* set up unix socket */
1563 this->socket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
1564 if (this->socket
== -1)
1566 DBG1(DBG_CFG
, "could not create whack socket");
1571 old
= umask(~S_IRWXU
);
1572 if (bind(this->socket
, (struct sockaddr
*)&socket_addr
, sizeof(socket_addr
)) < 0)
1574 DBG1(DBG_CFG
, "could not bind stroke socket: %s", strerror(errno
));
1575 close(this->socket
);
1581 if (listen(this->socket
, 0) < 0)
1583 DBG1(DBG_CFG
, "could not listen on stroke socket: %s", strerror(errno
));
1584 close(this->socket
);
1585 unlink(socket_addr
.sun_path
);
1590 /* start threads reading from the socket */
1591 for (i
= 0; i
< STROKE_THREADS
; i
++)
1593 if (pthread_create(&this->threads
[i
], NULL
, (void*(*)(void*))stroke_receive
, this) != 0)
1595 charon
->kill(charon
, "unable to create stroke thread");
1599 return (&this->public);