OpenDNSSEC-enforcer 2.1.12
engine.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009 NLNet Labs. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 */
26
32#include "config.h"
33
34#include <pthread.h>
35
36#include "daemon/cfg.h"
38#include "clientpipe.h"
39#include "cmdhandler.h"
40#include "locks.h"
41#include "daemon/engine.h"
42#include "scheduler/schedule.h"
43#include "scheduler/task.h"
44#include "file.h"
45#include "log.h"
46#include "privdrop.h"
47#include "status.h"
48#include "util.h"
49#include "db/db_configuration.h"
50#include "db/db_connection.h"
51#include "db/database_version.h"
53#include "libhsm.h"
54#include "locks.h"
55
56#include <errno.h>
57#include <libxml/parser.h>
58#include <signal.h>
59#include <stdio.h>
60#include <stdlib.h>
61#include <string.h>
62#include <strings.h>
63#include <sys/socket.h>
64#include <sys/types.h>
65#include <sys/un.h>
66#include <time.h>
67#include <unistd.h>
68#include <fcntl.h>
69
70static const char* engine_str = "engine";
71
72static engine_type* engine = NULL;
73
80{
81 engine = (engine_type*) malloc(sizeof(engine_type));
82 if (!engine) return NULL;
83
84 pthread_mutex_init(&engine->signal_lock, NULL);
85 pthread_cond_init(&engine->signal_cond, NULL);
86
87 engine->dbcfg_list = NULL;
88 engine->taskq = schedule_create();
89 if (!engine->taskq) {
90 free(engine);
91 return NULL;
92 }
93 return engine;
94}
95
96void
98{
99 schedule_cleanup(engine->taskq);
100 pthread_mutex_destroy(&engine->signal_lock);
101 pthread_cond_destroy(&engine->signal_cond);
102 if (engine->dbcfg_list) {
104 }
106 free(engine);
107}
108
109static void
110engine_start_cmdhandler(engine_type* engine)
111{
112 ods_log_assert(engine);
113 ods_log_debug("[%s] start command handler", engine_str);
114 janitor_thread_create(&engine->cmdhandler->thread_id, workerthreadclass, (janitor_runfn_t)cmdhandler_start, engine->cmdhandler);
115}
116
121static ods_status
122engine_privdrop(engine_type* engine)
123{
124 ods_status status = ODS_STATUS_OK;
125 uid_t uid = -1;
126 gid_t gid = -1;
127
128 ods_log_assert(engine);
129 ods_log_assert(engine->config);
130 ods_log_debug("[%s] drop privileges", engine_str);
131
132 if (engine->config->username && engine->config->group) {
133 ods_log_verbose("[%s] drop privileges to user %s, group %s",
134 engine_str, engine->config->username, engine->config->group);
135 } else if (engine->config->username) {
136 ods_log_verbose("[%s] drop privileges to user %s", engine_str,
137 engine->config->username);
138 } else if (engine->config->group) {
139 ods_log_verbose("[%s] drop privileges to group %s", engine_str,
140 engine->config->group);
141 }
142 if (engine->config->chroot) {
143 ods_log_verbose("[%s] chroot to %s", engine_str,
144 engine->config->chroot);
145 }
146 status = privdrop(engine->config->username, engine->config->group,
147 engine->config->chroot, &uid, &gid);
148 engine->uid = uid;
149 engine->gid = gid;
150 privclose(engine->config->username, engine->config->group);
151 return status;
152}
153
158static void
159engine_create_workers(engine_type* engine)
160{
161 char* name;
162 int i = 0;
163 ods_log_assert(engine);
164 ods_log_assert(engine->config);
165 engine->workers = (worker_type**) malloc(
166 (size_t)engine->config->num_worker_threads * sizeof(worker_type*));
167 for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
168 asprintf(&name, "worker[%d]", i+1);
169 engine->workers[i] = worker_create(name, engine->taskq);
170 }
171}
172
173void
175{
176 size_t i = 0;
177
178 ods_log_assert(engine);
179 ods_log_assert(engine->config);
180 ods_log_debug("[%s] start workers", engine_str);
181 for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
182 engine->workers[i]->need_to_exit = 0;
183 engine->workers[i]->context = get_database_connection(engine);
184 if (!engine->workers[i]->context) {
185 ods_log_crit("Failed to start worker, could not connect to database");
186 } else {
187 janitor_thread_create(&engine->workers[i]->thread_id, workerthreadclass, (janitor_runfn_t)worker_start, engine->workers[i]);
188 }
189 }
190}
191
192void
194{
195 int i = 0;
196
197 ods_log_assert(engine);
198 ods_log_assert(engine->config);
199 ods_log_debug("[%s] stop workers", engine_str);
200 /* tell them to exit and wake up sleepyheads */
201 for (i=0; i < engine->config->num_worker_threads; i++) {
202 engine->workers[i]->need_to_exit = 1;
203 }
204 engine_wakeup_workers(engine);
205 /* head count */
206 for (i=0; i < engine->config->num_worker_threads; i++) {
207 ods_log_debug("[%s] join worker %i", engine_str, i+1);
208 janitor_thread_join(engine->workers[i]->thread_id);
209 db_connection_free(engine->workers[i]->context);
210 }
211}
212
217void
219{
220 ods_log_assert(engine);
221 ods_log_debug("[%s] wake up workers", engine_str);
222 schedule_release_all(engine->taskq);
223}
224
227{
228 db_connection_t* dbconn;
229
230 if (!(dbconn = db_connection_new())
232 || db_connection_setup(dbconn)
233 || db_connection_connect(dbconn))
234 {
235 db_connection_free(dbconn);
236 ods_log_crit("database connection failed");
237 return NULL;
238 }
239 return dbconn;
240}
241
242/*
243 * Try to open a connection to the database and close it again.
244 * \param dbcfg_list, database configuration list
245 * \return 0 on success, 1 on failure.
246 */
247static int
248probe_database(engine_type* engine)
249{
250 db_connection_t *conn;
251 int version;
252
253 conn = get_database_connection(engine);
254 if (!conn) return 1;
255 version = database_version_get_version(conn);
256 db_connection_free(conn);
257 return !version;
258}
259
260/*
261 * Prepare for database connections and store dbcfg_list in engine
262 * if successfull the counterpart desetup_database() must be called
263 * when quitting the daemon.
264 * \param engine engine config where configuration list is stored
265 * \return 0 on succes, 1 on failure
266 */
267static int
268setup_database(engine_type* engine)
269{
270 db_configuration_t* dbcfg;
271
272 if (!(engine->dbcfg_list = db_configuration_list_new())) {
273 fprintf(stderr, "db_configuraiton_list_new failed\n");
274 return 1;
275 }
277 if (!(dbcfg = db_configuration_new())
278 || db_configuration_set_name(dbcfg, "backend")
279 || db_configuration_set_value(dbcfg, "sqlite")
280 || db_configuration_list_add(engine->dbcfg_list, dbcfg))
281 {
284 engine->dbcfg_list = NULL;
285 fprintf(stderr, "setup configuration backend failed\n");
286 return 1;
287 }
288 if (!(dbcfg = db_configuration_new())
289 || db_configuration_set_name(dbcfg, "file")
291 || db_configuration_list_add(engine->dbcfg_list, dbcfg))
292 {
295 engine->dbcfg_list = NULL;
296 fprintf(stderr, "setup configuration file failed\n");
297 return 1;
298 }
299 dbcfg = NULL;
300 }
301 else if (engine->config->db_type == ENFORCER_DATABASE_TYPE_MYSQL) {
302 if (!(dbcfg = db_configuration_new())
303 || db_configuration_set_name(dbcfg, "backend")
304 || db_configuration_set_value(dbcfg, "mysql")
305 || db_configuration_list_add(engine->dbcfg_list, dbcfg))
306 {
309 engine->dbcfg_list = NULL;
310 fprintf(stderr, "setup configuration backend failed\n");
311 return 1;
312 }
313 if (!(dbcfg = db_configuration_new())
314 || db_configuration_set_name(dbcfg, "host")
315 || db_configuration_set_value(dbcfg, engine->config->db_host)
316 || db_configuration_list_add(engine->dbcfg_list, dbcfg))
317 {
320 engine->dbcfg_list = NULL;
321 fprintf(stderr, "setup configuration file failed\n");
322 return 1;
323 }
324 dbcfg = NULL;
325 if (engine->config->db_port) {
326 char str[32];
327 if (snprintf(&str[0], sizeof(str), "%d", engine->config->db_port) >= (int)sizeof(str)) {
329 engine->dbcfg_list = NULL;
330 fprintf(stderr, "setup configuration file failed\n");
331 return 1;
332 }
333 if (!(dbcfg = db_configuration_new())
334 || db_configuration_set_name(dbcfg, "port")
335 || db_configuration_set_value(dbcfg, str)
336 || db_configuration_list_add(engine->dbcfg_list, dbcfg))
337 {
340 engine->dbcfg_list = NULL;
341 fprintf(stderr, "setup configuration file failed\n");
342 return 1;
343 }
344 dbcfg = NULL;
345 }
346 if (!(dbcfg = db_configuration_new())
347 || db_configuration_set_name(dbcfg, "user")
349 || db_configuration_list_add(engine->dbcfg_list, dbcfg))
350 {
353 engine->dbcfg_list = NULL;
354 fprintf(stderr, "setup configuration file failed\n");
355 return 1;
356 }
357 dbcfg = NULL;
358 if (!(dbcfg = db_configuration_new())
359 || db_configuration_set_name(dbcfg, "pass")
361 || db_configuration_list_add(engine->dbcfg_list, dbcfg))
362 {
365 engine->dbcfg_list = NULL;
366 fprintf(stderr, "setup configuration file failed\n");
367 return 1;
368 }
369 dbcfg = NULL;
370 if (!(dbcfg = db_configuration_new())
371 || db_configuration_set_name(dbcfg, "db")
373 || db_configuration_list_add(engine->dbcfg_list, dbcfg))
374 {
377 engine->dbcfg_list = NULL;
378 fprintf(stderr, "setup configuration file failed\n");
379 return 1;
380 }
381 dbcfg = NULL;
382 }
383 else {
384 return 1;
385 }
386 return 0;
387}
388
389/*
390 * destroy database configuration. Call only after all connections
391 * are closed.
392 * \param engine engine config where configuration list is stored
393 */
394static void
395desetup_database(engine_type* engine)
396{
398 engine->dbcfg_list = NULL;
399}
400
401static void
402signal_handler(sig_atomic_t sig)
403{
404 switch (sig) {
405 case SIGHUP:
406 if (engine) {
407 engine->need_to_reload = 1;
408 pthread_mutex_lock(&engine->signal_lock);
409 pthread_cond_signal(&engine->signal_cond);
410 pthread_mutex_unlock(&engine->signal_lock);
411 }
412 break;
413 case SIGINT:
414 case SIGTERM:
415 if (engine) {
416 engine->need_to_exit = 1;
417 pthread_mutex_lock(&engine->signal_lock);
418 pthread_cond_signal(&engine->signal_cond);
419 pthread_mutex_unlock(&engine->signal_lock);
420 }
421 break;
422 default:
423 break;
424 }
425}
426
431ods_status
433{
434 int fd, error;
435 int pipefd[2];
436 char buff = '\0';
437
438 ods_log_debug("[%s] enforcer setup", engine_str);
439
440 engine->pid = getpid(); /* We need to do this again after fork() */
441
442 if (!util_pidfile_avail(engine->config->pid_filename)) {
443 ods_log_error("[%s] Pidfile exists and process with PID is running", engine_str);
444 return ODS_STATUS_WRITE_PIDFILE_ERR;
445 }
446 /* setup database configuration */
447 if (setup_database(engine)) return ODS_STATUS_DB_ERR;
448 /* Probe the database, can we connect to it? */
449 if (probe_database(engine)) {
450 ods_log_crit("Could not connect to database or database not set"
451 " up properly.");
452 return ODS_STATUS_DB_ERR;
453 }
454
455 /* create command handler (before chowning socket file) */
456 engine->cmdhandler = cmdhandler_create(engine->config->clisock_filename, enforcercommands, engine, (void*(*)(void*)) &get_database_connection, (void(*)(void*))&db_connection_free);
457 if (!engine->cmdhandler) {
458 ods_log_error("[%s] create command handler to %s failed",
459 engine_str, engine->config->clisock_filename);
460 return ODS_STATUS_CMDHANDLER_ERR;
461 }
462
463 if(pipe(pipefd)) {
464 ods_log_error("[%s] unable to pipe: %s", engine_str, strerror(errno));
465 return ODS_STATUS_PIPE_ERR;
466 }
467
468 if (!engine->init_setup_done) {
469 /* privdrop */
470 engine->uid = privuid(engine->config->username);
471 engine->gid = privgid(engine->config->group);
472 /* TODO: does piddir exists? */
473 /* remove the chown stuff: piddir? */
474 ods_chown(engine->config->pid_filename, engine->uid, engine->gid, 1);
475 ods_chown(engine->config->clisock_filename, engine->uid, engine->gid, 0);
476 ods_chown(engine->config->working_dir, engine->uid, engine->gid, 0);
477 if (engine->config->log_filename && !engine->config->use_syslog) {
478 ods_chown(engine->config->log_filename, engine->uid, engine->gid, 0);
479 }
480 if (engine->config->working_dir &&
481 chdir(engine->config->working_dir) != 0) {
482 ods_log_error("[%s] chdir to %s failed: %s", engine_str,
483 engine->config->working_dir, strerror(errno));
484 return ODS_STATUS_CHDIR_ERR;
485 }
486 if (engine_privdrop(engine) != ODS_STATUS_OK) {
487 ods_log_error("[%s] unable to drop privileges", engine_str);
488 return ODS_STATUS_PRIVDROP_ERR;
489 }
490
491 /* daemonize */
492 if (engine->daemonize) {
493 switch (fork()) {
494 case -1: /* error */
495 ods_log_error("[%s] unable to fork daemon: %s",
496 engine_str, strerror(errno));
497 return ODS_STATUS_FORK_ERR;
498 case 0: /* child */
499 if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
500 (void)dup2(fd, STDIN_FILENO);
501 (void)dup2(fd, STDOUT_FILENO);
502 (void)dup2(fd, STDERR_FILENO);
503 if (fd > 2) (void)close(fd);
504 }
505 close(pipefd[0]);
506 break;
507 default: /* parent */
508 close(pipefd[1]);
509 /* Print messages the child may have send us. */
510 while (read(pipefd[0], &buff, 1) != -1) {
511 if (buff <= 1) break;
512 printf("%c", buff);
513 }
514 close(pipefd[0]);
515 if (buff != '\1') {
516 ods_log_error("[%s] fail to start enforcerd completely", engine_str);
517 exit(1);
518 }
519 ods_log_debug("[%s] enforcerd started successfully", engine_str);
520 exit(0);
521 }
522 if (setsid() == -1) {
523 ods_log_error("[%s] unable to setsid daemon (%s)",
524 engine_str, strerror(errno));
525 const char *err = "unable to setsid daemon: ";
526 ods_writen(pipefd[1], err, strlen(err));
527 ods_writeln(pipefd[1], strerror(errno));
528 write(pipefd[1], "\0", 1);
529 close(pipefd[1]);
530 return ODS_STATUS_SETSID_ERR;
531 }
532 }
533 }
534 engine->init_setup_done = 1;
535
536 engine->pid = getpid();
537 ods_log_info("[%s] running as pid %lu", engine_str,
538 (unsigned long) engine->pid);
539
540 /* create workers */
541 engine_create_workers(engine);
542
543 /* write pidfile */
544 if (util_write_pidfile(engine->config->pid_filename, engine->pid) == -1) {
545 hsm_close();
546 ods_log_error("[%s] unable to write pid file", engine_str);
547 if (engine->daemonize) {
548 ods_writeln(pipefd[1], "unable to write pid file");
549 write(pipefd[1], "\0", 1);
550 close(pipefd[1]);
551 }
552 return ODS_STATUS_WRITE_PIDFILE_ERR;
553 }
554 ods_log_info("[%s] enforcer started", engine_str);
555 error = hsm_open2(engine->config->repositories, hsm_prompt_pin);
556 if (error != HSM_OK) {
557 char* errorstr = hsm_get_error(NULL);
558 if (!errorstr)
559 (void)asprintf(&errorstr, "error opening libhsm (errno %i)", error);
560 if (errorstr)
561 ods_log_error("[%s] %s", engine_str, errorstr);
562 if (engine->daemonize) {
563 if (errorstr) ods_writeln(pipefd[1], errorstr);
564 write(pipefd[1], "\0", 1);
565 close(pipefd[1]);
566 }
567 free(errorstr);
568 return ODS_STATUS_HSM_ERR;
569 }
570 engine->need_to_reload = 0;
571 engine_start_cmdhandler(engine);
572
573 write(pipefd[1], "\1", 1);
574 close(pipefd[1]);
575 if (!engine->daemonize) close(pipefd[0]);
576 engine->daemonize = 0; /* don't fork again on reload */
577 return ODS_STATUS_OK;
578}
579
584void
586{
587 size_t i = 0;
588
589 if (!engine) return;
590 if (engine->config) {
591 if (engine->config->pid_filename) {
592 (void)unlink(engine->config->pid_filename);
593 }
594 if (engine->config->clisock_filename) {
595 (void)unlink(engine->config->clisock_filename);
596 }
597 }
598 if (engine->workers && engine->config) {
599 for (i=0; i < (size_t) engine->config->num_worker_threads; i++) {
600 worker_cleanup(engine->workers[i]);
601 }
602 free(engine->workers);
603 engine->workers = NULL;
604 }
605 if (engine->cmdhandler) {
606 cmdhandler_cleanup(engine->cmdhandler);
607 engine->cmdhandler = NULL;
608 }
609 desetup_database(engine);
610}
611
612void
613engine_init(engine_type* engine, int daemonize)
614{
615 struct sigaction action;
616
617 engine->config = NULL;
618 engine->workers = NULL;
619 engine->cmdhandler = NULL;
620 engine->init_setup_done = 0;
621 engine->pid = getpid(); /* We need to do this again after fork() */
622 engine->uid = -1;
623 engine->gid = -1;
624 engine->need_to_exit = 0;
625 engine->need_to_reload = 0;
626 engine->daemonize = daemonize;
627 /* catch signals */
628 action.sa_handler = (void (*)(int))signal_handler;
629 sigfillset(&action.sa_mask);
630 action.sa_flags = 0;
631 sigaction(SIGHUP, &action, NULL);
632 sigaction(SIGTERM, &action, NULL);
633 sigaction(SIGINT, &action, NULL);
634 engine->dbcfg_list = NULL;
635 action.sa_handler = SIG_IGN;
636 sigaction(SIGPIPE, &action, NULL);
637}
638
643int
644engine_run(engine_type* engine, start_cb_t start, int single_run)
645{
646 int error;
647 ods_log_assert(engine);
648
649 engine_start_workers(engine);
650
651 /* call the external start callback function */
652 start(engine);
653
654 while (!engine->need_to_exit && !engine->need_to_reload) {
655 if (single_run) {
656 engine->need_to_exit = 1;
657 /* FIXME: all tasks need to terminate, then set need_to_exit to 1 */
658 }
659
660 /* We must use locking here to avoid race conditions. We want
661 * to sleep indefinitely and want to wake up on signal. This
662 * is to make sure we never mis the signal. */
663 pthread_mutex_lock(&engine->signal_lock);
664 if (!engine->need_to_exit && !engine->need_to_reload && !single_run) {
665 /* TODO: this silly. We should be handling the commandhandler
666 * connections. No reason to spawn that as a thread.
667 * Also it would be easier to wake up the command hander
668 * as signals will reach it if it is the main thread! */
669 ods_log_debug("[%s] taking a break", engine_str);
670 pthread_cond_wait(&engine->signal_cond, &engine->signal_lock);
671 }
672 pthread_mutex_unlock(&engine->signal_lock);
673 }
674 ods_log_debug("[%s] enforcer halted", engine_str);
675 engine_stop_workers(engine);
676 cmdhandler_stop(engine->cmdhandler);
677 schedule_purge(engine->taskq); /* Remove old tasks in queue */
678 hsm_close();
679 return 0;
680}
@ ENFORCER_DATABASE_TYPE_MYSQL
Definition: cfg.h:46
@ ENFORCER_DATABASE_TYPE_SQLITE
Definition: cfg.h:45
int database_version_get_version(db_connection_t *connection)
db_configuration_t * db_configuration_new(void)
db_configuration_list_t * db_configuration_list_new(void)
void db_configuration_free(db_configuration_t *configuration)
int db_configuration_set_name(db_configuration_t *configuration, const char *name)
int db_configuration_list_add(db_configuration_list_t *configuration_list, db_configuration_t *configuration)
int db_configuration_set_value(db_configuration_t *configuration, const char *value)
void db_configuration_list_free(db_configuration_list_t *configuration_list)
int db_connection_connect(const db_connection_t *connection)
Definition: db_connection.c:88
db_connection_t * db_connection_new(void)
Definition: db_connection.c:38
int db_connection_setup(db_connection_t *connection)
Definition: db_connection.c:66
void db_connection_free(db_connection_t *connection)
Definition: db_connection.c:45
int db_connection_set_configuration_list(db_connection_t *connection, const db_configuration_list_t *configuration_list)
Definition: db_connection.c:54
struct cmd_func_block ** enforcercommands
void engine_teardown(engine_type *engine)
Definition: engine.c:585
void engine_init(engine_type *engine, int daemonize)
Definition: engine.c:613
void engine_dealloc(engine_type *engine)
Definition: engine.c:97
engine_type * engine_alloc(void)
Definition: engine.c:79
void engine_wakeup_workers(engine_type *engine)
Definition: engine.c:218
void engine_start_workers(engine_type *engine)
Definition: engine.c:174
int engine_run(engine_type *engine, start_cb_t start, int single_run)
Definition: engine.c:644
void engine_stop_workers(engine_type *engine)
Definition: engine.c:193
db_connection_t * get_database_connection(engine_type *engine)
Definition: engine.c:226
ods_status engine_setup()
Definition: engine.c:432
void(* start_cb_t)(engine_type *engine)
Definition: engine.h:98
void hsm_key_factory_deinit(void)
schedule_type * taskq
Definition: engine.h:60
pthread_mutex_t signal_lock
Definition: engine.h:65
pid_t pid
Definition: engine.h:50
gid_t gid
Definition: engine.h:52
cmdhandler_type * cmdhandler
Definition: engine.h:61
pthread_cond_t signal_cond
Definition: engine.h:64
int need_to_reload
Definition: engine.h:56
int daemonize
Definition: engine.h:54
uid_t uid
Definition: engine.h:51
int init_setup_done
Definition: engine.h:57
db_configuration_list_t * dbcfg_list
Definition: engine.h:67
int need_to_exit
Definition: engine.h:55
worker_type ** workers
Definition: engine.h:59
engineconfig_type * config
Definition: engine.h:48
const char * chroot
Definition: cfg.h:67
const char * datastore
Definition: cfg.h:68
const char * db_password
Definition: cfg.h:71
const char * group
Definition: cfg.h:66
engineconfig_database_type_t db_type
Definition: cfg.h:80
const char * clisock_filename
Definition: cfg.h:63
const char * working_dir
Definition: cfg.h:64
hsm_repository_t * repositories
Definition: cfg.h:79
int num_worker_threads
Definition: cfg.h:73
int use_syslog
Definition: cfg.h:72
const char * pid_filename
Definition: cfg.h:60
const char * log_filename
Definition: cfg.h:59
const char * db_username
Definition: cfg.h:70
const char * db_host
Definition: cfg.h:69
const char * username
Definition: cfg.h:65