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