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 * Hello routines for Storage daemon.
22 * This file contains all the code relating to reading and writing of
23 * all Hello commands between the daemons.
25 * Written by Kern Sibbald, June 2014
33 extern STORES *me; /* our Global resource */
35 const int dbglvl = 50;
39 * Note: Enterprise versions now numbered in 30000
40 * and community is at SD version 3
41 * None prior to 06Aug13
44 * 3 22Feb14 - Added SD->SD with SD_Calls_Client
46 * 305 04Jun15 - Added JobMedia queueing
47 * 306 20Mar15 - Added comm line compression
50 #define SD_VERSION 306 /* Community SD version */
51 #define FD_VERSION 214 /* Community FD version */
53 static char hello_sd[] = "Hello Bacula SD: Start Job %s %d %d\n";
55 static char Sorry[] = "3999 No go\n";
56 static char OK_hello[] = "3000 OK Hello %d\n";
59 /*********************************************************************
61 * Validate hello from the Director.
63 * Returns: true if Hello is good.
64 * false if Hello is bad.
66 bool validate_dir_hello(JCR* jcr)
69 DIRRES *director = NULL;
71 BSOCK *dir = jcr->dir_bsock;
73 if (dir->msglen < 25 || dir->msglen > 500) {
74 Dmsg2(dbglvl, "Bad Hello command from Director at %s. Len=%d.\n",
75 dir->who(), dir->msglen);
76 Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
77 dir->who(), dir->msglen);
80 dirname = get_pool_memory(PM_MESSAGE);
81 dirname = check_pool_memory_size(dirname, dir->msglen);
83 if (sscanf(dir->msg, "Hello SD: Bacula Director %127s calling %d",
84 dirname, &dir_version) != 2 &&
85 sscanf(dir->msg, "Hello SD: Bacula Director %127s calling",
88 Dmsg2(dbglvl, "Bad Hello command from Director at %s: %s\n",
89 dir->who(), dir->msg);
90 Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
91 dir->who(), dir->msg);
92 free_pool_memory(dirname);
96 if (dir_version >= 1 && me->comm_compression) {
99 dir->clear_compress();
100 Dmsg0(050, "**** No SD compression to Dir\n");
103 unbash_spaces(dirname);
104 foreach_res(director, R_DIRECTOR) {
105 if (strcasecmp(director->hdr.name, dirname) == 0) {
110 Dmsg2(dbglvl, "Connection from unknown Director %s at %s rejected.\n",
111 dirname, dir->who());
112 Jmsg2(jcr, M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"
113 "Please see " MANUAL_AUTH_URL " for help.\n"),
114 dirname, dir->who());
115 free_pool_memory(dirname);
118 jcr->director = director;
119 free_pool_memory(dirname);
124 * After receiving a connection (in dircmd.c) if it is
125 * from the File daemon, this routine is called.
127 void handle_client_connection(BSOCK *fd)
134 * Do a sanity check on the message received
136 if (fd->msglen < 25 || fd->msglen > (int)sizeof(job_name)) {
137 Pmsg1(000, "<filed: %s", fd->msg);
138 Jmsg2(NULL, M_ERROR, 0, _("Invalid connection from %s. Len=%d\n"), fd->who(), fd->msglen);
139 bmicrosleep(5, 0); /* make user wait 5 seconds */
144 Dmsg1(100, "Conn: %s", fd->msg);
146 * See if this is a File daemon connection. If so
149 if (sscanf(fd->msg, "Hello Bacula SD: Start Job %127s %d %d", job_name, &fd_version, &sd_version) != 3 &&
150 sscanf(fd->msg, "Hello FD: Bacula Storage calling Start Job %127s %d", job_name, &sd_version) != 2 &&
151 sscanf(fd->msg, "Hello Start Job %127s", job_name) != 1) {
152 Jmsg2(NULL, M_ERROR, 0, _("Invalid Hello from %s. Len=%d\n"), fd->who(), fd->msglen);
156 if (!(jcr=get_jcr_by_full_name(job_name))) {
157 Jmsg1(NULL, M_FATAL, 0, _("Client connect failed: Job name not found: %s\n"), job_name);
158 Dmsg1(3, "**** Job \"%s\" not found.\n", job_name);
163 /* After this point, we can use bail_out */
164 Dmsg1(100, "Found Client Job %s\n", job_name);
165 if (jcr->authenticated) {
166 Jmsg3(jcr, M_WARNING, 0, _("A Client \"%s\" tried to authenticate for Job %s, "
167 "but the Job is already authenticated with \"%s\".\n"),
168 fd->who(), jcr->Job, jcr->file_bsock?jcr->file_bsock->who():"N/A");
169 Dmsg2(050, "Hey!!!! JobId %u Job %s already authenticated.\n",
170 (uint32_t)jcr->JobId, jcr->Job);
175 Dmsg2(050, "fd_version=%d sd_version=%d\n", fd_version, sd_version);
177 /* Turn on compression for newer FDs */
178 if (fd_version >= 214 || sd_version >= 306) {
179 fd->set_compress(); /* set compression allowed */
181 fd->clear_compress();
182 Dmsg0(050, "*** No SD compression to FD\n");
186 * Authenticate the Client (FD or SD)
188 jcr->lock_auth(); /* Ensure that only one thread is dealing with auth */
189 if (jcr->authenticated) {
190 Jmsg2(jcr, M_WARNING, 0, _("A Client \"%s\" tried to authenticate for Job %s, "
191 "but the job is already authenticated.\n"),
192 fd->who(), jcr->Job);
194 } else if (!authenticate_filed(jcr, fd, fd_version)) {
195 Dmsg1(50, "Authentication failed Job %s\n", jcr->Job);
196 /* Job not yet started, we can cancel */
197 Jmsg(jcr, M_FATAL, 0, _("Unable to authenticate File daemon\n"));
200 Dmsg2(050, "OK Authentication jid=%u Job %s\n", (uint32_t)jcr->JobId, jcr->Job);
201 jcr->file_bsock = fd;
202 jcr->FDVersion = fd_version;
203 jcr->SDVersion = sd_version;
204 jcr->authenticated = true;
206 if (sd_version > 0) {
207 jcr->sd_client = true;
212 if (!jcr->authenticated) {
213 jcr->setJobStatus(JS_ErrorTerminated);
216 Dmsg4(050, "=== Auth %s, unblock Job %s jid=%d sd_ver=%d\n",
217 jcr->authenticated?"OK":"KO", job_name, jcr->JobId, sd_version);
220 /* file_bsock might be NULL or a previous BSOCK */
221 if (jcr->file_bsock != fd) {
224 pthread_cond_signal(&jcr->job_start_wait); /* wake waiting job */
230 bool is_client_connection(BSOCK *bs)
233 sscanf(bs->msg, "Hello Bacula SD: Start Job ") == 0 ||
234 sscanf(bs->msg, "Hello FD: Bacula Storage calling Start Job ") == 0 ||
235 sscanf(bs->msg, "Hello Start Job ") == 0;
239 * If sd_calls_client, we must read the client's response to
240 * the hello we previously sent.
242 bool read_client_hello(JCR *jcr)
248 BSOCK *cl = jcr->file_bsock;
251 /* We connected to Client, so finish work */
253 Jmsg0(jcr, M_FATAL, 0, _("Client socket not open. Could not connect to Client.\n"));
254 Dmsg0(050, "Client socket not open. Could not connect to Client.\n");
257 /* Get response to Hello command sent earlier */
258 Dmsg0(050, "Read Hello command from Client\n");
259 for (i=0; i<60; i++) {
269 Jmsg1(jcr, M_FATAL, 0, _("Recv request to Client failed. ERR=%s\n"),
271 Dmsg1(050, _("Recv request to Client failed. ERR=%s\n"), be.bstrerror());
274 Dmsg1(050, ">filed: %s\n", cl->msg);
275 if (sscanf(cl->msg, "Hello Bacula SD: Start Job %127s %d %d", job_name, &fd_version, &sd_version) != 3) {
276 Jmsg1(jcr, M_FATAL, 0, _("Bad Hello from Client: %s.\n"), cl->msg);
277 Dmsg1(050, _("Bad Hello from Client: %s.\n"), cl->msg);
280 unbash_spaces(job_name);
281 jcr->FDVersion = fd_version;
282 jcr->SDVersion = sd_version;
283 Dmsg1(050, "FDVersion=%d\n", fd_version);
284 /* Turn on compression for newer FDs, except for Community version */
285 if (jcr->FDVersion >= 214 && me->comm_compression) {
286 cl->set_compress(); /* set compression allowed */
288 cl->clear_compress();
289 Dmsg0(050, "*** No SD compression to FD\n");
296 * Send Hello OK to DIR or FD
298 bool send_hello_ok(BSOCK *bs)
300 return bs->fsend(OK_hello, SD_VERSION);
303 bool send_sorry(BSOCK *bs)
305 return bs->fsend(Sorry);
309 * We are acting as a client, so send Hello to the SD.
311 bool send_hello_sd(JCR *jcr, char *Job)
314 BSOCK *sd = jcr->store_bsock;
317 rtn = sd->fsend(hello_sd, Job, FD_VERSION, SD_VERSION);
319 Dmsg1(100, "Send to SD: %s\n", sd->msg);
327 * We are SD so send Hello to client
328 * Note: later the Client will send us a Hello.
330 bool send_hello_client(JCR *jcr, char *Job)
333 BSOCK *cl = jcr->file_bsock;
336 rtn = cl->fsend("Hello FD: Bacula Storage calling Start Job %s %d\n", Job, SD_VERSION);