]> 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  * Try to connect to host for max_retry_time at retry_time intervals.
650  */
651 BSOCK *bnet_connect(JCR * jcr, int retry_interval, utime_t max_retry_time,
652                     utime_t heart_beat,
653                     const char *name, char *host, char *service, int port,
654                     int verbose)
655 {
656    int i;
657    BSOCK *bsock;
658    int fatal = 0;
659    time_t begin_time = time(NULL);
660    time_t now;
661    btimer_t *tid = NULL;
662
663    /* Try to trap out of OS call when time expires */
664    if (max_retry_time) {
665       tid = start_thread_timer(pthread_self(), (uint32_t)max_retry_time);
666    }
667    
668    for (i = 0; (bsock = bnet_open(jcr, name, host, service, port, heart_beat, &fatal)) == NULL;
669         i -= retry_interval) {
670       berrno be;
671       if (fatal || (jcr && job_canceled(jcr))) {
672          bsock = NULL;
673          goto bail_out;
674       }
675       Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
676             name, host, port, be.bstrerror());
677       if (i < 0) {
678          i = 60 * 5;               /* complain again in 5 minutes */
679          if (verbose)
680             Qmsg4(jcr, M_WARNING, 0, _(
681                "Could not connect to %s on %s:%d. ERR=%s\n"
682                "Retrying ...\n"), name, host, port, be.bstrerror());
683       }
684       bmicrosleep(retry_interval, 0);
685       now = time(NULL);
686       if (begin_time + max_retry_time <= now) {
687          Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
688                name, host, port, be.bstrerror());
689          bsock = NULL;
690          goto bail_out;
691       }
692    }
693
694 bail_out:
695    if (tid) {
696       stop_thread_timer(tid);
697    }
698    return bsock;
699 }
700
701
702 /*
703  * Return the string for the error that occurred
704  * on the socket. Only the first error is retained.
705  */
706 const char *bnet_strerror(BSOCK * bsock)
707 {
708    berrno be;
709    if (bsock->errmsg == NULL) {
710       bsock->errmsg = get_pool_memory(PM_MESSAGE);
711    }
712    pm_strcpy(bsock->errmsg, be.bstrerror(bsock->b_errno));
713    return bsock->errmsg;
714 }
715
716 /*
717  * Format and send a message
718  *  Returns: false on error
719  *           true  on success
720  */
721 bool bnet_fsend(BSOCK * bs, const char *fmt, ...)
722 {
723    va_list arg_ptr;
724    int maxlen;
725
726    if (bs->errors || bs->is_terminated()) {
727       return false;
728    }
729    /* This probably won't work, but we vsnprintf, then if we
730     * get a negative length or a length greater than our buffer
731     * (depending on which library is used), the printf was truncated, so
732     * get a bigger buffer and try again.
733     */
734    for (;;) {
735       maxlen = sizeof_pool_memory(bs->msg) - 1;
736       va_start(arg_ptr, fmt);
737       bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
738       va_end(arg_ptr);
739       if (bs->msglen > 0 && bs->msglen < (maxlen - 5)) {
740          break;
741       }
742       bs->msg = realloc_pool_memory(bs->msg, maxlen + maxlen / 2);
743    }
744    return bs->send();
745 }
746
747 int bnet_get_peer(BSOCK *bs, char *buf, socklen_t buflen) 
748 {
749    return bs->get_peer(buf, buflen);  
750 }
751
752 /*
753  * Set the network buffer size, suggested size is in size.
754  *  Actual size obtained is returned in bs->msglen
755  *
756  *  Returns: 0 on failure
757  *           1 on success
758  */
759 bool bnet_set_buffer_size(BSOCK * bs, uint32_t size, int rw)
760 {
761    return bs->set_buffer_size(size, rw);
762 }
763
764 /*
765  * Set socket non-blocking
766  * Returns previous socket flag
767  */
768 int bnet_set_nonblocking(BSOCK *bsock) 
769 {
770    return bsock->set_nonblocking();
771 }
772
773 /*
774  * Set socket blocking
775  * Returns previous socket flags
776  */
777 int bnet_set_blocking(BSOCK *bsock) 
778 {
779    return bsock->set_blocking();
780 }
781
782 /*
783  * Restores socket flags
784  */
785 void bnet_restore_blocking (BSOCK *bsock, int flags) 
786 {
787    bsock->restore_blocking(flags);
788 }
789
790
791 /*
792  * Send a network "signal" to the other end
793  *  This consists of sending a negative packet length
794  *
795  *  Returns: false on failure
796  *           true  on success
797  */
798 bool bnet_sig(BSOCK * bs, int signal)
799 {
800    return bs->signal(signal);
801 }
802
803 /*
804  * Convert a network "signal" code into
805  * human readable ASCII.
806  */
807 const char *bnet_sig_to_ascii(BSOCK * bs)
808 {
809    static char buf[30];
810    switch (bs->msglen) {
811    case BNET_EOD:
812       return "BNET_EOD";           /* end of data stream */
813    case BNET_EOD_POLL:
814       return "BNET_EOD_POLL";
815    case BNET_STATUS:
816       return "BNET_STATUS";
817    case BNET_TERMINATE:
818       return "BNET_TERMINATE";     /* terminate connection */
819    case BNET_POLL:
820       return "BNET_POLL";
821    case BNET_HEARTBEAT:
822       return "BNET_HEARTBEAT";
823    case BNET_HB_RESPONSE:
824       return "BNET_HB_RESPONSE";
825    case BNET_PROMPT:
826       return "BNET_PROMPT";
827    default:
828       sprintf(buf, _("Unknown sig %d"), (int)bs->msglen);
829       return buf;
830    }
831 }
832
833
834 /* Initialize internal socket structure.
835  *  This probably should be done in net_open
836  */
837 BSOCK *init_bsock(JCR * jcr, int sockfd, const char *who, const char *host, int port,
838                   struct sockaddr *client_addr)
839 {
840    Dmsg3(100, "who=%s host=%s port=%d\n", who, host, port);
841    BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
842    memset(bsock, 0, sizeof(BSOCK));
843    bsock->m_fd = sockfd;
844    bsock->tls = NULL;
845    bsock->errors = 0;
846    bsock->m_blocking = 1;
847    bsock->msg = get_pool_memory(PM_MESSAGE);
848    bsock->errmsg = get_pool_memory(PM_MESSAGE);
849    bsock->set_who(bstrdup(who));
850    bsock->set_host(bstrdup(host));
851    bsock->set_port(port);
852    memset(&bsock->peer_addr, 0, sizeof(bsock->peer_addr));
853    memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
854    /*
855     * ****FIXME**** reduce this to a few hours once
856     *   heartbeats are implemented
857     */
858    bsock->timeout = 60 * 60 * 6 * 24;   /* 6 days timeout */
859    bsock->set_jcr(jcr);
860    return bsock;
861 }
862
863 BSOCK *dup_bsock(BSOCK * osock)
864 {
865    BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
866    memcpy(bsock, osock, sizeof(BSOCK));
867    bsock->msg = get_pool_memory(PM_MESSAGE);
868    bsock->errmsg = get_pool_memory(PM_MESSAGE);
869    if (osock->who()) {
870       bsock->set_who(bstrdup(osock->who()));
871    }
872    if (osock->host()) {
873       bsock->set_host(bstrdup(osock->host()));
874    }
875    bsock->m_duped = true;
876    return bsock;
877 }
878
879 /* Close the network connection */
880 void bnet_close(BSOCK * bsock)
881 {
882    bsock->close();                    /* this calls destroy */
883 }
884
885 void term_bsock(BSOCK * bsock)
886 {
887    bsock->destroy();
888 }