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)
50 #define socketRead(fd, buf, len) read(fd, buf, len)
51 #define socketWrite(fd, buf, len) write(fd, buf, len)
56 * Read a nbytes from the network.
57 * It is possible that the total bytes require in several
61 static int32_t read_nbytes(BSOCK *bsock, char *ptr, int32_t nbytes)
69 nread = socketRead(bsock->fd, ptr, nleft);
70 if (bsock->timed_out || bsock->terminated) {
73 } while (nread == -1 && (errno == EINTR || errno == EAGAIN));
75 return nread; /* error, or EOF */
80 return nbytes - nleft; /* return >= 0 */
84 * Write nbytes to the network.
85 * It may require several writes.
88 static int32_t write_nbytes(BSOCK *bsock, char *ptr, int32_t nbytes)
90 int32_t nleft, nwritten;
93 nwritten = fwrite(ptr, 1, nbytes, bsock->spool_fd);
94 if (nwritten != nbytes) {
95 Qmsg1(bsock->jcr, M_FATAL, 0, _("Attr spool write error. ERR=%s\n"), strerror(errno));
96 Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes);
105 nwritten = socketWrite(bsock->fd, ptr, nleft);
106 if (bsock->timed_out || bsock->terminated) {
109 } while (nwritten == -1 && errno == EINTR);
111 * If connection is non-blocking, we will get EAGAIN, so
112 * use select() to keep from consuming all the CPU
115 if (nwritten == -1 && errno == EAGAIN) {
120 FD_SET(bsock->fd, &fdset);
123 select(bsock->fd + 1, NULL, &fdset, NULL, &tv);
127 return nwritten; /* error */
136 * Receive a message from the other end. Each message consists of
137 * two packets. The first is a header that contains the size
138 * of the data that follows in the second packet.
139 * Returns number of bytes read (may return zero)
140 * Returns -1 on signal (BNET_SIGNAL)
141 * Returns -2 on hard end of file (BNET_HARDEOF)
142 * Returns -3 on error (BNET_ERROR)
144 * Unfortunately, it is a bit complicated because we have these
147 * 2. Signal including end of data stream
148 * 3. Hard end of file
150 * Using is_bnet_stop() and is_bnet_error() you can figure this all out.
152 int32_t bnet_recv(BSOCK *bsock)
157 ASSERT(bsock != NULL);
158 mp_chr(bsock->msg)[0] = 0;
159 if (bsock->errors || bsock->terminated) {
163 bsock->read_seqno++; /* bump sequence number */
164 bsock->timer_start = watchdog_time; /* set start wait time */
165 bsock->timed_out = 0;
166 /* get data size -- in int32_t */
167 if ((nbytes = read_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
168 bsock->timer_start = 0; /* clear timer */
169 /* probably pipe broken because client died */
171 bsock->b_errno = ENODATA;
173 bsock->b_errno = errno;
176 return BNET_HARDEOF; /* assume hard EOF received */
178 bsock->timer_start = 0; /* clear timer */
179 if (nbytes != sizeof(int32_t)) {
181 bsock->b_errno = EIO;
182 Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
183 sizeof(int32_t), nbytes, bsock->who, bsock->host, bsock->port);
187 pktsiz = ntohl(pktsiz); /* decode no. of bytes that follow */
189 if (pktsiz == 0) { /* No data transferred */
190 bsock->timer_start = 0; /* clear timer */
193 return 0; /* zero bytes read */
196 /* If signal or packet size too big */
197 if (pktsiz < 0 || pktsiz > 1000000) {
198 if (pktsiz > 0) { /* if packet too big */
199 Qmsg3(bsock->jcr, M_FATAL, 0,
200 _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
201 bsock->who, bsock->host, bsock->port);
202 pktsiz = BNET_TERMINATE; /* hang up */
204 if (pktsiz == BNET_TERMINATE) {
205 bsock->terminated = 1;
207 bsock->timer_start = 0; /* clear timer */
208 bsock->b_errno = ENODATA;
209 bsock->msglen = pktsiz; /* signal code */
210 return BNET_SIGNAL; /* signal */
213 /* Make sure the buffer is big enough + one byte for EOS */
214 if (pktsiz >= (int32_t)sizeof_pool_memory(bsock->msg)) {
215 bsock->msg = realloc_pool_memory(bsock->msg, pktsiz + 100);
218 bsock->timer_start = watchdog_time; /* set start wait time */
219 bsock->timed_out = 0;
220 /* now read the actual data */
221 if ((nbytes = read_nbytes(bsock, mp_chr(bsock->msg), pktsiz)) <= 0) {
222 bsock->timer_start = 0; /* clear timer */
224 bsock->b_errno = ENODATA;
226 bsock->b_errno = errno;
229 Qmsg4(bsock->jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
230 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
233 bsock->timer_start = 0; /* clear timer */
235 bsock->msglen = nbytes;
236 if (nbytes != pktsiz) {
237 bsock->b_errno = EIO;
239 Qmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"), pktsiz, nbytes,
240 bsock->who, bsock->host, bsock->port);
243 /* always add a zero by to properly terminate any
244 * string that was send to us. Note, we ensured above that the
245 * buffer is at least one byte longer than the message length.
247 mp_chr(bsock->msg)[nbytes] = 0; /* terminate in case it is a string */
248 sm_check(__FILE__, __LINE__, false);
249 return nbytes; /* return actual length of message */
254 * Return 1 if there are errors on this bsock or it is closed,
255 * i.e. stop communicating on this line.
257 int is_bnet_stop(BSOCK *bsock)
259 return bsock->errors || bsock->terminated;
263 * Return number of errors on socket
265 int is_bnet_error(BSOCK *bsock)
267 return bsock->errors;
271 * Call here after error during closing to suppress error
272 * messages which are due to the other end shutting down too.
275 bnet_suppress_error_messages(BSOCK *bsock, bool flag)
277 bsock->suppress_error_msgs = flag;
282 * Transmit spooled data now to a BSOCK
284 int bnet_despool_to_bsock(BSOCK *bsock, void update_attr_spool_size(ssize_t size), ssize_t tsize)
288 ssize_t last = 0, size = 0;
291 rewind(bsock->spool_fd);
292 while (fread((char *)&pktsiz, 1, sizeof(int32_t), bsock->spool_fd) == sizeof(int32_t)) {
293 size += sizeof(int32_t);
294 bsock->msglen = ntohl(pktsiz);
295 if (bsock->msglen > 0) {
296 if (bsock->msglen > (int32_t)sizeof_pool_memory(bsock->msg)) {
297 bsock->msg = realloc_pool_memory(bsock->msg, bsock->msglen + 1);
299 nbytes = fread(bsock->msg, 1, bsock->msglen, bsock->spool_fd);
300 if (nbytes != (size_t)bsock->msglen) {
301 Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, bsock->msglen);
302 Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"), strerror(errno));
303 update_attr_spool_size(tsize-last);
307 if ((++count & 0x3F) == 0) {
308 update_attr_spool_size(size-last);
314 update_attr_spool_size(tsize-last);
315 if (ferror(bsock->spool_fd)) {
316 Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"), strerror(errno));
324 * Send a message over the network. The send consists of
325 * two network packets. The first is sends a 32 bit integer containing
326 * the length of the data packet which follows.
328 * Returns: 0 on failure
332 bnet_send(BSOCK *bsock)
338 if (bsock->errors || bsock->terminated || bsock->msglen > 1000000) {
341 msglen = bsock->msglen;
342 pktsiz = htonl((int32_t)bsock->msglen);
343 /* send int32_t containing size of data packet */
344 bsock->timer_start = watchdog_time; /* start timer */
345 bsock->timed_out = 0;
346 rc = write_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t));
347 bsock->timer_start = 0; /* clear timer */
348 if (rc != sizeof(int32_t)) {
349 if (bsock->msglen == BNET_TERMINATE) { /* if we were terminating */
350 bsock->terminated = 1;
351 return 0; /* ignore any errors */
355 bsock->b_errno = EIO;
357 bsock->b_errno = errno;
360 if (!bsock->suppress_error_msgs && !bsock->timed_out) {
361 Qmsg4(bsock->jcr, M_ERROR, 0, _("Write error sending to %s:%s:%d: ERR=%s\n"),
362 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
365 Qmsg5(bsock->jcr, M_ERROR, 0, _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
366 bsock->who, bsock->host, bsock->port, bsock->msglen, rc);
371 bsock->out_msg_no++; /* increment message number */
372 if (bsock->msglen <= 0) { /* length only? */
373 return 1; /* yes, no data */
376 /* send data packet */
377 bsock->timer_start = watchdog_time; /* start timer */
378 bsock->timed_out = 0;
379 rc = write_nbytes(bsock, mp_chr(bsock->msg), bsock->msglen);
380 bsock->timer_start = 0; /* clear timer */
381 if (rc != bsock->msglen) {
384 bsock->b_errno = EIO;
386 bsock->b_errno = errno;
389 if (!bsock->suppress_error_msgs) {
390 Qmsg4(bsock->jcr, M_ERROR, 0, _("Write error sending to %s:%s:%d: ERR=%s\n"),
391 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
394 Qmsg5(bsock->jcr, M_ERROR, 0, _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
395 bsock->msglen, bsock->who, bsock->host, bsock->port, rc);
403 * Establish an SSL connection -- server side
404 * Codes that ssl_need and ssl_has can take
405 * BNET_SSL_NONE I cannot do ssl
406 * BNET_SSL_OK I can do ssl, but it is not required on my end
407 * BNET_SSL_REQUIRED ssl is required on my end
410 bnet_ssl_server(BSOCK *bsock, char *password, int ssl_need, int ssl_has)
412 /* Check to see if what we need (ssl_need) corresponds to what he has (ssl_has) */
413 /* The other side expects a response from us */
418 * Establish an SSL connection -- client side
420 int bnet_ssl_client(BSOCK *bsock, char *password, int ssl_need)
422 /* We are the client so we must wait for the server to notify us */
428 * Wait for a specified time for data to appear on
429 * the BSOCK connection.
431 * Returns: 1 if data available
436 bnet_wait_data(BSOCK *bsock, int sec)
442 FD_SET(bsock->fd, &fdset);
446 switch(select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
447 case 0: /* timeout */
451 bsock->b_errno = errno;
452 if (errno == EINTR || errno == EAGAIN) {
455 return -1; /* error return */
464 * As above, but returns on interrupt
467 bnet_wait_data_intr(BSOCK *bsock, int sec)
473 FD_SET(bsock->fd, &fdset);
477 switch(select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
478 case 0: /* timeout */
482 bsock->b_errno = errno;
483 return -1; /* error return */
491 #ifndef NETDB_INTERNAL
492 #define NETDB_INTERNAL -1 /* See errno. */
494 #ifndef NETDB_SUCCESS
495 #define NETDB_SUCCESS 0 /* No problem. */
497 #ifndef HOST_NOT_FOUND
498 #define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found. */
501 #define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL. */
504 #define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP. */
507 #define NO_DATA 4 /* Valid name, no data record of requested type. */
511 * Get human readable error for gethostbyname()
513 static const char *gethost_strerror()
517 return strerror(errno);
519 return "No problem.";
521 return "Authoritative answer Host not found.";
523 return "Non-authoritative Host not found, or ServerFail.";
525 return "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.";
527 return "Valid name, no data record of resquested type.";
529 return "Unknown error.";
534 static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
537 * Convert a hostname or dotted IP address into
538 * a s_addr. We handle only IPv4.
540 static uint32_t *bget_host_ip(JCR *jcr, char *host)
542 struct in_addr inaddr;
543 uint32_t *addr_list; /* this really should be struct in_addr */
548 if ((inaddr.s_addr = inet_addr(host)) != INADDR_NONE) {
549 addr_list = (uint32_t *) malloc(sizeof(uint32_t) * 2);
550 addr_list[0] = inaddr.s_addr;
551 addr_list[1] = (uint32_t) -1;
554 if ((hp = gethostbyname(host)) == NULL) {
555 Qmsg2(jcr, M_ERROR, 0, "gethostbyname() for host \"%s\" failed: ERR=%s\n",
556 host, gethost_strerror());
560 if (hp->h_length != sizeof(inaddr.s_addr) || hp->h_addrtype != AF_INET) {
561 Qmsg2(jcr, M_ERROR, 0, _("gethostbyname() network address length error.\n\
562 Wanted %d got %d bytes for s_addr.\n"), sizeof(inaddr.s_addr), hp->h_length);
567 for (p = hp->h_addr_list; *p != 0; p++) {
571 addr_list = (uint32_t *)malloc(sizeof(uint32_t) * i);
573 for (p = hp->h_addr_list; *p != 0; p++) {
574 addr_list[i++] = (*(struct in_addr **)p)->s_addr;
576 addr_list[i] = (uint32_t) -1;
583 * Open a TCP connection to the UPS network server
585 * Returns BSOCK * pointer on success
587 * ***FIXME*** implement service from /etc/services
590 bnet_open(JCR *jcr, const char *name, char *host, char *service, int port, int *fatal)
593 struct sockaddr_in tcp_serv_addr; /* socket information */
595 int i, connected = 0;
599 * Fill in the structure serv_addr with the address of
600 * the server that we want to connect with.
602 memset((char *)&tcp_serv_addr, 0, sizeof(tcp_serv_addr));
603 tcp_serv_addr.sin_family = AF_INET;
604 tcp_serv_addr.sin_port = htons(port);
606 if ((addr_list=bget_host_ip(jcr, host)) == NULL) {
611 /* Open a TCP socket */
612 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
619 * Receive notification when connection dies.
621 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
622 Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"), strerror(errno));
625 for (i = 0; addr_list[i] != ((uint32_t) -1); i++) {
626 /* connect to server */
627 tcp_serv_addr.sin_addr.s_addr = addr_list[i];
628 if (connect(sockfd, (struct sockaddr *)&tcp_serv_addr, sizeof(tcp_serv_addr)) < 0) {
640 return init_bsock(jcr, sockfd, name, host, port, &tcp_serv_addr);
644 * Try to connect to host for max_retry_time at retry_time intervals.
647 bnet_connect(JCR *jcr, int retry_interval, int max_retry_time, const char *name,
648 char *host, char *service, int port, int verbose)
654 for (i=0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL; i -= retry_interval) {
655 if (fatal || (jcr && job_canceled(jcr))) {
658 Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
659 name, host, port, strerror(errno));
661 i = 60 * 5; /* complain again in 5 minutes */
663 Qmsg4(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
664 Retrying ...\n", name, host, port, strerror(errno));
666 bmicrosleep(retry_interval, 0);
667 max_retry_time -= retry_interval;
668 if (max_retry_time <= 0) {
669 Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
670 name, host, port, strerror(errno));
679 * Return the string for the error that occurred
680 * on the socket. Only the first error is retained.
682 char *bnet_strerror(BSOCK *bsock)
684 return strerror(bsock->b_errno);
688 * Format and send a message
689 * Returns: 0 on failure
693 bnet_fsend(BSOCK *bs, const char *fmt, ...)
698 if (bs->errors || bs->terminated) {
701 /* This probably won't work, but we vsnprintf, then if we
702 * get a negative length or a length greater than our buffer
703 * (depending on which library is used), the printf was truncated, so
704 * get a biger buffer and try again.
707 maxlen = sizeof_pool_memory(bs->msg) - 1;
708 va_start(arg_ptr, fmt);
709 bs->msglen = bvsnprintf(mp_chr(bs->msg), maxlen, fmt, arg_ptr);
711 if (bs->msglen < 0 || bs->msglen >= maxlen) {
712 bs->msg = realloc_pool_memory(bs->msg, maxlen + maxlen / 2);
715 return bnet_send(bs);
719 * Set the network buffer size, suggested size is in size.
720 * Actual size obtained is returned in bs->msglen
722 * Returns: 0 on failure
725 int bnet_set_buffer_size(BSOCK *bs, uint32_t size, int rw)
727 uint32_t dbuf_size, start_size;
728 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
731 opt = IPTOS_THROUGHPUT;
732 setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t)&opt, sizeof(opt));
738 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
740 start_size = dbuf_size;
741 if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size+100)) == NULL) {
742 Qmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
745 if (rw & BNET_SETBUF_READ) {
746 while ((dbuf_size > TAPE_BSIZE) &&
747 (setsockopt(bs->fd, SOL_SOCKET, SO_RCVBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
748 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
749 dbuf_size -= TAPE_BSIZE;
751 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
752 if (dbuf_size != start_size) {
753 Qmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
755 if (dbuf_size % TAPE_BSIZE != 0) {
756 Qmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
763 dbuf_size = DEFAULT_NETWORK_BUFFER_SIZE;
765 start_size = dbuf_size;
766 if (rw & BNET_SETBUF_WRITE) {
767 while ((dbuf_size > TAPE_BSIZE) &&
768 (setsockopt(bs->fd, SOL_SOCKET, SO_SNDBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
769 Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
770 dbuf_size -= TAPE_BSIZE;
772 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
773 if (dbuf_size != start_size) {
774 Qmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
776 if (dbuf_size % TAPE_BSIZE != 0) {
777 Qmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
782 bs->msglen = dbuf_size;
787 * Send a network "signal" to the other end
788 * This consists of sending a negative packet length
790 * Returns: 0 on failure
793 int bnet_sig(BSOCK *bs, int sig)
796 return bnet_send(bs);
800 * Convert a network "signal" code into
801 * human readable ASCII.
803 char *bnet_sig_to_ascii(BSOCK *bs)
806 switch (bs->msglen) {
808 return "BNET_EOD"; /* end of data stream */
810 return "BNET_EOD_POLL";
812 return "BNET_STATUS";
814 return "BNET_TERMINATE"; /* terminate connection */
818 return "BNET_HEARTBEAT";
819 case BNET_HB_RESPONSE:
820 return "BNET_HB_RESPONSE";
822 return "BNET_PROMPT";
824 sprintf(buf, "Unknown sig %d", bs->msglen);
830 /* Initialize internal socket structure.
831 * This probably should be done in net_open
834 init_bsock(JCR *jcr, int sockfd, const char *who, char *host, int port,
835 struct sockaddr_in *client_addr)
837 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
838 memset(bsock, 0, sizeof(BSOCK));
841 bsock->msg = get_pool_memory(PM_MESSAGE);
842 bsock->errmsg = get_pool_memory(PM_MESSAGE);
843 bsock->who = bstrdup(who);
844 bsock->host = bstrdup(host);
846 memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
848 * ****FIXME**** reduce this to a few hours once
849 * heartbeats are implemented
851 bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */
857 dup_bsock(BSOCK *osock)
859 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
860 memcpy(bsock, osock, sizeof(BSOCK));
861 bsock->msg = get_pool_memory(PM_MESSAGE);
862 bsock->errmsg = get_pool_memory(PM_MESSAGE);
864 bsock->who = bstrdup(osock->who);
867 bsock->host = bstrdup(osock->host);
873 /* Close the network connection */
875 bnet_close(BSOCK *bsock)
879 for ( ; bsock != NULL; bsock = next) {
882 if (bsock->timed_out) {
883 shutdown(bsock->fd, 2); /* discard any pending I/O */
885 close(bsock->fd); /* normal close */
893 term_bsock(BSOCK *bsock)
896 free_pool_memory(bsock->msg);
899 ASSERT(1==0); /* double close */
902 free_pool_memory(bsock->errmsg);
903 bsock->errmsg = NULL;