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