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 || (u_int
)*string
< (u_int
)((char*)msg
->buffer
- (char*)msg
)
97 || (u_int
)*string
> msg
->length
)
99 *string
= "(invalid pointer in stroke msg)";
103 *string
= (char*)msg
+ (u_int
)*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
, "worker threads idle: %d of %d\n",
649 charon
->thread_pool
->get_idle_threads(charon
->thread_pool
),
650 charon
->thread_pool
->get_pool_size(charon
->thread_pool
));
651 fprintf(this->out
, "job queue load: %d\n",
652 charon
->job_queue
->get_count(charon
->job_queue
));
653 fprintf(this->out
, "scheduled events: %d\n",
654 charon
->event_queue
->get_count(charon
->event_queue
));
655 list
= charon
->socket
->create_local_address_list(charon
->socket
);
656 fprintf(this->out
, "listening on %d addresses:\n", list
->get_count(list
));
657 while (list
->remove_first(list
, (void**)&host
) == SUCCESS
)
659 fprintf(this->out
, " %H\n", host
);
664 if (msg
->status
.name
)
666 pop_string(msg
, &(msg
->status
.name
));
669 fprintf(this->out
, "connections:\n");
670 iterator
= charon
->connections
->create_iterator(charon
->connections
);
671 while (iterator
->iterate(iterator
, (void**)&connection
))
673 if (connection
->is_ikev2(connection
) && (msg
->status
.name
== NULL
||
674 streq(msg
->status
.name
, connection
->get_name(connection
))))
676 fprintf(this->out
, "%10s: %H...%H\n",
677 connection
->get_name(connection
),
678 connection
->get_my_host(connection
),
679 connection
->get_other_host(connection
));
682 iterator
->destroy(iterator
);
684 fprintf(this->out
, "policies:\n");
685 iterator
= charon
->policies
->create_iterator(charon
->policies
);
686 while (iterator
->iterate(iterator
, (void**)&policy
))
688 if (msg
->status
.name
== NULL
||
689 streq(msg
->status
.name
, policy
->get_name(policy
)))
691 fprintf(this->out
, "%10s: %D...%D\n",
692 policy
->get_name(policy
),
693 policy
->get_my_id(policy
),
694 policy
->get_other_id(policy
));
697 iterator
->destroy(iterator
);
699 fprintf(this->out
, "IKE_SAs:\n");
700 iterator
= charon
->ike_sa_manager
->create_iterator(charon
->ike_sa_manager
);
701 while (iterator
->iterate(iterator
, (void**)&ike_sa
))
703 bool ike_sa_printed
= FALSE
;
704 child_sa_t
*child_sa
;
705 iterator_t
*children
= ike_sa
->create_child_sa_iterator(ike_sa
);
706 while (children
->iterate(children
, (void**)&child_sa
))
708 if (!ike_sa_printed
&&
709 (msg
->status
.name
== NULL
||
710 streq(msg
->status
.name
, child_sa
->get_name(child_sa
)) ||
711 streq(msg
->status
.name
, ike_sa
->get_name(ike_sa
))))
713 fprintf(this->out
, "%#K\n", ike_sa
);
714 ike_sa_printed
= TRUE
;
718 fprintf(this->out
, "%#P\n", child_sa
);
721 children
->destroy(children
);
723 iterator
->destroy(iterator
);
727 * show status of daemon
729 static void stroke_status(private_stroke_t
*this, stroke_msg_t
*msg
)
731 iterator_t
*iterator
;
734 if (msg
->status
.name
)
736 pop_string(msg
, &(msg
->status
.name
));
739 iterator
= charon
->ike_sa_manager
->create_iterator(charon
->ike_sa_manager
);
740 while (iterator
->iterate(iterator
, (void**)&ike_sa
))
742 bool ike_sa_printed
= FALSE
;
743 child_sa_t
*child_sa
;
744 iterator_t
*children
= ike_sa
->create_child_sa_iterator(ike_sa
);
745 while (children
->iterate(children
, (void**)&child_sa
))
747 if (!ike_sa_printed
&&
748 (msg
->status
.name
== NULL
||
749 streq(msg
->status
.name
, child_sa
->get_name(child_sa
)) ||
750 streq(msg
->status
.name
, ike_sa
->get_name(ike_sa
))))
752 fprintf(this->out
, "%K\n", ike_sa
);
753 ike_sa_printed
= TRUE
;
757 fprintf(this->out
, "%P\n", child_sa
);
760 children
->destroy(children
);
762 iterator
->destroy(iterator
);
766 * list various information
768 static void stroke_list(private_stroke_t
*this, stroke_msg_t
*msg
)
770 iterator_t
*iterator
;
772 if (msg
->list
.flags
& LIST_CERTS
)
776 iterator
= charon
->credentials
->create_cert_iterator(charon
->credentials
);
777 if (iterator
->get_count(iterator
))
779 fprintf(this->out
, "\n");
780 fprintf(this->out
, "List of X.509 End Entity Certificates:\n");
781 fprintf(this->out
, "\n");
783 while (iterator
->iterate(iterator
, (void**)&cert
))
785 fprintf(this->out
, "%#Q", cert
, msg
->list
.utc
);
786 if (charon
->credentials
->has_rsa_private_key(
787 charon
->credentials
, cert
->get_public_key(cert
)))
789 fprintf(this->out
, ", has private key");
791 fprintf(this->out
, "\n");
794 iterator
->destroy(iterator
);
796 if (msg
->list
.flags
& LIST_CACERTS
)
800 iterator
= charon
->credentials
->create_cacert_iterator(charon
->credentials
);
801 if (iterator
->get_count(iterator
))
803 fprintf(this->out
, "\n");
804 fprintf(this->out
, "List of X.509 CA Certificates:\n");
805 fprintf(this->out
, "\n");
807 while (iterator
->iterate(iterator
, (void**)&cert
))
809 fprintf(this->out
, "%#Q\n", cert
, msg
->list
.utc
);
811 iterator
->destroy(iterator
);
813 if (msg
->list
.flags
& LIST_CRLS
)
817 iterator
= charon
->credentials
->create_crl_iterator(charon
->credentials
);
818 if (iterator
->get_count(iterator
))
820 fprintf(this->out
, "\n");
821 fprintf(this->out
, "List of X.509 CRLs:\n");
822 fprintf(this->out
, "\n");
824 while (iterator
->iterate(iterator
, (void**)&crl
))
826 fprintf(this->out
, "%#U\n", crl
, msg
->list
.utc
);
828 iterator
->destroy(iterator
);
833 * reread various information
835 static void stroke_reread(private_stroke_t
*this, stroke_msg_t
*msg
)
837 if (msg
->reread
.flags
& REREAD_CACERTS
)
839 charon
->credentials
->load_ca_certificates(charon
->credentials
);
841 if (msg
->reread
.flags
& REREAD_CRLS
)
843 charon
->credentials
->load_crls(charon
->credentials
);
847 signal_t
get_signal_from_logtype(char *type
)
849 if (strcasecmp(type
, "any") == 0) return SIG_ANY
;
850 else if (strcasecmp(type
, "mgr") == 0) return DBG_MGR
;
851 else if (strcasecmp(type
, "ike") == 0) return DBG_IKE
;
852 else if (strcasecmp(type
, "chd") == 0) return DBG_CHD
;
853 else if (strcasecmp(type
, "job") == 0) return DBG_JOB
;
854 else if (strcasecmp(type
, "cfg") == 0) return DBG_CFG
;
855 else if (strcasecmp(type
, "knl") == 0) return DBG_KNL
;
856 else if (strcasecmp(type
, "net") == 0) return DBG_NET
;
857 else if (strcasecmp(type
, "enc") == 0) return DBG_ENC
;
858 else if (strcasecmp(type
, "lib") == 0) return DBG_LIB
;
863 * set the verbosity debug output
865 static void stroke_loglevel(private_stroke_t
*this, stroke_msg_t
*msg
)
869 pop_string(msg
, &(msg
->loglevel
.type
));
870 DBG1(DBG_CFG
, "received stroke: loglevel %d for %s",
871 msg
->loglevel
.level
, msg
->loglevel
.type
);
873 signal
= get_signal_from_logtype(msg
->loglevel
.type
);
876 fprintf(this->out
, "invalid type (%s)!\n", msg
->loglevel
.type
);
880 charon
->outlog
->set_level(charon
->outlog
, signal
, msg
->loglevel
.level
);
881 charon
->syslog
->set_level(charon
->syslog
, signal
, msg
->loglevel
.level
);
885 * Implementation of private_stroke_t.stroke_receive.
887 static void stroke_receive(private_stroke_t
*this)
890 u_int16_t msg_length
;
891 struct sockaddr_un strokeaddr
;
892 int strokeaddrlen
= sizeof(strokeaddr
);
897 /* ignore sigpipe. writing over the pipe back to the console
898 * only fails if SIGPIPE is ignored. */
899 signal(SIGPIPE
, SIG_IGN
);
901 /* disable cancellation by default */
902 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
906 /* wait for connections, but allow thread to terminate */
907 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, &oldstate
);
908 strokefd
= accept(this->socket
, (struct sockaddr
*)&strokeaddr
, &strokeaddrlen
);
909 pthread_setcancelstate(oldstate
, NULL
);
913 DBG1(DBG_CFG
, "accepting stroke connection failed: %m");
917 /* peek the length */
918 bytes_read
= recv(strokefd
, &msg_length
, sizeof(msg_length
), MSG_PEEK
);
919 if (bytes_read
!= sizeof(msg_length
))
921 DBG1(DBG_CFG
, "reading lenght of stroke message failed");
927 msg
= malloc(msg_length
);
928 bytes_read
= recv(strokefd
, msg
, msg_length
, 0);
929 if (bytes_read
!= msg_length
)
931 DBG1(DBG_CFG
, "reading stroke message failed: %m");
936 this->out
= fdopen(dup(strokefd
), "w");
937 if (this->out
== NULL
)
939 DBG1(DBG_CFG
, "opening stroke output channel failed: %m");
945 DBG3(DBG_CFG
, "stroke message %b", (void*)msg
, msg_length
);
950 stroke_initiate(this, msg
);
953 stroke_route(this, msg
, TRUE
);
956 stroke_route(this, msg
, FALSE
);
959 stroke_terminate(this, msg
);
962 stroke_status(this, msg
);
965 stroke_statusall(this, msg
);
968 stroke_add_conn(this, msg
);
971 stroke_del_conn(this, msg
);
974 stroke_loglevel(this, msg
);
977 stroke_list(this, msg
);
980 stroke_reread(this, msg
);
983 DBG1(DBG_CFG
, "received unknown stroke");
992 * Implementation of stroke_t.destroy.
994 static void destroy(private_stroke_t
*this)
996 pthread_cancel(this->assigned_thread
);
997 pthread_join(this->assigned_thread
, NULL
);
1000 unlink(socket_addr
.sun_path
);
1005 * Described in header-file
1007 stroke_t
*stroke_create()
1009 private_stroke_t
*this = malloc_thing(private_stroke_t
);
1012 /* public functions */
1013 this->public.destroy
= (void (*)(stroke_t
*))destroy
;
1015 /* set up unix socket */
1016 this->socket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
1017 if (this->socket
== -1)
1019 DBG1(DBG_CFG
, "could not create whack socket");
1024 old
= umask(~S_IRWXU
);
1025 if (bind(this->socket
, (struct sockaddr
*)&socket_addr
, sizeof(socket_addr
)) < 0)
1027 DBG1(DBG_CFG
, "could not bind stroke socket: %m");
1028 close(this->socket
);
1034 if (listen(this->socket
, 0) < 0)
1036 DBG1(DBG_CFG
, "could not listen on stroke socket: %m");
1037 close(this->socket
);
1038 unlink(socket_addr
.sun_path
);
1043 /* start a thread reading from the socket */
1044 if (pthread_create(&(this->assigned_thread
), NULL
, (void*(*)(void*))stroke_receive
, this) != 0)
1046 DBG1(DBG_CFG
, "could not spawn stroke thread");
1047 close(this->socket
);
1048 unlink(socket_addr
.sun_path
);
1053 return (&this->public);