]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/bnet.c
9d52383d72fc4e8820d5776e73064defcdbeeab5
[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    switch (h_errno) {
523    case NETDB_INTERNAL:
524       return strerror(errno);
525    case NETDB_SUCCESS:
526       return "No problem.";
527    case HOST_NOT_FOUND:
528       return "Authoritative answer Host not found.";
529    case TRY_AGAIN:
530       return "Non-authoritative Host not found, or ServerFail.";
531    case NO_RECOVERY:
532       return "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.";
533    case NO_DATA:
534       return "Valid name, no data record of resquested type.";
535    default:
536       return "Unknown error.";
537    }
538 }
539
540
541 static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
542
543
544 static IPADDR *add_any(int family)
545 {
546    IPADDR *addr = New(IPADDR(family));
547    addr->set_type(IPADDR::R_MULTIPLE);
548    addr->set_addr_any();
549    return addr;
550 }
551
552 static int resolv_host(int family, const char *host, dlist * addr_list,
553                        const char **errstr)
554 {
555    struct hostent *hp;
556
557    P(ip_mutex);
558 #ifdef HAVE_GETHOSTBYNAME2
559    if ((hp = gethostbyname2(host, family)) == NULL) {
560 #else
561    if ((hp = gethostbyname(host)) == NULL) {
562 #endif
563       /* may be the strerror give not the right result -:( */
564       *errstr = gethost_strerror();
565       V(ip_mutex);
566       return 0;
567    } else {
568       char **p;
569       for (p = hp->h_addr_list; *p != 0; p++) {
570          IPADDR *addr =  New(IPADDR(hp->h_addrtype));
571          addr->set_type(IPADDR::R_MULTIPLE);
572          if (addr->get_family() == AF_INET) {
573              addr->set_addr4((struct in_addr*)*p);
574          }
575 #ifdef HAVE_IPV6
576          else {
577              addr->set_addr6((struct in6_addr*)*p);
578          }
579 #endif
580          addr_list->append(addr);
581       }
582       V(ip_mutex);
583    }
584    return 1;
585 }
586
587 /*
588  * i host = 0 mean INADDR_ANY only ipv4
589  */
590 dlist *bnet_host2ipaddrs(const char *host, int family, const char **errstr)
591 {
592    struct in_addr inaddr;
593    IPADDR *addr = 0;
594 #ifdef HAVE_IPV6
595    struct in6_addr inaddr6;
596 #endif
597
598    dlist *addr_list = New(dlist(addr, &addr->link));
599    if (!host || host[0] == '\0') {
600       if (family != 0) {
601          addr_list->append(add_any(family));
602       } else {
603          addr_list->append(add_any(AF_INET));
604 #ifdef HAVE_IPV6
605          addr_list->append(add_any(AF_INET6));
606 #endif
607       }
608    } else if (inet_aton(host, &inaddr)) { /* MA Bug 4 */
609       addr = New(IPADDR(AF_INET));
610       addr->set_type(IPADDR::R_MULTIPLE);
611       addr->set_addr4(&inaddr);
612       addr_list->append(addr);
613    } else
614 #ifdef HAVE_IPV6
615    if (inet_pton(AF_INET6, host, &inaddr6) > 1) {
616       addr = New(IPADDR(AF_INET6));
617       addr->set_type(IPADDR::R_MULTIPLE);
618       addr->set_addr6(&inaddr6);
619       addr_list->append(addr);
620    } else
621 #endif
622    {
623       if (family != 0) {
624          if (!resolv_host(family, host, addr_list, errstr)) {
625             free_addresses(addr_list);
626             return 0;
627          }
628       } else {
629          int done = 0;
630          done |= resolv_host(AF_INET, host, addr_list, errstr);
631 #ifdef HAVE_IPV6
632          done |= resolv_host(AF_INET6, host, addr_list, errstr);
633 #endif
634          if (!done) {
635             free_addresses(addr_list);
636             return 0;
637          }
638       }
639    }
640    return addr_list;
641 }
642
643 /*     
644  * Open a TCP connection to the UPS network server
645  * Returns NULL
646  * Returns BSOCK * pointer on success
647  *
648  */
649 static BSOCK *bnet_open(JCR * jcr, const char *name, char *host, char *service,
650                         int port, int *fatal)
651 {
652    int sockfd = -1;
653    dlist *addr_list;
654    IPADDR *ipaddr;
655    bool connected = false;
656    int turnon = 1;
657    const char *errstr;
658    int save_errno = 0;
659
660    /* 
661     * Fill in the structure serv_addr with the address of
662     * the server that we want to connect with.
663     */
664    if ((addr_list = bnet_host2ipaddrs(host, 0, &errstr)) == NULL) {
665       Qmsg2(jcr, M_ERROR, 0, "gethostbyname() for host \"%s\" failed: ERR=%s\n",
666             host, errstr);
667       free((void *)errstr);
668       *fatal = 1;
669       return NULL;
670    }
671
672    foreach_dlist(ipaddr, addr_list) {
673       ipaddr->set_port_net(htons(port));
674       char allbuf[256 * 10];
675       char curbuf[256];
676       Dmsg2(100, "Current %sAll %s\n", 
677                    ipaddr->build_address_str(curbuf, sizeof(curbuf)), 
678                    build_addresses_str(addr_list, allbuf, sizeof(allbuf)));
679       /* Open a TCP socket */
680       if ((sockfd = socket(ipaddr->get_family(), SOCK_STREAM, 0)) < 0) {
681          berrno be;
682          save_errno = errno;
683          *fatal = 1;
684          Pmsg3(000, "Socket open error. proto=%d port=%d. ERR=%s\n", 
685             ipaddr->get_family(), ipaddr->get_port_host_order(), be.strerror());
686          continue;
687       }
688       /*
689        * Receive notification when connection dies.
690        */
691       if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t) & turnon,
692            sizeof(turnon)) < 0) {
693          berrno be;
694          Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
695                be.strerror());
696       }
697       /* connect to server */
698       if (connect(sockfd, ipaddr->get_sockaddr(), ipaddr->get_sockaddr_len()) < 0) {
699          save_errno = errno;
700          close(sockfd);
701          continue;
702       }
703       *fatal = 0;
704       connected = true;
705       break;
706    }
707
708    if (!connected) {
709          free_addresses(addr_list);
710       errno = save_errno;
711       return NULL;
712    }
713    BSOCK* ret =  init_bsock(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
714    free_addresses(addr_list);
715    return ret;
716 }
717
718 /*
719  * Try to connect to host for max_retry_time at retry_time intervals.
720  */
721 BSOCK *bnet_connect(JCR * jcr, int retry_interval, int max_retry_time,
722                     const char *name, char *host, char *service, int port,
723                     int verbose)
724 {
725    int i;
726    BSOCK *bsock;
727    int fatal = 0;
728
729    for (i = 0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL;
730         i -= retry_interval) {
731       berrno be;
732       if (fatal || (jcr && job_canceled(jcr))) {
733          return NULL;
734       }
735       Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
736             name, host, port, be.strerror());
737       if (i < 0) {
738          i = 60 * 5;               /* complain again in 5 minutes */
739          if (verbose)
740             Qmsg4(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
741 Retrying ...\n", name, host, port, be.strerror());
742       }
743       bmicrosleep(retry_interval, 0);
744       max_retry_time -= retry_interval;
745       if (max_retry_time <= 0) {
746          Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
747                name, host, port, be.strerror());
748          return NULL;
749       }
750    }
751    return bsock;
752 }
753
754
755 /*
756  * Return the string for the error that occurred
757  * on the socket. Only the first error is retained.
758  */
759 char *bnet_strerror(BSOCK * bsock)
760 {
761    return strerror(bsock->b_errno);
762 }
763
764 /*
765  * Format and send a message
766  *  Returns: false on error
767  *           true  on success
768  */
769 bool bnet_fsend(BSOCK * bs, const char *fmt, ...)
770 {
771    va_list arg_ptr;
772    int maxlen;
773
774    if (bs->errors || bs->terminated) {
775       return false;
776    }
777    /* This probably won't work, but we vsnprintf, then if we
778     * get a negative length or a length greater than our buffer
779     * (depending on which library is used), the printf was truncated, so
780     * get a bigger buffer and try again.
781     */
782    for (;;) {
783       maxlen = sizeof_pool_memory(bs->msg) - 1;
784       va_start(arg_ptr, fmt);
785       bs->msglen = bvsnprintf(mp_chr(bs->msg), maxlen, fmt, arg_ptr);
786       va_end(arg_ptr);
787       if (bs->msglen > 0 && bs->msglen < (maxlen - 5)) {
788          break;
789       }
790       bs->msg = realloc_pool_memory(bs->msg, maxlen + maxlen / 2);
791    }
792    return bnet_send(bs);
793 }
794
795 /* 
796  * Set the network buffer size, suggested size is in size.
797  *  Actual size obtained is returned in bs->msglen
798  *
799  *  Returns: 0 on failure
800  *           1 on success
801  */
802 bool bnet_set_buffer_size(BSOCK * bs, uint32_t size, int rw)
803 {
804    uint32_t dbuf_size, start_size;
805 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
806    int opt;
807
808    opt = IPTOS_THROUGHPUT;
809    setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t) & opt, sizeof(opt));
810 #endif
811
812    if (size != 0) {
813       dbuf_size = size;
814    } else {
815       dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
816    }
817    start_size = dbuf_size;
818    if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size + 100)) == NULL) {
819       Qmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
820       return false;
821    }
822    if (rw & BNET_SETBUF_READ) {
823       while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET, 
824               SO_RCVBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
825          berrno be;
826          Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
827          dbuf_size -= TAPE_BSIZE;
828       }
829       Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
830       if (dbuf_size != start_size) {
831          Qmsg1(bs->jcr, M_WARNING, 0,
832                _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
833       }
834       if (dbuf_size % TAPE_BSIZE != 0) {
835          Qmsg1(bs->jcr, M_ABORT, 0,
836                _("Network buffer size %d not multiple of tape block size.\n"),
837                dbuf_size);
838       }
839    }
840    if (size != 0) {
841       dbuf_size = size;
842    } else {
843       dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
844    }
845    start_size = dbuf_size;
846    if (rw & BNET_SETBUF_WRITE) {
847       while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET, 
848               SO_SNDBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
849          berrno be;
850          Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
851          dbuf_size -= TAPE_BSIZE;
852       }
853       Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
854       if (dbuf_size != start_size) {
855          Qmsg1(bs->jcr, M_WARNING, 0,
856                _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
857       }
858       if (dbuf_size % TAPE_BSIZE != 0) {
859          Qmsg1(bs->jcr, M_ABORT, 0,
860                _("Network buffer size %d not multiple of tape block size.\n"),
861                dbuf_size);
862       }
863    }
864
865    bs->msglen = dbuf_size;
866    return true;
867 }
868
869 /*
870  * Send a network "signal" to the other end 
871  *  This consists of sending a negative packet length
872  *
873  *  Returns: false on failure
874  *           true  on success
875  */
876 bool bnet_sig(BSOCK * bs, int sig)
877 {
878    bs->msglen = sig;
879    return bnet_send(bs);
880 }
881
882 /*
883  * Convert a network "signal" code into
884  * human readable ASCII.
885  */
886 const char *bnet_sig_to_ascii(BSOCK * bs)
887 {
888    static char buf[30];
889    switch (bs->msglen) {
890    case BNET_EOD:
891       return "BNET_EOD";           /* end of data stream */
892    case BNET_EOD_POLL:
893       return "BNET_EOD_POLL";
894    case BNET_STATUS:
895       return "BNET_STATUS";
896    case BNET_TERMINATE:
897       return "BNET_TERMINATE";     /* terminate connection */
898    case BNET_POLL:
899       return "BNET_POLL";
900    case BNET_HEARTBEAT:
901       return "BNET_HEARTBEAT";
902    case BNET_HB_RESPONSE:
903       return "BNET_HB_RESPONSE";
904    case BNET_PROMPT:
905       return "BNET_PROMPT";
906    default:
907       sprintf(buf, "Unknown sig %d", bs->msglen);
908       return buf;
909    }
910 }
911
912
913 /* Initialize internal socket structure.  
914  *  This probably should be done in net_open
915  */
916 BSOCK *init_bsock(JCR * jcr, int sockfd, const char *who, const char *host, int port,
917                   struct sockaddr *client_addr)
918 {
919    Dmsg3(100, "who=%s host=%s port=%d\n", who, host, port);
920    BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
921    memset(bsock, 0, sizeof(BSOCK));
922    bsock->fd = sockfd;
923    bsock->errors = 0;
924    bsock->msg = get_pool_memory(PM_MESSAGE);
925    bsock->errmsg = get_pool_memory(PM_MESSAGE);
926    bsock->who = bstrdup(who);
927    bsock->host = bstrdup(host);
928    bsock->port = port;
929    memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
930    /*
931     * ****FIXME**** reduce this to a few hours once   
932     *   heartbeats are implemented
933     */
934    bsock->timeout = 60 * 60 * 6 * 24;   /* 6 days timeout */
935    bsock->jcr = jcr;
936    return bsock;
937 }
938
939 BSOCK *dup_bsock(BSOCK * osock)
940 {
941    BSOCK *bsock = (BSOCK *) malloc(sizeof(BSOCK));
942    memcpy(bsock, osock, sizeof(BSOCK));
943    bsock->msg = get_pool_memory(PM_MESSAGE);
944    bsock->errmsg = get_pool_memory(PM_MESSAGE);
945    if (osock->who) {
946       bsock->who = bstrdup(osock->who);
947    }
948    if (osock->host) {
949       bsock->host = bstrdup(osock->host);
950    }
951    bsock->duped = true;
952    return bsock;
953 }
954
955 /* Close the network connection */
956 void bnet_close(BSOCK * bsock)
957 {
958    BSOCK *next;
959
960    for (; bsock != NULL; bsock = next) {
961       next = bsock->next;
962       if (!bsock->duped) {
963          if (bsock->timed_out) {
964             shutdown(bsock->fd, 2);     /* discard any pending I/O */
965          }
966          socketClose(bsock->fd);   /* normal close */
967       }
968       term_bsock(bsock);
969    }
970    return;
971 }
972
973 void term_bsock(BSOCK * bsock)
974 {
975    if (bsock->msg) {
976       free_pool_memory(bsock->msg);
977       bsock->msg = NULL;
978    } else {
979       ASSERT(1 == 0);              /* double close */
980    }
981    if (bsock->errmsg) {
982       free_pool_memory(bsock->errmsg);
983       bsock->errmsg = NULL;
984    }
985    if (bsock->who) {
986       free(bsock->who);
987       bsock->who = NULL;
988    }
989    if (bsock->host) {
990       free(bsock->host);
991       bsock->host = NULL;
992    }
993    free(bsock);
994 }