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
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)
56 static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
59 * Read a nbytes from the network.
60 * It is possible that the total bytes require in several
64 static int32_t read_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes)
72 nread = socketRead(bsock->fd, ptr, nleft);
73 if (bsock->timed_out || bsock->terminated) {
76 } while (nread == -1 && (errno == EINTR || errno == EAGAIN));
78 return nread; /* error, or EOF */
83 return nbytes - nleft; /* return >= 0 */
87 * Write nbytes to the network.
88 * It may require several writes.
91 static int32_t write_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes)
93 int32_t nleft, nwritten;
96 nwritten = fwrite(ptr, 1, nbytes, bsock->spool_fd);
97 if (nwritten != nbytes) {
99 bsock->b_errno = errno;
100 Qmsg1(bsock->jcr, M_FATAL, 0, _("Attr spool write error. ERR=%s\n"),
102 Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes);
103 errno = bsock->b_errno;
112 nwritten = socketWrite(bsock->fd, ptr, nleft);
113 if (bsock->timed_out || bsock->terminated) {
116 } while (nwritten == -1 && errno == EINTR);
118 * If connection is non-blocking, we will get EAGAIN, so
119 * use select() to keep from consuming all the CPU
122 if (nwritten == -1 && errno == EAGAIN) {
127 FD_SET((unsigned)bsock->fd, &fdset);
130 select(bsock->fd + 1, NULL, &fdset, NULL, &tv);
134 return nwritten; /* error */
139 return nbytes - nleft;
143 * Receive a message from the other end. Each message consists of
144 * two packets. The first is a header that contains the size
145 * of the data that follows in the second packet.
146 * Returns number of bytes read (may return zero)
147 * Returns -1 on signal (BNET_SIGNAL)
148 * Returns -2 on hard end of file (BNET_HARDEOF)
149 * Returns -3 on error (BNET_ERROR)
151 * Unfortunately, it is a bit complicated because we have these
154 * 2. Signal including end of data stream
155 * 3. Hard end of file
157 * Using is_bnet_stop() and is_bnet_error() you can figure this all out.
159 int32_t bnet_recv(BSOCK * bsock)
164 ASSERT(bsock != NULL);
167 if (bsock->errors || bsock->terminated) {
171 bsock->read_seqno++; /* bump sequence number */
172 bsock->timer_start = watchdog_time; /* set start wait time */
173 bsock->timed_out = 0;
174 /* get data size -- in int32_t */
175 if ((nbytes = read_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
176 bsock->timer_start = 0; /* clear timer */
177 /* probably pipe broken because client died */
179 bsock->b_errno = ENODATA;
181 bsock->b_errno = errno;
184 return BNET_HARDEOF; /* assume hard EOF received */
186 bsock->timer_start = 0; /* clear timer */
187 if (nbytes != sizeof(int32_t)) {
189 bsock->b_errno = EIO;
190 Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
191 sizeof(int32_t), nbytes, bsock->who, bsock->host, bsock->port);
195 pktsiz = ntohl(pktsiz); /* decode no. of bytes that follow */
197 if (pktsiz == 0) { /* No data transferred */
198 bsock->timer_start = 0; /* clear timer */
201 return 0; /* zero bytes read */
204 /* If signal or packet size too big */
205 if (pktsiz < 0 || pktsiz > 1000000) {
206 if (pktsiz > 0) { /* if packet too big */
207 Qmsg3(bsock->jcr, M_FATAL, 0,
208 _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
209 bsock->who, bsock->host, bsock->port);
210 pktsiz = BNET_TERMINATE; /* hang up */
212 if (pktsiz == BNET_TERMINATE) {
213 bsock->terminated = 1;
215 bsock->timer_start = 0; /* clear timer */
216 bsock->b_errno = ENODATA;
217 bsock->msglen = pktsiz; /* signal code */
218 return BNET_SIGNAL; /* signal */
221 /* Make sure the buffer is big enough + one byte for EOS */
222 if (pktsiz >= (int32_t) sizeof_pool_memory(bsock->msg)) {
223 bsock->msg = realloc_pool_memory(bsock->msg, pktsiz + 100);
226 bsock->timer_start = watchdog_time; /* set start wait time */
227 bsock->timed_out = 0;
228 /* now read the actual data */
229 if ((nbytes = read_nbytes(bsock, bsock->msg, pktsiz)) <= 0) {
230 bsock->timer_start = 0; /* clear timer */
232 bsock->b_errno = ENODATA;
234 bsock->b_errno = errno;
237 Qmsg4(bsock->jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
238 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
241 bsock->timer_start = 0; /* clear timer */
243 bsock->msglen = nbytes;
244 if (nbytes != pktsiz) {
245 bsock->b_errno = EIO;
247 Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
248 pktsiz, nbytes, bsock->who, bsock->host, bsock->port);
251 /* always add a zero by to properly terminate any
252 * string that was send to us. Note, we ensured above that the
253 * buffer is at least one byte longer than the message length.
255 bsock->msg[nbytes] = 0; /* terminate in case it is a string */
256 sm_check(__FILE__, __LINE__, false);
257 return nbytes; /* return actual length of message */
262 * Return 1 if there are errors on this bsock or it is closed,
263 * i.e. stop communicating on this line.
265 bool is_bnet_stop(BSOCK * bsock)
267 return bsock->errors || bsock->terminated;
271 * Return number of errors on socket
273 int is_bnet_error(BSOCK * bsock)
275 errno = bsock->b_errno;
276 return bsock->errors;
280 * Call here after error during closing to suppress error
281 * messages which are due to the other end shutting down too.
283 void bnet_suppress_error_messages(BSOCK * bsock, bool flag)
285 bsock->suppress_error_msgs = flag;
290 * Transmit spooled data now to a BSOCK
292 int bnet_despool_to_bsock(BSOCK * bsock, void update_attr_spool_size(ssize_t size),
297 ssize_t last = 0, size = 0;
300 rewind(bsock->spool_fd);
301 while (fread((char *)&pktsiz, 1, sizeof(int32_t), bsock->spool_fd) ==
303 size += sizeof(int32_t);
304 bsock->msglen = ntohl(pktsiz);
305 if (bsock->msglen > 0) {
306 if (bsock->msglen > (int32_t) sizeof_pool_memory(bsock->msg)) {
307 bsock->msg = realloc_pool_memory(bsock->msg, bsock->msglen + 1);
309 nbytes = fread(bsock->msg, 1, bsock->msglen, bsock->spool_fd);
310 if (nbytes != (size_t) bsock->msglen) {
312 Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, bsock->msglen);
313 Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
315 update_attr_spool_size(tsize - last);
319 if ((++count & 0x3F) == 0) {
320 update_attr_spool_size(size - last);
326 update_attr_spool_size(tsize - last);
327 if (ferror(bsock->spool_fd)) {
329 Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
338 * Send a message over the network. The send consists of
339 * two network packets. The first is sends a 32 bit integer containing
340 * the length of the data packet which follows.
342 * Returns: false on failure
345 bool bnet_send(BSOCK * bsock)
350 if (bsock->errors || bsock->terminated || bsock->msglen > 1000000) {
353 pktsiz = htonl((int32_t) bsock->msglen);
354 /* send int32_t containing size of data packet */
355 bsock->timer_start = watchdog_time; /* start timer */
356 bsock->timed_out = 0;
357 rc = write_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t));
358 bsock->timer_start = 0; /* clear timer */
359 if (rc != sizeof(int32_t)) {
360 if (bsock->msglen == BNET_TERMINATE) { /* if we were terminating */
361 bsock->terminated = 1;
362 return false; /* ignore any errors */
366 bsock->b_errno = EIO;
368 bsock->b_errno = errno;
371 if (!bsock->suppress_error_msgs && !bsock->timed_out) {
372 Qmsg4(bsock->jcr, M_ERROR, 0,
373 _("Write error sending to %s:%s:%d: ERR=%s\n"), bsock->who,
374 bsock->host, bsock->port, bnet_strerror(bsock));
377 Qmsg5(bsock->jcr, M_ERROR, 0,
378 _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"), bsock->who,
379 bsock->host, bsock->port, bsock->msglen, rc);
384 bsock->out_msg_no++; /* increment message number */
385 if (bsock->msglen <= 0) { /* length only? */
386 return true; /* yes, no data */
389 /* send data packet */
390 bsock->timer_start = watchdog_time; /* start timer */
391 bsock->timed_out = 0;
392 rc = write_nbytes(bsock, bsock->msg, bsock->msglen);
393 bsock->timer_start = 0; /* clear timer */
394 if (rc != bsock->msglen) {
397 bsock->b_errno = EIO;
399 bsock->b_errno = errno;
402 if (!bsock->suppress_error_msgs) {
403 Qmsg4(bsock->jcr, M_ERROR, 0,
404 _("Write error sending to %s:%s:%d: ERR=%s\n"), bsock->who,
405 bsock->host, bsock->port, bnet_strerror(bsock));
408 Qmsg5(bsock->jcr, M_ERROR, 0,
409 _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
410 bsock->msglen, bsock->who, bsock->host, bsock->port, rc);
418 * Establish an SSL connection -- server side
419 * Codes that ssl_need and ssl_has can take
420 * BNET_SSL_NONE I cannot do ssl
421 * BNET_SSL_OK I can do ssl, but it is not required on my end
422 * BNET_SSL_REQUIRED ssl is required on my end
424 int bnet_ssl_server(BSOCK * bsock, char *password, int ssl_need, int ssl_has)
426 /* Check to see if what we need (ssl_need) corresponds to what he has (ssl_has) */
427 /* The other side expects a response from us */
432 * Establish an SSL connection -- client side
434 int bnet_ssl_client(BSOCK * bsock, char *password, int ssl_need)
436 /* We are the client so we must wait for the server to notify us */
442 * Wait for a specified time for data to appear on
443 * the BSOCK connection.
445 * Returns: 1 if data available
449 int bnet_wait_data(BSOCK * bsock, int sec)
455 FD_SET((unsigned)bsock->fd, &fdset);
459 switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
460 case 0: /* timeout */
464 bsock->b_errno = errno;
465 if (errno == EINTR || errno == EAGAIN) {
468 return -1; /* error return */
477 * As above, but returns on interrupt
479 int bnet_wait_data_intr(BSOCK * bsock, int sec)
485 FD_SET((unsigned)bsock->fd, &fdset);
489 switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
490 case 0: /* timeout */
494 bsock->b_errno = errno;
495 return -1; /* error return */
503 #ifndef NETDB_INTERNAL
504 #define NETDB_INTERNAL -1 /* See errno. */
506 #ifndef NETDB_SUCCESS
507 #define NETDB_SUCCESS 0 /* No problem. */
509 #ifndef HOST_NOT_FOUND
510 #define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found. */
513 #define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL. */
516 #define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP. */
519 #define NO_DATA 4 /* Valid name, no data record of requested type. */
523 * Get human readable error for gethostbyname()
525 static const char *gethost_strerror()
530 msg = strerror(errno);
536 msg = "Authoritative answer for host not found.";
539 msg = "Non-authoritative for host not found, or ServerFail.";
542 msg = "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.";
545 msg = "Valid name, no data record of resquested type.";
548 msg = "Unknown error.";
556 static IPADDR *add_any(int family)
558 IPADDR *addr = New(IPADDR(family));
559 addr->set_type(IPADDR::R_MULTIPLE);
560 addr->set_addr_any();
564 static const char *resolv_host(int family, const char *host, dlist * addr_list)
570 #ifdef HAVE_GETHOSTBYNAME2
571 if ((hp = gethostbyname2(host, family)) == NULL) {
573 if ((hp = gethostbyname(host)) == NULL) {
575 /* may be the strerror give not the right result -:( */
576 errmsg = gethost_strerror();
581 for (p = hp->h_addr_list; *p != 0; p++) {
582 IPADDR *addr = New(IPADDR(hp->h_addrtype));
583 addr->set_type(IPADDR::R_MULTIPLE);
584 if (addr->get_family() == AF_INET) {
585 addr->set_addr4((struct in_addr*)*p);
589 addr->set_addr6((struct in6_addr*)*p);
592 addr_list->append(addr);
600 * i host = 0 mean INADDR_ANY only ipv4
602 dlist *bnet_host2ipaddrs(const char *host, int family, const char **errstr)
604 struct in_addr inaddr;
608 struct in6_addr inaddr6;
611 dlist *addr_list = New(dlist(addr, &addr->link));
612 if (!host || host[0] == '\0') {
614 addr_list->append(add_any(family));
616 addr_list->append(add_any(AF_INET));
618 addr_list->append(add_any(AF_INET6));
621 } else if (inet_aton(host, &inaddr)) { /* MA Bug 4 */
622 addr = New(IPADDR(AF_INET));
623 addr->set_type(IPADDR::R_MULTIPLE);
624 addr->set_addr4(&inaddr);
625 addr_list->append(addr);
628 if (inet_pton(AF_INET6, host, &inaddr6) > 1) {
629 addr = New(IPADDR(AF_INET6));
630 addr->set_type(IPADDR::R_MULTIPLE);
631 addr->set_addr6(&inaddr6);
632 addr_list->append(addr);
637 errmsg = resolv_host(family, host, addr_list);
640 free_addresses(addr_list);
644 errmsg = resolv_host(AF_INET, host, addr_list);
647 errmsg = resolv_host(AF_INET6, host, addr_list);
652 free_addresses(addr_list);
661 * Open a TCP connection to the UPS network server
663 * Returns BSOCK * pointer on success
666 static BSOCK *bnet_open(JCR * jcr, const char *name, char *host, char *service,
667 int port, int *fatal)
672 bool connected = false;
678 * Fill in the structure serv_addr with the address of
679 * the server that we want to connect with.
681 if ((addr_list = bnet_host2ipaddrs(host, 0, &errstr)) == NULL) {
682 /* Note errstr is not malloc'ed */
683 Qmsg2(jcr, M_ERROR, 0, "gethostbyname() for host \"%s\" failed: ERR=%s\n",
685 Dmsg2(100, "bnet_host2ipaddrs() for host %s failed: ERR=%s\n",
691 foreach_dlist(ipaddr, addr_list) {
692 ipaddr->set_port_net(htons(port));
693 char allbuf[256 * 10];
695 Dmsg2(100, "Current %sAll %s\n",
696 ipaddr->build_address_str(curbuf, sizeof(curbuf)),
697 build_addresses_str(addr_list, allbuf, sizeof(allbuf)));
698 /* Open a TCP socket */
699 if ((sockfd = socket(ipaddr->get_family(), SOCK_STREAM, 0)) < 0) {
703 Pmsg3(000, "Socket open error. proto=%d port=%d. ERR=%s\n",
704 ipaddr->get_family(), ipaddr->get_port_host_order(), be.strerror());
708 * Keep socket from timing out from inactivity
710 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
712 Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
715 /* connect to server */
716 if (connect(sockfd, ipaddr->get_sockaddr(), ipaddr->get_sockaddr_len()) < 0) {
727 free_addresses(addr_list);
732 * Keep socket from timing out from inactivity
733 * Do this a second time out of paranoia
735 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
737 Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
740 BSOCK* ret = init_bsock(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
741 free_addresses(addr_list);
746 * Try to connect to host for max_retry_time at retry_time intervals.
748 BSOCK *bnet_connect(JCR * jcr, int retry_interval, int max_retry_time,
749 const char *name, char *host, char *service, int port,
756 for (i = 0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL;
757 i -= retry_interval) {
759 if (fatal || (jcr && job_canceled(jcr))) {
762 Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
763 name, host, port, be.strerror());
765 i = 60 * 5; /* complain again in 5 minutes */
767 Qmsg4(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n"
768 "Retrying ...\n", name, host, port, be.strerror());
770 bmicrosleep(retry_interval, 0);
771 max_retry_time -= retry_interval;
772 if (max_retry_time <= 0) {
773 Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
774 name, host, port, be.strerror());
783 * Return the string for the error that occurred
784 * on the socket. Only the first error is retained.
786 const char *bnet_strerror(BSOCK * bsock)
789 if (bsock->errmsg == NULL) {
790 bsock->errmsg = get_pool_memory(PM_MESSAGE);
792 pm_strcpy(bsock->errmsg, be.strerror(bsock->b_errno));
793 return bsock->errmsg;
797 * Format and send a message
798 * Returns: false on error
801 bool bnet_fsend(BSOCK * bs, const char *fmt, ...)
806 if (bs->errors || bs->terminated) {
809 /* This probably won't work, but we vsnprintf, then if we
810 * get a negative length or a length greater than our buffer
811 * (depending on which library is used), the printf was truncated, so
812 * get a bigger buffer and try again.
815 maxlen = sizeof_pool_memory(bs->msg) - 1;
816 va_start(arg_ptr, fmt);
817 bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
819 if (bs->msglen > 0 && bs->msglen < (maxlen - 5)) {
822 bs->msg = realloc_pool_memory(bs->msg, maxlen + maxlen / 2);
824 return bnet_send(bs);
828 * Set the network buffer size, suggested size is in size.
829 * Actual size obtained is returned in bs->msglen
831 * Returns: 0 on failure
834 bool bnet_set_buffer_size(BSOCK * bs, uint32_t size, int rw)
836 uint32_t dbuf_size, start_size;
837 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
840 opt = IPTOS_THROUGHPUT;
841 setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t) & opt, sizeof(opt));
847 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
849 start_size = dbuf_size;
850 if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size + 100)) == NULL) {
851 Qmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
854 if (rw & BNET_SETBUF_READ) {
855 while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
856 SO_RCVBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
858 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
859 dbuf_size -= TAPE_BSIZE;
861 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
862 if (dbuf_size != start_size) {
863 Qmsg1(bs->jcr, M_WARNING, 0,
864 _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
866 if (dbuf_size % TAPE_BSIZE != 0) {
867 Qmsg1(bs->jcr, M_ABORT, 0,
868 _("Network buffer size %d not multiple of tape block size.\n"),
875 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
877 start_size = dbuf_size;
878 if (rw & BNET_SETBUF_WRITE) {
879 while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
880 SO_SNDBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
882 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
883 dbuf_size -= TAPE_BSIZE;
885 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
886 if (dbuf_size != start_size) {
887 Qmsg1(bs->jcr, M_WARNING, 0,
888 _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
890 if (dbuf_size % TAPE_BSIZE != 0) {
891 Qmsg1(bs->jcr, M_ABORT, 0,
892 _("Network buffer size %d not multiple of tape block size.\n"),
897 bs->msglen = dbuf_size;
902 * Send a network "signal" to the other end
903 * This consists of sending a negative packet length
905 * Returns: false on failure
908 bool bnet_sig(BSOCK * bs, int sig)
911 return bnet_send(bs);
915 * Convert a network "signal" code into
916 * human readable ASCII.
918 const char *bnet_sig_to_ascii(BSOCK * bs)
921 switch (bs->msglen) {
923 return "BNET_EOD"; /* end of data stream */
925 return "BNET_EOD_POLL";
927 return "BNET_STATUS";
929 return "BNET_TERMINATE"; /* terminate connection */
933 return "BNET_HEARTBEAT";
934 case BNET_HB_RESPONSE:
935 return "BNET_HB_RESPONSE";
937 return "BNET_PROMPT";
939 sprintf(buf, "Unknown sig %d", (int)bs->msglen);
945 /* Initialize internal socket structure.
946 * This probably should be done in net_open
948 BSOCK *init_bsock(JCR * jcr, int sockfd, const char *who, const char *host, int port,
949 struct sockaddr *client_addr)
951 Dmsg3(100, "who=%s host=%s port=%d\n", who, host, port);
952 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
953 memset(bsock, 0, sizeof(BSOCK));
956 bsock->msg = get_pool_memory(PM_MESSAGE);
957 bsock->errmsg = get_pool_memory(PM_MESSAGE);
958 bsock->who = bstrdup(who);
959 bsock->host = bstrdup(host);
961 memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
963 * ****FIXME**** reduce this to a few hours once
964 * heartbeats are implemented
966 bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */
971 BSOCK *dup_bsock(BSOCK * osock)
973 BSOCK *bsock = (BSOCK *) malloc(sizeof(BSOCK));
974 memcpy(bsock, osock, sizeof(BSOCK));
975 bsock->msg = get_pool_memory(PM_MESSAGE);
976 bsock->errmsg = get_pool_memory(PM_MESSAGE);
978 bsock->who = bstrdup(osock->who);
981 bsock->host = bstrdup(osock->host);
987 /* Close the network connection */
988 void bnet_close(BSOCK * bsock)
992 for (; bsock != NULL; bsock = next) {
995 if (bsock->timed_out) {
996 shutdown(bsock->fd, 2); /* discard any pending I/O */
998 socketClose(bsock->fd); /* normal close */
1005 void term_bsock(BSOCK * bsock)
1008 free_pool_memory(bsock->msg);
1011 ASSERT(1 == 0); /* double close */
1013 if (bsock->errmsg) {
1014 free_pool_memory(bsock->errmsg);
1015 bsock->errmsg = NULL;