]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/bnet.c
kes Add dynamic dll entry point for SHGetFolderPath to Win32 code.
[bacula/bacula] / bacula / src / lib / bnet.c
index 7af71868f183305b274d240b845c60a8bd64477a..3c2d88be5f0bf14bba9d80a11850272bf8e046f1 100644 (file)
@@ -9,19 +9,32 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Bacula® - The Network Backup Solution
 
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License
-   version 2 as ammended with additional clauses defined in the
-   file LICENSE in the main source directory.
+   Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
 
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
-   the file LICENSE for additional details.
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation plus additions
+   that are listed in the file LICENSE.
 
- */
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
 
 
 #include "bacula.h"
@@ -69,13 +82,20 @@ static int32_t read_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes)
 
    nleft = nbytes;
    while (nleft > 0) {
-      do {
-         errno = 0;
-         nread = socketRead(bsock->fd, ptr, nleft);
-         if (bsock->timed_out || bsock->terminated) {
-            return nread;
+      errno = 0;
+      nread = socketRead(bsock->fd, ptr, nleft);
+      if (bsock->timed_out || bsock->terminated) {
+         return nread;
+      }
+      if (nread == -1) {
+         if (errno == EINTR) {
+            continue;
          }
-      } while (nread == -1 && (errno == EINTR || errno == EAGAIN));
+         if (errno == EAGAIN) {
+            bmicrosleep(0, 200000);  /* try again in 200ms */
+            continue;
+         }
+      }
       if (nread <= 0) {
          return nread;             /* error, or EOF */
       }
@@ -171,7 +191,9 @@ int32_t bnet_recv(BSOCK * bsock)
    int32_t nbytes;
    int32_t pktsiz;
 
-   ASSERT(bsock != NULL);
+   if (!bsock) {
+      return BNET_HARDEOF;
+   }
    bsock->msg[0] = 0;
    bsock->msglen = 0;
    if (bsock->errors || bsock->terminated) {
@@ -385,8 +407,9 @@ bool bnet_send(BSOCK * bsock)
          }
       } else {
          Qmsg5(bsock->jcr, M_ERROR, 0,
-               _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"), bsock->who,
-               bsock->host, bsock->port, bsock->msglen, rc);
+               _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
+               sizeof(int32_t), bsock->who,
+               bsock->host, bsock->port, rc);
       }
       return false;
    }
@@ -427,18 +450,18 @@ bool bnet_send(BSOCK * bsock)
 
 /*
  * Establish a TLS connection -- server side
- *  Returns: 1 on success
- *           0 failure
+ *  Returns: true  on success
+ *           false on failure
  */
 #ifdef HAVE_TLS
-int bnet_tls_server(TLS_CONTEXT *ctx, BSOCK * bsock, alist *verify_list)
+bool bnet_tls_server(TLS_CONTEXT *ctx, BSOCK * bsock, alist *verify_list)
 {
    TLS_CONNECTION *tls;
    
    tls = new_tls_connection(ctx, bsock->fd);
    if (!tls) {
       Qmsg0(bsock->jcr, M_FATAL, 0, _("TLS connection initialization failed.\n"));
-      return 0;
+      return false;
    }
 
    bsock->tls = tls;
@@ -457,28 +480,27 @@ int bnet_tls_server(TLS_CONTEXT *ctx, BSOCK * bsock, alist *verify_list)
          goto err;
       }
    }
-   return 1;
+   return true;
 
 err:
    free_tls_connection(tls);
    bsock->tls = NULL;
-   return 0;
+   return false;
 }
 
 /*
  * Establish a TLS connection -- client side
- * Returns: 1 on success
- *          0 failure
+ * Returns: true  on success
+ *          false on failure
  */
-int bnet_tls_client(TLS_CONTEXT *ctx, BSOCK * bsock)
+bool bnet_tls_client(TLS_CONTEXT *ctx, BSOCK * bsock)
 {
    TLS_CONNECTION *tls;
 
    tls  = new_tls_connection(ctx, bsock->fd);
    if (!tls) {
       Qmsg0(bsock->jcr, M_FATAL, 0, _("TLS connection initialization failed.\n"));
-      return 0;
+      return false;
    }
 
    bsock->tls = tls;
@@ -492,24 +514,23 @@ int bnet_tls_client(TLS_CONTEXT *ctx, BSOCK * bsock)
       Qmsg1(bsock->jcr, M_FATAL, 0, _("TLS host certificate verification failed. Host %s did not match presented certificate\n"), bsock->host);
       goto err;
    }
-   return 1;
+   return true;
 
 err:
    free_tls_connection(tls);
    bsock->tls = NULL;
-   return 0;
+   return false;
 }
 #else
-int bnet_tls_server(TLS_CONTEXT *ctx, BSOCK * bsock, alist *verify_list)
+bool bnet_tls_server(TLS_CONTEXT *ctx, BSOCK * bsock, alist *verify_list)
 {
-   Jmsg(bsock->jcr, M_ABORT, 0, _("TLS not configured.\n"));
-   return 0;
+   Jmsg(bsock->jcr, M_ABORT, 0, _("TLS enabled but not configured.\n"));
+   return false;
 }
