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)) {
304 bsock->b_errno = EIO;
306 bsock->b_errno = errno;
309 if (!bsock->suppress_error_msgs) {
310 Jmsg4(bsock->jcr, M_ERROR, 0, _("Write error sending to %s:%s:%d: ERR=%s\n"),
311 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
314 Jmsg5(bsock->jcr, M_ERROR, 0, _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
315 bsock->who, bsock->host, bsock->port, bsock->msglen, rc);
320 bsock->out_msg_no++; /* increment message number */
321 if (bsock->msglen <= 0) { /* length only? */
322 return 1; /* yes, no data */
325 /* send data packet */
326 bsock->timer_start = watchdog_time; /* start timer */
327 bsock->timed_out = 0;
328 rc = write_nbytes(bsock, bsock->msg, bsock->msglen);
329 bsock->timer_start = 0; /* clear timer */
330 if (rc != bsock->msglen) {
333 bsock->b_errno = EIO;
335 bsock->b_errno = errno;
338 if (!bsock->suppress_error_msgs) {
339 Jmsg4(bsock->jcr, M_ERROR, 0, _("Write error sending to %s:%s:%d: ERR=%s\n"),
340 bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
343 Jmsg5(bsock->jcr, M_ERROR, 0, _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
344 bsock->msglen, bsock->who, bsock->host, bsock->port, rc);
352 * Establish an SSL connection -- server side
353 * Codes that ssl_need and ssl_has can take
354 * BNET_SSL_NONE I cannot do ssl
355 * BNET_SSL_OK I can do ssl, but it is not required on my end
356 * BNET_SSL_REQUIRED ssl is required on my end
359 bnet_ssl_server(BSOCK *bsock, char *password, int ssl_need, int ssl_has)
361 /* Check to see if what we need (ssl_need) corresponds to what he has (ssl_has) */
362 /* The other side expects a response from us */
367 * Establish an SSL connection -- client side
369 int bnet_ssl_client(BSOCK *bsock, char *password, int ssl_need)
371 /* We are the client so we must wait for the server to notify us */
377 * Wait for a specified time for data to appear on
378 * the BSOCK connection.
380 * Returns: 1 if data available
385 bnet_wait_data(BSOCK *bsock, int sec)
391 FD_SET(bsock->fd, &fdset);
395 switch(select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
396 case 0: /* timeout */
400 bsock->b_errno = errno;
401 if (errno == EINTR || errno == EAGAIN) {
404 return -1; /* error return */
413 * As above, but returns on interrupt
416 bnet_wait_data_intr(BSOCK *bsock, int sec)
422 FD_SET(bsock->fd, &fdset);
426 switch(select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
427 case 0: /* timeout */
431 bsock->b_errno = errno;
432 return -1; /* error return */
441 static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER;
444 * Convert a hostname or dotted IP address into
445 * a s_addr. We handle only IPv4.
447 static uint32_t *bget_host_ip(void *jcr, char *host)
449 struct in_addr inaddr;
450 uint32_t *addr_list; /* this really should be struct in_addr */
455 if ((inaddr.s_addr = inet_addr(host)) != INADDR_NONE) {
456 addr_list = (uint32_t *) malloc(sizeof(uint32_t) * 2);
457 addr_list[0] = inaddr.s_addr;
458 addr_list[1] = (uint32_t) -1;
461 if ((hp = gethostbyname(host)) == NULL) {
462 Jmsg2(jcr, M_ERROR, 0, "gethostbyname() for %s failed: ERR=%s\n",
463 host, strerror(errno));
467 if (hp->h_length != sizeof(inaddr.s_addr) || hp->h_addrtype != AF_INET) {
468 Jmsg2(jcr, M_ERROR, 0, _("gethostbyname() network address length error.\n\
469 Wanted %d got %d bytes for s_addr.\n"), sizeof(inaddr.s_addr), hp->h_length);
474 for (p = hp->h_addr_list; *p != 0; p++) {
478 addr_list = (uint32_t *) malloc(sizeof(uint32_t) * i);
480 for (p = hp->h_addr_list; *p != 0; p++) {
481 addr_list[i++] = (*(struct in_addr **)p)->s_addr;
483 addr_list[i] = (uint32_t) -1;
490 * Open a TCP connection to the UPS network server
492 * Returns BSOCK * pointer on success
494 * ***FIXME*** implement service from /etc/services
497 bnet_open(void *jcr, char *name, char *host, char *service, int port, int *fatal)
500 struct sockaddr_in tcp_serv_addr; /* socket information */
502 int i, connected = 0;
506 * Fill in the structure serv_addr with the address of
507 * the server that we want to connect with.
509 memset((char *)&tcp_serv_addr, 0, sizeof(tcp_serv_addr));
510 tcp_serv_addr.sin_family = AF_INET;
511 tcp_serv_addr.sin_port = htons(port);
513 if ((addr_list=bget_host_ip(jcr, host)) == NULL) {
518 /* Open a TCP socket */
519 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
526 * Receive notification when connection dies.
528 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
529 Jmsg(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"), strerror(errno));
532 for (i = 0; addr_list[i] != ((uint32_t) -1); i++) {
533 /* connect to server */
534 tcp_serv_addr.sin_addr.s_addr = addr_list[i];
535 if (connect(sockfd, (struct sockaddr *)&tcp_serv_addr, sizeof(tcp_serv_addr)) < 0) {
547 return init_bsock(jcr, sockfd, name, host, port);
551 * Try to connect to host for max_retry_time at retry_time intervals.
554 bnet_connect(void *vjcr, int retry_interval, int max_retry_time, char *name,
555 char *host, char *service, int port, int verbose)
559 JCR *jcr = (JCR *)vjcr;
562 for (i=0; (bsock = bnet_open(jcr, name, host, service, port, &fatal)) == NULL; i -= retry_interval) {
563 if (fatal || (jcr && job_canceled(jcr))) {
566 Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
567 name, host, port, strerror(errno));
569 i = 60 * 5; /* complain again in 5 minutes */
571 Jmsg(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
572 Retrying ...\n", name, host, port, strerror(errno));
574 bmicrosleep(retry_interval, 0);
575 max_retry_time -= retry_interval;
576 if (max_retry_time <= 0) {
577 Jmsg(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
578 name, host, port, strerror(errno));
587 * Return the string for the error that occurred
588 * on the socket. Only the first error is retained.
590 char *bnet_strerror(BSOCK *bsock)
592 return strerror(bsock->b_errno);
596 * Format and send a message
597 * Returns: 0 on failure
601 bnet_fsend(BSOCK *bs, char *fmt, ...)
606 /* This probably won't work, but we vsnprintf, then if we
607 * get a negative length or a length greater than our buffer
608 * (depending on which library is used), the printf was truncated, so
609 * get a biger buffer and try again.
612 maxlen = sizeof_pool_memory(bs->msg) - 1;
613 va_start(arg_ptr, fmt);
614 bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
616 if (bs->msglen < 0 || bs->msglen >= maxlen) {
617 bs->msg = realloc_pool_memory(bs->msg, maxlen + 200);
620 return bnet_send(bs) < 0 ? 0 : 1;
624 * Set the network buffer size, suggested size is in size.
625 * Actual size obtained is returned in bs->msglen
627 * Returns: 0 on failure
630 int bnet_set_buffer_size(BSOCK *bs, uint32_t size, int rw)
633 #if defined(IP_TOS) && defined(IPTOS_THROUGHPUT)
636 opt = IPTOS_THROUGHPUT;
637 setsockopt(bs->fd, IPPROTO_IP, IP_TOS, (sockopt_val_t)&opt, sizeof(opt));
641 if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size+100)) == NULL) {
642 Jmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
645 if (rw & BNET_SETBUF_READ) {
646 while ((dbuf_size > TAPE_BSIZE) &&
647 (setsockopt(bs->fd, SOL_SOCKET, SO_RCVBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
648 Jmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
649 dbuf_size -= TAPE_BSIZE;
651 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
652 if (dbuf_size != MAX_NETWORK_BUFFER_SIZE)
653 Jmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
654 if (dbuf_size % TAPE_BSIZE != 0) {
655 Jmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
660 if (rw & BNET_SETBUF_WRITE) {
661 while ((dbuf_size > TAPE_BSIZE) &&
662 (setsockopt(bs->fd, SOL_SOCKET, SO_SNDBUF, (sockopt_val_t)&dbuf_size, sizeof(dbuf_size)) < 0)) {
663 Jmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), strerror(errno));
664 dbuf_size -= TAPE_BSIZE;
666 Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
667 if (dbuf_size != MAX_NETWORK_BUFFER_SIZE)
668 Jmsg1(bs->jcr, M_WARNING, 0, _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
669 if (dbuf_size % TAPE_BSIZE != 0) {
670 Jmsg1(bs->jcr, M_ABORT, 0, _("Network buffer size %d not multiple of tape block size.\n"),
675 bs->msglen = dbuf_size;
680 * Send a network "signal" to the other end
681 * This consists of sending a negative packet length
683 * Returns: 0 on failure
686 int bnet_sig(BSOCK *bs, int sig)
689 return bnet_send(bs);
693 * Convert a network "signal" code into
694 * human readable ASCII.
696 char *bnet_sig_to_ascii(BSOCK *bs)
699 switch (bs->msglen) {
701 return "BNET_EOD"; /* end of data stream */
703 return "BNET_EOD_POLL";
705 return "BNET_STATUS";
707 return "BNET_TERMINATE"; /* terminate connection */
711 return "BNET_HEARTBEAT";
712 case BNET_HB_RESPONSE:
713 return "BNET_HB_RESPONSE";
715 return "BNET_PROMPT";
717 sprintf(buf, "Unknown sig %d", bs->msglen);
723 /* Initialize internal socket structure.
724 * This probably should be done in net_open
727 init_bsock(void *jcr, int sockfd, char *who, char *host, int port)
729 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
730 memset(bsock, 0, sizeof(BSOCK));
733 bsock->msg = get_pool_memory(PM_MESSAGE);
734 bsock->errmsg = get_pool_memory(PM_MESSAGE);
735 bsock->who = bstrdup(who);
736 bsock->host = bstrdup(host);
739 * ****FIXME**** reduce this to a few hours once
740 * heartbeats are implemented
742 bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */
748 dup_bsock(BSOCK *osock)
750 BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
751 memcpy(bsock, osock, sizeof(BSOCK));
752 bsock->msg = get_pool_memory(PM_MESSAGE);
753 bsock->errmsg = get_pool_memory(PM_MESSAGE);
755 bsock->who = bstrdup(osock->who);
758 bsock->host = bstrdup(osock->host);
764 /* Close the network connection */
766 bnet_close(BSOCK *bsock)
770 for ( ; bsock != NULL; bsock = next) {
781 term_bsock(BSOCK *bsock)
784 free_pool_memory(bsock->msg);
787 ASSERT(1==0); /* double close */
790 free_pool_memory(bsock->errmsg);
791 bsock->errmsg = NULL;