]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/console/console_conf.c
ebl update debug message (last time) :)
[bacula/bacula] / bacula / src / console / console_conf.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation plus additions
11    that are listed in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of John Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *   Main configuration file parser for Bacula User Agent
30  *    some parts may be split into separate files such as
31  *    the schedule configuration (sch_config.c).
32  *
33  *   Note, the configuration file parser consists of three parts
34  *
35  *   1. The generic lexical scanner in lib/lex.c and lib/lex.h
36  *
37  *   2. The generic config  scanner in lib/parse_config.c and
38  *      lib/parse_config.h.
39  *      These files contain the parser code, some utility
40  *      routines, and the common store routines (name, int,
41  *      string).
42  *
43  *   3. The daemon specific file, which contains the Resource
44  *      definitions as well as any specific store routines
45  *      for the resource records.
46  *
47  *     Kern Sibbald, January MM, September MM
48  */
49
50 #include "bacula.h"
51 #include "console_conf.h"
52
53 /* Define the first and last resource ID record
54  * types. Note, these should be unique for each
55  * daemon though not a requirement.
56  */
57 int r_first = R_FIRST;
58 int r_last  = R_LAST;
59 static RES *sres_head[R_LAST - R_FIRST + 1];
60 RES **res_head = sres_head;
61
62 /* Forward referenced subroutines */
63
64
65 /* We build the current resource here as we are
66  * scanning the resource configuration definition,
67  * then move it to allocated memory when the resource
68  * scan is complete.
69  */
70 #if defined(_MSC_VER)
71 extern "C" { // work around visual compiler mangling variables
72     URES res_all;
73 }
74 #else
75 URES res_all;
76 #endif
77 int  res_all_size = sizeof(res_all);
78
79 /* Definition of records permitted within each
80  * resource with the routine to process the record
81  * information.
82  */
83
84 /*  Console "globals" */
85 static RES_ITEM cons_items[] = {
86    {"name",           store_name,     ITEM(res_cons.hdr.name), 0, ITEM_REQUIRED, 0},
87    {"description",    store_str,      ITEM(res_cons.hdr.desc), 0, 0, 0},
88    {"rcfile",         store_dir,      ITEM(res_cons.rc_file), 0, 0, 0},
89    {"historyfile",    store_dir,      ITEM(res_cons.hist_file), 0, 0, 0},
90    {"password",       store_password, ITEM(res_cons.password), 0, ITEM_REQUIRED, 0},
91    {"tlsenable",      store_bit,     ITEM(res_cons.tls_enable), 1, 0, 0},
92    {"tlsrequire",     store_bit,     ITEM(res_cons.tls_require), 1, 0, 0},
93    {"tlscacertificatefile", store_dir, ITEM(res_cons.tls_ca_certfile), 0, 0, 0},
94    {"tlscacertificatedir", store_dir,  ITEM(res_cons.tls_ca_certdir), 0, 0, 0},
95    {"tlscertificate", store_dir,       ITEM(res_cons.tls_certfile), 0, 0, 0},
96    {"tlskey",         store_dir,       ITEM(res_cons.tls_keyfile), 0, 0, 0},
97    {"director",       store_str,       ITEM(res_cons.director), 0, 0, 0},
98    {"heartbeatinterval", store_time, ITEM(res_cons.heartbeat_interval), 0, ITEM_DEFAULT, 0},
99    {NULL, NULL, {0}, 0, 0, 0}
100 };
101
102
103 /*  Director's that we can contact */
104 static RES_ITEM dir_items[] = {
105    {"name",           store_name,      ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0},
106    {"description",    store_str,       ITEM(res_dir.hdr.desc), 0, 0, 0},
107    {"dirport",        store_int,       ITEM(res_dir.DIRport),  0, ITEM_DEFAULT, 9101},
108    {"address",        store_str,       ITEM(res_dir.address),  0, 0, 0},
109    {"password",       store_password,  ITEM(res_dir.password), 0, ITEM_REQUIRED, 0},
110    {"tlsenable",      store_bit,     ITEM(res_dir.tls_enable), 1, 0, 0},
111    {"tlsrequire",     store_bit,     ITEM(res_dir.tls_require), 1, 0, 0},
112    {"tlscacertificatefile", store_dir, ITEM(res_dir.tls_ca_certfile), 0, 0, 0},
113    {"tlscacertificatedir", store_dir,  ITEM(res_dir.tls_ca_certdir), 0, 0, 0},
114    {"tlscertificate", store_dir,       ITEM(res_dir.tls_certfile), 0, 0, 0},
115    {"tlskey",         store_dir,       ITEM(res_dir.tls_keyfile), 0, 0, 0},
116    {"heartbeatinterval", store_time, ITEM(res_dir.heartbeat_interval), 0, ITEM_DEFAULT, 0},
117    {NULL, NULL, {0}, 0, 0, 0}
118 };
119
120 /*
121  * This is the master resource definition.
122  * It must have one item for each of the resources.
123  */
124 RES_TABLE resources[] = {
125    {"console",       cons_items,  R_CONSOLE},
126    {"director",      dir_items,   R_DIRECTOR},
127    {NULL,            NULL,        0}
128 };
129
130
131 /* Dump contents of resource */
132 void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fmt, ...), void *sock)
133 {
134    URES *res = (URES *)reshdr;
135    bool recurse = true;
136
137    if (res == NULL) {
138       printf(_("No record for %d %s\n"), type, res_to_str(type));
139       return;
140    }
141    if (type < 0) {                    /* no recursion */
142       type = - type;
143       recurse = false;
144    }
145    switch (type) {
146    case R_CONSOLE:
147       printf(_("Console: name=%s rcfile=%s histfile=%s\n"), reshdr->name,
148              res->res_cons.rc_file, res->res_cons.hist_file);
149       break;
150    case R_DIRECTOR:
151       printf(_("Director: name=%s address=%s DIRport=%d\n"), reshdr->name,
152               res->res_dir.address, res->res_dir.DIRport);
153       break;
154    default:
155       printf(_("Unknown resource type %d\n"), type);
156    }
157    if (recurse && res->res_dir.hdr.next) {
158       dump_resource(type, res->res_dir.hdr.next, sendit, sock);
159    }
160 }
161
162 /*
163  * Free memory of resource.
164  * NB, we don't need to worry about freeing any references
165  * to other resources as they will be freed when that
166  * resource chain is traversed.  Mainly we worry about freeing
167  * allocated strings (names).
168  */
169 void free_resource(RES *sres, int type)
170 {
171    RES *nres;
172    URES *res = (URES *)sres;
173
174    if (res == NULL)
175       return;
176
177    /* common stuff -- free the resource name */
178    nres = (RES *)res->res_dir.hdr.next;
179    if (res->res_dir.hdr.name) {
180       free(res->res_dir.hdr.name);
181    }
182    if (res->res_dir.hdr.desc) {
183       free(res->res_dir.hdr.desc);
184    }
185
186    switch (type) {
187    case R_CONSOLE:
188       if (res->res_cons.rc_file) {
189          free(res->res_cons.rc_file);
190       }
191       if (res->res_cons.hist_file) {
192          free(res->res_cons.hist_file);
193       }
194       if (res->res_cons.tls_ctx) { 
195          free_tls_context(res->res_cons.tls_ctx);
196       }
197       if (res->res_cons.tls_ca_certfile) {
198          free(res->res_cons.tls_ca_certfile);
199       }
200       if (res->res_cons.tls_ca_certdir) {
201          free(res->res_cons.tls_ca_certdir);
202       }
203       if (res->res_cons.tls_certfile) {
204          free(res->res_cons.tls_certfile);
205       }
206       if (res->res_cons.tls_keyfile) {
207          free(res->res_cons.tls_keyfile);
208       }
209       break;
210    case R_DIRECTOR:
211       if (res->res_dir.address) {
212          free(res->res_dir.address);
213       }
214       if (res->res_dir.tls_ctx) { 
215          free_tls_context(res->res_dir.tls_ctx);
216       }
217       if (res->res_dir.tls_ca_certfile) {
218          free(res->res_dir.tls_ca_certfile);
219       }
220       if (res->res_dir.tls_ca_certdir) {
221          free(res->res_dir.tls_ca_certdir);
222       }
223       if (res->res_dir.tls_certfile) {
224          free(res->res_dir.tls_certfile);
225       }
226       if (res->res_dir.tls_keyfile) {
227          free(res->res_dir.tls_keyfile);
228       }
229       break;
230    default:
231       printf(_("Unknown resource type %d\n"), type);
232    }
233    /* Common stuff again -- free the resource, recurse to next one */
234    free(res);
235    if (nres) {
236       free_resource(nres, type);
237    }
238 }
239
240 /* Save the new resource by chaining it into the head list for
241  * the resource. If this is pass 2, we update any resource
242  * pointers (currently only in the Job resource).
243  */
244 void save_resource(int type, RES_ITEM *items, int pass)
245 {
246    URES *res;
247    int rindex = type - r_first;
248    int i, size;
249    int error = 0;
250
251    /*
252     * Ensure that all required items are present
253     */
254    for (i=0; items[i].name; i++) {
255       if (items[i].flags & ITEM_REQUIRED) {
256             if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
257                Emsg2(M_ABORT, 0, _("%s item is required in %s resource, but not found.\n"),
258                  items[i].name, resources[rindex]);
259              }
260       }
261    }
262
263    /* During pass 2, we looked up pointers to all the resources
264     * referrenced in the current resource, , now we
265     * must copy their address from the static record to the allocated
266     * record.
267     */
268    if (pass == 2) {
269       switch (type) {
270          /* Resources not containing a resource */
271          case R_CONSOLE:
272          case R_DIRECTOR:
273             break;
274
275          default:
276             Emsg1(M_ERROR, 0, _("Unknown resource type %d\n"), type);
277             error = 1;
278             break;
279       }
280       /* Note, the resoure name was already saved during pass 1,
281        * so here, we can just release it.
282        */
283       if (res_all.res_dir.hdr.name) {
284          free(res_all.res_dir.hdr.name);
285          res_all.res_dir.hdr.name = NULL;
286       }
287       if (res_all.res_dir.hdr.desc) {
288          free(res_all.res_dir.hdr.desc);
289          res_all.res_dir.hdr.desc = NULL;
290       }
291       return;
292    }
293
294    /* The following code is only executed during pass 1 */
295    switch (type) {
296    case R_CONSOLE:
297       size = sizeof(CONRES);
298       break;
299    case R_DIRECTOR:
300       size = sizeof(DIRRES);
301       break;
302    default:
303       printf(_("Unknown resource type %d\n"), type);
304       error = 1;
305       size = 1;
306       break;
307    }
308    /* Common */
309    if (!error) {
310       res = (URES *)malloc(size);
311       memcpy(res, &res_all, size);
312       if (!res_head[rindex]) {
313          res_head[rindex] = (RES *)res; /* store first entry */
314       } else {
315          RES *next, *last;
316          for (last=next=res_head[rindex]; next; next=next->next) {
317             last = next;
318             if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
319                Emsg2(M_ERROR_TERM, 0,
320                   _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
321                   resources[rindex].name, res->res_dir.hdr.name);
322             }
323          }
324          last->next = (RES *)res;
325          Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
326                res->res_dir.hdr.name);
327       }
328    }
329 }