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 len 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 Qmsg5(bsock->jcr, M_ERROR, 0,
404 _("Write error sending %d bytes to %s:%s:%d: ERR=%s\n"),
405 bsock->msglen, bsock->who,
406 bsock->host, bsock->port, bnet_strerror(bsock));
409 Qmsg5(bsock->jcr, M_ERROR, 0,
410 _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
411 bsock->msglen, bsock->who, bsock->host, bsock->port, rc);
419 * Establish an SSL connection -- server side
420 * Codes that ssl_need and ssl_has can take
421 * BNET_SSL_NONE I cannot do ssl
422 * BNET_SSL_OK I can do ssl, but it is not required on my end
423 * BNET_SSL_REQUIRED ssl is required on my end
425 int bnet_ssl_server(BSOCK * bsock, char *password, int ssl_need, int ssl_has)
427 /* Check to see if what we need (ssl_need) corresponds to what he has (ssl_has) */
428 /* The other side expects a response from us */
433 * Establish an SSL connection -- client side
435 int bnet_ssl_client(BSOCK * bsock, char *password, int ssl_need)
437 /* We are the client so we must wait for the server to notify us */
443 * Wait for a specified time for data to appear on
444 * the BSOCK connection.
446 * Returns: 1 if data available
450 int bnet_wait_data(BSOCK * bsock, int sec)
456 FD_SET((unsigned)bsock->fd, &fdset);
460 switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
461 case 0: /* timeout */
465 bsock->b_errno = errno;
466 if (errno == EINTR || errno == EAGAIN) {
469 return -1; /* error return */
478 * As above, but returns on interrupt
480 int bnet_wait_data_intr(BSOCK * bsock, int sec)
486 FD_SET((unsigned)bsock->fd, &fdset);
490 switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
491 case 0: /* timeout */
495 bsock->b_errno = errno;
496 return -1; /* error return */
504 #ifndef NETDB_INTERNAL
505 #define NETDB_INTERNAL -1 /* See errno. */
507 #ifndef NETDB_SUCCESS
508 #define NETDB_SUCCESS 0 /* No problem. */
510 #ifndef HOST_NOT_FOUND
511 #define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found. */
514 #define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL. */
517 #define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP. */
520 #define NO_DATA 4 /* Valid name, no data record of requested type. */
524 * Get human readable error for gethostbyname()
526 static const char *gethost_strerror()
531 msg = strerror(errno);
537 msg = "Authoritative answer for host not found.";
540 msg = "Non-authoritative for host not found, or ServerFail.";
543 msg = "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.";
546 msg = "Valid name, no data record of resquested type.";
549 msg = "Unknown error.";
557 static IPADDR *add_any(int family)
559 IPADDR *addr = New(IPADDR(family));
560 addr->set_type(IPADDR::R_MULTIPLE);
561 addr->set_addr_any();
565 static const char *resolv_host(int family, const char *host, dlist * addr_list)
571 #ifdef HAVE_GETHOSTBYNAME2
572 if ((hp = gethostbyname2(host, family)) == NULL) {
574 if ((hp = gethostbyname(host)) == NULL) {
576 /* may be the strerror give not the right result -:( */
577 errmsg = gethost_strerror();
582 for (p = hp->h_addr_list; *p != 0; p++) {
583 IPADDR *addr = New(IPADDR(hp->h_addrtype));
584 addr->set_type(IPADDR::R_MULTIPLE);
585 if (addr->get_family() == AF_INET) {
586 addr->set_addr4((struct in_addr*)*p);
590 addr->set_addr6((struct in6_addr*)*p);
593 addr_list->append(addr);
601 * i host = 0 mean INADDR_ANY only ipv4
603 dlist *bnet_host2ipaddrs(const char *host, int family, const char **errstr)
605 struct in_addr inaddr;
609 struct in6_addr inaddr6;
612 dlist *addr_list = New(dlist(addr, &addr->link));
613 if (!host || host[0] == '\0') {
615 addr_list->append(add_any(family));
617 addr_list->append(add_any(AF_INET));
619 addr_list->append(add_any(AF_INET6));
622 } else if (inet_aton(host, &inaddr)) { /* MA Bug 4 */
623 addr = New(IPADDR(AF_INET));
624 addr->set_type(IPADDR::R_MULTIPLE);
625 addr->set_addr4(&inaddr);
626 addr_list->append(addr);
629 if (inet_pton(AF_INET6, host, &inaddr6) > 1) {
630 addr = New(IPADDR(AF_INET6));
631 addr->set_type(IPADDR::R_MULTIPLE);
632 addr->set_addr6(&inaddr6);
633 addr_list->append(addr);
638 errmsg = resolv_host(family, host, addr_list);
641 free_addresses(addr_list);
645 errmsg = resolv_host(AF_INET, host, addr_list);
648 errmsg = resolv_host(AF_INET6, host, addr_list);
653 free_addresses(addr_list);
662 * Open a TCP connection to the UPS network server
664 * Returns BSOCK * pointer on success
667 static BSOCK *bnet_open(JCR * jcr, const char *name, char *host, char *service,
668 int port, int *fatal)
673 bool connected = false;
679 * Fill in the structure serv_addr with the address of
680 * the server that we want to connect with.
682 if ((addr_list = bnet_host2ipaddrs(host, 0, &errstr)) == NULL) {
683 /* Note errstr is not malloc'ed */
684 Qmsg2(jcr, M_ERROR, 0, "gethostbyname() for host \"%s\" failed: ERR=%s\n",
686 Dmsg2(100, "bnet_host2ipaddrs() for host %s failed: ERR=%s\n",
692 foreach_dlist(ipaddr, addr_list) {
693 ipaddr->set_port_net(htons(port));
694 char allbuf[256 * 10];
696 Dmsg2(100, "Current %sAll %s\n",
697 ipaddr->build_address_str(curbuf, sizeof(curbuf)),
698 build_addresses_str(addr_list, allbuf, sizeof(allbuf)));
699 /* Open a TCP socket */
700 if ((sockfd = socket(ipaddr->get_family(), SOCK_STREAM, 0)) < 0) {
704 Pmsg3(000, "Socket open error. proto=%d port=%d. ERR=%s\n",
705 ipaddr->get_family(), ipaddr->get_port_host_order(), be.strerror());
709 * Keep socket from timing out from inactivity
711 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
713 Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
716 /* connect to server */
717 if (connect(sockfd, ipaddr->get_sockaddr(), ipaddr->get_sockaddr_len()) < 0) {
728 free_addresses(addr_list);
733 * Keep socket from timing out from inactivity
734 * Do this a second time out of paranoia
736 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
738 Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
741 BSOCK* ret = init_bsock(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
742 free_addresses(addr_list);
747 * Try to connect to host for max_retry_time at retry_time intervals.
749 BSOCK *bnet_connect(JCR * jcr, int retry_interval, int max_retry_time,
750 const char *name, char *host, char *service, int port,
757 for (i = 0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL;
758 i -= retry_interval) {
760 if (fatal || (jcr && job_canceled(jcr))) {
763 Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
764 name, host, port, be.strerror());
766 i = 60 * 5; /* complain again in 5 minutes */
768 Qmsg4(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n"
769 "Retrying ...\n", name, host, port, be.strerror());
771 bmicrosleep(retry_interval, 0);
772 max_retry_time -= retry_interval;
773 if (max_retry_time <= 0) {
774 Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
775 name, host, port, be.strerror());
784 * Return the string for the error that occurred
785 * on the socket. Only the first error is retained.
787 const char *bnet_strerror(BSOCK * bsock)
790 if (bsock->errmsg == NULL) {
791 bsock->errmsg = get_pool_memory(PM_MESSAGE);
793 pm_strcpy(bsock->errmsg, be.strerror(bsock->b_errno));
794 return bsock->errmsg;
798 * Format and send a message
799 * Returns: false on error
802 bool bnet_fsend(BSOCK * bs, const char *fmt, ...)
807 if (bs->errors || bs->terminated) {
810 /* This probably won't work, but we vsnprintf, then if we
811 * get a negative length or a length greater than our buffer
812 * (depending on which library is used), the printf was truncated, so
813 * get a bigger buffer and try again.
816 maxlen = sizeof_pool_memory(bs->msg) - 1;
817 va_start(arg_ptr, fmt);
818 bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
820 if (bs->msglen > 0 && bs->msglen < (maxlen - 5)) {
823 bs->msg = realloc_pool_memory(bs->msg, maxlen + maxlen / 2);
825 return bnet_send(bs);
829 * Set the network buffer size, suggested size is in size.
830 * Actual size obtained is returned in bs->msglen
832 * Returns: 0 on failure
835 bool bnet_set_buffer_size(BSOCK * bs, uint32_t size, int rw)
837 uint32_t dbuf_size, start_size;
838 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
841 opt = IPTOS_THROUGHPUT;
842 setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t) & opt, sizeof(opt));
848 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
850 start_size = dbuf_size;
851 if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size + 100)) == NULL) {
852 Qmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
855 if (rw & BNET_SETBUF_READ) {
856 while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
857 SO_RCVBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
859 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
860 dbuf_size -= TAPE_BSIZE;
862 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
863 if (dbuf_size != start_size) {
864 Qmsg1(bs->jcr, M_WARNING, 0,
865 _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
867 if (dbuf_size % TAPE_BSIZE != 0) {
868 Qmsg1(bs->jcr, M_ABORT, 0,
869 _("Network buffer size %d not multiple of tape block size.\n"),
876 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
878 start_size = dbuf_size;
879 if (rw & BNET_SETBUF_WRITE) {
880 while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
881 SO_SNDBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
883 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
884 dbuf_size -= TAPE_BSIZE;
886 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
887 if (dbuf_size != start_size) {
888 Qmsg1(bs->jcr, M_WARNING, 0,
889 _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
891 if (dbuf_size % TAPE_BSIZE != 0) {
892 Qmsg1(bs->jcr, M_ABORT, 0,
893 _("Network buffer size %d not multiple of tape block size.\n"),
898 bs->msglen = dbuf_size;
903 * Send a network "signal" to the other end
904 * This consists of sending a negative packet length
906 * Returns: false on failure
909 bool bnet_sig(BSOCK * bs, int sig)
912 return bnet_send(bs);
916 * Convert a network "signal" code into
917 * human readable ASCII.
919 const char *bnet_sig_to_ascii(BSOCK * bs)
922 switch (bs->msglen) {
924 return "BNET_EOD"; /* end of data stream */
926 return "BNET_EOD_POLL";
928 return "BNET_STATUS";
930 return "BNET_TERMINATE"; /* terminate connection */
934 return "BNET_HEARTBEAT";
935 case BNET_HB_RESPONSE:
936 return "BNET_HB_RESPONSE";
938 return "BNET_PROMPT";
940 sprintf(buf, "Unknown sig %d", (int)bs->msglen);
946 /* Initialize internal socket structure.
947 * This probably should be done in net_open
949 BSOCK *init_bsock(JCR * jcr, int sockfd, const char *who, const char *host, int port,
950 struct sockaddr *client_addr)
952 Dmsg3(100, "who=%s host=%s port=%d\n", who, host, port);
953 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
954 memset(bsock, 0, sizeof(BSOCK));
957 bsock->msg = get_pool_memory(PM_MESSAGE);
958 bsock->errmsg = get_pool_memory(PM_MESSAGE);
959 bsock->who = bstrdup(who);
960 bsock->host = bstrdup(host);
962 memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
964 * ****FIXME**** reduce this to a few hours once
965 * heartbeats are implemented
967 bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */
972 BSOCK *dup_bsock(BSOCK * osock)
974 BSOCK *bsock = (BSOCK *) malloc(sizeof(BSOCK));
975 memcpy(bsock, osock, sizeof(BSOCK));
976 bsock->msg = get_pool_memory(PM_MESSAGE);
977 bsock->errmsg = get_pool_memory(PM_MESSAGE);
979 bsock->who = bstrdup(osock->who);
982 bsock->host = bstrdup(osock->host);
988 /* Close the network connection */
989 void bnet_close(BSOCK * bsock)
993 for (; bsock != NULL; bsock = next) {
996 if (bsock->timed_out) {
997 shutdown(bsock->fd, 2); /* discard any pending I/O */
999 socketClose(bsock->fd); /* normal close */
1006 void term_bsock(BSOCK * bsock)
1009 free_pool_memory(bsock->msg);
1012 ASSERT(1 == 0); /* double close */
1014 if (bsock->errmsg) {
1015 free_pool_memory(bsock->errmsg);
1016 bsock->errmsg = NULL;