3 * Bacula Director -- routines to receive network data and
4 * handle network signals. These routines handle the connections
5 * to the Storage daemon and the File daemon.
7 * Kern Sibbald, August MM
9 * This routine runs as a thread and must be thread reentrant.
11 * Basic tasks done here:
12 * Handle network signals (signals).
13 * Signals always have return status 0 from bnet_recv() and
14 * a zero or negative message length.
15 * Pass appropriate messages back to the caller (responses).
16 * Responses always have a digit as the first character.
17 * Handle requests for message and catalog services (requests).
18 * Requests are any message that does not begin with a digit.
19 * In affect, they are commands.
24 Copyright (C) 2000-2004 Kern Sibbald and John Walker
26 This program is free software; you can redistribute it and/or
27 modify it under the terms of the GNU General Public License as
28 published by the Free Software Foundation; either version 2 of
29 the License, or (at your option) any later version.
31 This program is distributed in the hope that it will be useful,
32 but WITHOUT ANY WARRANTY; without even the implied warranty of
33 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 General Public License for more details.
36 You should have received a copy of the GNU General Public
37 License along with this program; if not, write to the Free
38 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
46 /* Forward referenced functions */
47 static char *find_msg_start(char *msg);
49 static char OK_msg[] = "1000 OK\n";
53 * Call appropriate processing routine
54 * If it is not a Jmsg or a ReqCat message,
55 * return it to the caller.
57 * This routine is called to get the next message from
58 * another daemon. If the message is in canonical message
59 * format and the type is known, it will be dispatched
60 * to the appropriate handler. If the message is
61 * in any other format, it will be returned.
63 * E.g. any message beginning with a digit will be returned.
64 * any message beginning with Jmsg will be processed.
67 int bget_dirmsg(BSOCK *bs)
70 char Job[MAX_NAME_LENGTH];
78 Dmsg2(120, "bget_dirmsg %d: %s\n", n, bs->msg);
80 if (is_bnet_stop(bs)) {
81 return n; /* error or terminate */
83 if (n == BNET_SIGNAL) { /* handle signal */
84 /* BNET_SIGNAL (-1) return from bnet_recv() => network signal */
86 case BNET_EOD: /* end of data */
89 bnet_fsend(bs, OK_msg);/* send response */
90 return n; /* end of data */
95 bnet_fsend(bs, OK_msg); /* send response */
98 // encode_time(time(NULL), Job);
99 // Dmsg1(100, "%s got heartbeat.\n", Job);
101 case BNET_HB_RESPONSE:
104 /* *****FIXME***** Implement more completely */
105 bnet_fsend(bs, "Status OK\n");
106 bnet_sig(bs, BNET_EOD);
108 case BNET_BTIME: /* send Bacula time */
110 bnet_fsend(bs, "btime %s\n", edit_uint64(get_current_btime(),ed1));
113 Emsg1(M_WARNING, 0, _("bget_dirmsg: unknown bnet signal %d\n"), bs->msglen);
119 /* Handle normal data */
121 if (n > 0 && B_ISDIGIT(bs->msg[0])) { /* response? */
122 return n; /* yes, return it */
126 * If we get here, it must be a request. Either
127 * a message to dispatch, or a catalog request.
130 if (sscanf(bs->msg, "%020s Job=%127s ", MsgType, Job) != 2) {
131 Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
134 if (!(jcr=get_jcr_by_full_name(Job))) {
135 Emsg1(M_ERROR, 0, _("Job not found: %s\n"), bs->msg);
138 Dmsg1(200, "Getmsg got jcr 0x%x\n", jcr);
140 /* Skip past "Jmsg Job=nnn" */
141 if (!(msg=find_msg_start(bs->msg))) {
142 Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
148 * Here we are expecting a message of the following format:
149 * Jmsg Job=nnn type=nnn level=nnn Message-string
151 if (bs->msg[0] == 'J') { /* Job message */
152 if (sscanf(bs->msg, "Jmsg Job=%127s type=%d level=%d",
153 Job, &type, &level) != 3) {
154 Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
158 Dmsg1(120, "Got msg: %s\n", bs->msg);
160 skip_nonspaces(&msg); /* skip type=nnn */
162 skip_nonspaces(&msg); /* skip level=nnn */
164 msg++; /* skip leading space */
166 Dmsg1(120, "Dispatch msg: %s", msg);
167 dispatch_message(jcr, type, level, msg);
172 * Here we expact a CatReq message
173 * CatReq Job=nn Catalog-Request-Message
175 if (bs->msg[0] == 'C') { /* Catalog request */
176 Dmsg2(120, "Catalog req jcr 0x%x: %s", jcr, bs->msg);
177 catalog_request(jcr, bs, msg);
178 Dmsg1(200, "Calling freejcr 0x%x\n", jcr);
182 if (bs->msg[0] == 'U') { /* Catalog update */
183 Dmsg2(120, "Catalog upd jcr 0x%x: %s", jcr, bs->msg);
184 catalog_update(jcr, bs, msg);
185 Dmsg1(200, "Calling freejcr 0x%x\n", jcr);
189 if (bs->msg[0] == 'M') { /* Mount request */
190 Dmsg1(120, "Mount req: %s", bs->msg);
191 mount_request(jcr, bs, msg);
199 static char *find_msg_start(char *msg)
203 skip_nonspaces(&p); /* skip message type */
205 skip_nonspaces(&p); /* skip Job */
206 skip_spaces(&p); /* after spaces come the message */
211 * Get response from File daemon to a command we
212 * sent. Check that the response agrees with what we expect.
214 * Returns: 0 on failure
217 int response(JCR *jcr, BSOCK *fd, char *resp, char *cmd, e_prtmsg prtmsg)
221 if (is_bnet_error(fd)) {
224 if ((n = bget_dirmsg(fd)) >= 0) {
226 if (strcmp(fd->msg, resp) == 0) {
229 if (prtmsg == DISPLAY_ERROR) {
230 Jmsg(jcr, M_FATAL, 0, _("FD gave bad response to %s command: wanted %s got: %s\n"),
235 Jmsg(jcr, M_FATAL, 0, _("Socket error from Filed on %s command: ERR=%s\n"),
236 cmd, bnet_strerror(fd));