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