]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/bnet.c
181574b543eefee2320f1154763a77992deb0345
[bacula/bacula] / bacula / src / lib / bnet.c
1 /*
2  * Network Utility Routines
3  *
4  *  by Kern Sibbald
5  *
6  * Adapted and enhanced for Bacula, originally written 
7  * for inclusion in the Apcupsd package
8  *
9  *   Version $Id$
10  */
11 /*
12    Copyright (C) 2000-2004 Kern Sibbald and John Walker
13
14    This library is free software; you can redistribute it and/or
15    modify it under the terms of the GNU Lesser General Public
16    License as published by the Free Software Foundation; either
17    version 2.1 of the License, or (at your option) any later version.
18
19    This library is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22    Lesser General Public License for more details.
23
24    You should have received a copy of the GNU Lesser General Public
25    License along with this library; if not, write to the Free
26    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27    MA 02111-1307, USA.
28
29  */
30
31
32 #include "bacula.h"
33 #include "jcr.h"
34 #include <netdb.h>
35
36 extern time_t watchdog_time;
37
38 #ifndef   INADDR_NONE
39 #define   INADDR_NONE    -1
40 #endif
41
42 #ifndef ENODATA                    /* not defined on BSD systems */
43 #define ENODATA EPIPE
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
57 /*
58  * Read a nbytes from the network.
59  * It is possible that the total bytes require in several
60  * read requests
61  */
62
63 static int32_t read_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes)
64 {
65    int32_t nleft, nread;
66
67    nleft = nbytes;
68    while (nleft > 0) {
69       do {
70          errno = 0;
71          nread = socketRead(bsock->fd, ptr, nleft);
72          if (bsock->timed_out || bsock->terminated) {
73             return nread;
74          }
75       } while (nread == -1 && (errno == EINTR || errno == EAGAIN));
76       if (nread <= 0) {
77          return nread;             /* error, or EOF */
78       }
79       nleft -= nread;
80       ptr += nread;
81    }
82    return nbytes - nleft;          /* return >= 0 */
83 }
84
85 /*
86  * Write nbytes to the network.
87  * It may require several writes.
88  */
89
90 static int32_t write_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes)
91 {
92    int32_t nleft, nwritten;
93
94    if (bsock->spool) {
95       nwritten = fwrite(ptr, 1, nbytes, bsock->spool_fd);
96       if (nwritten != nbytes) {
97          berrno be;
98          Qmsg1(bsock->jcr, M_FATAL, 0, _("Attr spool write error. ERR=%s\n"),
99                be.strerror());
100          Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes);
101          return -1;
102       }
103       return nbytes;
104    }
105    nleft = nbytes;
106    while (nleft > 0) {
107       do {
108          errno = 0;
109          nwritten = socketWrite(bsock->fd, ptr, nleft);
110          if (bsock->timed_out || bsock->terminated) {
111             return nwritten;
112          }
113       } while (nwritten == -1 && errno == EINTR);
114       /*
115        * If connection is non-blocking, we will get EAGAIN, so
116        * use select() to keep from consuming all the CPU
117        * and try again.
118        */
119       if (nwritten == -1 && errno == EAGAIN) {
120          fd_set fdset;
121          struct timeval tv;
122
123          FD_ZERO(&fdset);
124          FD_SET((unsigned)bsock->fd, &fdset);
125          tv.tv_sec = 10;
126          tv.tv_usec = 0;
127          select(bsock->fd + 1, NULL, &fdset, NULL, &tv);
128          continue;
129       }
130       if (nwritten <= 0) {
131          return nwritten;          /* error */
132       }
133       nleft -= nwritten;
134       ptr += nwritten;
135    }
136    return nbytes - nleft;
137 }
138
139 /* 
140  * Receive a message from the other end. Each message consists of
141  * two packets. The first is a header that contains the size
142  * of the data that follows in the second packet.
143  * Returns number of bytes read (may return zero)
144  * Returns -1 on signal (BNET_SIGNAL) 
145  * Returns -2 on hard end of file (BNET_HARDEOF)
146  * Returns -3 on error  (BNET_ERROR)
147  *
148  *  Unfortunately, it is a bit complicated because we have these
149  *    four return types:
150  *    1. Normal data
151  *    2. Signal including end of data stream
152  *    3. Hard end of file                 
153  *    4. Error
154  *  Using is_bnet_stop() and is_bnet_error() you can figure this all out.
155  */
156 int32_t bnet_recv(BSOCK * bsock)
157 {
158    int32_t nbytes;
159    int32_t pktsiz;
160
161    ASSERT(bsock != NULL);
162    bsock->msg[0] = 0;
163    if (bsock->errors || bsock->terminated) {
164       return BNET_HARDEOF;
165    }
166
167    bsock->read_seqno++;            /* bump sequence number */
168    bsock->timer_start = watchdog_time;  /* set start wait time */
169    bsock->timed_out = 0;
170    /* get data size -- in int32_t */
171    if ((nbytes = read_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
172       bsock->timer_start = 0;      /* clear timer */
173       /* probably pipe broken because client died */
174       if (errno == 0) {
175          bsock->b_errno = ENODATA;
176       } else {
177          bsock->b_errno = errno;
178       }
179       bsock->errors++;
180       return BNET_HARDEOF;         /* assume hard EOF received */
181    }
182    bsock->timer_start = 0;         /* clear timer */
183    if (nbytes != sizeof(int32_t)) {
184       bsock->errors++;
185       bsock->b_errno = EIO;
186       Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
187             sizeof(int32_t), nbytes, bsock->who, bsock->host, bsock->port);
188       return BNET_ERROR;
189    }
190
191    pktsiz = ntohl(pktsiz);         /* decode no. of bytes that follow */
192
193    if (pktsiz == 0) {              /* No data transferred */
194       bsock->timer_start = 0;      /* clear timer */
195       bsock->in_msg_no++;
196       bsock->msglen = 0;
197       return 0;                    /* zero bytes read */
198    }
199
200    /* If signal or packet size too big */
201    if (pktsiz < 0 || pktsiz > 1000000) {
202       if (pktsiz > 0) {            /* if packet too big */
203          Qmsg3(bsock->jcr, M_FATAL, 0,
204                _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
205                bsock->who, bsock->host, bsock->port);
206          pktsiz = BNET_TERMINATE;  /* hang up */
207       }
208       if (pktsiz == BNET_TERMINATE) {
209          bsock->terminated = 1;
210       }
211       bsock->timer_start = 0;      /* clear timer */
212       bsock->b_errno = ENODATA;
213       bsock->msglen = pktsiz;      /* signal code */
214       return BNET_SIGNAL;          /* signal */
215    }
216
217    /* Make sure the buffer is big enough + one byte for EOS */
218    if (pktsiz >= (int32_t) sizeof_pool_memory(bsock->msg)) {
219       bsock->msg = realloc_pool_memory(bsock->msg, pktsiz + 100);
220    }
221
222    bsock->timer_start = watchdog_time;  /* set start wait time */
223    bsock->timed_out = 0;
224    /* now read the actual data */
225    if ((nbytes = read_nbytes(bsock, bsock->msg, pktsiz)) <= 0) {
226       bsock->timer_start = 0;      /* clear timer */
227       if (errno == 0) {
228          bsock->b_errno = ENODATA;
229       } else {
230          bsock->b_errno = errno;
231       }
232       bsock->errors++;
233       Qmsg4(bsock->jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
234             bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
235       return BNET_ERROR;
236    }
237    bsock->timer_start = 0;         /* clear timer */
238    bsock->in_msg_no++;
239    bsock->msglen = nbytes;
240    if (nbytes != pktsiz) {
241       bsock->b_errno = EIO;
242       bsock->errors++;
243       Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
244             pktsiz, nbytes, bsock->who, bsock->host, bsock->port);
245       return BNET_ERROR;
246    }
247    /* always add a zero by to properly terminate any
248     * string that was send to us. Note, we ensured above that the
249     * buffer is at least one byte longer than the message length.
250     */
251    bsock->msg[nbytes] = 0; /* terminate in case it is a string */
252    sm_check(__FILE__, __LINE__, false);
253    return nbytes;                  /* return actual length of message */
254 }
255
256
257 /*
258  * Return 1 if there are errors on this bsock or it is closed,  
259  *   i.e. stop communicating on this line.
260  */
261 bool is_bnet_stop(BSOCK * bsock)
262 {
263    return bsock->errors || bsock->terminated;
264 }
265
266 /*
267  * Return number of errors on socket 
268  */
269 int is_bnet_error(BSOCK * bsock)
270 {
271    return bsock->errors;
272 }
273
274 /*
275  * Call here after error during closing to suppress error
276  *  messages which are due to the other end shutting down too.
277  */
278 void bnet_suppress_error_messages(BSOCK * bsock, bool flag)
279 {
280    bsock->suppress_error_msgs = flag;
281 }
282
283
284 /*
285  * Transmit spooled data now to a BSOCK
286  */
287 int bnet_despool_to_bsock(BSOCK * bsock, void update_attr_spool_size(ssize_t size),
288                           ssize_t tsize)
289 {
290    int32_t pktsiz;
291    size_t nbytes;
292    ssize_t last = 0, size = 0;
293    int count = 0;
294
295    rewind(bsock->spool_fd);
296    while (fread((char *)&pktsiz, 1, sizeof(int32_t), bsock->spool_fd) ==
297           sizeof(int32_t)) {
298       size += sizeof(int32_t);
299       bsock->msglen = ntohl(pktsiz);
300       if (bsock->msglen > 0) {
301          if (bsock->msglen > (int32_t) sizeof_pool_memory(bsock->msg)) {
302             bsock->msg = realloc_pool_memory(bsock->msg, bsock->msglen + 1);
303          }
304          nbytes = fread(bsock->msg, 1, bsock->msglen, bsock->spool_fd);
305          if (nbytes != (size_t) bsock->msglen) {
306             berrno be;
307             Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, bsock->msglen);
308             Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
309                   be.strerror());
310             update_attr_spool_size(tsize - last);
311             return 0;
312          }
313          size += nbytes;
314          if ((++count & 0x3F) == 0) {
315             update_attr_spool_size(size - last);
316             last = size;
317          }
318       }
319       bnet_send(bsock);
320    }
321    update_attr_spool_size(tsize - last);
322    if (ferror(bsock->spool_fd)) {
323       berrno be;
324       Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
325             be.strerror());
326       return 0;
327    }
328    return 1;
329 }
330
331
332 /*
333  * Send a message over the network. The send consists of
334  * two network packets. The first is sends a 32 bit integer containing
335  * the length of the data packet which follows.
336  *
337  * Returns: 0 on failure
338  *          1 on success
339  */
340 bool bnet_send(BSOCK * bsock)
341 {
342    int32_t rc;
343    int32_t pktsiz;
344
345    if (bsock->errors || bsock->terminated || bsock->msglen > 1000000) {
346       return false;
347    }
348    pktsiz = htonl((int32_t) bsock->msglen);
349    /* send int32_t containing size of data packet */
350    bsock->timer_start = watchdog_time;  /* start timer */
351    bsock->timed_out = 0;
352    rc = write_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t));
353    bsock->timer_start = 0;         /* clear timer */
354    if (rc != sizeof(int32_t)) {
355       if (bsock->msglen == BNET_TERMINATE) {    /* if we were terminating */
356          bsock->terminated = 1;
357          return false;             /* ignore any errors */
358       }
359       bsock->errors++;
360       if (errno == 0) {
361          bsock->b_errno = EIO;
362       } else {
363          bsock->b_errno = errno;
364       }
365       if (rc < 0) {
366          if (!bsock->suppress_error_msgs && !bsock->timed_out) {
367             Qmsg4(bsock->jcr, M_ERROR, 0,
368                   _("Write error sending to %s:%s:%d: ERR=%s\n"), bsock->who,
369                   bsock->host, bsock->port, bnet_strerror(bsock));
370          }
371       } else {
372          Qmsg5(bsock->jcr, M_ERROR, 0,
373                _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"), bsock->who,
374                bsock->host, bsock->port, bsock->msglen, rc);
375       }
376       return false;
377    }
378
379    bsock->out_msg_no++;            /* increment message number */
380    if (bsock->msglen <= 0) {       /* length only? */
381       return true;                 /* yes, no data */
382    }
383
384    /* send data packet */
385    bsock->timer_start = watchdog_time;  /* start timer */
386    bsock->timed_out = 0;
387    rc = write_nbytes(bsock, bsock->msg, bsock->msglen);
388    bsock->timer_start = 0;         /* clear timer */
389    if (rc != bsock->msglen) {
390       bsock->errors++;
391       if (errno == 0) {
392          bsock->b_errno = EIO;
393       } else {
394          bsock->b_errno = errno;
395       }
396       if (rc < 0) {
397          if (!bsock->suppress_error_msgs) {
398             Qmsg4(bsock->jcr, M_ERROR, 0,
399                   _("Write error sending to %s:%s:%d: ERR=%s\n"), bsock->who,
400                   bsock->host, bsock->port, bnet_strerror(bsock));
401          }
402       } else {
403          Qmsg5(bsock->jcr, M_ERROR, 0,
404                _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
405                bsock->msglen, bsock->who, bsock->host, bsock->port, rc);
406       }
407       return false;
408    }
409    return true;
410 }
411
412 /*
413  * Establish an SSL connection -- server side         
414  *  Codes that ssl_need and ssl_has can take
415  *    BNET_SSL_NONE      I cannot do ssl
416  *    BNET_SSL_OK        I can do ssl, but it is not required on my end
417  *    BNET_SSL_REQUIRED  ssl is required on my end
418  */
419 int bnet_ssl_server(BSOCK * bsock, char *password, int ssl_need, int ssl_has)
420 {
421    /* Check to see if what we need (ssl_need) corresponds to what he has (ssl_has) */
422    /* The other side expects a response from us */
423    return 1;
424 }
425
426 /*
427  * Establish an SSL connection -- client side   
428  */
429 int bnet_ssl_client(BSOCK * bsock, char *password, int ssl_need)
430 {
431    /* We are the client so we must wait for the server to notify us */
432    return 1;
433 }
434
435
436 /*
437  * Wait for a specified time for data to appear on
438  * the BSOCK connection.
439  *
440  *   Returns: 1 if data available
441  *            0 if timeout
442  *           -1 if error
443  */
444 int bnet_wait_data(BSOCK * bsock, int sec)
445 {
446    fd_set fdset;
447    struct timeval tv;
448
449    FD_ZERO(&fdset);
450    FD_SET((unsigned)bsock->fd, &fdset);
451    tv.tv_sec = sec;
452    tv.tv_usec = 0;
453    for (;;) {
454       switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
455       case 0:                      /* timeout */
456          bsock->b_errno = 0;
457          return 0;
458       case -1:
459          bsock->b_errno = errno;
460          if (errno == EINTR || errno == EAGAIN) {
461             continue;
462          }
463          return -1;                /* error return */
464       default:
465          bsock->b_errno = 0;
466          return 1;
467       }
468    }
469 }
470
471 /*
472  * As above, but returns on interrupt
473  */
474 int bnet_wait_data_intr(BSOCK * bsock, int sec)
475 {
476    fd_set fdset;
477    struct timeval tv;
478
479    FD_ZERO(&fdset);
480    FD_SET((unsigned)bsock->fd, &fdset);
481    tv.tv_sec = sec;
482    tv.tv_usec = 0;
483    for (;;) {
484       switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
485       case 0:                      /* timeout */
486          bsock->b_errno = 0;
487          return 0;
488       case -1:
489          bsock->b_errno = errno;
490          return -1;                /* error return */
491       default:
492          bsock->b_errno = 0;
493          return 1;
494       }
495    }
496 }
497
498 #ifndef NETDB_INTERNAL
499 #define NETDB_INTERNAL  -1         /* See errno. */
500 #endif
501 #ifndef NETDB_SUCCESS
502 #define NETDB_SUCCESS   0          /* No problem. */
503 #endif
504 #ifndef HOST_NOT_FOUND
505 #define HOST_NOT_FOUND  1          /* Authoritative Answer Host not found. */
506 #endif
507 #ifndef TRY_AGAIN
508 #define TRY_AGAIN       2          /* Non-Authoritative Host not found, or SERVERFAIL. */
509 #endif
510 #ifndef NO_RECOVERY
511 #define NO_RECOVERY     3          /* Non recoverable errors, FORMERR, REFUSED, NOTIMP. */
512 #endif
513 #ifndef NO_DATA
514 #define NO_DATA         4          /* Valid name, no data record of requested type. */
515 #endif
516
517 /*
518  * Get human readable error for gethostbyname()
519  */
520 static const char *gethost_strerror()
521 {
522    const char *msg;
523    switch (h_errno) {
524    case NETDB_INTERNAL:
525       msg = strerror(errno);
526       break;
527    case NETDB_SUCCESS:
528       msg = "No problem.";
529       break;
530    case HOST_NOT_FOUND:
531       msg = "Authoritative answer for host not found.";
532       break;
533    case TRY_AGAIN:
534       msg = "Non-authoritative for host not found, or ServerFail.";
535       break;
536    case NO_RECOVERY:
537       msg = "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.";
538       break;
539    case NO_DATA:
540       msg = "Valid name, no data record of resquested type.";
541       break;
542    default:
543       msg = "Unknown error.";
544    }
545    return msg;
546 }
547
548
549 static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
550
551
552 static IPADDR *add_any(int family)
553 {
554    IPADDR *addr = New(IPADDR(family));
555    addr->set_type(IPADDR::R_MULTIPLE);
556    addr->set_addr_any();
557    return addr;
558 }
559
560 static const char *resolv_host(int family, const char *host, dlist * addr_list)
561 {
562    struct hostent *hp;
563    const char *errmsg;
564
565    P(ip_mutex);
566 #ifdef HAVE_GETHOSTBYNAME2
567    if ((hp = gethostbyname2(host, family)) == NULL) {
568 #else
569    if ((hp = gethostbyname(host)) == NULL) {
570 #endif
571       /* may be the strerror give not the right result -:( */
572       errmsg = gethost_strerror();
573       V(ip_mutex);
574       return errmsg;
575    } else {
576       char **p;
577       for (p = hp->h_addr_list; *p != 0; p++) {
578          IPADDR *addr =  New(IPADDR(hp->h_addrtype));
579          addr->set_type(IPADDR::R_MULTIPLE);
580          if (addr->get_family() == AF_INET) {
581              addr->set_addr4((struct in_addr*)*p);
582          }
583 #ifdef HAVE_IPV6
584          else {
585              addr->set_addr6((struct in6_addr*)*p);
586          }
587 #endif
588          addr_list->append(addr);
589       }
590       V(ip_mutex);
591    }
592    return NULL;
593 }
594
595 /*
596  * i host = 0 mean INADDR_ANY only ipv4
597  */
598 dlist *bnet_host2ipaddrs(const char *host, int family, const char **errstr)
599 {
600    struct in_addr inaddr;
601    IPADDR *addr = 0;
602    const char *errmsg;
603 #ifdef HAVE_IPV6
604    struct in6_addr inaddr6;
605 #endif
606
607    dlist *addr_list = New(dlist(addr, &addr->link));
608    if (!host || host[0] == '\0') {
609       if (family != 0) {
610          addr_list->append(add_any(family));
611       } else {
612          addr_list->append(add_any(AF_INET));
613 #ifdef HAVE_IPV6
614          addr_list->append(add_any(AF_INET6));
615 #endif
616       }
617    } else if (inet_aton(host, &inaddr)) { /* MA Bug 4 */
618       addr = New(IPADDR(AF_INET));
619       addr->set_type(IPADDR::R_MULTIPLE);
620       addr->set_addr4(&inaddr);
621       addr_list->append(addr);
622    } else
623 #ifdef HAVE_IPV6
624    if (inet_pton(AF_INET6, host, &inaddr6) > 1) {
625       addr = New(IPADDR(AF_INET6));
626       addr->set_type(IPADDR::R_MULTIPLE);
627       addr->set_addr6(&inaddr6);
628       addr_list->append(addr);
629    } else
630 #endif
631    {
632       if (family != 0) {
633          errmsg = resolv_host(family, host, addr_list);
634          if (errmsg) {
635             *errstr = errmsg;
636             free_addresses(addr_list);
637             return 0;
638          }
639       } else {
640          errmsg = resolv_host(AF_INET, host, addr_list);
641 #ifdef HAVE_IPV6
642          if (errmsg) {
643             errmsg = resolv_host(AF_INET6, host, addr_list);
644          }
645 #endif
646          if (errmsg) {
647             *errstr = errmsg;
648             free_addresses(addr_list);
649             return 0;
650          }
651       }
652    }
653    return addr_list;
654 }
655
656 /*     
657  * Open a TCP connection to the UPS network server
658  * Returns NULL
659  * Returns BSOCK * pointer on success
660  *
661  */
662 static BSOCK *bnet_open(JCR * jcr, const char *name, char *host, char *service,
663                         int port, int *fatal)
664 {
665    int sockfd = -1;
666    dlist *addr_list;
667    IPADDR *ipaddr;
668    bool connected = false;
669    int turnon = 1;
670    const char *errstr;
671    int save_errno = 0;
672
673    /* 
674     * Fill in the structure serv_addr with the address of
675     * the server that we want to connect with.
676     */
677    if ((addr_list = bnet_host2ipaddrs(host, 0, &errstr)) == NULL) {
678       /* Note errstr is not malloc'ed */
679       Qmsg2(jcr, M_ERROR, 0, "gethostbyname() for host \"%s\" failed: ERR=%s\n",
680             host, errstr);
681       Dmsg2(100, "bnet_host2ipaddrs() for host %s failed: ERR=%s\n",
682             host, errstr);
683       *fatal = 1;
684       return NULL;
685    }
686
687    foreach_dlist(ipaddr, addr_list) {
688       ipaddr->set_port_net(htons(port));
689       char allbuf[256 * 10];
690       char curbuf[256];
691       Dmsg2(100, "Current %sAll %s\n", 
692                    ipaddr->build_address_str(curbuf, sizeof(curbuf)), 
693                    build_addresses_str(addr_list, allbuf, sizeof(allbuf)));
694       /* Open a TCP socket */
695       if ((sockfd = socket(ipaddr->get_family(), SOCK_STREAM, 0)) < 0) {
696          berrno be;
697          save_errno = errno;
698          *fatal = 1;
699          Pmsg3(000, "Socket open error. proto=%d port=%d. ERR=%s\n", 
700             ipaddr->get_family(), ipaddr->get_port_host_order(), be.strerror());
701          continue;
702       }
703       /*
704        * Keep socket from timing out from inactivity
705        */
706       if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
707          berrno be;
708          Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
709                be.strerror());
710       }
711       /* connect to server */
712       if (connect(sockfd, ipaddr->get_sockaddr(), ipaddr->get_sockaddr_len()) < 0) {
713          save_errno = errno;
714          close(sockfd);
715          continue;
716       }
717       *fatal = 0;
718       connected = true;
719       break;
720    }
721
722    if (!connected) {
723          free_addresses(addr_list);
724       errno = save_errno;
725       return NULL;
726    }
727    /*
728     * Keep socket from timing out from inactivity
729     *   Do this a second time out of paranoia
730     */
731    if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
732       berrno be;
733       Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
734             be.strerror());
735    }
736    BSOCK* ret =  init_bsock(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
737    free_addresses(addr_list);
738    return ret;
739 }
740
741 /*
742  * Try to connect to host for max_retry_time at retry_time intervals.
743  */
744 BSOCK *bnet_connect(JCR * jcr, int retry_interval, int max_retry_time,
745                     const char *name, char *host, char *service, int port,
746                     int verbose)
747 {
748    int i;
749    BSOCK *bsock;
750    int fatal = 0;
751
752    for (i = 0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL;
753         i -= retry_interval) {
754       berrno be;
755       if (fatal || (jcr && job_canceled(jcr))) {
756          return NULL;
757       }
758       Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
759             name, host, port, be.strerror());
760       if (i < 0) {
761          i = 60 * 5;               /* complain again in 5 minutes */
762          if (verbose)
763             Qmsg4(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
764 Retrying ...\n", name, host, port, be.strerror());
765       }
766       bmicrosleep(retry_interval, 0);
767       max_retry_time -= retry_interval;
768       if (max_retry_time <= 0) {
769          Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
770                name, host, port, be.strerror());
771          return NULL;
772       }
773    }
774    return bsock;
775 }
776
777
778 /*
779  * Return the string for the error that occurred
780  * on the socket. Only the first error is retained.
781  */
782 char *bnet_strerror(BSOCK * bsock)
783 {
784    return strerror(bsock->b_errno);
785 }
786
787 /*
788  * Format and send a message
789  *  Returns: false on error
790  *           true  on success
791  */
792 bool bnet_fsend(BSOCK * bs, const char *fmt, ...)
793 {
794    va_list arg_ptr;
795    int maxlen;
796
797    if (bs->errors || bs->terminated) {
798       return false;
799    }
800    /* This probably won't work, but we vsnprintf, then if we
801     * get a negative length or a length greater than our buffer
802     * (depending on which library is used), the printf was truncated, so
803     * get a bigger buffer and try again.
804     */
805    for (;;) {
806       maxlen = sizeof_pool_memory(bs->msg) - 1;
807       va_start(arg_ptr, fmt);
808       bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
809       va_end(arg_ptr);
810       if (bs->msglen > 0 && bs->msglen < (maxlen - 5)) {
811          break;
812       }
813       bs->msg = realloc_pool_memory(bs->msg, maxlen + maxlen / 2);
814    }
815    return bnet_send(bs);
816 }
817
818 /* 
819  * Set the network buffer size, suggested size is in size.
820  *  Actual size obtained is returned in bs->msglen
821  *
822  *  Returns: 0 on failure
823  *           1 on success
824  */
825 bool bnet_set_buffer_size(BSOCK * bs, uint32_t size, int rw)
826 {
827    uint32_t dbuf_size, start_size;
828 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
829    int opt;
830
831    opt = IPTOS_THROUGHPUT;
832    setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t) & opt, sizeof(opt));
833 #endif
834
835    if (size != 0) {
836       dbuf_size = size;
837    } else {
838       dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
839    }
840    start_size = dbuf_size;
841    if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size + 100)) == NULL) {
842       Qmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
843       return false;
844    }
845    if (rw & BNET_SETBUF_READ) {
846       while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET, 
847               SO_RCVBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
848          berrno be;
849          Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
850          dbuf_size -= TAPE_BSIZE;
851       }
852       Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
853       if (dbuf_size != start_size) {
854          Qmsg1(bs->jcr, M_WARNING, 0,
855                _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
856       }
857       if (dbuf_size % TAPE_BSIZE != 0) {
858          Qmsg1(bs->jcr, M_ABORT, 0,
859                _("Network buffer size %d not multiple of tape block size.\n"),
860                dbuf_size);
861       }
862    }
863    if (size != 0) {
864       dbuf_size = size;
865    } else {
866       dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
867    }
868    start_size = dbuf_size;
869    if (rw & BNET_SETBUF_WRITE) {
870       while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET, 
871               SO_SNDBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
872          berrno be;
873          Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
874          dbuf_size -= TAPE_BSIZE;
875       }
876       Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
877       if (dbuf_size != start_size) {
878          Qmsg1(bs->jcr, M_WARNING, 0,
879                _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
880       }
881       if (dbuf_size % TAPE_BSIZE != 0) {
882          Qmsg1(bs->jcr, M_ABORT, 0,
883                _("Network buffer size %d not multiple of tape block size.\n"),
884                dbuf_size);
885       }
886    }
887
888    bs->msglen = dbuf_size;
889    return true;
890 }
891
892 /*
893  * Send a network "signal" to the other end 
894  *  This consists of sending a negative packet length
895  *
896  *  Returns: false on failure
897  *           true  on success
898  */
899 bool bnet_sig(BSOCK * bs, int sig)
900 {
901    bs->msglen = sig;
902    return bnet_send(bs);
903 }
904
905 /*
906  * Convert a network "signal" code into
907  * human readable ASCII.
908  */
909 const char *bnet_sig_to_ascii(BSOCK * bs)
910 {
911    static char buf[30];
912    switch (bs->msglen) {
913    case BNET_EOD:
914       return "BNET_EOD";           /* end of data stream */
915    case BNET_EOD_POLL:
916       return "BNET_EOD_POLL";
917    case BNET_STATUS:
918       return "BNET_STATUS";
919    case BNET_TERMINATE:
920       return "BNET_TERMINATE";     /* terminate connection */
921    case BNET_POLL:
922       return "BNET_POLL";
923    case BNET_HEARTBEAT:
924       return "BNET_HEARTBEAT";
925    case BNET_HB_RESPONSE:
926       return "BNET_HB_RESPONSE";
927    case BNET_PROMPT:
928       return "BNET_PROMPT";
929    default:
930       sprintf(buf, "Unknown sig %d", bs->msglen);
931       return buf;
932    }
933 }
934
935
936 /* Initialize internal socket structure.  
937  *  This probably should be done in net_open
938  */
939 BSOCK *init_bsock(JCR * jcr, int sockfd, const char *who, const char *host, int port,
940                   struct sockaddr *client_addr)
941 {
942    Dmsg3(100, "who=%s host=%s port=%d\n", who, host, port);
943    BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
944    memset(bsock, 0, sizeof(BSOCK));
945    bsock->fd = sockfd;
946    bsock->errors = 0;
947    bsock->msg = get_pool_memory(PM_MESSAGE);
948    bsock->errmsg = get_pool_memory(PM_MESSAGE);
949    bsock->who = bstrdup(who);
950    bsock->host = bstrdup(host);
951    bsock->port = port;
952    memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
953    /*
954     * ****FIXME**** reduce this to a few hours once   
955     *   heartbeats are implemented
956     */
957    bsock->timeout = 60 * 60 * 6 * 24;   /* 6 days timeout */
958    bsock->jcr = jcr;
959    return bsock;
960 }
961
962 BSOCK *dup_bsock(BSOCK * osock)
963 {
964    BSOCK *bsock = (BSOCK *) malloc(sizeof(BSOCK));
965    memcpy(bsock, osock, sizeof(BSOCK));
966    bsock->msg = get_pool_memory(PM_MESSAGE);
967    bsock->errmsg = get_pool_memory(PM_MESSAGE);
968    if (osock->who) {
969       bsock->who = bstrdup(osock->who);
970    }
971    if (osock->host) {
972       bsock->host = bstrdup(osock->host);
973    }
974    bsock->duped = true;
975    return bsock;
976 }
977
978 /* Close the network connection */
979 void bnet_close(BSOCK * bsock)
980 {
981    BSOCK *next;
982
983    for (; bsock != NULL; bsock = next) {
984       next = bsock->next;
985       if (!bsock->duped) {
986          if (bsock->timed_out) {
987             shutdown(bsock->fd, 2);     /* discard any pending I/O */
988          }
989          socketClose(bsock->fd);   /* normal close */
990       }
991       term_bsock(bsock);
992    }
993    return;
994 }
995
996 void term_bsock(BSOCK * bsock)
997 {
998    if (bsock->msg) {
999       free_pool_memory(bsock->msg);
1000       bsock->msg = NULL;
1001    } else {
1002       ASSERT(1 == 0);              /* double close */
1003    }
1004    if (bsock->errmsg) {
1005       free_pool_memory(bsock->errmsg);
1006       bsock->errmsg = NULL;
1007    }
1008    if (bsock->who) {
1009       free(bsock->who);
1010       bsock->who = NULL;
1011    }
1012    if (bsock->host) {
1013       free(bsock->host);
1014       bsock->host = NULL;
1015    }
1016    free(bsock);
1017 }