-int bnet_tls_client(TLS_CONTEXT *ctx, BSOCK * bsock)
+bool bnet_tls_client(TLS_CONTEXT *ctx, BSOCK * bsock)
 {
-   Jmsg(bsock->jcr, M_ABORT, 0, _("TLS not configured.\n"));
-   return 0;
+   Jmsg(bsock->jcr, M_ABORT, 0, _("TLS enable but not configured.\n"));
+   return false;
 }
 #endif /* HAVE_TLS */
 
@@ -528,16 +549,16 @@ int bnet_wait_data(BSOCK * bsock, int sec)
 
    FD_ZERO(&fdset);
    FD_SET((unsigned)bsock->fd, &fdset);
-   tv.tv_sec = sec;
-   tv.tv_usec = 0;
    for (;;) {
+      tv.tv_sec = sec;
+      tv.tv_usec = 0;
       switch (select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) {
       case 0:                      /* timeout */
          bsock->b_errno = 0;
          return 0;
       case -1:
          bsock->b_errno = errno;
-         if (errno == EINTR || errno == EAGAIN) {
+         if (errno == EINTR) {
             continue;
          }
          return -1;                /* error return */
@@ -604,22 +625,22 @@ static const char *gethost_strerror()
       msg = be.strerror();
       break;
    case NETDB_SUCCESS:
-      msg = "No problem.";
+      msg = _("No problem.");
       break;
    case HOST_NOT_FOUND:
-      msg = "Authoritative answer for host not found.";
+      msg = _("Authoritative answer for host not found.");
       break;
    case TRY_AGAIN:
-      msg = "Non-authoritative for host not found, or ServerFail.";
+      msg = _("Non-authoritative for host not found, or ServerFail.");
       break;
    case NO_RECOVERY:
-      msg = "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.";
+      msg = _("Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.");
       break;
    case NO_DATA:
-      msg = "Valid name, no data record of resquested type.";
+      msg = _("Valid name, no data record of resquested type.");
       break;
    default:
-      msg = "Unknown error.";
+      msg = _("Unknown error.");
    }
    return msg;
 }
@@ -754,7 +775,7 @@ static BSOCK *bnet_open(JCR * jcr, const char *name, char *host, char *service,
     */
    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",
+      Qmsg2(jcr, M_ERROR, 0, _("gethostbyname() for host \"%s\" failed: ERR=%s\n"),
             host, errstr);
       Dmsg2(100, "bnet_host2ipaddrs() for host %s failed: ERR=%s\n",
             host, errstr);
@@ -774,7 +795,7 @@ static BSOCK *bnet_open(JCR * jcr, const char *name, char *host, char *service,
          berrno be;
          save_errno = errno;
          *fatal = 1;
-         Pmsg3(000, "Socket open error. proto=%d port=%d. ERR=%s\n",
+         Pmsg3(000, _("Socket open error. proto=%d port=%d. ERR=%s\n"),
             ipaddr->get_family(), ipaddr->get_port_host_order(), be.strerror());
          continue;
       }
@@ -789,7 +810,7 @@ static BSOCK *bnet_open(JCR * jcr, const char *name, char *host, char *service,
       /* connect to server */
       if (connect(sockfd, ipaddr->get_sockaddr(), ipaddr->get_sockaddr_len()) < 0) {
          save_errno = errno;
-         close(sockfd);
+         socketClose(sockfd);
          continue;
       }
       *fatal = 0;
@@ -798,7 +819,7 @@ static BSOCK *bnet_open(JCR * jcr, const char *name, char *host, char *service,
    }
 
    if (!connected) {
-         free_addresses(addr_list);
+      free_addresses(addr_list);
       errno = save_errno;
       return NULL;
    }
@@ -838,8 +859,9 @@ BSOCK *bnet_connect(JCR * jcr, int retry_interval, int max_retry_time,
       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;
@@ -898,6 +920,21 @@ bool bnet_fsend(BSOCK * bs, const char *fmt, ...)
    return bnet_send(bs);
 }
 
+int bnet_get_peer(BSOCK *bs, char *buf, socklen_t buflen) {
+#if !defined(HAVE_WIN32)
+    if (bs->peer_addr.sin_family == 0) {
+        socklen_t salen = sizeof(bs->peer_addr);
+        int rval = (getpeername)(bs->fd, (struct sockaddr *)&bs->peer_addr, &salen);
+        if (rval < 0) return rval;
+    }
+    if (!inet_ntop(bs->peer_addr.sin_family, &bs->peer_addr.sin_addr, buf, buflen))
+        return -1;
+
+    return 0;
+#else
+    return -1;
+#endif
+}
 /*
  * Set the network buffer size, suggested size is in size.
  *  Actual size obtained is returned in bs->msglen
@@ -977,19 +1014,19 @@ bool bnet_set_buffer_size(BSOCK * bs, uint32_t size, int rw)
  * Returns previous socket flag
  */
 int bnet_set_nonblocking (BSOCK *bsock) {
-#ifndef WIN32
+#ifndef HAVE_WIN32
    int oflags;
 
    /* Get current flags */
-   if((oflags = fcntl(bsock->fd, F_GETFL, 0)) < 0) {
+   if ((oflags = fcntl(bsock->fd, F_GETFL, 0)) < 0) {
       berrno be;
-      Emsg1(M_ABORT, 0, "fcntl F_GETFL error. ERR=%s\n", be.strerror());
+      Jmsg1(bsock->jcr, M_ABORT, 0, _("fcntl F_GETFL error. ERR=%s\n"), be.strerror());
    }
 
    /* Set O_NONBLOCK flag */
-   if((fcntl(bsock->fd, F_SETFL, oflags|O_NONBLOCK)) < 0) {
+   if ((fcntl(bsock->fd, F_SETFL, oflags|O_NONBLOCK)) < 0) {
       berrno be;
-      Emsg1(M_ABORT, 0, "fcntl F_SETFL error. ERR=%s\n", be.strerror());
+      Jmsg1(bsock->jcr, M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.strerror());
    }
 
    bsock->blocking = 0;
@@ -1002,7 +1039,7 @@ int bnet_set_nonblocking (BSOCK *bsock) {
    ioctlsocket(bsock->fd, FIONBIO, &ioctlArg);
    bsock->blocking = 0;
 
-   return (flags);
+   return flags;
 #endif
 }
 
@@ -1010,23 +1047,24 @@ int bnet_set_nonblocking (BSOCK *bsock) {
  * Set socket blocking
  * Returns previous socket flags
  */
-int bnet_set_blocking (BSOCK *bsock) {
-#ifndef WIN32
+int bnet_set_blocking (BSOCK *bsock) 
+{
+#ifndef HAVE_WIN32
    int oflags;
    /* Get current flags */
-   if((oflags = fcntl(bsock->fd, F_GETFL, 0)) < 0) {
+   if ((oflags = fcntl(bsock->fd, F_GETFL, 0)) < 0) {
       berrno be;
-      Emsg1(M_ABORT, 0, "fcntl F_GETFL error. ERR=%s\n", be.strerror());
+      Jmsg1(bsock->jcr, M_ABORT, 0, _("fcntl F_GETFL error. ERR=%s\n"), be.strerror());
    }
 
    /* Set O_NONBLOCK flag */
-   if((fcntl(bsock->fd, F_SETFL, oflags & ~O_NONBLOCK)) < 0) {
+   if ((fcntl(bsock->fd, F_SETFL, oflags & ~O_NONBLOCK)) < 0) {
       berrno be;
-      Emsg1(M_ABORT, 0, "fcntl F_SETFL error. ERR=%s\n", be.strerror());
+      Jmsg1(bsock->jcr, M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.strerror());
    }
 
    bsock->blocking = 1;
-   return (oflags);
+   return oflags;
 #else
    int flags;
    u_long ioctlArg = 0;
@@ -1035,18 +1073,19 @@ int bnet_set_blocking (BSOCK *bsock) {
    ioctlsocket(bsock->fd, FIONBIO, &ioctlArg);
    bsock->blocking = 1;
 
-   return (flags);
+   return flags;
 #endif
 }
 
 /*
  * Restores socket flags
  */
-void bnet_restore_blocking (BSOCK *bsock, int flags) {
-#ifndef WIN32
-   if((fcntl(bsock->fd, F_SETFL, flags)) < 0) {
+void bnet_restore_blocking (BSOCK *bsock, int flags) 
+{
+#ifndef HAVE_WIN32
+   if ((fcntl(bsock->fd, F_SETFL, flags)) < 0) {
       berrno be;
-      Emsg1(M_ABORT, 0, "fcntl F_SETFL error. ERR=%s\n", be.strerror());
+      Jmsg1(bsock->jcr, M_ABORT, 0, _("fcntl F_SETFL error. ERR=%s\n"), be.strerror());
    }
 
    bsock->blocking = (flags & O_NONBLOCK);
@@ -1100,7 +1139,7 @@ const char *bnet_sig_to_ascii(BSOCK * bs)
    case BNET_PROMPT:
       return "BNET_PROMPT";
    default:
-      sprintf(buf, "Unknown sig %d", (int)bs->msglen);
+      sprintf(buf, _("Unknown sig %d"), (int)bs->msglen);
       return buf;
    }
 }
@@ -1124,6 +1163,7 @@ BSOCK *init_bsock(JCR * jcr, int sockfd, const char *who, const char *host, int
    bsock->who = bstrdup(who);
    bsock->host = bstrdup(host);
    bsock->port = port;
+   memset(&bsock->peer_addr, 0, sizeof(bsock->peer_addr));
    memcpy(&bsock->client_addr, client_addr, sizeof(bsock->client_addr));
    /*
     * ****FIXME**** reduce this to a few hours once