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