4 * Kern Sibbald, March MM
10 Copyright (C) 2000-2005 Kern Sibbald
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.
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.
27 /* Imported Functions */
28 extern void *handle_client_request(void *dir_sock);
30 /* Imported Variables */
31 extern time_t watchdog_sleep_time;
33 /* Forward referenced functions */
34 void terminate_filed(int sig);
35 static int check_resources();
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;
43 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
44 const int win32_client = 1;
46 const int win32_client = 0;
50 #define CONFIG_FILE "./bacula-fd.conf" /* default config file */
52 static 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;
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"
70 " -s no signals (for debugging)\n"
71 " -t test configuration file and exit\n"
73 " -v verbose user messages\n"
74 " -? print this message.\n"
80 /*********************************************************************
82 * Main Bacula Unix Client Program
85 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
86 #define main BaculaMain
89 int main (int argc, char *argv[])
92 bool test_config = false;
97 my_name_is(argc, argv, "bacula-fd");
100 daemon_start_time = time(NULL);
102 while ((ch = getopt(argc, argv, "c:d:fg:istu:v?")) != -1) {
104 case 'c': /* configuration file */
105 if (configfile != NULL) {
108 configfile = bstrdup(optarg);
111 case 'd': /* debug level */
112 debug_level = atoi(optarg);
113 if (debug_level <= 0) {
118 case 'f': /* run in foreground */
122 case 'g': /* set group */
127 inetd_request = true;
137 case 'u': /* set userid */
141 case 'v': /* verbose */
155 if (configfile != NULL)
157 configfile = bstrdup(*argv);
165 server_tid = pthread_self();
167 init_signals(terminate_filed);
169 /* This reduces the number of signals facilitating debugging */
170 watchdog_sleep_time = 120; /* long timeout for debugging */
173 if (configfile == NULL) {
174 configfile = bstrdup(CONFIG_FILE);
177 parse_config(configfile);
179 if (init_tls() != 0) {
180 Emsg0(M_ERROR, 0, _("TLS library initialization failed.\n"));
184 if (!check_resources()) {
185 Emsg1(M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile);
189 set_working_directory(me->working_directory);
195 if (!foreground &&!inetd_request) {
197 init_stack_dump(); /* set new pid */
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));
210 init_python_interpreter(me->hdr.name, me->scripts_directory, "FDStartUp");
212 set_thread_concurrency(10);
215 start_watchdog(); /* start watchdog thread */
216 init_jcr_subsystem(); /* start JCR watchdogs etc. */
218 server_tid = pthread_self();
221 /* Socket is on fd 0 */
222 struct sockaddr client_addr;
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);
229 BSOCK *bs = init_bsock(NULL, 0, "client", "unknown client", port, &client_addr);
230 handle_client_request((void *)bs);
232 /* Become server, and handle requests */
234 foreach_dlist(p, me->FDaddrs) {
235 Dmsg1(10, "filed: listening on port %d\n", p->get_port_host_order());
237 bnet_thread_server(me->FDaddrs, me->MaxConcurrentJobs, &dir_workq, handle_client_request);
241 exit(0); /* should never get here */
244 void terminate_filed(int sig)
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));
251 if (configfile != NULL) {
254 if (debug_level > 5) {
255 print_memory_pool_stats();
257 free_config_resources();
261 close_memory_pool(); /* release free memory in pool */
262 sm_dump(false); /* dump orphaned buffers */
267 * Make a quick check to see that we have all the
270 static int check_resources()
277 me = (CLIENT *)GetNextRes(R_CLIENT, NULL);
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);
283 if (GetNextRes(R_CLIENT, (RES *) me) != NULL) {
284 Emsg1(M_FATAL, 0, _("Only one Client resource permitted in %s\n"),
288 my_name_is(0, NULL, me->hdr.name);
290 me->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
292 Emsg1(M_FATAL, 0, _("No Messages resource defined in %s\n"), configfile);
296 /* tls_require implies tls_enable */
297 if (me->tls_require) {
299 Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
302 me->tls_enable = true;
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"),
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);
323 Emsg2(M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
324 me->hdr.name, configfile);
331 /* Verify that a director record exists */
333 director = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
336 Emsg1(M_FATAL, 0, _("No Director resource defined in %s\n"),
341 foreach_res(director, R_DIRECTOR) {
342 /* tls_require implies tls_enable */
343 if (director->tls_require) {
345 Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
349 director->tls_enable = true;
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);
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);
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);
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);
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);
395 close_msg(NULL); /* close temp message handler */
396 init_msg(NULL, me->messages); /* open user specified message handler */