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 bsock->b_errno = errno;
99 Qmsg1(bsock->jcr, M_FATAL, 0, _("Attr spool write error. ERR=%s\n"),
101 Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes);
102 errno = bsock->b_errno;
111 nwritten = socketWrite(bsock->fd, ptr, nleft);
112 if (bsock->timed_out || bsock->terminated) {
115 } while (nwritten == -1 && errno == EINTR);
117 * If connection is non-blocking, we will get EAGAIN, so
118 * use select() to keep from consuming all the CPU
121 if (nwritten == -1 && errno == EAGAIN) {
126 FD_SET((unsigned)bsock->fd, &fdset);
129 select(bsock->fd + 1, NULL, &fdset, NULL, &tv);
133 return nwritten; /* error */
138 return nbytes - nleft;
142 * Receive a message from the other end. Each message consists of
143 * two packets. The first is a header that contains the size
144 * of the data that follows in the second packet.
145 * Returns number of bytes read (may return zero)
146 * Returns -1 on signal (BNET_SIGNAL)
147 * Returns -2 on hard end of file (BNET_HARDEOF)
148 * Returns -3 on error (BNET_ERROR)
150 * Unfortunately, it is a bit complicated because we have these
153 * 2. Signal including end of data stream
154 * 3. Hard end of file
156 * Using is_bnet_stop() and is_bnet_error() you can figure this all out.
158 int32_t bnet_recv(BSOCK * bsock)
163 ASSERT(bsock != NULL);
165 if (bsock->errors || bsock->terminated) {
169 bsock->read_seqno++; /* bump sequence number */
170 bsock->timer_start = watchdog_time; /* set start wait time */
171 bsock->timed_out = 0;
172 /* get data size -- in int32_t */
173 if ((nbytes = read_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
174 bsock->timer_start = 0; /* clear timer */
175 /* probably pipe broken because client died */
177 bsock->b_errno = ENODATA;
179 bsock->b_errno = errno;
182 return BNET_HARDEOF; /* assume hard EOF received */
184 bsock->timer_start = 0; /* clear timer */
185 if (nbytes != sizeof(int32_t)) {
187 bsock->b_errno = EIO;
188 Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
189 sizeof(int32_t), nbytes, bsock->who, bsock->host, bsock->port);
193 pktsiz = ntohl(pktsiz); /* decode no. of bytes that follow */
195 if (pktsiz == 0) { /* No data transferred */
196 bsock->timer_start = 0; /* clear timer */
199 return 0; /* zero bytes read */
202 /* If signal or packet size too big */
203 if (pktsiz < 0 || pktsiz > 1000000) {
204 if (pktsiz > 0) { /* if packet too big */
205 Qmsg3(bsock->jcr, M_FATAL, 0,
206 _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
207 bsock->who, bsock->host, bsock->port);
208 pktsiz = BNET_TERMINATE; /* hang up */
210 if (pktsiz == BNET_TERMINATE) {
211 bsock->terminated = 1;
213 bsock->timer_start = 0; /* clear timer */
214 bsock->b_errno = ENODATA;
215 bsock->msglen = pktsiz; /* signal code */
216 return BNET_SIGNAL; /* signal */
219 /* Make sure the buffer is big enough + one byte for EOS */
220 if (pktsiz >= (int32_t) sizeof_pool_memory(bsock->msg)) {
221 bsock->msg = realloc_pool_memory(bsock->msg, pktsiz + 100);
224 bsock->timer_start = watchdog_time; /* set start wait time */
225 bsock->timed_out = 0;
226 /* now read the actual data */
227 if ((nbytes = read_nbytes(bsock, bsock->msg, pktsiz)) <= 0) {
228 bsock->timer_start = 0; /* clear timer */
230 bsock->b_errno = ENODATA;
232 bsock->b_errno = errno;
235 Qmsg4(bsock->jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
236 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
239 bsock->timer_start = 0; /* clear timer */
241 bsock->msglen = nbytes;
242 if (nbytes != pktsiz) {
243 bsock->b_errno = EIO;
245 Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
246 pktsiz, nbytes, bsock->who, bsock->host, bsock->port);
249 /* always add a zero by to properly terminate any
250 * string that was send to us. Note, we ensured above that the
251 * buffer is at least one byte longer than the message length.
253 bsock->msg[nbytes] = 0; /* terminate in case it is a string */
254 sm_check(__FILE__, __LINE__, false);
255 return nbytes; /* return actual length of message */
260 * Return 1 if there are errors on this bsock or it is closed,
261 * i.e. stop communicating on this line.
263 bool is_bnet_stop(BSOCK * bsock)
265 return bsock->errors || bsock->terminated;
269 * Return number of errors on socket
271 int is_bnet_error(BSOCK * bsock)
273 return bsock->errors;
277 * Call here after error during closing to suppress error
278 * messages which are due to the other end shutting down too.
280 void bnet_suppress_error_messages(BSOCK * bsock, bool flag)
282 bsock->suppress_error_msgs = flag;
287 * Transmit spooled data now to a BSOCK
289 int bnet_despool_to_bsock(BSOCK * bsock, void update_attr_spool_size(ssize_t size),
294 ssize_t last = 0, size = 0;
297 rewind(bsock->spool_fd);
298 while (fread((char *)&pktsiz, 1, sizeof(int32_t), bsock->spool_fd) ==
300 size += sizeof(int32_t);
301 bsock->msglen = ntohl(pktsiz);
302 if (bsock->msglen > 0) {
303 if (bsock->msglen > (int32_t) sizeof_pool_memory(bsock->msg)) {
304 bsock->msg = realloc_pool_memory(bsock->msg, bsock->msglen + 1);
306 nbytes = fread(bsock->msg, 1, bsock->msglen, bsock->spool_fd);
307 if (nbytes != (size_t) bsock->msglen) {
309 Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, bsock->msglen);
310 Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
312 update_attr_spool_size(tsize - last);
316 if ((++count & 0x3F) == 0) {
317 update_attr_spool_size(size - last);
323 update_attr_spool_size(tsize - last);
324 if (ferror(bsock->spool_fd)) {
326 Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
335 * Send a message over the network. The send consists of
336 * two network packets. The first is sends a 32 bit integer containing
337 * the length of the data packet which follows.
339 * Returns: false on failure
342 bool bnet_send(BSOCK * bsock)
347 if (bsock->errors || bsock->terminated || bsock->msglen > 1000000) {
350 pktsiz = htonl((int32_t) bsock->msglen);
351 /* send int32_t containing size of data packet */
352 bsock->timer_start = watchdog_time; /* start timer */
353 bsock->timed_out = 0;
354 rc = write_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t));
355 bsock->timer_start = 0; /* clear timer */
356 if (rc != sizeof(int32_t)) {
357 if (bsock->msglen == BNET_TERMINATE) { /* if we were terminating */
358 bsock->terminated = 1;
359 return false; /* ignore any errors */
363 bsock->b_errno = EIO;
365 bsock->b_errno = errno;
368 if (!bsock->suppress_error_msgs && !bsock->timed_out) {
369 Qmsg4(bsock->jcr, M_ERROR, 0,
370 _("Write error sending to %s:%s:%d: ERR=%s\n"), bsock->who,
371 bsock->host, bsock->port, bnet_strerror(bsock));
374 Qmsg5(bsock->jcr, M_ERROR, 0,
375 _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"), bsock->who,
376 bsock->host, bsock->port, bsock->msglen, rc);
381 bsock->out_msg_no++; /* increment message number */
382 if (bsock->msglen <= 0) { /* length only? */
383 return true; /* yes, no data */
386 /* send data packet */
387 bsock->timer_start = watchdog_time; /* start timer */
388 bsock->timed_out = 0;
389 rc = write_nbytes(bsock, bsock->msg, bsock->msglen);
390 bsock->timer_start = 0; /* clear timer */
391 if (rc != bsock->msglen) {
394 bsock->b_errno = EIO;
396 bsock->b_errno = errno;
399 if (!bsock->suppress_error_msgs) {
400 Qmsg4(bsock->jcr, M_ERROR, 0,
401 _("Write error sending to %s:%s:%d: ERR=%s\n"), bsock->who,
402 bsock->host, bsock->port, bnet_strerror(bsock));
405 Qmsg5(bsock->jcr, M_ERROR, 0,
406 _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
407 bsock->msglen, bsock->who, bsock->host, bsock->port, rc);
415 * Establish an SSL connection -- server side
416 * Codes that ssl_need and ssl_has can take
417 * BNET_SSL_NONE I cannot do ssl
418 * BNET_SSL_OK I can do ssl, but it is not required on my end
419 * BNET_SSL_REQUIRED ssl is required on my end
421 int bnet_ssl_server(BSOCK * bsock, char *password, int ssl_need, int ssl_has)
423 /* Check to see if what we need (ssl_need) corresponds to what he has (ssl_has) */
424 /* The other side expects a response from us */
429 * Establish an SSL connection -- client side
431 int bnet_ssl_client(BSOCK * bsock, char *password, int ssl_need)
433 /* We are the client so we must wait for the server to notify us */
439 * Wait for a specified time for data to appear on
440 * the BSOCK connection.
442 * Returns: 1 if data available
446 int bnet_wait_data(BSOCK * bsock, int sec)
452 FD_SET((unsigned)bsock->fd, &fdset);
456 switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
457 case 0: /* timeout */
461 bsock->b_errno = errno;
462 if (errno == EINTR || errno == EAGAIN) {
465 return -1; /* error return */
474 * As above, but returns on interrupt
476 int bnet_wait_data_intr(BSOCK * bsock, int sec)
482 FD_SET((unsigned)bsock->fd, &fdset);
486 switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
487 case 0: /* timeout */
491 bsock->b_errno = errno;
492 return -1; /* error return */
500 #ifndef NETDB_INTERNAL
501 #define NETDB_INTERNAL -1 /* See errno. */
503 #ifndef NETDB_SUCCESS
504 #define NETDB_SUCCESS 0 /* No problem. */
506 #ifndef HOST_NOT_FOUND
507 #define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found. */
510 #define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL. */
513 #define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP. */
516 #define NO_DATA 4 /* Valid name, no data record of requested type. */
520 * Get human readable error for gethostbyname()
522 static const char *gethost_strerror()
527 msg = strerror(errno);
533 msg = "Authoritative answer for host not found.";
536 msg = "Non-authoritative for host not found, or ServerFail.";
539 msg = "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.";
542 msg = "Valid name, no data record of resquested type.";
545 msg = "Unknown error.";
551 static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
554 static IPADDR *add_any(int family)
556 IPADDR *addr = New(IPADDR(family));
557 addr->set_type(IPADDR::R_MULTIPLE);
558 addr->set_addr_any();
562 static const char *resolv_host(int family, const char *host, dlist * addr_list)
568 #ifdef HAVE_GETHOSTBYNAME2
569 if ((hp = gethostbyname2(host, family)) == NULL) {
571 if ((hp = gethostbyname(host)) == NULL) {
573 /* may be the strerror give not the right result -:( */
574 errmsg = gethost_strerror();
579 for (p = hp->h_addr_list; *p != 0; p++) {
580 IPADDR *addr = New(IPADDR(hp->h_addrtype));
581 addr->set_type(IPADDR::R_MULTIPLE);
582 if (addr->get_family() == AF_INET) {
583 addr->set_addr4((struct in_addr*)*p);
587 addr->set_addr6((struct in6_addr*)*p);
590 addr_list->append(addr);
598 * i host = 0 mean INADDR_ANY only ipv4
600 dlist *bnet_host2ipaddrs(const char *host, int family, const char **errstr)
602 struct in_addr inaddr;
606 struct in6_addr inaddr6;
609 dlist *addr_list = New(dlist(addr, &addr->link));
610 if (!host || host[0] == '\0') {
612 addr_list->append(add_any(family));
614 addr_list->append(add_any(AF_INET));
616 addr_list->append(add_any(AF_INET6));
619 } else if (inet_aton(host, &inaddr)) { /* MA Bug 4 */
620 addr = New(IPADDR(AF_INET));
621 addr->set_type(IPADDR::R_MULTIPLE);
622 addr->set_addr4(&inaddr);
623 addr_list->append(addr);
626 if (inet_pton(AF_INET6, host, &inaddr6) > 1) {
627 addr = New(IPADDR(AF_INET6));
628 addr->set_type(IPADDR::R_MULTIPLE);
629 addr->set_addr6(&inaddr6);
630 addr_list->append(addr);
635 errmsg = resolv_host(family, host, addr_list);
638 free_addresses(addr_list);
642 errmsg = resolv_host(AF_INET, host, addr_list);
645 errmsg = resolv_host(AF_INET6, host, addr_list);
650 free_addresses(addr_list);
659 * Open a TCP connection to the UPS network server
661 * Returns BSOCK * pointer on success
664 static BSOCK *bnet_open(JCR * jcr, const char *name, char *host, char *service,
665 int port, int *fatal)
670 bool connected = false;
676 * Fill in the structure serv_addr with the address of
677 * the server that we want to connect with.
679 if ((addr_list = bnet_host2ipaddrs(host, 0, &errstr)) == NULL) {
680 /* Note errstr is not malloc'ed */
681 Qmsg2(jcr, M_ERROR, 0, "gethostbyname() for host \"%s\" failed: ERR=%s\n",
683 Dmsg2(100, "bnet_host2ipaddrs() for host %s failed: ERR=%s\n",
689 foreach_dlist(ipaddr, addr_list) {
690 ipaddr->set_port_net(htons(port));
691 char allbuf[256 * 10];
693 Dmsg2(100, "Current %sAll %s\n",
694 ipaddr->build_address_str(curbuf, sizeof(curbuf)),
695 build_addresses_str(addr_list, allbuf, sizeof(allbuf)));
696 /* Open a TCP socket */
697 if ((sockfd = socket(ipaddr->get_family(), SOCK_STREAM, 0)) < 0) {
701 Pmsg3(000, "Socket open error. proto=%d port=%d. ERR=%s\n",
702 ipaddr->get_family(), ipaddr->get_port_host_order(), be.strerror());
706 * Keep socket from timing out from inactivity
708 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
710 Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
713 /* connect to server */
714 if (connect(sockfd, ipaddr->get_sockaddr(), ipaddr->get_sockaddr_len()) < 0) {
725 free_addresses(addr_list);
730 * Keep socket from timing out from inactivity
731 * Do this a second time out of paranoia
733 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
735 Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
738 BSOCK* ret = init_bsock(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
739 free_addresses(addr_list);
744 * Try to connect to host for max_retry_time at retry_time intervals.
746 BSOCK *bnet_connect(JCR * jcr, int retry_interval, int max_retry_time,
747 const char *name, char *host, char *service, int port,
754 for (i = 0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL;
755 i -= retry_interval) {
757 if (fatal || (jcr && job_canceled(jcr))) {
760 Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
761 name, host, port, be.strerror());
763 i = 60 * 5; /* complain again in 5 minutes */
765 Qmsg4(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
766 Retrying ...\n", name, host, port, be.strerror());
768 bmicrosleep(retry_interval, 0);
769 max_retry_time -= retry_interval;
770 if (max_retry_time <= 0) {
771 Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
772 name, host, port, be.strerror());
781 * Return the string for the error that occurred
782 * on the socket. Only the first error is retained.
784 const char *bnet_strerror(BSOCK * bsock)
787 if (bsock->errmsg == NULL) {
788 bsock->errmsg = get_pool_memory(PM_MESSAGE);
790 pm_strcpy(bsock->errmsg, be.strerror(bsock->b_errno));
791 return bsock->errmsg;
795 * Format and send a message
796 * Returns: false on error
799 bool bnet_fsend(BSOCK * bs, const char *fmt, ...)
804 if (bs->errors || bs->terminated) {
807 /* This probably won't work, but we vsnprintf, then if we
808 * get a negative length or a length greater than our buffer
809 * (depending on which library is used), the printf was truncated, so
810 * get a bigger buffer and try again.
813 maxlen = sizeof_pool_memory(bs->msg) - 1;
814 va_start(arg_ptr, fmt);
815 bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
817 if (bs->msglen > 0 && bs->msglen < (maxlen - 5)) {
820 bs->msg = realloc_pool_memory(bs->msg, maxlen + maxlen / 2);
822 return bnet_send(bs);
826 * Set the network buffer size, suggested size is in size.
827 * Actual size obtained is returned in bs->msglen
829 * Returns: 0 on failure
832 bool bnet_set_buffer_size(BSOCK * bs, uint32_t size, int rw)
834 uint32_t dbuf_size, start_size;
835 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
838 opt = IPTOS_THROUGHPUT;
839 setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t) & opt, sizeof(opt));
845 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
847 start_size = dbuf_size;
848 if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size + 100)) == NULL) {
849 Qmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
852 if (rw & BNET_SETBUF_READ) {
853 while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
854 SO_RCVBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
856 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
857 dbuf_size -= TAPE_BSIZE;
859 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
860 if (dbuf_size != start_size) {
861 Qmsg1(bs->jcr, M_WARNING, 0,
862 _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
864 if (dbuf_size % TAPE_BSIZE != 0) {
865 Qmsg1(bs->jcr, M_ABORT, 0,
866 _("Network buffer size %d not multiple of tape block size.\n"),
873 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
875 start_size = dbuf_size;
876 if (rw & BNET_SETBUF_WRITE) {
877 while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
878 SO_SNDBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
880 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
881 dbuf_size -= TAPE_BSIZE;
883 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
884 if (dbuf_size != start_size) {
885 Qmsg1(bs->jcr, M_WARNING, 0,
886 _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
888 if (dbuf_size % TAPE_BSIZE != 0) {
889 Qmsg1(bs->jcr, M_ABORT, 0,
890 _("Network buffer size %d not multiple of tape block size.\n"),
895 bs->msglen = dbuf_size;
900 * Send a network "signal" to the other end
901 * This consists of sending a negative packet length
903 * Returns: false on failure
906 bool bnet_sig(BSOCK * bs, int sig)
909 return bnet_send(bs);
913 * Convert a network "signal" code into
914 * human readable ASCII.
916 const char *bnet_sig_to_ascii(BSOCK * bs)
919 switch (bs->msglen) {
921 return "BNET_EOD"; /* end of data stream */
923 return "BNET_EOD_POLL";
925 return "BNET_STATUS";
927 return "BNET_TERMINATE"; /* terminate connection */
931 return "BNET_HEARTBEAT";
932 case BNET_HB_RESPONSE:
933 return "BNET_HB_RESPONSE";
935 return "BNET_PROMPT";
937 sprintf(buf, "Unknown sig %d", bs->msglen);
943 /* Initialize internal socket structure.
944 * This probably should be done in net_open
946 BSOCK *init_bsock(JCR * jcr, int sockfd, const char *who, const char *host, int port,
947 struct sockaddr *client_addr)
949 Dmsg3(100, "who=%s host=%s port=%d\n", who, host, port);
950 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
951 memset(bsock, 0, sizeof(BSOCK));
954 bsock->msg = get_pool_memory(PM_MESSAGE);
955 bsock->errmsg = get_pool_memory(PM_MESSAGE);
956 bsock->who = bstrdup(who);
957 bsock->host = bstrdup(host);
959 memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
961 * ****FIXME**** reduce this to a few hours once
962 * heartbeats are implemented
964 bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */
969 BSOCK *dup_bsock(BSOCK * osock)
971 BSOCK *bsock = (BSOCK *) malloc(sizeof(BSOCK));
972 memcpy(bsock, osock, sizeof(BSOCK));
973 bsock->msg = get_pool_memory(PM_MESSAGE);
974 bsock->errmsg = get_pool_memory(PM_MESSAGE);
976 bsock->who = bstrdup(osock->who);
979 bsock->host = bstrdup(osock->host);
985 /* Close the network connection */
986 void bnet_close(BSOCK * bsock)
990 for (; bsock != NULL; bsock = next) {
993 if (bsock->timed_out) {
994 shutdown(bsock->fd, 2); /* discard any pending I/O */
996 socketClose(bsock->fd); /* normal close */
1003 void term_bsock(BSOCK * bsock)
1006 free_pool_memory(bsock->msg);
1009 ASSERT(1 == 0); /* double close */
1011 if (bsock->errmsg) {
1012 free_pool_memory(bsock->errmsg);
1013 bsock->errmsg = NULL;