]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/bnet.c
Move more bnet functions into the BSOCK class.
[bacula/bacula] / bacula / src / lib / bnet.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
5
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.
12
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.
17
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
21    02110-1301, USA.
22
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.
27 */
28 /*
29  * Network Utility Routines
30  *
31  *  by Kern Sibbald
32  *
33  * Adapted and enhanced for Bacula, originally written
34  * for inclusion in the Apcupsd package
35  *
36  *   Version $Id$
37  */
38
39
40 #include "bacula.h"
41 #include "jcr.h"
42 #include <netdb.h>
43
44 extern time_t watchdog_time;
45
46 #ifndef   INADDR_NONE
47 #define   INADDR_NONE    -1
48 #endif
49
50 #ifdef HAVE_WIN32
51 #define socketRead(fd, buf, len)  recv(fd, buf, len, 0)
52 #define socketWrite(fd, buf, len) send(fd, buf, len, 0)
53 #define socketClose(fd)           closesocket(fd)
54 #else
55 #define socketRead(fd, buf, len)  read(fd, buf, len)
56 #define socketWrite(fd, buf, len) write(fd, buf, len)
57 #define socketClose(fd)           close(fd)
58 #endif
59
60 static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
61
62 /*
63  * Read a nbytes from the network.
64  * It is possible that the total bytes require in several
65  * read requests
66  */
67
68 int32_t read_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes)
69 {
70    int32_t nleft, nread;
71
72 #ifdef HAVE_TLS
73    if (bsock->tls) {
74       /* TLS enabled */
75       return (tls_bsock_readn(bsock, ptr, nbytes));
76    }
77 #endif /* HAVE_TLS */
78
79    nleft = nbytes;
80    while (nleft > 0) {
81       errno = 0;
82       nread = socketRead(bsock->m_fd, ptr, nleft);
83       if (bsock->is_timed_out() || bsock->is_terminated()) {
84          return nread;
85       }
86       if (nread == -1) {
87          if (errno == EINTR) {
88             continue;
89          }
90          if (errno == EAGAIN) {
91             bmicrosleep(0, 200000);  /* try again in 200ms */
92             continue;
93          }
94       }
95       if (nread <= 0) {
96          return nread;             /* error, or EOF */
97       }
98       nleft -= nread;
99       ptr += nread;
100    }
101    return nbytes - nleft;          /* return >= 0 */
102 }
103
104 /*
105  * Write nbytes to the network.
106  * It may require several writes.
107  */
108
109 int32_t write_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes)
110 {
111    int32_t nleft, nwritten;
112
113    if (bsock->m_spool) {
114       nwritten = fwrite(ptr, 1, nbytes, bsock->m_spool_fd);
115       if (nwritten != nbytes) {
116          berrno be;
117          bsock->b_errno = errno;
118          Qmsg1(bsock->jcr(), M_FATAL, 0, _("Attr spool write error. ERR=%s\n"),
119                be.bstrerror());
120          Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes);
121          errno = bsock->b_errno;
122          return -1;
123       }
124       return nbytes;
125    }
126
127 #ifdef HAVE_TLS
128    if (bsock->tls) {
129       /* TLS enabled */
130       return (tls_bsock_writen(bsock, ptr, nbytes));
131    }
132 #endif /* HAVE_TLS */
133
134    nleft = nbytes;
135    while (nleft > 0) {
136       do {
137          errno = 0;
138          nwritten = socketWrite(bsock->m_fd, ptr, nleft);
139          if (bsock->is_timed_out() || bsock->is_terminated()) {
140             return nwritten;
141          }
142       } while (nwritten == -1 && errno == EINTR);
143       /*
144        * If connection is non-blocking, we will get EAGAIN, so
145        * use select() to keep from consuming all the CPU
146        * and try again.
147        */
148       if (nwritten == -1 && errno == EAGAIN) {
149          fd_set fdset;
150          struct timeval tv;
151
152          FD_ZERO(&fdset);
153          FD_SET((unsigned)bsock->m_fd, &fdset);
154          tv.tv_sec = 10;
155          tv.tv_usec = 0;
156          select(bsock->m_fd + 1, NULL, &fdset, NULL, &tv);
157          continue;
158       }
159       if (nwritten <= 0) {
160          return nwritten;          /* error */
161       }
162       nleft -= nwritten;
163       ptr += nwritten;
164    }
165    return nbytes - nleft;
166 }
167
168 /*
169  * Receive a message from the other end. Each message consists of
170  * two packets. The first is a header that contains the size
171  * of the data that follows in the second packet.
172  * Returns number of bytes read (may return zero)
173  * Returns -1 on signal (BNET_SIGNAL)
174  * Returns -2 on hard end of file (BNET_HARDEOF)
175  * Returns -3 on error  (BNET_ERROR)
176  *
177  *  Unfortunately, it is a bit complicated because we have these
178  *    four return types:
179  *    1. Normal data
180  *    2. Signal including end of data stream
181  *    3. Hard end of file
182  *    4. Error
183  *  Using is_bnet_stop() and is_bnet_error() you can figure this all out.
184  */
185 int32_t bnet_recv(BSOCK * bsock)
186 {
187    return bsock->recv();
188 }
189
190
191 /*
192  * Return 1 if there are errors on this bsock or it is closed,
193  *   i.e. stop communicating on this line.
194  */
195 bool is_bnet_stop(BSOCK * bsock)
196 {
197    return bsock->errors || bsock->is_terminated();
198 }
199
200 /*
201  * Return number of errors on socket
202  */
203 int is_bnet_error(BSOCK * bsock)
204 {
205    errno = bsock->b_errno;
206    return bsock->errors;
207 }
208
209 /*
210  * Call here after error during closing to suppress error
211  *  messages which are due to the other end shutting down too.
212  */
213 void bnet_suppress_error_messages(BSOCK * bsock, bool flag)
214 {
215    bsock->m_suppress_error_msgs = flag;
216 }
217
218 /*
219  * Send a message over the network. The send consists of
220  * two network packets. The first is sends a 32 bit integer containing
221  * the length of the data packet which follows.
222  *
223  * Returns: false on failure
224  *          true  on success
225  */
226 bool bnet_send(BSOCK *bsock)
227 {
228    return bsock->send();
229 }
230
231
232 /*
233  * Establish a TLS connection -- server side
234  *  Returns: true  on success
235  *           false on failure
236  */
237 #ifdef HAVE_TLS
238 bool bnet_tls_server(TLS_CONTEXT *ctx, BSOCK * bsock, alist *verify_list)
239 {
240    TLS_CONNECTION *tls;
241    
242    tls = new_tls_connection(ctx, bsock->m_fd);
243    if (!tls) {
244       Qmsg0(bsock->jcr(), M_FATAL, 0, _("TLS connection initialization failed.\n"));
245       return false;
246    }
247
248    bsock->tls = tls;
249
250    /* Initiate TLS Negotiation */
251    if (!tls_bsock_accept(bsock)) {
252       Qmsg0(bsock->jcr(), M_FATAL, 0, _("TLS Negotiation failed.\n"));
253       goto err;
254    }
255
256    if (verify_list) {
257       if (!tls_postconnect_verify_cn(tls, verify_list)) {
258          Qmsg1(bsock->jcr(), M_FATAL, 0, _("TLS certificate verification failed."
259                                          " Peer certificate did not match a required commonName\n"),
260                                          bsock->host());
261          goto err;
262       }
263    }
264    return true;
265
266 err:
267    free_tls_connection(tls);
268    bsock->tls = NULL;
269    return false;
270 }
271
272 /*
273  * Establish a TLS connection -- client side
274  * Returns: true  on success
275  *          false on failure
276  */
277 bool bnet_tls_client(TLS_CONTEXT *ctx, BSOCK * bsock, alist *verify_list)
278 {
279    TLS_CONNECTION *tls;
280
281    tls  = new_tls_connection(ctx, bsock->m_fd);
282    if (!tls) {
283       Qmsg0(bsock->jcr(), M_FATAL, 0, _("TLS connection initialization failed.\n"));
284       return false;
285    }
286
287    bsock->tls = tls;
288
289    /* Initiate TLS Negotiation */
290    if (!tls_bsock_connect(bsock)) {
291       goto err;
292    }
293
294    /* If there's an Allowed CN verify list, use that to validate the remote
295     * certificate's CN. Otherwise, we use standard host/CN matching. */
296    if (verify_list) {
297       if (!tls_postconnect_verify_cn(tls, verify_list)) {
298          Qmsg1(bsock->jcr(), M_FATAL, 0, _("TLS certificate verification failed."
299                                          " Peer certificate did not match a required commonName\n"),
300                                          bsock->host());
301          goto err;
302       }
303    } else {
304       if (!tls_postconnect_verify_host(tls, bsock->host())) {
305          Qmsg1(bsock->jcr(), M_FATAL, 0, _("TLS host certificate verification failed. Host %s did not match presented certificate\n"), 
306                bsock->host());
307          goto err;
308       }
309    }
310
311    return true;
312
313 err:
314    free_tls_connection(tls);
315    bsock->tls = NULL;
316    return false;
317 }
318 #else
319
320 bool bnet_tls_server(TLS_CONTEXT *ctx, BSOCK * bsock, alist *verify_list)
321 {
322    Jmsg(bsock->jcr(), M_ABORT, 0, _("TLS enabled but not configured.\n"));
323    return false;
324 }
325
326 bool bnet_tls_client(TLS_CONTEXT *ctx, BSOCK * bsock, alist *verify_list)
327 {
328    Jmsg(bsock->jcr(), M_ABORT, 0, _("TLS enable but not configured.\n"));
329    return false;
330 }
331
332 #endif /* HAVE_TLS */
333
334 /*
335  * Wait for a specified time for data to appear on
336  * the BSOCK connection.
337  *
338  *   Returns: 1 if data available
339  *            0 if timeout
340  *           -1 if error
341  */
342 int bnet_wait_data(BSOCK * bsock, int sec)
343 {
344    fd_set fdset;
345    struct timeval tv;
346
347    FD_ZERO(&fdset);
348    FD_SET((unsigned)bsock->m_fd, &fdset);
349    for (;;) {
350       tv.tv_sec = sec;
351       tv.tv_usec = 0;
352       switch (select(bsock->m_fd + 1, &fdset, NULL, NULL, &tv)) {
353       case 0:                      /* timeout */
354          bsock->b_errno = 0;
355          return 0;
356       case -1:
357          bsock->b_errno = errno;
358          if (errno == EINTR) {
359             continue;
360          }
361          return -1;                /* error return */
362       default:
363          bsock->b_errno = 0;
364          return 1;
365       }
366    }
367 }
368
369 /*
370  * As above, but returns on interrupt
371  */
372 int bnet_wait_data_intr(BSOCK * bsock, int sec)
373 {
374    fd_set fdset;
375    struct timeval tv;
376
377    FD_ZERO(&fdset);
378    FD_SET((unsigned)bsock->m_fd, &fdset);
379    tv.tv_sec = sec;
380    tv.tv_usec = 0;
381    switch (select(bsock->m_fd + 1, &fdset, NULL, NULL, &tv)) {
382    case 0:                      /* timeout */
383       bsock->b_errno = 0;
384       return 0;
385    case -1:
386       bsock->b_errno = errno;
387       return -1;                /* error return */
388    default:
389       bsock->b_errno = 0;
390    }
391    return 1;
392 }
393
394 #ifndef NETDB_INTERNAL
395 #define NETDB_INTERNAL  -1         /* See errno. */
396 #endif
397 #ifndef NETDB_SUCCESS
398 #define NETDB_SUCCESS   0          /* No problem. */
399 #endif
400 #ifndef HOST_NOT_FOUND
401 #define HOST_NOT_FOUND  1          /* Authoritative Answer Host not found. */
402 #endif
403 #ifndef TRY_AGAIN
404 #define TRY_AGAIN       2          /* Non-Authoritative Host not found, or SERVERFAIL. */
405 #endif
406 #ifndef NO_RECOVERY
407 #define NO_RECOVERY     3          /* Non recoverable errors, FORMERR, REFUSED, NOTIMP. */
408 #endif
409 #ifndef NO_DATA
410 #define NO_DATA         4          /* Valid name, no data record of requested type. */
411 #endif
412
413 /*
414  * Get human readable error for gethostbyname()
415  */
416 static const char *gethost_strerror()
417 {
418    const char *msg;
419    berrno be;
420    switch (h_errno) {
421    case NETDB_INTERNAL:
422       msg = be.bstrerror();
423       break;
424    case NETDB_SUCCESS:
425       msg = _("No problem.");
426       break;
427    case HOST_NOT_FOUND:
428       msg = _("Authoritative answer for host not found.");
429       break;
430    case TRY_AGAIN:
431       msg = _("Non-authoritative for host not found, or ServerFail.");
432       break;
433    case NO_RECOVERY:
434       msg = _("Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.");
435       break;
436    case NO_DATA:
437       msg = _("Valid name, no data record of resquested type.");
438       break;
439    default:
440       msg = _("Unknown error.");
441    }
442    return msg;
443 }
444
445
446
447
448 static IPADDR *add_any(int family)
449 {
450    IPADDR *addr = New(IPADDR(family));
451    addr->set_type(IPADDR::R_MULTIPLE);
452    addr->set_addr_any();
453    return addr;
454 }
455
456 static const char *resolv_host(int family, const char *host, dlist * addr_list)
457 {
458    struct hostent *hp;
459    const char *errmsg;
460
461    P(ip_mutex);                       /* gethostbyname() is not thread safe */
462 #ifdef HAVE_GETHOSTBYNAME2
463    if ((hp = gethostbyname2(host, family)) == NULL) {
464 #else
465    if ((hp = gethostbyname(host)) == NULL) {
466 #endif
467       /* may be the strerror give not the right result -:( */
468       errmsg = gethost_strerror();
469       V(ip_mutex);
470       return errmsg;
471    } else {
472       char **p;
473       for (p = hp->h_addr_list; *p != 0; p++) {
474          IPADDR *addr =  New(IPADDR(hp->h_addrtype));
475          addr->set_type(IPADDR::R_MULTIPLE);
476          if (addr->get_family() == AF_INET) {
477              addr->set_addr4((struct in_addr*)*p);
478          }
479 #ifdef HAVE_IPV6
480          else {
481              addr->set_addr6((struct in6_addr*)*p);
482          }
483 #endif
484          addr_list->append(addr);
485       }
486       V(ip_mutex);
487    }
488    return NULL;
489 }
490
491 /*
492  * i host = 0 mean INADDR_ANY only ipv4
493  */
494 dlist *bnet_host2ipaddrs(const char *host, int family, const char **errstr)
495 {
496    struct in_addr inaddr;
497    IPADDR *addr = 0;
498    const char *errmsg;
499 #ifdef HAVE_IPV6
500    struct in6_addr inaddr6;
501 #endif
502
503    dlist *addr_list = New(dlist(addr, &addr->link));
504    if (!host || host[0] == '\0') {
505       if (family != 0) {
506          addr_list->append(add_any(family));
507       } else {
508          addr_list->append(add_any(AF_INET));
509 #ifdef HAVE_IPV6
510          addr_list->append(add_any(AF_INET6));
511 #endif
512       }
513    } else if (inet_aton(host, &inaddr)) { /* MA Bug 4 */
514       addr = New(IPADDR(AF_INET));
515       addr->set_type(IPADDR::R_MULTIPLE);
516       addr->set_addr4(&inaddr);
517       addr_list->append(addr);
518    } else
519 #ifdef HAVE_IPV6
520    if (inet_pton(AF_INET6, host, &inaddr6) > 1) {
521       addr = New(IPADDR(AF_INET6));
522       addr->set_type(IPADDR::R_MULTIPLE);
523       addr->set_addr6(&inaddr6);
524       addr_list->append(addr);
525    } else
526 #endif
527    {
528       if (family != 0) {
529          errmsg = resolv_host(family, host, addr_list);
530          if (errmsg) {
531             *errstr = errmsg;
532             free_addresses(addr_list);
533             return 0;
534          }
535       } else {
536          errmsg = resolv_host(AF_INET, host, addr_list);
537 #ifdef HAVE_IPV6
538          if (errmsg) {
539             errmsg = resolv_host(AF_INET6, host, addr_list);
540          }
541 #endif
542          if (errmsg) {
543             *errstr = errmsg;
544             free_addresses(addr_list);
545             return 0;
546          }
547       }
548    }
549    return addr_list;
550 }
551
552 /*
553  * Open a TCP connection to the UPS network server
554  * Returns NULL
555  * Returns BSOCK * pointer on success
556  *
557  */
558 static BSOCK *bnet_open(JCR *jcr, const char *name, char *host, char *service,
559                         int port, utime_t heart_beat, int *fatal)
560 {
561    int sockfd = -1;
562    dlist *addr_list;
563    IPADDR *ipaddr;
564    bool connected = false;
565    int turnon = 1;
566    const char *errstr;
567    int save_errno = 0;
568
569    /*
570     * Fill in the structure serv_addr with the address of
571     * the server that we want to connect with.
572     */
573    if ((addr_list = bnet_host2ipaddrs(host, 0, &errstr)) == NULL) {
574       /* Note errstr is not malloc'ed */
575       Qmsg2(jcr, M_ERROR, 0, _("gethostbyname() for host \"%s\" failed: ERR=%s\n"),
576             host, errstr);
577       Dmsg2(100, "bnet_host2ipaddrs() for host %s failed: ERR=%s\n",
578             host, errstr);
579       *fatal = 1;
580       return NULL;
581    }
582
583    foreach_dlist(ipaddr, addr_list) {
584       ipaddr->set_port_net(htons(port));
585       char allbuf[256 * 10];
586       char curbuf[256];
587       Dmsg2(100, "Current %sAll %s\n",
588                    ipaddr->build_address_str(curbuf, sizeof(curbuf)),
589                    build_addresses_str(addr_list, allbuf, sizeof(allbuf)));
590       /* Open a TCP socket */
591       if ((sockfd = socket(ipaddr->get_family(), SOCK_STREAM, 0)) < 0) {
592          berrno be;
593          save_errno = errno;
594          *fatal = 1;
595          Pmsg3(000, _("Socket open error. proto=%d port=%d. ERR=%s\n"),
596             ipaddr->get_family(), ipaddr->get_port_host_order(), be.bstrerror());
597          continue;
598       }
599       /*
600        * Keep socket from timing out from inactivity
601        */
602       if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
603          berrno be;
604          Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
605                be.bstrerror());
606       }
607 #if defined(TCP_KEEPIDLE)
608       if (heart_beat) {
609          int opt = heart_beat
610          if (setsockopt(sockfd, IPPROTO_IP, TCP_KEEPIDLE, (sockopt_val_t)&opt, sizeof(opt)) < 0) {
611             berrno be;
612             Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPIDLE on socket: %s\n"),
613                   be.bstrerror());
614          }
615       }
616 #endif
617
618       /* connect to server */
619       if (connect(sockfd, ipaddr->get_sockaddr(), ipaddr->get_sockaddr_len()) < 0) {
620          save_errno = errno;
621          socketClose(sockfd);
622          continue;
623       }
624       *fatal = 0;
625       connected = true;
626       break;
627    }
628
629    if (!connected) {
630       free_addresses(addr_list);
631       errno = save_errno | b_errno_win32;
632       return NULL;
633    }
634    /*
635     * Keep socket from timing out from inactivity
636     *   Do this a second time out of paranoia
637     */
638    if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
639       berrno be;
640       Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
641             be.bstrerror());
642    }
643    BSOCK* ret =  init_bsock(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
644    free_addresses(addr_list);
645    return ret;
646 }
647
648
649 #ifdef xxx
650 BSOCK *bnet_connect(JCR * jcr, int retry_interval, utime_t max_retry_time,
651                     utime_t heart_beat,
652                     const char *name, char *host, char *service, int port,
653                     int verbose)
654 {
655    BSOCK *bsock = new BSOCK();
656    if (!bsock->connect(jcr, retry_interval, max_retry_time, heart_beat,
657                        name, host, service, port, verbose)) {
658        delete bsock;
659        bsock = NULL;
660    }
661    return bsock;
662 }
663 #endif
664
665
666 /*
667  * Try to connect to host for max_retry_time at retry_time intervals.
668  */
669 BSOCK *bnet_connect(JCR * jcr, int retry_interval, utime_t max_retry_time,
670                     utime_t heart_beat,
671                     const char *name, char *host, char *service, int port,
672                     int verbose)
673 {
674    int i;
675    BSOCK *bsock;
676    int fatal = 0;
677    time_t begin_time = time(NULL);
678    time_t now;
679    btimer_t *tid = NULL;
680
681    /* Try to trap out of OS call when time expires */
682    if (max_retry_time) {
683       tid = start_thread_timer(pthread_self(), (uint32_t)max_retry_time);
684    }
685    
686    for (i = 0; (bsock = bnet_open(jcr, name, host, service, port, heart_beat, &fatal)) == NULL;
687         i -= retry_interval) {
688       berrno be;
689       if (fatal || (jcr && job_canceled(jcr))) {
690          bsock = NULL;
691          goto bail_out;
692       }
693       Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
694             name, host, port, be.bstrerror());
695       if (i < 0) {
696          i = 60 * 5;               /* complain again in 5 minutes */
697          if (verbose)
698             Qmsg4(jcr, M_WARNING, 0, _(
699                "Could not connect to %s on %s:%d. ERR=%s\n"
700                "Retrying ...\n"), name, host, port, be.bstrerror());
701       }
702       bmicrosleep(retry_interval, 0);
703       now = time(NULL);
704       if (begin_time + max_retry_time <= now) {
705          Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
706                name, host, port, be.bstrerror());
707          bsock = NULL;
708          goto bail_out;
709       }
710    }
711
712 bail_out:
713    if (tid) {
714       stop_thread_timer(tid);
715    }
716    return bsock;
717 }
718
719
720 /*
721  * Return the string for the error that occurred
722  * on the socket. Only the first error is retained.
723  */
724 const char *bnet_strerror(BSOCK * bsock)
725 {
726    berrno be;
727    if (bsock->errmsg == NULL) {
728       bsock->errmsg = get_pool_memory(PM_MESSAGE);
729    }
730    pm_strcpy(bsock->errmsg, be.bstrerror(bsock->b_errno));
731    return bsock->errmsg;
732 }
733
734 /*
735  * Format and send a message
736  *  Returns: false on error
737  *           true  on success
738  */
739 bool bnet_fsend(BSOCK * bs, const char *fmt, ...)
740 {
741    va_list arg_ptr;
742    int maxlen;
743
744    if (bs->errors || bs->is_terminated()) {
745       return false;
746    }
747    /* This probably won't work, but we vsnprintf, then if we
748     * get a negative length or a length greater than our buffer
749     * (depending on which library is used), the printf was truncated, so
750     * get a bigger buffer and try again.
751     */
752    for (;;) {
753       maxlen = sizeof_pool_memory(bs->msg) - 1;
754       va_start(arg_ptr, fmt);
755       bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
756       va_end(arg_ptr);
757       if (bs->msglen > 0 && bs->msglen < (maxlen - 5)) {
758          break;
759       }
760       bs->msg = realloc_pool_memory(bs->msg, maxlen + maxlen / 2);
761    }
762    return bs->send();
763 }
764
765 int bnet_get_peer(BSOCK *bs, char *buf, socklen_t buflen) 
766 {
767    return bs->get_peer(buf, buflen);  
768 }
769
770 /*
771  * Set the network buffer size, suggested size is in size.
772  *  Actual size obtained is returned in bs->msglen
773  *
774  *  Returns: 0 on failure
775  *           1 on success
776  */
777 bool bnet_set_buffer_size(BSOCK * bs, uint32_t size, int rw)
778 {
779    return bs->set_buffer_size(size, rw);
780 }
781
782 /*
783  * Set socket non-blocking
784  * Returns previous socket flag
785  */
786 int bnet_set_nonblocking(BSOCK *bsock) 
787 {
788    return bsock->set_nonblocking();
789 }
790
791 /*
792  * Set socket blocking
793  * Returns previous socket flags
794  */
795 int bnet_set_blocking(BSOCK *bsock) 
796 {
797    return bsock->set_blocking();
798 }
799
800 /*
801  * Restores socket flags
802  */
803 void bnet_restore_blocking (BSOCK *bsock, int flags) 
804 {
805    bsock->restore_blocking(flags);
806 }
807
808
809 /*
810  * Send a network "signal" to the other end
811  *  This consists of sending a negative packet length
812  *
813  *  Returns: false on failure
814  *           true  on success
815  */
816 bool bnet_sig(BSOCK * bs, int signal)
817 {
818    return bs->signal(signal);
819 }
820
821 /*
822  * Convert a network "signal" code into
823  * human readable ASCII.
824  */
825 const char *bnet_sig_to_ascii(BSOCK * bs)
826 {
827    static char buf[30];
828    switch (bs->msglen) {
829    case BNET_EOD:
830       return "BNET_EOD";           /* end of data stream */
831    case BNET_EOD_POLL:
832       return "BNET_EOD_POLL";
833    case BNET_STATUS:
834       return "BNET_STATUS";
835    case BNET_TERMINATE:
836       return "BNET_TERMINATE";     /* terminate connection */
837    case BNET_POLL:
838       return "BNET_POLL";
839    case BNET_HEARTBEAT:
840       return "BNET_HEARTBEAT";
841    case BNET_HB_RESPONSE:
842       return "BNET_HB_RESPONSE";
843    case BNET_PROMPT:
844       return "BNET_PROMPT";
845    default:
846       sprintf(buf, _("Unknown sig %d"), (int)bs->msglen);
847       return buf;
848    }
849 }
850
851
852 /* Initialize internal socket structure.
853  *  This probably should be done in net_open
854  */
855 BSOCK *init_bsock(JCR * jcr, int sockfd, const char *who, const char *host, int port,
856                   struct sockaddr *client_addr)
857 {
858    Dmsg3(100, "who=%s host=%s port=%d\n", who, host, port);
859    BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
860    memset(bsock, 0, sizeof(BSOCK));
861    bsock->m_fd = sockfd;
862    bsock->tls = NULL;
863    bsock->errors = 0;
864    bsock->m_blocking = 1;
865    bsock->msg = get_pool_memory(PM_MESSAGE);
866    bsock->errmsg = get_pool_memory(PM_MESSAGE);
867    bsock->set_who(bstrdup(who));
868    bsock->set_host(bstrdup(host));
869    bsock->set_port(port);
870    memset(&bsock->peer_addr, 0, sizeof(bsock->peer_addr));
871    memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
872    /*
873     * ****FIXME**** reduce this to a few hours once
874     *   heartbeats are implemented
875     */
876    bsock->timeout = 60 * 60 * 6 * 24;   /* 6 days timeout */
877    bsock->set_jcr(jcr);
878    return bsock;
879 }
880
881 BSOCK *dup_bsock(BSOCK * osock)
882 {
883    BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
884    memcpy(bsock, osock, sizeof(BSOCK));
885    bsock->msg = get_pool_memory(PM_MESSAGE);
886    bsock->errmsg = get_pool_memory(PM_MESSAGE);
887    if (osock->who()) {
888       bsock->set_who(bstrdup(osock->who()));
889    }
890    if (osock->host()) {
891       bsock->set_host(bstrdup(osock->host()));
892    }
893    bsock->m_duped = true;
894    return bsock;
895 }
896
897 /* Close the network connection */
898 void bnet_close(BSOCK * bsock)
899 {
900    bsock->close();                    /* this calls destroy */
901 }
902
903 void term_bsock(BSOCK * bsock)
904 {
905    bsock->destroy();
906 }