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 amended 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));
73 nread = socketRead(bsock->fd, ptr, nleft);
74 if (bsock->timed_out || bsock->terminated) {
81 if (errno == EAGAIN) {
82 bmicrosleep(0, 200000); /* try again in 200ms */
87 return nread; /* error, or EOF */
92 return nbytes - nleft; /* return >= 0 */
96 * Write nbytes to the network.
97 * It may require several writes.
100 static int32_t write_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes)
102 int32_t nleft, nwritten;
105 nwritten = fwrite(ptr, 1, nbytes, bsock->spool_fd);
106 if (nwritten != nbytes) {
108 bsock->b_errno = errno;
109 Qmsg1(bsock->jcr, M_FATAL, 0, _("Attr spool write error. ERR=%s\n"),
111 Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes);
112 errno = bsock->b_errno;
121 return (tls_bsock_writen(bsock, ptr, nbytes));
123 #endif /* HAVE_TLS */
129 nwritten = socketWrite(bsock->fd, ptr, nleft);
130 if (bsock->timed_out || bsock->terminated) {
133 } while (nwritten == -1 && errno == EINTR);
135 * If connection is non-blocking, we will get EAGAIN, so
136 * use select() to keep from consuming all the CPU
139 if (nwritten == -1 && errno == EAGAIN) {
144 FD_SET((unsigned)bsock->fd, &fdset);
147 select(bsock->fd + 1, NULL, &fdset, NULL, &tv);
151 return nwritten; /* error */
156 return nbytes - nleft;
160 * Receive a message from the other end. Each message consists of
161 * two packets. The first is a header that contains the size
162 * of the data that follows in the second packet.
163 * Returns number of bytes read (may return zero)
164 * Returns -1 on signal (BNET_SIGNAL)
165 * Returns -2 on hard end of file (BNET_HARDEOF)
166 * Returns -3 on error (BNET_ERROR)
168 * Unfortunately, it is a bit complicated because we have these
171 * 2. Signal including end of data stream
172 * 3. Hard end of file
174 * Using is_bnet_stop() and is_bnet_error() you can figure this all out.
176 int32_t bnet_recv(BSOCK * bsock)
186 if (bsock->errors || bsock->terminated) {
190 bsock->read_seqno++; /* bump sequence number */
191 bsock->timer_start = watchdog_time; /* set start wait time */
192 bsock->timed_out = 0;
193 /* get data size -- in int32_t */
194 if ((nbytes = read_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
195 bsock->timer_start = 0; /* clear timer */
196 /* probably pipe broken because client died */
198 bsock->b_errno = ENODATA;
200 bsock->b_errno = errno;
203 return BNET_HARDEOF; /* assume hard EOF received */
205 bsock->timer_start = 0; /* clear timer */
206 if (nbytes != sizeof(int32_t)) {
208 bsock->b_errno = EIO;
209 Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
210 sizeof(int32_t), nbytes, bsock->who, bsock->host, bsock->port);
214 pktsiz = ntohl(pktsiz); /* decode no. of bytes that follow */
216 if (pktsiz == 0) { /* No data transferred */
217 bsock->timer_start = 0; /* clear timer */
220 return 0; /* zero bytes read */
223 /* If signal or packet size too big */
224 if (pktsiz < 0 || pktsiz > 1000000) {
225 if (pktsiz > 0) { /* if packet too big */
226 Qmsg3(bsock->jcr, M_FATAL, 0,
227 _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
228 bsock->who, bsock->host, bsock->port);
229 pktsiz = BNET_TERMINATE; /* hang up */
231 if (pktsiz == BNET_TERMINATE) {
232 bsock->terminated = 1;
234 bsock->timer_start = 0; /* clear timer */
235 bsock->b_errno = ENODATA;
236 bsock->msglen = pktsiz; /* signal code */
237 return BNET_SIGNAL; /* signal */
240 /* Make sure the buffer is big enough + one byte for EOS */
241 if (pktsiz >= (int32_t) sizeof_pool_memory(bsock->msg)) {
242 bsock->msg = realloc_pool_memory(bsock->msg, pktsiz + 100);
245 bsock->timer_start = watchdog_time; /* set start wait time */
246 bsock->timed_out = 0;
247 /* now read the actual data */
248 if ((nbytes = read_nbytes(bsock, bsock->msg, pktsiz)) <= 0) {
249 bsock->timer_start = 0; /* clear timer */
251 bsock->b_errno = ENODATA;
253 bsock->b_errno = errno;
256 Qmsg4(bsock->jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
257 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
260 bsock->timer_start = 0; /* clear timer */
262 bsock->msglen = nbytes;
263 if (nbytes != pktsiz) {
264 bsock->b_errno = EIO;
266 Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
267 pktsiz, nbytes, bsock->who, bsock->host, bsock->port);
270 /* always add a zero by to properly terminate any
271 * string that was send to us. Note, we ensured above that the
272 * buffer is at least one byte longer than the message length.
274 bsock->msg[nbytes] = 0; /* terminate in case it is a string */
275 sm_check(__FILE__, __LINE__, false);
276 return nbytes; /* return actual length of message */
281 * Return 1 if there are errors on this bsock or it is closed,
282 * i.e. stop communicating on this line.
284 bool is_bnet_stop(BSOCK * bsock)
286 return bsock->errors || bsock->terminated;
290 * Return number of errors on socket
292 int is_bnet_error(BSOCK * bsock)
294 errno = bsock->b_errno;
295 return bsock->errors;
299 * Call here after error during closing to suppress error
300 * messages which are due to the other end shutting down too.
302 void bnet_suppress_error_messages(BSOCK * bsock, bool flag)
304 bsock->suppress_error_msgs = flag;
309 * Transmit spooled data now to a BSOCK
311 int bnet_despool_to_bsock(BSOCK * bsock, void update_attr_spool_size(ssize_t size),
316 ssize_t last = 0, size = 0;
319 rewind(bsock->spool_fd);
320 while (fread((char *)&pktsiz, 1, sizeof(int32_t), bsock->spool_fd) ==
322 size += sizeof(int32_t);
323 bsock->msglen = ntohl(pktsiz);
324 if (bsock->msglen > 0) {
325 if (bsock->msglen > (int32_t) sizeof_pool_memory(bsock->msg)) {
326 bsock->msg = realloc_pool_memory(bsock->msg, bsock->msglen + 1);
328 nbytes = fread(bsock->msg, 1, bsock->msglen, bsock->spool_fd);
329 if (nbytes != (size_t) bsock->msglen) {
331 Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, bsock->msglen);
332 Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
334 update_attr_spool_size(tsize - last);
338 if ((++count & 0x3F) == 0) {
339 update_attr_spool_size(size - last);
345 update_attr_spool_size(tsize - last);
346 if (ferror(bsock->spool_fd)) {
348 Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
357 * Send a message over the network. The send consists of
358 * two network packets. The first is sends a 32 bit integer containing
359 * the length of the data packet which follows.
361 * Returns: false on failure
364 bool bnet_send(BSOCK * bsock)
369 if (bsock->errors || bsock->terminated || bsock->msglen > 1000000) {
372 pktsiz = htonl((int32_t) bsock->msglen);
373 /* send int32_t containing size of data packet */
374 bsock->timer_start = watchdog_time; /* start timer */
375 bsock->timed_out = 0;
376 rc = write_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t));
377 bsock->timer_start = 0; /* clear timer */
378 if (rc != sizeof(int32_t)) {
379 if (bsock->msglen == BNET_TERMINATE) { /* if we were terminating */
380 bsock->terminated = 1;
381 return false; /* ignore any errors */
385 bsock->b_errno = EIO;
387 bsock->b_errno = errno;
390 if (!bsock->suppress_error_msgs && !bsock->timed_out) {
391 Qmsg4(bsock->jcr, M_ERROR, 0,
392 _("Write error sending len to %s:%s:%d: ERR=%s\n"), bsock->who,
393 bsock->host, bsock->port, bnet_strerror(bsock));
396 Qmsg5(bsock->jcr, M_ERROR, 0,
397 _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
398 sizeof(int32_t), bsock->who,
399 bsock->host, bsock->port, rc);
404 bsock->out_msg_no++; /* increment message number */
405 if (bsock->msglen <= 0) { /* length only? */
406 return true; /* yes, no data */
409 /* send data packet */
410 bsock->timer_start = watchdog_time; /* start timer */
411 bsock->timed_out = 0;
412 rc = write_nbytes(bsock, bsock->msg, bsock->msglen);
413 bsock->timer_start = 0; /* clear timer */
414 if (rc != bsock->msglen) {
417 bsock->b_errno = EIO;
419 bsock->b_errno = errno;
422 if (!bsock->suppress_error_msgs) {
423 Qmsg5(bsock->jcr, M_ERROR, 0,
424 _("Write error sending %d bytes to %s:%s:%d: ERR=%s\n"),
425 bsock->msglen, bsock->who,
426 bsock->host, bsock->port, bnet_strerror(bsock));
429 Qmsg5(bsock->jcr, M_ERROR, 0,
430 _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
431 bsock->msglen, bsock->who, bsock->host, bsock->port, rc);
439 * Establish a TLS connection -- server side
440 * Returns: true on success
444 bool bnet_tls_server(TLS_CONTEXT *ctx, BSOCK * bsock, alist *verify_list)
448 tls = new_tls_connection(ctx, bsock->fd);
450 Qmsg0(bsock->jcr, M_FATAL, 0, _("TLS connection initialization failed.\n"));
456 /* Initiate TLS Negotiation */
457 if (!tls_bsock_accept(bsock)) {
458 Qmsg0(bsock->jcr, M_FATAL, 0, _("TLS Negotiation failed.\n"));
463 if (!tls_postconnect_verify_cn(tls, verify_list)) {
464 Qmsg1(bsock->jcr, M_FATAL, 0, _("TLS certificate verification failed."
465 " Peer certificate did not match a required commonName\n"),
473 free_tls_connection(tls);
479 * Establish a TLS connection -- client side
480 * Returns: true on success
483 bool bnet_tls_client(TLS_CONTEXT *ctx, BSOCK * bsock)
487 tls = new_tls_connection(ctx, bsock->fd);
489 Qmsg0(bsock->jcr, M_FATAL, 0, _("TLS connection initialization failed.\n"));
495 /* Initiate TLS Negotiation */
496 if (!tls_bsock_connect(bsock)) {
500 if (!tls_postconnect_verify_host(tls, bsock->host)) {
501 Qmsg1(bsock->jcr, M_FATAL, 0, _("TLS host certificate verification failed. Host %s did not match presented certificate\n"), bsock->host);
507 free_tls_connection(tls);
512 bool bnet_tls_server(TLS_CONTEXT *ctx, BSOCK * bsock, alist *verify_list)
514 Jmsg(bsock->jcr, M_ABORT, 0, _("TLS enabled but not configured.\n"));
517 bool bnet_tls_client(TLS_CONTEXT *ctx, BSOCK * bsock)
519 Jmsg(bsock->jcr, M_ABORT, 0, _("TLS enable but not configured.\n"));
522 #endif /* HAVE_TLS */
525 * Wait for a specified time for data to appear on
526 * the BSOCK connection.
528 * Returns: 1 if data available
532 int bnet_wait_data(BSOCK * bsock, int sec)
538 FD_SET((unsigned)bsock->fd, &fdset);
542 switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
543 case 0: /* timeout */
547 bsock->b_errno = errno;
548 if (errno == EINTR) {
551 return -1; /* error return */
560 * As above, but returns on interrupt
562 int bnet_wait_data_intr(BSOCK * bsock, int sec)
568 FD_SET((unsigned)bsock->fd, &fdset);
571 switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
572 case 0: /* timeout */
576 bsock->b_errno = errno;
577 return -1; /* error return */
584 #ifndef NETDB_INTERNAL
585 #define NETDB_INTERNAL -1 /* See errno. */
587 #ifndef NETDB_SUCCESS
588 #define NETDB_SUCCESS 0 /* No problem. */
590 #ifndef HOST_NOT_FOUND
591 #define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found. */
594 #define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL. */
597 #define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP. */
600 #define NO_DATA 4 /* Valid name, no data record of requested type. */
604 * Get human readable error for gethostbyname()
606 static const char *gethost_strerror()
615 msg = _("No problem.");
618 msg = _("Authoritative answer for host not found.");
621 msg = _("Non-authoritative for host not found, or ServerFail.");
624 msg = _("Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.");
627 msg = _("Valid name, no data record of resquested type.");
630 msg = _("Unknown error.");
638 static IPADDR *add_any(int family)
640 IPADDR *addr = New(IPADDR(family));
641 addr->set_type(IPADDR::R_MULTIPLE);
642 addr->set_addr_any();
646 static const char *resolv_host(int family, const char *host, dlist * addr_list)
652 #ifdef HAVE_GETHOSTBYNAME2
653 if ((hp = gethostbyname2(host, family)) == NULL) {
655 if ((hp = gethostbyname(host)) == NULL) {
657 /* may be the strerror give not the right result -:( */
658 errmsg = gethost_strerror();
663 for (p = hp->h_addr_list; *p != 0; p++) {
664 IPADDR *addr = New(IPADDR(hp->h_addrtype));
665 addr->set_type(IPADDR::R_MULTIPLE);
666 if (addr->get_family() == AF_INET) {
667 addr->set_addr4((struct in_addr*)*p);
671 addr->set_addr6((struct in6_addr*)*p);
674 addr_list->append(addr);
682 * i host = 0 mean INADDR_ANY only ipv4
684 dlist *bnet_host2ipaddrs(const char *host, int family, const char **errstr)
686 struct in_addr inaddr;
690 struct in6_addr inaddr6;
693 dlist *addr_list = New(dlist(addr, &addr->link));
694 if (!host || host[0] == '\0') {
696 addr_list->append(add_any(family));
698 addr_list->append(add_any(AF_INET));
700 addr_list->append(add_any(AF_INET6));
703 } else if (inet_aton(host, &inaddr)) { /* MA Bug 4 */
704 addr = New(IPADDR(AF_INET));
705 addr->set_type(IPADDR::R_MULTIPLE);
706 addr->set_addr4(&inaddr);
707 addr_list->append(addr);
710 if (inet_pton(AF_INET6, host, &inaddr6) > 1) {
711 addr = New(IPADDR(AF_INET6));
712 addr->set_type(IPADDR::R_MULTIPLE);
713 addr->set_addr6(&inaddr6);
714 addr_list->append(addr);
719 errmsg = resolv_host(family, host, addr_list);
722 free_addresses(addr_list);
726 errmsg = resolv_host(AF_INET, host, addr_list);
729 errmsg = resolv_host(AF_INET6, host, addr_list);
734 free_addresses(addr_list);
743 * Open a TCP connection to the UPS network server
745 * Returns BSOCK * pointer on success
748 static BSOCK *bnet_open(JCR * jcr, const char *name, char *host, char *service,
749 int port, int *fatal)
754 bool connected = false;
760 * Fill in the structure serv_addr with the address of
761 * the server that we want to connect with.
763 if ((addr_list = bnet_host2ipaddrs(host, 0, &errstr)) == NULL) {
764 /* Note errstr is not malloc'ed */
765 Qmsg2(jcr, M_ERROR, 0, _("gethostbyname() for host \"%s\" failed: ERR=%s\n"),
767 Dmsg2(100, "bnet_host2ipaddrs() for host %s failed: ERR=%s\n",
773 foreach_dlist(ipaddr, addr_list) {
774 ipaddr->set_port_net(htons(port));
775 char allbuf[256 * 10];
777 Dmsg2(100, "Current %sAll %s\n",
778 ipaddr->build_address_str(curbuf, sizeof(curbuf)),
779 build_addresses_str(addr_list, allbuf, sizeof(allbuf)));
780 /* Open a TCP socket */
781 if ((sockfd = socket(ipaddr->get_family(), SOCK_STREAM, 0)) < 0) {
785 Pmsg3(000, _("Socket open error. proto=%d port=%d. ERR=%s\n"),
786 ipaddr->get_family(), ipaddr->get_port_host_order(), be.strerror());
790 * Keep socket from timing out from inactivity
792 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
794 Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
797 /* connect to server */
798 if (connect(sockfd, ipaddr->get_sockaddr(), ipaddr->get_sockaddr_len()) < 0) {
809 free_addresses(addr_list);
814 * Keep socket from timing out from inactivity
815 * Do this a second time out of paranoia
817 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
819 Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
822 BSOCK* ret = init_bsock(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
823 free_addresses(addr_list);
828 * Try to connect to host for max_retry_time at retry_time intervals.
830 BSOCK *bnet_connect(JCR * jcr, int retry_interval, int max_retry_time,
831 const char *name, char *host, char *service, int port,
838 for (i = 0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL;
839 i -= retry_interval) {
841 if (fatal || (jcr && job_canceled(jcr))) {
844 Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
845 name, host, port, be.strerror());
847 i = 60 * 5; /* complain again in 5 minutes */
849 Qmsg4(jcr, M_WARNING, 0, _(
850 "Could not connect to %s on %s:%d. ERR=%s\n"
851 "Retrying ...\n"), name, host, port, be.strerror());
853 bmicrosleep(retry_interval, 0);
854 max_retry_time -= retry_interval;
855 if (max_retry_time <= 0) {
856 Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
857 name, host, port, be.strerror());
866 * Return the string for the error that occurred
867 * on the socket. Only the first error is retained.
869 const char *bnet_strerror(BSOCK * bsock)
872 if (bsock->errmsg == NULL) {
873 bsock->errmsg = get_pool_memory(PM_MESSAGE);
875 pm_strcpy(bsock->errmsg, be.strerror(bsock->b_errno));
876 return bsock->errmsg;
880 * Format and send a message
881 * Returns: false on error
884 bool bnet_fsend(BSOCK * bs, const char *fmt, ...)
889 if (bs->errors || bs->terminated) {
892 /* This probably won't work, but we vsnprintf, then if we
893 * get a negative length or a length greater than our buffer
894 * (depending on which library is used), the printf was truncated, so
895 * get a bigger buffer and try again.
898 maxlen = sizeof_pool_memory(bs->msg) - 1;
899 va_start(arg_ptr, fmt);
900 bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
902 if (bs->msglen > 0 && bs->msglen < (maxlen - 5)) {
905 bs->msg = realloc_pool_memory(bs->msg, maxlen + maxlen / 2);
907 return bnet_send(bs);
910 int bnet_get_peer(BSOCK *bs, char *buf, socklen_t buflen) {
911 #if !defined(HAVE_WIN32)
912 if (bs->peer_addr.sin_family == 0) {
913 socklen_t salen = sizeof(bs->peer_addr);
914 int rval = (getpeername)(bs->fd, (struct sockaddr *)&bs->peer_addr, &salen);
915 if (rval < 0) return rval;
917 if (!inet_ntop(bs->peer_addr.sin_family, &bs->peer_addr.sin_addr, buf, buflen))
926 * Set the network buffer size, suggested size is in size.
927 * Actual size obtained is returned in bs->msglen
929 * Returns: 0 on failure
932 bool bnet_set_buffer_size(BSOCK * bs, uint32_t size, int rw)
934 uint32_t dbuf_size, start_size;
935 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
938 opt = IPTOS_THROUGHPUT;
939 setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t) & opt, sizeof(opt));
945 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
947 start_size = dbuf_size;
948 if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size + 100)) == NULL) {
949 Qmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
952 if (rw & BNET_SETBUF_READ) {
953 while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
954 SO_RCVBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
956 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
957 dbuf_size -= TAPE_BSIZE;
959 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
960 if (dbuf_size != start_size) {
961 Qmsg1(bs->jcr, M_WARNING, 0,
962 _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
964 if (dbuf_size % TAPE_BSIZE != 0) {
965 Qmsg1(bs->jcr, M_ABORT, 0,
966 _("Network buffer size %d not multiple of tape block size.\n"),
973 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
975 start_size = dbuf_size;
976 if (rw & BNET_SETBUF_WRITE) {
977 while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
978 SO_SNDBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
980 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
981 dbuf_size -= TAPE_BSIZE;
983 Dmsg1(900, "set network buffer size=%d\n", dbuf_size);
984 if (dbuf_size != start_size) {
985 Qmsg1(bs->jcr, M_WARNING, 0,
986 _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
988 if (dbuf_size % TAPE_BSIZE != 0) {
989 Qmsg1(bs->jcr, M_ABORT, 0,
990 _("Network buffer size %d not multiple of tape block size.\n"),
995 bs->msglen = dbuf_size;
1000 * Set socket non-blocking
1001 * Returns previous socket flag
1003 int bnet_set_nonblocking (BSOCK *bsock) {
1007 /* Get current flags */
1008 if ((oflags = fcntl(bsock->fd, F_GETFL, 0)) < 0) {
1010 Jmsg1(bsock->jcr, M_ABORT, 0, _("fcntl F_GETFL error. ERR=%s\n"), be.strerror());
1013 /* Set O_NONBLOCK flag */
1014 if ((fcntl(bsock->fd, F_SETFL, oflags|O_NONBLOCK)) < 0) {
1016 Jmsg1(bsock->jcr, M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.strerror());
1019 bsock->blocking = 0;
1023 u_long ioctlArg = 1;
1025 flags = bsock->blocking;
1026 ioctlsocket(bsock->fd, FIONBIO, &ioctlArg);
1027 bsock->blocking = 0;
1034 * Set socket blocking
1035 * Returns previous socket flags
1037 int bnet_set_blocking (BSOCK *bsock)
1041 /* Get current flags */
1042 if ((oflags = fcntl(bsock->fd, F_GETFL, 0)) < 0) {
1044 Jmsg1(bsock->jcr, M_ABORT, 0, _("fcntl F_GETFL error. ERR=%s\n"), be.strerror());
1047 /* Set O_NONBLOCK flag */
1048 if ((fcntl(bsock->fd, F_SETFL, oflags & ~O_NONBLOCK)) < 0) {
1050 Jmsg1(bsock->jcr, M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.strerror());
1053 bsock->blocking = 1;
1057 u_long ioctlArg = 0;
1059 flags = bsock->blocking;
1060 ioctlsocket(bsock->fd, FIONBIO, &ioctlArg);
1061 bsock->blocking = 1;
1068 * Restores socket flags
1070 void bnet_restore_blocking (BSOCK *bsock, int flags)
1073 if ((fcntl(bsock->fd, F_SETFL, flags)) < 0) {
1075 Jmsg1(bsock->jcr, M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.strerror());
1078 bsock->blocking = (flags & O_NONBLOCK);
1080 u_long ioctlArg = flags;
1082 ioctlsocket(bsock->fd, FIONBIO, &ioctlArg);
1083 bsock->blocking = 1;
1089 * Send a network "signal" to the other end
1090 * This consists of sending a negative packet length
1092 * Returns: false on failure
1095 bool bnet_sig(BSOCK * bs, int sig)
1098 if (sig == BNET_TERMINATE) {
1099 bs->suppress_error_msgs = true;
1101 return bnet_send(bs);
1105 * Convert a network "signal" code into
1106 * human readable ASCII.
1108 const char *bnet_sig_to_ascii(BSOCK * bs)
1110 static char buf[30];
1111 switch (bs->msglen) {
1113 return "BNET_EOD"; /* end of data stream */
1115 return "BNET_EOD_POLL";
1117 return "BNET_STATUS";
1118 case BNET_TERMINATE:
1119 return "BNET_TERMINATE"; /* terminate connection */
1122 case BNET_HEARTBEAT:
1123 return "BNET_HEARTBEAT";
1124 case BNET_HB_RESPONSE:
1125 return "BNET_HB_RESPONSE";
1127 return "BNET_PROMPT";
1129 sprintf(buf, _("Unknown sig %d"), (int)bs->msglen);
1135 /* Initialize internal socket structure.
1136 * This probably should be done in net_open
1138 BSOCK *init_bsock(JCR * jcr, int sockfd, const char *who, const char *host, int port,
1139 struct sockaddr *client_addr)
1141 Dmsg3(100, "who=%s host=%s port=%d\n", who, host, port);
1142 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
1143 memset(bsock, 0, sizeof(BSOCK));
1147 bsock->blocking = 1;
1148 bsock->msg = get_pool_memory(PM_MESSAGE);
1149 bsock->errmsg = get_pool_memory(PM_MESSAGE);
1150 bsock->who = bstrdup(who);
1151 bsock->host = bstrdup(host);
1153 memset(&bsock->peer_addr, 0, sizeof(bsock->peer_addr));
1154 memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
1156 * ****FIXME**** reduce this to a few hours once
1157 * heartbeats are implemented
1159 bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */
1164 BSOCK *dup_bsock(BSOCK * osock)
1166 BSOCK *bsock = (BSOCK *) malloc(sizeof(BSOCK));
1167 memcpy(bsock, osock, sizeof(BSOCK));
1168 bsock->msg = get_pool_memory(PM_MESSAGE);
1169 bsock->errmsg = get_pool_memory(PM_MESSAGE);
1171 bsock->who = bstrdup(osock->who);
1174 bsock->host = bstrdup(osock->host);
1176 bsock->duped = true;
1180 /* Close the network connection */
1181 void bnet_close(BSOCK * bsock)
1185 for (; bsock != NULL; bsock = next) {
1187 if (!bsock->duped) {
1189 /* Shutdown tls cleanly. */
1191 tls_bsock_shutdown(bsock);
1192 free_tls_connection(bsock->tls);
1195 #endif /* HAVE_TLS */
1196 if (bsock->timed_out) {
1197 shutdown(bsock->fd, 2); /* discard any pending I/O */
1199 socketClose(bsock->fd); /* normal close */
1206 void term_bsock(BSOCK * bsock)
1209 free_pool_memory(bsock->msg);
1212 ASSERT(1 == 0); /* double close */
1214 if (bsock->errmsg) {
1215 free_pool_memory(bsock->errmsg);
1216 bsock->errmsg = NULL;