X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Flib%2Fbnet.c;h=1e8b8f4d3eca2ec52497c37f3a6b5442e18ae0c7;hb=ea7882c881de995b5c237609207ee58bcae40186;hp=2e247eef23c48e0bc297161563e7472f4c4950a4;hpb=957747c98782b1d29f21b665ca172474923a0755;p=bacula%2Fbacula diff --git a/bacula/src/lib/bnet.c b/bacula/src/lib/bnet.c index 2e247eef23..1e8b8f4d3e 100644 --- a/bacula/src/lib/bnet.c +++ b/bacula/src/lib/bnet.c @@ -1,12 +1,12 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2008 Free Software Foundation Europe e.V. + Copyright (C) 2000-2011 Free Software Foundation Europe e.V. 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 + modify it under the terms of version three of the GNU Affero General Public License as published by the Free Software Foundation and included in the file LICENSE. @@ -15,7 +15,7 @@ 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 + You should have received a copy of the GNU Affero 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. @@ -33,10 +33,8 @@ * Adapted and enhanced for Bacula, originally written * for inclusion in the Apcupsd package * - * Version $Id$ */ - #include "bacula.h" #include "jcr.h" #include @@ -55,14 +53,15 @@ #define socketClose(fd) close(fd) #endif +#ifndef HAVE_GETADDRINFO static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif /* * Read a nbytes from the network. * It is possible that the total bytes require in several * read requests */ - int32_t read_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes) { int32_t nleft, nread; @@ -79,19 +78,38 @@ int32_t read_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes) errno = 0; nread = socketRead(bsock->m_fd, ptr, nleft); if (bsock->is_timed_out() || bsock->is_terminated()) { - return nread; + return -1; } + +#ifdef HAVE_WIN32 + /* + * For Windows, we must simulate Unix errno on a socket + * error in order to handle errors correctly. + */ + if (nread == SOCKET_ERROR) { + DWORD err = WSAGetLastError(); + nread = -1; + if (err == WSAEINTR) { + errno = EINTR; + } else if (err == WSAEWOULDBLOCK) { + errno = EAGAIN; + } else { + errno = EIO; /* some other error */ + } + } +#endif + if (nread == -1) { if (errno == EINTR) { continue; } if (errno == EAGAIN) { - bmicrosleep(0, 200000); /* try again in 200ms */ + bmicrosleep(0, 20000); /* try again in 20ms */ continue; } } if (nread <= 0) { - return nread; /* error, or EOF */ + return -1; /* error, or EOF */ } nleft -= nread; ptr += nread; @@ -135,8 +153,27 @@ int32_t write_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes) errno = 0; nwritten = socketWrite(bsock->m_fd, ptr, nleft); if (bsock->is_timed_out() || bsock->is_terminated()) { - return nwritten; + return -1; + } + +#ifdef HAVE_WIN32 + /* + * For Windows, we must simulate Unix errno on a socket + * error in order to handle errors correctly. + */ + if (nwritten == SOCKET_ERROR) { + DWORD err = WSAGetLastError(); + nwritten = -1; + if (err == WSAEINTR) { + errno = EINTR; + } else if (err == WSAEWOULDBLOCK) { + errno = EAGAIN; + } else { + errno = EIO; /* some other error */ + } } +#endif + } while (nwritten == -1 && errno == EINTR); /* * If connection is non-blocking, we will get EAGAIN, so @@ -149,13 +186,13 @@ int32_t write_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes) FD_ZERO(&fdset); FD_SET((unsigned)bsock->m_fd, &fdset); - tv.tv_sec = 10; + tv.tv_sec = 1; tv.tv_usec = 0; select(bsock->m_fd + 1, NULL, &fdset, NULL, &tv); continue; } if (nwritten <= 0) { - return nwritten; /* error */ + return -1; /* error */ } nleft -= nwritten; ptr += nwritten; @@ -192,7 +229,7 @@ int32_t bnet_recv(BSOCK * bsock) */ bool is_bnet_stop(BSOCK * bsock) { - return bsock->errors || bsock->is_terminated(); + return bsock->is_stop(); } /* @@ -200,8 +237,7 @@ bool is_bnet_stop(BSOCK * bsock) */ int is_bnet_error(BSOCK * bsock) { - errno = bsock->b_errno; - return bsock->errors; + return bsock->is_error(); } /* @@ -372,6 +408,64 @@ int bnet_wait_data_intr(BSOCK * bsock, int sec) #define NO_DATA 4 /* Valid name, no data record of requested type. */ #endif +#if HAVE_GETADDRINFO +const char *resolv_host(int family, const char *host, dlist *addr_list) +{ + int res; + struct addrinfo hints; + struct addrinfo *ai, *rp; + IPADDR *addr; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = family; + hints.ai_socktype = 0; + hints.ai_protocol = 0; + hints.ai_flags = 0; + + res = getaddrinfo(host, NULL, &hints, &ai); + if (res != 0) { + return gai_strerror(res); + } + + for (rp = ai; rp != NULL; rp = rp->ai_next) { + switch (rp->ai_addr->sa_family) { + case AF_INET: + addr = New(IPADDR(rp->ai_addr->sa_family)); + addr->set_type(IPADDR::R_MULTIPLE); + /* + * Some serious casting to get the struct in_addr * + * rp->ai_addr == struct sockaddr + * as this is AF_INET family we can cast that + * to struct_sockaddr_in. Of that we need the + * address of the sin_addr member which contains a + * struct in_addr + */ + addr->set_addr4(&(((struct sockaddr_in *)rp->ai_addr)->sin_addr)); + break; +#ifdef HAVE_IPV6 + case AF_INET6: + addr = New(IPADDR(rp->ai_addr->sa_family)); + addr->set_type(IPADDR::R_MULTIPLE); + /* + * Some serious casting to get the struct in6_addr * + * rp->ai_addr == struct sockaddr + * as this is AF_INET6 family we can cast that + * to struct_sockaddr_in6. Of that we need the + * address of the sin6_addr member which contains a + * struct in6_addr + */ + addr->set_addr6(&(((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr)); + break; +#endif + default: + continue; + } + addr_list->append(addr); + } + freeaddrinfo(ai); + return NULL; +} +#else /* * Get human readable error for gethostbyname() */ @@ -404,21 +498,12 @@ static const char *gethost_strerror() return msg; } - - - -static IPADDR *add_any(int family) -{ - IPADDR *addr = New(IPADDR(family)); - addr->set_type(IPADDR::R_MULTIPLE); - addr->set_addr_any(); - return addr; -} - -static const char *resolv_host(int family, const char *host, dlist * addr_list) +static const char *resolv_host(int family, const char *host, dlist *addr_list) { struct hostent *hp; const char *errmsg; + char **p; + IPADDR *addr; P(ip_mutex); /* gethostbyname() is not thread safe */ #ifdef HAVE_GETHOSTBYNAME2 @@ -431,24 +516,38 @@ static const char *resolv_host(int family, const char *host, dlist * addr_list) V(ip_mutex); return errmsg; } else { - char **p; for (p = hp->h_addr_list; *p != 0; p++) { - 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); - } + switch (hp->h_addrtype) { + case AF_INET: + addr = New(IPADDR(hp->h_addrtype)); + addr->set_type(IPADDR::R_MULTIPLE); + addr->set_addr4((struct in_addr *)*p); + break; #ifdef HAVE_IPV6 - else { - addr->set_addr6((struct in6_addr*)*p); - } + case AF_INET6: + addr = New(IPADDR(hp->h_addrtype)); + addr->set_type(IPADDR::R_MULTIPLE); + addr->set_addr6((struct in6_addr *)*p); + break; #endif + default: + continue; + } addr_list->append(addr); } V(ip_mutex); } return NULL; } +#endif + +static IPADDR *add_any(int family) +{ + IPADDR *addr = New(IPADDR(family)); + addr->set_type(IPADDR::R_MULTIPLE); + addr->set_addr_any(); + return addr; +} /* * i host = 0 mean INADDR_ANY only ipv4 @@ -533,8 +632,6 @@ BSOCK *bnet_connect(JCR * jcr, int retry_interval, utime_t max_retry_time, return bsock; } - - /* * Return the string for the error that occurred * on the socket. Only the first error is retained. @@ -618,7 +715,6 @@ void bnet_restore_blocking (BSOCK *bsock, int flags) bsock->restore_blocking(flags); } - /* * Send a network "signal" to the other end * This consists of sending a negative packet length @@ -653,8 +749,10 @@ const char *bnet_sig_to_ascii(BSOCK * bs) return "BNET_HEARTBEAT"; case BNET_HB_RESPONSE: return "BNET_HB_RESPONSE"; - case BNET_PROMPT: - return "BNET_PROMPT"; + case BNET_SUB_PROMPT: + return "BNET_SUB_PROMPT"; + case BNET_TEXT_INPUT: + return "BNET_TEXT_INPUT"; default: sprintf(buf, _("Unknown sig %d"), (int)bs->msglen); return buf; @@ -674,7 +772,7 @@ BSOCK *init_bsock(JCR * jcr, int sockfd, const char *who, const char *host, int bsock->tls = NULL; bsock->errors = 0; bsock->m_blocking = 1; - bsock->msg = get_pool_memory(PM_MESSAGE); + bsock->msg = get_pool_memory(PM_BSOCK); bsock->errmsg = get_pool_memory(PM_MESSAGE); bsock->set_who(bstrdup(who)); bsock->set_host(bstrdup(host)); @@ -694,7 +792,7 @@ BSOCK *dup_bsock(BSOCK *osock) { BSOCK *bsock = (BSOCK *)malloc(sizeof(BSOCK)); memcpy(bsock, osock, sizeof(BSOCK)); - bsock->msg = get_pool_memory(PM_MESSAGE); + bsock->msg = get_pool_memory(PM_BSOCK); bsock->errmsg = get_pool_memory(PM_MESSAGE); if (osock->who()) { bsock->set_who(bstrdup(osock->who())); @@ -702,6 +800,9 @@ BSOCK *dup_bsock(BSOCK *osock) if (osock->host()) { bsock->set_host(bstrdup(osock->host())); } + if (osock->src_addr) { + bsock->src_addr = New( IPADDR( *(osock->src_addr)) ); + } bsock->set_duped(); return bsock; }