2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2017 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Main configuration file parser for Bacula Tray Monitor.
22 * Adapted from dird_conf.c
24 * Note, the configuration file parser consists of three parts
26 * 1. The generic lexical scanner in lib/lex.c and lib/lex.h
28 * 2. The generic config scanner in lib/parse_config.c and
30 * These files contain the parser code, some utility
31 * routines, and the common store routines (name, int,
34 * 3. The daemon specific file, which contains the Resource
35 * definitions as well as any specific store routines
36 * for the resource records.
38 * Nicolas Boichat, August MMIV
43 #include "tray_conf.h"
45 worker *worker_start();
46 void worker_stop(worker *);
48 /* Define the first and last resource ID record
49 * types. Note, these should be unique for each
50 * daemon though not a requirement.
52 int32_t r_first = R_FIRST;
53 int32_t r_last = R_LAST;
56 /* We build the current resource here as we are
57 * scanning the resource configuration definition,
58 * then move it to allocated memory when the resource
62 int32_t res_all_size = sizeof(res_all);
65 /* Definition of records permitted within each
66 * resource with the routine to process the record
67 * information. NOTE! quoted names must be in lower case.
72 * name handler value code flags default_value
74 static RES_ITEM mon_items[] = {
75 {"Name", store_name, ITEM(res_monitor.hdr.name), 0, ITEM_REQUIRED, 0},
76 {"Description", store_str, ITEM(res_monitor.hdr.desc), 0, 0, 0},
77 {"requiressl", store_bool, ITEM(res_monitor.require_ssl), 1, ITEM_DEFAULT, 0},
78 {"RefreshInterval", store_time,ITEM(res_monitor.RefreshInterval), 0, ITEM_DEFAULT, 60},
79 {"CommCompression", store_bool, ITEM(res_monitor.comm_compression), 0, ITEM_DEFAULT, true},
80 {"CommandDirectory", store_dir, ITEM(res_monitor.command_dir), 0, 0, 0},
81 {"DisplayAdvancedOptions", store_bool, ITEM(res_monitor.display_advanced_options), 0, 0, 0},
82 {NULL, NULL, {0}, 0, 0, 0}
85 /* Director's that we can contact */
86 static RES_ITEM dir_items[] = {
87 {"Name", store_name, ITEM(res_main.hdr.name), 0, ITEM_REQUIRED, 0},
88 {"Description", store_str, ITEM(res_main.hdr.desc), 0, 0, 0},
89 {"Port", store_pint32, ITEM(res_main.port), 0, ITEM_DEFAULT, 9101},
90 {"Address", store_str, ITEM(res_main.address), 0, ITEM_REQUIRED, 0},
91 {"Password", store_password, ITEM(res_main.password), 0, ITEM_REQUIRED, 0},
92 {"Monitor", store_bool, ITEM(res_main.use_monitor), 0, ITEM_DEFAULT, 0},
93 {"ConnectTimeout", store_time,ITEM(res_main.connect_timeout), 0, ITEM_DEFAULT, 10},
94 {"UseSetIp", store_bool, ITEM(res_main.use_setip), 0, 0, 0},
95 {"TlsEnable", store_bool, ITEM(res_main.tls_enable), 0, 0, 0},
96 {"TlsCaCertificateFile", store_dir, ITEM(res_main.tls_ca_certfile), 0, 0, 0},
97 {"TlsCaCertificateDir", store_dir, ITEM(res_main.tls_ca_certdir), 0, 0, 0},
98 {"TlsCertificate", store_dir, ITEM(res_main.tls_certfile), 0, 0, 0},
99 {"TlsKey", store_dir, ITEM(res_main.tls_keyfile), 0, 0, 0},
101 {NULL, NULL, {0}, 0, 0, 0}
105 * Client or File daemon resource
107 * name handler value code flags default_value
110 static RES_ITEM cli_items[] = {
111 {"Name", store_name, ITEM(res_main.hdr.name), 0, ITEM_REQUIRED, 0},
112 {"Description", store_str, ITEM(res_main.hdr.desc), 0, 0, 0},
113 {"Address", store_str, ITEM(res_main.address), 0, ITEM_REQUIRED, 0},
114 {"Port", store_pint32, ITEM(res_main.port), 0, ITEM_DEFAULT, 9102},
115 {"Password", store_password, ITEM(res_main.password), 0, ITEM_REQUIRED, 0},
116 {"ConnectTimeout", store_time,ITEM(res_main.connect_timeout), 0, ITEM_DEFAULT, 10},
117 {"Remote", store_bool, ITEM(res_main.use_remote), 0, ITEM_DEFAULT, 0},
118 {"Monitor", store_bool, ITEM(res_main.use_monitor), 0, ITEM_DEFAULT, 0},
119 {"TlsEnable", store_bool, ITEM(res_main.tls_enable), 0, 0, 0},
120 {"TlsCaCertificateFile", store_dir, ITEM(res_main.tls_ca_certfile), 0, 0, 0},
121 {"TlsCaCertificateDir", store_dir, ITEM(res_main.tls_ca_certdir), 0, 0, 0},
122 {"TlsCertificate", store_dir, ITEM(res_main.tls_certfile), 0, 0, 0},
123 {"TlsKey", store_dir, ITEM(res_main.tls_keyfile), 0, 0, 0},
124 {NULL, NULL, {0}, 0, 0, 0}
127 /* Storage daemon resource
129 * name handler value code flags default_value
131 static RES_ITEM store_items[] = {
132 {"Name", store_name, ITEM(res_main.hdr.name), 0, ITEM_REQUIRED, 0},
133 {"Description", store_str, ITEM(res_main.hdr.desc), 0, 0, 0},
134 {"Port", store_pint32, ITEM(res_main.port), 0, ITEM_DEFAULT, 9103},
135 {"Address", store_str, ITEM(res_main.address), 0, ITEM_REQUIRED, 0},
136 {"Password", store_password, ITEM(res_main.password), 0, ITEM_REQUIRED, 0},
137 {"ConnectTimeout", store_time,ITEM(res_main.connect_timeout), 0, ITEM_DEFAULT, 10},
138 {"Monitor", store_bool, ITEM(res_main.use_monitor), 0, ITEM_DEFAULT, 0},
139 {"TlsEnable", store_bool, ITEM(res_main.tls_enable), 0, 0, 0},
140 {"TlsCaCertificateFile", store_dir, ITEM(res_main.tls_ca_certfile), 0, 0, 0},
141 {"TlsCaCertificateDir", store_dir, ITEM(res_main.tls_ca_certdir), 0, 0, 0},
142 {"TlsCertificate", store_dir, ITEM(res_main.tls_certfile), 0, 0, 0},
143 {"TlsKey", store_dir, ITEM(res_main.tls_keyfile), 0, 0, 0},
144 {NULL, NULL, {0}, 0, 0, 0}
148 * This is the master resource definition.
149 * It must have one item for each of the resources.
151 * NOTE!!! keep it in the same order as the R_codes
152 * or eliminate all resources[rindex].name
154 * name items rcode res_head
156 RES_TABLE resources[] = {
157 {"monitor", mon_items, R_MONITOR},
158 {"director", dir_items, R_DIRECTOR},
159 {"client", cli_items, R_CLIENT},
160 {"storage", store_items, R_STORAGE},
164 /* Dump contents of resource */
165 void dump_resource(int type, RES *ares, void sendit(void *sock, const char *fmt, ...), void *sock)
168 URES *res = (URES *)ares;
172 sendit(sock, _("No %s resource defined\n"), res_to_str(type));
175 if (type < 0) { /* no recursion */
181 sendit(sock, _("Monitor: name=%s\n"), ares->name);
184 sendit(sock, _("Director: name=%s address=%s port=%d\n"),
185 res->res_main.hdr.name, res->res_main.address, res->res_main.port);
188 sendit(sock, _("Client: name=%s address=%s port=%d\n"),
189 res->res_main.hdr.name, res->res_main.address, res->res_main.port);
192 sendit(sock, _("Storage: name=%s address=%s port=%d\n"),
193 res->res_main.hdr.name, res->res_main.address, res->res_main.port);
196 sendit(sock, _("Unknown resource type %d in dump_resource.\n"), type);
200 next = GetNextRes(0, (RES *)res);
202 dump_resource(type, next, sendit, sock);
208 * Free memory of resource -- called when daemon terminates.
209 * NB, we don't need to worry about freeing any references
210 * to other resources as they will be freed when that
211 * resource chain is traversed. Mainly we worry about freeing
212 * allocated strings (names).
214 void free_resource(RES *sres, int type)
216 URES *res = (URES *)sres;
220 /* common stuff -- free the resource name and description */
221 if (res->res_monitor.hdr.name) {
222 free(res->res_monitor.hdr.name);
224 if (res->res_monitor.hdr.desc) {
225 free(res->res_monitor.hdr.desc);
230 if (res->res_monitor.password) {
231 free(res->res_monitor.password);
233 if (res->res_monitor.command_dir) {
234 free(res->res_monitor.command_dir);
240 delete res->res_main.mutex;
241 free_bsock(res->res_main.bs);
242 if (res->res_main.wrk) {
243 worker_stop(res->res_main.wrk);
244 res->res_main.wrk = NULL;
246 if (res->res_main.address) {
247 free(res->res_main.address);
249 if (res->res_main.tls_ctx) {
250 free_tls_context(res->res_main.tls_ctx);
252 if (res->res_main.tls_ca_certfile) {
253 free(res->res_main.tls_ca_certfile);
255 if (res->res_main.tls_ca_certdir) {
256 free(res->res_main.tls_ca_certdir);
258 if (res->res_main.tls_certfile) {
259 free(res->res_main.tls_certfile);
261 if (res->res_main.tls_keyfile) {
262 free(res->res_main.tls_keyfile);
264 if (res->res_main.jobs) {
265 delete res->res_main.jobs;
267 if (res->res_main.clients) {
268 delete res->res_main.clients;
270 if (res->res_main.filesets) {
271 delete res->res_main.filesets;
273 if (res->res_main.pools) {
274 delete res->res_main.pools;
276 if (res->res_main.storages) {
277 delete res->res_main.storages;
279 if (res->res_main.running_jobs) {
280 delete res->res_main.terminated_jobs;
284 printf(_("Unknown resource type %d in free_resource.\n"), type);
287 /* Common stuff again -- free the resource, recurse to next one */
294 * Save the new resource by chaining it into the head list for
295 * the resource. If this is pass 2, we update any resource
296 * pointers because they may not have been defined until
299 bool save_resource(CONFIG *config, int type, RES_ITEM *items, int pass)
301 int rindex = type - r_first;
306 * Ensure that all required items are present
308 for (i=0; items[i].name; i++) {
309 if (items[i].flags & ITEM_REQUIRED) {
310 if (!bit_is_set(i, res_all.res_monitor.hdr.item_present)) {
311 Mmsg(config->m_errmsg, _("\"%s\" directive is required in \"%s\" resource, but not found.\n"),
312 items[i].name, resources[rindex].name);
316 /* If this triggers, take a look at lib/parse_conf.h */
317 if (i >= MAX_RES_ITEMS) {
318 Mmsg(config->m_errmsg, _("Too many directives in \"%s\" resource\n"), resources[rindex].name);
324 * During pass 2 in each "store" routine, we looked up pointers
325 * to all the resources referrenced in the current resource, now we
326 * must copy their addresses from the static record to the allocated
331 /* Resources not containing a resource */
338 Emsg1(M_ERROR, 0, _("Unknown resource type %d in save_resource.\n"), type);
342 /* Note, the resource name was already saved during pass 1,
343 * so here, we can just release it.
345 if (res_all.res_monitor.hdr.name) {
346 free(res_all.res_monitor.hdr.name);
347 res_all.res_monitor.hdr.name = NULL;
349 if (res_all.res_monitor.hdr.desc) {
350 free(res_all.res_monitor.hdr.desc);
351 res_all.res_monitor.hdr.desc = NULL;
357 * The following code is only executed during pass 1
361 size = sizeof(MONITOR);
366 // We need to initialize the mutex
367 res_all.res_main.mutex = new QMutex();
368 res_all.res_main.wrk = worker_start();
369 size = sizeof(RESMON);
372 printf(_("Unknown resource type %d in save_resource.\n"), type);
379 res_all.res_main.type = type;
380 if (!config->insert_res(rindex, size)) {
387 bool parse_tmon_config(CONFIG *config, const char *configfile, int exit_code)
389 config->init(configfile, error_handler, exit_code,
390 (void *)&res_all, res_all_size,
391 r_first, r_last, resources, &res_head);
392 return config->parse_config();