4 * @brief Implementation of stroke_t.
9 * Copyright (C) 2006 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/crl.h>
42 #include <queues/jobs/initiate_job.h>
43 #include <queues/jobs/route_job.h>
44 #include <utils/leak_detective.h>
50 struct sockaddr_un socket_addr
= { AF_UNIX
, STROKE_SOCKET
};
53 typedef struct private_stroke_t private_stroke_t
;
56 * Private data of an stroke_t object.
58 struct private_stroke_t
{
61 * Public part of stroke_t object.
66 * Output stream (stroke console)
71 * Unix socket to listen for strokes
76 * Thread which reads from the Socket
78 pthread_t assigned_thread
;
82 * Helper function which corrects the string pointers
83 * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
84 * contains RELATIVE addresses (relative to the beginning of the
85 * stroke_msg). They must be corrected if they reach our address
88 static void pop_string(stroke_msg_t
*msg
, char **string
)
93 /* check for sanity of string pointer and string */
94 if (string
< (char**)msg
95 || string
> (char**)msg
+ sizeof(stroke_msg_t
)
96 || (unsigned long)*string
< (unsigned long)((char*)msg
->buffer
- (char*)msg
)
97 || (unsigned long)*string
> msg
->length
)
99 *string
= "(invalid pointer in stroke msg)";
103 *string
= (char*)msg
+ (unsigned long)*string
;
108 * Load end entitity certificate
110 static x509_t
* load_end_certificate(const char *filename
, identification_t
**idp
)
115 if (*filename
== '/')
117 /* absolute path name */
118 snprintf(path
, sizeof(path
), "%s", filename
);
122 /* relative path name */
123 snprintf(path
, sizeof(path
), "%s/%s", CERTIFICATE_DIR
, filename
);
126 cert
= x509_create_from_file(path
, "end entity certificate");
130 identification_t
*id
= *idp
;
131 identification_t
*subject
= cert
->get_subject(cert
);
133 err_t ugh
= cert
->is_valid(cert
, NULL
);
137 DBG1(DBG_CFG
, "warning: certificate %s", ugh
);
139 if (!id
->equals(id
, subject
) && !cert
->equals_subjectAltName(cert
, id
))
143 *idp
= id
->clone(id
);
145 return charon
->credentials
->add_end_certificate(charon
->credentials
, cert
);
151 * Add a connection to the configuration list
153 static void stroke_add_conn(private_stroke_t
*this, stroke_msg_t
*msg
)
155 connection_t
*connection
;
157 identification_t
*my_id
, *other_id
;
158 identification_t
*my_ca
= NULL
;
159 identification_t
*other_ca
= NULL
;
160 bool my_ca_same
= FALSE
;
161 bool other_ca_same
=FALSE
;
162 host_t
*my_host
, *other_host
, *my_subnet
, *other_subnet
;
163 proposal_t
*proposal
;
164 traffic_selector_t
*my_ts
, *other_ts
;
166 pop_string(msg
, &msg
->add_conn
.name
);
167 pop_string(msg
, &msg
->add_conn
.me
.address
);
168 pop_string(msg
, &msg
->add_conn
.other
.address
);
169 pop_string(msg
, &msg
->add_conn
.me
.subnet
);
170 pop_string(msg
, &msg
->add_conn
.other
.subnet
);
171 pop_string(msg
, &msg
->add_conn
.me
.id
);
172 pop_string(msg
, &msg
->add_conn
.other
.id
);
173 pop_string(msg
, &msg
->add_conn
.me
.cert
);
174 pop_string(msg
, &msg
->add_conn
.other
.cert
);
175 pop_string(msg
, &msg
->add_conn
.me
.ca
);
176 pop_string(msg
, &msg
->add_conn
.other
.ca
);
177 pop_string(msg
, &msg
->add_conn
.me
.updown
);
178 pop_string(msg
, &msg
->add_conn
.other
.updown
);
179 pop_string(msg
, &msg
->add_conn
.algorithms
.ike
);
180 pop_string(msg
, &msg
->add_conn
.algorithms
.esp
);
182 DBG1(DBG_CFG
, "received stroke: add connection '%s'", msg
->add_conn
.name
);
184 DBG2(DBG_CFG
, "conn %s", msg
->add_conn
.name
);
185 DBG2(DBG_CFG
, " right=%s", msg
->add_conn
.me
.address
);
186 DBG2(DBG_CFG
, " left=%s", msg
->add_conn
.other
.address
);
187 DBG2(DBG_CFG
, " rightsubnet=%s", msg
->add_conn
.me
.subnet
);
188 DBG2(DBG_CFG
, " leftsubnet=%s", msg
->add_conn
.other
.subnet
);
189 DBG2(DBG_CFG
, " rightid=%s", msg
->add_conn
.me
.id
);
190 DBG2(DBG_CFG
, " leftid=%s", msg
->add_conn
.other
.id
);
191 DBG2(DBG_CFG
, " rightcert=%s", msg
->add_conn
.me
.cert
);
192 DBG2(DBG_CFG
, " leftcert=%s", msg
->add_conn
.other
.cert
);
193 DBG2(DBG_CFG
, " rightca=%s", msg
->add_conn
.me
.ca
);
194 DBG2(DBG_CFG
, " leftca=%s", msg
->add_conn
.other
.ca
);
195 DBG2(DBG_CFG
, " ike=%s", msg
->add_conn
.algorithms
.ike
);
196 DBG2(DBG_CFG
, " esp=%s", msg
->add_conn
.algorithms
.esp
);
198 my_host
= msg
->add_conn
.me
.address?
199 host_create_from_string(msg
->add_conn
.me
.address
, IKE_PORT
) : NULL
;
202 DBG1(DBG_CFG
, "invalid host: %s\n", msg
->add_conn
.me
.address
);
206 other_host
= msg
->add_conn
.other
.address ?
207 host_create_from_string(msg
->add_conn
.other
.address
, IKE_PORT
) : NULL
;
208 if (other_host
== NULL
)
210 DBG1(DBG_CFG
, "invalid host: %s\n", msg
->add_conn
.other
.address
);
211 my_host
->destroy(my_host
);
215 if (charon
->socket
->is_local_address(charon
->socket
, other_host
, NULL
))
217 stroke_end_t tmp_end
;
220 DBG2(DBG_CFG
, "left is other host, swapping ends\n");
223 my_host
= other_host
;
224 other_host
= tmp_host
;
226 tmp_end
= msg
->add_conn
.me
;
227 msg
->add_conn
.me
= msg
->add_conn
.other
;
228 msg
->add_conn
.other
= tmp_end
;
230 else if (!charon
->socket
->is_local_address(charon
->socket
, my_host
, NULL
))
232 DBG1(DBG_CFG
, "left nor right host is our side, aborting\n");
236 my_id
= identification_create_from_string(msg
->add_conn
.me
.id ?
237 msg
->add_conn
.me
.id
: msg
->add_conn
.me
.address
);
240 DBG1(DBG_CFG
, "invalid ID: %s\n", msg
->add_conn
.me
.id
);
244 other_id
= identification_create_from_string(msg
->add_conn
.other
.id ?
245 msg
->add_conn
.other
.id
: msg
->add_conn
.other
.address
);
246 if (other_id
== NULL
)
248 DBG1(DBG_CFG
, "invalid ID: %s\n", msg
->add_conn
.other
.id
);
249 my_id
->destroy(my_id
);
253 my_subnet
= host_create_from_string(msg
->add_conn
.me
.subnet ?
254 msg
->add_conn
.me
.subnet
: msg
->add_conn
.me
.address
, IKE_PORT
);
255 if (my_subnet
== NULL
)
257 DBG1(DBG_CFG
, "invalid subnet: %s\n", msg
->add_conn
.me
.subnet
);
261 other_subnet
= host_create_from_string(msg
->add_conn
.other
.subnet ?
262 msg
->add_conn
.other
.subnet
: msg
->add_conn
.other
.address
, IKE_PORT
);
263 if (other_subnet
== NULL
)
265 DBG1(DBG_CFG
, "invalid subnet: %s\n", msg
->add_conn
.me
.subnet
);
266 my_subnet
->destroy(my_subnet
);
270 my_ts
= traffic_selector_create_from_subnet(my_subnet
,
271 msg
->add_conn
.me
.subnet ? msg
->add_conn
.me
.subnet_mask
: 0,
272 msg
->add_conn
.me
.protocol
, msg
->add_conn
.me
.port
);
273 my_subnet
->destroy(my_subnet
);
275 other_ts
= traffic_selector_create_from_subnet(other_subnet
,
276 msg
->add_conn
.other
.subnet ? msg
->add_conn
.other
.subnet_mask
: 0,
277 msg
->add_conn
.other
.protocol
, msg
->add_conn
.other
.port
);
278 other_subnet
->destroy(other_subnet
);
280 if (msg
->add_conn
.me
.ca
)
282 if (streq(msg
->add_conn
.me
.ca
, "%same"))
288 my_ca
= identification_create_from_string(msg
->add_conn
.me
.ca
);
291 if (msg
->add_conn
.other
.ca
)
293 if (streq(msg
->add_conn
.other
.ca
, "%same"))
295 other_ca_same
= TRUE
;
299 other_ca
= identification_create_from_string(msg
->add_conn
.other
.ca
);
302 if (msg
->add_conn
.me
.cert
)
304 x509_t
*cert
= load_end_certificate(msg
->add_conn
.me
.cert
, &my_id
);
306 if (my_ca
== NULL
&& !my_ca_same
&& cert
)
308 identification_t
*issuer
= cert
->get_issuer(cert
);
310 my_ca
= issuer
->clone(issuer
);
313 if (msg
->add_conn
.other
.cert
)
315 x509_t
*cert
= load_end_certificate(msg
->add_conn
.other
.cert
, &other_id
);
317 if (other_ca
== NULL
&& !other_ca_same
&& cert
)
319 identification_t
*issuer
= cert
->get_issuer(cert
);
321 other_ca
= issuer
->clone(issuer
);
324 if (other_ca_same
&& my_ca
)
326 other_ca
= my_ca
->clone(my_ca
);
328 else if (my_ca_same
&& other_ca
)
330 my_ca
= other_ca
->clone(other_ca
);
334 my_ca
= identification_create_from_string("%any");
336 if (other_ca
== NULL
)
338 other_ca
= identification_create_from_string("%any");
340 DBG2(DBG_CFG
, " my ca: '%D'", my_ca
);
341 DBG2(DBG_CFG
, " other ca:'%D'", other_ca
);
342 DBG2(DBG_CFG
, " updown: '%s'", msg
->add_conn
.me
.updown
);
344 connection
= connection_create(msg
->add_conn
.name
,
346 msg
->add_conn
.me
.sendcert
,
347 msg
->add_conn
.other
.sendcert
,
349 msg
->add_conn
.dpd
.delay
,
350 msg
->add_conn
.rekey
.tries
,
351 msg
->add_conn
.rekey
.ike_lifetime
,
352 msg
->add_conn
.rekey
.ike_lifetime
- msg
->add_conn
.rekey
.margin
,
353 msg
->add_conn
.rekey
.margin
* msg
->add_conn
.rekey
.fuzz
/ 100);
355 if (msg
->add_conn
.algorithms
.ike
)
357 char *proposal_string
;
358 char *strict
= msg
->add_conn
.algorithms
.ike
+ strlen(msg
->add_conn
.algorithms
.ike
) - 1;
365 while ((proposal_string
= strsep(&msg
->add_conn
.algorithms
.ike
, ",")))
367 proposal
= proposal_create_from_string(PROTO_IKE
, proposal_string
);
368 if (proposal
== NULL
)
370 DBG1(DBG_CFG
, "invalid IKE proposal string: %s", proposal_string
);
371 my_id
->destroy(my_id
);
372 other_id
->destroy(other_id
);
373 my_ts
->destroy(my_ts
);
374 other_ts
->destroy(other_ts
);
375 my_ca
->destroy(my_ca
);
376 other_ca
->destroy(other_ca
);
377 connection
->destroy(connection
);
380 connection
->add_proposal(connection
, proposal
);
384 proposal
= proposal_create_default(PROTO_IKE
);
385 connection
->add_proposal(connection
, proposal
);
390 proposal
= proposal_create_default(PROTO_IKE
);
391 connection
->add_proposal(connection
, proposal
);
394 policy
= policy_create(msg
->add_conn
.name
, my_id
, other_id
,
395 msg
->add_conn
.auth_method
,
396 msg
->add_conn
.rekey
.ipsec_lifetime
,
397 msg
->add_conn
.rekey
.ipsec_lifetime
- msg
->add_conn
.rekey
.margin
,
398 msg
->add_conn
.rekey
.margin
* msg
->add_conn
.rekey
.fuzz
/ 100,
399 msg
->add_conn
.me
.updown
, msg
->add_conn
.me
.hostaccess
,
400 msg
->add_conn
.dpd
.action
);
401 policy
->add_my_traffic_selector(policy
, my_ts
);
402 policy
->add_other_traffic_selector(policy
, other_ts
);
403 policy
->add_authorities(policy
, my_ca
, other_ca
);
405 if (msg
->add_conn
.algorithms
.esp
)
407 char *proposal_string
;
408 char *strict
= msg
->add_conn
.algorithms
.esp
+ strlen(msg
->add_conn
.algorithms
.esp
) - 1;
415 while ((proposal_string
= strsep(&msg
->add_conn
.algorithms
.esp
, ",")))
417 proposal
= proposal_create_from_string(PROTO_ESP
, proposal_string
);
418 if (proposal
== NULL
)
420 DBG1(DBG_CFG
, "invalid ESP proposal string: %s", proposal_string
);
421 policy
->destroy(policy
);
422 connection
->destroy(connection
);
425 policy
->add_proposal(policy
, proposal
);
429 proposal
= proposal_create_default(PROTO_ESP
);
430 policy
->add_proposal(policy
, proposal
);
435 proposal
= proposal_create_default(PROTO_ESP
);
436 policy
->add_proposal(policy
, proposal
);
439 /* add to global connection list */
440 charon
->connections
->add_connection(charon
->connections
, connection
);
441 DBG1(DBG_CFG
, "added connection '%s': %H[%D]...%H[%D]",
442 msg
->add_conn
.name
, my_host
, my_id
, other_host
, other_id
);
443 /* add to global policy list */
444 charon
->policies
->add_policy(charon
->policies
, policy
);
448 /* mopping up after parsing errors */
451 my_id
->destroy(my_id
);
452 other_id
->destroy(other_id
);
455 my_host
->destroy(my_host
);
456 other_host
->destroy(other_host
);
460 * Delete a connection from the list
462 static void stroke_del_conn(private_stroke_t
*this, stroke_msg_t
*msg
)
466 pop_string(msg
, &(msg
->del_conn
.name
));
467 DBG1(DBG_CFG
, "received stroke: delete '%s'", msg
->del_conn
.name
);
469 status
= charon
->connections
->delete_connection(charon
->connections
,
471 charon
->policies
->delete_policy(charon
->policies
, msg
->del_conn
.name
);
472 if (status
== SUCCESS
)
474 fprintf(this->out
, "deleted connection '%s'\n", msg
->del_conn
.name
);
478 fprintf(this->out
, "no connection named '%s'\n", msg
->del_conn
.name
);
483 * initiate a connection by name
485 static void stroke_initiate(private_stroke_t
*this, stroke_msg_t
*msg
)
488 connection_t
*connection
;
490 ike_sa_t
*init_ike_sa
= NULL
;
493 pop_string(msg
, &(msg
->initiate
.name
));
494 DBG1(DBG_CFG
, "received stroke: initiate '%s'", msg
->initiate
.name
);
496 connection
= charon
->connections
->get_connection_by_name(charon
->connections
,
498 if (connection
== NULL
)
500 if (msg
->output_verbosity
>= 0)
502 fprintf(this->out
, "no connection named '%s'\n", msg
->initiate
.name
);
506 if (!connection
->is_ikev2(connection
))
508 connection
->destroy(connection
);
512 policy
= charon
->policies
->get_policy_by_name(charon
->policies
,
516 if (msg
->output_verbosity
>= 0)
518 fprintf(this->out
, "no policy named '%s'\n", msg
->initiate
.name
);
520 connection
->destroy(connection
);
524 job
= initiate_job_create(connection
, policy
);
526 if (msg->output_verbosity < 0)
528 TODO: detach immediately if verbosity is SILENT. Local credential store
529 is not threadsave yet, so this would cause crashes!!
530 charon->job_queue->add(charon->job_queue, (job_t*)job);
534 charon
->bus
->set_listen_state(charon
->bus
, TRUE
);
535 charon
->job_queue
->add(charon
->job_queue
, (job_t
*)job
);
544 signal
= charon
->bus
->listen(charon
->bus
, &level
, &thread
, &ike_sa
, &format
, &args
);
546 if ((init_ike_sa
== NULL
|| ike_sa
== init_ike_sa
) &&
547 level
<= msg
->output_verbosity
)
549 if (vfprintf(this->out
, format
, args
) < 0 ||
550 fprintf(this->out
, "\n") < 0 ||
553 charon
->bus
->set_listen_state(charon
->bus
, FALSE
);
560 case CHILD_UP_SUCCESS
:
561 case CHILD_UP_FAILED
:
562 if (ike_sa
== init_ike_sa
)
564 charon
->bus
->set_listen_state(charon
->bus
, FALSE
);
570 if (init_ike_sa
== NULL
)
572 init_ike_sa
= ike_sa
;
582 * route/unroute a policy (install SPD entries)
584 static void stroke_route(private_stroke_t
*this, stroke_msg_t
*msg
, bool route
)
587 connection_t
*connection
;
590 pop_string(msg
, &(msg
->route
.name
));
591 DBG1(DBG_CFG
, "received stroke: %s '%s'",
592 route ?
"route" : "unroute", msg
->route
.name
);
594 /* we wouldn't need a connection, but we only want to route policies
595 * whose connections are keyexchange=ikev2. */
596 connection
= charon
->connections
->get_connection_by_name(charon
->connections
,
598 if (connection
== NULL
)
600 fprintf(this->out
, "no connection named '%s'\n", msg
->route
.name
);
603 if (!connection
->is_ikev2(connection
))
605 connection
->destroy(connection
);
609 policy
= charon
->policies
->get_policy_by_name(charon
->policies
,
613 fprintf(this->out
, "no policy named '%s'\n", msg
->route
.name
);
614 connection
->destroy(connection
);
617 fprintf(this->out
, "%s policy '%s'\n",
618 route ?
"routing" : "unrouting", msg
->route
.name
);
619 job
= route_job_create(connection
, policy
, route
);
620 charon
->job_queue
->add(charon
->job_queue
, (job_t
*)job
);
624 * terminate a connection by name
626 static void stroke_terminate(private_stroke_t
*this, stroke_msg_t
*msg
)
628 pop_string(msg
, &(msg
->terminate
.name
));
629 DBG1(DBG_CFG
, "received stroke: terminate '%s'", msg
->terminate
.name
);
631 charon
->ike_sa_manager
->delete_by_name(charon
->ike_sa_manager
, msg
->terminate
.name
);
635 * show status of daemon
637 static void stroke_statusall(private_stroke_t
*this, stroke_msg_t
*msg
)
639 iterator_t
*iterator
;
642 connection_t
*connection
;
646 leak_detective_status(this->out
);
648 fprintf(this->out
, "Performance:\n");
649 fprintf(this->out
, " worker threads: %d idle of %d,",
650 charon
->thread_pool
->get_idle_threads(charon
->thread_pool
),
651 charon
->thread_pool
->get_pool_size(charon
->thread_pool
));
652 fprintf(this->out
, " job queue load: %d,",
653 charon
->job_queue
->get_count(charon
->job_queue
));
654 fprintf(this->out
, " scheduled events: %d\n",
655 charon
->event_queue
->get_count(charon
->event_queue
));
656 list
= charon
->socket
->create_local_address_list(charon
->socket
);
658 fprintf(this->out
, "Listening on %d IP addresses:\n", list
->get_count(list
));
659 while (list
->remove_first(list
, (void**)&host
) == SUCCESS
)
661 fprintf(this->out
, " %H\n", host
);
666 if (msg
->status
.name
)
668 pop_string(msg
, &(msg
->status
.name
));
671 iterator
= charon
->connections
->create_iterator(charon
->connections
);
672 if (iterator
->get_count(iterator
) > 0)
674 fprintf(this->out
, "Connections:\n");
676 while (iterator
->iterate(iterator
, (void**)&connection
))
678 if (connection
->is_ikev2(connection
) && (msg
->status
.name
== NULL
679 || streq(msg
->status
.name
, connection
->get_name(connection
))))
681 fprintf(this->out
, "%12s: %H...%H\n",
682 connection
->get_name(connection
),
683 connection
->get_my_host(connection
),
684 connection
->get_other_host(connection
));
687 iterator
->destroy(iterator
);
689 iterator
= charon
->policies
->create_iterator(charon
->policies
);
690 if (iterator
->get_count(iterator
) > 0)
692 fprintf(this->out
, "Policies:\n");
694 while (iterator
->iterate(iterator
, (void**)&policy
))
696 if (msg
->status
.name
== NULL
697 || streq(msg
->status
.name
, policy
->get_name(policy
)))
699 fprintf(this->out
, "%12s: '%D'...'%D'\n",
700 policy
->get_name(policy
),
701 policy
->get_my_id(policy
),
702 policy
->get_other_id(policy
));
705 iterator
->destroy(iterator
);
707 iterator
= charon
->ike_sa_manager
->create_iterator(charon
->ike_sa_manager
);
708 if (iterator
->get_count(iterator
) > 0)
710 fprintf(this->out
, "Security Associations:\n");
712 while (iterator
->iterate(iterator
, (void**)&ike_sa
))
714 bool ike_sa_printed
= FALSE
;
715 child_sa_t
*child_sa
;
716 iterator_t
*children
= ike_sa
->create_child_sa_iterator(ike_sa
);
718 while (children
->iterate(children
, (void**)&child_sa
))
721 && (msg
->status
.name
== NULL
722 || streq(msg
->status
.name
, child_sa
->get_name(child_sa
))
723 || streq(msg
->status
.name
, ike_sa
->get_name(ike_sa
))))
725 fprintf(this->out
, "%#K\n", ike_sa
);
726 ike_sa_printed
= TRUE
;
730 fprintf(this->out
, "%#P\n", child_sa
);
733 children
->destroy(children
);
735 iterator
->destroy(iterator
);
739 * show status of daemon
741 static void stroke_status(private_stroke_t
*this, stroke_msg_t
*msg
)
743 iterator_t
*iterator
;
746 if (msg
->status
.name
)
748 pop_string(msg
, &(msg
->status
.name
));
751 iterator
= charon
->ike_sa_manager
->create_iterator(charon
->ike_sa_manager
);
752 while (iterator
->iterate(iterator
, (void**)&ike_sa
))
754 bool ike_sa_printed
= FALSE
;
755 child_sa_t
*child_sa
;
756 iterator_t
*children
= ike_sa
->create_child_sa_iterator(ike_sa
);
758 while (children
->iterate(children
, (void**)&child_sa
))
761 && (msg
->status
.name
== NULL
762 || streq(msg
->status
.name
, child_sa
->get_name(child_sa
))
763 || streq(msg
->status
.name
, ike_sa
->get_name(ike_sa
))))
765 fprintf(this->out
, "%K\n", ike_sa
);
766 ike_sa_printed
= TRUE
;
770 fprintf(this->out
, "%P\n", child_sa
);
773 children
->destroy(children
);
775 iterator
->destroy(iterator
);
779 * list various information
781 static void stroke_list(private_stroke_t
*this, stroke_msg_t
*msg
)
783 iterator_t
*iterator
;
785 if (msg
->list
.flags
& LIST_CERTS
)
789 iterator
= charon
->credentials
->create_cert_iterator(charon
->credentials
);
790 if (iterator
->get_count(iterator
))
792 fprintf(this->out
, "\n");
793 fprintf(this->out
, "List of X.509 End Entity Certificates:\n");
794 fprintf(this->out
, "\n");
796 while (iterator
->iterate(iterator
, (void**)&cert
))
798 fprintf(this->out
, "%#Q", cert
, msg
->list
.utc
);
799 if (charon
->credentials
->has_rsa_private_key(
800 charon
->credentials
, cert
->get_public_key(cert
)))
802 fprintf(this->out
, ", has private key");
804 fprintf(this->out
, "\n");
807 iterator
->destroy(iterator
);
809 if (msg
->list
.flags
& LIST_CACERTS
)
813 iterator
= charon
->credentials
->create_cacert_iterator(charon
->credentials
);
814 if (iterator
->get_count(iterator
))
816 fprintf(this->out
, "\n");
817 fprintf(this->out
, "List of X.509 CA Certificates:\n");
818 fprintf(this->out
, "\n");
820 while (iterator
->iterate(iterator
, (void**)&cert
))
822 fprintf(this->out
, "%#Q\n", cert
, msg
->list
.utc
);
824 iterator
->destroy(iterator
);
826 if (msg
->list
.flags
& LIST_CRLS
)
830 iterator
= charon
->credentials
->create_crl_iterator(charon
->credentials
);
831 if (iterator
->get_count(iterator
))
833 fprintf(this->out
, "\n");
834 fprintf(this->out
, "List of X.509 CRLs:\n");
835 fprintf(this->out
, "\n");
837 while (iterator
->iterate(iterator
, (void**)&crl
))
839 fprintf(this->out
, "%#U\n", crl
, msg
->list
.utc
);
841 iterator
->destroy(iterator
);
846 * reread various information
848 static void stroke_reread(private_stroke_t
*this, stroke_msg_t
*msg
)
850 if (msg
->reread
.flags
& REREAD_CACERTS
)
852 charon
->credentials
->load_ca_certificates(charon
->credentials
);
854 if (msg
->reread
.flags
& REREAD_CRLS
)
856 charon
->credentials
->load_crls(charon
->credentials
);
860 signal_t
get_signal_from_logtype(char *type
)
862 if (strcasecmp(type
, "any") == 0) return SIG_ANY
;
863 else if (strcasecmp(type
, "mgr") == 0) return DBG_MGR
;
864 else if (strcasecmp(type
, "ike") == 0) return DBG_IKE
;
865 else if (strcasecmp(type
, "chd") == 0) return DBG_CHD
;
866 else if (strcasecmp(type
, "job") == 0) return DBG_JOB
;
867 else if (strcasecmp(type
, "cfg") == 0) return DBG_CFG
;
868 else if (strcasecmp(type
, "knl") == 0) return DBG_KNL
;
869 else if (strcasecmp(type
, "net") == 0) return DBG_NET
;
870 else if (strcasecmp(type
, "enc") == 0) return DBG_ENC
;
871 else if (strcasecmp(type
, "lib") == 0) return DBG_LIB
;
876 * set the verbosity debug output
878 static void stroke_loglevel(private_stroke_t
*this, stroke_msg_t
*msg
)
882 pop_string(msg
, &(msg
->loglevel
.type
));
883 DBG1(DBG_CFG
, "received stroke: loglevel %d for %s",
884 msg
->loglevel
.level
, msg
->loglevel
.type
);
886 signal
= get_signal_from_logtype(msg
->loglevel
.type
);
889 fprintf(this->out
, "invalid type (%s)!\n", msg
->loglevel
.type
);
893 charon
->outlog
->set_level(charon
->outlog
, signal
, msg
->loglevel
.level
);
894 charon
->syslog
->set_level(charon
->syslog
, signal
, msg
->loglevel
.level
);
898 * Implementation of private_stroke_t.stroke_receive.
900 static void stroke_receive(private_stroke_t
*this)
903 u_int16_t msg_length
;
904 struct sockaddr_un strokeaddr
;
905 int strokeaddrlen
= sizeof(strokeaddr
);
910 /* ignore sigpipe. writing over the pipe back to the console
911 * only fails if SIGPIPE is ignored. */
912 signal(SIGPIPE
, SIG_IGN
);
914 /* disable cancellation by default */
915 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
919 /* wait for connections, but allow thread to terminate */
920 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, &oldstate
);
921 strokefd
= accept(this->socket
, (struct sockaddr
*)&strokeaddr
, &strokeaddrlen
);
922 pthread_setcancelstate(oldstate
, NULL
);
926 DBG1(DBG_CFG
, "accepting stroke connection failed: %m");
930 /* peek the length */
931 bytes_read
= recv(strokefd
, &msg_length
, sizeof(msg_length
), MSG_PEEK
);
932 if (bytes_read
!= sizeof(msg_length
))
934 DBG1(DBG_CFG
, "reading lenght of stroke message failed");
940 msg
= malloc(msg_length
);
941 bytes_read
= recv(strokefd
, msg
, msg_length
, 0);
942 if (bytes_read
!= msg_length
)
944 DBG1(DBG_CFG
, "reading stroke message failed: %m");
949 this->out
= fdopen(dup(strokefd
), "w");
950 if (this->out
== NULL
)
952 DBG1(DBG_CFG
, "opening stroke output channel failed: %m");
958 DBG3(DBG_CFG
, "stroke message %b", (void*)msg
, msg_length
);
963 stroke_initiate(this, msg
);
966 stroke_route(this, msg
, TRUE
);
969 stroke_route(this, msg
, FALSE
);
972 stroke_terminate(this, msg
);
975 stroke_status(this, msg
);
978 stroke_statusall(this, msg
);
981 stroke_add_conn(this, msg
);
984 stroke_del_conn(this, msg
);
987 stroke_loglevel(this, msg
);
990 stroke_list(this, msg
);
993 stroke_reread(this, msg
);
996 DBG1(DBG_CFG
, "received unknown stroke");
1005 * Implementation of stroke_t.destroy.
1007 static void destroy(private_stroke_t
*this)
1009 pthread_cancel(this->assigned_thread
);
1010 pthread_join(this->assigned_thread
, NULL
);
1012 close(this->socket
);
1013 unlink(socket_addr
.sun_path
);
1018 * Described in header-file
1020 stroke_t
*stroke_create()
1022 private_stroke_t
*this = malloc_thing(private_stroke_t
);
1025 /* public functions */
1026 this->public.destroy
= (void (*)(stroke_t
*))destroy
;
1028 /* set up unix socket */
1029 this->socket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
1030 if (this->socket
== -1)
1032 DBG1(DBG_CFG
, "could not create whack socket");
1037 old
= umask(~S_IRWXU
);
1038 if (bind(this->socket
, (struct sockaddr
*)&socket_addr
, sizeof(socket_addr
)) < 0)
1040 DBG1(DBG_CFG
, "could not bind stroke socket: %m");
1041 close(this->socket
);
1047 if (listen(this->socket
, 0) < 0)
1049 DBG1(DBG_CFG
, "could not listen on stroke socket: %m");
1050 close(this->socket
);
1051 unlink(socket_addr
.sun_path
);
1056 /* start a thread reading from the socket */
1057 if (pthread_create(&(this->assigned_thread
), NULL
, (void*(*)(void*))stroke_receive
, this) != 0)
1059 DBG1(DBG_CFG
, "could not spawn stroke thread");
1060 close(this->socket
);
1061 unlink(socket_addr
.sun_path
);
1066 return (&this->public);