2 * Network Utility Routines
6 * Adapted and enhanced for Bacula, originally written
7 * for inclusion in the Apcupsd package
12 Copyright (C) 2000, 2001, 2002 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,
35 extern time_t watchdog_time;
38 #define INADDR_NONE -1
41 #ifndef ENODATA /* not defined on BSD systems */
49 * Read a nbytes from the network.
50 * It is possible that the total bytes require in several
54 static int32_t read_nbytes(BSOCK *bsock, char *ptr, int32_t nbytes)
62 nread = read(bsock->fd, ptr, nleft);
63 if (bsock->timed_out || bsock->terminated) {
64 Dmsg1(000, "timed_out = %d\n", bsock->timed_out);
67 } while (nread == -1 && (errno == EINTR || errno == EAGAIN));
69 return nread; /* error, or EOF */
74 return nbytes - nleft; /* return >= 0 */
78 * Write nbytes to the network.
79 * It may require several writes.
82 static int32_t write_nbytes(BSOCK *bsock, char *ptr, int32_t nbytes)
84 int32_t nleft, nwritten;
87 nwritten = fwrite(ptr, 1, nbytes, bsock->spool_fd);
88 if (nwritten != nbytes) {
89 Jmsg1(bsock->jcr, M_ERROR, 0, _("Spool write error. ERR=%s\n"), strerror(errno));
90 Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes);
99 nwritten = write(bsock->fd, ptr, nleft);
100 if (bsock->timed_out || bsock->terminated) {
103 } while (nwritten == -1 && errno == EINTR);
105 * If connection is non-blocking, we will get EAGAIN, so
106 * use select() to keep from consuming all the CPU
109 if (nwritten == -1 && errno == EAGAIN) {
114 FD_SET(bsock->fd, &fdset);
117 select(bsock->fd + 1, NULL, &fdset, NULL, &tv);
121 return nwritten; /* error */
130 * Receive a message from the other end. Each message consists of
131 * two packets. The first is a header that contains the size
132 * of the data that follows in the second packet.
133 * Returns number of bytes read (may return zero)
134 * Returns -1 on signal (BNET_SIGNAL)
135 * Returns -2 on hard end of file (BNET_HARDEOF)
136 * Returns -3 on error (BNET_ERROR)
138 * Unfortunately, it is a bit complicated because we have these
141 * 2. Signal including end of data stream
142 * 3. Hard end of file
144 * Using is_bnet_stop() and is_bnet_error() you can figure this all out.
146 int32_t bnet_recv(BSOCK *bsock)
151 ASSERT(bsock != NULL);
152 mp_chr(bsock->msg)[0] = 0;
153 if (bsock->errors || bsock->terminated) {
157 bsock->read_seqno++; /* bump sequence number */
158 bsock->timer_start = watchdog_time; /* set start wait time */
159 bsock->timed_out = 0;
160 /* get data size -- in int32_t */
161 if ((nbytes = read_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
162 bsock->timer_start = 0; /* clear timer */
163 /* probably pipe broken because client died */
165 bsock->b_errno = ENODATA;
167 bsock->b_errno = errno;
170 return BNET_HARDEOF; /* assume hard EOF received */
172 bsock->timer_start = 0; /* clear timer */
173 if (nbytes != sizeof(int32_t)) {
175 bsock->b_errno = EIO;
176 Jmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"), pktsiz, nbytes,
177 bsock->who, bsock->host, bsock->port);
181 pktsiz = ntohl(pktsiz); /* decode no. of bytes that follow */
183 if (pktsiz == 0) { /* No data transferred */
184 bsock->timer_start = 0; /* clear timer */
187 return 0; /* zero bytes read */
190 /* If signal or packet size too big */
191 if (pktsiz < 0 || pktsiz > 1000000) {
192 if (pktsiz > 0) { /* if packet too big */
193 Jmsg3(bsock->jcr, M_FATAL, 0,
194 _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
195 bsock->who, bsock->host, bsock->port);
196 pktsiz = BNET_TERMINATE; /* hang up */
198 if (pktsiz == BNET_TERMINATE) {
199 bsock->terminated = 1;
201 bsock->timer_start = 0; /* clear timer */
202 bsock->b_errno = ENODATA;
203 bsock->msglen = pktsiz; /* signal code */
204 return BNET_SIGNAL; /* signal */
207 /* Make sure the buffer is big enough + one byte for EOS */
208 if (pktsiz >= (int32_t)sizeof_pool_memory(bsock->msg)) {
209 bsock->msg = realloc_pool_memory(bsock->msg, pktsiz + 100);
212 bsock->timer_start = watchdog_time; /* set start wait time */
213 bsock->timed_out = 0;
214 /* now read the actual data */
215 if ((nbytes = read_nbytes(bsock, mp_chr(bsock->msg), pktsiz)) <= 0) {
216 bsock->timer_start = 0; /* clear timer */
218 bsock->b_errno = ENODATA;
220 bsock->b_errno = errno;
223 Jmsg4(bsock->jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
224 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
227 bsock->timer_start = 0; /* clear timer */
229 bsock->msglen = nbytes;
230 if (nbytes != pktsiz) {
231 bsock->b_errno = EIO;
233 Jmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"), pktsiz, nbytes,
234 bsock->who, bsock->host, bsock->port);
237 /* always add a zero by to properly terminate any
238 * string that was send to us. Note, we ensured above that the
239 * buffer is at least one byte longer than the message length.
241 mp_chr(bsock->msg)[nbytes] = 0; /* terminate in case it is a string */
242 sm_check(__FILE__, __LINE__, False);
243 return nbytes; /* return actual length of message */
248 * Return 1 if there are errors on this bsock or it is closed,
249 * i.e. stop communicating on this line.
251 int is_bnet_stop(BSOCK *bsock)
253 return bsock->errors || bsock->terminated;
257 * Return number of errors on socket
259 int is_bnet_error(BSOCK *bsock)
261 return bsock->errors;
265 * Call here after error during closing to suppress error
266 * messages which are due to the other end shutting down too.
269 bnet_suppress_error_messages(BSOCK *bsock, int flag)
271 bsock->suppress_error_msgs = flag;
276 * Transmit spooled data now
278 int bnet_despool(BSOCK *bsock)
283 rewind(bsock->spool_fd);
284 while (fread((char *)&pktsiz, 1, sizeof(int32_t), bsock->spool_fd) == sizeof(int32_t)) {
285 bsock->msglen = ntohl(pktsiz);
286 if (bsock->msglen > 0) {
287 if (bsock->msglen > (int32_t)sizeof_pool_memory(bsock->msg)) {
288 bsock->msg = realloc_pool_memory(bsock->msg, bsock->msglen);
290 nbytes = fread(bsock->msg, 1, bsock->msglen, bsock->spool_fd);
291 if (nbytes != (size_t)bsock->msglen) {
292 Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, bsock->msglen);
293 Jmsg1(bsock->jcr, M_ERROR, 0, _("fread error. ERR=%s\n"), strerror(errno));
299 if (ferror(bsock->spool_fd)) {
300 Jmsg1(bsock->jcr, M_ERROR, 0, _("fread error. ERR=%s\n"), strerror(errno));
308 * Send a message over the network. The send consists of
309 * two network packets. The first is sends a 32 bit integer containing
310 * the length of the data packet which follows.
312 * Returns: 0 on failure
316 bnet_send(BSOCK *bsock)
322 if (bsock->errors || bsock->terminated) {
325 msglen = bsock->msglen;
326 ASSERT(bsock->msglen < 1000000);
327 pktsiz = htonl((int32_t)bsock->msglen);
328 /* send int32_t containing size of data packet */
329 bsock->timer_start = watchdog_time; /* start timer */
330 bsock->timed_out = 0;
331 rc = write_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t));
332 bsock->timer_start = 0; /* clear timer */
333 if (rc != sizeof(int32_t)) {
334 if (bsock->msglen == BNET_TERMINATE) { /* if we were terminating */
335 bsock->terminated = 1;
336 return 0; /* ignore any errors */
340 bsock->b_errno = EIO;
342 bsock->b_errno = errno;
345 if (!bsock->suppress_error_msgs && !bsock->timed_out) {
346 Jmsg4(bsock->jcr, M_ERROR, 0, _("Write error sending to %s:%s:%d: ERR=%s\n"),
347 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
350 Jmsg5(bsock->jcr, M_ERROR, 0, _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
351 bsock->who, bsock->host, bsock->port, bsock->msglen, rc);
356 bsock->out_msg_no++; /* increment message number */
357 if (bsock->msglen <= 0) { /* length only? */
358 ASSERT(msglen == bsock->msglen);
359 return 1; /* yes, no data */
362 /* send data packet */
363 bsock->timer_start = watchdog_time; /* start timer */
364 bsock->timed_out = 0;
365 rc = write_nbytes(bsock, mp_chr(bsock->msg), bsock->msglen);
366 bsock->timer_start = 0; /* clear timer */
367 if (rc != bsock->msglen) {
370 bsock->b_errno = EIO;
372 bsock->b_errno = errno;
375 if (!bsock->suppress_error_msgs) {
376 Jmsg4(bsock->jcr, M_ERROR, 0, _("Write error sending to %s:%s:%d: ERR=%s\n"),
377 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
380 Jmsg5(bsock->jcr, M_ERROR, 0, _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
381 bsock->msglen, bsock->who, bsock->host, bsock->port, rc);
385 ASSERT(msglen == bsock->msglen);
390 * Establish an SSL connection -- server side
391 * Codes that ssl_need and ssl_has can take
392 * BNET_SSL_NONE I cannot do ssl
393 * BNET_SSL_OK I can do ssl, but it is not required on my end
394 * BNET_SSL_REQUIRED ssl is required on my end
397 bnet_ssl_server(BSOCK *bsock, char *password, int ssl_need, int ssl_has)
399 /* Check to see if what we need (ssl_need) corresponds to what he has (ssl_has) */
400 /* The other side expects a response from us */
405 * Establish an SSL connection -- client side
407 int bnet_ssl_client(BSOCK *bsock, char *password, int ssl_need)
409 /* We are the client so we must wait for the server to notify us */
415 * Wait for a specified time for data to appear on
416 * the BSOCK connection.
418 * Returns: 1 if data available
423 bnet_wait_data(BSOCK *bsock, int sec)
429 FD_SET(bsock->fd, &fdset);
433 switch(select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
434 case 0: /* timeout */
438 bsock->b_errno = errno;
439 if (errno == EINTR || errno == EAGAIN) {
442 return -1; /* error return */
451 * As above, but returns on interrupt
454 bnet_wait_data_intr(BSOCK *bsock, int sec)
460 FD_SET(bsock->fd, &fdset);
464 switch(select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
465 case 0: /* timeout */
469 bsock->b_errno = errno;
470 return -1; /* error return */
478 #ifndef NETDB_INTERNAL
479 #define NETDB_INTERNAL -1 /* See errno. */
481 #ifndef NETDB_SUCCESS
482 #define NETDB_SUCCESS 0 /* No problem. */
484 #ifndef HOST_NOT_FOUND
485 #define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found. */
488 #define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL. */
491 #define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP. */
494 #define NO_DATA 4 /* Valid name, no data record of requested type. */
497 extern int h_errno; /* On error has one of the above */
500 * Get human readable error for gethostbyname()
502 static char *gethost_strerror()
506 return strerror(errno);
508 return "No problem.";
510 return "Authoritative answer Host not found.";
512 return "Non-authoritative Host not found, or ServerFail.";
514 return "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.";
516 return "Valid name, no data record of resquested type.";
518 return "Unknown error.";
523 static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
526 * Convert a hostname or dotted IP address into
527 * a s_addr. We handle only IPv4.
529 static uint32_t *bget_host_ip(JCR *jcr, char *host)
531 struct in_addr inaddr;
532 uint32_t *addr_list; /* this really should be struct in_addr */
537 if ((inaddr.s_addr = inet_addr(host)) != INADDR_NONE) {
538 addr_list = (uint32_t *) malloc(sizeof(uint32_t) * 2);
539 addr_list[0] = inaddr.s_addr;
540 addr_list[1] = (uint32_t) -1;
543 if ((hp = gethostbyname(host)) == NULL) {
544 Jmsg2(jcr, M_ERROR, 0, "gethostbyname() for %s failed: ERR=%s\n",
545 host, gethost_strerror());
549 if (hp->h_length != sizeof(inaddr.s_addr) || hp->h_addrtype != AF_INET) {
550 Jmsg2(jcr, M_ERROR, 0, _("gethostbyname() network address length error.\n\
551 Wanted %d got %d bytes for s_addr.\n"), sizeof(inaddr.s_addr), hp->h_length);
556 for (p = hp->h_addr_list; *p != 0; p++) {
560 addr_list = (uint32_t *)malloc(sizeof(uint32_t) * i);
562 for (p = hp->h_addr_list; *p != 0; p++) {
563 addr_list[i++] = (*(struct in_addr **)p)->s_addr;
565 addr_list[i] = (uint32_t) -1;
572 * Open a TCP connection to the UPS network server
574 * Returns BSOCK * pointer on success
576 * ***FIXME*** implement service from /etc/services
579 bnet_open(JCR *jcr, char *name, char *host, char *service, int port, int *fatal)
582 struct sockaddr_in tcp_serv_addr; /* socket information */
584 int i, connected = 0;
588 * Fill in the structure serv_addr with the address of
589 * the server that we want to connect with.
591 memset((char *)&tcp_serv_addr, 0, sizeof(tcp_serv_addr));
592 tcp_serv_addr.sin_family = AF_INET;
593 tcp_serv_addr.sin_port = htons(port);
595 if ((addr_list=bget_host_ip(jcr, host)) == NULL) {
600 /* Open a TCP socket */
601 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
608 * Receive notification when connection dies.
610 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
611 Jmsg(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"), strerror(errno));
614 for (i = 0; addr_list[i] != ((uint32_t) -1); i++) {
615 /* connect to server */
616 tcp_serv_addr.sin_addr.s_addr = addr_list[i];
617 if (connect(sockfd, (struct sockaddr *)&tcp_serv_addr, sizeof(tcp_serv_addr)) < 0) {
629 return init_bsock(jcr, sockfd, name, host, port);
633 * Try to connect to host for max_retry_time at retry_time intervals.
636 bnet_connect(JCR *jcr, int retry_interval, int max_retry_time, char *name,
637 char *host, char *service, int port, int verbose)
643 for (i=0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL; i -= retry_interval) {
644 if (fatal || (jcr && job_canceled(jcr))) {
647 Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
648 name, host, port, strerror(errno));
650 i = 60 * 5; /* complain again in 5 minutes */
652 Jmsg(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
653 Retrying ...\n", name, host, port, strerror(errno));
655 bmicrosleep(retry_interval, 0);
656 max_retry_time -= retry_interval;
657 if (max_retry_time <= 0) {
658 Jmsg(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
659 name, host, port, strerror(errno));
668 * Return the string for the error that occurred
669 * on the socket. Only the first error is retained.
671 char *bnet_strerror(BSOCK *bsock)
673 return strerror(bsock->b_errno);
677 * Format and send a message
678 * Returns: 0 on failure
682 bnet_fsend(BSOCK *bs, char *fmt, ...)
687 /* This probably won't work, but we vsnprintf, then if we
688 * get a negative length or a length greater than our buffer
689 * (depending on which library is used), the printf was truncated, so
690 * get a biger buffer and try again.
693 maxlen = sizeof_pool_memory(bs->msg) - 1;
694 va_start(arg_ptr, fmt);
695 bs->msglen = bvsnprintf(mp_chr(bs->msg), maxlen, fmt, arg_ptr);
697 if (bs->msglen < 0 || bs->msglen >= maxlen) {
698 bs->msg = realloc_pool_memory(bs->msg, maxlen + 200);
701 return bnet_send(bs) < 0 ? 0 : 1;
705 * Set the network buffer size, suggested size is in size.
706 * Actual size obtained is returned in bs->msglen
708 * Returns: 0 on failure
711 int bnet_set_buffer_size(BSOCK *bs, uint32_t size, int rw)
714 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
717 opt = IPTOS_THROUGHPUT;
718 setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t)&opt, sizeof(opt));
722 if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size+100)) == NULL) {
723 Jmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
726 if (rw & BNET_SETBUF_READ) {
727 while ((dbuf_size > TAPE_BSIZE) &&
728 (setsockopt(bs->fd, SOL_SOCKET, SO_RCVBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
729 Jmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
730 dbuf_size -= TAPE_BSIZE;
732 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
733 if (dbuf_size != MAX_NETWORK_BUFFER_SIZE)
734 Jmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
735 if (dbuf_size % TAPE_BSIZE != 0) {
736 Jmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
741 if (rw & BNET_SETBUF_WRITE) {
742 while ((dbuf_size > TAPE_BSIZE) &&
743 (setsockopt(bs->fd, SOL_SOCKET, SO_SNDBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
744 Jmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
745 dbuf_size -= TAPE_BSIZE;
747 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
748 if (dbuf_size != MAX_NETWORK_BUFFER_SIZE)
749 Jmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
750 if (dbuf_size % TAPE_BSIZE != 0) {
751 Jmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
756 bs->msglen = dbuf_size;
761 * Send a network "signal" to the other end
762 * This consists of sending a negative packet length
764 * Returns: 0 on failure
767 int bnet_sig(BSOCK *bs, int sig)
770 return bnet_send(bs);
774 * Convert a network "signal" code into
775 * human readable ASCII.
777 char *bnet_sig_to_ascii(BSOCK *bs)
780 switch (bs->msglen) {
782 return "BNET_EOD"; /* end of data stream */
784 return "BNET_EOD_POLL";
786 return "BNET_STATUS";
788 return "BNET_TERMINATE"; /* terminate connection */
792 return "BNET_HEARTBEAT";
793 case BNET_HB_RESPONSE:
794 return "BNET_HB_RESPONSE";
796 return "BNET_PROMPT";
798 sprintf(buf, "Unknown sig %d", bs->msglen);
804 /* Initialize internal socket structure.
805 * This probably should be done in net_open
808 init_bsock(JCR *jcr, int sockfd, char *who, char *host, int port)
810 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
811 memset(bsock, 0, sizeof(BSOCK));
814 bsock->msg = get_pool_memory(PM_MESSAGE);
815 bsock->errmsg = get_pool_memory(PM_MESSAGE);
816 bsock->who = bstrdup(who);
817 bsock->host = bstrdup(host);
820 * ****FIXME**** reduce this to a few hours once
821 * heartbeats are implemented
823 bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */
829 dup_bsock(BSOCK *osock)
831 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
832 memcpy(bsock, osock, sizeof(BSOCK));
833 bsock->msg = get_pool_memory(PM_MESSAGE);
834 bsock->errmsg = get_pool_memory(PM_MESSAGE);
836 bsock->who = bstrdup(osock->who);
839 bsock->host = bstrdup(osock->host);
845 /* Close the network connection */
847 bnet_close(BSOCK *bsock)
851 for ( ; bsock != NULL; bsock = next) {
854 if (bsock->timed_out) {
855 shutdown(bsock->fd, 2); /* discard any pending I/O */
857 close(bsock->fd); /* normal close */
865 term_bsock(BSOCK *bsock)
868 free_pool_memory(bsock->msg);
871 ASSERT(1==0); /* double close */
874 free_pool_memory(bsock->errmsg);
875 bsock->errmsg = NULL;