*
* by Kern Sibbald
*
- * Adapted and enhanced for Bacula, originally written
+ * Adapted and enhanced for Bacula, originally written
* for inclusion in the Apcupsd package
*
* Version $Id$
#endif
+#ifdef HAVE_OLD_SOCKOPT
+int inet_aton(const char *cp, struct in_addr *inp)
+{
+ struct in_addr inaddr;
+
+ if((inaddr.s_addr = inet_addr(cp)) != INADDR_NONE) {
+ inp->s_addr = inaddr.s_addr;
+ return 1;
+ }
+ return 0;
+}
+#endif
+
/*
* Read a nbytes from the network.
* It is possible that the total bytes require in several
nwritten = fwrite(ptr, 1, nbytes, bsock->spool_fd);
if (nwritten != nbytes) {
berrno be;
- Qmsg1(bsock->jcr, M_FATAL, 0, _("Attr spool write error. ERR=%s\n"),
+ bsock->b_errno = errno;
+ Qmsg1(bsock->jcr, M_FATAL, 0, _("Attr spool write error. ERR=%s\n"),
be.strerror());
- Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes);
+ Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes);
+ errno = bsock->b_errno;
return -1;
}
return nbytes;
return nbytes - nleft;
}
-/*
+/*
* Receive a message from the other end. Each message consists of
* two packets. The first is a header that contains the size
* of the data that follows in the second packet.
* Returns number of bytes read (may return zero)
- * Returns -1 on signal (BNET_SIGNAL)
+ * Returns -1 on signal (BNET_SIGNAL)
* Returns -2 on hard end of file (BNET_HARDEOF)
* Returns -3 on error (BNET_ERROR)
*
* four return types:
* 1. Normal data
* 2. Signal including end of data stream
- * 3. Hard end of file
+ * 3. Hard end of file
* 4. Error
* Using is_bnet_stop() and is_bnet_error() you can figure this all out.
*/
int32_t pktsiz;
ASSERT(bsock != NULL);
- mp_chr(bsock->msg)[0] = 0;
+ bsock->msg[0] = 0;
+ bsock->msglen = 0;
if (bsock->errors || bsock->terminated) {
return BNET_HARDEOF;
}
if (pktsiz < 0 || pktsiz > 1000000) {
if (pktsiz > 0) { /* if packet too big */
Qmsg3(bsock->jcr, M_FATAL, 0,
- _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
+ _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
bsock->who, bsock->host, bsock->port);
pktsiz = BNET_TERMINATE; /* hang up */
}
bsock->timer_start = watchdog_time; /* set start wait time */
bsock->timed_out = 0;
/* now read the actual data */
- if ((nbytes = read_nbytes(bsock, mp_chr(bsock->msg), pktsiz)) <= 0) {
+ if ((nbytes = read_nbytes(bsock, bsock->msg, pktsiz)) <= 0) {
bsock->timer_start = 0; /* clear timer */
if (errno == 0) {
bsock->b_errno = ENODATA;
* string that was send to us. Note, we ensured above that the
* buffer is at least one byte longer than the message length.
*/
- mp_chr(bsock->msg)[nbytes] = 0; /* terminate in case it is a string */
+ bsock->msg[nbytes] = 0; /* terminate in case it is a string */
sm_check(__FILE__, __LINE__, false);
return nbytes; /* return actual length of message */
}
/*
- * Return 1 if there are errors on this bsock or it is closed,
+ * Return 1 if there are errors on this bsock or it is closed,
* i.e. stop communicating on this line.
*/
bool is_bnet_stop(BSOCK * bsock)
}
/*
- * Return number of errors on socket
+ * Return number of errors on socket
*/
int is_bnet_error(BSOCK * bsock)
{
nbytes = fread(bsock->msg, 1, bsock->msglen, bsock->spool_fd);
if (nbytes != (size_t) bsock->msglen) {
berrno be;
- Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, bsock->msglen);
- Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
+ Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, bsock->msglen);
+ Qmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
be.strerror());
update_attr_spool_size(tsize - last);
return 0;
* two network packets. The first is sends a 32 bit integer containing
* the length of the data packet which follows.
*
- * Returns: 0 on failure
- * 1 on success
+ * Returns: false on failure
+ * true on success
*/
bool bnet_send(BSOCK * bsock)
{
if (rc < 0) {
if (!bsock->suppress_error_msgs && !bsock->timed_out) {
Qmsg4(bsock->jcr, M_ERROR, 0,
- _("Write error sending to %s:%s:%d: ERR=%s\n"), bsock->who,
+ _("Write error sending to %s:%s:%d: ERR=%s\n"), bsock->who,
bsock->host, bsock->port, bnet_strerror(bsock));
}
} else {
Qmsg5(bsock->jcr, M_ERROR, 0,
- _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"), bsock->who,
+ _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"), bsock->who,
bsock->host, bsock->port, bsock->msglen, rc);
}
return false;
/* send data packet */
bsock->timer_start = watchdog_time; /* start timer */
bsock->timed_out = 0;
- rc = write_nbytes(bsock, mp_chr(bsock->msg), bsock->msglen);
+ rc = write_nbytes(bsock, bsock->msg, bsock->msglen);
bsock->timer_start = 0; /* clear timer */
if (rc != bsock->msglen) {
bsock->errors++;
if (rc < 0) {
if (!bsock->suppress_error_msgs) {
Qmsg4(bsock->jcr, M_ERROR, 0,
- _("Write error sending to %s:%s:%d: ERR=%s\n"), bsock->who,
+ _("Write error sending to %s:%s:%d: ERR=%s\n"), bsock->who,
bsock->host, bsock->port, bnet_strerror(bsock));
}
} else {
Qmsg5(bsock->jcr, M_ERROR, 0,
- _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
+ _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
bsock->msglen, bsock->who, bsock->host, bsock->port, rc);
}
return false;
}
/*
- * Establish an SSL connection -- server side
+ * Establish an SSL connection -- server side
* Codes that ssl_need and ssl_has can take
* BNET_SSL_NONE I cannot do ssl
* BNET_SSL_OK I can do ssl, but it is not required on my end
}
/*
- * Establish an SSL connection -- client side
+ * Establish an SSL connection -- client side
*/
int bnet_ssl_client(BSOCK * bsock, char *password, int ssl_need)
{
*/
static const char *gethost_strerror()
{
+ const char *msg;
switch (h_errno) {
case NETDB_INTERNAL:
- return strerror(errno);
+ msg = strerror(errno);
+ break;
case NETDB_SUCCESS:
- return "No problem.";
+ msg = "No problem.";
+ break;
case HOST_NOT_FOUND:
- return "Authoritative answer Host not found.";
+ msg = "Authoritative answer for host not found.";
+ break;
case TRY_AGAIN:
- return "Non-authoritative Host not found, or ServerFail.";
+ msg = "Non-authoritative for host not found, or ServerFail.";
+ break;
case NO_RECOVERY:
- return "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.";
+ msg = "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.";
+ break;
case NO_DATA:
- return "Valid name, no data record of resquested type.";
+ msg = "Valid name, no data record of resquested type.";
+ break;
default:
- return "Unknown error.";
+ msg = "Unknown error.";
}
+ return msg;
}
static IPADDR *add_any(int family)
{
- IPADDR *addr = new IPADDR(family);
+ IPADDR *addr = New(IPADDR(family));
addr->set_type(IPADDR::R_MULTIPLE);
addr->set_addr_any();
return addr;
}
-static int resolv_host(int family, const char *host, dlist * addr_list,
- const char **errstr)
+static const char *resolv_host(int family, const char *host, dlist * addr_list)
{
struct hostent *hp;
+ const char *errmsg;
P(ip_mutex);
#ifdef HAVE_GETHOSTBYNAME2
if ((hp = gethostbyname(host)) == NULL) {
#endif
/* may be the strerror give not the right result -:( */
- *errstr = gethost_strerror();
+ errmsg = gethost_strerror();
V(ip_mutex);
- return 0;
+ return errmsg;
} else {
char **p;
for (p = hp->h_addr_list; *p != 0; p++) {
- IPADDR *addr = new IPADDR(hp->h_addrtype);
+ IPADDR *addr = New(IPADDR(hp->h_addrtype));
addr->set_type(IPADDR::R_MULTIPLE);
if (addr->get_family() == AF_INET) {
addr->set_addr4((struct in_addr*)*p);
}
V(ip_mutex);
}
- return 1;
+ return NULL;
}
/*
{
struct in_addr inaddr;
IPADDR *addr = 0;
+ const char *errmsg;
#ifdef HAVE_IPV6
struct in6_addr inaddr6;
#endif
- dlist *addr_list = new dlist(addr, &addr->link);
+ dlist *addr_list = New(dlist(addr, &addr->link));
if (!host || host[0] == '\0') {
if (family != 0) {
addr_list->append(add_any(family));
addr_list->append(add_any(AF_INET6));
#endif
}
- } else if ((inaddr.s_addr = inet_addr(host)) != INADDR_NONE) {
- addr = new IPADDR(AF_INET);
+ } else if (inet_aton(host, &inaddr)) { /* MA Bug 4 */
+ addr = New(IPADDR(AF_INET));
addr->set_type(IPADDR::R_MULTIPLE);
addr->set_addr4(&inaddr);
addr_list->append(addr);
} else
#ifdef HAVE_IPV6
if (inet_pton(AF_INET6, host, &inaddr6) > 1) {
- addr = new IPADDR(AF_INET6);
+ addr = New(IPADDR(AF_INET6));
addr->set_type(IPADDR::R_MULTIPLE);
addr->set_addr6(&inaddr6);
addr_list->append(addr);
#endif
{
if (family != 0) {
- if (!resolv_host(family, host, addr_list, errstr)) {
+ errmsg = resolv_host(family, host, addr_list);
+ if (errmsg) {
+ *errstr = errmsg;
free_addresses(addr_list);
return 0;
}
} else {
- int done = 0;
- done |= resolv_host(AF_INET, host, addr_list, errstr);
+ errmsg = resolv_host(AF_INET, host, addr_list);
#ifdef HAVE_IPV6
- done |= resolv_host(AF_INET6, host, addr_list, errstr);
+ if (errmsg) {
+ errmsg = resolv_host(AF_INET6, host, addr_list);
+ }
#endif
- if (!done) {
+ if (errmsg) {
+ *errstr = errmsg;
free_addresses(addr_list);
return 0;
}
return addr_list;
}
-/*
+/*
* Open a TCP connection to the UPS network server
* Returns NULL
* Returns BSOCK * pointer on success
const char *errstr;
int save_errno = 0;
- /*
+ /*
* Fill in the structure serv_addr with the address of
* the server that we want to connect with.
*/
if ((addr_list = bnet_host2ipaddrs(host, 0, &errstr)) == NULL) {
+ /* Note errstr is not malloc'ed */
Qmsg2(jcr, M_ERROR, 0, "gethostbyname() for host \"%s\" failed: ERR=%s\n",
host, errstr);
- free((void *)errstr);
+ Dmsg2(100, "bnet_host2ipaddrs() for host %s failed: ERR=%s\n",
+ host, errstr);
*fatal = 1;
return NULL;
}
foreach_dlist(ipaddr, addr_list) {
- ipaddr->set_port(htons(port));
+ ipaddr->set_port_net(htons(port));
char allbuf[256 * 10];
char curbuf[256];
- Dmsg2(100, "Current %sAll %s\n",
- ipaddr->build_address_str(curbuf, sizeof(curbuf)),
+ Dmsg2(100, "Current %sAll %s\n",
+ ipaddr->build_address_str(curbuf, sizeof(curbuf)),
build_addresses_str(addr_list, allbuf, sizeof(allbuf)));
/* Open a TCP socket */
if ((sockfd = socket(ipaddr->get_family(), SOCK_STREAM, 0)) < 0) {
berrno be;
save_errno = errno;
*fatal = 1;
- Pmsg3(000, "Socket open error. proto=%d port=%d. ERR=%s\n",
- ipaddr->get_family(), ipaddr->get_port(), be.strerror());
+ Pmsg3(000, "Socket open error. proto=%d port=%d. ERR=%s\n",
+ ipaddr->get_family(), ipaddr->get_port_host_order(), be.strerror());
continue;
}
/*
- * Receive notification when connection dies.
+ * Keep socket from timing out from inactivity
*/
- if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t) & turnon,
- sizeof(turnon)) < 0) {
+ if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
berrno be;
- Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
+ Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
be.strerror());
}
/* connect to server */
break;
}
- free_addresses(addr_list);
if (!connected) {
+ free_addresses(addr_list);
errno = save_errno;
return NULL;
}
- return init_bsock(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
+ /*
+ * Keep socket from timing out from inactivity
+ * Do this a second time out of paranoia
+ */
+ if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (sockopt_val_t)&turnon, sizeof(turnon)) < 0) {
+ berrno be;
+ Qmsg1(jcr, M_WARNING, 0, _("Cannot set SO_KEEPALIVE on socket: %s\n"),
+ be.strerror());
+ }
+ BSOCK* ret = init_bsock(jcr, sockfd, name, host, port, ipaddr->get_sockaddr());
+ free_addresses(addr_list);
+ return ret;
}
/*
if (i < 0) {
i = 60 * 5; /* complain again in 5 minutes */
if (verbose)
- Qmsg4(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
-Retrying ...\n", name, host, port, be.strerror());
+ Qmsg4(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n"
+"Retrying ...\n", name, host, port, be.strerror());
}
bmicrosleep(retry_interval, 0);
max_retry_time -= retry_interval;
if (max_retry_time <= 0) {
- Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
+ Qmsg4(jcr, M_FATAL, 0, _("Unable to connect to %s on %s:%d. ERR=%s\n"),
name, host, port, be.strerror());
return NULL;
}
* Return the string for the error that occurred
* on the socket. Only the first error is retained.
*/
-char *bnet_strerror(BSOCK * bsock)
+const char *bnet_strerror(BSOCK * bsock)
{
- return strerror(bsock->b_errno);
+ berrno be;
+ if (bsock->errmsg == NULL) {
+ bsock->errmsg = get_pool_memory(PM_MESSAGE);
+ }
+ pm_strcpy(bsock->errmsg, be.strerror(bsock->b_errno));
+ return bsock->errmsg;
}
/*
for (;;) {
maxlen = sizeof_pool_memory(bs->msg) - 1;
va_start(arg_ptr, fmt);
- bs->msglen = bvsnprintf(mp_chr(bs->msg), maxlen, fmt, arg_ptr);
+ bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
va_end(arg_ptr);
if (bs->msglen > 0 && bs->msglen < (maxlen - 5)) {
break;
return bnet_send(bs);
}
-/*
+/*
* Set the network buffer size, suggested size is in size.
* Actual size obtained is returned in bs->msglen
*
return false;
}
if (rw & BNET_SETBUF_READ) {
- while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
+ while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
SO_RCVBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
berrno be;
- Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
+ Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
dbuf_size -= TAPE_BSIZE;
}
Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
if (dbuf_size != start_size) {
Qmsg1(bs->jcr, M_WARNING, 0,
- _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
+ _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
}
if (dbuf_size % TAPE_BSIZE != 0) {
Qmsg1(bs->jcr, M_ABORT, 0,
- _("Network buffer size %d not multiple of tape block size.\n"),
+ _("Network buffer size %d not multiple of tape block size.\n"),
dbuf_size);
}
}
}
start_size = dbuf_size;
if (rw & BNET_SETBUF_WRITE) {
- while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
+ while ((dbuf_size > TAPE_BSIZE) && (setsockopt(bs->fd, SOL_SOCKET,
SO_SNDBUF, (sockopt_val_t) & dbuf_size, sizeof(dbuf_size)) < 0)) {
berrno be;
- Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
+ Qmsg1(bs->jcr, M_ERROR, 0, _("sockopt error: %s\n"), be.strerror());
dbuf_size -= TAPE_BSIZE;
}
Dmsg1(200, "set network buffer size=%d\n", dbuf_size);
if (dbuf_size != start_size) {
Qmsg1(bs->jcr, M_WARNING, 0,
- _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
+ _("Warning network buffer = %d bytes not max size.\n"), dbuf_size);
}
if (dbuf_size % TAPE_BSIZE != 0) {
Qmsg1(bs->jcr, M_ABORT, 0,
- _("Network buffer size %d not multiple of tape block size.\n"),
+ _("Network buffer size %d not multiple of tape block size.\n"),
dbuf_size);
}
}
}
/*
- * Send a network "signal" to the other end
+ * Send a network "signal" to the other end
* This consists of sending a negative packet length
*
* Returns: false on failure
}
-/* Initialize internal socket structure.
+/* Initialize internal socket structure.
* This probably should be done in net_open
*/
BSOCK *init_bsock(JCR * jcr, int sockfd, const char *who, const char *host, int port,
- struct sockaddr * client_addr)
+ struct sockaddr *client_addr)
{
+ Dmsg3(100, "who=%s host=%s port=%d\n", who, host, port);
BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK));
memset(bsock, 0, sizeof(BSOCK));
bsock->fd = sockfd;
bsock->port = port;
memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
/*
- * ****FIXME**** reduce this to a few hours once
+ * ****FIXME**** reduce this to a few hours once
* heartbeats are implemented
*/
bsock->timeout = 60 * 60 * 6 * 24; /* 6 days timeout */