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 <control/interface_manager.h>
44 #include <control/interfaces/interface.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_interfacet object.
59 struct private_stroke_interface_t
{
62 * Public part of stroke_interfacet object.
64 stroke_interface_t
public;
67 * Unix socket to listen for strokes
72 * Thread which reads from the Socket
74 pthread_t threads
[STROKE_THREADS
];
77 typedef struct stroke_log_info_t stroke_log_info_t
;
80 * helper struct to say what and where to log when using controller callback
82 struct stroke_log_info_t
{
96 * Helper function which corrects the string pointers
97 * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
98 * contains RELATIVE addresses (relative to the beginning of the
99 * stroke_msg). They must be corrected if they reach our address
102 static void pop_string(stroke_msg_t
*msg
, char **string
)
107 /* check for sanity of string pointer and string */
108 if (string
< (char**)msg
109 || string
> (char**)msg
+ sizeof(stroke_msg_t
)
110 || (unsigned long)*string
< (unsigned long)((char*)msg
->buffer
- (char*)msg
)
111 || (unsigned long)*string
> msg
->length
)
113 *string
= "(invalid pointer in stroke msg)";
117 *string
= (char*)msg
+ (unsigned long)*string
;
122 * Load end entitity certificate
124 static x509_t
* load_end_certificate(const char *filename
, identification_t
**idp
)
129 if (*filename
== '/')
131 /* absolute path name */
132 snprintf(path
, sizeof(path
), "%s", filename
);
136 /* relative path name */
137 snprintf(path
, sizeof(path
), "%s/%s", CERTIFICATE_DIR
, filename
);
140 cert
= x509_create_from_file(path
, "end entity");
144 identification_t
*id
= *idp
;
145 identification_t
*subject
= cert
->get_subject(cert
);
147 err_t ugh
= cert
->is_valid(cert
, NULL
);
151 DBG1(DBG_CFG
, "warning: certificate %s", ugh
);
153 if (!id
->equals(id
, subject
) && !cert
->equals_subjectAltName(cert
, id
))
157 *idp
= id
->clone(id
);
159 return charon
->credentials
->add_end_certificate(charon
->credentials
, cert
);
165 * Load ca certificate
167 static x509_t
* load_ca_certificate(const char *filename
)
172 if (*filename
== '/')
174 /* absolute path name */
175 snprintf(path
, sizeof(path
), "%s", filename
);
179 /* relative path name */
180 snprintf(path
, sizeof(path
), "%s/%s", CA_CERTIFICATE_DIR
, filename
);
183 cert
= x509_create_from_file(path
, "ca");
187 if (cert
->is_ca(cert
))
189 return charon
->credentials
->add_auth_certificate(charon
->credentials
, cert
, AUTH_CA
);
193 DBG1(DBG_CFG
, " CA basic constraints flag not set, cert discarded");
201 * Pop the strings of a stroke_end_t struct and log them for debugging purposes
203 static void pop_end(stroke_msg_t
*msg
, const char* label
, stroke_end_t
*end
)
205 pop_string(msg
, &end
->address
);
206 pop_string(msg
, &end
->subnet
);
207 pop_string(msg
, &end
->sourceip
);
208 pop_string(msg
, &end
->id
);
209 pop_string(msg
, &end
->cert
);
210 pop_string(msg
, &end
->ca
);
211 pop_string(msg
, &end
->groups
);
212 pop_string(msg
, &end
->updown
);
214 DBG2(DBG_CFG
, " %s=%s", label
, end
->address
);
215 DBG2(DBG_CFG
, " %ssubnet=%s", label
, end
->subnet
);
216 DBG2(DBG_CFG
, " %ssourceip=%s", label
, end
->sourceip
);
217 DBG2(DBG_CFG
, " %sid=%s", label
, end
->id
);
218 DBG2(DBG_CFG
, " %scert=%s", label
, end
->cert
);
219 DBG2(DBG_CFG
, " %sca=%s", label
, end
->ca
);
220 DBG2(DBG_CFG
, " %sgroups=%s", label
, end
->groups
);
221 DBG2(DBG_CFG
, " %supdown=%s", label
, end
->updown
);
225 * Add a connection to the configuration list
227 static void stroke_add_conn(private_stroke_interface_t
*this,
228 stroke_msg_t
*msg
, FILE *out
)
231 peer_cfg_t
*peer_cfg
;
232 child_cfg_t
*child_cfg
;
233 identification_t
*my_id
, *other_id
;
234 identification_t
*my_ca
= NULL
;
235 identification_t
*other_ca
= NULL
;
236 bool my_ca_same
= FALSE
;
237 bool other_ca_same
=FALSE
;
238 host_t
*my_host
, *other_host
, *my_subnet
, *other_subnet
;
239 host_t
*my_vip
= NULL
, *other_vip
= NULL
;
240 proposal_t
*proposal
;
241 traffic_selector_t
*my_ts
, *other_ts
;
243 bool use_existing
= FALSE
;
244 iterator_t
*iterator
;
246 pop_string(msg
, &msg
->add_conn
.name
);
247 DBG1(DBG_CFG
, "received stroke: add connection '%s'", msg
->add_conn
.name
);
248 DBG2(DBG_CFG
, "conn %s", msg
->add_conn
.name
);
249 pop_end(msg
, "left", &msg
->add_conn
.me
);
250 pop_end(msg
, "right", &msg
->add_conn
.other
);
251 pop_string(msg
, &msg
->add_conn
.algorithms
.ike
);
252 pop_string(msg
, &msg
->add_conn
.algorithms
.esp
);
253 DBG2(DBG_CFG
, " ike=%s", msg
->add_conn
.algorithms
.ike
);
254 DBG2(DBG_CFG
, " esp=%s", msg
->add_conn
.algorithms
.esp
);
256 my_host
= msg
->add_conn
.me
.address?
257 host_create_from_string(msg
->add_conn
.me
.address
, IKE_PORT
) : NULL
;
260 DBG1(DBG_CFG
, "invalid host: %s\n", msg
->add_conn
.me
.address
);
264 other_host
= msg
->add_conn
.other
.address ?
265 host_create_from_string(msg
->add_conn
.other
.address
, IKE_PORT
) : NULL
;
266 if (other_host
== NULL
)
268 DBG1(DBG_CFG
, "invalid host: %s\n", msg
->add_conn
.other
.address
);
269 my_host
->destroy(my_host
);
273 interface
= charon
->kernel_interface
->get_interface(charon
->kernel_interface
,
277 stroke_end_t tmp_end
;
280 DBG2(DBG_CFG
, "left is other host, swapping ends\n");
283 my_host
= other_host
;
284 other_host
= tmp_host
;
286 tmp_end
= msg
->add_conn
.me
;
287 msg
->add_conn
.me
= msg
->add_conn
.other
;
288 msg
->add_conn
.other
= tmp_end
;
293 interface
= charon
->kernel_interface
->get_interface(
294 charon
->kernel_interface
, my_host
);
297 DBG1(DBG_CFG
, "left nor right host is our side, aborting\n");
303 my_id
= identification_create_from_string(msg
->add_conn
.me
.id ?
304 msg
->add_conn
.me
.id
: msg
->add_conn
.me
.address
);
307 DBG1(DBG_CFG
, "invalid ID: %s\n", msg
->add_conn
.me
.id
);
311 other_id
= identification_create_from_string(msg
->add_conn
.other
.id ?
312 msg
->add_conn
.other
.id
: msg
->add_conn
.other
.address
);
313 if (other_id
== NULL
)
315 DBG1(DBG_CFG
, "invalid ID: %s\n", msg
->add_conn
.other
.id
);
316 my_id
->destroy(my_id
);
320 my_subnet
= host_create_from_string(msg
->add_conn
.me
.subnet ?
321 msg
->add_conn
.me
.subnet
: msg
->add_conn
.me
.address
, IKE_PORT
);
322 if (my_subnet
== NULL
)
324 DBG1(DBG_CFG
, "invalid subnet: %s\n", msg
->add_conn
.me
.subnet
);
328 other_subnet
= host_create_from_string(msg
->add_conn
.other
.subnet ?
329 msg
->add_conn
.other
.subnet
: msg
->add_conn
.other
.address
, IKE_PORT
);
330 if (other_subnet
== NULL
)
332 DBG1(DBG_CFG
, "invalid subnet: %s\n", msg
->add_conn
.me
.subnet
);
333 my_subnet
->destroy(my_subnet
);
337 if (msg
->add_conn
.me
.virtual_ip
)
339 my_vip
= host_create_from_string(msg
->add_conn
.me
.sourceip
, 0);
341 other_vip
= host_create_from_string(msg
->add_conn
.other
.sourceip
, 0);
343 if (msg
->add_conn
.me
.tohost
)
345 my_ts
= traffic_selector_create_dynamic(msg
->add_conn
.me
.protocol
,
346 my_host
->get_family(my_host
) == AF_INET ?
347 TS_IPV4_ADDR_RANGE
: TS_IPV6_ADDR_RANGE
,
348 msg
->add_conn
.me
.port ? msg
->add_conn
.me
.port
: 0,
349 msg
->add_conn
.me
.port ? msg
->add_conn
.me
.port
: 65535);
353 my_ts
= traffic_selector_create_from_subnet(my_subnet
,
354 msg
->add_conn
.me
.subnet ? msg
->add_conn
.me
.subnet_mask
: 0,
355 msg
->add_conn
.me
.protocol
, msg
->add_conn
.me
.port
);
357 my_subnet
->destroy(my_subnet
);
359 if (msg
->add_conn
.other
.tohost
)
361 other_ts
= traffic_selector_create_dynamic(msg
->add_conn
.other
.protocol
,
362 other_host
->get_family(other_host
) == AF_INET ?
363 TS_IPV4_ADDR_RANGE
: TS_IPV6_ADDR_RANGE
,
364 msg
->add_conn
.other
.port ? msg
->add_conn
.other
.port
: 0,
365 msg
->add_conn
.other
.port ? msg
->add_conn
.other
.port
: 65535);
369 other_ts
= traffic_selector_create_from_subnet(other_subnet
,
370 msg
->add_conn
.other
.subnet ? msg
->add_conn
.other
.subnet_mask
: 0,
371 msg
->add_conn
.other
.protocol
, msg
->add_conn
.other
.port
);
373 other_subnet
->destroy(other_subnet
);
375 if (msg
->add_conn
.me
.ca
)
377 if (streq(msg
->add_conn
.me
.ca
, "%same"))
383 my_ca
= identification_create_from_string(msg
->add_conn
.me
.ca
);
386 if (msg
->add_conn
.other
.ca
)
388 if (streq(msg
->add_conn
.other
.ca
, "%same"))
390 other_ca_same
= TRUE
;
394 other_ca
= identification_create_from_string(msg
->add_conn
.other
.ca
);
397 if (msg
->add_conn
.me
.cert
)
399 x509_t
*cert
= load_end_certificate(msg
->add_conn
.me
.cert
, &my_id
);
405 if (cert
->is_self_signed(cert
))
407 /* a self-signed certificate is its own ca */
408 ca_info
= ca_info_create(NULL
, cert
);
409 ca_info
= charon
->credentials
->add_ca_info(charon
->credentials
, ca_info
);
410 cert
->set_ca_info(cert
, ca_info
);
414 /* get_issuer() automatically sets cert->ca_info */
415 ca_info
= charon
->credentials
->get_issuer(charon
->credentials
, cert
);
417 if (my_ca
== NULL
&& !my_ca_same
)
419 identification_t
*issuer
= cert
->get_issuer(cert
);
421 my_ca
= issuer
->clone(issuer
);
425 if (msg
->add_conn
.other
.cert
)
427 x509_t
*cert
= load_end_certificate(msg
->add_conn
.other
.cert
, &other_id
);
433 if (cert
->is_self_signed(cert
))
435 /* a self-signed certificate is its own ca */
436 ca_info
= ca_info_create(NULL
, cert
);
437 ca_info
= charon
->credentials
->add_ca_info(charon
->credentials
, ca_info
);
438 cert
->set_ca_info(cert
, ca_info
);
442 /* get_issuer() automatically sets cert->ca_info */
443 ca_info
= charon
->credentials
->get_issuer(charon
->credentials
, cert
);
445 if (other_ca
== NULL
&& !other_ca_same
)
447 identification_t
*issuer
= cert
->get_issuer(cert
);
449 other_ca
= issuer
->clone(issuer
);
453 if (other_ca_same
&& my_ca
)
455 other_ca
= my_ca
->clone(my_ca
);
457 else if (my_ca_same
&& other_ca
)
459 my_ca
= other_ca
->clone(other_ca
);
463 my_ca
= identification_create_from_string("%any");
465 if (other_ca
== NULL
)
467 other_ca
= identification_create_from_string("%any");
469 DBG2(DBG_CFG
, " my ca: '%D'", my_ca
);
470 DBG2(DBG_CFG
, " other ca:'%D'", other_ca
);
472 /* have a look for an (almost) identical peer config to reuse */
473 iterator
= charon
->backends
->create_iterator(charon
->backends
);
474 while (iterator
->iterate(iterator
, (void**)&peer_cfg
))
476 ike_cfg
= peer_cfg
->get_ike_cfg(peer_cfg
);
477 if (my_id
->equals(my_id
, peer_cfg
->get_my_id(peer_cfg
))
478 && other_id
->equals(other_id
, peer_cfg
->get_other_id(peer_cfg
))
479 && my_host
->equals(my_host
, ike_cfg
->get_my_host(ike_cfg
))
480 && other_host
->equals(other_host
, ike_cfg
->get_other_host(ike_cfg
))
481 && other_ca
->equals(other_ca
, peer_cfg
->get_other_ca(peer_cfg
))
482 && peer_cfg
->get_ike_version(peer_cfg
) == (msg
->add_conn
.ikev2 ?
2 : 1)
483 && peer_cfg
->get_auth_method(peer_cfg
) == msg
->add_conn
.auth_method
484 && peer_cfg
->get_eap_type(peer_cfg
) == msg
->add_conn
.eap_type
)
486 DBG1(DBG_CFG
, "reusing existing configuration '%s'",
487 peer_cfg
->get_name(peer_cfg
));
492 iterator
->destroy(iterator
);
497 DESTROY_IF(other_vip
);
498 my_host
->destroy(my_host
);
499 my_id
->destroy(my_id
);
500 my_ca
->destroy(my_ca
);
501 other_host
->destroy(other_host
);
502 other_id
->destroy(other_id
);
503 other_ca
->destroy(other_ca
);
507 ike_cfg
= ike_cfg_create(msg
->add_conn
.other
.sendcert
!= CERT_NEVER_SEND
,
508 my_host
, other_host
);
510 if (msg
->add_conn
.algorithms
.ike
)
512 char *proposal_string
;
513 char *strict
= msg
->add_conn
.algorithms
.ike
+ strlen(msg
->add_conn
.algorithms
.ike
) - 1;
520 while ((proposal_string
= strsep(&msg
->add_conn
.algorithms
.ike
, ",")))
522 proposal
= proposal_create_from_string(PROTO_IKE
, proposal_string
);
523 if (proposal
== NULL
)
525 DBG1(DBG_CFG
, "invalid IKE proposal string: %s", proposal_string
);
526 my_id
->destroy(my_id
);
527 other_id
->destroy(other_id
);
528 my_ts
->destroy(my_ts
);
529 other_ts
->destroy(other_ts
);
530 my_ca
->destroy(my_ca
);
531 other_ca
->destroy(other_ca
);
532 ike_cfg
->destroy(ike_cfg
);
535 ike_cfg
->add_proposal(ike_cfg
, proposal
);
539 proposal
= proposal_create_default(PROTO_IKE
);
540 ike_cfg
->add_proposal(ike_cfg
, proposal
);
545 proposal
= proposal_create_default(PROTO_IKE
);
546 ike_cfg
->add_proposal(ike_cfg
, proposal
);
550 peer_cfg
= peer_cfg_create(msg
->add_conn
.name
, msg
->add_conn
.ikev2 ?
2 : 1,
551 ike_cfg
, my_id
, other_id
, my_ca
, other_ca
, msg
->add_conn
.me
.sendcert
,
552 msg
->add_conn
.auth_method
, msg
->add_conn
.eap_type
,
553 msg
->add_conn
.rekey
.tries
, msg
->add_conn
.rekey
.ike_lifetime
,
554 msg
->add_conn
.rekey
.ike_lifetime
- msg
->add_conn
.rekey
.margin
,
555 msg
->add_conn
.rekey
.margin
* msg
->add_conn
.rekey
.fuzz
/ 100,
556 msg
->add_conn
.rekey
.reauth
, msg
->add_conn
.dpd
.delay
,
557 msg
->add_conn
.dpd
.action
,my_vip
, other_vip
);
560 child_cfg
= child_cfg_create(
561 msg
->add_conn
.name
, msg
->add_conn
.rekey
.ipsec_lifetime
,
562 msg
->add_conn
.rekey
.ipsec_lifetime
- msg
->add_conn
.rekey
.margin
,
563 msg
->add_conn
.rekey
.margin
* msg
->add_conn
.rekey
.fuzz
/ 100,
564 msg
->add_conn
.me
.updown
, msg
->add_conn
.me
.hostaccess
,
567 peer_cfg
->add_child_cfg(peer_cfg
, child_cfg
);
569 child_cfg
->add_traffic_selector(child_cfg
, TRUE
, my_ts
);
570 child_cfg
->add_traffic_selector(child_cfg
, FALSE
, other_ts
);
572 if (msg
->add_conn
.algorithms
.esp
)
574 char *proposal_string
;
575 char *strict
= msg
->add_conn
.algorithms
.esp
+ strlen(msg
->add_conn
.algorithms
.esp
) - 1;
582 while ((proposal_string
= strsep(&msg
->add_conn
.algorithms
.esp
, ",")))
584 proposal
= proposal_create_from_string(PROTO_ESP
, proposal_string
);
585 if (proposal
== NULL
)
587 DBG1(DBG_CFG
, "invalid ESP proposal string: %s", proposal_string
);
588 peer_cfg
->destroy(peer_cfg
);
591 child_cfg
->add_proposal(child_cfg
, proposal
);
595 proposal
= proposal_create_default(PROTO_ESP
);
596 child_cfg
->add_proposal(child_cfg
, proposal
);
601 proposal
= proposal_create_default(PROTO_ESP
);
602 child_cfg
->add_proposal(child_cfg
, proposal
);
607 /* add config to backend */
608 charon
->backends
->add_peer_cfg(charon
->backends
, peer_cfg
);
609 DBG1(DBG_CFG
, "added configuration '%s': %H[%D]...%H[%D]",
610 msg
->add_conn
.name
, my_host
, my_id
, other_host
, other_id
);
614 /* mopping up after parsing errors */
617 my_id
->destroy(my_id
);
618 other_id
->destroy(other_id
);
621 my_host
->destroy(my_host
);
622 other_host
->destroy(other_host
);
626 * Delete a connection from the list
628 static void stroke_del_conn(private_stroke_interface_t
*this,
629 stroke_msg_t
*msg
, FILE *out
)
631 iterator_t
*peer_iter
, *child_iter
;
632 peer_cfg_t
*peer
, *child
;
634 pop_string(msg
, &(msg
->del_conn
.name
));
635 DBG1(DBG_CFG
, "received stroke: delete connection '%s'", msg
->del_conn
.name
);
637 peer_iter
= charon
->backends
->create_iterator(charon
->backends
);
638 while (peer_iter
->iterate(peer_iter
, (void**)&peer
))
640 /* remove peer config with such a name */
641 if (streq(peer
->get_name(peer
), msg
->del_conn
.name
))
643 peer_iter
->remove(peer_iter
);
647 /* remove any child with such a name */
648 child_iter
= peer
->create_child_cfg_iterator(peer
);
649 while (child_iter
->iterate(child_iter
, (void**)&child
))
651 if (streq(child
->get_name(child
), msg
->del_conn
.name
))
653 child_iter
->remove(child_iter
);
654 child
->destroy(child
);
657 child_iter
->destroy(child_iter
);
659 peer_iter
->destroy(peer_iter
);
661 fprintf(out
, "deleted connection '%s'\n", msg
->del_conn
.name
);
665 * get the child_cfg with the same name as the peer cfg
667 static child_cfg_t
* get_child_from_peer(peer_cfg_t
*peer_cfg
, char *name
)
669 child_cfg_t
*current
, *found
= NULL
;
670 iterator_t
*iterator
;
672 iterator
= peer_cfg
->create_child_cfg_iterator(peer_cfg
);
673 while (iterator
->iterate(iterator
, (void**)¤t
))
675 if (streq(current
->get_name(current
), name
))
678 found
->get_ref(found
);
682 iterator
->destroy(iterator
);
687 * logging to the stroke interface
689 static bool stroke_log(stroke_log_info_t
*info
, signal_t signal
, level_t level
,
690 ike_sa_t
*ike_sa
, char *format
, va_list args
)
692 if (level
<= info
->level
)
694 if (vfprintf(info
->out
, format
, args
) < 0 ||
695 fprintf(info
->out
, "\n") < 0 ||
696 fflush(info
->out
) != 0)
705 * get a peer configuration by its name, or a name of its children
707 static peer_cfg_t
*get_peer_cfg_by_name(char *name
)
710 peer_cfg_t
*current
, *found
= NULL
;
713 i1
= charon
->backends
->create_iterator(charon
->backends
);
714 while (i1
->iterate(i1
, (void**)¤t
))
716 /* compare peer_cfgs name first */
717 if (streq(current
->get_name(current
), name
))
720 found
->get_ref(found
);
723 /* compare all child_cfg names otherwise */
724 i2
= current
->create_child_cfg_iterator(current
);
725 while (i2
->iterate(i2
, (void**)&child
))
727 if (streq(child
->get_name(child
), name
))
730 found
->get_ref(found
);
745 * initiate a connection by name
747 static void stroke_initiate(private_stroke_interface_t
*this,
748 stroke_msg_t
*msg
, FILE *out
)
750 peer_cfg_t
*peer_cfg
;
751 child_cfg_t
*child_cfg
;
752 stroke_log_info_t info
;
754 pop_string(msg
, &(msg
->initiate
.name
));
755 DBG1(DBG_CFG
, "received stroke: initiate '%s'", msg
->initiate
.name
);
757 peer_cfg
= get_peer_cfg_by_name(msg
->initiate
.name
);
758 if (peer_cfg
== NULL
)
760 fprintf(out
, "no config named '%s'\n", msg
->initiate
.name
);
763 if (peer_cfg
->get_ike_version(peer_cfg
) != 2)
765 DBG1(DBG_CFG
, "ignoring initiation request for IKEv%d config",
766 peer_cfg
->get_ike_version(peer_cfg
));
767 peer_cfg
->destroy(peer_cfg
);
771 child_cfg
= get_child_from_peer(peer_cfg
, msg
->initiate
.name
);
772 if (child_cfg
== NULL
)
774 fprintf(out
, "no child config named '%s'\n", msg
->initiate
.name
);
775 peer_cfg
->destroy(peer_cfg
);
780 info
.level
= msg
->output_verbosity
;
782 charon
->interfaces
->initiate(charon
->interfaces
, peer_cfg
, child_cfg
,
783 (interface_manager_cb_t
)stroke_log
, &info
);
784 peer_cfg
->destroy(peer_cfg
);
785 child_cfg
->destroy(child_cfg
);
789 * route a policy (install SPD entries)
791 static void stroke_route(private_stroke_interface_t
*this,
792 stroke_msg_t
*msg
, FILE *out
)
794 peer_cfg_t
*peer_cfg
;
795 child_cfg_t
*child_cfg
;
796 stroke_log_info_t info
;
798 pop_string(msg
, &(msg
->route
.name
));
799 DBG1(DBG_CFG
, "received stroke: route '%s'", msg
->route
.name
);
801 peer_cfg
= get_peer_cfg_by_name(msg
->route
.name
);
802 if (peer_cfg
== NULL
)
804 fprintf(out
, "no config named '%s'\n", msg
->route
.name
);
807 if (peer_cfg
->get_ike_version(peer_cfg
) != 2)
809 peer_cfg
->destroy(peer_cfg
);
813 child_cfg
= get_child_from_peer(peer_cfg
, msg
->route
.name
);
814 if (child_cfg
== NULL
)
816 fprintf(out
, "no child config named '%s'\n", msg
->route
.name
);
817 peer_cfg
->destroy(peer_cfg
);
822 info
.level
= msg
->output_verbosity
;
823 charon
->interfaces
->route(charon
->interfaces
, peer_cfg
, child_cfg
,
824 (interface_manager_cb_t
)stroke_log
, &info
);
825 peer_cfg
->destroy(peer_cfg
);
826 child_cfg
->destroy(child_cfg
);
832 static void stroke_unroute(private_stroke_interface_t
*this,
833 stroke_msg_t
*msg
, FILE *out
)
837 iterator_t
*iterator
;
838 stroke_log_info_t info
;
840 pop_string(msg
, &(msg
->terminate
.name
));
841 name
= msg
->terminate
.name
;
844 info
.level
= msg
->output_verbosity
;
846 iterator
= charon
->interfaces
->create_ike_sa_iterator(charon
->interfaces
);
847 while (iterator
->iterate(iterator
, (void**)&ike_sa
))
849 child_sa_t
*child_sa
;
850 iterator_t
*children
;
853 children
= ike_sa
->create_child_sa_iterator(ike_sa
);
854 while (children
->iterate(children
, (void**)&child_sa
))
856 if (child_sa
->get_state(child_sa
) == CHILD_ROUTED
&&
857 streq(name
, child_sa
->get_name(child_sa
)))
859 id
= child_sa
->get_reqid(child_sa
);
860 children
->destroy(children
);
861 iterator
->destroy(iterator
);
862 charon
->interfaces
->unroute(charon
->interfaces
, id
,
863 (interface_manager_cb_t
)stroke_log
, &info
);
867 children
->destroy(children
);
869 iterator
->destroy(iterator
);
870 DBG1(DBG_CFG
, "no such SA found");
874 * terminate a connection by name
876 static void stroke_terminate(private_stroke_interface_t
*this,
877 stroke_msg_t
*msg
, FILE *out
)
879 char *string
, *pos
= NULL
, *name
= NULL
;
884 iterator_t
*iterator
;
885 stroke_log_info_t info
;
887 pop_string(msg
, &(msg
->terminate
.name
));
888 string
= msg
->terminate
.name
;
889 DBG1(DBG_CFG
, "received stroke: terminate '%s'", string
);
891 len
= strlen(string
);
894 DBG1(DBG_CFG
, "error parsing string");
897 switch (string
[len
-1])
901 pos
= strchr(string
, '{');
905 pos
= strchr(string
, '[');
915 /* is a single name */
917 else if (pos
== string
+ len
- 2)
918 { /* is name[] or name{} */
919 string
[len
-2] = '\0';
923 { /* is name[123] or name{23} */
924 string
[len
-1] = '\0';
928 DBG1(DBG_CFG
, "error parsing string");
934 info
.level
= msg
->output_verbosity
;
936 iterator
= charon
->interfaces
->create_ike_sa_iterator(charon
->interfaces
);
937 while (iterator
->iterate(iterator
, (void**)&ike_sa
))
939 child_sa_t
*child_sa
;
940 iterator_t
*children
;
944 children
= ike_sa
->create_child_sa_iterator(ike_sa
);
945 while (children
->iterate(children
, (void**)&child_sa
))
947 if ((name
&& streq(name
, child_sa
->get_name(child_sa
))) ||
948 (id
&& id
== child_sa
->get_reqid(child_sa
)))
950 id
= child_sa
->get_reqid(child_sa
);
951 children
->destroy(children
);
952 iterator
->destroy(iterator
);
954 charon
->interfaces
->terminate_child(charon
->interfaces
, id
,
955 (interface_manager_cb_t
)stroke_log
, &info
);
959 children
->destroy(children
);
961 else if ((name
&& streq(name
, ike_sa
->get_name(ike_sa
))) ||
962 (id
&& id
== ike_sa
->get_unique_id(ike_sa
)))
964 id
= ike_sa
->get_unique_id(ike_sa
);
965 /* unlock manager first */
966 iterator
->destroy(iterator
);
968 charon
->interfaces
->terminate_ike(charon
->interfaces
, id
,
969 (interface_manager_cb_t
)stroke_log
, &info
);
974 iterator
->destroy(iterator
);
975 DBG1(DBG_CFG
, "no such SA found");
979 * Add a ca information record to the cainfo list
981 static void stroke_add_ca(private_stroke_interface_t
*this,
982 stroke_msg_t
*msg
, FILE *out
)
987 pop_string(msg
, &msg
->add_ca
.name
);
988 pop_string(msg
, &msg
->add_ca
.cacert
);
989 pop_string(msg
, &msg
->add_ca
.crluri
);
990 pop_string(msg
, &msg
->add_ca
.crluri2
);
991 pop_string(msg
, &msg
->add_ca
.ocspuri
);
992 pop_string(msg
, &msg
->add_ca
.ocspuri2
);
994 DBG1(DBG_CFG
, "received stroke: add ca '%s'", msg
->add_ca
.name
);
996 DBG2(DBG_CFG
, "ca %s", msg
->add_ca
.name
);
997 DBG2(DBG_CFG
, " cacert=%s", msg
->add_ca
.cacert
);
998 DBG2(DBG_CFG
, " crluri=%s", msg
->add_ca
.crluri
);
999 DBG2(DBG_CFG
, " crluri2=%s", msg
->add_ca
.crluri2
);
1000 DBG2(DBG_CFG
, " ocspuri=%s", msg
->add_ca
.ocspuri
);
1001 DBG2(DBG_CFG
, " ocspuri2=%s", msg
->add_ca
.ocspuri2
);
1003 if (msg
->add_ca
.cacert
== NULL
)
1005 DBG1(DBG_CFG
, "missing cacert parameter\n");
1009 cacert
= load_ca_certificate(msg
->add_ca
.cacert
);
1015 ca_info
= ca_info_create(msg
->add_ca
.name
, cacert
);
1017 if (msg
->add_ca
.crluri
)
1019 chunk_t uri
= { msg
->add_ca
.crluri
, strlen(msg
->add_ca
.crluri
) };
1021 ca_info
->add_crluri(ca_info
, uri
);
1023 if (msg
->add_ca
.crluri2
)
1025 chunk_t uri
= { msg
->add_ca
.crluri2
, strlen(msg
->add_ca
.crluri2
) };
1027 ca_info
->add_crluri(ca_info
, uri
);
1029 if (msg
->add_ca
.ocspuri
)
1031 chunk_t uri
= { msg
->add_ca
.ocspuri
, strlen(msg
->add_ca
.ocspuri
) };
1033 ca_info
->add_ocspuri(ca_info
, uri
);
1035 if (msg
->add_ca
.ocspuri2
)
1037 chunk_t uri
= { msg
->add_ca
.ocspuri2
, strlen(msg
->add_ca
.ocspuri2
) };
1039 ca_info
->add_ocspuri(ca_info
, uri
);
1041 charon
->credentials
->add_ca_info(charon
->credentials
, ca_info
);
1042 DBG1(DBG_CFG
, "added ca '%s'", msg
->add_ca
.name
);
1047 * Delete a ca information record from the cainfo list
1049 static void stroke_del_ca(private_stroke_interface_t
*this,
1050 stroke_msg_t
*msg
, FILE *out
)
1054 pop_string(msg
, &(msg
->del_ca
.name
));
1055 DBG1(DBG_CFG
, "received stroke: delete ca '%s'", msg
->del_ca
.name
);
1057 status
= charon
->credentials
->release_ca_info(charon
->credentials
,
1060 if (status
== SUCCESS
)
1062 fprintf(out
, "deleted ca '%s'\n", msg
->del_ca
.name
);
1066 fprintf(out
, "no ca named '%s'\n", msg
->del_ca
.name
);
1071 * log an IKE_SA to out
1073 static void log_ike_sa(FILE *out
, ike_sa_t
*ike_sa
, bool all
)
1075 peer_cfg_t
*cfg
= ike_sa
->get_peer_cfg(ike_sa
);
1076 ike_sa_id_t
*id
= ike_sa
->get_id(ike_sa
);
1077 u_int32_t next
, now
= time(NULL
);
1079 fprintf(out
, "%12s[%d]: %N, %H[%D]...%H[%D]\n",
1080 ike_sa
->get_name(ike_sa
), ike_sa
->get_unique_id(ike_sa
),
1081 ike_sa_state_names
, ike_sa
->get_state(ike_sa
),
1082 ike_sa
->get_my_host(ike_sa
), ike_sa
->get_my_id(ike_sa
),
1083 ike_sa
->get_other_host(ike_sa
), ike_sa
->get_other_id(ike_sa
));
1087 fprintf(out
, "%12s[%d]: IKE SPIs: 0x%0llx_i%s 0x%0llx_r%s, ",
1088 ike_sa
->get_name(ike_sa
), ike_sa
->get_unique_id(ike_sa
),
1089 id
->get_initiator_spi(id
), id
->is_initiator(id
) ?
"*" : "",
1090 id
->get_responder_spi(id
), id
->is_initiator(id
) ?
"" : "");
1092 ike_sa
->get_stats(ike_sa
, &next
);
1095 fprintf(out
, "%s in %V\n", cfg
->use_reauth(cfg
) ?
1096 "reauthentication" : "rekeying", &now
, &next
);
1100 fprintf(out
, "rekeying disabled\n");
1106 * log an CHILD_SA to out
1108 static void log_child_sa(FILE *out
, child_sa_t
*child_sa
, bool all
)
1110 u_int32_t rekey
, now
= time(NULL
);
1111 u_int32_t use_in
, use_out
, use_fwd
;
1112 encryption_algorithm_t encr_alg
;
1113 integrity_algorithm_t int_alg
;
1114 size_t encr_len
, int_len
;
1117 child_sa
->get_stats(child_sa
, &mode
, &encr_alg
, &encr_len
,
1118 &int_alg
, &int_len
, &rekey
, &use_in
, &use_out
,
1121 fprintf(out
, "%12s{%d}: %N, %N",
1122 child_sa
->get_name(child_sa
), child_sa
->get_reqid(child_sa
),
1123 child_sa_state_names
, child_sa
->get_state(child_sa
),
1126 if (child_sa
->get_state(child_sa
) == CHILD_INSTALLED
)
1128 fprintf(out
, ", %N SPIs: 0x%0x_i 0x%0x_o",
1129 protocol_id_names
, child_sa
->get_protocol(child_sa
),
1130 htonl(child_sa
->get_spi(child_sa
, TRUE
)),
1131 htonl(child_sa
->get_spi(child_sa
, FALSE
)));
1135 fprintf(out
, "\n%12s{%d}: ", child_sa
->get_name(child_sa
),
1136 child_sa
->get_reqid(child_sa
));
1139 if (child_sa
->get_protocol(child_sa
) == PROTO_ESP
)
1141 fprintf(out
, "%N", encryption_algorithm_names
, encr_alg
);
1145 fprintf(out
, "-%d", encr_len
);
1150 fprintf(out
, "%N", integrity_algorithm_names
, int_alg
);
1153 fprintf(out
, "-%d", int_len
);
1155 fprintf(out
, ", rekeying ");
1159 fprintf(out
, "in %V", &now
, &rekey
);
1163 fprintf(out
, "disabled");
1166 fprintf(out
, ", last use: ");
1167 use_in
= max(use_in
, use_fwd
);
1170 fprintf(out
, "%ds_i ", now
- use_in
);
1174 fprintf(out
, "no_i ");
1178 fprintf(out
, "%ds_o ", now
- use_out
);
1182 fprintf(out
, "no_o ");
1187 fprintf(out
, "\n%12s{%d}: %#R=== %#R\n",
1188 child_sa
->get_name(child_sa
), child_sa
->get_reqid(child_sa
),
1189 child_sa
->get_traffic_selectors(child_sa
, TRUE
),
1190 child_sa
->get_traffic_selectors(child_sa
, FALSE
));
1194 * show status of daemon
1196 static void stroke_status(private_stroke_interface_t
*this,
1197 stroke_msg_t
*msg
, FILE *out
, bool all
)
1199 iterator_t
*iterator
, *children
;
1200 linked_list_t
*list
;
1202 peer_cfg_t
*peer_cfg
;
1204 child_cfg_t
*child_cfg
;
1208 if (msg
->status
.name
)
1210 pop_string(msg
, &(msg
->status
.name
));
1211 name
= msg
->status
.name
;
1216 leak_detective_status(out
);
1218 fprintf(out
, "Performance:\n");
1219 fprintf(out
, " worker threads: %d idle of %d,",
1220 charon
->thread_pool
->get_idle_threads(charon
->thread_pool
),
1221 charon
->thread_pool
->get_pool_size(charon
->thread_pool
));
1222 fprintf(out
, " job queue load: %d,",
1223 charon
->job_queue
->get_count(charon
->job_queue
));
1224 fprintf(out
, " scheduled events: %d\n",
1225 charon
->event_queue
->get_count(charon
->event_queue
));
1226 list
= charon
->kernel_interface
->create_address_list(charon
->kernel_interface
);
1228 fprintf(out
, "Listening on %d IP addresses:\n", list
->get_count(list
));
1229 while (list
->remove_first(list
, (void**)&host
) == SUCCESS
)
1231 fprintf(out
, " %H\n", host
);
1232 host
->destroy(host
);
1234 list
->destroy(list
);
1236 fprintf(out
, "Connections:\n");
1237 iterator
= charon
->backends
->create_iterator(charon
->backends
);
1238 while (iterator
->iterate(iterator
, (void**)&peer_cfg
))
1240 if (peer_cfg
->get_ike_version(peer_cfg
) != 2 ||
1241 (name
&& !streq(name
, peer_cfg
->get_name(peer_cfg
))))
1246 ike_cfg
= peer_cfg
->get_ike_cfg(peer_cfg
);
1247 fprintf(out
, "%12s: %H[%D]...%H[%D]\n", peer_cfg
->get_name(peer_cfg
),
1248 ike_cfg
->get_my_host(ike_cfg
), peer_cfg
->get_my_id(peer_cfg
),
1249 ike_cfg
->get_other_host(ike_cfg
), peer_cfg
->get_other_id(peer_cfg
));
1251 identification_t
*my_ca
= peer_cfg
->get_my_ca(peer_cfg
);
1252 identification_t
*other_ca
= peer_cfg
->get_other_ca(peer_cfg
);
1254 if (my_ca
->get_type(my_ca
) != ID_ANY
1255 || other_ca
->get_type(other_ca
) != ID_ANY
)
1257 fprintf(out
, "%12s: CAs: '%D'...'%D'\n", peer_cfg
->get_name(peer_cfg
),
1261 children
= peer_cfg
->create_child_cfg_iterator(peer_cfg
);
1262 while (children
->iterate(children
, (void**)&child_cfg
))
1264 linked_list_t
*my_ts
, *other_ts
;
1265 my_ts
= child_cfg
->get_traffic_selectors(child_cfg
, TRUE
, NULL
, NULL
);
1266 other_ts
= child_cfg
->get_traffic_selectors(child_cfg
, FALSE
, NULL
, NULL
);
1267 fprintf(out
, "%12s: %#R=== %#R\n", child_cfg
->get_name(child_cfg
),
1269 my_ts
->destroy_offset(my_ts
, offsetof(traffic_selector_t
, destroy
));
1270 other_ts
->destroy_offset(other_ts
, offsetof(traffic_selector_t
, destroy
));
1272 children
->destroy(children
);
1274 iterator
->destroy(iterator
);
1277 iterator
= charon
->ike_sa_manager
->create_iterator(charon
->ike_sa_manager
);
1278 if (all
&& iterator
->get_count(iterator
) > 0)
1280 fprintf(out
, "Security Associations:\n");
1282 while (iterator
->iterate(iterator
, (void**)&ike_sa
))
1284 bool ike_printed
= FALSE
;
1285 child_sa_t
*child_sa
;
1286 iterator_t
*children
= ike_sa
->create_child_sa_iterator(ike_sa
);
1288 if (name
== NULL
|| streq(name
, ike_sa
->get_name(ike_sa
)))
1290 log_ike_sa(out
, ike_sa
, all
);
1294 while (children
->iterate(children
, (void**)&child_sa
))
1296 if (name
== NULL
|| streq(name
, child_sa
->get_name(child_sa
)))
1300 log_ike_sa(out
, ike_sa
, all
);
1303 log_child_sa(out
, child_sa
, all
);
1306 children
->destroy(children
);
1308 iterator
->destroy(iterator
);
1312 * list all authority certificates matching a specified flag
1314 static void list_auth_certificates(private_stroke_interface_t
*this, u_int flag
,
1315 const char *label
, bool utc
, FILE *out
)
1320 iterator_t
*iterator
= charon
->credentials
->create_auth_cert_iterator(charon
->credentials
);
1322 while (iterator
->iterate(iterator
, (void**)&cert
))
1324 if (cert
->has_authority_flag(cert
, flag
))
1329 fprintf(out
, "List of X.509 %s Certificates:\n", label
);
1333 cert
->list(cert
, out
, utc
);
1337 iterator
->destroy(iterator
);
1341 * list various information
1343 static void stroke_list(private_stroke_interface_t
*this,
1344 stroke_msg_t
*msg
, FILE *out
)
1346 iterator_t
*iterator
;
1348 if (msg
->list
.flags
& LIST_CERTS
)
1352 iterator
= charon
->credentials
->create_cert_iterator(charon
->credentials
);
1353 if (iterator
->get_count(iterator
))
1356 fprintf(out
, "List of X.509 End Entity Certificates:\n");
1359 while (iterator
->iterate(iterator
, (void**)&cert
))
1361 cert
->list(cert
, out
, msg
->list
.utc
);
1362 if (charon
->credentials
->has_rsa_private_key(
1363 charon
->credentials
, cert
->get_public_key(cert
)))
1365 fprintf(out
, ", has private key");
1370 iterator
->destroy(iterator
);
1372 if (msg
->list
.flags
& LIST_CACERTS
)
1374 list_auth_certificates(this, AUTH_CA
, "CA", msg
->list
.utc
, out
);
1376 if (msg
->list
.flags
& LIST_OCSPCERTS
)
1378 list_auth_certificates(this, AUTH_OCSP
, "OCSP", msg
->list
.utc
, out
);
1380 if (msg
->list
.flags
& LIST_AACERTS
)
1382 list_auth_certificates(this, AUTH_AA
, "AA", msg
->list
.utc
, out
);
1384 if (msg
->list
.flags
& LIST_CAINFOS
)
1389 iterator
= charon
->credentials
->create_cainfo_iterator(charon
->credentials
);
1390 while (iterator
->iterate(iterator
, (void**)&ca_info
))
1392 if (ca_info
->is_ca(ca_info
))
1397 fprintf(out
, "List of X.509 CA Information Records:\n");
1401 ca_info
->list(ca_info
, out
, msg
->list
.utc
);
1404 iterator
->destroy(iterator
);
1406 if (msg
->list
.flags
& LIST_CRLS
)
1411 iterator
= charon
->credentials
->create_cainfo_iterator(charon
->credentials
);
1412 while (iterator
->iterate(iterator
, (void **)&ca_info
))
1414 if (ca_info
->is_ca(ca_info
) && ca_info
->has_crl(ca_info
))
1419 fprintf(out
, "List of X.509 CRLs:\n");
1423 ca_info
->list_crl(ca_info
, out
, msg
->list
.utc
);
1426 iterator
->destroy(iterator
);
1428 if (msg
->list
.flags
& LIST_OCSP
)
1433 iterator
= charon
->credentials
->create_cainfo_iterator(charon
->credentials
);
1434 while (iterator
->iterate(iterator
, (void **)&ca_info
))
1436 if (ca_info
->is_ca(ca_info
) && ca_info
->has_certinfos(ca_info
))
1441 fprintf(out
, "List of OCSP responses:\n");
1445 ca_info
->list_certinfos(ca_info
, out
, msg
->list
.utc
);
1448 iterator
->destroy(iterator
);
1453 * reread various information
1455 static void stroke_reread(private_stroke_interface_t
*this,
1456 stroke_msg_t
*msg
, FILE *out
)
1458 if (msg
->reread
.flags
& REREAD_CACERTS
)
1460 charon
->credentials
->load_ca_certificates(charon
->credentials
);
1462 if (msg
->reread
.flags
& REREAD_OCSPCERTS
)
1464 charon
->credentials
->load_ocsp_certificates(charon
->credentials
);
1466 if (msg
->reread
.flags
& REREAD_CRLS
)
1468 charon
->credentials
->load_crls(charon
->credentials
);
1473 * purge various information
1475 static void stroke_purge(private_stroke_interface_t
*this,
1476 stroke_msg_t
*msg
, FILE *out
)
1478 if (msg
->purge
.flags
& PURGE_OCSP
)
1480 iterator_t
*iterator
= charon
->credentials
->create_cainfo_iterator(charon
->credentials
);
1483 while (iterator
->iterate(iterator
, (void**)&ca_info
))
1485 if (ca_info
->is_ca(ca_info
))
1487 ca_info
->purge_ocsp(ca_info
);
1490 iterator
->destroy(iterator
);
1494 signal_t
get_signal_from_logtype(char *type
)
1496 if (strcasecmp(type
, "any") == 0) return SIG_ANY
;
1497 else if (strcasecmp(type
, "mgr") == 0) return DBG_MGR
;
1498 else if (strcasecmp(type
, "ike") == 0) return DBG_IKE
;
1499 else if (strcasecmp(type
, "chd") == 0) return DBG_CHD
;
1500 else if (strcasecmp(type
, "job") == 0) return DBG_JOB
;
1501 else if (strcasecmp(type
, "cfg") == 0) return DBG_CFG
;
1502 else if (strcasecmp(type
, "knl") == 0) return DBG_KNL
;
1503 else if (strcasecmp(type
, "net") == 0) return DBG_NET
;
1504 else if (strcasecmp(type
, "enc") == 0) return DBG_ENC
;
1505 else if (strcasecmp(type
, "lib") == 0) return DBG_LIB
;
1510 * set the verbosity debug output
1512 static void stroke_loglevel(private_stroke_interface_t
*this,
1513 stroke_msg_t
*msg
, FILE *out
)
1517 pop_string(msg
, &(msg
->loglevel
.type
));
1518 DBG1(DBG_CFG
, "received stroke: loglevel %d for %s",
1519 msg
->loglevel
.level
, msg
->loglevel
.type
);
1521 signal
= get_signal_from_logtype(msg
->loglevel
.type
);
1524 fprintf(out
, "invalid type (%s)!\n", msg
->loglevel
.type
);
1528 charon
->outlog
->set_level(charon
->outlog
, signal
, msg
->loglevel
.level
);
1529 charon
->syslog
->set_level(charon
->syslog
, signal
, msg
->loglevel
.level
);
1533 * process a stroke request from the socket pointed by "fd"
1535 static void stroke_process(private_stroke_interface_t
*this, int strokefd
)
1538 u_int16_t msg_length
;
1542 /* peek the length */
1543 bytes_read
= recv(strokefd
, &msg_length
, sizeof(msg_length
), MSG_PEEK
);
1544 if (bytes_read
!= sizeof(msg_length
))
1546 DBG1(DBG_CFG
, "reading length of stroke message failed");
1552 msg
= malloc(msg_length
);
1553 bytes_read
= recv(strokefd
, msg
, msg_length
, 0);
1554 if (bytes_read
!= msg_length
)
1556 DBG1(DBG_CFG
, "reading stroke message failed: %s", strerror(errno
));
1561 out
= fdopen(dup(strokefd
), "w");
1564 DBG1(DBG_CFG
, "opening stroke output channel failed: %s", strerror(errno
));
1570 DBG3(DBG_CFG
, "stroke message %b", (void*)msg
, msg_length
);
1575 stroke_initiate(this, msg
, out
);
1578 stroke_route(this, msg
, out
);
1581 stroke_unroute(this, msg
, out
);
1584 stroke_terminate(this, msg
, out
);
1587 stroke_status(this, msg
, out
, FALSE
);
1589 case STR_STATUS_ALL
:
1590 stroke_status(this, msg
, out
, TRUE
);
1593 stroke_add_conn(this, msg
, out
);
1596 stroke_del_conn(this, msg
, out
);
1599 stroke_add_ca(this, msg
, out
);
1602 stroke_del_ca(this, msg
, out
);
1605 stroke_loglevel(this, msg
, out
);
1608 stroke_list(this, msg
, out
);
1611 stroke_reread(this, msg
, out
);
1614 stroke_purge(this, msg
, out
);
1617 DBG1(DBG_CFG
, "received unknown stroke");
1625 * Implementation of private_stroke_interface_t.stroke_receive.
1627 static void stroke_receive(private_stroke_interface_t
*this)
1629 struct sockaddr_un strokeaddr
;
1630 int strokeaddrlen
= sizeof(strokeaddr
);
1634 charon
->drop_capabilities(charon
, TRUE
);
1636 /* ignore sigpipe. writing over the pipe back to the console
1637 * only fails if SIGPIPE is ignored. */
1638 signal(SIGPIPE
, SIG_IGN
);
1640 /* disable cancellation by default */
1641 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
1645 /* wait for connections, but allow thread to terminate */
1646 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, &oldstate
);
1647 strokefd
= accept(this->socket
, (struct sockaddr
*)&strokeaddr
, &strokeaddrlen
);
1648 pthread_setcancelstate(oldstate
, NULL
);
1652 DBG1(DBG_CFG
, "accepting stroke connection failed: %s", strerror(errno
));
1655 stroke_process(this, strokefd
);
1660 * Implementation of interface_t.destroy.
1662 static void destroy(private_stroke_interface_t
*this)
1666 for (i
= 0; i
< STROKE_THREADS
; i
++)
1668 pthread_cancel(this->threads
[i
]);
1669 pthread_join(this->threads
[i
], NULL
);
1672 close(this->socket
);
1673 unlink(socket_addr
.sun_path
);
1678 * Described in header-file
1680 interface_t
*interface_create()
1682 private_stroke_interface_t
*this = malloc_thing(private_stroke_interface_t
);
1686 /* public functions */
1687 this->public.interface
.destroy
= (void (*)(interface_t
*))destroy
;
1689 /* set up unix socket */
1690 this->socket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
1691 if (this->socket
== -1)
1693 DBG1(DBG_CFG
, "could not create stroke socket");
1698 old
= umask(~S_IRWXU
);
1699 if (bind(this->socket
, (struct sockaddr
*)&socket_addr
, sizeof(socket_addr
)) < 0)
1701 DBG1(DBG_CFG
, "could not bind stroke socket: %s", strerror(errno
));
1702 close(this->socket
);
1708 if (listen(this->socket
, 0) < 0)
1710 DBG1(DBG_CFG
, "could not listen on stroke socket: %s", strerror(errno
));
1711 close(this->socket
);
1712 unlink(socket_addr
.sun_path
);
1717 /* start threads reading from the socket */
1718 for (i
= 0; i
< STROKE_THREADS
; i
++)
1720 if (pthread_create(&this->threads
[i
], NULL
, (void*(*)(void*))stroke_receive
, this) != 0)
1722 charon
->kill(charon
, "unable to create stroke thread");
1726 return &this->public.interface
;