stroke: use a stream service to handle stroke requests
[strongswan.git] / src / libcharon / plugins / stroke / stroke_socket.c
1 /*
2 * Copyright (C) 2011-2012 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "stroke_socket.h"
18
19 #include <stdlib.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/socket.h>
23 #include <sys/un.h>
24 #include <unistd.h>
25 #include <errno.h>
26
27 #include <hydra.h>
28 #include <daemon.h>
29
30 #include "stroke_config.h"
31 #include "stroke_control.h"
32 #include "stroke_cred.h"
33 #include "stroke_ca.h"
34 #include "stroke_attribute.h"
35 #include "stroke_handler.h"
36 #include "stroke_list.h"
37 #include "stroke_counter.h"
38
39 /**
40 * To avoid clogging the thread pool with (blocking) jobs, we limit the number
41 * of concurrently handled stroke commands.
42 */
43 #define MAX_CONCURRENT_DEFAULT 4
44
45 typedef struct stroke_job_context_t stroke_job_context_t;
46 typedef struct private_stroke_socket_t private_stroke_socket_t;
47
48 /**
49 * private data of stroke_socket
50 */
51 struct private_stroke_socket_t {
52
53 /**
54 * public functions
55 */
56 stroke_socket_t public;
57
58 /**
59 * Service accepting stroke connections
60 */
61 stream_service_t *service;
62
63 /**
64 * configuration backend
65 */
66 stroke_config_t *config;
67
68 /**
69 * attribute provider
70 */
71 stroke_attribute_t *attribute;
72
73 /**
74 * attribute handler (requests only)
75 */
76 stroke_handler_t *handler;
77
78 /**
79 * controller to control daemon
80 */
81 stroke_control_t *control;
82
83 /**
84 * credential set
85 */
86 stroke_cred_t *cred;
87
88 /**
89 * CA sections
90 */
91 stroke_ca_t *ca;
92
93 /**
94 * status information logging
95 */
96 stroke_list_t *list;
97
98 /**
99 * Counter values for IKE events
100 */
101 stroke_counter_t *counter;
102 };
103
104 /**
105 * Helper function which corrects the string pointers
106 * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
107 * contains RELATIVE addresses (relative to the beginning of the
108 * stroke_msg). They must be corrected if they reach our address
109 * space...
110 */
111 static void pop_string(stroke_msg_t *msg, char **string)
112 {
113 if (*string == NULL)
114 {
115 return;
116 }
117
118 /* check for sanity of string pointer and string */
119 if (string < (char**)msg ||
120 string > (char**)((char*)msg + sizeof(stroke_msg_t)) ||
121 (unsigned long)*string < (unsigned long)((char*)msg->buffer - (char*)msg) ||
122 (unsigned long)*string > msg->length)
123 {
124 *string = "(invalid pointer in stroke msg)";
125 }
126 else
127 {
128 *string = (char*)msg + (unsigned long)*string;
129 }
130 }
131
132 /**
133 * Pop the strings of a stroke_end_t struct and log them for debugging purposes
134 */
135 static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
136 {
137 pop_string(msg, &end->address);
138 pop_string(msg, &end->subnets);
139 pop_string(msg, &end->sourceip);
140 pop_string(msg, &end->dns);
141 pop_string(msg, &end->auth);
142 pop_string(msg, &end->auth2);
143 pop_string(msg, &end->id);
144 pop_string(msg, &end->id2);
145 pop_string(msg, &end->rsakey);
146 pop_string(msg, &end->cert);
147 pop_string(msg, &end->cert2);
148 pop_string(msg, &end->ca);
149 pop_string(msg, &end->ca2);
150 pop_string(msg, &end->groups);
151 pop_string(msg, &end->groups2);
152 pop_string(msg, &end->cert_policy);
153 pop_string(msg, &end->updown);
154
155 DBG2(DBG_CFG, " %s=%s", label, end->address);
156 DBG2(DBG_CFG, " %ssubnet=%s", label, end->subnets);
157 DBG2(DBG_CFG, " %ssourceip=%s", label, end->sourceip);
158 DBG2(DBG_CFG, " %sdns=%s", label, end->dns);
159 DBG2(DBG_CFG, " %sauth=%s", label, end->auth);
160 DBG2(DBG_CFG, " %sauth2=%s", label, end->auth2);
161 DBG2(DBG_CFG, " %sid=%s", label, end->id);
162 DBG2(DBG_CFG, " %sid2=%s", label, end->id2);
163 DBG2(DBG_CFG, " %srsakey=%s", label, end->rsakey);
164 DBG2(DBG_CFG, " %scert=%s", label, end->cert);
165 DBG2(DBG_CFG, " %scert2=%s", label, end->cert2);
166 DBG2(DBG_CFG, " %sca=%s", label, end->ca);
167 DBG2(DBG_CFG, " %sca2=%s", label, end->ca2);
168 DBG2(DBG_CFG, " %sgroups=%s", label, end->groups);
169 DBG2(DBG_CFG, " %sgroups2=%s", label, end->groups2);
170 DBG2(DBG_CFG, " %supdown=%s", label, end->updown);
171 }
172
173 /**
174 * Add a connection to the configuration list
175 */
176 static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
177 {
178 pop_string(msg, &msg->add_conn.name);
179 DBG1(DBG_CFG, "received stroke: add connection '%s'", msg->add_conn.name);
180
181 DBG2(DBG_CFG, "conn %s", msg->add_conn.name);
182 pop_end(msg, "left", &msg->add_conn.me);
183 pop_end(msg, "right", &msg->add_conn.other);
184 pop_string(msg, &msg->add_conn.eap_identity);
185 pop_string(msg, &msg->add_conn.aaa_identity);
186 pop_string(msg, &msg->add_conn.xauth_identity);
187 pop_string(msg, &msg->add_conn.algorithms.ike);
188 pop_string(msg, &msg->add_conn.algorithms.esp);
189 pop_string(msg, &msg->add_conn.ikeme.mediated_by);
190 pop_string(msg, &msg->add_conn.ikeme.peerid);
191 DBG2(DBG_CFG, " eap_identity=%s", msg->add_conn.eap_identity);
192 DBG2(DBG_CFG, " aaa_identity=%s", msg->add_conn.aaa_identity);
193 DBG2(DBG_CFG, " xauth_identity=%s", msg->add_conn.xauth_identity);
194 DBG2(DBG_CFG, " ike=%s", msg->add_conn.algorithms.ike);
195 DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp);
196 DBG2(DBG_CFG, " dpddelay=%d", msg->add_conn.dpd.delay);
197 DBG2(DBG_CFG, " dpdtimeout=%d", msg->add_conn.dpd.timeout);
198 DBG2(DBG_CFG, " dpdaction=%d", msg->add_conn.dpd.action);
199 DBG2(DBG_CFG, " closeaction=%d", msg->add_conn.close_action);
200 DBG2(DBG_CFG, " mediation=%s", msg->add_conn.ikeme.mediation ? "yes" : "no");
201 DBG2(DBG_CFG, " mediated_by=%s", msg->add_conn.ikeme.mediated_by);
202 DBG2(DBG_CFG, " me_peerid=%s", msg->add_conn.ikeme.peerid);
203 DBG2(DBG_CFG, " keyexchange=ikev%u", msg->add_conn.version);
204
205 this->config->add(this->config, msg);
206 this->attribute->add_dns(this->attribute, msg);
207 this->handler->add_attributes(this->handler, msg);
208 }
209
210 /**
211 * Delete a connection from the list
212 */
213 static void stroke_del_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
214 {
215 pop_string(msg, &msg->del_conn.name);
216 DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
217
218 this->config->del(this->config, msg);
219 this->attribute->del_dns(this->attribute, msg);
220 this->handler->del_attributes(this->handler, msg);
221 }
222
223 /**
224 * initiate a connection by name
225 */
226 static void stroke_initiate(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
227 {
228 pop_string(msg, &msg->initiate.name);
229 DBG1(DBG_CFG, "received stroke: initiate '%s'", msg->initiate.name);
230
231 this->control->initiate(this->control, msg, out);
232 }
233
234 /**
235 * terminate a connection by name
236 */
237 static void stroke_terminate(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
238 {
239 pop_string(msg, &msg->terminate.name);
240 DBG1(DBG_CFG, "received stroke: terminate '%s'", msg->terminate.name);
241
242 this->control->terminate(this->control, msg, out);
243 }
244
245 /**
246 * terminate a connection by peers virtual IP
247 */
248 static void stroke_terminate_srcip(private_stroke_socket_t *this,
249 stroke_msg_t *msg, FILE *out)
250 {
251 pop_string(msg, &msg->terminate_srcip.start);
252 pop_string(msg, &msg->terminate_srcip.end);
253 DBG1(DBG_CFG, "received stroke: terminate-srcip %s-%s",
254 msg->terminate_srcip.start, msg->terminate_srcip.end);
255
256 this->control->terminate_srcip(this->control, msg, out);
257 }
258
259 /**
260 * rekey a connection by name/id
261 */
262 static void stroke_rekey(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
263 {
264 pop_string(msg, &msg->terminate.name);
265 DBG1(DBG_CFG, "received stroke: rekey '%s'", msg->rekey.name);
266
267 this->control->rekey(this->control, msg, out);
268 }
269
270 /**
271 * route a policy (install SPD entries)
272 */
273 static void stroke_route(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
274 {
275 pop_string(msg, &msg->route.name);
276 DBG1(DBG_CFG, "received stroke: route '%s'", msg->route.name);
277
278 this->control->route(this->control, msg, out);
279 }
280
281 /**
282 * unroute a policy
283 */
284 static void stroke_unroute(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
285 {
286 pop_string(msg, &msg->terminate.name);
287 DBG1(DBG_CFG, "received stroke: unroute '%s'", msg->route.name);
288
289 this->control->unroute(this->control, msg, out);
290 }
291
292 /**
293 * Add a ca information record to the cainfo list
294 */
295 static void stroke_add_ca(private_stroke_socket_t *this,
296 stroke_msg_t *msg, FILE *out)
297 {
298 pop_string(msg, &msg->add_ca.name);
299 DBG1(DBG_CFG, "received stroke: add ca '%s'", msg->add_ca.name);
300
301 pop_string(msg, &msg->add_ca.cacert);
302 pop_string(msg, &msg->add_ca.crluri);
303 pop_string(msg, &msg->add_ca.crluri2);
304 pop_string(msg, &msg->add_ca.ocspuri);
305 pop_string(msg, &msg->add_ca.ocspuri2);
306 pop_string(msg, &msg->add_ca.certuribase);
307 DBG2(DBG_CFG, "ca %s", msg->add_ca.name);
308 DBG2(DBG_CFG, " cacert=%s", msg->add_ca.cacert);
309 DBG2(DBG_CFG, " crluri=%s", msg->add_ca.crluri);
310 DBG2(DBG_CFG, " crluri2=%s", msg->add_ca.crluri2);
311 DBG2(DBG_CFG, " ocspuri=%s", msg->add_ca.ocspuri);
312 DBG2(DBG_CFG, " ocspuri2=%s", msg->add_ca.ocspuri2);
313 DBG2(DBG_CFG, " certuribase=%s", msg->add_ca.certuribase);
314
315 this->ca->add(this->ca, msg);
316 }
317
318 /**
319 * Delete a ca information record from the cainfo list
320 */
321 static void stroke_del_ca(private_stroke_socket_t *this,
322 stroke_msg_t *msg, FILE *out)
323 {
324 pop_string(msg, &msg->del_ca.name);
325 DBG1(DBG_CFG, "received stroke: delete ca '%s'", msg->del_ca.name);
326
327 this->ca->del(this->ca, msg);
328 }
329
330
331 /**
332 * show status of daemon
333 */
334 static void stroke_status(private_stroke_socket_t *this,
335 stroke_msg_t *msg, FILE *out, bool all, bool wait)
336 {
337 pop_string(msg, &(msg->status.name));
338
339 this->list->status(this->list, msg, out, all, wait);
340 }
341
342 /**
343 * list various information
344 */
345 static void stroke_list(private_stroke_socket_t *this, stroke_msg_t *msg,
346 FILE *out)
347 {
348 if (msg->list.flags & LIST_CAINFOS)
349 {
350 this->ca->list(this->ca, msg, out);
351 }
352 this->list->list(this->list, msg, out);
353 }
354
355 /**
356 * reread various information
357 */
358 static void stroke_reread(private_stroke_socket_t *this,
359 stroke_msg_t *msg, FILE *out)
360 {
361 this->cred->reread(this->cred, msg, out);
362 }
363
364 /**
365 * purge various information
366 */
367 static void stroke_purge(private_stroke_socket_t *this,
368 stroke_msg_t *msg, FILE *out)
369 {
370 if (msg->purge.flags & PURGE_OCSP)
371 {
372 lib->credmgr->flush_cache(lib->credmgr, CERT_X509_OCSP_RESPONSE);
373 }
374 if (msg->purge.flags & PURGE_CRLS)
375 {
376 lib->credmgr->flush_cache(lib->credmgr, CERT_X509_CRL);
377 }
378 if (msg->purge.flags & PURGE_CERTS)
379 {
380 lib->credmgr->flush_cache(lib->credmgr, CERT_X509);
381 }
382 if (msg->purge.flags & PURGE_IKE)
383 {
384 this->control->purge_ike(this->control, msg, out);
385 }
386 }
387
388 /**
389 * Print a certificate in PEM to out
390 */
391 static void print_pem_cert(FILE *out, certificate_t *cert)
392 {
393 chunk_t encoded;
394
395 if (cert->get_encoding(cert, CERT_PEM, &encoded))
396 {
397 fprintf(out, "%.*s", (int)encoded.len, encoded.ptr);
398 free(encoded.ptr);
399 }
400 }
401
402 /**
403 * Export in-memory credentials
404 */
405 static void stroke_export(private_stroke_socket_t *this,
406 stroke_msg_t *msg, FILE *out)
407 {
408 pop_string(msg, &msg->export.selector);
409
410 if (msg->export.flags & EXPORT_X509)
411 {
412 enumerator_t *enumerator;
413 identification_t *id;
414 certificate_t *cert;
415
416 id = identification_create_from_string(msg->export.selector);
417 enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
418 CERT_X509, KEY_ANY, id, FALSE);
419 while (enumerator->enumerate(enumerator, &cert))
420 {
421 print_pem_cert(out, cert);
422 }
423 enumerator->destroy(enumerator);
424 id->destroy(id);
425 }
426
427 if (msg->export.flags & (EXPORT_CONN_CERT | EXPORT_CONN_CHAIN))
428 {
429 enumerator_t *sas, *auths, *certs;
430 ike_sa_t *ike_sa;
431 auth_cfg_t *auth;
432 certificate_t *cert;
433 auth_rule_t rule;
434
435 sas = charon->ike_sa_manager->create_enumerator(
436 charon->ike_sa_manager, TRUE);
437 while (sas->enumerate(sas, &ike_sa))
438 {
439 if (streq(msg->export.selector, ike_sa->get_name(ike_sa)))
440 {
441 auths = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE);
442 while (auths->enumerate(auths, &auth))
443 {
444 bool got_subject = FALSE;
445
446 certs = auth->create_enumerator(auth);
447 while (certs->enumerate(certs, &rule, &cert))
448 {
449 switch (rule)
450 {
451 case AUTH_RULE_CA_CERT:
452 case AUTH_RULE_IM_CERT:
453 if (msg->export.flags & EXPORT_CONN_CHAIN)
454 {
455 print_pem_cert(out, cert);
456 }
457 break;
458 case AUTH_RULE_SUBJECT_CERT:
459 if (!got_subject)
460 {
461 print_pem_cert(out, cert);
462 got_subject = TRUE;
463 }
464 break;
465 default:
466 break;
467 }
468 }
469 certs->destroy(certs);
470 }
471 auths->destroy(auths);
472 }
473 }
474 sas->destroy(sas);
475 }
476 }
477
478 /**
479 * list pool leases
480 */
481 static void stroke_leases(private_stroke_socket_t *this,
482 stroke_msg_t *msg, FILE *out)
483 {
484 pop_string(msg, &msg->leases.pool);
485 pop_string(msg, &msg->leases.address);
486
487 this->list->leases(this->list, msg, out);
488 }
489
490 /**
491 * Show memory usage
492 */
493 static void stroke_memusage(private_stroke_socket_t *this,
494 stroke_msg_t *msg, FILE *out)
495 {
496 if (lib->leak_detective)
497 {
498 lib->leak_detective->usage(lib->leak_detective, out);
499 }
500 }
501
502 /**
503 * Set username and password for a connection
504 */
505 static void stroke_user_creds(private_stroke_socket_t *this,
506 stroke_msg_t *msg, FILE *out)
507 {
508 pop_string(msg, &msg->user_creds.name);
509 pop_string(msg, &msg->user_creds.username);
510 pop_string(msg, &msg->user_creds.password);
511
512 DBG1(DBG_CFG, "received stroke: user-creds '%s'", msg->user_creds.name);
513
514 this->config->set_user_credentials(this->config, msg, out);
515 }
516
517 /**
518 * Print stroke counter values
519 */
520 static void stroke_counters(private_stroke_socket_t *this,
521 stroke_msg_t *msg, FILE *out)
522 {
523 pop_string(msg, &msg->counters.name);
524
525 if (msg->counters.reset)
526 {
527 this->counter->reset(this->counter, msg->counters.name);
528 }
529 else
530 {
531 this->counter->print(this->counter, out, msg->counters.name);
532 }
533 }
534
535 /**
536 * set the verbosity debug output
537 */
538 static void stroke_loglevel(private_stroke_socket_t *this,
539 stroke_msg_t *msg, FILE *out)
540 {
541 debug_t group;
542
543 pop_string(msg, &(msg->loglevel.type));
544 DBG1(DBG_CFG, "received stroke: loglevel %d for %s",
545 msg->loglevel.level, msg->loglevel.type);
546
547 if (strcaseeq(msg->loglevel.type, "any"))
548 {
549 group = DBG_ANY;
550 }
551 else
552 {
553 group = enum_from_name(debug_names, msg->loglevel.type);
554 if ((int)group < 0)
555 {
556 fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
557 return;
558 }
559 }
560 charon->set_level(charon, group, msg->loglevel.level);
561 }
562
563 /**
564 * set various config options
565 */
566 static void stroke_config(private_stroke_socket_t *this,
567 stroke_msg_t *msg, FILE *out)
568 {
569 this->cred->cachecrl(this->cred, msg->config.cachecrl);
570 }
571
572 /**
573 * process a stroke request
574 */
575 static bool on_accept(private_stroke_socket_t *this, stream_t *stream)
576 {
577 stroke_msg_t *msg;
578 u_int16_t len;
579 FILE *out;
580
581 /* read length */
582 if (!stream->read_all(stream, &len, sizeof(len)))
583 {
584 if (errno != EWOULDBLOCK)
585 {
586 DBG1(DBG_CFG, "reading length of stroke message failed: %s",
587 strerror(errno));
588 }
589 return FALSE;
590 }
591
592 /* read message */
593 msg = malloc(len);
594 msg->length = len;
595 if (!stream->read_all(stream, (char*)msg + sizeof(len), len - sizeof(len)))
596 {
597 if (errno != EWOULDBLOCK)
598 {
599 DBG1(DBG_CFG, "reading stroke message failed: %s", strerror(errno));
600 }
601 free(msg);
602 return FALSE;
603 }
604
605 DBG3(DBG_CFG, "stroke message %b", (void*)msg, len);
606
607 out = stream->get_file(stream);
608 if (!out)
609 {
610 DBG1(DBG_CFG, "creating stroke output stream failed");
611 free(msg);
612 return FALSE;
613 }
614 switch (msg->type)
615 {
616 case STR_INITIATE:
617 stroke_initiate(this, msg, out);
618 break;
619 case STR_ROUTE:
620 stroke_route(this, msg, out);
621 break;
622 case STR_UNROUTE:
623 stroke_unroute(this, msg, out);
624 break;
625 case STR_TERMINATE:
626 stroke_terminate(this, msg, out);
627 break;
628 case STR_TERMINATE_SRCIP:
629 stroke_terminate_srcip(this, msg, out);
630 break;
631 case STR_REKEY:
632 stroke_rekey(this, msg, out);
633 break;
634 case STR_STATUS:
635 stroke_status(this, msg, out, FALSE, TRUE);
636 break;
637 case STR_STATUS_ALL:
638 stroke_status(this, msg, out, TRUE, TRUE);
639 break;
640 case STR_STATUS_ALL_NOBLK:
641 stroke_status(this, msg, out, TRUE, FALSE);
642 break;
643 case STR_ADD_CONN:
644 stroke_add_conn(this, msg);
645 break;
646 case STR_DEL_CONN:
647 stroke_del_conn(this, msg);
648 break;
649 case STR_ADD_CA:
650 stroke_add_ca(this, msg, out);
651 break;
652 case STR_DEL_CA:
653 stroke_del_ca(this, msg, out);
654 break;
655 case STR_LOGLEVEL:
656 stroke_loglevel(this, msg, out);
657 break;
658 case STR_CONFIG:
659 stroke_config(this, msg, out);
660 break;
661 case STR_LIST:
662 stroke_list(this, msg, out);
663 break;
664 case STR_REREAD:
665 stroke_reread(this, msg, out);
666 break;
667 case STR_PURGE:
668 stroke_purge(this, msg, out);
669 break;
670 case STR_EXPORT:
671 stroke_export(this, msg, out);
672 break;
673 case STR_LEASES:
674 stroke_leases(this, msg, out);
675 break;
676 case STR_MEMUSAGE:
677 stroke_memusage(this, msg, out);
678 break;
679 case STR_USER_CREDS:
680 stroke_user_creds(this, msg, out);
681 break;
682 case STR_COUNTERS:
683 stroke_counters(this, msg, out);
684 break;
685 default:
686 DBG1(DBG_CFG, "received unknown stroke");
687 break;
688 }
689 free(msg);
690 fclose(out);
691 return FALSE;
692 }
693
694 METHOD(stroke_socket_t, destroy, void,
695 private_stroke_socket_t *this)
696 {
697 DESTROY_IF(this->service);
698 lib->credmgr->remove_set(lib->credmgr, &this->ca->set);
699 lib->credmgr->remove_set(lib->credmgr, &this->cred->set);
700 charon->backends->remove_backend(charon->backends, &this->config->backend);
701 hydra->attributes->remove_provider(hydra->attributes, &this->attribute->provider);
702 hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
703 charon->bus->remove_listener(charon->bus, &this->counter->listener);
704 this->cred->destroy(this->cred);
705 this->ca->destroy(this->ca);
706 this->config->destroy(this->config);
707 this->attribute->destroy(this->attribute);
708 this->handler->destroy(this->handler);
709 this->control->destroy(this->control);
710 this->list->destroy(this->list);
711 this->counter->destroy(this->counter);
712 free(this);
713 }
714
715 /*
716 * see header file
717 */
718 stroke_socket_t *stroke_socket_create()
719 {
720 private_stroke_socket_t *this;
721 int max_concurrent;
722 char *uri;
723
724 INIT(this,
725 .public = {
726 .destroy = _destroy,
727 },
728 );
729
730 this->cred = stroke_cred_create();
731 this->attribute = stroke_attribute_create();
732 this->handler = stroke_handler_create();
733 this->ca = stroke_ca_create(this->cred);
734 this->config = stroke_config_create(this->ca, this->cred, this->attribute);
735 this->control = stroke_control_create();
736 this->list = stroke_list_create(this->attribute);
737 this->counter = stroke_counter_create();
738
739 lib->credmgr->add_set(lib->credmgr, &this->ca->set);
740 lib->credmgr->add_set(lib->credmgr, &this->cred->set);
741 charon->backends->add_backend(charon->backends, &this->config->backend);
742 hydra->attributes->add_provider(hydra->attributes, &this->attribute->provider);
743 hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
744 charon->bus->add_listener(charon->bus, &this->counter->listener);
745
746 max_concurrent = lib->settings->get_int(lib->settings,
747 "%s.plugins.stroke.max_concurrent", MAX_CONCURRENT_DEFAULT,
748 charon->name);
749 uri = lib->settings->get_str(lib->settings,
750 "%s.plugins.stroke.socket", "unix://" STROKE_SOCKET, charon->name);
751 this->service = lib->streams->create_service(lib->streams, uri, 10);
752 if (!this->service)
753 {
754 DBG1(DBG_CFG, "creating stroke socket failed");
755 destroy(this);
756 return NULL;
757 }
758 this->service->on_accept(this->service, (stream_service_cb_t)on_accept,
759 this, JOB_PRIO_CRITICAL, max_concurrent);
760
761 return &this->public;
762 }