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);
166 if (bsock->errors || bsock->terminated) {
170 bsock->read_seqno++; /* bump sequence number */
171 bsock->timer_start = watchdog_time; /* set start wait time */
172 bsock->timed_out = 0;
173 /* get data size -- in int32_t */
174 if ((nbytes = read_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
175 bsock->timer_start = 0; /* clear timer */
176 /* probably pipe broken because client died */
178 bsock->b_errno = ENODATA;
180 bsock->b_errno = errno;
183 return BNET_HARDEOF; /* assume hard EOF received */
185 bsock->timer_start = 0; /* clear timer */
186 if (nbytes != sizeof(int32_t)) {
188 bsock->b_errno = EIO;
189 Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
190 sizeof(int32_t), nbytes, bsock->who, bsock->host, bsock->port);
194 pktsiz = ntohl(pktsiz); /* decode no. of bytes that follow */
196 if (pktsiz == 0) { /* No data transferred */
197 bsock->timer_start = 0; /* clear timer */
200 return 0; /* zero bytes read */
203 /* If signal or packet size too big */
204 if (pktsiz < 0 || pktsiz > 1000000) {
205 if (pktsiz > 0) { /* if packet too big */
206 Qmsg3(bsock->jcr, M_FATAL, 0,
207 _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
208 bsock->who, bsock->host, bsock->port);
209 pktsiz = BNET_TERMINATE; /* hang up */
211 if (pktsiz == BNET_TERMINATE) {
212 bsock->terminated = 1;
214 bsock->timer_start = 0; /* clear timer */
215 bsock->b_errno = ENODATA;
216 bsock->msglen = pktsiz; /* signal code */
217 return BNET_SIGNAL; /* signal */
220 /* Make sure the buffer is big enough + one byte for EOS */
221 if (pktsiz >= (int32_t) sizeof_pool_memory(bsock->msg)) {
222 bsock->msg = realloc_pool_memory(bsock->msg, pktsiz + 100);
225 bsock->timer_start = watchdog_time; /* set start wait time */
226 bsock->timed_out = 0;
227 /* now read the actual data */
228 if ((nbytes = read_nbytes(bsock, bsock->msg, pktsiz)) <= 0) {
229 bsock->timer_start = 0; /* clear timer */
231 bsock->b_errno = ENODATA;
233 bsock->b_errno = errno;
236 Qmsg4(bsock->jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
237 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
240 bsock->timer_start = 0; /* clear timer */
242 bsock->msglen = nbytes;
243 if (nbytes != pktsiz) {
244 bsock->b_errno = EIO;
246 Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
247 pktsiz, nbytes, bsock->who, bsock->host, bsock->port);
250 /* always add a zero by to properly terminate any
251 * string that was send to us. Note, we ensured above that the
252 * buffer is at least one byte longer than the message length.
254 bsock->msg[nbytes] = 0; /* terminate in case it is a string */
255 sm_check(__FILE__, __LINE__, false);
256 return nbytes; /* return actual length of message */
261 * Return 1 if there are errors on this bsock or it is closed,
262 * i.e. stop communicating on this line.
264 bool is_bnet_stop(BSOCK * bsock)
266 return bsock->errors || bsock->terminated;
270 * Return number of errors on socket
272 int is_bnet_error(BSOCK * bsock)
274 return bsock->errors;
278 * Call here after error during closing to suppress error
279 * messages which are due to the other end shutting down too.
281 void bnet_suppress_error_messages(BSOCK * bsock, bool flag)
283 bsock->suppress_error_msgs = flag;
288 * Transmit spooled data now to a BSOCK
290 int bnet_despool_to_bsock(BSOCK * bsock, void update_attr_spool_size(ssize_t size),
295 ssize_t last = 0, size = 0;
298 rewind(bsock->spool_fd);
299 while (fread((char *)&pktsiz, 1, sizeof(int32_t), bsock->spool_fd) ==
301 size += sizeof(int32_t);
302 bsock->msglen = ntohl(pktsiz);
303 if (bsock->msglen > 0) {
304 if (bsock->msglen > (int32_t) sizeof_pool_memory(bsock->msg)) {
305 bsock->msg = realloc_pool_memory(bsock->msg, bsock->msglen + 1);
307 nbytes = fread(bsock->msg, 1, bsock->msglen, bsock->spool_fd);
308 if (nbytes != (size_t) bsock->msglen) {
310 Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, bsock->msglen);
311 Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
313 update_attr_spool_size(tsize - last);
317 if ((++count & 0x3F) == 0) {
318 update_attr_spool_size(size - last);
324 update_attr_spool_size(tsize - last);
325 if (ferror(bsock->spool_fd)) {
327 Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
336 * Send a message over the network. The send consists of
337 * two network packets. The first is sends a 32 bit integer containing
338 * the length of the data packet which follows.
340 * Returns: false on failure
343 bool bnet_send(BSOCK * bsock)
348 if (bsock->errors || bsock->terminated || bsock->msglen > 1000000) {
351 pktsiz = htonl((int32_t) bsock->msglen);
352 /* send int32_t containing size of data packet */
353 bsock->timer_start = watchdog_time; /* start timer */
354 bsock->timed_out = 0;
355 rc = write_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t));
356 bsock->timer_start = 0; /* clear timer */
357 if (rc != sizeof(int32_t)) {
358 if (bsock->msglen == BNET_TERMINATE) { /* if we were terminating */
359 bsock->terminated = 1;
360 return false; /* ignore any errors */
364 bsock->b_errno = EIO;
366 bsock->b_errno = errno;
369 if (!bsock->suppress_error_msgs && !bsock->timed_out) {
370 Qmsg4(bsock->jcr, M_ERROR, 0,
371 _("Write error sending to %s:%s:%d: ERR=%s\n"), bsock->who,
372 bsock->host, bsock->port, bnet_strerror(bsock));
375 Qmsg5(bsock->jcr, M_ERROR, 0,
376 _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"), bsock->who,
377 bsock->host, bsock->port, bsock->msglen, rc);
382 bsock->out_msg_no++; /* increment message number */
383 if (bsock->msglen <= 0) { /* length only? */
384 return true; /* yes, no data */
387 /* send data packet */
388 bsock->timer_start = watchdog_time; /* start timer */
389 bsock->timed_out = 0;
390 rc = write_nbytes(bsock, bsock->msg, bsock->msglen);
391 bsock->timer_start = 0; /* clear timer */
392 if (rc != bsock->msglen) {
395 bsock->b_errno = EIO;
397 bsock->b_errno = errno;
400 if (!bsock->suppress_error_msgs) {
401 Qmsg4(bsock->jcr, M_ERROR, 0,
402 _("Write error sending to %s:%s:%d: ERR=%s\n"), bsock->who,
403 bsock->host, bsock->port, bnet_strerror(bsock));
406 Qmsg5(bsock->jcr, M_ERROR, 0,
407 _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
408 bsock->msglen, bsock->who, bsock->host, bsock->port, rc);
416 * Establish an SSL connection -- server side
417 * Codes that ssl_need and ssl_has can take
418 * BNET_SSL_NONE I cannot do ssl
419 * BNET_SSL_OK I can do ssl, but it is not required on my end
420 * BNET_SSL_REQUIRED ssl is required on my end
422 int bnet_ssl_server(BSOCK * bsock, char *password, int ssl_need, int ssl_has)
424 /* Check to see if what we need (ssl_need) corresponds to what he has (ssl_has) */
425 /* The other side expects a response from us */
430 * Establish an SSL connection -- client side
432 int bnet_ssl_client(BSOCK * bsock, char *password, int ssl_need)
434 /* We are the client so we must wait for the server to notify us */
440 * Wait for a specified time for data to appear on
441 * the BSOCK connection.
443 * Returns: 1 if data available
447 int bnet_wait_data(BSOCK * bsock, int sec)
453 FD_SET((unsigned)bsock->fd, &fdset);
457 switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
458 case 0: /* timeout */
462 bsock->b_errno = errno;
463 if (errno == EINTR || errno == EAGAIN) {
466 return -1; /* error return */
475 * As above, but returns on interrupt
477 int bnet_wait_data_intr(BSOCK * bsock, int sec)
483 FD_SET((unsigned)bsock->fd, &fdset);
487 switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
488 case 0: /* timeout */
492 bsock->b_errno = errno;
493 return -1; /* error return */
501 #ifndef NETDB_INTERNAL
502 #define NETDB_INTERNAL -1 /* See errno. */
504 #ifndef NETDB_SUCCESS
505 #define NETDB_SUCCESS 0 /* No problem. */
507 #ifndef HOST_NOT_FOUND
508 #define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found. */
511 #define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL. */
514 #define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP. */
517 #define NO_DATA 4 /* Valid name, no data record of requested type. */
521 * Get human readable error for gethostbyname()
523 static const char *gethost_strerror()
528 msg = strerror(errno);
534 msg = "Authoritative answer for host not found.";
537 msg = "Non-authoritative for host not found, or ServerFail.";
540 msg = "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.";
543 msg = "Valid name, no data record of resquested type.";
546 msg = "Unknown error.";
552 static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
555 static IPADDR *add_any(int family)
557 IPADDR *addr = New(IPADDR(family));
558 addr->set_type(IPADDR::R_MULTIPLE);
559 addr->set_addr_any();
563 static const char *resolv_host(int family, const char *host, dlist * addr_list)
569 #ifdef HAVE_GETHOSTBYNAME2
570 if ((hp = gethostbyname2(host, family)) == NULL) {
572 if ((hp = gethostbyname(host)) == NULL) {
574 /* may be the strerror give not the right result -:( */
575 errmsg = gethost_strerror();
580 for (p = hp->h_addr_list; *p != 0; p++) {
581 IPADDR *addr = New(IPADDR(hp->h_addrtype));
582 addr->set_type(IPADDR::R_MULTIPLE);
583 if (addr->get_family() == AF_INET) {
584 addr->set_addr4((struct in_addr*)*p);
588 addr->set_addr6((struct in6_addr*)*p);
591 addr_list->append(addr);
599 * i host = 0 mean INADDR_ANY only ipv4
601 dlist *bnet_host2ipaddrs(const char *host, int family, const char **errstr)
603 struct in_addr inaddr;
607 struct in6_addr inaddr6;
610 dlist *addr_list = New(dlist(addr, &addr->link));
611 if (!host || host[0] == '\0') {
613 addr_list->append(add_any(family));
615 addr_list->append(add_any(AF_INET));
617 addr_list->append(add_any(AF_INET6));
620 } else if (inet_aton(host, &inaddr)) { /* MA Bug 4 */
621 addr = New(IPADDR(AF_INET));
622 addr->set_type(IPADDR::R_MULTIPLE);
623 addr->set_addr4(&inaddr);
624 addr_list->append(addr);
627 if (inet_pton(AF_INET6, host, &inaddr6) > 1) {
628 addr = New(IPADDR(AF_INET6));
629 addr->set_type(IPADDR::R_MULTIPLE);
630 addr->set_addr6(&inaddr6);
631 addr_list->append(addr);
636 errmsg = resolv_host(family, host, addr_list);
639 free_addresses(addr_list);
643 errmsg = resolv_host(AF_INET, host, addr_list);
646 errmsg = resolv_host(AF_INET6, host, addr_list);
651 free_addresses(addr_list);
660 * Open a TCP connection to the UPS network server
662 * Returns BSOCK * pointer on success
665 static BSOCK *bnet_open(JCR * jcr, const char *name, char *host, char *service,
666 int port, int *fatal)
671 bool connected = false;
677 * Fill in the structure serv_addr with the address of
678 * the server that we want to connect with.
680 if ((addr_list = bnet_host2ipaddrs(host, 0, &errstr)) == NULL) {
681 /* Note errstr is not malloc'ed */
682 Qmsg2(jcr, M_ERROR, 0, "gethostbyname() for host \"%s\" failed: ERR=%s\n",
684 Dmsg2(100, "bnet_host2ipaddrs() for host %s failed: ERR=%s\n",
690 foreach_dlist(ipaddr, addr_list) {
691 ipaddr->set_port_net(htons(port));
692 char allbuf[256 * 10];
694 Dmsg2(100, "Current %sAll %s\n",
695 ipaddr->build_address_str(curbuf, sizeof(curbuf)),
696 build_addresses_str(addr_list, allbuf, sizeof(allbuf)));
697 /* Open a TCP socket */
698 if ((sockfd = socket(ipaddr->get_family(), SOCK_STREAM, 0)) < 0) {
702 Pmsg3(000, "Socket open error. proto=%d port=%d. ERR=%s\n",
703 ipaddr->get_family(), ipaddr->get_port_host_order(), be.strerror());
707 * Keep socket from timing out from inactivity
709 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
711 Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
714 /* connect to server */
715 if (connect(sockfd, ipaddr->get_sockaddr(), ipaddr->get_sockaddr_len()) < 0) {
726 free_addresses(addr_list);
731 * Keep socket from timing out from inactivity
732 * Do this a second time out of paranoia
734 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
736 Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
739 BSOCK* ret = init_bsock(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
740 free_addresses(addr_list);
745 * Try to connect to host for max_retry_time at retry_time intervals.
747 BSOCK *bnet_connect(JCR * jcr, int retry_interval, int max_retry_time,
748 const char *name, char *host, char *service, int port,
755 for (i = 0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL;
756 i -= retry_interval) {
758 if (fatal || (jcr && job_canceled(jcr))) {
761 Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
762 name, host, port, be.strerror());
764 i = 60 * 5; /* complain again in 5 minutes */
766 Qmsg4(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
767 Retrying ...\n", name, host, port, be.strerror());
769 bmicrosleep(retry_interval, 0);
770 max_retry_time -= retry_interval;
771 if (max_retry_time <= 0) {
772 Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
773 name, host, port, be.strerror());
782 * Return the string for the error that occurred
783 * on the socket. Only the first error is retained.
785 const char *bnet_strerror(BSOCK * bsock)
788 if (bsock->errmsg == NULL) {
789 bsock->errmsg = get_pool_memory(PM_MESSAGE);
791 pm_strcpy(bsock->errmsg, be.strerror(bsock->b_errno));
792 return bsock->errmsg;
796 * Format and send a message
797 * Returns: false on error
800 bool bnet_fsend(BSOCK * bs, const char *fmt, ...)
805 if (bs->errors || bs->terminated) {
808 /* This probably won't work, but we vsnprintf, then if we
809 * get a negative length or a length greater than our buffer
810 * (depending on which library is used), the printf was truncated, so
811 * get a bigger buffer and try again.
814 maxlen = sizeof_pool_memory(bs->msg) - 1;
815 va_start(arg_ptr, fmt);
816 bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
818 if (bs->msglen > 0 && bs->msglen < (maxlen - 5)) {
821 bs->msg = realloc_pool_memory(bs->msg, maxlen + maxlen / 2);
823 return bnet_send(bs);
827 * Set the network buffer size, suggested size is in size.
828 * Actual size obtained is returned in bs->msglen
830 * Returns: 0 on failure
833 bool bnet_set_buffer_size(BSOCK * bs, uint32_t size, int rw)
835 uint32_t dbuf_size, start_size;
836 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
839 opt = IPTOS_THROUGHPUT;
840 setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t) & opt, sizeof(opt));
846 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
848 start_size = dbuf_size;
849 if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size + 100)) == NULL) {
850 Qmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
853 if (rw & BNET_SETBUF_READ) {
854 while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
855 SO_RCVBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
857 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
858 dbuf_size -= TAPE_BSIZE;
860 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
861 if (dbuf_size != start_size) {
862 Qmsg1(bs->jcr, M_WARNING, 0,
863 _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
865 if (dbuf_size % TAPE_BSIZE != 0) {
866 Qmsg1(bs->jcr, M_ABORT, 0,
867 _("Network buffer size %d not multiple of tape block size.\n"),
874 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
876 start_size = dbuf_size;
877 if (rw & BNET_SETBUF_WRITE) {
878 while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
879 SO_SNDBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
881 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
882 dbuf_size -= TAPE_BSIZE;
884 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
885 if (dbuf_size != start_size) {
886 Qmsg1(bs->jcr, M_WARNING, 0,
887 _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
889 if (dbuf_size % TAPE_BSIZE != 0) {
890 Qmsg1(bs->jcr, M_ABORT, 0,
891 _("Network buffer size %d not multiple of tape block size.\n"),
896 bs->msglen = dbuf_size;
901 * Send a network "signal" to the other end
902 * This consists of sending a negative packet length
904 * Returns: false on failure
907 bool bnet_sig(BSOCK * bs, int sig)
910 return bnet_send(bs);
914 * Convert a network "signal" code into
915 * human readable ASCII.
917 const char *bnet_sig_to_ascii(BSOCK * bs)
920 switch (bs->msglen) {
922 return "BNET_EOD"; /* end of data stream */
924 return "BNET_EOD_POLL";
926 return "BNET_STATUS";
928 return "BNET_TERMINATE"; /* terminate connection */
932 return "BNET_HEARTBEAT";
933 case BNET_HB_RESPONSE:
934 return "BNET_HB_RESPONSE";
936 return "BNET_PROMPT";
938 sprintf(buf, "Unknown sig %d", bs->msglen);
944 /* Initialize internal socket structure.
945 * This probably should be done in net_open
947 BSOCK *init_bsock(JCR * jcr, int sockfd, const char *who, const char *host, int port,
948 struct sockaddr *client_addr)
950 Dmsg3(100, "who=%s host=%s port=%d\n", who, host, port);
951 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
952 memset(bsock, 0, sizeof(BSOCK));
955 bsock->msg = get_pool_memory(PM_MESSAGE);
956 bsock->errmsg = get_pool_memory(PM_MESSAGE);
957 bsock->who = bstrdup(who);
958 bsock->host = bstrdup(host);
960 memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
962 * ****FIXME**** reduce this to a few hours once
963 * heartbeats are implemented
965 bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */
970 BSOCK *dup_bsock(BSOCK * osock)
972 BSOCK *bsock = (BSOCK *) malloc(sizeof(BSOCK));
973 memcpy(bsock, osock, sizeof(BSOCK));
974 bsock->msg = get_pool_memory(PM_MESSAGE);
975 bsock->errmsg = get_pool_memory(PM_MESSAGE);
977 bsock->who = bstrdup(osock->who);
980 bsock->host = bstrdup(osock->host);
986 /* Close the network connection */
987 void bnet_close(BSOCK * bsock)
991 for (; bsock != NULL; bsock = next) {
994 if (bsock->timed_out) {
995 shutdown(bsock->fd, 2); /* discard any pending I/O */
997 socketClose(bsock->fd); /* normal close */
1004 void term_bsock(BSOCK * bsock)
1007 free_pool_memory(bsock->msg);
1010 ASSERT(1 == 0); /* double close */
1012 if (bsock->errmsg) {
1013 free_pool_memory(bsock->errmsg);
1014 bsock->errmsg = NULL;