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(void *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(void *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(void *vjcr, int retry_interval, int max_retry_time, char *name,
559 char *host, char *service, int port, int verbose)
563 JCR *jcr = (JCR *)vjcr;
566 for (i=0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL; i -= retry_interval) {
567 if (fatal || (jcr && job_canceled(jcr))) {
570 Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
571 name, host, port, strerror(errno));
573 i = 60 * 5; /* complain again in 5 minutes */
575 Jmsg(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
576 Retrying ...\n", name, host, port, strerror(errno));
578 bmicrosleep(retry_interval, 0);
579 max_retry_time -= retry_interval;
580 if (max_retry_time <= 0) {
581 Jmsg(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
582 name, host, port, strerror(errno));
591 * Return the string for the error that occurred
592 * on the socket. Only the first error is retained.
594 char *bnet_strerror(BSOCK *bsock)
596 return strerror(bsock->b_errno);
600 * Format and send a message
601 * Returns: 0 on failure
605 bnet_fsend(BSOCK *bs, char *fmt, ...)
610 /* This probably won't work, but we vsnprintf, then if we
611 * get a negative length or a length greater than our buffer
612 * (depending on which library is used), the printf was truncated, so
613 * get a biger buffer and try again.
616 maxlen = sizeof_pool_memory(bs->msg) - 1;
617 va_start(arg_ptr, fmt);
618 bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
620 if (bs->msglen < 0 || bs->msglen >= maxlen) {
621 bs->msg = realloc_pool_memory(bs->msg, maxlen + 200);
624 return bnet_send(bs) < 0 ? 0 : 1;
628 * Set the network buffer size, suggested size is in size.
629 * Actual size obtained is returned in bs->msglen
631 * Returns: 0 on failure
634 int bnet_set_buffer_size(BSOCK *bs, uint32_t size, int rw)
637 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
640 opt = IPTOS_THROUGHPUT;
641 setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t)&opt, sizeof(opt));
645 if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size+100)) == NULL) {
646 Jmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
649 if (rw & BNET_SETBUF_READ) {
650 while ((dbuf_size > TAPE_BSIZE) &&
651 (setsockopt(bs->fd, SOL_SOCKET, SO_RCVBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
652 Jmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
653 dbuf_size -= TAPE_BSIZE;
655 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
656 if (dbuf_size != MAX_NETWORK_BUFFER_SIZE)
657 Jmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
658 if (dbuf_size % TAPE_BSIZE != 0) {
659 Jmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
664 if (rw & BNET_SETBUF_WRITE) {
665 while ((dbuf_size > TAPE_BSIZE) &&
666 (setsockopt(bs->fd, SOL_SOCKET, SO_SNDBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
667 Jmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
668 dbuf_size -= TAPE_BSIZE;
670 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
671 if (dbuf_size != MAX_NETWORK_BUFFER_SIZE)
672 Jmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
673 if (dbuf_size % TAPE_BSIZE != 0) {
674 Jmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
679 bs->msglen = dbuf_size;
684 * Send a network "signal" to the other end
685 * This consists of sending a negative packet length
687 * Returns: 0 on failure
690 int bnet_sig(BSOCK *bs, int sig)
693 return bnet_send(bs);
697 * Convert a network "signal" code into
698 * human readable ASCII.
700 char *bnet_sig_to_ascii(BSOCK *bs)
703 switch (bs->msglen) {
705 return "BNET_EOD"; /* end of data stream */
707 return "BNET_EOD_POLL";
709 return "BNET_STATUS";
711 return "BNET_TERMINATE"; /* terminate connection */
715 return "BNET_HEARTBEAT";
716 case BNET_HB_RESPONSE:
717 return "BNET_HB_RESPONSE";
719 return "BNET_PROMPT";
721 sprintf(buf, "Unknown sig %d", bs->msglen);
727 /* Initialize internal socket structure.
728 * This probably should be done in net_open
731 init_bsock(void *jcr, int sockfd, char *who, char *host, int port)
733 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
734 memset(bsock, 0, sizeof(BSOCK));
737 bsock->msg = get_pool_memory(PM_MESSAGE);
738 bsock->errmsg = get_pool_memory(PM_MESSAGE);
739 bsock->who = bstrdup(who);
740 bsock->host = bstrdup(host);
743 * ****FIXME**** reduce this to a few hours once
744 * heartbeats are implemented
746 bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */
752 dup_bsock(BSOCK *osock)
754 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
755 memcpy(bsock, osock, sizeof(BSOCK));
756 bsock->msg = get_pool_memory(PM_MESSAGE);
757 bsock->errmsg = get_pool_memory(PM_MESSAGE);
759 bsock->who = bstrdup(osock->who);
762 bsock->host = bstrdup(osock->host);
768 /* Close the network connection */
770 bnet_close(BSOCK *bsock)
774 for ( ; bsock != NULL; bsock = next) {
785 term_bsock(BSOCK *bsock)
788 free_pool_memory(bsock->msg);
791 ASSERT(1==0); /* double close */
794 free_pool_memory(bsock->errmsg);
795 bsock->errmsg = NULL;