]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/filed.c
- Move Python variables from Job to Bacula. They are
[bacula/bacula] / bacula / src / filed / filed.c
1 /*
2  *  Bacula File Daemon
3  *
4  *    Kern Sibbald, March MM
5  *
6  *   Version $Id$
7  *
8  */
9 /*
10    Copyright (C) 2000-2005 Kern Sibbald
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License
14    version 2 as amended with additional clauses defined in the
15    file LICENSE in the main source directory.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
20    the file LICENSE for additional details.
21
22  */
23
24 #include "bacula.h"
25 #include "filed.h"
26
27 /* Imported Functions */
28 extern void *handle_client_request(void *dir_sock);
29
30 /* Imported Variables */
31 extern time_t watchdog_sleep_time;
32
33 /* Forward referenced functions */
34 void terminate_filed(int sig);
35 static int check_resources();
36
37 /* Exported variables */
38 CLIENT *me;                           /* my resource */
39 char OK_msg[]   = "2000 OK\n";
40 char TERM_msg[] = "2999 Terminate\n";
41 bool no_signals = false;
42
43 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
44 const int win32_client = 1;
45 #else
46 const int win32_client = 0;
47 #endif
48
49
50 #define CONFIG_FILE "./bacula-fd.conf" /* default config file */
51
52 char *configfile = NULL;
53 static bool foreground = false;
54 static bool inetd_request = false;
55 static workq_t dir_workq;             /* queue of work from Director */
56 static pthread_t server_tid;
57
58
59 static void usage()
60 {
61    Pmsg0(-1, _(
62 "Copyright (C) 2000-2005 Kern Sibbald\n"
63 "\nVersion: " VERSION " (" BDATE ")\n\n"
64 "Usage: bacula-fd [-f -s] [-c config_file] [-d debug_level]\n"
65 "        -c <file>   use <file> as configuration file\n"
66 "        -dnn        set debug level to nn\n"
67 "        -f          run in foreground (for debugging)\n"
68 "        -g          groupid\n"
69 "        -i          inetd request\n"
70 "        -s          no signals (for debugging)\n"
71 "        -t          test configuration file and exit\n"
72 "        -u          userid\n"
73 "        -v          verbose user messages\n"
74 "        -?          print this message.\n"
75 "\n"));
76    exit(1);
77 }
78
79
80 /*********************************************************************
81  *
82  *  Main Bacula Unix Client Program
83  *
84  */
85 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
86 #define main BaculaMain
87 #endif
88
89 int main (int argc, char *argv[])
90 {
91    int ch;
92    bool test_config = false;
93    char *uid = NULL;
94    char *gid = NULL;
95
96    init_stack_dump();
97    my_name_is(argc, argv, "bacula-fd");
98    textdomain("bacula");
99    init_msg(NULL, NULL);
100    daemon_start_time = time(NULL);
101
102    while ((ch = getopt(argc, argv, "c:d:fg:istu:v?")) != -1) {
103       switch (ch) {
104       case 'c':                    /* configuration file */
105          if (configfile != NULL) {
106             free(configfile);
107          }
108          configfile = bstrdup(optarg);
109          break;
110
111       case 'd':                    /* debug level */
112          debug_level = atoi(optarg);
113          if (debug_level <= 0) {
114             debug_level = 1;
115          }
116          break;
117
118       case 'f':                    /* run in foreground */
119          foreground = true;
120          break;
121
122       case 'g':                    /* set group */
123          gid = optarg;
124          break;
125
126       case 'i':
127          inetd_request = true;
128          break;
129       case 's':
130          no_signals = true;
131          break;
132
133       case 't':
134          test_config = true;
135          break;
136
137       case 'u':                    /* set userid */
138          uid = optarg;
139          break;
140
141       case 'v':                    /* verbose */
142          verbose++;
143          break;
144
145       case '?':
146       default:
147          usage();
148
149       }
150    }
151    argc -= optind;
152    argv += optind;
153
154    if (argc) {
155       if (configfile != NULL)
156          free(configfile);
157       configfile = bstrdup(*argv);
158       argc--;
159       argv++;
160    }
161    if (argc) {
162       usage();
163    }
164
165    server_tid = pthread_self();
166    if (!no_signals) {
167       init_signals(terminate_filed);
168    } else {
169       /* This reduces the number of signals facilitating debugging */
170       watchdog_sleep_time = 120;      /* long timeout for debugging */
171    }
172
173    if (configfile == NULL) {
174       configfile = bstrdup(CONFIG_FILE);
175    }
176
177    parse_config(configfile);
178
179    if (init_tls() != 0) {
180       Emsg0(M_ERROR, 0, _("TLS library initialization failed.\n"));
181       terminate_filed(1);
182    }
183
184    if (!check_resources()) {
185       Emsg1(M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile);
186       terminate_filed(1);
187    }
188
189    set_working_directory(me->working_directory);
190
191    if (test_config) {
192       terminate_filed(0);
193    }
194
195    if (!foreground &&!inetd_request) {
196       daemon_start();
197       init_stack_dump();              /* set new pid */
198    }
199
200    /* Maximum 1 daemon at a time */
201    create_pid_file(me->pid_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
202    read_state_file(me->working_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
203
204    drop(uid, gid);
205
206 #ifdef BOMB
207    me += 1000000;
208 #endif
209
210    init_python_interpreter(me->hdr.name, me->scripts_directory, "FDStartUp");
211
212    set_thread_concurrency(10);
213
214    if (!no_signals) {
215       start_watchdog();               /* start watchdog thread */
216       init_jcr_subsystem();           /* start JCR watchdogs etc. */
217    }
218    server_tid = pthread_self();
219
220    if (inetd_request) {
221       /* Socket is on fd 0 */
222       struct sockaddr client_addr;
223       int port = -1;
224       socklen_t client_addr_len = sizeof(client_addr);
225       if (getsockname(0, &client_addr, &client_addr_len) == 0) {
226                 /* MA BUG 6 remove ifdefs */
227                 port = sockaddr_get_port_net_order(&client_addr);
228       }
229       BSOCK *bs = init_bsock(NULL, 0, "client", "unknown client", port, &client_addr);
230       handle_client_request((void *)bs);
231    } else {
232       /* Become server, and handle requests */
233       IPADDR *p;
234       foreach_dlist(p, me->FDaddrs) {
235          Dmsg1(10, "filed: listening on port %d\n", p->get_port_host_order());
236       }
237       bnet_thread_server(me->FDaddrs, me->MaxConcurrentJobs, &dir_workq, handle_client_request);
238    }
239
240    terminate_filed(0);
241    exit(0);                           /* should never get here */
242 }
243
244 void terminate_filed(int sig)
245 {
246    bnet_stop_thread_server(server_tid);
247    generate_daemon_event(NULL, "Exit");
248    write_state_file(me->working_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
249    delete_pid_file(me->pid_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
250
251    if (configfile != NULL) {
252       free(configfile);
253    }
254    if (debug_level > 5) {
255       print_memory_pool_stats();
256    }
257    free_config_resources();
258    term_msg();
259    stop_watchdog();
260    cleanup_tls();
261    close_memory_pool();               /* release free memory in pool */
262    sm_dump(false);                    /* dump orphaned buffers */
263    exit(sig);
264 }
265
266 /*
267 * Make a quick check to see that we have all the
268 * resources needed.
269 */
270 static int check_resources()
271 {
272    bool OK = true;
273    DIRRES *director;
274
275    LockRes();
276
277    me = (CLIENT *)GetNextRes(R_CLIENT, NULL);
278    if (!me) {
279       Emsg1(M_FATAL, 0, _("No File daemon resource defined in %s\n"
280             "Without that I don't know who I am :-(\n"), configfile);
281       OK = false;
282    } else {
283       if (GetNextRes(R_CLIENT, (RES *) me) != NULL) {
284          Emsg1(M_FATAL, 0, _("Only one Client resource permitted in %s\n"),
285               configfile);
286          OK = false;
287       }
288       my_name_is(0, NULL, me->hdr.name);
289       if (!me->messages) {
290          me->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
291          if (!me->messages) {
292              Emsg1(M_FATAL, 0, _("No Messages resource defined in %s\n"), configfile);
293              OK = false;
294          }
295       }
296       /* tls_require implies tls_enable */
297       if (me->tls_require) {
298 #ifndef HAVE_TLS
299          Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
300          OK = false;
301 #else
302          me->tls_enable = true;
303 #endif
304       }
305
306       if ((!me->tls_ca_certfile && !me->tls_ca_certdir) && me->tls_enable) {
307          Emsg1(M_FATAL, 0, _("Neither \"TLS CA Certificate\""
308             " or \"TLS CA Certificate Dir\" are defined for File daemon in %s.\n"),
309                             configfile);
310         OK = false;
311       }
312
313       /* If everything is well, attempt to initialize our per-resource TLS context */
314       if (OK && (me->tls_enable || me->tls_require)) {
315          /* Initialize TLS context:
316           * Args: CA certfile, CA certdir, Certfile, Keyfile,
317           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
318          me->tls_ctx = new_tls_context(me->tls_ca_certfile,
319             me->tls_ca_certdir, me->tls_certfile, me->tls_keyfile,
320             NULL, NULL, NULL, true);
321
322          if (!me->tls_ctx) { 
323             Emsg2(M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
324                                 me->hdr.name, configfile);
325             OK = false;
326          }
327       }
328    }
329
330
331    /* Verify that a director record exists */
332    LockRes();
333    director = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
334    UnlockRes();
335    if (!director) {
336       Emsg1(M_FATAL, 0, _("No Director resource defined in %s\n"),
337             configfile);
338       OK = false;
339    }
340
341    foreach_res(director, R_DIRECTOR) { 
342       /* tls_require implies tls_enable */
343       if (director->tls_require) {
344 #ifndef HAVE_TLS
345          Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
346          OK = false;
347          continue;
348 #else
349          director->tls_enable = true;
350 #endif
351       }
352
353       if (!director->tls_certfile && director->tls_enable) {
354          Emsg2(M_FATAL, 0, _("\"TLS Certificate\" file not defined for Director \"%s\" in %s.\n"),
355                director->hdr.name, configfile);
356          OK = false;
357       }
358
359       if (!director->tls_keyfile && director->tls_enable) {
360          Emsg2(M_FATAL, 0, _("\"TLS Key\" file not defined for Director \"%s\" in %s.\n"),
361                director->hdr.name, configfile);
362          OK = false;
363       }
364
365       if ((!director->tls_ca_certfile && !director->tls_ca_certdir) && director->tls_enable && director->tls_verify_peer) {
366          Emsg2(M_FATAL, 0, _("Neither \"TLS CA Certificate\""
367                              " or \"TLS CA Certificate Dir\" are defined for Director \"%s\" in %s."
368                              " At least one CA certificate store is required"
369                              " when using \"TLS Verify Peer\".\n"),
370                              director->hdr.name, configfile);
371          OK = false;
372       }
373
374       /* If everything is well, attempt to initialize our per-resource TLS context */
375       if (OK && (director->tls_enable || director->tls_require)) {
376          /* Initialize TLS context:
377           * Args: CA certfile, CA certdir, Certfile, Keyfile,
378           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
379          director->tls_ctx = new_tls_context(director->tls_ca_certfile,
380             director->tls_ca_certdir, director->tls_certfile,
381             director->tls_keyfile, NULL, NULL, director->tls_dhfile,
382             director->tls_verify_peer);
383
384          if (!director->tls_ctx) { 
385             Emsg2(M_FATAL, 0, _("Failed to initialize TLS context for Director \"%s\" in %s.\n"),
386                                 director->hdr.name, configfile);
387             OK = false;
388          }
389       }
390    }
391
392    UnlockRes();
393
394    if (OK) {
395       close_msg(NULL);                /* close temp message handler */
396       init_msg(NULL, me->messages);   /* open user specified message handler */
397    }
398
399    return OK;
400 }