2 * Network Utility Routines
6 * Adapted and enhanced for Bacula, originally written
7 * for inclusion in the Apcupsd package
12 Copyright (C) 2000-2005 Kern Sibbald
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License
16 version 2 as ammended with additional clauses defined in the
17 file LICENSE in the main source directory.
19 This program 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
22 the file LICENSE for additional details.
31 extern time_t watchdog_time;
34 #define INADDR_NONE -1
37 #ifndef ENODATA /* not defined on BSD systems */
42 #define socketRead(fd, buf, len) recv(fd, buf, len, 0)
43 #define socketWrite(fd, buf, len) send(fd, buf, len, 0)
44 #define socketClose(fd) closesocket(fd)
46 #define socketRead(fd, buf, len) read(fd, buf, len)
47 #define socketWrite(fd, buf, len) write(fd, buf, len)
48 #define socketClose(fd) close(fd)
51 static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
54 * Read a nbytes from the network.
55 * It is possible that the total bytes require in several
59 static int32_t read_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes)
66 return (tls_bsock_readn(bsock, ptr, nbytes));
74 nread = socketRead(bsock->fd, ptr, nleft);
75 if (bsock->timed_out || bsock->terminated) {
78 } while (nread == -1 && (errno == EINTR || errno == EAGAIN));
80 return nread; /* error, or EOF */
85 return nbytes - nleft; /* return >= 0 */
89 * Write nbytes to the network.
90 * It may require several writes.
93 static int32_t write_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes)
95 int32_t nleft, nwritten;
98 nwritten = fwrite(ptr, 1, nbytes, bsock->spool_fd);
99 if (nwritten != nbytes) {
101 bsock->b_errno = errno;
102 Qmsg1(bsock->jcr, M_FATAL, 0, _("Attr spool write error. ERR=%s\n"),
104 Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes);
105 errno = bsock->b_errno;
114 return (tls_bsock_writen(bsock, ptr, nbytes));
116 #endif /* HAVE_TLS */
122 nwritten = socketWrite(bsock->fd, ptr, nleft);
123 if (bsock->timed_out || bsock->terminated) {
126 } while (nwritten == -1 && errno == EINTR);
128 * If connection is non-blocking, we will get EAGAIN, so
129 * use select() to keep from consuming all the CPU
132 if (nwritten == -1 && errno == EAGAIN) {
137 FD_SET((unsigned)bsock->fd, &fdset);
140 select(bsock->fd + 1, NULL, &fdset, NULL, &tv);
144 return nwritten; /* error */
149 return nbytes - nleft;
153 * Receive a message from the other end. Each message consists of
154 * two packets. The first is a header that contains the size
155 * of the data that follows in the second packet.
156 * Returns number of bytes read (may return zero)
157 * Returns -1 on signal (BNET_SIGNAL)
158 * Returns -2 on hard end of file (BNET_HARDEOF)
159 * Returns -3 on error (BNET_ERROR)
161 * Unfortunately, it is a bit complicated because we have these
164 * 2. Signal including end of data stream
165 * 3. Hard end of file
167 * Using is_bnet_stop() and is_bnet_error() you can figure this all out.
169 int32_t bnet_recv(BSOCK * bsock)
174 ASSERT(bsock != NULL);
177 if (bsock->errors || bsock->terminated) {
181 bsock->read_seqno++; /* bump sequence number */
182 bsock->timer_start = watchdog_time; /* set start wait time */
183 bsock->timed_out = 0;
184 /* get data size -- in int32_t */
185 if ((nbytes = read_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
186 bsock->timer_start = 0; /* clear timer */
187 /* probably pipe broken because client died */
189 bsock->b_errno = ENODATA;
191 bsock->b_errno = errno;
194 return BNET_HARDEOF; /* assume hard EOF received */
196 bsock->timer_start = 0; /* clear timer */
197 if (nbytes != sizeof(int32_t)) {
199 bsock->b_errno = EIO;
200 Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
201 sizeof(int32_t), nbytes, bsock->who, bsock->host, bsock->port);
205 pktsiz = ntohl(pktsiz); /* decode no. of bytes that follow */
207 if (pktsiz == 0) { /* No data transferred */
208 bsock->timer_start = 0; /* clear timer */
211 return 0; /* zero bytes read */
214 /* If signal or packet size too big */
215 if (pktsiz < 0 || pktsiz > 1000000) {
216 if (pktsiz > 0) { /* if packet too big */
217 Qmsg3(bsock->jcr, M_FATAL, 0,
218 _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
219 bsock->who, bsock->host, bsock->port);
220 pktsiz = BNET_TERMINATE; /* hang up */
222 if (pktsiz == BNET_TERMINATE) {
223 bsock->terminated = 1;
225 bsock->timer_start = 0; /* clear timer */
226 bsock->b_errno = ENODATA;
227 bsock->msglen = pktsiz; /* signal code */
228 return BNET_SIGNAL; /* signal */
231 /* Make sure the buffer is big enough + one byte for EOS */
232 if (pktsiz >= (int32_t) sizeof_pool_memory(bsock->msg)) {
233 bsock->msg = realloc_pool_memory(bsock->msg, pktsiz + 100);
236 bsock->timer_start = watchdog_time; /* set start wait time */
237 bsock->timed_out = 0;
238 /* now read the actual data */
239 if ((nbytes = read_nbytes(bsock, bsock->msg, pktsiz)) <= 0) {
240 bsock->timer_start = 0; /* clear timer */
242 bsock->b_errno = ENODATA;
244 bsock->b_errno = errno;
247 Qmsg4(bsock->jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
248 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
251 bsock->timer_start = 0; /* clear timer */
253 bsock->msglen = nbytes;
254 if (nbytes != pktsiz) {
255 bsock->b_errno = EIO;
257 Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
258 pktsiz, nbytes, bsock->who, bsock->host, bsock->port);
261 /* always add a zero by to properly terminate any
262 * string that was send to us. Note, we ensured above that the
263 * buffer is at least one byte longer than the message length.
265 bsock->msg[nbytes] = 0; /* terminate in case it is a string */
266 sm_check(__FILE__, __LINE__, false);
267 return nbytes; /* return actual length of message */
272 * Return 1 if there are errors on this bsock or it is closed,
273 * i.e. stop communicating on this line.
275 bool is_bnet_stop(BSOCK * bsock)
277 return bsock->errors || bsock->terminated;
281 * Return number of errors on socket
283 int is_bnet_error(BSOCK * bsock)
285 errno = bsock->b_errno;
286 return bsock->errors;
290 * Call here after error during closing to suppress error
291 * messages which are due to the other end shutting down too.
293 void bnet_suppress_error_messages(BSOCK * bsock, bool flag)
295 bsock->suppress_error_msgs = flag;
300 * Transmit spooled data now to a BSOCK
302 int bnet_despool_to_bsock(BSOCK * bsock, void update_attr_spool_size(ssize_t size),
307 ssize_t last = 0, size = 0;
310 rewind(bsock->spool_fd);
311 while (fread((char *)&pktsiz, 1, sizeof(int32_t), bsock->spool_fd) ==
313 size += sizeof(int32_t);
314 bsock->msglen = ntohl(pktsiz);
315 if (bsock->msglen > 0) {
316 if (bsock->msglen > (int32_t) sizeof_pool_memory(bsock->msg)) {
317 bsock->msg = realloc_pool_memory(bsock->msg, bsock->msglen + 1);
319 nbytes = fread(bsock->msg, 1, bsock->msglen, bsock->spool_fd);
320 if (nbytes != (size_t) bsock->msglen) {
322 Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, bsock->msglen);
323 Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
325 update_attr_spool_size(tsize - last);
329 if ((++count & 0x3F) == 0) {
330 update_attr_spool_size(size - last);
336 update_attr_spool_size(tsize - last);
337 if (ferror(bsock->spool_fd)) {
339 Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
348 * Send a message over the network. The send consists of
349 * two network packets. The first is sends a 32 bit integer containing
350 * the length of the data packet which follows.
352 * Returns: false on failure
355 bool bnet_send(BSOCK * bsock)
360 if (bsock->errors || bsock->terminated || bsock->msglen > 1000000) {
363 pktsiz = htonl((int32_t) bsock->msglen);
364 /* send int32_t containing size of data packet */
365 bsock->timer_start = watchdog_time; /* start timer */
366 bsock->timed_out = 0;
367 rc = write_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t));
368 bsock->timer_start = 0; /* clear timer */
369 if (rc != sizeof(int32_t)) {
370 if (bsock->msglen == BNET_TERMINATE) { /* if we were terminating */
371 bsock->terminated = 1;
372 return false; /* ignore any errors */
376 bsock->b_errno = EIO;
378 bsock->b_errno = errno;
381 if (!bsock->suppress_error_msgs && !bsock->timed_out) {
382 Qmsg4(bsock->jcr, M_ERROR, 0,
383 _("Write error sending len to %s:%s:%d: ERR=%s\n"), bsock->who,
384 bsock->host, bsock->port, bnet_strerror(bsock));
387 Qmsg5(bsock->jcr, M_ERROR, 0,
388 _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"), bsock->who,
389 bsock->host, bsock->port, bsock->msglen, rc);
394 bsock->out_msg_no++; /* increment message number */
395 if (bsock->msglen <= 0) { /* length only? */
396 return true; /* yes, no data */
399 /* send data packet */
400 bsock->timer_start = watchdog_time; /* start timer */
401 bsock->timed_out = 0;
402 rc = write_nbytes(bsock, bsock->msg, bsock->msglen);
403 bsock->timer_start = 0; /* clear timer */
404 if (rc != bsock->msglen) {
407 bsock->b_errno = EIO;
409 bsock->b_errno = errno;
412 if (!bsock->suppress_error_msgs) {
413 Qmsg5(bsock->jcr, M_ERROR, 0,
414 _("Write error sending %d bytes to %s:%s:%d: ERR=%s\n"),
415 bsock->msglen, bsock->who,
416 bsock->host, bsock->port, bnet_strerror(bsock));
419 Qmsg5(bsock->jcr, M_ERROR, 0,
420 _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
421 bsock->msglen, bsock->who, bsock->host, bsock->port, rc);
429 * Establish a TLS connection -- server side
430 * Returns: 1 on success
434 int bnet_tls_server(TLS_CONTEXT *ctx, BSOCK * bsock, alist *verify_list)
438 tls = new_tls_connection(ctx, bsock->fd);
440 Qmsg0(bsock->jcr, M_FATAL, 0, _("TLS connection initialization failed.\n"));
446 /* Initiate TLS Negotiation */
447 if (!tls_bsock_accept(bsock)) {
448 Qmsg0(bsock->jcr, M_FATAL, 0, _("TLS Negotiation failed.\n"));
453 if (!tls_postconnect_verify_cn(tls, verify_list)) {
454 Qmsg1(bsock->jcr, M_FATAL, 0, _("TLS certificate verification failed."
455 " Peer certificate did not match a required commonName\n"),
464 free_tls_connection(tls);
470 * Establish a TLS connection -- client side
471 * Returns: 1 on success
474 int bnet_tls_client(TLS_CONTEXT *ctx, BSOCK * bsock)
478 tls = new_tls_connection(ctx, bsock->fd);
480 Qmsg0(bsock->jcr, M_FATAL, 0, _("TLS connection initialization failed.\n"));
486 /* Initiate TLS Negotiation */
487 if (!tls_bsock_connect(bsock)) {
491 if (!tls_postconnect_verify_host(tls, bsock->host)) {
492 Qmsg1(bsock->jcr, M_FATAL, 0, _("TLS host certificate verification failed. Host %s did not match presented certificate\n"), bsock->host);
499 free_tls_connection(tls);
503 #endif /* HAVE_TLS */
506 * Wait for a specified time for data to appear on
507 * the BSOCK connection.
509 * Returns: 1 if data available
513 int bnet_wait_data(BSOCK * bsock, int sec)
519 FD_SET((unsigned)bsock->fd, &fdset);
523 switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
524 case 0: /* timeout */
528 bsock->b_errno = errno;
529 if (errno == EINTR || errno == EAGAIN) {
532 return -1; /* error return */
541 * As above, but returns on interrupt
543 int bnet_wait_data_intr(BSOCK * bsock, int sec)
549 FD_SET((unsigned)bsock->fd, &fdset);
552 switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
553 case 0: /* timeout */
557 bsock->b_errno = errno;
558 return -1; /* error return */
565 #ifndef NETDB_INTERNAL
566 #define NETDB_INTERNAL -1 /* See errno. */
568 #ifndef NETDB_SUCCESS
569 #define NETDB_SUCCESS 0 /* No problem. */
571 #ifndef HOST_NOT_FOUND
572 #define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found. */
575 #define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL. */
578 #define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP. */
581 #define NO_DATA 4 /* Valid name, no data record of requested type. */
585 * Get human readable error for gethostbyname()
587 static const char *gethost_strerror()
599 msg = "Authoritative answer for host not found.";
602 msg = "Non-authoritative for host not found, or ServerFail.";
605 msg = "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.";
608 msg = "Valid name, no data record of resquested type.";
611 msg = "Unknown error.";
619 static IPADDR *add_any(int family)
621 IPADDR *addr = New(IPADDR(family));
622 addr->set_type(IPADDR::R_MULTIPLE);
623 addr->set_addr_any();
627 static const char *resolv_host(int family, const char *host, dlist * addr_list)
633 #ifdef HAVE_GETHOSTBYNAME2
634 if ((hp = gethostbyname2(host, family)) == NULL) {
636 if ((hp = gethostbyname(host)) == NULL) {
638 /* may be the strerror give not the right result -:( */
639 errmsg = gethost_strerror();
644 for (p = hp->h_addr_list; *p != 0; p++) {
645 IPADDR *addr = New(IPADDR(hp->h_addrtype));
646 addr->set_type(IPADDR::R_MULTIPLE);
647 if (addr->get_family() == AF_INET) {
648 addr->set_addr4((struct in_addr*)*p);
652 addr->set_addr6((struct in6_addr*)*p);
655 addr_list->append(addr);
663 * i host = 0 mean INADDR_ANY only ipv4
665 dlist *bnet_host2ipaddrs(const char *host, int family, const char **errstr)
667 struct in_addr inaddr;
671 struct in6_addr inaddr6;
674 dlist *addr_list = New(dlist(addr, &addr->link));
675 if (!host || host[0] == '\0') {
677 addr_list->append(add_any(family));
679 addr_list->append(add_any(AF_INET));
681 addr_list->append(add_any(AF_INET6));
684 } else if (inet_aton(host, &inaddr)) { /* MA Bug 4 */
685 addr = New(IPADDR(AF_INET));
686 addr->set_type(IPADDR::R_MULTIPLE);
687 addr->set_addr4(&inaddr);
688 addr_list->append(addr);
691 if (inet_pton(AF_INET6, host, &inaddr6) > 1) {
692 addr = New(IPADDR(AF_INET6));
693 addr->set_type(IPADDR::R_MULTIPLE);
694 addr->set_addr6(&inaddr6);
695 addr_list->append(addr);
700 errmsg = resolv_host(family, host, addr_list);
703 free_addresses(addr_list);
707 errmsg = resolv_host(AF_INET, host, addr_list);
710 errmsg = resolv_host(AF_INET6, host, addr_list);
715 free_addresses(addr_list);
724 * Open a TCP connection to the UPS network server
726 * Returns BSOCK * pointer on success
729 static BSOCK *bnet_open(JCR * jcr, const char *name, char *host, char *service,
730 int port, int *fatal)
735 bool connected = false;
741 * Fill in the structure serv_addr with the address of
742 * the server that we want to connect with.
744 if ((addr_list = bnet_host2ipaddrs(host, 0, &errstr)) == NULL) {
745 /* Note errstr is not malloc'ed */
746 Qmsg2(jcr, M_ERROR, 0, "gethostbyname() for host \"%s\" failed: ERR=%s\n",
748 Dmsg2(100, "bnet_host2ipaddrs() for host %s failed: ERR=%s\n",
754 foreach_dlist(ipaddr, addr_list) {
755 ipaddr->set_port_net(htons(port));
756 char allbuf[256 * 10];
758 Dmsg2(100, "Current %sAll %s\n",
759 ipaddr->build_address_str(curbuf, sizeof(curbuf)),
760 build_addresses_str(addr_list, allbuf, sizeof(allbuf)));
761 /* Open a TCP socket */
762 if ((sockfd = socket(ipaddr->get_family(), SOCK_STREAM, 0)) < 0) {
766 Pmsg3(000, "Socket open error. proto=%d port=%d. ERR=%s\n",
767 ipaddr->get_family(), ipaddr->get_port_host_order(), be.strerror());
771 * Keep socket from timing out from inactivity
773 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
775 Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
778 /* connect to server */
779 if (connect(sockfd, ipaddr->get_sockaddr(), ipaddr->get_sockaddr_len()) < 0) {
790 free_addresses(addr_list);
795 * Keep socket from timing out from inactivity
796 * Do this a second time out of paranoia
798 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
800 Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
803 BSOCK* ret = init_bsock(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
804 free_addresses(addr_list);
809 * Try to connect to host for max_retry_time at retry_time intervals.
811 BSOCK *bnet_connect(JCR * jcr, int retry_interval, int max_retry_time,
812 const char *name, char *host, char *service, int port,
819 for (i = 0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL;
820 i -= retry_interval) {
822 if (fatal || (jcr && job_canceled(jcr))) {
825 Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
826 name, host, port, be.strerror());
828 i = 60 * 5; /* complain again in 5 minutes */
830 Qmsg4(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n"
831 "Retrying ...\n", name, host, port, be.strerror());
833 bmicrosleep(retry_interval, 0);
834 max_retry_time -= retry_interval;
835 if (max_retry_time <= 0) {
836 Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
837 name, host, port, be.strerror());
846 * Return the string for the error that occurred
847 * on the socket. Only the first error is retained.
849 const char *bnet_strerror(BSOCK * bsock)
852 if (bsock->errmsg == NULL) {
853 bsock->errmsg = get_pool_memory(PM_MESSAGE);
855 pm_strcpy(bsock->errmsg, be.strerror(bsock->b_errno));
856 return bsock->errmsg;
860 * Format and send a message
861 * Returns: false on error
864 bool bnet_fsend(BSOCK * bs, const char *fmt, ...)
869 if (bs->errors || bs->terminated) {
872 /* This probably won't work, but we vsnprintf, then if we
873 * get a negative length or a length greater than our buffer
874 * (depending on which library is used), the printf was truncated, so
875 * get a bigger buffer and try again.
878 maxlen = sizeof_pool_memory(bs->msg) - 1;
879 va_start(arg_ptr, fmt);
880 bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
882 if (bs->msglen > 0 && bs->msglen < (maxlen - 5)) {
885 bs->msg = realloc_pool_memory(bs->msg, maxlen + maxlen / 2);
887 return bnet_send(bs);
891 * Set the network buffer size, suggested size is in size.
892 * Actual size obtained is returned in bs->msglen
894 * Returns: 0 on failure
897 bool bnet_set_buffer_size(BSOCK * bs, uint32_t size, int rw)
899 uint32_t dbuf_size, start_size;
900 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
903 opt = IPTOS_THROUGHPUT;
904 setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t) & opt, sizeof(opt));
910 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
912 start_size = dbuf_size;
913 if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size + 100)) == NULL) {
914 Qmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
917 if (rw & BNET_SETBUF_READ) {
918 while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
919 SO_RCVBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
921 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
922 dbuf_size -= TAPE_BSIZE;
924 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
925 if (dbuf_size != start_size) {
926 Qmsg1(bs->jcr, M_WARNING, 0,
927 _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
929 if (dbuf_size % TAPE_BSIZE != 0) {
930 Qmsg1(bs->jcr, M_ABORT, 0,
931 _("Network buffer size %d not multiple of tape block size.\n"),
938 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
940 start_size = dbuf_size;
941 if (rw & BNET_SETBUF_WRITE) {
942 while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
943 SO_SNDBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
945 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
946 dbuf_size -= TAPE_BSIZE;
948 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
949 if (dbuf_size != start_size) {
950 Qmsg1(bs->jcr, M_WARNING, 0,
951 _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
953 if (dbuf_size % TAPE_BSIZE != 0) {
954 Qmsg1(bs->jcr, M_ABORT, 0,
955 _("Network buffer size %d not multiple of tape block size.\n"),
960 bs->msglen = dbuf_size;
965 * Set socket non-blocking
966 * Returns previous socket flag
968 int bnet_set_nonblocking (BSOCK *bsock) {
972 /* Get current flags */
973 if((oflags = fcntl(bsock->fd, F_GETFL, 0)) < 0) {
975 Emsg1(M_ABORT, 0, "fcntl F_GETFL error. ERR=%s\n", be.strerror());
978 /* Set O_NONBLOCK flag */
979 if((fcntl(bsock->fd, F_SETFL, oflags|O_NONBLOCK)) < 0) {
981 Emsg1(M_ABORT, 0, "fcntl F_SETFL error. ERR=%s\n", be.strerror());
990 flags = bsock->blocking;
991 ioctlsocket(bsock->fd, FIONBIO, &ioctlArg);
999 * Set socket blocking
1000 * Returns previous socket flags
1002 int bnet_set_blocking (BSOCK *bsock) {
1005 /* Get current flags */
1006 if((oflags = fcntl(bsock->fd, F_GETFL, 0)) < 0) {
1008 Emsg1(M_ABORT, 0, "fcntl F_GETFL error. ERR=%s\n", be.strerror());
1011 /* Set O_NONBLOCK flag */
1012 if((fcntl(bsock->fd, F_SETFL, oflags & ~O_NONBLOCK)) < 0) {
1014 Emsg1(M_ABORT, 0, "fcntl F_SETFL error. ERR=%s\n", be.strerror());
1017 bsock->blocking = 1;
1021 u_long ioctlArg = 0;
1023 flags = bsock->blocking;
1024 ioctlsocket(bsock->fd, FIONBIO, &ioctlArg);
1025 bsock->blocking = 1;
1032 * Restores socket flags
1034 void bnet_restore_blocking (BSOCK *bsock, int flags) {
1036 if((fcntl(bsock->fd, F_SETFL, flags)) < 0) {
1038 Emsg1(M_ABORT, 0, "fcntl F_SETFL error. ERR=%s\n", be.strerror());
1041 bsock->blocking = (flags & O_NONBLOCK);
1043 u_long ioctlArg = flags;
1045 ioctlsocket(bsock->fd, FIONBIO, &ioctlArg);
1046 bsock->blocking = 1;
1052 * Send a network "signal" to the other end
1053 * This consists of sending a negative packet length
1055 * Returns: false on failure
1058 bool bnet_sig(BSOCK * bs, int sig)
1061 if (sig == BNET_TERMINATE) {
1062 bs->suppress_error_msgs = true;
1064 return bnet_send(bs);
1068 * Convert a network "signal" code into
1069 * human readable ASCII.
1071 const char *bnet_sig_to_ascii(BSOCK * bs)
1073 static char buf[30];
1074 switch (bs->msglen) {
1076 return "BNET_EOD"; /* end of data stream */
1078 return "BNET_EOD_POLL";
1080 return "BNET_STATUS";
1081 case BNET_TERMINATE:
1082 return "BNET_TERMINATE"; /* terminate connection */
1085 case BNET_HEARTBEAT:
1086 return "BNET_HEARTBEAT";
1087 case BNET_HB_RESPONSE:
1088 return "BNET_HB_RESPONSE";
1090 return "BNET_PROMPT";
1092 sprintf(buf, "Unknown sig %d", (int)bs->msglen);
1098 /* Initialize internal socket structure.
1099 * This probably should be done in net_open
1101 BSOCK *init_bsock(JCR * jcr, int sockfd, const char *who, const char *host, int port,
1102 struct sockaddr *client_addr)
1104 Dmsg3(100, "who=%s host=%s port=%d\n", who, host, port);
1105 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
1106 memset(bsock, 0, sizeof(BSOCK));
1110 bsock->blocking = 1;
1111 bsock->msg = get_pool_memory(PM_MESSAGE);
1112 bsock->errmsg = get_pool_memory(PM_MESSAGE);
1113 bsock->who = bstrdup(who);
1114 bsock->host = bstrdup(host);
1116 memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
1118 * ****FIXME**** reduce this to a few hours once
1119 * heartbeats are implemented
1121 bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */
1126 BSOCK *dup_bsock(BSOCK * osock)
1128 BSOCK *bsock = (BSOCK *) malloc(sizeof(BSOCK));
1129 memcpy(bsock, osock, sizeof(BSOCK));
1130 bsock->msg = get_pool_memory(PM_MESSAGE);
1131 bsock->errmsg = get_pool_memory(PM_MESSAGE);
1133 bsock->who = bstrdup(osock->who);
1136 bsock->host = bstrdup(osock->host);
1138 bsock->duped = true;
1142 /* Close the network connection */
1143 void bnet_close(BSOCK * bsock)
1147 for (; bsock != NULL; bsock = next) {
1149 if (!bsock->duped) {
1151 /* Shutdown tls cleanly. */
1153 tls_bsock_shutdown(bsock);
1154 free_tls_connection(bsock->tls);
1157 #endif /* HAVE_TLS */
1158 if (bsock->timed_out) {
1159 shutdown(bsock->fd, 2); /* discard any pending I/O */
1161 socketClose(bsock->fd); /* normal close */
1168 void term_bsock(BSOCK * bsock)
1171 free_pool_memory(bsock->msg);
1174 ASSERT(1 == 0); /* double close */
1176 if (bsock->errmsg) {
1177 free_pool_memory(bsock->errmsg);
1178 bsock->errmsg = NULL;