]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/filed.c
Mark translatable strings in all source files.
[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    Pmsg2(-1, _(
62 "Copyright (C) 2000-2005 Kern Sibbald\n"
63 "\nVersion: %s (%s)\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"), VERSION, BDATE);
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    setlocale(LC_ALL, "");
97    bindtextdomain("bacula", LOCALEDIR);
98    textdomain("bacula");
99
100    init_stack_dump();
101    my_name_is(argc, argv, "bacula-fd");
102    init_msg(NULL, NULL);
103    daemon_start_time = time(NULL);
104
105    while ((ch = getopt(argc, argv, "c:d:fg:istu:v?")) != -1) {
106       switch (ch) {
107       case 'c':                    /* configuration file */
108          if (configfile != NULL) {
109             free(configfile);
110          }
111          configfile = bstrdup(optarg);
112          break;
113
114       case 'd':                    /* debug level */
115          debug_level = atoi(optarg);
116          if (debug_level <= 0) {
117             debug_level = 1;
118          }
119          break;
120
121       case 'f':                    /* run in foreground */
122          foreground = true;
123          break;
124
125       case 'g':                    /* set group */
126          gid = optarg;
127          break;
128
129       case 'i':
130          inetd_request = true;
131          break;
132       case 's':
133          no_signals = true;
134          break;
135
136       case 't':
137          test_config = true;
138          break;
139
140       case 'u':                    /* set userid */
141          uid = optarg;
142          break;
143
144       case 'v':                    /* verbose */
145          verbose++;
146          break;
147
148       case '?':
149       default:
150          usage();
151
152       }
153    }
154    argc -= optind;
155    argv += optind;
156
157    if (argc) {
158       if (configfile != NULL)
159          free(configfile);
160       configfile = bstrdup(*argv);
161       argc--;
162       argv++;
163    }
164    if (argc) {
165       usage();
166    }
167
168    server_tid = pthread_self();
169    if (!no_signals) {
170       init_signals(terminate_filed);
171    } else {
172       /* This reduces the number of signals facilitating debugging */
173       watchdog_sleep_time = 120;      /* long timeout for debugging */
174    }
175
176    if (configfile == NULL) {
177       configfile = bstrdup(CONFIG_FILE);
178    }
179
180    parse_config(configfile);
181
182    if (init_tls() != 0) {
183       Emsg0(M_ERROR, 0, _("TLS library initialization failed.\n"));
184       terminate_filed(1);
185    }
186
187    if (!check_resources()) {
188       Emsg1(M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile);
189       terminate_filed(1);
190    }
191
192    set_working_directory(me->working_directory);
193
194    if (test_config) {
195       terminate_filed(0);
196    }
197
198    if (!foreground &&!inetd_request) {
199       daemon_start();
200       init_stack_dump();              /* set new pid */
201    }
202
203    /* Maximum 1 daemon at a time */
204    create_pid_file(me->pid_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
205    read_state_file(me->working_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
206
207    drop(uid, gid);
208
209 #ifdef BOMB
210    me += 1000000;
211 #endif
212
213    init_python_interpreter(me->hdr.name, me->scripts_directory, "FDStartUp");
214
215    set_thread_concurrency(10);
216
217    if (!no_signals) {
218       start_watchdog();               /* start watchdog thread */
219       init_jcr_subsystem();           /* start JCR watchdogs etc. */
220    }
221    server_tid = pthread_self();
222
223    if (inetd_request) {
224       /* Socket is on fd 0 */
225       struct sockaddr client_addr;
226       int port = -1;
227       socklen_t client_addr_len = sizeof(client_addr);
228       if (getsockname(0, &client_addr, &client_addr_len) == 0) {
229                 /* MA BUG 6 remove ifdefs */
230                 port = sockaddr_get_port_net_order(&client_addr);
231       }
232       BSOCK *bs = init_bsock(NULL, 0, "client", "unknown client", port, &client_addr);
233       handle_client_request((void *)bs);
234    } else {
235       /* Become server, and handle requests */
236       IPADDR *p;
237       foreach_dlist(p, me->FDaddrs) {
238          Dmsg1(10, "filed: listening on port %d\n", p->get_port_host_order());
239       }
240       bnet_thread_server(me->FDaddrs, me->MaxConcurrentJobs, &dir_workq, handle_client_request);
241    }
242
243    terminate_filed(0);
244    exit(0);                           /* should never get here */
245 }
246
247 void terminate_filed(int sig)
248 {
249    bnet_stop_thread_server(server_tid);
250    generate_daemon_event(NULL, "Exit");
251    write_state_file(me->working_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
252    delete_pid_file(me->pid_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
253
254    if (configfile != NULL) {
255       free(configfile);
256    }
257    if (debug_level > 5) {
258       print_memory_pool_stats();
259    }
260    free_config_resources();
261    term_msg();
262    stop_watchdog();
263    cleanup_tls();
264    close_memory_pool();               /* release free memory in pool */
265    sm_dump(false);                    /* dump orphaned buffers */
266    exit(sig);
267 }
268
269 /*
270 * Make a quick check to see that we have all the
271 * resources needed.
272 */
273 static int check_resources()
274 {
275    bool OK = true;
276    DIRRES *director;
277
278    LockRes();
279
280    me = (CLIENT *)GetNextRes(R_CLIENT, NULL);
281    if (!me) {
282       Emsg1(M_FATAL, 0, _("No File daemon resource defined in %s\n"
283             "Without that I don't know who I am :-(\n"), configfile);
284       OK = false;
285    } else {
286       if (GetNextRes(R_CLIENT, (RES *) me) != NULL) {
287          Emsg1(M_FATAL, 0, _("Only one Client resource permitted in %s\n"),
288               configfile);
289          OK = false;
290       }
291       my_name_is(0, NULL, me->hdr.name);
292       if (!me->messages) {
293          me->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
294          if (!me->messages) {
295              Emsg1(M_FATAL, 0, _("No Messages resource defined in %s\n"), configfile);
296              OK = false;
297          }
298       }
299       /* tls_require implies tls_enable */
300       if (me->tls_require) {
301 #ifndef HAVE_TLS
302          Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
303          OK = false;
304 #else
305          me->tls_enable = true;
306 #endif
307       }
308
309       if ((!me->tls_ca_certfile && !me->tls_ca_certdir) && me->tls_enable) {
310          Emsg1(M_FATAL, 0, _("Neither \"TLS CA Certificate\""
311             " or \"TLS CA Certificate Dir\" are defined for File daemon in %s.\n"),
312                             configfile);
313         OK = false;
314       }
315
316       /* If everything is well, attempt to initialize our per-resource TLS context */
317       if (OK && (me->tls_enable || me->tls_require)) {
318          /* Initialize TLS context:
319           * Args: CA certfile, CA certdir, Certfile, Keyfile,
320           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
321          me->tls_ctx = new_tls_context(me->tls_ca_certfile,
322             me->tls_ca_certdir, me->tls_certfile, me->tls_keyfile,
323             NULL, NULL, NULL, true);
324
325          if (!me->tls_ctx) { 
326             Emsg2(M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
327                                 me->hdr.name, configfile);
328             OK = false;
329          }
330       }
331    }
332
333
334    /* Verify that a director record exists */
335    LockRes();
336    director = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
337    UnlockRes();
338    if (!director) {
339       Emsg1(M_FATAL, 0, _("No Director resource defined in %s\n"),
340             configfile);
341       OK = false;
342    }
343
344    foreach_res(director, R_DIRECTOR) { 
345       /* tls_require implies tls_enable */
346       if (director->tls_require) {
347 #ifndef HAVE_TLS
348          Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
349          OK = false;
350          continue;
351 #else
352          director->tls_enable = true;
353 #endif
354       }
355
356       if (!director->tls_certfile && director->tls_enable) {
357          Emsg2(M_FATAL, 0, _("\"TLS Certificate\" file not defined for Director \"%s\" in %s.\n"),
358                director->hdr.name, configfile);
359          OK = false;
360       }
361
362       if (!director->tls_keyfile && director->tls_enable) {
363          Emsg2(M_FATAL, 0, _("\"TLS Key\" file not defined for Director \"%s\" in %s.\n"),
364                director->hdr.name, configfile);
365          OK = false;
366       }
367
368       if ((!director->tls_ca_certfile && !director->tls_ca_certdir) && director->tls_enable && director->tls_verify_peer) {
369          Emsg2(M_FATAL, 0, _("Neither \"TLS CA Certificate\""
370                              " or \"TLS CA Certificate Dir\" are defined for Director \"%s\" in %s."
371                              " At least one CA certificate store is required"
372                              " when using \"TLS Verify Peer\".\n"),
373                              director->hdr.name, configfile);
374          OK = false;
375       }
376
377       /* If everything is well, attempt to initialize our per-resource TLS context */
378       if (OK && (director->tls_enable || director->tls_require)) {
379          /* Initialize TLS context:
380           * Args: CA certfile, CA certdir, Certfile, Keyfile,
381           * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
382          director->tls_ctx = new_tls_context(director->tls_ca_certfile,
383             director->tls_ca_certdir, director->tls_certfile,
384             director->tls_keyfile, NULL, NULL, director->tls_dhfile,
385             director->tls_verify_peer);
386
387          if (!director->tls_ctx) { 
388             Emsg2(M_FATAL, 0, _("Failed to initialize TLS context for Director \"%s\" in %s.\n"),
389                                 director->hdr.name, configfile);
390             OK = false;
391          }
392       }
393    }
394
395    UnlockRes();
396
397    if (OK) {
398       close_msg(NULL);                /* close temp message handler */
399       init_msg(NULL, me->messages);   /* open user specified message handler */
400    }
401
402    return OK;
403 }