AC_DEFINE(HAVE_SA_LEN, 1, [Define if sa_len field exists in struct sockaddr])
fi
+dnl
+dnl check for working getaddrinfo()
+dnl
+dnl Note that if the system doesn't have gai_strerror(), we
+dnl can't use getaddrinfo() because we can't get strings
+dnl describing the error codes.
+dnl
+AC_CACHE_CHECK(for working getaddrinfo, ac_cv_working_getaddrinfo,
+ [
+ AC_TRY_RUN(
+ [
+ #include <netdb.h>
+ #include <string.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+
+ void main(void) {
+ struct addrinfo hints, *ai;
+ int error;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ error = getaddrinfo("127.0.0.1", NULL, &hints, &ai);
+ if (error) {
+ exit(1);
+ }
+ if (ai->ai_addr->sa_family != AF_INET) {
+ exit(1);
+ }
+ exit(0);
+ }
+ ],[
+ ac_cv_working_getaddrinfo="yes"
+ ],[
+ ac_cv_working_getaddrinfo="no"
+ ],[
+ ac_cv_working_getaddrinfo="yes"
+ ]
+ )
+ ]
+)
+AC_CHECK_FUNC(gai_strerror, [AC_DEFINE(HAVE_GAI_STRERROR, 1, [Define to 1 if you have the 'gai_strerror' function.])])
+
+if test "$ac_cv_working_getaddrinfo" = "yes"; then
+ if test "$ac_cv_func_gai_strerror" != "yes"; then
+ ac_cv_working_getaddrinfo="no"
+ else
+ AC_DEFINE(HAVE_GETADDRINFO, 1, [Define to 1 if getaddrinfo exists and works])
+ fi
+fi
+
AC_FUNC_STRFTIME
AC_FUNC_VPRINTF
AC_FUNC_ALLOCA
*
*/
-
#include "bacula.h"
#include "jcr.h"
#include <netdb.h>
#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;
#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()
*/
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
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
return bsock;
}
-
-
/*
* Return the string for the error that occurred
* on the socket. Only the first error is retained.
bsock->restore_blocking(flags);
}
-
/*
* Send a network "signal" to the other end
* This consists of sending a negative packet length
copyright. See:
http://archives.neohapsis.com/archives/postfix/2000-05/1520.html
-
- Version $Id$
-
*/
-
#include "bacula.h"
#include "jcr.h"
#define MY_NAME "bsmtp"
#include <lmcons.h>
#endif
-/* Dummy functions */
+/*
+ * Dummy functions
+ */
int generate_daemon_event(JCR *jcr, const char *event)
- { return 1; }
+{
+ return 1;
+}
#ifndef MAXSTRING
#define MAXSTRING 254
/*
* Return the offset west from localtime to UTC in minutes
- * Same as timezone.tz_minuteswest
- * Unix tz_offset coded by: Attila Fülöp
- */
-
+ * Same as timezone.tz_minuteswest
+ * Unix tz_offset coded by: Attila Fülöp
+ */
static long tz_offset(time_t lnow, struct tm &tm)
{
#if defined(HAVE_WIN32)
my_timezone = tz_offset(now, tm);
strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S", &tm);
- sprintf(tzbuf, " %+2.2ld%2.2u", -my_timezone / 60, abs(my_timezone) % 60);
+ snprintf(tzbuf, sizeof(tzbuf), " %+2.2ld%2.2u", -my_timezone / 60, abs(my_timezone) % 60);
strcat(buf, tzbuf); /* add +0100 */
strftime(tzbuf, sizeof(tzbuf), " (%Z)", &tm);
strcat(buf, tzbuf); /* add (CEST) */
}
-
/*********************************************************************
*
* Program to send email
*/
int main (int argc, char *argv[])
{
- char buf[1000];
- struct sockaddr_in sin;
- struct hostent *hp;
- int i, ch;
- unsigned long maxlines, lines;
+ char buf[1000];
+ int i, ch;
+ unsigned long maxlines, lines;
#if defined(HAVE_WIN32)
- SOCKET s;
+ SOCKET s;
+#else
+ int s, r;
+ struct passwd *pwd;
+#endif
+ char *cp, *p;
+#ifdef HAVE_GETADDRINFO
+ int res;
+ struct addrinfo hints;
+ struct addrinfo *ai, *rp;
+ char mail_port[10];
#else
- int s, r;
- struct passwd *pwd;
+ struct hostent *hp;
+ struct sockaddr_in sin;
#endif
- char *cp, *p;
setlocale(LC_ALL, "en_US");
bindtextdomain("bacula", LOCALEDIR);
exit(1);
}
-
/*
* Determine SMTP server
*/
Pmsg1(0, _("Fatal gethostname error: ERR=%s\n"), strerror(errno));
exit(1);
}
+#ifdef HAVE_GETADDRINFO
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = 0;
+ hints.ai_protocol = 0;
+ hints.ai_flags = AI_CANONNAME;
+
+ if ((res = getaddrinfo(my_hostname, NULL, &hints, &ai)) != 0) {
+ Pmsg2(0, _("Fatal getaddrinfo for myself failed \"%s\": ERR=%s\n"),
+ my_hostname, gai_strerror(res));
+ exit(1);
+ }
+ strcpy(my_hostname, ai->ai_canonname);
+ freeaddrinfo(ai);
+#else
if ((hp = gethostbyname(my_hostname)) == NULL) {
- Pmsg2(0, _("Fatal gethostbyname for myself failed \"%s\": ERR=%s\n"), my_hostname,
- strerror(errno));
+ Pmsg2(0, _("Fatal gethostbyname for myself failed \"%s\": ERR=%s\n"),
+ my_hostname, strerror(errno));
exit(1);
}
strcpy(my_hostname, hp->h_name);
+#endif
Dmsg1(20, "My hostname is: %s\n", my_hostname);
/*
LPSTR lpszBuffer = (LPSTR)alloca(dwSize);
if (GetUserName(lpszBuffer, &dwSize)) {
- sprintf(buf, "%s@%s", lpszBuffer, my_hostname);
+ snprintf(buf, sizeof(buf), "%s@%s", lpszBuffer, my_hostname);
} else {
- sprintf(buf, "unknown-user@%s", my_hostname);
+ snprintf(buf, sizeof(buf), "unknown-user@%s", my_hostname);
}
#else
if ((pwd = getpwuid(getuid())) == 0) {
- sprintf(buf, "userid-%d@%s", (int)getuid(), my_hostname);
+ snprintf(buf, sizeof(buf), "userid-%d@%s", (int)getuid(), my_hostname);
} else {
- sprintf(buf, "%s@%s", pwd->pw_name, my_hostname);
+ snprintf(buf, sizeof(buf), "%s@%s", pwd->pw_name, my_hostname);
}
#endif
from_addr = bstrdup(buf);
/*
* Connect to smtp daemon on mailhost.
*/
-hp:
+lookup_host:
+#ifdef HAVE_GETADDRINFO
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_flags = 0;
+ snprintf(mail_port, sizeof(mail_port), "%d", mailport);
+
+ if ((res = getaddrinfo(mailhost, mail_port, &hints, &ai)) != 0) {
+ Pmsg2(0, _("Error unknown mail host \"%s\": ERR=%s\n"),
+ mailhost, gai_strerror(res));
+ if (!strcasecmp(mailhost, "localhost")) {
+ Pmsg0(0, _("Retrying connection using \"localhost\".\n"));
+ mailhost = "localhost";
+ goto lookup_host;
+ }
+ exit(1);
+ }
+
+ for (rp = ai; rp != NULL; rp = rp->ai_next) {
+#if defined(HAVE_WIN32)
+ s = WSASocket(rp->ai_family, rp->ai_socktype, rp->ai_protocol, NULL, 0, 0);
+#else
+ s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+#endif
+ if (s < 0) {
+ continue;
+ }
+
+ if (connect(s, rp->ai_addr, rp->ai_addrlen) != -1) {
+ break;
+ }
+
+ close(s);
+ }
+
+ if (!rp) {
+ Pmsg1(0, _("Failed to connect to mailhost %s\n"), mailhost);
+ exit(1);
+ }
+
+ freeaddrinfo(ai);
+#else
if ((hp = gethostbyname(mailhost)) == NULL) {
Pmsg2(0, _("Error unknown mail host \"%s\": ERR=%s\n"), mailhost,
strerror(errno));
if (strcasecmp(mailhost, "localhost") != 0) {
Pmsg0(0, _("Retrying connection using \"localhost\".\n"));
mailhost = "localhost";
- goto hp;
+ goto lookup_host;
}
exit(1);
}
exit(1);
}
Dmsg0(20, "Connected\n");
+#endif
#if defined(HAVE_WIN32)
int fdSocket = _open_osfhandle(s, _O_RDWR | _O_BINARY);