]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/bnet.c
change all void *jcr into JCR *jcr
[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       if (bsock->msglen == BNET_TERMINATE) { /* if we were terminating */
303          bsock->terminated = 1;
304          return 0;                    /* ignore any errors */
305       }
306       bsock->errors++;
307       if (errno == 0) {
308          bsock->b_errno = EIO;
309       } else {
310          bsock->b_errno = errno;
311       }
312       if (rc < 0) {
313          if (!bsock->suppress_error_msgs) {
314             Jmsg4(bsock->jcr, M_ERROR, 0, _("Write error sending to %s:%s:%d: ERR=%s\n"), 
315                   bsock->who, bsock->host, bsock->port,  bnet_strerror(bsock));
316          }
317       } else {
318          Jmsg5(bsock->jcr, M_ERROR, 0, _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"), 
319                bsock->who, bsock->host, bsock->port, bsock->msglen, rc);
320       }
321       return 0;
322    }
323
324    bsock->out_msg_no++;               /* increment message number */
325    if (bsock->msglen <= 0) {          /* length only? */
326       return 1;                       /* yes, no data */
327    }
328
329    /* send data packet */
330    bsock->timer_start = watchdog_time; /* start timer */
331    bsock->timed_out = 0;               
332    rc = write_nbytes(bsock, bsock->msg, bsock->msglen);
333    bsock->timer_start = 0;            /* clear timer */
334    if (rc != bsock->msglen) {
335       bsock->errors++;
336       if (errno == 0) {
337          bsock->b_errno = EIO;
338       } else {
339          bsock->b_errno = errno;
340       }
341       if (rc < 0) {
342          if (!bsock->suppress_error_msgs) {
343             Jmsg4(bsock->jcr, M_ERROR, 0, _("Write error sending to %s:%s:%d: ERR=%s\n"), 
344                   bsock->who, bsock->host, bsock->port,  bnet_strerror(bsock));
345          }
346       } else {
347          Jmsg5(bsock->jcr, M_ERROR, 0, _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"), 
348                bsock->msglen, bsock->who, bsock->host, bsock->port, rc);
349       }
350       return 0;
351    }
352    return 1;
353 }
354
355 /*
356  * Establish an SSL connection -- server side         
357  *  Codes that ssl_need and ssl_has can take
358  *    BNET_SSL_NONE      I cannot do ssl
359  *    BNET_SSL_OK        I can do ssl, but it is not required on my end
360  *    BNET_SSL_REQUIRED  ssl is required on my end
361  */
362 int     
363 bnet_ssl_server(BSOCK *bsock, char *password, int ssl_need, int ssl_has)
364 {
365    /* Check to see if what we need (ssl_need) corresponds to what he has (ssl_has) */
366    /* The other side expects a response from us */
367    return 1;
368 }
369
370 /*
371  * Establish an SSL connection -- client side   
372  */
373 int bnet_ssl_client(BSOCK *bsock, char *password, int ssl_need)
374 {
375    /* We are the client so we must wait for the server to notify us */
376    return 1;
377 }
378
379
380 /*
381  * Wait for a specified time for data to appear on
382  * the BSOCK connection.
383  *
384  *   Returns: 1 if data available
385  *            0 if timeout
386  *           -1 if error
387  */
388 int 
389 bnet_wait_data(BSOCK *bsock, int sec)          
390 {
391    fd_set fdset;
392    struct timeval tv;
393
394    FD_ZERO(&fdset);
395    FD_SET(bsock->fd, &fdset);
396    tv.tv_sec = sec;
397    tv.tv_usec = 0;
398    for ( ;; ) {
399       switch(select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
400       case 0:                         /* timeout */
401          bsock->b_errno = 0;
402          return 0;
403       case -1:
404          bsock->b_errno = errno;
405          if (errno == EINTR || errno == EAGAIN) {
406             continue;
407          }
408          return -1;                  /* error return */
409       default:
410          bsock->b_errno = 0;
411          return 1;
412       }
413    }
414 }
415
416 /*
417  * As above, but returns on interrupt
418  */
419 int
420 bnet_wait_data_intr(BSOCK *bsock, int sec)          
421 {
422    fd_set fdset;
423    struct timeval tv;
424
425    FD_ZERO(&fdset);
426    FD_SET(bsock->fd, &fdset);
427    tv.tv_sec = sec;
428    tv.tv_usec = 0;
429    for ( ;; ) {
430       switch(select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
431       case 0:                         /* timeout */
432          bsock->b_errno = 0;
433          return 0;
434       case -1:
435          bsock->b_errno = errno;
436          return -1;                  /* error return */
437       default:
438          bsock->b_errno = 0;
439          return 1;
440       }
441    }
442 }
443
444
445 static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
446
447 /*
448  * Convert a hostname or dotted IP address into   
449  * a s_addr.  We handle only IPv4.
450  */
451 static uint32_t *bget_host_ip(JCR *jcr, char *host)
452 {
453    struct in_addr inaddr;
454    uint32_t *addr_list;               /* this really should be struct in_addr */
455    struct hostent *hp;
456    char **p;
457    int i;
458
459    if ((inaddr.s_addr = inet_addr(host)) != INADDR_NONE) {
460       addr_list = (uint32_t *) malloc(sizeof(uint32_t) * 2);
461       addr_list[0] = inaddr.s_addr;
462       addr_list[1] = (uint32_t) -1;
463    } else {
464       P(ip_mutex);
465       if ((hp = gethostbyname(host)) == NULL) {
466          Jmsg2(jcr, M_ERROR, 0, "gethostbyname() for %s failed: ERR=%s\n", 
467                host, strerror(errno));
468          V(ip_mutex);
469          return NULL;
470       }
471       if (hp->h_length != sizeof(inaddr.s_addr) || hp->h_addrtype != AF_INET) {
472          Jmsg2(jcr, M_ERROR, 0, _("gethostbyname() network address length error.\n\
473 Wanted %d got %d bytes for s_addr.\n"), sizeof(inaddr.s_addr), hp->h_length);
474          V(ip_mutex);
475          return NULL;
476       }
477       i = 0;
478       for (p = hp->h_addr_list; *p != 0; p++) {
479          i++;
480       }
481       i++;
482       addr_list = (uint32_t *) malloc(sizeof(uint32_t) * i);
483       i = 0;
484       for (p = hp->h_addr_list; *p != 0; p++) {
485          addr_list[i++] = (*(struct in_addr **)p)->s_addr;
486       }
487       addr_list[i] = (uint32_t) -1;
488       V(ip_mutex);
489    }
490    return addr_list;
491 }
492
493 /*     
494  * Open a TCP connection to the UPS network server
495  * Returns NULL
496  * Returns BSOCK * pointer on success
497  *
498  *  ***FIXME*** implement service from /etc/services
499  */
500 static BSOCK *
501 bnet_open(JCR *jcr, char *name, char *host, char *service, int port, int *fatal)
502 {
503    int sockfd;
504    struct sockaddr_in tcp_serv_addr;     /* socket information */
505    uint32_t *addr_list;
506    int i, connected = 0;
507    int turnon = 1;
508
509    /* 
510     * Fill in the structure serv_addr with the address of
511     * the server that we want to connect with.
512     */
513    memset((char *)&tcp_serv_addr, 0,  sizeof(tcp_serv_addr));
514    tcp_serv_addr.sin_family = AF_INET;
515    tcp_serv_addr.sin_port = htons(port);
516
517    if ((addr_list=bget_host_ip(jcr, host)) == NULL) {
518      *fatal = 1;
519      return NULL;
520    }
521
522    /* Open a TCP socket */
523    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
524       free(addr_list);
525       *fatal = 1;
526       return NULL;
527    }
528
529    /*
530     * Receive notification when connection dies.
531     */
532    if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
533       Jmsg(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"), strerror(errno));
534    }
535    
536    for (i = 0; addr_list[i] != ((uint32_t) -1); i++) {
537       /* connect to server */
538       tcp_serv_addr.sin_addr.s_addr = addr_list[i];
539       if (connect(sockfd, (struct sockaddr *)&tcp_serv_addr, sizeof(tcp_serv_addr)) < 0) {
540          continue;
541       }
542       connected = 1;
543       break;
544    }
545
546    free(addr_list);
547    if (!connected) {
548       close(sockfd);
549       return NULL;
550    }
551    return init_bsock(jcr, sockfd, name, host, port);
552 }
553
554 /*
555  * Try to connect to host for max_retry_time at retry_time intervals.
556  */
557 BSOCK *
558 bnet_connect(JCR *jcr, int retry_interval, int max_retry_time, char *name,
559              char *host, char *service, int port, int verbose)
560 {
561    int i;
562    BSOCK *bsock;
563    int fatal = 0;
564
565    for (i=0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL; i -= retry_interval) {
566      if (fatal || (jcr && job_canceled(jcr))) {
567         return NULL;
568      }
569      Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
570               name, host, port, strerror(errno));
571       if (i < 0) {
572          i = 60 * 5;                  /* complain again in 5 minutes */
573          if (verbose)
574             Jmsg(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
575 Retrying ...\n", name, host, port, strerror(errno));
576       }
577       bmicrosleep(retry_interval, 0);
578       max_retry_time -= retry_interval;
579       if (max_retry_time <= 0) {
580          Jmsg(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
581               name, host, port, strerror(errno));
582          return NULL;
583       }
584    }
585    return bsock;
586 }
587
588
589 /*
590  * Return the string for the error that occurred
591  * on the socket. Only the first error is retained.
592  */
593 char *bnet_strerror(BSOCK *bsock)
594 {
595    return strerror(bsock->b_errno);
596 }
597
598 /*
599  * Format and send a message
600  *  Returns: 0 on failure
601  *           1 on success
602  */
603 int
604 bnet_fsend(BSOCK *bs, char *fmt, ...)
605 {
606    va_list arg_ptr;
607    int maxlen;
608
609    /* This probably won't work, but we vsnprintf, then if we
610     * get a negative length or a length greater than our buffer
611     * (depending on which library is used), the printf was truncated, so
612     * get a biger buffer and try again.
613     */
614 again:
615    maxlen = sizeof_pool_memory(bs->msg) - 1;
616    va_start(arg_ptr, fmt);
617    bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
618    va_end(arg_ptr);
619    if (bs->msglen < 0 || bs->msglen >= maxlen) {
620       bs->msg = realloc_pool_memory(bs->msg, maxlen + 200);
621       goto again;
622    }
623    return bnet_send(bs) < 0 ? 0 : 1;
624 }
625
626 /* 
627  * Set the network buffer size, suggested size is in size.
628  *  Actual size obtained is returned in bs->msglen
629  *
630  *  Returns: 0 on failure
631  *           1 on success
632  */
633 int bnet_set_buffer_size(BSOCK *bs, uint32_t size, int rw)
634 {
635    uint32_t dbuf_size;
636 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
637    int opt;
638
639     opt = IPTOS_THROUGHPUT;
640     setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t)&opt, sizeof(opt));
641 #endif
642
643    dbuf_size = size;
644    if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size+100)) == NULL) {
645       Jmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
646       return 0;
647    }
648    if (rw & BNET_SETBUF_READ) {
649       while ((dbuf_size > TAPE_BSIZE) &&
650          (setsockopt(bs->fd, SOL_SOCKET, SO_RCVBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
651          Jmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
652          dbuf_size -= TAPE_BSIZE;
653       }
654       Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
655       if (dbuf_size != MAX_NETWORK_BUFFER_SIZE)
656          Jmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
657       if (dbuf_size % TAPE_BSIZE != 0) {
658          Jmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
659               dbuf_size);
660       }
661    }
662    dbuf_size = size;
663    if (rw & BNET_SETBUF_WRITE) {
664       while ((dbuf_size > TAPE_BSIZE) &&
665          (setsockopt(bs->fd, SOL_SOCKET, SO_SNDBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
666          Jmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
667          dbuf_size -= TAPE_BSIZE;
668       }
669       Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
670       if (dbuf_size != MAX_NETWORK_BUFFER_SIZE)
671          Jmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
672       if (dbuf_size % TAPE_BSIZE != 0) {
673          Jmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
674               dbuf_size);
675       }
676    }
677
678    bs->msglen = dbuf_size;
679    return 1;
680 }
681
682 /*
683  * Send a network "signal" to the other end 
684  *  This consists of sending a negative packet length
685  *
686  *  Returns: 0 on failure
687  *           1 on success
688  */
689 int bnet_sig(BSOCK *bs, int sig)
690 {
691    bs->msglen = sig;
692    return bnet_send(bs);
693 }
694
695 /*
696  * Convert a network "signal" code into
697  * human readable ASCII.
698  */
699 char *bnet_sig_to_ascii(BSOCK *bs)
700 {
701    static char buf[30];
702    switch (bs->msglen) {
703       case BNET_EOD:
704          return "BNET_EOD";           /* end of data stream */
705       case BNET_EOD_POLL:
706          return "BNET_EOD_POLL";
707       case BNET_STATUS:
708          return "BNET_STATUS";
709       case BNET_TERMINATE:
710          return "BNET_TERMINATE";     /* terminate connection */
711       case BNET_POLL:
712          return "BNET_POLL";
713       case BNET_HEARTBEAT:
714          return "BNET_HEARTBEAT";
715       case BNET_HB_RESPONSE:
716          return "BNET_HB_RESPONSE";
717       case BNET_PROMPT:
718          return "BNET_PROMPT";
719       default:
720          sprintf(buf, "Unknown sig %d", bs->msglen);
721          return buf;
722    }
723 }
724
725
726 /* Initialize internal socket structure.  
727  *  This probably should be done in net_open
728  */
729 BSOCK *
730 init_bsock(JCR *jcr, int sockfd, char *who, char *host, int port) 
731 {
732    BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
733    memset(bsock, 0, sizeof(BSOCK));
734    bsock->fd = sockfd;
735    bsock->errors = 0;
736    bsock->msg = get_pool_memory(PM_MESSAGE);
737    bsock->errmsg = get_pool_memory(PM_MESSAGE);
738    bsock->who = bstrdup(who);
739    bsock->host = bstrdup(host);
740    bsock->port = port;
741    /*
742     * ****FIXME**** reduce this to a few hours once   
743     *   heartbeats are implemented
744     */
745    bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */
746    bsock->jcr = jcr;
747    return bsock;
748 }
749
750 BSOCK *
751 dup_bsock(BSOCK *osock)
752 {
753    BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
754    memcpy(bsock, osock, sizeof(BSOCK));
755    bsock->msg = get_pool_memory(PM_MESSAGE);
756    bsock->errmsg = get_pool_memory(PM_MESSAGE);
757    if (osock->who) {
758       bsock->who = bstrdup(osock->who);
759    }
760    if (osock->host) {
761       bsock->host = bstrdup(osock->host);
762    }
763    bsock->duped = TRUE;
764    return bsock;
765 }
766
767 /* Close the network connection */
768 void 
769 bnet_close(BSOCK *bsock)
770 {
771    BSOCK *next;
772
773    for ( ; bsock != NULL; bsock = next) {
774       next = bsock->next;
775       if (!bsock->duped) {
776          close(bsock->fd);
777       }
778       term_bsock(bsock);
779    }
780    return;
781 }
782
783 void
784 term_bsock(BSOCK *bsock)
785 {
786    if (bsock->msg) {
787       free_pool_memory(bsock->msg);
788       bsock->msg = NULL;
789    } else {
790       ASSERT(1==0);                   /* double close */
791    }
792    if (bsock->errmsg) {
793       free_pool_memory(bsock->errmsg);
794       bsock->errmsg = NULL;
795    }
796    if (bsock->who) {
797       free(bsock->who);
798       bsock->who = NULL;
799    }
800    if (bsock->host) {
801       free(bsock->host);
802       bsock->host = NULL;
803    }
804    free(bsock);
805 }
806