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