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