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