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 mp_chr(bsock->msg)[0] = 0;
151 if (bsock->errors || bsock->terminated) {
155 bsock->read_seqno++; /* bump sequence number */
156 bsock->timer_start = watchdog_time; /* set start wait time */
157 bsock->timed_out = 0;
158 /* get data size -- in int32_t */
159 if ((nbytes = read_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
160 bsock->timer_start = 0; /* clear timer */
161 /* probably pipe broken because client died */
163 bsock->b_errno = ENODATA;
165 bsock->b_errno = errno;
168 return BNET_HARDEOF; /* assume hard EOF received */
170 bsock->timer_start = 0; /* clear timer */
171 if (nbytes != sizeof(int32_t)) {
173 bsock->b_errno = EIO;
174 Jmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"), pktsiz, nbytes,
175 bsock->who, bsock->host, bsock->port);
179 pktsiz = ntohl(pktsiz); /* decode no. of bytes that follow */
181 if (pktsiz == 0) { /* No data transferred */
182 bsock->timer_start = 0; /* clear timer */
185 return 0; /* zero bytes read */
188 /* If signal or packet size too big */
189 if (pktsiz < 0 || pktsiz > 1000000) {
190 if (pktsiz > 0) { /* if packet too big */
191 Jmsg3(bsock->jcr, M_FATAL, 0,
192 _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
193 bsock->who, bsock->host, bsock->port);
194 pktsiz = BNET_TERMINATE; /* hang up */
196 if (pktsiz == BNET_TERMINATE) {
197 bsock->terminated = 1;
199 bsock->timer_start = 0; /* clear timer */
200 bsock->b_errno = ENODATA;
201 bsock->msglen = pktsiz; /* signal code */
202 return BNET_SIGNAL; /* signal */
205 /* Make sure the buffer is big enough + one byte for EOS */
206 if (pktsiz >= (int32_t)sizeof_pool_memory(bsock->msg)) {
207 bsock->msg = realloc_pool_memory(bsock->msg, pktsiz + 100);
210 bsock->timer_start = watchdog_time; /* set start wait time */
211 bsock->timed_out = 0;
212 /* now read the actual data */
213 if ((nbytes = read_nbytes(bsock, mp_chr(bsock->msg), pktsiz)) <= 0) {
214 bsock->timer_start = 0; /* clear timer */
216 bsock->b_errno = ENODATA;
218 bsock->b_errno = errno;
221 Jmsg4(bsock->jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
222 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
225 bsock->timer_start = 0; /* clear timer */
227 bsock->msglen = nbytes;
228 if (nbytes != pktsiz) {
229 bsock->b_errno = EIO;
231 Jmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"), pktsiz, nbytes,
232 bsock->who, bsock->host, bsock->port);
235 /* always add a zero by to properly terminate any
236 * string that was send to us. Note, we ensured above that the
237 * buffer is at least one byte longer than the message length.
239 mp_chr(bsock->msg)[nbytes] = 0; /* terminate in case it is a string */
240 sm_check(__FILE__, __LINE__, False);
241 return nbytes; /* return actual length of message */
246 * Return 1 if there are errors on this bsock or it is closed,
247 * i.e. stop communicating on this line.
249 int is_bnet_stop(BSOCK *bsock)
251 return bsock->errors || bsock->terminated;
255 * Return number of errors on socket
257 int is_bnet_error(BSOCK *bsock)
259 return bsock->errors;
263 * Call here after error during closing to suppress error
264 * messages which are due to the other end shutting down too.
267 bnet_suppress_error_messages(BSOCK *bsock, int flag)
269 bsock->suppress_error_msgs = flag;
274 * Transmit spooled data now
276 int bnet_despool(BSOCK *bsock)
281 rewind(bsock->spool_fd);
282 while (fread((char *)&pktsiz, 1, sizeof(int32_t), bsock->spool_fd) == sizeof(int32_t)) {
283 bsock->msglen = ntohl(pktsiz);
284 if (bsock->msglen > 0) {
285 if (bsock->msglen > (int32_t)sizeof_pool_memory(bsock->msg)) {
286 bsock->msg = realloc_pool_memory(bsock->msg, bsock->msglen);
288 nbytes = fread(bsock->msg, 1, bsock->msglen, bsock->spool_fd);
289 if (nbytes != (size_t)bsock->msglen) {
290 Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, bsock->msglen);
291 Jmsg1(bsock->jcr, M_ERROR, 0, _("fread error. ERR=%s\n"), strerror(errno));
297 if (ferror(bsock->spool_fd)) {
298 Jmsg1(bsock->jcr, M_ERROR, 0, _("fread error. ERR=%s\n"), strerror(errno));
306 * Send a message over the network. The send consists of
307 * two network packets. The first is sends a 32 bit integer containing
308 * the length of the data packet which follows.
310 * Returns: 0 on failure
314 bnet_send(BSOCK *bsock)
320 if (bsock->errors || bsock->terminated) {
323 msglen = bsock->msglen;
324 ASSERT(bsock->msglen < 1000000);
325 pktsiz = htonl((int32_t)bsock->msglen);
326 /* send int32_t containing size of data packet */
327 bsock->timer_start = watchdog_time; /* start timer */
328 bsock->timed_out = 0;
329 rc = write_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t));
330 bsock->timer_start = 0; /* clear timer */
331 if (rc != sizeof(int32_t)) {
332 if (bsock->msglen == BNET_TERMINATE) { /* if we were terminating */
333 bsock->terminated = 1;
334 return 0; /* ignore any errors */
338 bsock->b_errno = EIO;
340 bsock->b_errno = errno;
343 if (!bsock->suppress_error_msgs && !bsock->timed_out) {
344 Jmsg4(bsock->jcr, M_ERROR, 0, _("Write error sending to %s:%s:%d: ERR=%s\n"),
345 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
348 Jmsg5(bsock->jcr, M_ERROR, 0, _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
349 bsock->who, bsock->host, bsock->port, bsock->msglen, rc);
354 bsock->out_msg_no++; /* increment message number */
355 if (bsock->msglen <= 0) { /* length only? */
356 ASSERT(msglen == bsock->msglen);
357 return 1; /* yes, no data */
360 /* send data packet */
361 bsock->timer_start = watchdog_time; /* start timer */
362 bsock->timed_out = 0;
363 rc = write_nbytes(bsock, mp_chr(bsock->msg), bsock->msglen);
364 bsock->timer_start = 0; /* clear timer */
365 if (rc != bsock->msglen) {
368 bsock->b_errno = EIO;
370 bsock->b_errno = errno;
373 if (!bsock->suppress_error_msgs) {
374 Jmsg4(bsock->jcr, M_ERROR, 0, _("Write error sending to %s:%s:%d: ERR=%s\n"),
375 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
378 Jmsg5(bsock->jcr, M_ERROR, 0, _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
379 bsock->msglen, bsock->who, bsock->host, bsock->port, rc);
383 ASSERT(msglen == bsock->msglen);
388 * Establish an SSL connection -- server side
389 * Codes that ssl_need and ssl_has can take
390 * BNET_SSL_NONE I cannot do ssl
391 * BNET_SSL_OK I can do ssl, but it is not required on my end
392 * BNET_SSL_REQUIRED ssl is required on my end
395 bnet_ssl_server(BSOCK *bsock, char *password, int ssl_need, int ssl_has)
397 /* Check to see if what we need (ssl_need) corresponds to what he has (ssl_has) */
398 /* The other side expects a response from us */
403 * Establish an SSL connection -- client side
405 int bnet_ssl_client(BSOCK *bsock, char *password, int ssl_need)
407 /* We are the client so we must wait for the server to notify us */
413 * Wait for a specified time for data to appear on
414 * the BSOCK connection.
416 * Returns: 1 if data available
421 bnet_wait_data(BSOCK *bsock, int sec)
427 FD_SET(bsock->fd, &fdset);
431 switch(select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
432 case 0: /* timeout */
436 bsock->b_errno = errno;
437 if (errno == EINTR || errno == EAGAIN) {
440 return -1; /* error return */
449 * As above, but returns on interrupt
452 bnet_wait_data_intr(BSOCK *bsock, int sec)
458 FD_SET(bsock->fd, &fdset);
462 switch(select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
463 case 0: /* timeout */
467 bsock->b_errno = errno;
468 return -1; /* error return */
477 static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
480 * Convert a hostname or dotted IP address into
481 * a s_addr. We handle only IPv4.
483 static uint32_t *bget_host_ip(JCR *jcr, char *host)
485 struct in_addr inaddr;
486 uint32_t *addr_list; /* this really should be struct in_addr */
491 if ((inaddr.s_addr = inet_addr(host)) != INADDR_NONE) {
492 addr_list = (uint32_t *) malloc(sizeof(uint32_t) * 2);
493 addr_list[0] = inaddr.s_addr;
494 addr_list[1] = (uint32_t) -1;
497 if ((hp = gethostbyname(host)) == NULL) {
498 Jmsg2(jcr, M_ERROR, 0, "gethostbyname() for %s failed: ERR=%s\n",
499 host, strerror(errno));
503 if (hp->h_length != sizeof(inaddr.s_addr) || hp->h_addrtype != AF_INET) {
504 Jmsg2(jcr, M_ERROR, 0, _("gethostbyname() network address length error.\n\
505 Wanted %d got %d bytes for s_addr.\n"), sizeof(inaddr.s_addr), hp->h_length);
510 for (p = hp->h_addr_list; *p != 0; p++) {
514 addr_list = (uint32_t *) malloc(sizeof(uint32_t) * i);
516 for (p = hp->h_addr_list; *p != 0; p++) {
517 addr_list[i++] = (*(struct in_addr **)p)->s_addr;
519 addr_list[i] = (uint32_t) -1;
526 * Open a TCP connection to the UPS network server
528 * Returns BSOCK * pointer on success
530 * ***FIXME*** implement service from /etc/services
533 bnet_open(JCR *jcr, char *name, char *host, char *service, int port, int *fatal)
536 struct sockaddr_in tcp_serv_addr; /* socket information */
538 int i, connected = 0;
542 * Fill in the structure serv_addr with the address of
543 * the server that we want to connect with.
545 memset((char *)&tcp_serv_addr, 0, sizeof(tcp_serv_addr));
546 tcp_serv_addr.sin_family = AF_INET;
547 tcp_serv_addr.sin_port = htons(port);
549 if ((addr_list=bget_host_ip(jcr, host)) == NULL) {
554 /* Open a TCP socket */
555 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
562 * Receive notification when connection dies.
564 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
565 Jmsg(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"), strerror(errno));
568 for (i = 0; addr_list[i] != ((uint32_t) -1); i++) {
569 /* connect to server */
570 tcp_serv_addr.sin_addr.s_addr = addr_list[i];
571 if (connect(sockfd, (struct sockaddr *)&tcp_serv_addr, sizeof(tcp_serv_addr)) < 0) {
583 return init_bsock(jcr, sockfd, name, host, port);
587 * Try to connect to host for max_retry_time at retry_time intervals.
590 bnet_connect(JCR *jcr, int retry_interval, int max_retry_time, char *name,
591 char *host, char *service, int port, int verbose)
597 for (i=0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL; i -= retry_interval) {
598 if (fatal || (jcr && job_canceled(jcr))) {
601 Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
602 name, host, port, strerror(errno));
604 i = 60 * 5; /* complain again in 5 minutes */
606 Jmsg(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
607 Retrying ...\n", name, host, port, strerror(errno));
609 bmicrosleep(retry_interval, 0);
610 max_retry_time -= retry_interval;
611 if (max_retry_time <= 0) {
612 Jmsg(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
613 name, host, port, strerror(errno));
622 * Return the string for the error that occurred
623 * on the socket. Only the first error is retained.
625 char *bnet_strerror(BSOCK *bsock)
627 return strerror(bsock->b_errno);
631 * Format and send a message
632 * Returns: 0 on failure
636 bnet_fsend(BSOCK *bs, char *fmt, ...)
641 /* This probably won't work, but we vsnprintf, then if we
642 * get a negative length or a length greater than our buffer
643 * (depending on which library is used), the printf was truncated, so
644 * get a biger buffer and try again.
647 maxlen = sizeof_pool_memory(bs->msg) - 1;
648 va_start(arg_ptr, fmt);
649 bs->msglen = bvsnprintf(mp_chr(bs->msg), maxlen, fmt, arg_ptr);
651 if (bs->msglen < 0 || bs->msglen >= maxlen) {
652 bs->msg = realloc_pool_memory(bs->msg, maxlen + 200);
655 return bnet_send(bs) < 0 ? 0 : 1;
659 * Set the network buffer size, suggested size is in size.
660 * Actual size obtained is returned in bs->msglen
662 * Returns: 0 on failure
665 int bnet_set_buffer_size(BSOCK *bs, uint32_t size, int rw)
668 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
671 opt = IPTOS_THROUGHPUT;
672 setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t)&opt, sizeof(opt));
676 if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size+100)) == NULL) {
677 Jmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
680 if (rw & BNET_SETBUF_READ) {
681 while ((dbuf_size > TAPE_BSIZE) &&
682 (setsockopt(bs->fd, SOL_SOCKET, SO_RCVBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
683 Jmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
684 dbuf_size -= TAPE_BSIZE;
686 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
687 if (dbuf_size != MAX_NETWORK_BUFFER_SIZE)
688 Jmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
689 if (dbuf_size % TAPE_BSIZE != 0) {
690 Jmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
695 if (rw & BNET_SETBUF_WRITE) {
696 while ((dbuf_size > TAPE_BSIZE) &&
697 (setsockopt(bs->fd, SOL_SOCKET, SO_SNDBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
698 Jmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
699 dbuf_size -= TAPE_BSIZE;
701 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
702 if (dbuf_size != MAX_NETWORK_BUFFER_SIZE)
703 Jmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
704 if (dbuf_size % TAPE_BSIZE != 0) {
705 Jmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
710 bs->msglen = dbuf_size;
715 * Send a network "signal" to the other end
716 * This consists of sending a negative packet length
718 * Returns: 0 on failure
721 int bnet_sig(BSOCK *bs, int sig)
724 return bnet_send(bs);
728 * Convert a network "signal" code into
729 * human readable ASCII.
731 char *bnet_sig_to_ascii(BSOCK *bs)
734 switch (bs->msglen) {
736 return "BNET_EOD"; /* end of data stream */
738 return "BNET_EOD_POLL";
740 return "BNET_STATUS";
742 return "BNET_TERMINATE"; /* terminate connection */
746 return "BNET_HEARTBEAT";
747 case BNET_HB_RESPONSE:
748 return "BNET_HB_RESPONSE";
750 return "BNET_PROMPT";
752 sprintf(buf, "Unknown sig %d", bs->msglen);
758 /* Initialize internal socket structure.
759 * This probably should be done in net_open
762 init_bsock(JCR *jcr, int sockfd, char *who, char *host, int port)
764 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
765 memset(bsock, 0, sizeof(BSOCK));
768 bsock->msg = get_pool_memory(PM_MESSAGE);
769 bsock->errmsg = get_pool_memory(PM_MESSAGE);
770 bsock->who = bstrdup(who);
771 bsock->host = bstrdup(host);
774 * ****FIXME**** reduce this to a few hours once
775 * heartbeats are implemented
777 bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */
783 dup_bsock(BSOCK *osock)
785 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
786 memcpy(bsock, osock, sizeof(BSOCK));
787 bsock->msg = get_pool_memory(PM_MESSAGE);
788 bsock->errmsg = get_pool_memory(PM_MESSAGE);
790 bsock->who = bstrdup(osock->who);
793 bsock->host = bstrdup(osock->host);
799 /* Close the network connection */
801 bnet_close(BSOCK *bsock)
805 for ( ; bsock != NULL; bsock = next) {
808 if (bsock->timed_out) {
809 shutdown(bsock->fd, 2); /* discard any pending I/O */
811 close(bsock->fd); /* normal close */
819 term_bsock(BSOCK *bsock)
822 free_pool_memory(bsock->msg);
825 ASSERT(1==0); /* double close */
828 free_pool_memory(bsock->errmsg);
829 bsock->errmsg = NULL;