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 */
47 * Read a nbytes from the network.
48 * It is possible that the total bytes require in several
52 static int32_t read_nbytes(BSOCK *bsock, char *ptr, int32_t nbytes)
60 nread = read(bsock->fd, ptr, nleft);
61 } while (!bsock->timed_out && nread == -1 && (errno == EINTR || errno == EAGAIN));
63 return nread; /* error, or EOF */
68 return nbytes - nleft; /* return >= 0 */
72 * Write nbytes to the network.
73 * It may require several writes.
76 static int32_t write_nbytes(BSOCK *bsock, char *ptr, int32_t nbytes)
78 int32_t nleft, nwritten;
81 nwritten = fwrite(ptr, 1, nbytes, bsock->spool_fd);
82 if (nwritten != nbytes) {
83 Jmsg1(bsock->jcr, M_ERROR, 0, _("Spool write error. ERR=%s\n"), strerror(errno));
84 Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes);
93 nwritten = write(bsock->fd, ptr, nleft);
94 } while (!bsock->timed_out && nwritten == -1 && (errno == EINTR || errno == EAGAIN));
96 return nwritten; /* error */
105 * Receive a message from the other end. Each message consists of
106 * two packets. The first is a header that contains the size
107 * of the data that follows in the second packet.
108 * Returns number of bytes read (may return zero)
109 * Returns -1 on signal (BNET_SIGNAL)
110 * Returns -2 on hard end of file (BNET_HARDEOF)
111 * Returns -3 on error (BNET_ERROR)
113 * Unfortunately, it is a bit complicated because we have these
116 * 2. Signal including end of data stream
117 * 3. Hard end of file
119 * Using is_bnet_stop() and is_bnet_error() you can figure this all out.
121 int32_t bnet_recv(BSOCK *bsock)
127 if (bsock->errors || bsock->terminated) {
131 bsock->read_seqno++; /* bump sequence number */
132 bsock->timer_start = watchdog_time; /* set start wait time */
133 bsock->timed_out = 0;
134 /* get data size -- in int32_t */
135 if ((nbytes = read_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
136 bsock->timer_start = 0; /* clear timer */
137 /* probably pipe broken because client died */
139 bsock->b_errno = ENODATA;
141 bsock->b_errno = errno;
144 return BNET_HARDEOF; /* assume hard EOF received */
146 bsock->timer_start = 0; /* clear timer */
147 if (nbytes != sizeof(int32_t)) {
149 bsock->b_errno = EIO;
150 Jmsg3(bsock->jcr, M_ERROR, 0, _("Read %d expected %d from %s\n"), nbytes, sizeof(int32_t),
155 pktsiz = ntohl(pktsiz); /* decode no. of bytes that follow */
157 if (pktsiz == 0) { /* No data transferred */
158 bsock->timer_start = 0; /* clear timer */
161 return 0; /* zero bytes read */
164 /* If signal or packet size too big */
165 if (pktsiz < 0 || pktsiz > 1000000) {
166 if (pktsiz > 0) { /* if packet too big */
167 pktsiz = BNET_TERMINATE; /* hang up */
169 if (pktsiz == BNET_TERMINATE) {
170 bsock->terminated = 1;
172 bsock->timer_start = 0; /* clear timer */
173 bsock->b_errno = ENODATA;
174 bsock->msglen = pktsiz; /* signal code */
175 return BNET_SIGNAL; /* signal */
178 /* Make sure the buffer is big enough + one byte for EOS */
179 if (pktsiz >= (int32_t)sizeof_pool_memory(bsock->msg)) {
180 bsock->msg = realloc_pool_memory(bsock->msg, pktsiz + 100);
183 bsock->timer_start = watchdog_time; /* set start wait time */
184 bsock->timed_out = 0;
185 /* now read the actual data */
186 if ((nbytes = read_nbytes(bsock, bsock->msg, pktsiz)) <= 0) {
187 bsock->timer_start = 0; /* clear timer */
189 bsock->b_errno = ENODATA;
191 bsock->b_errno = errno;
194 Jmsg4(bsock->jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
195 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
198 bsock->timer_start = 0; /* clear timer */
200 bsock->msglen = nbytes;
201 if (nbytes != pktsiz) {
202 bsock->b_errno = EIO;
204 Jmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"), pktsiz, nbytes,
205 bsock->who, bsock->host, bsock->port);
208 /* always add a zero by to properly terminate any
209 * string that was send to us. Note, we ensured above that the
210 * buffer is at least one byte longer than the message length.
212 bsock->msg[nbytes] = 0; /* terminate in case it is a string */
213 sm_check(__FILE__, __LINE__, False);
214 return nbytes; /* return actual length of message */
219 * Return 1 if there are errors on this bsock or it is closed,
220 * i.e. stop communicating on this line.
222 int is_bnet_stop(BSOCK *bsock)
224 return bsock->errors || bsock->terminated;
228 * Return number of errors on socket
230 int is_bnet_error(BSOCK *bsock)
232 return bsock->errors;
236 * Call here after error during closing to suppress error
237 * messages which are due to the other end shutting down too.
240 bnet_suppress_error_messages(BSOCK *bsock, int flag)
242 bsock->suppress_error_msgs = flag;
247 * Transmit spooled data now
249 int bnet_despool(BSOCK *bsock)
254 rewind(bsock->spool_fd);
255 while (fread((char *)&pktsiz, 1, sizeof(int32_t), bsock->spool_fd) == sizeof(int32_t)) {
256 bsock->msglen = ntohl(pktsiz);
257 if (bsock->msglen > 0) {
258 if (bsock->msglen > (int32_t)sizeof_pool_memory(bsock->msg)) {
259 bsock->msg = realloc_pool_memory(bsock->msg, bsock->msglen);
261 nbytes = fread(bsock->msg, 1, bsock->msglen, bsock->spool_fd);
262 if (nbytes != (size_t)bsock->msglen) {
263 Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, bsock->msglen);
264 Jmsg1(bsock->jcr, M_ERROR, 0, _("fread error. ERR=%s\n"), strerror(errno));
270 if (ferror(bsock->spool_fd)) {
271 Jmsg1(bsock->jcr, M_ERROR, 0, _("fread error. ERR=%s\n"), strerror(errno));
279 * Send a message over the network. The send consists of
280 * two network packets. The first is sends a 32 bit integer containing
281 * the length of the data packet which follows.
283 * Returns: 0 on failure
287 bnet_send(BSOCK *bsock)
292 if (bsock->errors || bsock->terminated) {
295 pktsiz = htonl((int32_t)bsock->msglen);
296 /* send int32_t containing size of data packet */
297 bsock->timer_start = watchdog_time; /* start timer */
298 bsock->timed_out = 0;
299 rc = write_nbytes(bsock, (char *)&pktsiz, sizeof(int32_t));
300 bsock->timer_start = 0; /* clear timer */
301 if (rc != sizeof(int32_t)) {
302 if (bsock->msglen == BNET_TERMINATE) { /* if we were terminating */
303 bsock->terminated = 1;
304 return 0; /* ignore any errors */
308 bsock->b_errno = EIO;
310 bsock->b_errno = errno;
313 if (!bsock->suppress_error_msgs) {
314 Jmsg4(bsock->jcr, M_ERROR, 0, _("Write error sending to %s:%s:%d: ERR=%s\n"),
315 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
318 Jmsg5(bsock->jcr, M_ERROR, 0, _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
319 bsock->who, bsock->host, bsock->port, bsock->msglen, rc);
324 bsock->out_msg_no++; /* increment message number */
325 if (bsock->msglen <= 0) { /* length only? */
326 return 1; /* yes, no data */
329 /* send data packet */
330 bsock->timer_start = watchdog_time; /* start timer */
331 bsock->timed_out = 0;
332 rc = write_nbytes(bsock, bsock->msg, bsock->msglen);
333 bsock->timer_start = 0; /* clear timer */
334 if (rc != bsock->msglen) {
337 bsock->b_errno = EIO;
339 bsock->b_errno = errno;
342 if (!bsock->suppress_error_msgs) {
343 Jmsg4(bsock->jcr, M_ERROR, 0, _("Write error sending to %s:%s:%d: ERR=%s\n"),
344 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
347 Jmsg5(bsock->jcr, M_ERROR, 0, _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
348 bsock->msglen, bsock->who, bsock->host, bsock->port, rc);
356 * Establish an SSL connection -- server side
357 * Codes that ssl_need and ssl_has can take
358 * BNET_SSL_NONE I cannot do ssl
359 * BNET_SSL_OK I can do ssl, but it is not required on my end
360 * BNET_SSL_REQUIRED ssl is required on my end
363 bnet_ssl_server(BSOCK *bsock, char *password, int ssl_need, int ssl_has)
365 /* Check to see if what we need (ssl_need) corresponds to what he has (ssl_has) */
366 /* The other side expects a response from us */
371 * Establish an SSL connection -- client side
373 int bnet_ssl_client(BSOCK *bsock, char *password, int ssl_need)
375 /* We are the client so we must wait for the server to notify us */
381 * Wait for a specified time for data to appear on
382 * the BSOCK connection.
384 * Returns: 1 if data available
389 bnet_wait_data(BSOCK *bsock, int sec)
395 FD_SET(bsock->fd, &fdset);
399 switch(select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
400 case 0: /* timeout */
404 bsock->b_errno = errno;
405 if (errno == EINTR || errno == EAGAIN) {
408 return -1; /* error return */
417 * As above, but returns on interrupt
420 bnet_wait_data_intr(BSOCK *bsock, int sec)
426 FD_SET(bsock->fd, &fdset);
430 switch(select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
431 case 0: /* timeout */
435 bsock->b_errno = errno;
436 return -1; /* error return */
445 static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
448 * Convert a hostname or dotted IP address into
449 * a s_addr. We handle only IPv4.
451 static uint32_t *bget_host_ip(JCR *jcr, char *host)
453 struct in_addr inaddr;
454 uint32_t *addr_list; /* this really should be struct in_addr */
459 if ((inaddr.s_addr = inet_addr(host)) != INADDR_NONE) {
460 addr_list = (uint32_t *) malloc(sizeof(uint32_t) * 2);
461 addr_list[0] = inaddr.s_addr;
462 addr_list[1] = (uint32_t) -1;
465 if ((hp = gethostbyname(host)) == NULL) {
466 Jmsg2(jcr, M_ERROR, 0, "gethostbyname() for %s failed: ERR=%s\n",
467 host, strerror(errno));
471 if (hp->h_length != sizeof(inaddr.s_addr) || hp->h_addrtype != AF_INET) {
472 Jmsg2(jcr, M_ERROR, 0, _("gethostbyname() network address length error.\n\
473 Wanted %d got %d bytes for s_addr.\n"), sizeof(inaddr.s_addr), hp->h_length);
478 for (p = hp->h_addr_list; *p != 0; p++) {
482 addr_list = (uint32_t *) malloc(sizeof(uint32_t) * i);
484 for (p = hp->h_addr_list; *p != 0; p++) {
485 addr_list[i++] = (*(struct in_addr **)p)->s_addr;
487 addr_list[i] = (uint32_t) -1;
494 * Open a TCP connection to the UPS network server
496 * Returns BSOCK * pointer on success
498 * ***FIXME*** implement service from /etc/services
501 bnet_open(JCR *jcr, char *name, char *host, char *service, int port, int *fatal)
504 struct sockaddr_in tcp_serv_addr; /* socket information */
506 int i, connected = 0;
510 * Fill in the structure serv_addr with the address of
511 * the server that we want to connect with.
513 memset((char *)&tcp_serv_addr, 0, sizeof(tcp_serv_addr));
514 tcp_serv_addr.sin_family = AF_INET;
515 tcp_serv_addr.sin_port = htons(port);
517 if ((addr_list=bget_host_ip(jcr, host)) == NULL) {
522 /* Open a TCP socket */
523 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
530 * Receive notification when connection dies.
532 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
533 Jmsg(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"), strerror(errno));
536 for (i = 0; addr_list[i] != ((uint32_t) -1); i++) {
537 /* connect to server */
538 tcp_serv_addr.sin_addr.s_addr = addr_list[i];
539 if (connect(sockfd, (struct sockaddr *)&tcp_serv_addr, sizeof(tcp_serv_addr)) < 0) {
551 return init_bsock(jcr, sockfd, name, host, port);
555 * Try to connect to host for max_retry_time at retry_time intervals.
558 bnet_connect(JCR *jcr, int retry_interval, int max_retry_time, char *name,
559 char *host, char *service, int port, int verbose)
565 for (i=0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL; i -= retry_interval) {
566 if (fatal || (jcr && job_canceled(jcr))) {
569 Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
570 name, host, port, strerror(errno));
572 i = 60 * 5; /* complain again in 5 minutes */
574 Jmsg(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
575 Retrying ...\n", name, host, port, strerror(errno));
577 bmicrosleep(retry_interval, 0);
578 max_retry_time -= retry_interval;
579 if (max_retry_time <= 0) {
580 Jmsg(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
581 name, host, port, strerror(errno));
590 * Return the string for the error that occurred
591 * on the socket. Only the first error is retained.
593 char *bnet_strerror(BSOCK *bsock)
595 return strerror(bsock->b_errno);
599 * Format and send a message
600 * Returns: 0 on failure
604 bnet_fsend(BSOCK *bs, char *fmt, ...)
609 /* This probably won't work, but we vsnprintf, then if we
610 * get a negative length or a length greater than our buffer
611 * (depending on which library is used), the printf was truncated, so
612 * get a biger buffer and try again.
615 maxlen = sizeof_pool_memory(bs->msg) - 1;
616 va_start(arg_ptr, fmt);
617 bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
619 if (bs->msglen < 0 || bs->msglen >= maxlen) {
620 bs->msg = realloc_pool_memory(bs->msg, maxlen + 200);
623 return bnet_send(bs) < 0 ? 0 : 1;
627 * Set the network buffer size, suggested size is in size.
628 * Actual size obtained is returned in bs->msglen
630 * Returns: 0 on failure
633 int bnet_set_buffer_size(BSOCK *bs, uint32_t size, int rw)
636 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
639 opt = IPTOS_THROUGHPUT;
640 setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t)&opt, sizeof(opt));
644 if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size+100)) == NULL) {
645 Jmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
648 if (rw & BNET_SETBUF_READ) {
649 while ((dbuf_size > TAPE_BSIZE) &&
650 (setsockopt(bs->fd, SOL_SOCKET, SO_RCVBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
651 Jmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
652 dbuf_size -= TAPE_BSIZE;
654 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
655 if (dbuf_size != MAX_NETWORK_BUFFER_SIZE)
656 Jmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
657 if (dbuf_size % TAPE_BSIZE != 0) {
658 Jmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
663 if (rw & BNET_SETBUF_WRITE) {
664 while ((dbuf_size > TAPE_BSIZE) &&
665 (setsockopt(bs->fd, SOL_SOCKET, SO_SNDBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
666 Jmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
667 dbuf_size -= TAPE_BSIZE;
669 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
670 if (dbuf_size != MAX_NETWORK_BUFFER_SIZE)
671 Jmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
672 if (dbuf_size % TAPE_BSIZE != 0) {
673 Jmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
678 bs->msglen = dbuf_size;
683 * Send a network "signal" to the other end
684 * This consists of sending a negative packet length
686 * Returns: 0 on failure
689 int bnet_sig(BSOCK *bs, int sig)
692 return bnet_send(bs);
696 * Convert a network "signal" code into
697 * human readable ASCII.
699 char *bnet_sig_to_ascii(BSOCK *bs)
702 switch (bs->msglen) {
704 return "BNET_EOD"; /* end of data stream */
706 return "BNET_EOD_POLL";
708 return "BNET_STATUS";
710 return "BNET_TERMINATE"; /* terminate connection */
714 return "BNET_HEARTBEAT";
715 case BNET_HB_RESPONSE:
716 return "BNET_HB_RESPONSE";
718 return "BNET_PROMPT";
720 sprintf(buf, "Unknown sig %d", bs->msglen);
726 /* Initialize internal socket structure.
727 * This probably should be done in net_open
730 init_bsock(JCR *jcr, int sockfd, char *who, char *host, int port)
732 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
733 memset(bsock, 0, sizeof(BSOCK));
736 bsock->msg = get_pool_memory(PM_MESSAGE);
737 bsock->errmsg = get_pool_memory(PM_MESSAGE);
738 bsock->who = bstrdup(who);
739 bsock->host = bstrdup(host);
742 * ****FIXME**** reduce this to a few hours once
743 * heartbeats are implemented
745 bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */
751 dup_bsock(BSOCK *osock)
753 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
754 memcpy(bsock, osock, sizeof(BSOCK));
755 bsock->msg = get_pool_memory(PM_MESSAGE);
756 bsock->errmsg = get_pool_memory(PM_MESSAGE);
758 bsock->who = bstrdup(osock->who);
761 bsock->host = bstrdup(osock->host);
767 /* Close the network connection */
769 bnet_close(BSOCK *bsock)
773 for ( ; bsock != NULL; bsock = next) {
784 term_bsock(BSOCK *bsock)
787 free_pool_memory(bsock->msg);
790 ASSERT(1==0); /* double close */
793 free_pool_memory(bsock->errmsg);
794 bsock->errmsg = NULL;