]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/bnet.c
- Applied a patch from Peter Eriksson that removes a dynamic stack
[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    mp_chr(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, mp_chr(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    mp_chr(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, mp_chr(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          int done = 0;
641          errmsg = resolv_host(AF_INET, host, addr_list);
642 #ifdef HAVE_IPV6
643          if (errmsg) {
644             errmsg = resolv_host(AF_INET6, host, addr_list);
645             if (!errmsg) {
646                done = 1;
647             }
648          } else {  
649             done = 1;
650          }
651 #endif
652          if (!done) {
653             *errstr = errmsg;
654             free_addresses(addr_list);
655             return 0;
656          }
657       }
658    }
659    return addr_list;
660 }
661
662 /*     
663  * Open a TCP connection to the UPS network server
664  * Returns NULL
665  * Returns BSOCK * pointer on success
666  *
667  */
668 static BSOCK *bnet_open(JCR * jcr, const char *name, char *host, char *service,
669                         int port, int *fatal)
670 {
671    int sockfd = -1;
672    dlist *addr_list;
673    IPADDR *ipaddr;
674    bool connected = false;
675    int turnon = 1;
676    const char *errstr;
677    int save_errno = 0;
678
679    /* 
680     * Fill in the structure serv_addr with the address of
681     * the server that we want to connect with.
682     */
683    if ((addr_list = bnet_host2ipaddrs(host, 0, &errstr)) == NULL) {
684       /* Note errstr is not malloc'ed */
685       Qmsg2(jcr, M_ERROR, 0, "gethostbyname() for host \"%s\" failed: ERR=%s\n",
686             host, errstr);
687       *fatal = 1;
688       return NULL;
689    }
690
691    foreach_dlist(ipaddr, addr_list) {
692       ipaddr->set_port_net(htons(port));
693       char allbuf[256 * 10];
694       char curbuf[256];
695       Dmsg2(100, "Current %sAll %s\n", 
696                    ipaddr->build_address_str(curbuf, sizeof(curbuf)), 
697                    build_addresses_str(addr_list, allbuf, sizeof(allbuf)));
698       /* Open a TCP socket */
699       if ((sockfd = socket(ipaddr->get_family(), SOCK_STREAM, 0)) < 0) {
700          berrno be;
701          save_errno = errno;
702          *fatal = 1;
703          Pmsg3(000, "Socket open error. proto=%d port=%d. ERR=%s\n", 
704             ipaddr->get_family(), ipaddr->get_port_host_order(), be.strerror());
705          continue;
706       }
707       /*
708        * Receive notification when connection dies.
709        */
710       if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t) & turnon,
711            sizeof(turnon)) < 0) {
712          berrno be;
713          Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
714                be.strerror());
715       }
716       /* connect to server */
717       if (connect(sockfd, ipaddr->get_sockaddr(), ipaddr->get_sockaddr_len()) < 0) {
718          save_errno = errno;
719          close(sockfd);
720          continue;
721       }
722       *fatal = 0;
723       connected = true;
724       break;
725    }
726
727    if (!connected) {
728          free_addresses(addr_list);
729       errno = save_errno;
730       return NULL;
731    }
732    BSOCK* ret =  init_bsock(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
733    free_addresses(addr_list);
734    return ret;
735 }
736
737 /*
738  * Try to connect to host for max_retry_time at retry_time intervals.
739  */
740 BSOCK *bnet_connect(JCR * jcr, int retry_interval, int max_retry_time,
741                     const char *name, char *host, char *service, int port,
742                     int verbose)
743 {
744    int i;
745    BSOCK *bsock;
746    int fatal = 0;
747
748    for (i = 0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL;
749         i -= retry_interval) {
750       berrno be;
751       if (fatal || (jcr && job_canceled(jcr))) {
752          return NULL;
753       }
754       Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
755             name, host, port, be.strerror());
756       if (i < 0) {
757          i = 60 * 5;               /* complain again in 5 minutes */
758          if (verbose)
759             Qmsg4(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
760 Retrying ...\n", name, host, port, be.strerror());
761       }
762       bmicrosleep(retry_interval, 0);
763       max_retry_time -= retry_interval;
764       if (max_retry_time <= 0) {
765          Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
766                name, host, port, be.strerror());
767          return NULL;
768       }
769    }
770    return bsock;
771 }
772
773
774 /*
775  * Return the string for the error that occurred
776  * on the socket. Only the first error is retained.
777  */
778 char *bnet_strerror(BSOCK * bsock)
779 {
780    return strerror(bsock->b_errno);
781 }
782
783 /*
784  * Format and send a message
785  *  Returns: false on error
786  *           true  on success
787  */
788 bool bnet_fsend(BSOCK * bs, const char *fmt, ...)
789 {
790    va_list arg_ptr;
791    int maxlen;
792
793    if (bs->errors || bs->terminated) {
794       return false;
795    }
796    /* This probably won't work, but we vsnprintf, then if we
797     * get a negative length or a length greater than our buffer
798     * (depending on which library is used), the printf was truncated, so
799     * get a bigger buffer and try again.
800     */
801    for (;;) {
802       maxlen = sizeof_pool_memory(bs->msg) - 1;
803       va_start(arg_ptr, fmt);
804       bs->msglen = bvsnprintf(mp_chr(bs->msg), maxlen, fmt, arg_ptr);
805       va_end(arg_ptr);
806       if (bs->msglen > 0 && bs->msglen < (maxlen - 5)) {
807          break;
808       }
809       bs->msg = realloc_pool_memory(bs->msg, maxlen + maxlen / 2);
810    }
811    return bnet_send(bs);
812 }
813
814 /* 
815  * Set the network buffer size, suggested size is in size.
816  *  Actual size obtained is returned in bs->msglen
817  *
818  *  Returns: 0 on failure
819  *           1 on success
820  */
821 bool bnet_set_buffer_size(BSOCK * bs, uint32_t size, int rw)
822 {
823    uint32_t dbuf_size, start_size;
824 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
825    int opt;
826
827    opt = IPTOS_THROUGHPUT;
828    setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t) & opt, sizeof(opt));
829 #endif
830
831    if (size != 0) {
832       dbuf_size = size;
833    } else {
834       dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
835    }
836    start_size = dbuf_size;
837    if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size + 100)) == NULL) {
838       Qmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
839       return false;
840    }
841    if (rw & BNET_SETBUF_READ) {
842       while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET, 
843               SO_RCVBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
844          berrno be;
845          Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
846          dbuf_size -= TAPE_BSIZE;
847       }
848       Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
849       if (dbuf_size != start_size) {
850          Qmsg1(bs->jcr, M_WARNING, 0,
851                _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
852       }
853       if (dbuf_size % TAPE_BSIZE != 0) {
854          Qmsg1(bs->jcr, M_ABORT, 0,
855                _("Network buffer size %d not multiple of tape block size.\n"),
856                dbuf_size);
857       }
858    }
859    if (size != 0) {
860       dbuf_size = size;
861    } else {
862       dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
863    }
864    start_size = dbuf_size;
865    if (rw & BNET_SETBUF_WRITE) {
866       while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET, 
867               SO_SNDBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
868          berrno be;
869          Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
870          dbuf_size -= TAPE_BSIZE;
871       }
872       Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
873       if (dbuf_size != start_size) {
874          Qmsg1(bs->jcr, M_WARNING, 0,
875                _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
876       }
877       if (dbuf_size % TAPE_BSIZE != 0) {
878          Qmsg1(bs->jcr, M_ABORT, 0,
879                _("Network buffer size %d not multiple of tape block size.\n"),
880                dbuf_size);
881       }
882    }
883
884    bs->msglen = dbuf_size;
885    return true;
886 }
887
888 /*
889  * Send a network "signal" to the other end 
890  *  This consists of sending a negative packet length
891  *
892  *  Returns: false on failure
893  *           true  on success
894  */
895 bool bnet_sig(BSOCK * bs, int sig)
896 {
897    bs->msglen = sig;
898    return bnet_send(bs);
899 }
900
901 /*
902  * Convert a network "signal" code into
903  * human readable ASCII.
904  */
905 const char *bnet_sig_to_ascii(BSOCK * bs)
906 {
907    static char buf[30];
908    switch (bs->msglen) {
909    case BNET_EOD:
910       return "BNET_EOD";           /* end of data stream */
911    case BNET_EOD_POLL:
912       return "BNET_EOD_POLL";
913    case BNET_STATUS:
914       return "BNET_STATUS";
915    case BNET_TERMINATE:
916       return "BNET_TERMINATE";     /* terminate connection */
917    case BNET_POLL:
918       return "BNET_POLL";
919    case BNET_HEARTBEAT:
920       return "BNET_HEARTBEAT";
921    case BNET_HB_RESPONSE:
922       return "BNET_HB_RESPONSE";
923    case BNET_PROMPT:
924       return "BNET_PROMPT";
925    default:
926       sprintf(buf, "Unknown sig %d", bs->msglen);
927       return buf;
928    }
929 }
930
931
932 /* Initialize internal socket structure.  
933  *  This probably should be done in net_open
934  */
935 BSOCK *init_bsock(JCR * jcr, int sockfd, const char *who, const char *host, int port,
936                   struct sockaddr *client_addr)
937 {
938    Dmsg3(100, "who=%s host=%s port=%d\n", who, host, port);
939    BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
940    memset(bsock, 0, sizeof(BSOCK));
941    bsock->fd = sockfd;
942    bsock->errors = 0;
943    bsock->msg = get_pool_memory(PM_MESSAGE);
944    bsock->errmsg = get_pool_memory(PM_MESSAGE);
945    bsock->who = bstrdup(who);
946    bsock->host = bstrdup(host);
947    bsock->port = port;
948    memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
949    /*
950     * ****FIXME**** reduce this to a few hours once   
951     *   heartbeats are implemented
952     */
953    bsock->timeout = 60 * 60 * 6 * 24;   /* 6 days timeout */
954    bsock->jcr = jcr;
955    return bsock;
956 }
957
958 BSOCK *dup_bsock(BSOCK * osock)
959 {
960    BSOCK *bsock = (BSOCK *) malloc(sizeof(BSOCK));
961    memcpy(bsock, osock, sizeof(BSOCK));
962    bsock->msg = get_pool_memory(PM_MESSAGE);
963    bsock->errmsg = get_pool_memory(PM_MESSAGE);
964    if (osock->who) {
965       bsock->who = bstrdup(osock->who);
966    }
967    if (osock->host) {
968       bsock->host = bstrdup(osock->host);
969    }
970    bsock->duped = true;
971    return bsock;
972 }
973
974 /* Close the network connection */
975 void bnet_close(BSOCK * bsock)
976 {
977    BSOCK *next;
978
979    for (; bsock != NULL; bsock = next) {
980       next = bsock->next;
981       if (!bsock->duped) {
982          if (bsock->timed_out) {
983             shutdown(bsock->fd, 2);     /* discard any pending I/O */
984          }
985          socketClose(bsock->fd);   /* normal close */
986       }
987       term_bsock(bsock);
988    }
989    return;
990 }
991
992 void term_bsock(BSOCK * bsock)
993 {
994    if (bsock->msg) {
995       free_pool_memory(bsock->msg);
996       bsock->msg = NULL;
997    } else {
998       ASSERT(1 == 0);              /* double close */
999    }
1000    if (bsock->errmsg) {
1001       free_pool_memory(bsock->errmsg);
1002       bsock->errmsg = NULL;
1003    }
1004    if (bsock->who) {
1005       free(bsock->who);
1006       bsock->who = NULL;
1007    }
1008    if (bsock->host) {
1009       free(bsock->host);
1010       bsock->host = NULL;
1011    }
1012    free(bsock);
1013 }