2 * Network Utility Routines
6 * Adapted and enhanced for Bacula, originally written
7 * for inclusion in the Apcupsd package
12 Copyright (C) 2000-2004 Kern Sibbald and John Walker
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.
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.
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,
36 extern time_t watchdog_time;
39 #define INADDR_NONE -1
42 #ifndef ENODATA /* not defined on BSD systems */
47 #define socketRead(fd, buf, len) recv(fd, buf, len, 0)
48 #define socketWrite(fd, buf, len) send(fd, buf, len, 0)
49 #define socketClose(fd) closesocket(fd)
51 #define socketRead(fd, buf, len) read(fd, buf, len)
52 #define socketWrite(fd, buf, len) write(fd, buf, len)
53 #define socketClose(fd) close(fd)
58 * Read a nbytes from the network.
59 * It is possible that the total bytes require in several
63 static int32_t read_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes)
71 nread = socketRead(bsock->fd, ptr, nleft);
72 if (bsock->timed_out || bsock->terminated) {
75 } while (nread == -1 && (errno == EINTR || errno == EAGAIN));
77 return nread; /* error, or EOF */
82 return nbytes - nleft; /* return >= 0 */
86 * Write nbytes to the network.
87 * It may require several writes.
90 static int32_t write_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes)
92 int32_t nleft, nwritten;
95 nwritten = fwrite(ptr, 1, nbytes, bsock->spool_fd);
96 if (nwritten != nbytes) {
98 Qmsg1(bsock->jcr, M_FATAL, 0, _("Attr spool write error. ERR=%s\n"),
100 Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes);
109 nwritten = socketWrite(bsock->fd, ptr, nleft);
110 if (bsock->timed_out || bsock->terminated) {
113 } while (nwritten == -1 && errno == EINTR);
115 * If connection is non-blocking, we will get EAGAIN, so
116 * use select() to keep from consuming all the CPU
119 if (nwritten == -1 && errno == EAGAIN) {
124 FD_SET((unsigned)bsock->fd, &fdset);
127 select(bsock->fd + 1, NULL, &fdset, NULL, &tv);
131 return nwritten; /* error */
136 return nbytes - nleft;
140 * Receive a message from the other end. Each message consists of
141 * two packets. The first is a header that contains the size
142 * of the data that follows in the second packet.
143 * Returns number of bytes read (may return zero)
144 * Returns -1 on signal (BNET_SIGNAL)
145 * Returns -2 on hard end of file (BNET_HARDEOF)
146 * Returns -3 on error (BNET_ERROR)
148 * Unfortunately, it is a bit complicated because we have these
151 * 2. Signal including end of data stream
152 * 3. Hard end of file
154 * Using is_bnet_stop() and is_bnet_error() you can figure this all out.
156 int32_t bnet_recv(BSOCK * bsock)
161 ASSERT(bsock != NULL);
163 if (bsock->errors || bsock->terminated) {
167 bsock->read_seqno++; /* bump sequence number */
168 bsock->timer_start = watchdog_time; /* set start wait time */
169 bsock->timed_out = 0;
170 /* get data size -- in int32_t */
171 if ((nbytes = read_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
172 bsock->timer_start = 0; /* clear timer */
173 /* probably pipe broken because client died */
175 bsock->b_errno = ENODATA;
177 bsock->b_errno = errno;
180 return BNET_HARDEOF; /* assume hard EOF received */
182 bsock->timer_start = 0; /* clear timer */
183 if (nbytes != sizeof(int32_t)) {
185 bsock->b_errno = EIO;
186 Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
187 sizeof(int32_t), nbytes, bsock->who, bsock->host, bsock->port);
191 pktsiz = ntohl(pktsiz); /* decode no. of bytes that follow */
193 if (pktsiz == 0) { /* No data transferred */
194 bsock->timer_start = 0; /* clear timer */
197 return 0; /* zero bytes read */
200 /* If signal or packet size too big */
201 if (pktsiz < 0 || pktsiz > 1000000) {
202 if (pktsiz > 0) { /* if packet too big */
203 Qmsg3(bsock->jcr, M_FATAL, 0,
204 _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
205 bsock->who, bsock->host, bsock->port);
206 pktsiz = BNET_TERMINATE; /* hang up */
208 if (pktsiz == BNET_TERMINATE) {
209 bsock->terminated = 1;
211 bsock->timer_start = 0; /* clear timer */
212 bsock->b_errno = ENODATA;
213 bsock->msglen = pktsiz; /* signal code */
214 return BNET_SIGNAL; /* signal */
217 /* Make sure the buffer is big enough + one byte for EOS */
218 if (pktsiz >= (int32_t) sizeof_pool_memory(bsock->msg)) {
219 bsock->msg = realloc_pool_memory(bsock->msg, pktsiz + 100);
222 bsock->timer_start = watchdog_time; /* set start wait time */
223 bsock->timed_out = 0;
224 /* now read the actual data */
225 if ((nbytes = read_nbytes(bsock, bsock->msg, pktsiz)) <= 0) {
226 bsock->timer_start = 0; /* clear timer */
228 bsock->b_errno = ENODATA;
230 bsock->b_errno = errno;
233 Qmsg4(bsock->jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
234 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
237 bsock->timer_start = 0; /* clear timer */
239 bsock->msglen = nbytes;
240 if (nbytes != pktsiz) {
241 bsock->b_errno = EIO;
243 Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
244 pktsiz, nbytes, bsock->who, bsock->host, bsock->port);
247 /* always add a zero by to properly terminate any
248 * string that was send to us. Note, we ensured above that the
249 * buffer is at least one byte longer than the message length.
251 bsock->msg[nbytes] = 0; /* terminate in case it is a string */
252 sm_check(__FILE__, __LINE__, false);
253 return nbytes; /* return actual length of message */
258 * Return 1 if there are errors on this bsock or it is closed,
259 * i.e. stop communicating on this line.
261 bool is_bnet_stop(BSOCK * bsock)
263 return bsock->errors || bsock->terminated;
267 * Return number of errors on socket
269 int is_bnet_error(BSOCK * bsock)
271 return bsock->errors;
275 * Call here after error during closing to suppress error
276 * messages which are due to the other end shutting down too.
278 void bnet_suppress_error_messages(BSOCK * bsock, bool flag)
280 bsock->suppress_error_msgs = flag;
285 * Transmit spooled data now to a BSOCK
287 int bnet_despool_to_bsock(BSOCK * bsock, void update_attr_spool_size(ssize_t size),
292 ssize_t last = 0, size = 0;
295 rewind(bsock->spool_fd);
296 while (fread((char *)&pktsiz, 1, sizeof(int32_t), bsock->spool_fd) ==
298 size += sizeof(int32_t);
299 bsock->msglen = ntohl(pktsiz);
300 if (bsock->msglen > 0) {
301 if (bsock->msglen > (int32_t) sizeof_pool_memory(bsock->msg)) {
302 bsock->msg = realloc_pool_memory(bsock->msg, bsock->msglen + 1);
304 nbytes = fread(bsock->msg, 1, bsock->msglen, bsock->spool_fd);
305 if (nbytes != (size_t) bsock->msglen) {
307 Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, bsock->msglen);
308 Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
310 update_attr_spool_size(tsize - last);
314 if ((++count & 0x3F) == 0) {
315 update_attr_spool_size(size - last);
321 update_attr_spool_size(tsize - last);
322 if (ferror(bsock->spool_fd)) {
324 Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
333 * Send a message over the network. The send consists of
334 * two network packets. The first is sends a 32 bit integer containing
335 * the length of the data packet which follows.
337 * Returns: false on failure
340 bool bnet_send(BSOCK * bsock)
345 if (bsock->errors || bsock->terminated || bsock->msglen > 1000000) {
348 pktsiz = htonl((int32_t) bsock->msglen);
349 /* send int32_t containing size of data packet */
350 bsock->timer_start = watchdog_time; /* start timer */
351 bsock->timed_out = 0;
352 rc = write_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t));
353 bsock->timer_start = 0; /* clear timer */
354 if (rc != sizeof(int32_t)) {
355 if (bsock->msglen == BNET_TERMINATE) { /* if we were terminating */
356 bsock->terminated = 1;
357 return false; /* ignore any errors */
361 bsock->b_errno = EIO;
363 bsock->b_errno = errno;
366 if (!bsock->suppress_error_msgs && !bsock->timed_out) {
367 Qmsg4(bsock->jcr, M_ERROR, 0,
368 _("Write error sending to %s:%s:%d: ERR=%s\n"), bsock->who,
369 bsock->host, bsock->port, bnet_strerror(bsock));
372 Qmsg5(bsock->jcr, M_ERROR, 0,
373 _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"), bsock->who,
374 bsock->host, bsock->port, bsock->msglen, rc);
379 bsock->out_msg_no++; /* increment message number */
380 if (bsock->msglen <= 0) { /* length only? */
381 return true; /* yes, no data */
384 /* send data packet */
385 bsock->timer_start = watchdog_time; /* start timer */
386 bsock->timed_out = 0;
387 rc = write_nbytes(bsock, bsock->msg, bsock->msglen);
388 bsock->timer_start = 0; /* clear timer */
389 if (rc != bsock->msglen) {
392 bsock->b_errno = EIO;
394 bsock->b_errno = errno;
397 if (!bsock->suppress_error_msgs) {
398 Qmsg4(bsock->jcr, M_ERROR, 0,
399 _("Write error sending to %s:%s:%d: ERR=%s\n"), bsock->who,
400 bsock->host, bsock->port, bnet_strerror(bsock));
403 Qmsg5(bsock->jcr, M_ERROR, 0,
404 _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
405 bsock->msglen, bsock->who, bsock->host, bsock->port, rc);
413 * Establish an SSL connection -- server side
414 * Codes that ssl_need and ssl_has can take
415 * BNET_SSL_NONE I cannot do ssl
416 * BNET_SSL_OK I can do ssl, but it is not required on my end
417 * BNET_SSL_REQUIRED ssl is required on my end
419 int bnet_ssl_server(BSOCK * bsock, char *password, int ssl_need, int ssl_has)
421 /* Check to see if what we need (ssl_need) corresponds to what he has (ssl_has) */
422 /* The other side expects a response from us */
427 * Establish an SSL connection -- client side
429 int bnet_ssl_client(BSOCK * bsock, char *password, int ssl_need)
431 /* We are the client so we must wait for the server to notify us */
437 * Wait for a specified time for data to appear on
438 * the BSOCK connection.
440 * Returns: 1 if data available
444 int bnet_wait_data(BSOCK * bsock, int sec)
450 FD_SET((unsigned)bsock->fd, &fdset);
454 switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
455 case 0: /* timeout */
459 bsock->b_errno = errno;
460 if (errno == EINTR || errno == EAGAIN) {
463 return -1; /* error return */
472 * As above, but returns on interrupt
474 int bnet_wait_data_intr(BSOCK * bsock, int sec)
480 FD_SET((unsigned)bsock->fd, &fdset);
484 switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
485 case 0: /* timeout */
489 bsock->b_errno = errno;
490 return -1; /* error return */
498 #ifndef NETDB_INTERNAL
499 #define NETDB_INTERNAL -1 /* See errno. */
501 #ifndef NETDB_SUCCESS
502 #define NETDB_SUCCESS 0 /* No problem. */
504 #ifndef HOST_NOT_FOUND
505 #define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found. */
508 #define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL. */
511 #define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP. */
514 #define NO_DATA 4 /* Valid name, no data record of requested type. */
518 * Get human readable error for gethostbyname()
520 static const char *gethost_strerror()
525 msg = strerror(errno);
531 msg = "Authoritative answer for host not found.";
534 msg = "Non-authoritative for host not found, or ServerFail.";
537 msg = "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.";
540 msg = "Valid name, no data record of resquested type.";
543 msg = "Unknown error.";
549 static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
552 static IPADDR *add_any(int family)
554 IPADDR *addr = New(IPADDR(family));
555 addr->set_type(IPADDR::R_MULTIPLE);
556 addr->set_addr_any();
560 static const char *resolv_host(int family, const char *host, dlist * addr_list)
566 #ifdef HAVE_GETHOSTBYNAME2
567 if ((hp = gethostbyname2(host, family)) == NULL) {
569 if ((hp = gethostbyname(host)) == NULL) {
571 /* may be the strerror give not the right result -:( */
572 errmsg = gethost_strerror();
577 for (p = hp->h_addr_list; *p != 0; p++) {
578 IPADDR *addr = New(IPADDR(hp->h_addrtype));
579 addr->set_type(IPADDR::R_MULTIPLE);
580 if (addr->get_family() == AF_INET) {
581 addr->set_addr4((struct in_addr*)*p);
585 addr->set_addr6((struct in6_addr*)*p);
588 addr_list->append(addr);
596 * i host = 0 mean INADDR_ANY only ipv4
598 dlist *bnet_host2ipaddrs(const char *host, int family, const char **errstr)
600 struct in_addr inaddr;
604 struct in6_addr inaddr6;
607 dlist *addr_list = New(dlist(addr, &addr->link));
608 if (!host || host[0] == '\0') {
610 addr_list->append(add_any(family));
612 addr_list->append(add_any(AF_INET));
614 addr_list->append(add_any(AF_INET6));
617 } else if (inet_aton(host, &inaddr)) { /* MA Bug 4 */
618 addr = New(IPADDR(AF_INET));
619 addr->set_type(IPADDR::R_MULTIPLE);
620 addr->set_addr4(&inaddr);
621 addr_list->append(addr);
624 if (inet_pton(AF_INET6, host, &inaddr6) > 1) {
625 addr = New(IPADDR(AF_INET6));
626 addr->set_type(IPADDR::R_MULTIPLE);
627 addr->set_addr6(&inaddr6);
628 addr_list->append(addr);
633 errmsg = resolv_host(family, host, addr_list);
636 free_addresses(addr_list);
640 errmsg = resolv_host(AF_INET, host, addr_list);
643 errmsg = resolv_host(AF_INET6, host, addr_list);
648 free_addresses(addr_list);
657 * Open a TCP connection to the UPS network server
659 * Returns BSOCK * pointer on success
662 static BSOCK *bnet_open(JCR * jcr, const char *name, char *host, char *service,
663 int port, int *fatal)
668 bool connected = false;
674 * Fill in the structure serv_addr with the address of
675 * the server that we want to connect with.
677 if ((addr_list = bnet_host2ipaddrs(host, 0, &errstr)) == NULL) {
678 /* Note errstr is not malloc'ed */
679 Qmsg2(jcr, M_ERROR, 0, "gethostbyname() for host \"%s\" failed: ERR=%s\n",
681 Dmsg2(100, "bnet_host2ipaddrs() for host %s failed: ERR=%s\n",
687 foreach_dlist(ipaddr, addr_list) {
688 ipaddr->set_port_net(htons(port));
689 char allbuf[256 * 10];
691 Dmsg2(100, "Current %sAll %s\n",
692 ipaddr->build_address_str(curbuf, sizeof(curbuf)),
693 build_addresses_str(addr_list, allbuf, sizeof(allbuf)));
694 /* Open a TCP socket */
695 if ((sockfd = socket(ipaddr->get_family(), SOCK_STREAM, 0)) < 0) {
699 Pmsg3(000, "Socket open error. proto=%d port=%d. ERR=%s\n",
700 ipaddr->get_family(), ipaddr->get_port_host_order(), be.strerror());
704 * Keep socket from timing out from inactivity
706 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
708 Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
711 /* connect to server */
712 if (connect(sockfd, ipaddr->get_sockaddr(), ipaddr->get_sockaddr_len()) < 0) {
723 free_addresses(addr_list);
728 * Keep socket from timing out from inactivity
729 * Do this a second time out of paranoia
731 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
733 Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
736 BSOCK* ret = init_bsock(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
737 free_addresses(addr_list);
742 * Try to connect to host for max_retry_time at retry_time intervals.
744 BSOCK *bnet_connect(JCR * jcr, int retry_interval, int max_retry_time,
745 const char *name, char *host, char *service, int port,
752 for (i = 0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL;
753 i -= retry_interval) {
755 if (fatal || (jcr && job_canceled(jcr))) {
758 Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
759 name, host, port, be.strerror());
761 i = 60 * 5; /* complain again in 5 minutes */
763 Qmsg4(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
764 Retrying ...\n", name, host, port, be.strerror());
766 bmicrosleep(retry_interval, 0);
767 max_retry_time -= retry_interval;
768 if (max_retry_time <= 0) {
769 Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
770 name, host, port, be.strerror());
779 * Return the string for the error that occurred
780 * on the socket. Only the first error is retained.
782 char *bnet_strerror(BSOCK * bsock)
784 return strerror(bsock->b_errno);
788 * Format and send a message
789 * Returns: false on error
792 bool bnet_fsend(BSOCK * bs, const char *fmt, ...)
797 if (bs->errors || bs->terminated) {
800 /* This probably won't work, but we vsnprintf, then if we
801 * get a negative length or a length greater than our buffer
802 * (depending on which library is used), the printf was truncated, so
803 * get a bigger buffer and try again.
806 maxlen = sizeof_pool_memory(bs->msg) - 1;
807 va_start(arg_ptr, fmt);
808 bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
810 if (bs->msglen > 0 && bs->msglen < (maxlen - 5)) {
813 bs->msg = realloc_pool_memory(bs->msg, maxlen + maxlen / 2);
815 return bnet_send(bs);
819 * Set the network buffer size, suggested size is in size.
820 * Actual size obtained is returned in bs->msglen
822 * Returns: 0 on failure
825 bool bnet_set_buffer_size(BSOCK * bs, uint32_t size, int rw)
827 uint32_t dbuf_size, start_size;
828 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
831 opt = IPTOS_THROUGHPUT;
832 setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t) & opt, sizeof(opt));
838 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
840 start_size = dbuf_size;
841 if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size + 100)) == NULL) {
842 Qmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
845 if (rw & BNET_SETBUF_READ) {
846 while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
847 SO_RCVBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
849 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
850 dbuf_size -= TAPE_BSIZE;
852 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
853 if (dbuf_size != start_size) {
854 Qmsg1(bs->jcr, M_WARNING, 0,
855 _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
857 if (dbuf_size % TAPE_BSIZE != 0) {
858 Qmsg1(bs->jcr, M_ABORT, 0,
859 _("Network buffer size %d not multiple of tape block size.\n"),
866 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
868 start_size = dbuf_size;
869 if (rw & BNET_SETBUF_WRITE) {
870 while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
871 SO_SNDBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
873 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
874 dbuf_size -= TAPE_BSIZE;
876 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
877 if (dbuf_size != start_size) {
878 Qmsg1(bs->jcr, M_WARNING, 0,
879 _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
881 if (dbuf_size % TAPE_BSIZE != 0) {
882 Qmsg1(bs->jcr, M_ABORT, 0,
883 _("Network buffer size %d not multiple of tape block size.\n"),
888 bs->msglen = dbuf_size;
893 * Send a network "signal" to the other end
894 * This consists of sending a negative packet length
896 * Returns: false on failure
899 bool bnet_sig(BSOCK * bs, int sig)
902 return bnet_send(bs);
906 * Convert a network "signal" code into
907 * human readable ASCII.
909 const char *bnet_sig_to_ascii(BSOCK * bs)
912 switch (bs->msglen) {
914 return "BNET_EOD"; /* end of data stream */
916 return "BNET_EOD_POLL";
918 return "BNET_STATUS";
920 return "BNET_TERMINATE"; /* terminate connection */
924 return "BNET_HEARTBEAT";
925 case BNET_HB_RESPONSE:
926 return "BNET_HB_RESPONSE";
928 return "BNET_PROMPT";
930 sprintf(buf, "Unknown sig %d", bs->msglen);
936 /* Initialize internal socket structure.
937 * This probably should be done in net_open
939 BSOCK *init_bsock(JCR * jcr, int sockfd, const char *who, const char *host, int port,
940 struct sockaddr *client_addr)
942 Dmsg3(100, "who=%s host=%s port=%d\n", who, host, port);
943 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
944 memset(bsock, 0, sizeof(BSOCK));
947 bsock->msg = get_pool_memory(PM_MESSAGE);
948 bsock->errmsg = get_pool_memory(PM_MESSAGE);
949 bsock->who = bstrdup(who);
950 bsock->host = bstrdup(host);
952 memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
954 * ****FIXME**** reduce this to a few hours once
955 * heartbeats are implemented
957 bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */
962 BSOCK *dup_bsock(BSOCK * osock)
964 BSOCK *bsock = (BSOCK *) malloc(sizeof(BSOCK));
965 memcpy(bsock, osock, sizeof(BSOCK));
966 bsock->msg = get_pool_memory(PM_MESSAGE);
967 bsock->errmsg = get_pool_memory(PM_MESSAGE);
969 bsock->who = bstrdup(osock->who);
972 bsock->host = bstrdup(osock->host);
978 /* Close the network connection */
979 void bnet_close(BSOCK * bsock)
983 for (; bsock != NULL; bsock = next) {
986 if (bsock->timed_out) {
987 shutdown(bsock->fd, 2); /* discard any pending I/O */
989 socketClose(bsock->fd); /* normal close */
996 void term_bsock(BSOCK * bsock)
999 free_pool_memory(bsock->msg);
1002 ASSERT(1 == 0); /* double close */
1004 if (bsock->errmsg) {
1005 free_pool_memory(bsock->errmsg);
1006 bsock->errmsg = NULL;