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) {
97 Qmsg1(bsock->jcr, M_FATAL, 0, _("Attr spool write error. ERR=%s\n"), strerror(errno));
98 Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes);
107 nwritten = socketWrite(bsock->fd, ptr, nleft);
108 if (bsock->timed_out || bsock->terminated) {
111 } while (nwritten == -1 && errno == EINTR);
113 * If connection is non-blocking, we will get EAGAIN, so
114 * use select() to keep from consuming all the CPU
117 if (nwritten == -1 && errno == EAGAIN) {
122 FD_SET((unsigned)bsock->fd, &fdset);
125 select(bsock->fd + 1, NULL, &fdset, NULL, &tv);
129 return nwritten; /* error */
138 * Receive a message from the other end. Each message consists of
139 * two packets. The first is a header that contains the size
140 * of the data that follows in the second packet.
141 * Returns number of bytes read (may return zero)
142 * Returns -1 on signal (BNET_SIGNAL)
143 * Returns -2 on hard end of file (BNET_HARDEOF)
144 * Returns -3 on error (BNET_ERROR)
146 * Unfortunately, it is a bit complicated because we have these
149 * 2. Signal including end of data stream
150 * 3. Hard end of file
152 * Using is_bnet_stop() and is_bnet_error() you can figure this all out.
154 int32_t bnet_recv(BSOCK *bsock)
159 ASSERT(bsock != NULL);
160 mp_chr(bsock->msg)[0] = 0;
161 if (bsock->errors || bsock->terminated) {
165 bsock->read_seqno++; /* bump sequence number */
166 bsock->timer_start = watchdog_time; /* set start wait time */
167 bsock->timed_out = 0;
168 /* get data size -- in int32_t */
169 if ((nbytes = read_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
170 bsock->timer_start = 0; /* clear timer */
171 /* probably pipe broken because client died */
173 bsock->b_errno = ENODATA;
175 bsock->b_errno = errno;
178 return BNET_HARDEOF; /* assume hard EOF received */
180 bsock->timer_start = 0; /* clear timer */
181 if (nbytes != sizeof(int32_t)) {
183 bsock->b_errno = EIO;
184 Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
185 sizeof(int32_t), nbytes, bsock->who, bsock->host, bsock->port);
189 pktsiz = ntohl(pktsiz); /* decode no. of bytes that follow */
191 if (pktsiz == 0) { /* No data transferred */
192 bsock->timer_start = 0; /* clear timer */
195 return 0; /* zero bytes read */
198 /* If signal or packet size too big */
199 if (pktsiz < 0 || pktsiz > 1000000) {
200 if (pktsiz > 0) { /* if packet too big */
201 Qmsg3(bsock->jcr, M_FATAL, 0,
202 _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
203 bsock->who, bsock->host, bsock->port);
204 pktsiz = BNET_TERMINATE; /* hang up */
206 if (pktsiz == BNET_TERMINATE) {
207 bsock->terminated = 1;
209 bsock->timer_start = 0; /* clear timer */
210 bsock->b_errno = ENODATA;
211 bsock->msglen = pktsiz; /* signal code */
212 return BNET_SIGNAL; /* signal */
215 /* Make sure the buffer is big enough + one byte for EOS */
216 if (pktsiz >= (int32_t)sizeof_pool_memory(bsock->msg)) {
217 bsock->msg = realloc_pool_memory(bsock->msg, pktsiz + 100);
220 bsock->timer_start = watchdog_time; /* set start wait time */
221 bsock->timed_out = 0;
222 /* now read the actual data */
223 if ((nbytes = read_nbytes(bsock, mp_chr(bsock->msg), pktsiz)) <= 0) {
224 bsock->timer_start = 0; /* clear timer */
226 bsock->b_errno = ENODATA;
228 bsock->b_errno = errno;
231 Qmsg4(bsock->jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
232 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
235 bsock->timer_start = 0; /* clear timer */
237 bsock->msglen = nbytes;
238 if (nbytes != pktsiz) {
239 bsock->b_errno = EIO;
241 Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"), pktsiz, nbytes,
242 bsock->who, bsock->host, bsock->port);
245 /* always add a zero by to properly terminate any
246 * string that was send to us. Note, we ensured above that the
247 * buffer is at least one byte longer than the message length.
249 mp_chr(bsock->msg)[nbytes] = 0; /* terminate in case it is a string */
250 sm_check(__FILE__, __LINE__, false);
251 return nbytes; /* return actual length of message */
256 * Return 1 if there are errors on this bsock or it is closed,
257 * i.e. stop communicating on this line.
259 int is_bnet_stop(BSOCK *bsock)
261 return bsock->errors || bsock->terminated;
265 * Return number of errors on socket
267 int is_bnet_error(BSOCK *bsock)
269 return bsock->errors;
273 * Call here after error during closing to suppress error
274 * messages which are due to the other end shutting down too.
277 bnet_suppress_error_messages(BSOCK *bsock, bool flag)
279 bsock->suppress_error_msgs = flag;
284 * Transmit spooled data now to a BSOCK
286 int bnet_despool_to_bsock(BSOCK *bsock, void update_attr_spool_size(ssize_t size), ssize_t tsize)
290 ssize_t last = 0, size = 0;
293 rewind(bsock->spool_fd);
294 while (fread((char *)&pktsiz, 1, sizeof(int32_t), bsock->spool_fd) == sizeof(int32_t)) {
295 size += sizeof(int32_t);
296 bsock->msglen = ntohl(pktsiz);
297 if (bsock->msglen > 0) {
298 if (bsock->msglen > (int32_t)sizeof_pool_memory(bsock->msg)) {
299 bsock->msg = realloc_pool_memory(bsock->msg, bsock->msglen + 1);
301 nbytes = fread(bsock->msg, 1, bsock->msglen, bsock->spool_fd);
302 if (nbytes != (size_t)bsock->msglen) {
303 Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, bsock->msglen);
304 Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"), strerror(errno));
305 update_attr_spool_size(tsize-last);
309 if ((++count & 0x3F) == 0) {
310 update_attr_spool_size(size-last);
316 update_attr_spool_size(tsize-last);
317 if (ferror(bsock->spool_fd)) {
318 Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"), strerror(errno));
326 * Send a message over the network. The send consists of
327 * two network packets. The first is sends a 32 bit integer containing
328 * the length of the data packet which follows.
330 * Returns: 0 on failure
334 bnet_send(BSOCK *bsock)
340 if (bsock->errors || bsock->terminated || bsock->msglen > 1000000) {
343 msglen = bsock->msglen;
344 pktsiz = htonl((int32_t)bsock->msglen);
345 /* send int32_t containing size of data packet */
346 bsock->timer_start = watchdog_time; /* start timer */
347 bsock->timed_out = 0;
348 rc = write_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t));
349 bsock->timer_start = 0; /* clear timer */
350 if (rc != sizeof(int32_t)) {
351 if (bsock->msglen == BNET_TERMINATE) { /* if we were terminating */
352 bsock->terminated = 1;
353 return 0; /* ignore any errors */
357 bsock->b_errno = EIO;
359 bsock->b_errno = errno;
362 if (!bsock->suppress_error_msgs && !bsock->timed_out) {
363 Qmsg4(bsock->jcr, M_ERROR, 0, _("Write error sending to %s:%s:%d: ERR=%s\n"),
364 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
367 Qmsg5(bsock->jcr, M_ERROR, 0, _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
368 bsock->who, bsock->host, bsock->port, bsock->msglen, rc);
373 bsock->out_msg_no++; /* increment message number */
374 if (bsock->msglen <= 0) { /* length only? */
375 return 1; /* yes, no data */
378 /* send data packet */
379 bsock->timer_start = watchdog_time; /* start timer */
380 bsock->timed_out = 0;
381 rc = write_nbytes(bsock, mp_chr(bsock->msg), bsock->msglen);
382 bsock->timer_start = 0; /* clear timer */
383 if (rc != bsock->msglen) {
386 bsock->b_errno = EIO;
388 bsock->b_errno = errno;
391 if (!bsock->suppress_error_msgs) {
392 Qmsg4(bsock->jcr, M_ERROR, 0, _("Write error sending to %s:%s:%d: ERR=%s\n"),
393 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
396 Qmsg5(bsock->jcr, M_ERROR, 0, _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
397 bsock->msglen, bsock->who, bsock->host, bsock->port, rc);
405 * Establish an SSL connection -- server side
406 * Codes that ssl_need and ssl_has can take
407 * BNET_SSL_NONE I cannot do ssl
408 * BNET_SSL_OK I can do ssl, but it is not required on my end
409 * BNET_SSL_REQUIRED ssl is required on my end
412 bnet_ssl_server(BSOCK *bsock, char *password, int ssl_need, int ssl_has)
414 /* Check to see if what we need (ssl_need) corresponds to what he has (ssl_has) */
415 /* The other side expects a response from us */
420 * Establish an SSL connection -- client side
422 int bnet_ssl_client(BSOCK *bsock, char *password, int ssl_need)
424 /* We are the client so we must wait for the server to notify us */
430 * Wait for a specified time for data to appear on
431 * the BSOCK connection.
433 * Returns: 1 if data available
438 bnet_wait_data(BSOCK *bsock, int sec)
444 FD_SET((unsigned)bsock->fd, &fdset);
448 switch(select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
449 case 0: /* timeout */
453 bsock->b_errno = errno;
454 if (errno == EINTR || errno == EAGAIN) {
457 return -1; /* error return */
466 * As above, but returns on interrupt
469 bnet_wait_data_intr(BSOCK *bsock, int sec)
475 FD_SET((unsigned)bsock->fd, &fdset);
479 switch(select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
480 case 0: /* timeout */
484 bsock->b_errno = errno;
485 return -1; /* error return */
493 #ifndef NETDB_INTERNAL
494 #define NETDB_INTERNAL -1 /* See errno. */
496 #ifndef NETDB_SUCCESS
497 #define NETDB_SUCCESS 0 /* No problem. */
499 #ifndef HOST_NOT_FOUND
500 #define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found. */
503 #define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL. */
506 #define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP. */
509 #define NO_DATA 4 /* Valid name, no data record of requested type. */
513 * Get human readable error for gethostbyname()
515 static const char *gethost_strerror()
519 return strerror(errno);
521 return "No problem.";
523 return "Authoritative answer Host not found.";
525 return "Non-authoritative Host not found, or ServerFail.";
527 return "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.";
529 return "Valid name, no data record of resquested type.";
531 return "Unknown error.";
536 static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
539 * Convert a hostname or dotted IP address into
540 * a s_addr. We handle only IPv4.
542 static uint32_t *bget_host_ip(JCR *jcr, char *host)
544 struct in_addr inaddr;
545 uint32_t *addr_list; /* this really should be struct in_addr */
550 if ((inaddr.s_addr = inet_addr(host)) != INADDR_NONE) {
551 addr_list = (uint32_t *) malloc(sizeof(uint32_t) * 2);
552 addr_list[0] = inaddr.s_addr;
553 addr_list[1] = (uint32_t) -1;
556 if ((hp = gethostbyname(host)) == NULL) {
557 Qmsg2(jcr, M_ERROR, 0, "gethostbyname() for host \"%s\" failed: ERR=%s\n",
558 host, gethost_strerror());
562 if (hp->h_length != sizeof(inaddr.s_addr) || hp->h_addrtype != AF_INET) {
563 Qmsg2(jcr, M_ERROR, 0, _("gethostbyname() network address length error.\n\
564 Wanted %d got %d bytes for s_addr.\n"), sizeof(inaddr.s_addr), hp->h_length);
569 for (p = hp->h_addr_list; *p != 0; p++) {
573 addr_list = (uint32_t *)malloc(sizeof(uint32_t) * i);
575 for (p = hp->h_addr_list; *p != 0; p++) {
576 addr_list[i++] = (*(struct in_addr **)p)->s_addr;
578 addr_list[i] = (uint32_t) -1;
585 * Open a TCP connection to the UPS network server
587 * Returns BSOCK * pointer on success
589 * ***FIXME*** implement service from /etc/services
592 bnet_open(JCR *jcr, const char *name, char *host, char *service, int port, int *fatal)
595 struct sockaddr_in tcp_serv_addr; /* socket information */
597 int i, connected = 0;
601 * Fill in the structure serv_addr with the address of
602 * the server that we want to connect with.
604 memset((char *)&tcp_serv_addr, 0, sizeof(tcp_serv_addr));
605 tcp_serv_addr.sin_family = AF_INET;
606 tcp_serv_addr.sin_port = htons(port);
608 if ((addr_list=bget_host_ip(jcr, host)) == NULL) {
613 /* Open a TCP socket */
614 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
621 * Receive notification when connection dies.
623 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
624 Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"), strerror(errno));
627 for (i = 0; addr_list[i] != ((uint32_t) -1); i++) {
628 /* connect to server */
629 tcp_serv_addr.sin_addr.s_addr = addr_list[i];
630 if (connect(sockfd, (struct sockaddr *)&tcp_serv_addr, sizeof(tcp_serv_addr)) < 0) {
642 return init_bsock(jcr, sockfd, name, host, port, &tcp_serv_addr);
646 * Try to connect to host for max_retry_time at retry_time intervals.
649 bnet_connect(JCR *jcr, int retry_interval, int max_retry_time, const char *name,
650 char *host, char *service, int port, int verbose)
656 for (i=0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL; i -= retry_interval) {
657 if (fatal || (jcr && job_canceled(jcr))) {
660 Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
661 name, host, port, strerror(errno));
663 i = 60 * 5; /* complain again in 5 minutes */
665 Qmsg4(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
666 Retrying ...\n", name, host, port, strerror(errno));
668 bmicrosleep(retry_interval, 0);
669 max_retry_time -= retry_interval;
670 if (max_retry_time <= 0) {
671 Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
672 name, host, port, strerror(errno));
681 * Return the string for the error that occurred
682 * on the socket. Only the first error is retained.
684 char *bnet_strerror(BSOCK *bsock)
686 return strerror(bsock->b_errno);
690 * Format and send a message
691 * Returns: 0 on failure
695 bnet_fsend(BSOCK *bs, const char *fmt, ...)
700 if (bs->errors || bs->terminated) {
703 /* This probably won't work, but we vsnprintf, then if we
704 * get a negative length or a length greater than our buffer
705 * (depending on which library is used), the printf was truncated, so
706 * get a biger buffer and try again.
709 maxlen = sizeof_pool_memory(bs->msg) - 1;
710 va_start(arg_ptr, fmt);
711 bs->msglen = bvsnprintf(mp_chr(bs->msg), maxlen, fmt, arg_ptr);
713 if (bs->msglen < 0 || bs->msglen >= maxlen) {
714 bs->msg = realloc_pool_memory(bs->msg, maxlen + maxlen / 2);
717 return bnet_send(bs);
721 * Set the network buffer size, suggested size is in size.
722 * Actual size obtained is returned in bs->msglen
724 * Returns: 0 on failure
727 int bnet_set_buffer_size(BSOCK *bs, uint32_t size, int rw)
729 uint32_t dbuf_size, start_size;
730 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
733 opt = IPTOS_THROUGHPUT;
734 setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t)&opt, sizeof(opt));
740 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
742 start_size = dbuf_size;
743 if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size+100)) == NULL) {
744 Qmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
747 if (rw & BNET_SETBUF_READ) {
748 while ((dbuf_size > TAPE_BSIZE) &&
749 (setsockopt(bs->fd, SOL_SOCKET, SO_RCVBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
750 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
751 dbuf_size -= TAPE_BSIZE;
753 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
754 if (dbuf_size != start_size) {
755 Qmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
757 if (dbuf_size % TAPE_BSIZE != 0) {
758 Qmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
765 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
767 start_size = dbuf_size;
768 if (rw & BNET_SETBUF_WRITE) {
769 while ((dbuf_size > TAPE_BSIZE) &&
770 (setsockopt(bs->fd, SOL_SOCKET, SO_SNDBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
771 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
772 dbuf_size -= TAPE_BSIZE;
774 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
775 if (dbuf_size != start_size) {
776 Qmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
778 if (dbuf_size % TAPE_BSIZE != 0) {
779 Qmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
784 bs->msglen = dbuf_size;
789 * Send a network "signal" to the other end
790 * This consists of sending a negative packet length
792 * Returns: 0 on failure
795 int bnet_sig(BSOCK *bs, int sig)
798 return bnet_send(bs);
802 * Convert a network "signal" code into
803 * human readable ASCII.
805 const char *bnet_sig_to_ascii(BSOCK *bs)
808 switch (bs->msglen) {
810 return "BNET_EOD"; /* end of data stream */
812 return "BNET_EOD_POLL";
814 return "BNET_STATUS";
816 return "BNET_TERMINATE"; /* terminate connection */
820 return "BNET_HEARTBEAT";
821 case BNET_HB_RESPONSE:
822 return "BNET_HB_RESPONSE";
824 return "BNET_PROMPT";
826 sprintf(buf, "Unknown sig %d", bs->msglen);
832 /* Initialize internal socket structure.
833 * This probably should be done in net_open
836 init_bsock(JCR *jcr, int sockfd, const char *who, const char *host, int port,
837 struct sockaddr_in *client_addr)
839 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
840 memset(bsock, 0, sizeof(BSOCK));
843 bsock->msg = get_pool_memory(PM_MESSAGE);
844 bsock->errmsg = get_pool_memory(PM_MESSAGE);
845 bsock->who = bstrdup(who);
846 bsock->host = bstrdup(host);
848 memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
850 * ****FIXME**** reduce this to a few hours once
851 * heartbeats are implemented
853 bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */
859 dup_bsock(BSOCK *osock)
861 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
862 memcpy(bsock, osock, sizeof(BSOCK));
863 bsock->msg = get_pool_memory(PM_MESSAGE);
864 bsock->errmsg = get_pool_memory(PM_MESSAGE);
866 bsock->who = bstrdup(osock->who);
869 bsock->host = bstrdup(osock->host);
875 /* Close the network connection */
877 bnet_close(BSOCK *bsock)
881 for ( ; bsock != NULL; bsock = next) {
884 if (bsock->timed_out) {
885 shutdown(bsock->fd, 2); /* discard any pending I/O */
887 socketClose(bsock->fd); /* normal close */
895 term_bsock(BSOCK *bsock)
898 free_pool_memory(bsock->msg);
901 ASSERT(1==0); /* double close */
904 free_pool_memory(bsock->errmsg);
905 bsock->errmsg = NULL;