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) {
66 } while (nread == -1 && (errno == EINTR || errno == EAGAIN));
68 return nread; /* error, or EOF */
73 return nbytes - nleft; /* return >= 0 */
77 * Write nbytes to the network.
78 * It may require several writes.
81 static int32_t write_nbytes(BSOCK *bsock, char *ptr, int32_t nbytes)
83 int32_t nleft, nwritten;
86 nwritten = fwrite(ptr, 1, nbytes, bsock->spool_fd);
87 if (nwritten != nbytes) {
88 Jmsg1(bsock->jcr, M_ERROR, 0, _("Spool write error. ERR=%s\n"), strerror(errno));
89 Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes);
98 nwritten = write(bsock->fd, ptr, nleft);
99 if (bsock->timed_out || bsock->terminated) {
102 } while (nwritten == -1 && errno == EINTR);
104 * If connection is non-blocking, we will get EAGAIN, so
105 * use select() to keep from consuming all the CPU
108 if (nwritten == -1 && errno == EAGAIN) {
113 FD_SET(bsock->fd, &fdset);
116 select(bsock->fd + 1, NULL, &fdset, NULL, &tv);
120 return nwritten; /* error */
129 * Receive a message from the other end. Each message consists of
130 * two packets. The first is a header that contains the size
131 * of the data that follows in the second packet.
132 * Returns number of bytes read (may return zero)
133 * Returns -1 on signal (BNET_SIGNAL)
134 * Returns -2 on hard end of file (BNET_HARDEOF)
135 * Returns -3 on error (BNET_ERROR)
137 * Unfortunately, it is a bit complicated because we have these
140 * 2. Signal including end of data stream
141 * 3. Hard end of file
143 * Using is_bnet_stop() and is_bnet_error() you can figure this all out.
145 int32_t bnet_recv(BSOCK *bsock)
150 ASSERT(bsock != NULL);
151 mp_chr(bsock->msg)[0] = 0;
152 if (bsock->errors || bsock->terminated) {
156 bsock->read_seqno++; /* bump sequence number */
157 bsock->timer_start = watchdog_time; /* set start wait time */
158 bsock->timed_out = 0;
159 /* get data size -- in int32_t */
160 if ((nbytes = read_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
161 bsock->timer_start = 0; /* clear timer */
162 /* probably pipe broken because client died */
164 bsock->b_errno = ENODATA;
166 bsock->b_errno = errno;
169 return BNET_HARDEOF; /* assume hard EOF received */
171 bsock->timer_start = 0; /* clear timer */
172 if (nbytes != sizeof(int32_t)) {
174 bsock->b_errno = EIO;
175 Jmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"), pktsiz, nbytes,
176 bsock->who, bsock->host, bsock->port);
180 pktsiz = ntohl(pktsiz); /* decode no. of bytes that follow */
182 if (pktsiz == 0) { /* No data transferred */
183 bsock->timer_start = 0; /* clear timer */
186 return 0; /* zero bytes read */
189 /* If signal or packet size too big */
190 if (pktsiz < 0 || pktsiz > 1000000) {
191 if (pktsiz > 0) { /* if packet too big */
192 Jmsg3(bsock->jcr, M_FATAL, 0,
193 _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
194 bsock->who, bsock->host, bsock->port);
195 pktsiz = BNET_TERMINATE; /* hang up */
197 if (pktsiz == BNET_TERMINATE) {
198 bsock->terminated = 1;
200 bsock->timer_start = 0; /* clear timer */
201 bsock->b_errno = ENODATA;
202 bsock->msglen = pktsiz; /* signal code */
203 return BNET_SIGNAL; /* signal */
206 /* Make sure the buffer is big enough + one byte for EOS */
207 if (pktsiz >= (int32_t)sizeof_pool_memory(bsock->msg)) {
208 bsock->msg = realloc_pool_memory(bsock->msg, pktsiz + 100);
211 bsock->timer_start = watchdog_time; /* set start wait time */
212 bsock->timed_out = 0;
213 /* now read the actual data */
214 if ((nbytes = read_nbytes(bsock, mp_chr(bsock->msg), pktsiz)) <= 0) {
215 bsock->timer_start = 0; /* clear timer */
217 bsock->b_errno = ENODATA;
219 bsock->b_errno = errno;
222 Jmsg4(bsock->jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
223 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
226 bsock->timer_start = 0; /* clear timer */
228 bsock->msglen = nbytes;
229 if (nbytes != pktsiz) {
230 bsock->b_errno = EIO;
232 Jmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"), pktsiz, nbytes,
233 bsock->who, bsock->host, bsock->port);
236 /* always add a zero by to properly terminate any
237 * string that was send to us. Note, we ensured above that the
238 * buffer is at least one byte longer than the message length.
240 mp_chr(bsock->msg)[nbytes] = 0; /* terminate in case it is a string */
241 sm_check(__FILE__, __LINE__, False);
242 return nbytes; /* return actual length of message */
247 * Return 1 if there are errors on this bsock or it is closed,
248 * i.e. stop communicating on this line.
250 int is_bnet_stop(BSOCK *bsock)
252 return bsock->errors || bsock->terminated;
256 * Return number of errors on socket
258 int is_bnet_error(BSOCK *bsock)
260 return bsock->errors;
264 * Call here after error during closing to suppress error
265 * messages which are due to the other end shutting down too.
268 bnet_suppress_error_messages(BSOCK *bsock, int flag)
270 bsock->suppress_error_msgs = flag;
275 * Transmit spooled data now
277 int bnet_despool(BSOCK *bsock)
282 rewind(bsock->spool_fd);
283 while (fread((char *)&pktsiz, 1, sizeof(int32_t), bsock->spool_fd) == sizeof(int32_t)) {
284 bsock->msglen = ntohl(pktsiz);
285 if (bsock->msglen > 0) {
286 if (bsock->msglen > (int32_t)sizeof_pool_memory(bsock->msg)) {
287 bsock->msg = realloc_pool_memory(bsock->msg, bsock->msglen + 1);
289 nbytes = fread(bsock->msg, 1, bsock->msglen, bsock->spool_fd);
290 if (nbytes != (size_t)bsock->msglen) {
291 Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, bsock->msglen);
292 Jmsg1(bsock->jcr, M_ERROR, 0, _("fread error. ERR=%s\n"), strerror(errno));
298 if (ferror(bsock->spool_fd)) {
299 Jmsg1(bsock->jcr, M_ERROR, 0, _("fread error. ERR=%s\n"), strerror(errno));
307 * Send a message over the network. The send consists of
308 * two network packets. The first is sends a 32 bit integer containing
309 * the length of the data packet which follows.
311 * Returns: 0 on failure
315 bnet_send(BSOCK *bsock)
321 if (bsock->errors || bsock->terminated) {
324 msglen = bsock->msglen;
325 ASSERT(bsock->msglen < 1000000);
326 pktsiz = htonl((int32_t)bsock->msglen);
327 /* send int32_t containing size of data packet */
328 bsock->timer_start = watchdog_time; /* start timer */
329 bsock->timed_out = 0;
330 rc = write_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t));
331 bsock->timer_start = 0; /* clear timer */
332 if (rc != sizeof(int32_t)) {
333 if (bsock->msglen == BNET_TERMINATE) { /* if we were terminating */
334 bsock->terminated = 1;
335 return 0; /* ignore any errors */
339 bsock->b_errno = EIO;
341 bsock->b_errno = errno;
344 if (!bsock->suppress_error_msgs && !bsock->timed_out) {
345 Jmsg4(bsock->jcr, M_ERROR, 0, _("Write error sending to %s:%s:%d: ERR=%s\n"),
346 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
349 Jmsg5(bsock->jcr, M_ERROR, 0, _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
350 bsock->who, bsock->host, bsock->port, bsock->msglen, rc);
355 bsock->out_msg_no++; /* increment message number */
356 if (bsock->msglen <= 0) { /* length only? */
357 ASSERT(msglen == bsock->msglen);
358 return 1; /* yes, no data */
361 /* send data packet */
362 bsock->timer_start = watchdog_time; /* start timer */
363 bsock->timed_out = 0;
364 rc = write_nbytes(bsock, mp_chr(bsock->msg), bsock->msglen);
365 bsock->timer_start = 0; /* clear timer */
366 if (rc != bsock->msglen) {
369 bsock->b_errno = EIO;
371 bsock->b_errno = errno;
374 if (!bsock->suppress_error_msgs) {
375 Jmsg4(bsock->jcr, M_ERROR, 0, _("Write error sending to %s:%s:%d: ERR=%s\n"),
376 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
379 Jmsg5(bsock->jcr, M_ERROR, 0, _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
380 bsock->msglen, bsock->who, bsock->host, bsock->port, rc);
384 ASSERT(msglen == bsock->msglen);
389 * Establish an SSL connection -- server side
390 * Codes that ssl_need and ssl_has can take
391 * BNET_SSL_NONE I cannot do ssl
392 * BNET_SSL_OK I can do ssl, but it is not required on my end
393 * BNET_SSL_REQUIRED ssl is required on my end
396 bnet_ssl_server(BSOCK *bsock, char *password, int ssl_need, int ssl_has)
398 /* Check to see if what we need (ssl_need) corresponds to what he has (ssl_has) */
399 /* The other side expects a response from us */
404 * Establish an SSL connection -- client side
406 int bnet_ssl_client(BSOCK *bsock, char *password, int ssl_need)
408 /* We are the client so we must wait for the server to notify us */
414 * Wait for a specified time for data to appear on
415 * the BSOCK connection.
417 * Returns: 1 if data available
422 bnet_wait_data(BSOCK *bsock, int sec)
428 FD_SET(bsock->fd, &fdset);
432 switch(select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
433 case 0: /* timeout */
437 bsock->b_errno = errno;
438 if (errno == EINTR || errno == EAGAIN) {
441 return -1; /* error return */
450 * As above, but returns on interrupt
453 bnet_wait_data_intr(BSOCK *bsock, int sec)
459 FD_SET(bsock->fd, &fdset);
463 switch(select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
464 case 0: /* timeout */
468 bsock->b_errno = errno;
469 return -1; /* error return */
477 #ifndef NETDB_INTERNAL
478 #define NETDB_INTERNAL -1 /* See errno. */
480 #ifndef NETDB_SUCCESS
481 #define NETDB_SUCCESS 0 /* No problem. */
483 #ifndef HOST_NOT_FOUND
484 #define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found. */
487 #define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL. */
490 #define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP. */
493 #define NO_DATA 4 /* Valid name, no data record of requested type. */
496 extern int h_errno; /* On error has one of the above */
499 * Get human readable error for gethostbyname()
501 static char *gethost_strerror()
505 return strerror(errno);
507 return "No problem.";
509 return "Authoritative answer Host not found.";
511 return "Non-authoritative Host not found, or ServerFail.";
513 return "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.";
515 return "Valid name, no data record of resquested type.";
517 return "Unknown error.";
522 static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
525 * Convert a hostname or dotted IP address into
526 * a s_addr. We handle only IPv4.
528 static uint32_t *bget_host_ip(JCR *jcr, char *host)
530 struct in_addr inaddr;
531 uint32_t *addr_list; /* this really should be struct in_addr */
536 if ((inaddr.s_addr = inet_addr(host)) != INADDR_NONE) {
537 addr_list = (uint32_t *) malloc(sizeof(uint32_t) * 2);
538 addr_list[0] = inaddr.s_addr;
539 addr_list[1] = (uint32_t) -1;
542 if ((hp = gethostbyname(host)) == NULL) {
543 Jmsg2(jcr, M_ERROR, 0, "gethostbyname() for %s failed: ERR=%s\n",
544 host, gethost_strerror());
548 if (hp->h_length != sizeof(inaddr.s_addr) || hp->h_addrtype != AF_INET) {
549 Jmsg2(jcr, M_ERROR, 0, _("gethostbyname() network address length error.\n\
550 Wanted %d got %d bytes for s_addr.\n"), sizeof(inaddr.s_addr), hp->h_length);
555 for (p = hp->h_addr_list; *p != 0; p++) {
559 addr_list = (uint32_t *)malloc(sizeof(uint32_t) * i);
561 for (p = hp->h_addr_list; *p != 0; p++) {
562 addr_list[i++] = (*(struct in_addr **)p)->s_addr;
564 addr_list[i] = (uint32_t) -1;
571 * Open a TCP connection to the UPS network server
573 * Returns BSOCK * pointer on success
575 * ***FIXME*** implement service from /etc/services
578 bnet_open(JCR *jcr, char *name, char *host, char *service, int port, int *fatal)
581 struct sockaddr_in tcp_serv_addr; /* socket information */
583 int i, connected = 0;
587 * Fill in the structure serv_addr with the address of
588 * the server that we want to connect with.
590 memset((char *)&tcp_serv_addr, 0, sizeof(tcp_serv_addr));
591 tcp_serv_addr.sin_family = AF_INET;
592 tcp_serv_addr.sin_port = htons(port);
594 if ((addr_list=bget_host_ip(jcr, host)) == NULL) {
599 /* Open a TCP socket */
600 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
607 * Receive notification when connection dies.
609 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
610 Jmsg(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"), strerror(errno));
613 for (i = 0; addr_list[i] != ((uint32_t) -1); i++) {
614 /* connect to server */
615 tcp_serv_addr.sin_addr.s_addr = addr_list[i];
616 if (connect(sockfd, (struct sockaddr *)&tcp_serv_addr, sizeof(tcp_serv_addr)) < 0) {
628 return init_bsock(jcr, sockfd, name, host, port);
632 * Try to connect to host for max_retry_time at retry_time intervals.
635 bnet_connect(JCR *jcr, int retry_interval, int max_retry_time, char *name,
636 char *host, char *service, int port, int verbose)
642 for (i=0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL; i -= retry_interval) {
643 if (fatal || (jcr && job_canceled(jcr))) {
646 Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
647 name, host, port, strerror(errno));
649 i = 60 * 5; /* complain again in 5 minutes */
651 Jmsg(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
652 Retrying ...\n", name, host, port, strerror(errno));
654 bmicrosleep(retry_interval, 0);
655 max_retry_time -= retry_interval;
656 if (max_retry_time <= 0) {
657 Jmsg(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
658 name, host, port, strerror(errno));
667 * Return the string for the error that occurred
668 * on the socket. Only the first error is retained.
670 char *bnet_strerror(BSOCK *bsock)
672 return strerror(bsock->b_errno);
676 * Format and send a message
677 * Returns: 0 on failure
681 bnet_fsend(BSOCK *bs, char *fmt, ...)
686 if (bs->errors || bs->terminated) {
689 /* This probably won't work, but we vsnprintf, then if we
690 * get a negative length or a length greater than our buffer
691 * (depending on which library is used), the printf was truncated, so
692 * get a biger buffer and try again.
695 maxlen = sizeof_pool_memory(bs->msg) - 1;
696 va_start(arg_ptr, fmt);
697 bs->msglen = bvsnprintf(mp_chr(bs->msg), maxlen, fmt, arg_ptr);
699 if (bs->msglen < 0 || bs->msglen >= maxlen) {
700 bs->msg = realloc_pool_memory(bs->msg, maxlen + maxlen / 2);
703 return bnet_send(bs);
707 * Set the network buffer size, suggested size is in size.
708 * Actual size obtained is returned in bs->msglen
710 * Returns: 0 on failure
713 int bnet_set_buffer_size(BSOCK *bs, uint32_t size, int rw)
716 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
719 opt = IPTOS_THROUGHPUT;
720 setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t)&opt, sizeof(opt));
724 if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size+100)) == NULL) {
725 Jmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
728 if (rw & BNET_SETBUF_READ) {
729 while ((dbuf_size > TAPE_BSIZE) &&
730 (setsockopt(bs->fd, SOL_SOCKET, SO_RCVBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
731 Jmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
732 dbuf_size -= TAPE_BSIZE;
734 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
735 if (dbuf_size != MAX_NETWORK_BUFFER_SIZE)
736 Jmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
737 if (dbuf_size % TAPE_BSIZE != 0) {
738 Jmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
743 if (rw & BNET_SETBUF_WRITE) {
744 while ((dbuf_size > TAPE_BSIZE) &&
745 (setsockopt(bs->fd, SOL_SOCKET, SO_SNDBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
746 Jmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
747 dbuf_size -= TAPE_BSIZE;
749 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
750 if (dbuf_size != MAX_NETWORK_BUFFER_SIZE)
751 Jmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
752 if (dbuf_size % TAPE_BSIZE != 0) {
753 Jmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
758 bs->msglen = dbuf_size;
763 * Send a network "signal" to the other end
764 * This consists of sending a negative packet length
766 * Returns: 0 on failure
769 int bnet_sig(BSOCK *bs, int sig)
772 return bnet_send(bs);
776 * Convert a network "signal" code into
777 * human readable ASCII.
779 char *bnet_sig_to_ascii(BSOCK *bs)
782 switch (bs->msglen) {
784 return "BNET_EOD"; /* end of data stream */
786 return "BNET_EOD_POLL";
788 return "BNET_STATUS";
790 return "BNET_TERMINATE"; /* terminate connection */
794 return "BNET_HEARTBEAT";
795 case BNET_HB_RESPONSE:
796 return "BNET_HB_RESPONSE";
798 return "BNET_PROMPT";
800 sprintf(buf, "Unknown sig %d", bs->msglen);
806 /* Initialize internal socket structure.
807 * This probably should be done in net_open
810 init_bsock(JCR *jcr, int sockfd, char *who, char *host, int port)
812 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
813 memset(bsock, 0, sizeof(BSOCK));
816 bsock->msg = get_pool_memory(PM_MESSAGE);
817 bsock->errmsg = get_pool_memory(PM_MESSAGE);
818 bsock->who = bstrdup(who);
819 bsock->host = bstrdup(host);
822 * ****FIXME**** reduce this to a few hours once
823 * heartbeats are implemented
825 bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */
831 dup_bsock(BSOCK *osock)
833 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
834 memcpy(bsock, osock, sizeof(BSOCK));
835 bsock->msg = get_pool_memory(PM_MESSAGE);
836 bsock->errmsg = get_pool_memory(PM_MESSAGE);
838 bsock->who = bstrdup(osock->who);
841 bsock->host = bstrdup(osock->host);
847 /* Close the network connection */
849 bnet_close(BSOCK *bsock)
853 for ( ; bsock != NULL; bsock = next) {
856 if (bsock->timed_out) {
857 shutdown(bsock->fd, 2); /* discard any pending I/O */
859 close(bsock->fd); /* normal close */
867 term_bsock(BSOCK *bsock)
870 free_pool_memory(bsock->msg);
873 ASSERT(1==0); /* double close */
876 free_pool_memory(bsock->errmsg);
877 bsock->errmsg = NULL;