2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation plus additions
11 that are listed in the file LICENSE.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Network Utility Routines
33 * Version $Id: bnet.c 3670 2006-11-21 16:13:58Z kerns $
41 #ifndef ENODATA /* not defined on BSD systems */
46 #define socketRead(fd, buf, len) ::recv(fd, buf, len, 0)
47 #define socketWrite(fd, buf, len) ::send(fd, buf, len, 0)
48 #define socketClose(fd) ::closesocket(fd)
50 #define socketRead(fd, buf, len) ::read(fd, buf, len)
51 #define socketWrite(fd, buf, len) ::write(fd, buf, len)
52 #define socketClose(fd) ::close(fd)
56 * Send a message over the network. The send consists of
57 * two network packets. The first is sends a 32 bit integer containing
58 * the length of the data packet which follows.
60 * Returns: false on failure
69 if (errors || is_terminated() || msglen > 1000000) {
72 /* Compute total packet length */
74 pktsiz = sizeof(pktsiz); /* signal, no data */
76 pktsiz = msglen + sizeof(pktsiz); /* data */
78 /* Store packet length at head of message -- note, we
79 * have reserved an int32_t just before msg, so we can
82 hdr = (int32_t *)(msg - (int)sizeof(pktsiz));
83 *hdr = htonl(msglen); /* store signal/length */
85 out_msg_no++; /* increment message number */
87 /* send data packet */
88 timer_start = watchdog_time; /* start timer */
90 /* Full I/O done in one write */
91 rc = write_nbytes(this, (char *)hdr, pktsiz);
92 timer_start = 0; /* clear timer */
101 if (!m_suppress_error_msgs) {
102 Qmsg5(m_jcr, M_ERROR, 0,
103 _("Write error sending %d bytes to %s:%s:%d: ERR=%s\n"),
105 m_host, m_port, bnet_strerror(this));
108 Qmsg5(m_jcr, M_ERROR, 0,
109 _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
110 msglen, m_who, m_host, m_port, rc);
118 * Format and send a message
119 * Returns: false on error
122 bool BSOCK::fsend(const char *fmt, ...)
127 if (errors || is_terminated()) {
130 /* This probably won't work, but we vsnprintf, then if we
131 * get a negative length or a length greater than our buffer
132 * (depending on which library is used), the printf was truncated, so
133 * get a bigger buffer and try again.
136 maxlen = sizeof_pool_memory(msg) - 1;
137 va_start(arg_ptr, fmt);
138 msglen = bvsnprintf(msg, maxlen, fmt, arg_ptr);
140 if (msglen > 0 && msglen < (maxlen - 5)) {
143 msg = realloc_pool_memory(msg, maxlen + maxlen / 2);
149 * Receive a message from the other end. Each message consists of
150 * two packets. The first is a header that contains the size
151 * of the data that follows in the second packet.
152 * Returns number of bytes read (may return zero)
153 * Returns -1 on signal (BNET_SIGNAL)
154 * Returns -2 on hard end of file (BNET_HARDEOF)
155 * Returns -3 on error (BNET_ERROR)
157 * Unfortunately, it is a bit complicated because we have these
160 * 2. Signal including end of data stream
161 * 3. Hard end of file
163 * Using is_bnet_stop() and is_bnet_error() you can figure this all out.
165 int32_t BSOCK::recv()
172 if (errors || is_terminated()) {
176 read_seqno++; /* bump sequence number */
177 timer_start = watchdog_time; /* set start wait time */
179 /* get data size -- in int32_t */
180 if ((nbytes = read_nbytes(this, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
181 timer_start = 0; /* clear timer */
182 /* probably pipe broken because client died */
189 return BNET_HARDEOF; /* assume hard EOF received */
191 timer_start = 0; /* clear timer */
192 if (nbytes != sizeof(int32_t)) {
195 Qmsg5(m_jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
196 sizeof(int32_t), nbytes, m_who, m_host, m_port);
200 pktsiz = ntohl(pktsiz); /* decode no. of bytes that follow */
202 if (pktsiz == 0) { /* No data transferred */
203 timer_start = 0; /* clear timer */
206 return 0; /* zero bytes read */
209 /* If signal or packet size too big */
210 if (pktsiz < 0 || pktsiz > 1000000) {
211 if (pktsiz > 0) { /* if packet too big */
212 Qmsg3(m_jcr, M_FATAL, 0,
213 _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
214 m_who, m_host, m_port);
215 pktsiz = BNET_TERMINATE; /* hang up */
217 if (pktsiz == BNET_TERMINATE) {
220 timer_start = 0; /* clear timer */
222 msglen = pktsiz; /* signal code */
223 return BNET_SIGNAL; /* signal */
226 /* Make sure the buffer is big enough + one byte for EOS */
227 if (pktsiz >= (int32_t) sizeof_pool_memory(msg)) {
228 msg = realloc_pool_memory(msg, pktsiz + 100);
231 timer_start = watchdog_time; /* set start wait time */
233 /* now read the actual data */
234 if ((nbytes = read_nbytes(this, msg, pktsiz)) <= 0) {
235 timer_start = 0; /* clear timer */
242 Qmsg4(m_jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
243 m_who, m_host, m_port, bnet_strerror(this));
246 timer_start = 0; /* clear timer */
249 if (nbytes != pktsiz) {
252 Qmsg5(m_jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
253 pktsiz, nbytes, m_who, m_host, m_port);
256 /* always add a zero by to properly terminate any
257 * string that was send to us. Note, we ensured above that the
258 * buffer is at least one byte longer than the message length.
260 msg[nbytes] = 0; /* terminate in case it is a string */
261 sm_check(__FILE__, __LINE__, false);
262 return nbytes; /* return actual length of message */
269 bool BSOCK::signal(int signal)
272 if (signal == BNET_TERMINATE) {
273 m_suppress_error_msgs = true;
279 * Despool spooled attributes
281 bool BSOCK::despool(void update_attr_spool_size(ssize_t size), ssize_t tsize)
285 ssize_t last = 0, size = 0;
290 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
291 posix_fadvise(fileno(m_spool_fd), 0, 0, POSIX_FADV_WILLNEED);
294 while (fread((char *)&pktsiz, 1, sizeof(int32_t), m_spool_fd) ==
296 size += sizeof(int32_t);
297 msglen = ntohl(pktsiz);
299 if (msglen > (int32_t) sizeof_pool_memory(msg)) {
300 msg = realloc_pool_memory(msg, msglen + 1);
302 nbytes = fread(msg, 1, msglen, m_spool_fd);
303 if (nbytes != (size_t) msglen) {
305 Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, msglen);
306 Qmsg1(jcr(), M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
308 update_attr_spool_size(tsize - last);
312 if ((++count & 0x3F) == 0) {
313 update_attr_spool_size(size - last);
319 update_attr_spool_size(tsize - last);
320 if (ferror(m_spool_fd)) {
322 Qmsg1(jcr(), M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
330 * Return the string for the error that occurred
331 * on the socket. Only the first error is retained.
333 const char *BSOCK::bstrerror()
336 if (errmsg == NULL) {
337 errmsg = get_pool_memory(PM_MESSAGE);
339 pm_strcpy(errmsg, be.bstrerror(b_errno));
343 int BSOCK::get_peer(char *buf, socklen_t buflen)
345 #if !defined(HAVE_WIN32)
346 if (peer_addr.sin_family == 0) {
347 socklen_t salen = sizeof(peer_addr);
348 int rval = (getpeername)(m_fd, (struct sockaddr *)&peer_addr, &salen);
349 if (rval < 0) return rval;
351 if (!inet_ntop(peer_addr.sin_family, &peer_addr.sin_addr, buf, buflen))
361 * Set the network buffer size, suggested size is in size.
362 * Actual size obtained is returned in bs->msglen
364 * Returns: false on failure
367 bool BSOCK::set_buffer_size(uint32_t size, int rw)
369 uint32_t dbuf_size, start_size;
370 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
372 opt = IPTOS_THROUGHPUT;
373 setsockopt(fd, IPPROTO_IP, IP_TOS, (sockopt_val_t)&opt, sizeof(opt));
379 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
381 start_size = dbuf_size;
382 if ((msg = realloc_pool_memory(msg, dbuf_size + 100)) == NULL) {
383 Qmsg0(jcr(), M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
386 if (rw & BNET_SETBUF_READ) {
387 while ((dbuf_size > TAPE_BSIZE) && (setsockopt(m_fd, SOL_SOCKET,
388 SO_RCVBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
390 Qmsg1(jcr(), M_ERROR, 0, _("sockopt error: %s\n"), be.bstrerror());
391 dbuf_size -= TAPE_BSIZE;
393 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
394 if (dbuf_size != start_size) {
395 Qmsg1(jcr(), M_WARNING, 0,
396 _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
398 if (dbuf_size % TAPE_BSIZE != 0) {
399 Qmsg1(jcr(), M_ABORT, 0,
400 _("Network buffer size %d not multiple of tape block size.\n"),
407 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
409 start_size = dbuf_size;
410 if (rw & BNET_SETBUF_WRITE) {
411 while ((dbuf_size > TAPE_BSIZE) && (setsockopt(m_fd, SOL_SOCKET,
412 SO_SNDBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
414 Qmsg1(jcr(), M_ERROR, 0, _("sockopt error: %s\n"), be.bstrerror());
415 dbuf_size -= TAPE_BSIZE;
417 Dmsg1(900, "set network buffer size=%d\n", dbuf_size);
418 if (dbuf_size != start_size) {
419 Qmsg1(jcr(), M_WARNING, 0,
420 _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
422 if (dbuf_size % TAPE_BSIZE != 0) {
423 Qmsg1(jcr(), M_ABORT, 0,
424 _("Network buffer size %d not multiple of tape block size.\n"),
434 * Set socket non-blocking
435 * Returns previous socket flag
437 int BSOCK::set_nonblocking()
442 /* Get current flags */
443 if ((oflags = fcntl(m_fd, F_GETFL, 0)) < 0) {
445 Jmsg1(jcr(), M_ABORT, 0, _("fcntl F_GETFL error. ERR=%s\n"), be.bstrerror());
448 /* Set O_NONBLOCK flag */
449 if ((fcntl(m_fd, F_SETFL, oflags|O_NONBLOCK)) < 0) {
451 Jmsg1(jcr(), M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.bstrerror());
461 ioctlsocket(m_fd, FIONBIO, &ioctlArg);
469 * Set socket blocking
470 * Returns previous socket flags
472 int BSOCK::set_blocking()
476 /* Get current flags */
477 if ((oflags = fcntl(m_fd, F_GETFL, 0)) < 0) {
479 Jmsg1(jcr(), M_ABORT, 0, _("fcntl F_GETFL error. ERR=%s\n"), be.bstrerror());
482 /* Set O_NONBLOCK flag */
483 if ((fcntl(m_fd, F_SETFL, oflags & ~O_NONBLOCK)) < 0) {
485 Jmsg1(jcr(), M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.bstrerror());
495 ioctlsocket(m_fd, FIONBIO, &ioctlArg);
503 * Restores socket flags
505 void BSOCK::restore_blocking (int flags)
508 if ((fcntl(m_fd, F_SETFL, flags)) < 0) {
510 Jmsg1(jcr(), M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.bstrerror());
513 m_blocking = (flags & O_NONBLOCK) ? true : false;
515 u_long ioctlArg = flags;
517 ioctlsocket(m_fd, FIONBIO, &ioctlArg);
528 for (; bsock; bsock = next) {
529 next = bsock->m_next; /* get possible pointer to next before destoryed */
530 if (!bsock->m_duped) {
532 /* Shutdown tls cleanly. */
534 tls_bsock_shutdown(bsock);
535 free_tls_connection(bsock->tls);
538 #endif /* HAVE_TLS */
539 if (bsock->is_timed_out()) {
540 shutdown(bsock->m_fd, 2); /* discard any pending I/O */
542 socketClose(bsock->m_fd); /* normal close */
544 destroy(); /* free the packet */
549 void BSOCK::destroy()
552 free_pool_memory(msg);
555 ASSERT(1 == 0); /* double close */
558 free_pool_memory(errmsg);