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>
46 #include <processing/jobs/callback_job.h>
50 #define STROKE_THREADS 3
52 struct sockaddr_un socket_addr
= { AF_UNIX
, STROKE_SOCKET
};
55 typedef struct private_stroke_interface_t private_stroke_interface_t
;
58 * Private data of an stroke_interfacet object.
60 struct private_stroke_interface_t
{
63 * Public part of stroke_interfacet object.
65 stroke_interface_t
public;
68 * Unix socket to listen for strokes
73 * job accepting stroke messages
78 typedef struct stroke_log_info_t stroke_log_info_t
;
81 * helper struct to say what and where to log when using controller callback
83 struct stroke_log_info_t
{
97 * Helper function which corrects the string pointers
98 * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
99 * contains RELATIVE addresses (relative to the beginning of the
100 * stroke_msg). They must be corrected if they reach our address
103 static void pop_string(stroke_msg_t
*msg
, char **string
)
108 /* check for sanity of string pointer and string */
109 if (string
< (char**)msg
110 || string
> (char**)msg
+ sizeof(stroke_msg_t
)
111 || (unsigned long)*string
< (unsigned long)((char*)msg
->buffer
- (char*)msg
)
112 || (unsigned long)*string
> msg
->length
)
114 *string
= "(invalid pointer in stroke msg)";
118 *string
= (char*)msg
+ (unsigned long)*string
;
123 * Load end entitity certificate
125 static x509_t
* load_end_certificate(const char *filename
, identification_t
**idp
)
130 if (*filename
== '/')
132 /* absolute path name */
133 snprintf(path
, sizeof(path
), "%s", filename
);
137 /* relative path name */
138 snprintf(path
, sizeof(path
), "%s/%s", CERTIFICATE_DIR
, filename
);
141 cert
= x509_create_from_file(path
, "end entity");
145 identification_t
*id
= *idp
;
146 identification_t
*subject
= cert
->get_subject(cert
);
148 err_t ugh
= cert
->is_valid(cert
, NULL
);
152 DBG1(DBG_CFG
, "warning: certificate %s", ugh
);
154 if (!id
->equals(id
, subject
) && !cert
->equals_subjectAltName(cert
, id
))
158 *idp
= id
->clone(id
);
160 return charon
->credentials
->add_end_certificate(charon
->credentials
, cert
);
166 * Load ca certificate
168 static x509_t
* load_ca_certificate(const char *filename
)
173 if (*filename
== '/')
175 /* absolute path name */
176 snprintf(path
, sizeof(path
), "%s", filename
);
180 /* relative path name */
181 snprintf(path
, sizeof(path
), "%s/%s", CA_CERTIFICATE_DIR
, filename
);
184 cert
= x509_create_from_file(path
, "ca");
188 if (cert
->is_ca(cert
))
190 return charon
->credentials
->add_auth_certificate(charon
->credentials
, cert
, AUTH_CA
);
194 DBG1(DBG_CFG
, " CA basic constraints flag not set, cert discarded");
202 * Pop the strings of a stroke_end_t struct and log them for debugging purposes
204 static void pop_end(stroke_msg_t
*msg
, const char* label
, stroke_end_t
*end
)
206 pop_string(msg
, &end
->address
);
207 pop_string(msg
, &end
->subnet
);
208 pop_string(msg
, &end
->sourceip
);
209 pop_string(msg
, &end
->id
);
210 pop_string(msg
, &end
->cert
);
211 pop_string(msg
, &end
->ca
);
212 pop_string(msg
, &end
->groups
);
213 pop_string(msg
, &end
->updown
);
215 DBG2(DBG_CFG
, " %s=%s", label
, end
->address
);
216 DBG2(DBG_CFG
, " %ssubnet=%s", label
, end
->subnet
);
217 DBG2(DBG_CFG
, " %ssourceip=%s", label
, end
->sourceip
);
218 DBG2(DBG_CFG
, " %sid=%s", label
, end
->id
);
219 DBG2(DBG_CFG
, " %scert=%s", label
, end
->cert
);
220 DBG2(DBG_CFG
, " %sca=%s", label
, end
->ca
);
221 DBG2(DBG_CFG
, " %sgroups=%s", label
, end
->groups
);
222 DBG2(DBG_CFG
, " %supdown=%s", label
, end
->updown
);
226 * Add a connection to the configuration list
228 static void stroke_add_conn(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 if (msg
->add_conn
.other
.virtual_ip
)
343 other_vip
= host_create_from_string(msg
->add_conn
.other
.sourceip
, 0);
346 if (msg
->add_conn
.me
.tohost
)
348 my_ts
= traffic_selector_create_dynamic(msg
->add_conn
.me
.protocol
,
349 my_host
->get_family(my_host
) == AF_INET ?
350 TS_IPV4_ADDR_RANGE
: TS_IPV6_ADDR_RANGE
,
351 msg
->add_conn
.me
.port ? msg
->add_conn
.me
.port
: 0,
352 msg
->add_conn
.me
.port ? msg
->add_conn
.me
.port
: 65535);
356 my_ts
= traffic_selector_create_from_subnet(my_subnet
,
357 msg
->add_conn
.me
.subnet ? msg
->add_conn
.me
.subnet_mask
: 0,
358 msg
->add_conn
.me
.protocol
, msg
->add_conn
.me
.port
);
360 my_subnet
->destroy(my_subnet
);
362 if (msg
->add_conn
.other
.tohost
)
364 other_ts
= traffic_selector_create_dynamic(msg
->add_conn
.other
.protocol
,
365 other_host
->get_family(other_host
) == AF_INET ?
366 TS_IPV4_ADDR_RANGE
: TS_IPV6_ADDR_RANGE
,
367 msg
->add_conn
.other
.port ? msg
->add_conn
.other
.port
: 0,
368 msg
->add_conn
.other
.port ? msg
->add_conn
.other
.port
: 65535);
372 other_ts
= traffic_selector_create_from_subnet(other_subnet
,
373 msg
->add_conn
.other
.subnet ? msg
->add_conn
.other
.subnet_mask
: 0,
374 msg
->add_conn
.other
.protocol
, msg
->add_conn
.other
.port
);
376 other_subnet
->destroy(other_subnet
);
378 if (msg
->add_conn
.me
.ca
)
380 if (streq(msg
->add_conn
.me
.ca
, "%same"))
386 my_ca
= identification_create_from_string(msg
->add_conn
.me
.ca
);
389 if (msg
->add_conn
.other
.ca
)
391 if (streq(msg
->add_conn
.other
.ca
, "%same"))
393 other_ca_same
= TRUE
;
397 other_ca
= identification_create_from_string(msg
->add_conn
.other
.ca
);
400 if (msg
->add_conn
.me
.cert
)
402 x509_t
*cert
= load_end_certificate(msg
->add_conn
.me
.cert
, &my_id
);
408 if (cert
->is_self_signed(cert
))
410 /* a self-signed certificate is its own ca */
411 ca_info
= ca_info_create(NULL
, cert
);
412 ca_info
= charon
->credentials
->add_ca_info(charon
->credentials
, ca_info
);
413 cert
->set_ca_info(cert
, ca_info
);
417 /* get_issuer() automatically sets cert->ca_info */
418 ca_info
= charon
->credentials
->get_issuer(charon
->credentials
, cert
);
420 if (my_ca
== NULL
&& !my_ca_same
)
422 identification_t
*issuer
= cert
->get_issuer(cert
);
424 my_ca
= issuer
->clone(issuer
);
428 if (msg
->add_conn
.other
.cert
)
430 x509_t
*cert
= load_end_certificate(msg
->add_conn
.other
.cert
, &other_id
);
436 if (cert
->is_self_signed(cert
))
438 /* a self-signed certificate is its own ca */
439 ca_info
= ca_info_create(NULL
, cert
);
440 ca_info
= charon
->credentials
->add_ca_info(charon
->credentials
, ca_info
);
441 cert
->set_ca_info(cert
, ca_info
);
445 /* get_issuer() automatically sets cert->ca_info */
446 ca_info
= charon
->credentials
->get_issuer(charon
->credentials
, cert
);
448 if (other_ca
== NULL
&& !other_ca_same
)
450 identification_t
*issuer
= cert
->get_issuer(cert
);
452 other_ca
= issuer
->clone(issuer
);
456 if (other_ca_same
&& my_ca
)
458 other_ca
= my_ca
->clone(my_ca
);
460 else if (my_ca_same
&& other_ca
)
462 my_ca
= other_ca
->clone(other_ca
);
466 my_ca
= identification_create_from_string("%any");
468 if (other_ca
== NULL
)
470 other_ca
= identification_create_from_string("%any");
472 DBG2(DBG_CFG
, " my ca: '%D'", my_ca
);
473 DBG2(DBG_CFG
, " other ca:'%D'", other_ca
);
475 /* have a look for an (almost) identical peer config to reuse */
476 iterator
= charon
->backends
->create_iterator(charon
->backends
);
477 while (iterator
->iterate(iterator
, (void**)&peer_cfg
))
479 ike_cfg
= peer_cfg
->get_ike_cfg(peer_cfg
);
480 if (my_id
->equals(my_id
, peer_cfg
->get_my_id(peer_cfg
))
481 && other_id
->equals(other_id
, peer_cfg
->get_other_id(peer_cfg
))
482 && my_host
->equals(my_host
, ike_cfg
->get_my_host(ike_cfg
))
483 && other_host
->equals(other_host
, ike_cfg
->get_other_host(ike_cfg
))
484 && other_ca
->equals(other_ca
, peer_cfg
->get_other_ca(peer_cfg
))
485 && peer_cfg
->get_ike_version(peer_cfg
) == (msg
->add_conn
.ikev2 ?
2 : 1)
486 && peer_cfg
->get_auth_method(peer_cfg
) == msg
->add_conn
.auth_method
487 && peer_cfg
->get_eap_type(peer_cfg
) == msg
->add_conn
.eap_type
)
489 DBG1(DBG_CFG
, "reusing existing configuration '%s'",
490 peer_cfg
->get_name(peer_cfg
));
495 iterator
->destroy(iterator
);
500 DESTROY_IF(other_vip
);
501 my_host
->destroy(my_host
);
502 my_id
->destroy(my_id
);
503 my_ca
->destroy(my_ca
);
504 other_host
->destroy(other_host
);
505 other_id
->destroy(other_id
);
506 other_ca
->destroy(other_ca
);
510 ike_cfg
= ike_cfg_create(msg
->add_conn
.other
.sendcert
!= CERT_NEVER_SEND
,
511 my_host
, other_host
);
513 if (msg
->add_conn
.algorithms
.ike
)
515 char *proposal_string
;
516 char *strict
= msg
->add_conn
.algorithms
.ike
+ strlen(msg
->add_conn
.algorithms
.ike
) - 1;
523 while ((proposal_string
= strsep(&msg
->add_conn
.algorithms
.ike
, ",")))
525 proposal
= proposal_create_from_string(PROTO_IKE
, proposal_string
);
526 if (proposal
== NULL
)
528 DBG1(DBG_CFG
, "invalid IKE proposal string: %s", proposal_string
);
529 my_id
->destroy(my_id
);
530 other_id
->destroy(other_id
);
531 my_ts
->destroy(my_ts
);
532 other_ts
->destroy(other_ts
);
533 my_ca
->destroy(my_ca
);
534 other_ca
->destroy(other_ca
);
535 ike_cfg
->destroy(ike_cfg
);
538 ike_cfg
->add_proposal(ike_cfg
, proposal
);
542 proposal
= proposal_create_default(PROTO_IKE
);
543 ike_cfg
->add_proposal(ike_cfg
, proposal
);
548 proposal
= proposal_create_default(PROTO_IKE
);
549 ike_cfg
->add_proposal(ike_cfg
, proposal
);
553 peer_cfg
= peer_cfg_create(msg
->add_conn
.name
, msg
->add_conn
.ikev2 ?
2 : 1,
554 ike_cfg
, my_id
, other_id
, my_ca
, other_ca
, msg
->add_conn
.me
.sendcert
,
555 msg
->add_conn
.auth_method
, msg
->add_conn
.eap_type
,
556 msg
->add_conn
.rekey
.tries
, msg
->add_conn
.rekey
.ike_lifetime
,
557 msg
->add_conn
.rekey
.ike_lifetime
- msg
->add_conn
.rekey
.margin
,
558 msg
->add_conn
.rekey
.margin
* msg
->add_conn
.rekey
.fuzz
/ 100,
559 msg
->add_conn
.rekey
.reauth
, msg
->add_conn
.dpd
.delay
,
560 msg
->add_conn
.dpd
.action
,my_vip
, other_vip
);
563 child_cfg
= child_cfg_create(
564 msg
->add_conn
.name
, msg
->add_conn
.rekey
.ipsec_lifetime
,
565 msg
->add_conn
.rekey
.ipsec_lifetime
- msg
->add_conn
.rekey
.margin
,
566 msg
->add_conn
.rekey
.margin
* msg
->add_conn
.rekey
.fuzz
/ 100,
567 msg
->add_conn
.me
.updown
, msg
->add_conn
.me
.hostaccess
,
570 peer_cfg
->add_child_cfg(peer_cfg
, child_cfg
);
572 child_cfg
->add_traffic_selector(child_cfg
, TRUE
, my_ts
);
573 child_cfg
->add_traffic_selector(child_cfg
, FALSE
, other_ts
);
575 if (msg
->add_conn
.algorithms
.esp
)
577 char *proposal_string
;
578 char *strict
= msg
->add_conn
.algorithms
.esp
+ strlen(msg
->add_conn
.algorithms
.esp
) - 1;
585 while ((proposal_string
= strsep(&msg
->add_conn
.algorithms
.esp
, ",")))
587 proposal
= proposal_create_from_string(PROTO_ESP
, proposal_string
);
588 if (proposal
== NULL
)
590 DBG1(DBG_CFG
, "invalid ESP proposal string: %s", proposal_string
);
591 peer_cfg
->destroy(peer_cfg
);
594 child_cfg
->add_proposal(child_cfg
, proposal
);
598 proposal
= proposal_create_default(PROTO_ESP
);
599 child_cfg
->add_proposal(child_cfg
, proposal
);
604 proposal
= proposal_create_default(PROTO_ESP
);
605 child_cfg
->add_proposal(child_cfg
, proposal
);
610 /* add config to backend */
611 charon
->backends
->add_peer_cfg(charon
->backends
, peer_cfg
);
612 DBG1(DBG_CFG
, "added configuration '%s': %H[%D]...%H[%D]",
613 msg
->add_conn
.name
, my_host
, my_id
, other_host
, other_id
);
617 /* mopping up after parsing errors */
620 my_id
->destroy(my_id
);
621 other_id
->destroy(other_id
);
624 my_host
->destroy(my_host
);
625 other_host
->destroy(other_host
);
629 * Delete a connection from the list
631 static void stroke_del_conn(stroke_msg_t
*msg
, FILE *out
)
633 iterator_t
*peer_iter
, *child_iter
;
634 peer_cfg_t
*peer
, *child
;
636 pop_string(msg
, &(msg
->del_conn
.name
));
637 DBG1(DBG_CFG
, "received stroke: delete connection '%s'", msg
->del_conn
.name
);
639 peer_iter
= charon
->backends
->create_iterator(charon
->backends
);
640 while (peer_iter
->iterate(peer_iter
, (void**)&peer
))
642 /* remove peer config with such a name */
643 if (streq(peer
->get_name(peer
), msg
->del_conn
.name
))
645 peer_iter
->remove(peer_iter
);
649 /* remove any child with such a name */
650 child_iter
= peer
->create_child_cfg_iterator(peer
);
651 while (child_iter
->iterate(child_iter
, (void**)&child
))
653 if (streq(child
->get_name(child
), msg
->del_conn
.name
))
655 child_iter
->remove(child_iter
);
656 child
->destroy(child
);
659 child_iter
->destroy(child_iter
);
661 peer_iter
->destroy(peer_iter
);
663 fprintf(out
, "deleted connection '%s'\n", msg
->del_conn
.name
);
667 * get the child_cfg with the same name as the peer cfg
669 static child_cfg_t
* get_child_from_peer(peer_cfg_t
*peer_cfg
, char *name
)
671 child_cfg_t
*current
, *found
= NULL
;
672 iterator_t
*iterator
;
674 iterator
= peer_cfg
->create_child_cfg_iterator(peer_cfg
);
675 while (iterator
->iterate(iterator
, (void**)¤t
))
677 if (streq(current
->get_name(current
), name
))
680 found
->get_ref(found
);
684 iterator
->destroy(iterator
);
689 * logging to the stroke interface
691 static bool stroke_log(stroke_log_info_t
*info
, signal_t signal
, level_t level
,
692 ike_sa_t
*ike_sa
, char *format
, va_list args
)
694 if (level
<= info
->level
)
696 if (vfprintf(info
->out
, format
, args
) < 0 ||
697 fprintf(info
->out
, "\n") < 0 ||
698 fflush(info
->out
) != 0)
707 * get a peer configuration by its name, or a name of its children
709 static peer_cfg_t
*get_peer_cfg_by_name(char *name
)
712 peer_cfg_t
*current
, *found
= NULL
;
715 i1
= charon
->backends
->create_iterator(charon
->backends
);
716 while (i1
->iterate(i1
, (void**)¤t
))
718 /* compare peer_cfgs name first */
719 if (streq(current
->get_name(current
), name
))
722 found
->get_ref(found
);
725 /* compare all child_cfg names otherwise */
726 i2
= current
->create_child_cfg_iterator(current
);
727 while (i2
->iterate(i2
, (void**)&child
))
729 if (streq(child
->get_name(child
), name
))
732 found
->get_ref(found
);
747 * initiate a connection by name
749 static void stroke_initiate(stroke_msg_t
*msg
, FILE *out
)
751 peer_cfg_t
*peer_cfg
;
752 child_cfg_t
*child_cfg
;
753 stroke_log_info_t info
;
755 pop_string(msg
, &(msg
->initiate
.name
));
756 DBG1(DBG_CFG
, "received stroke: initiate '%s'", msg
->initiate
.name
);
758 peer_cfg
= get_peer_cfg_by_name(msg
->initiate
.name
);
759 if (peer_cfg
== NULL
)
761 fprintf(out
, "no config named '%s'\n", msg
->initiate
.name
);
764 if (peer_cfg
->get_ike_version(peer_cfg
) != 2)
766 DBG1(DBG_CFG
, "ignoring initiation request for IKEv%d config",
767 peer_cfg
->get_ike_version(peer_cfg
));
768 peer_cfg
->destroy(peer_cfg
);
772 child_cfg
= get_child_from_peer(peer_cfg
, msg
->initiate
.name
);
773 if (child_cfg
== NULL
)
775 fprintf(out
, "no child config named '%s'\n", msg
->initiate
.name
);
776 peer_cfg
->destroy(peer_cfg
);
781 info
.level
= msg
->output_verbosity
;
782 charon
->interfaces
->initiate(charon
->interfaces
, peer_cfg
, child_cfg
,
783 (interface_manager_cb_t
)stroke_log
, &info
);
787 * route a policy (install SPD entries)
789 static void stroke_route(stroke_msg_t
*msg
, FILE *out
)
791 peer_cfg_t
*peer_cfg
;
792 child_cfg_t
*child_cfg
;
793 stroke_log_info_t info
;
795 pop_string(msg
, &(msg
->route
.name
));
796 DBG1(DBG_CFG
, "received stroke: route '%s'", msg
->route
.name
);
798 peer_cfg
= get_peer_cfg_by_name(msg
->route
.name
);
799 if (peer_cfg
== NULL
)
801 fprintf(out
, "no config named '%s'\n", msg
->route
.name
);
804 if (peer_cfg
->get_ike_version(peer_cfg
) != 2)
806 peer_cfg
->destroy(peer_cfg
);
810 child_cfg
= get_child_from_peer(peer_cfg
, msg
->route
.name
);
811 if (child_cfg
== NULL
)
813 fprintf(out
, "no child config named '%s'\n", msg
->route
.name
);
814 peer_cfg
->destroy(peer_cfg
);
819 info
.level
= msg
->output_verbosity
;
820 charon
->interfaces
->route(charon
->interfaces
, peer_cfg
, child_cfg
,
821 (interface_manager_cb_t
)stroke_log
, &info
);
822 peer_cfg
->destroy(peer_cfg
);
823 child_cfg
->destroy(child_cfg
);
829 static void stroke_unroute(stroke_msg_t
*msg
, FILE *out
)
833 iterator_t
*iterator
;
834 stroke_log_info_t info
;
836 pop_string(msg
, &(msg
->terminate
.name
));
837 name
= msg
->terminate
.name
;
840 info
.level
= msg
->output_verbosity
;
842 iterator
= charon
->interfaces
->create_ike_sa_iterator(charon
->interfaces
);
843 while (iterator
->iterate(iterator
, (void**)&ike_sa
))
845 child_sa_t
*child_sa
;
846 iterator_t
*children
;
849 children
= ike_sa
->create_child_sa_iterator(ike_sa
);
850 while (children
->iterate(children
, (void**)&child_sa
))
852 if (child_sa
->get_state(child_sa
) == CHILD_ROUTED
&&
853 streq(name
, child_sa
->get_name(child_sa
)))
855 id
= child_sa
->get_reqid(child_sa
);
856 children
->destroy(children
);
857 iterator
->destroy(iterator
);
858 charon
->interfaces
->unroute(charon
->interfaces
, id
,
859 (interface_manager_cb_t
)stroke_log
, &info
);
863 children
->destroy(children
);
865 iterator
->destroy(iterator
);
866 DBG1(DBG_CFG
, "no such SA found");
870 * terminate a connection by name
872 static void stroke_terminate(stroke_msg_t
*msg
, FILE *out
)
874 char *string
, *pos
= NULL
, *name
= NULL
;
879 iterator_t
*iterator
;
880 stroke_log_info_t info
;
882 pop_string(msg
, &(msg
->terminate
.name
));
883 string
= msg
->terminate
.name
;
884 DBG1(DBG_CFG
, "received stroke: terminate '%s'", string
);
886 len
= strlen(string
);
889 DBG1(DBG_CFG
, "error parsing string");
892 switch (string
[len
-1])
896 pos
= strchr(string
, '{');
900 pos
= strchr(string
, '[');
910 /* is a single name */
912 else if (pos
== string
+ len
- 2)
913 { /* is name[] or name{} */
914 string
[len
-2] = '\0';
918 { /* is name[123] or name{23} */
919 string
[len
-1] = '\0';
923 DBG1(DBG_CFG
, "error parsing string");
929 info
.level
= msg
->output_verbosity
;
931 iterator
= charon
->interfaces
->create_ike_sa_iterator(charon
->interfaces
);
932 while (iterator
->iterate(iterator
, (void**)&ike_sa
))
934 child_sa_t
*child_sa
;
935 iterator_t
*children
;
939 children
= ike_sa
->create_child_sa_iterator(ike_sa
);
940 while (children
->iterate(children
, (void**)&child_sa
))
942 if ((name
&& streq(name
, child_sa
->get_name(child_sa
))) ||
943 (id
&& id
== child_sa
->get_reqid(child_sa
)))
945 id
= child_sa
->get_reqid(child_sa
);
946 children
->destroy(children
);
947 iterator
->destroy(iterator
);
949 charon
->interfaces
->terminate_child(charon
->interfaces
, id
,
950 (interface_manager_cb_t
)stroke_log
, &info
);
954 children
->destroy(children
);
956 else if ((name
&& streq(name
, ike_sa
->get_name(ike_sa
))) ||
957 (id
&& id
== ike_sa
->get_unique_id(ike_sa
)))
959 id
= ike_sa
->get_unique_id(ike_sa
);
960 /* unlock manager first */
961 iterator
->destroy(iterator
);
963 charon
->interfaces
->terminate_ike(charon
->interfaces
, id
,
964 (interface_manager_cb_t
)stroke_log
, &info
);
969 iterator
->destroy(iterator
);
970 DBG1(DBG_CFG
, "no such SA found");
974 * Add a ca information record to the cainfo list
976 static void stroke_add_ca(stroke_msg_t
*msg
, FILE *out
)
981 pop_string(msg
, &msg
->add_ca
.name
);
982 pop_string(msg
, &msg
->add_ca
.cacert
);
983 pop_string(msg
, &msg
->add_ca
.crluri
);
984 pop_string(msg
, &msg
->add_ca
.crluri2
);
985 pop_string(msg
, &msg
->add_ca
.ocspuri
);
986 pop_string(msg
, &msg
->add_ca
.ocspuri2
);
988 DBG1(DBG_CFG
, "received stroke: add ca '%s'", msg
->add_ca
.name
);
990 DBG2(DBG_CFG
, "ca %s", msg
->add_ca
.name
);
991 DBG2(DBG_CFG
, " cacert=%s", msg
->add_ca
.cacert
);
992 DBG2(DBG_CFG
, " crluri=%s", msg
->add_ca
.crluri
);
993 DBG2(DBG_CFG
, " crluri2=%s", msg
->add_ca
.crluri2
);
994 DBG2(DBG_CFG
, " ocspuri=%s", msg
->add_ca
.ocspuri
);
995 DBG2(DBG_CFG
, " ocspuri2=%s", msg
->add_ca
.ocspuri2
);
997 if (msg
->add_ca
.cacert
== NULL
)
999 DBG1(DBG_CFG
, "missing cacert parameter\n");
1003 cacert
= load_ca_certificate(msg
->add_ca
.cacert
);
1009 ca_info
= ca_info_create(msg
->add_ca
.name
, cacert
);
1011 if (msg
->add_ca
.crluri
)
1013 chunk_t uri
= { msg
->add_ca
.crluri
, strlen(msg
->add_ca
.crluri
) };
1015 ca_info
->add_crluri(ca_info
, uri
);
1017 if (msg
->add_ca
.crluri2
)
1019 chunk_t uri
= { msg
->add_ca
.crluri2
, strlen(msg
->add_ca
.crluri2
) };
1021 ca_info
->add_crluri(ca_info
, uri
);
1023 if (msg
->add_ca
.ocspuri
)
1025 chunk_t uri
= { msg
->add_ca
.ocspuri
, strlen(msg
->add_ca
.ocspuri
) };
1027 ca_info
->add_ocspuri(ca_info
, uri
);
1029 if (msg
->add_ca
.ocspuri2
)
1031 chunk_t uri
= { msg
->add_ca
.ocspuri2
, strlen(msg
->add_ca
.ocspuri2
) };
1033 ca_info
->add_ocspuri(ca_info
, uri
);
1035 charon
->credentials
->add_ca_info(charon
->credentials
, ca_info
);
1036 DBG1(DBG_CFG
, "added ca '%s'", msg
->add_ca
.name
);
1041 * Delete a ca information record from the cainfo list
1043 static void stroke_del_ca(stroke_msg_t
*msg
, FILE *out
)
1047 pop_string(msg
, &(msg
->del_ca
.name
));
1048 DBG1(DBG_CFG
, "received stroke: delete ca '%s'", msg
->del_ca
.name
);
1050 status
= charon
->credentials
->release_ca_info(charon
->credentials
,
1053 if (status
== SUCCESS
)
1055 fprintf(out
, "deleted ca '%s'\n", msg
->del_ca
.name
);
1059 fprintf(out
, "no ca named '%s'\n", msg
->del_ca
.name
);
1064 * log an IKE_SA to out
1066 static void log_ike_sa(FILE *out
, ike_sa_t
*ike_sa
, bool all
)
1068 peer_cfg_t
*cfg
= ike_sa
->get_peer_cfg(ike_sa
);
1069 ike_sa_id_t
*id
= ike_sa
->get_id(ike_sa
);
1070 u_int32_t next
, now
= time(NULL
);
1072 fprintf(out
, "%12s[%d]: %N, %H[%D]...%H[%D]\n",
1073 ike_sa
->get_name(ike_sa
), ike_sa
->get_unique_id(ike_sa
),
1074 ike_sa_state_names
, ike_sa
->get_state(ike_sa
),
1075 ike_sa
->get_my_host(ike_sa
), ike_sa
->get_my_id(ike_sa
),
1076 ike_sa
->get_other_host(ike_sa
), ike_sa
->get_other_id(ike_sa
));
1080 fprintf(out
, "%12s[%d]: IKE SPIs: 0x%0llx_i%s 0x%0llx_r%s, ",
1081 ike_sa
->get_name(ike_sa
), ike_sa
->get_unique_id(ike_sa
),
1082 id
->get_initiator_spi(id
), id
->is_initiator(id
) ?
"*" : "",
1083 id
->get_responder_spi(id
), id
->is_initiator(id
) ?
"" : "");
1085 ike_sa
->get_stats(ike_sa
, &next
);
1088 fprintf(out
, "%s in %V\n", cfg
->use_reauth(cfg
) ?
1089 "reauthentication" : "rekeying", &now
, &next
);
1093 fprintf(out
, "rekeying disabled\n");
1099 * log an CHILD_SA to out
1101 static void log_child_sa(FILE *out
, child_sa_t
*child_sa
, bool all
)
1103 u_int32_t rekey
, now
= time(NULL
);
1104 u_int32_t use_in
, use_out
, use_fwd
;
1105 encryption_algorithm_t encr_alg
;
1106 integrity_algorithm_t int_alg
;
1107 size_t encr_len
, int_len
;
1110 child_sa
->get_stats(child_sa
, &mode
, &encr_alg
, &encr_len
,
1111 &int_alg
, &int_len
, &rekey
, &use_in
, &use_out
,
1114 fprintf(out
, "%12s{%d}: %N, %N",
1115 child_sa
->get_name(child_sa
), child_sa
->get_reqid(child_sa
),
1116 child_sa_state_names
, child_sa
->get_state(child_sa
),
1119 if (child_sa
->get_state(child_sa
) == CHILD_INSTALLED
)
1121 fprintf(out
, ", %N SPIs: 0x%0x_i 0x%0x_o",
1122 protocol_id_names
, child_sa
->get_protocol(child_sa
),
1123 htonl(child_sa
->get_spi(child_sa
, TRUE
)),
1124 htonl(child_sa
->get_spi(child_sa
, FALSE
)));
1128 fprintf(out
, "\n%12s{%d}: ", child_sa
->get_name(child_sa
),
1129 child_sa
->get_reqid(child_sa
));
1132 if (child_sa
->get_protocol(child_sa
) == PROTO_ESP
)
1134 fprintf(out
, "%N", encryption_algorithm_names
, encr_alg
);
1138 fprintf(out
, "-%d", encr_len
);
1143 fprintf(out
, "%N", integrity_algorithm_names
, int_alg
);
1146 fprintf(out
, "-%d", int_len
);
1148 fprintf(out
, ", rekeying ");
1152 fprintf(out
, "in %V", &now
, &rekey
);
1156 fprintf(out
, "disabled");
1159 fprintf(out
, ", last use: ");
1160 use_in
= max(use_in
, use_fwd
);
1163 fprintf(out
, "%ds_i ", now
- use_in
);
1167 fprintf(out
, "no_i ");
1171 fprintf(out
, "%ds_o ", now
- use_out
);
1175 fprintf(out
, "no_o ");
1180 fprintf(out
, "\n%12s{%d}: %#R=== %#R\n",
1181 child_sa
->get_name(child_sa
), child_sa
->get_reqid(child_sa
),
1182 child_sa
->get_traffic_selectors(child_sa
, TRUE
),
1183 child_sa
->get_traffic_selectors(child_sa
, FALSE
));
1187 * show status of daemon
1189 static void stroke_status(stroke_msg_t
*msg
, FILE *out
, bool all
)
1191 iterator_t
*iterator
, *children
;
1193 peer_cfg_t
*peer_cfg
;
1195 child_cfg_t
*child_cfg
;
1199 if (msg
->status
.name
)
1201 pop_string(msg
, &(msg
->status
.name
));
1202 name
= msg
->status
.name
;
1207 leak_detective_status(out
);
1209 fprintf(out
, "Performance:\n");
1210 fprintf(out
, " worker threads: %d idle of %d,",
1211 charon
->processor
->get_idle_threads(charon
->processor
),
1212 charon
->processor
->get_total_threads(charon
->processor
));
1213 fprintf(out
, " job queue load: %d,",
1214 charon
->processor
->get_job_load(charon
->processor
));
1215 fprintf(out
, " scheduled events: %d\n",
1216 charon
->scheduler
->get_job_load(charon
->scheduler
));
1217 iterator
= charon
->kernel_interface
->create_address_iterator(
1218 charon
->kernel_interface
);
1219 fprintf(out
, "Listening IP addresses:\n");
1220 while (iterator
->iterate(iterator
, (void**)&host
))
1222 fprintf(out
, " %H\n", host
);
1224 iterator
->destroy(iterator
);
1226 fprintf(out
, "Connections:\n");
1227 iterator
= charon
->backends
->create_iterator(charon
->backends
);
1228 while (iterator
->iterate(iterator
, (void**)&peer_cfg
))
1230 if (peer_cfg
->get_ike_version(peer_cfg
) != 2 ||
1231 (name
&& !streq(name
, peer_cfg
->get_name(peer_cfg
))))
1236 ike_cfg
= peer_cfg
->get_ike_cfg(peer_cfg
);
1237 fprintf(out
, "%12s: %H[%D]...%H[%D]\n", peer_cfg
->get_name(peer_cfg
),
1238 ike_cfg
->get_my_host(ike_cfg
), peer_cfg
->get_my_id(peer_cfg
),
1239 ike_cfg
->get_other_host(ike_cfg
), peer_cfg
->get_other_id(peer_cfg
));
1241 identification_t
*my_ca
= peer_cfg
->get_my_ca(peer_cfg
);
1242 identification_t
*other_ca
= peer_cfg
->get_other_ca(peer_cfg
);
1244 if (my_ca
->get_type(my_ca
) != ID_ANY
1245 || other_ca
->get_type(other_ca
) != ID_ANY
)
1247 fprintf(out
, "%12s: CAs: '%D'...'%D'\n", peer_cfg
->get_name(peer_cfg
),
1251 children
= peer_cfg
->create_child_cfg_iterator(peer_cfg
);
1252 while (children
->iterate(children
, (void**)&child_cfg
))
1254 linked_list_t
*my_ts
, *other_ts
;
1255 my_ts
= child_cfg
->get_traffic_selectors(child_cfg
, TRUE
, NULL
, NULL
);
1256 other_ts
= child_cfg
->get_traffic_selectors(child_cfg
, FALSE
, NULL
, NULL
);
1257 fprintf(out
, "%12s: %#R=== %#R\n", child_cfg
->get_name(child_cfg
),
1259 my_ts
->destroy_offset(my_ts
, offsetof(traffic_selector_t
, destroy
));
1260 other_ts
->destroy_offset(other_ts
, offsetof(traffic_selector_t
, destroy
));
1262 children
->destroy(children
);
1264 iterator
->destroy(iterator
);
1267 iterator
= charon
->ike_sa_manager
->create_iterator(charon
->ike_sa_manager
);
1268 if (all
&& iterator
->get_count(iterator
) > 0)
1270 fprintf(out
, "Security Associations:\n");
1272 while (iterator
->iterate(iterator
, (void**)&ike_sa
))
1274 bool ike_printed
= FALSE
;
1275 child_sa_t
*child_sa
;
1276 iterator_t
*children
= ike_sa
->create_child_sa_iterator(ike_sa
);
1278 if (name
== NULL
|| streq(name
, ike_sa
->get_name(ike_sa
)))
1280 log_ike_sa(out
, ike_sa
, all
);
1284 while (children
->iterate(children
, (void**)&child_sa
))
1286 if (name
== NULL
|| streq(name
, child_sa
->get_name(child_sa
)))
1290 log_ike_sa(out
, ike_sa
, all
);
1293 log_child_sa(out
, child_sa
, all
);
1296 children
->destroy(children
);
1298 iterator
->destroy(iterator
);
1302 * list all authority certificates matching a specified flag
1304 static void list_auth_certificates(u_int flag
, const char *label
,
1305 bool utc
, FILE *out
)
1310 iterator_t
*iterator
= charon
->credentials
->create_auth_cert_iterator(charon
->credentials
);
1312 while (iterator
->iterate(iterator
, (void**)&cert
))
1314 if (cert
->has_authority_flag(cert
, flag
))
1319 fprintf(out
, "List of X.509 %s Certificates:\n", label
);
1323 cert
->list(cert
, out
, utc
);
1327 iterator
->destroy(iterator
);
1331 * list various information
1333 static void stroke_list(stroke_msg_t
*msg
, FILE *out
)
1335 iterator_t
*iterator
;
1337 if (msg
->list
.flags
& LIST_CERTS
)
1341 iterator
= charon
->credentials
->create_cert_iterator(charon
->credentials
);
1342 if (iterator
->get_count(iterator
))
1345 fprintf(out
, "List of X.509 End Entity Certificates:\n");
1348 while (iterator
->iterate(iterator
, (void**)&cert
))
1350 cert
->list(cert
, out
, msg
->list
.utc
);
1351 if (charon
->credentials
->has_rsa_private_key(
1352 charon
->credentials
, cert
->get_public_key(cert
)))
1354 fprintf(out
, ", has private key");
1359 iterator
->destroy(iterator
);
1361 if (msg
->list
.flags
& LIST_CACERTS
)
1363 list_auth_certificates(AUTH_CA
, "CA", msg
->list
.utc
, out
);
1365 if (msg
->list
.flags
& LIST_OCSPCERTS
)
1367 list_auth_certificates(AUTH_OCSP
, "OCSP", msg
->list
.utc
, out
);
1369 if (msg
->list
.flags
& LIST_AACERTS
)
1371 list_auth_certificates(AUTH_AA
, "AA", msg
->list
.utc
, out
);
1373 if (msg
->list
.flags
& LIST_CAINFOS
)
1378 iterator
= charon
->credentials
->create_cainfo_iterator(charon
->credentials
);
1379 while (iterator
->iterate(iterator
, (void**)&ca_info
))
1381 if (ca_info
->is_ca(ca_info
))
1386 fprintf(out
, "List of X.509 CA Information Records:\n");
1390 ca_info
->list(ca_info
, out
, msg
->list
.utc
);
1393 iterator
->destroy(iterator
);
1395 if (msg
->list
.flags
& LIST_CRLS
)
1400 iterator
= charon
->credentials
->create_cainfo_iterator(charon
->credentials
);
1401 while (iterator
->iterate(iterator
, (void **)&ca_info
))
1403 if (ca_info
->is_ca(ca_info
) && ca_info
->has_crl(ca_info
))
1408 fprintf(out
, "List of X.509 CRLs:\n");
1412 ca_info
->list_crl(ca_info
, out
, msg
->list
.utc
);
1415 iterator
->destroy(iterator
);
1417 if (msg
->list
.flags
& LIST_OCSP
)
1422 iterator
= charon
->credentials
->create_cainfo_iterator(charon
->credentials
);
1423 while (iterator
->iterate(iterator
, (void **)&ca_info
))
1425 if (ca_info
->is_ca(ca_info
) && ca_info
->has_certinfos(ca_info
))
1430 fprintf(out
, "List of OCSP responses:\n");
1434 ca_info
->list_certinfos(ca_info
, out
, msg
->list
.utc
);
1437 iterator
->destroy(iterator
);
1442 * reread various information
1444 static void stroke_reread(stroke_msg_t
*msg
, FILE *out
)
1446 if (msg
->reread
.flags
& REREAD_CACERTS
)
1448 charon
->credentials
->load_ca_certificates(charon
->credentials
);
1450 if (msg
->reread
.flags
& REREAD_OCSPCERTS
)
1452 charon
->credentials
->load_ocsp_certificates(charon
->credentials
);
1454 if (msg
->reread
.flags
& REREAD_CRLS
)
1456 charon
->credentials
->load_crls(charon
->credentials
);
1461 * purge various information
1463 static void stroke_purge(stroke_msg_t
*msg
, FILE *out
)
1465 if (msg
->purge
.flags
& PURGE_OCSP
)
1467 iterator_t
*iterator
= charon
->credentials
->create_cainfo_iterator(charon
->credentials
);
1470 while (iterator
->iterate(iterator
, (void**)&ca_info
))
1472 if (ca_info
->is_ca(ca_info
))
1474 ca_info
->purge_ocsp(ca_info
);
1477 iterator
->destroy(iterator
);
1481 signal_t
get_signal_from_logtype(char *type
)
1483 if (strcasecmp(type
, "any") == 0) return SIG_ANY
;
1484 else if (strcasecmp(type
, "mgr") == 0) return DBG_MGR
;
1485 else if (strcasecmp(type
, "ike") == 0) return DBG_IKE
;
1486 else if (strcasecmp(type
, "chd") == 0) return DBG_CHD
;
1487 else if (strcasecmp(type
, "job") == 0) return DBG_JOB
;
1488 else if (strcasecmp(type
, "cfg") == 0) return DBG_CFG
;
1489 else if (strcasecmp(type
, "knl") == 0) return DBG_KNL
;
1490 else if (strcasecmp(type
, "net") == 0) return DBG_NET
;
1491 else if (strcasecmp(type
, "enc") == 0) return DBG_ENC
;
1492 else if (strcasecmp(type
, "lib") == 0) return DBG_LIB
;
1497 * set the verbosity debug output
1499 static void stroke_loglevel(stroke_msg_t
*msg
, FILE *out
)
1503 pop_string(msg
, &(msg
->loglevel
.type
));
1504 DBG1(DBG_CFG
, "received stroke: loglevel %d for %s",
1505 msg
->loglevel
.level
, msg
->loglevel
.type
);
1507 signal
= get_signal_from_logtype(msg
->loglevel
.type
);
1510 fprintf(out
, "invalid type (%s)!\n", msg
->loglevel
.type
);
1514 charon
->outlog
->set_level(charon
->outlog
, signal
, msg
->loglevel
.level
);
1515 charon
->syslog
->set_level(charon
->syslog
, signal
, msg
->loglevel
.level
);
1519 * process a stroke request from the socket pointed by "fd"
1521 static job_requeue_t
stroke_process(int *fdp
)
1524 u_int16_t msg_length
;
1527 int strokefd
= *fdp
;
1529 /* peek the length */
1530 bytes_read
= recv(strokefd
, &msg_length
, sizeof(msg_length
), MSG_PEEK
);
1531 if (bytes_read
!= sizeof(msg_length
))
1533 DBG1(DBG_CFG
, "reading length of stroke message failed: %s",
1536 return JOB_REQUEUE_NONE
;
1540 msg
= malloc(msg_length
);
1541 bytes_read
= recv(strokefd
, msg
, msg_length
, 0);
1542 if (bytes_read
!= msg_length
)
1544 DBG1(DBG_CFG
, "reading stroke message failed: %s", strerror(errno
));
1546 return JOB_REQUEUE_NONE
;
1549 out
= fdopen(strokefd
, "w");
1552 DBG1(DBG_CFG
, "opening stroke output channel failed: %s", strerror(errno
));
1555 return JOB_REQUEUE_NONE
;
1558 DBG3(DBG_CFG
, "stroke message %b", (void*)msg
, msg_length
);
1560 /* the stroke_* functions are blocking, as they listen on the bus. Add
1561 * cancellation handlers. */
1562 pthread_cleanup_push((void*)fclose
, out
);
1563 pthread_cleanup_push(free
, msg
);
1568 stroke_initiate(msg
, out
);
1571 stroke_route(msg
, out
);
1574 stroke_unroute(msg
, out
);
1577 stroke_terminate(msg
, out
);
1580 stroke_status(msg
, out
, FALSE
);
1582 case STR_STATUS_ALL
:
1583 stroke_status(msg
, out
, TRUE
);
1586 stroke_add_conn(msg
, out
);
1589 stroke_del_conn(msg
, out
);
1592 stroke_add_ca(msg
, out
);
1595 stroke_del_ca(msg
, out
);
1598 stroke_loglevel(msg
, out
);
1601 stroke_list(msg
, out
);
1604 stroke_reread(msg
, out
);
1607 stroke_purge(msg
, out
);
1610 DBG1(DBG_CFG
, "received unknown stroke");
1612 /* remove and execute cancellation handlers */
1613 pthread_cleanup_pop(1);
1614 pthread_cleanup_pop(1);
1616 return JOB_REQUEUE_NONE
;
1621 * Implementation of private_stroke_interface_t.stroke_receive.
1623 static job_requeue_t
stroke_receive(private_stroke_interface_t
*this)
1625 struct sockaddr_un strokeaddr
;
1626 int strokeaddrlen
= sizeof(strokeaddr
);
1629 callback_job_t
*job
;
1631 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, &oldstate
);
1632 strokefd
= accept(this->socket
, (struct sockaddr
*)&strokeaddr
, &strokeaddrlen
);
1633 pthread_setcancelstate(oldstate
, NULL
);
1637 DBG1(DBG_CFG
, "accepting stroke connection failed: %s", strerror(errno
));
1638 return JOB_REQUEUE_FAIR
;
1641 fdp
= malloc_thing(int);
1643 job
= callback_job_create((callback_job_cb_t
)stroke_process
, fdp
, free
, this->job
);
1644 charon
->processor
->queue_job(charon
->processor
, (job_t
*)job
);
1646 return JOB_REQUEUE_FAIR
;
1650 * Implementation of interface_t.destroy.
1652 static void destroy(private_stroke_interface_t
*this)
1654 this->job
->cancel(this->job
);
1656 unlink(socket_addr
.sun_path
);
1660 * Described in header-file
1662 interface_t
*interface_create()
1664 private_stroke_interface_t
*this = malloc_thing(private_stroke_interface_t
);
1667 /* public functions */
1668 this->public.interface
.destroy
= (void (*)(interface_t
*))destroy
;
1670 /* set up unix socket */
1671 this->socket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
1672 if (this->socket
== -1)
1674 DBG1(DBG_CFG
, "could not create stroke socket");
1679 old
= umask(~S_IRWXU
);
1680 if (bind(this->socket
, (struct sockaddr
*)&socket_addr
, sizeof(socket_addr
)) < 0)
1682 DBG1(DBG_CFG
, "could not bind stroke socket: %s", strerror(errno
));
1683 close(this->socket
);
1689 if (listen(this->socket
, 0) < 0)
1691 DBG1(DBG_CFG
, "could not listen on stroke socket: %s", strerror(errno
));
1692 close(this->socket
);
1693 unlink(socket_addr
.sun_path
);
1698 this->job
= callback_job_create((callback_job_cb_t
)stroke_receive
,
1700 charon
->processor
->queue_job(charon
->processor
, (job_t
*)this->job
);
1702 return &this->public.interface
;