]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/bnet.c
Use rentrant mysql lib, eliminate race in sql_list, Win32 streams, misc see kes-1.31
[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(void *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(void *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(void *vjcr, 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    JCR *jcr = (JCR *)vjcr;
564    int fatal = 0;
565
566    for (i=0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL; i -= retry_interval) {
567      if (fatal || (jcr && job_canceled(jcr))) {
568         return NULL;
569      }
570      Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
571               name, host, port, strerror(errno));
572       if (i < 0) {
573          i = 60 * 5;                  /* complain again in 5 minutes */
574          if (verbose)
575             Jmsg(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
576 Retrying ...\n", name, host, port, strerror(errno));
577       }
578       bmicrosleep(retry_interval, 0);
579       max_retry_time -= retry_interval;
580       if (max_retry_time <= 0) {
581          Jmsg(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
582               name, host, port, strerror(errno));
583          return NULL;
584       }
585    }
586    return bsock;
587 }
588
589
590 /*
591  * Return the string for the error that occurred
592  * on the socket. Only the first error is retained.
593  */
594 char *bnet_strerror(BSOCK *bsock)
595 {
596    return strerror(bsock->b_errno);
597 }
598
599 /*
600  * Format and send a message
601  *  Returns: 0 on failure
602  *           1 on success
603  */
604 int
605 bnet_fsend(BSOCK *bs, char *fmt, ...)
606 {
607    va_list arg_ptr;
608    int maxlen;
609
610    /* This probably won't work, but we vsnprintf, then if we
611     * get a negative length or a length greater than our buffer
612     * (depending on which library is used), the printf was truncated, so
613     * get a biger buffer and try again.
614     */
615 again:
616    maxlen = sizeof_pool_memory(bs->msg) - 1;
617    va_start(arg_ptr, fmt);
618    bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
619    va_end(arg_ptr);
620    if (bs->msglen < 0 || bs->msglen >= maxlen) {
621       bs->msg = realloc_pool_memory(bs->msg, maxlen + 200);
622       goto again;
623    }
624    return bnet_send(bs) < 0 ? 0 : 1;
625 }
626
627 /* 
628  * Set the network buffer size, suggested size is in size.
629  *  Actual size obtained is returned in bs->msglen
630  *
631  *  Returns: 0 on failure
632  *           1 on success
633  */
634 int bnet_set_buffer_size(BSOCK *bs, uint32_t size, int rw)
635 {
636    uint32_t dbuf_size;
637 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
638    int opt;
639
640     opt = IPTOS_THROUGHPUT;
641     setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t)&opt, sizeof(opt));
642 #endif
643
644    dbuf_size = size;
645    if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size+100)) == NULL) {
646       Jmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
647       return 0;
648    }
649    if (rw & BNET_SETBUF_READ) {
650       while ((dbuf_size > TAPE_BSIZE) &&
651          (setsockopt(bs->fd, SOL_SOCKET, SO_RCVBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
652          Jmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
653          dbuf_size -= TAPE_BSIZE;
654       }
655       Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
656       if (dbuf_size != MAX_NETWORK_BUFFER_SIZE)
657          Jmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
658       if (dbuf_size % TAPE_BSIZE != 0) {
659          Jmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
660               dbuf_size);
661       }
662    }
663    dbuf_size = size;
664    if (rw & BNET_SETBUF_WRITE) {
665       while ((dbuf_size > TAPE_BSIZE) &&
666          (setsockopt(bs->fd, SOL_SOCKET, SO_SNDBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
667          Jmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
668          dbuf_size -= TAPE_BSIZE;
669       }
670       Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
671       if (dbuf_size != MAX_NETWORK_BUFFER_SIZE)
672          Jmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
673       if (dbuf_size % TAPE_BSIZE != 0) {
674          Jmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
675               dbuf_size);
676       }
677    }
678
679    bs->msglen = dbuf_size;
680    return 1;
681 }
682
683 /*
684  * Send a network "signal" to the other end 
685  *  This consists of sending a negative packet length
686  *
687  *  Returns: 0 on failure
688  *           1 on success
689  */
690 int bnet_sig(BSOCK *bs, int sig)
691 {
692    bs->msglen = sig;
693    return bnet_send(bs);
694 }
695
696 /*
697  * Convert a network "signal" code into
698  * human readable ASCII.
699  */
700 char *bnet_sig_to_ascii(BSOCK *bs)
701 {
702    static char buf[30];
703    switch (bs->msglen) {
704       case BNET_EOD:
705          return "BNET_EOD";           /* end of data stream */
706       case BNET_EOD_POLL:
707          return "BNET_EOD_POLL";
708       case BNET_STATUS:
709          return "BNET_STATUS";
710       case BNET_TERMINATE:
711          return "BNET_TERMINATE";     /* terminate connection */
712       case BNET_POLL:
713          return "BNET_POLL";
714       case BNET_HEARTBEAT:
715          return "BNET_HEARTBEAT";
716       case BNET_HB_RESPONSE:
717          return "BNET_HB_RESPONSE";
718       case BNET_PROMPT:
719          return "BNET_PROMPT";
720       default:
721          sprintf(buf, "Unknown sig %d", bs->msglen);
722          return buf;
723    }
724 }
725
726
727 /* Initialize internal socket structure.  
728  *  This probably should be done in net_open
729  */
730 BSOCK *
731 init_bsock(void *jcr, int sockfd, char *who, char *host, int port) 
732 {
733    BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
734    memset(bsock, 0, sizeof(BSOCK));
735    bsock->fd = sockfd;
736    bsock->errors = 0;
737    bsock->msg = get_pool_memory(PM_MESSAGE);
738    bsock->errmsg = get_pool_memory(PM_MESSAGE);
739    bsock->who = bstrdup(who);
740    bsock->host = bstrdup(host);
741    bsock->port = port;
742    /*
743     * ****FIXME**** reduce this to a few hours once   
744     *   heartbeats are implemented
745     */
746    bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */
747    bsock->jcr = jcr;
748    return bsock;
749 }
750
751 BSOCK *
752 dup_bsock(BSOCK *osock)
753 {
754    BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
755    memcpy(bsock, osock, sizeof(BSOCK));
756    bsock->msg = get_pool_memory(PM_MESSAGE);
757    bsock->errmsg = get_pool_memory(PM_MESSAGE);
758    if (osock->who) {
759       bsock->who = bstrdup(osock->who);
760    }
761    if (osock->host) {
762       bsock->host = bstrdup(osock->host);
763    }
764    bsock->duped = TRUE;
765    return bsock;
766 }
767
768 /* Close the network connection */
769 void 
770 bnet_close(BSOCK *bsock)
771 {
772    BSOCK *next;
773
774    for ( ; bsock != NULL; bsock = next) {
775       next = bsock->next;
776       if (!bsock->duped) {
777          close(bsock->fd);
778       }
779       term_bsock(bsock);
780    }
781    return;
782 }
783
784 void
785 term_bsock(BSOCK *bsock)
786 {
787    if (bsock->msg) {
788       free_pool_memory(bsock->msg);
789       bsock->msg = NULL;
790    } else {
791       ASSERT(1==0);                   /* double close */
792    }
793    if (bsock->errmsg) {
794       free_pool_memory(bsock->errmsg);
795       bsock->errmsg = NULL;
796    }
797    if (bsock->who) {
798       free(bsock->who);
799       bsock->who = NULL;
800    }
801    if (bsock->host) {
802       free(bsock->host);
803       bsock->host = NULL;
804    }
805    free(bsock);
806 }
807