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