aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--COPYING6
-rw-r--r--Makefile.am9
-rw-r--r--NEWS11
-rw-r--r--checkalias.c134
-rw-r--r--conf.c11
-rw-r--r--configure.ac29
-rw-r--r--driver.c83
-rw-r--r--env.c37
-rw-r--r--fetchmail.c39
-rw-r--r--fetchmail.h20
-rw-r--r--fetchmail.man21
-rw-r--r--imap.c11
-rw-r--r--interface.c19
-rw-r--r--options.c10
-rw-r--r--rcfile_y.y12
-rw-r--r--servport.c25
-rw-r--r--socket.c141
-rw-r--r--transact.c25
18 files changed, 244 insertions, 399 deletions
diff --git a/COPYING b/COPYING
index 46d7c250..c2df4621 100644
--- a/COPYING
+++ b/COPYING
@@ -33,6 +33,12 @@ Stenberg and also under a liberal license:
| MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
| CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
+The m4/gethostbyname_r.m4 and libesmtp/* files functions are (C) by
+Brian Stafford, see the respective file headers for details.
+
+The KAME/* files are (C) Copyright (C) 1995, 1996, 1997, and 1998 WIDE
+Project, see the respective file headers for details.
+
All other code in the distribution incorporates the copy of GPL version 2
below by reference.
diff --git a/Makefile.am b/Makefile.am
index 6517be76..7c5dad3a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,7 +4,7 @@ SUBDIRS= m4 po
AUTOMAKE_OPTIONS= foreign no-dist-gzip dist-bzip2
AM_CFLAGS= @CEFLAGS@
-AM_CPPFLAGS= @CPFLAGS@
+AM_CPPFLAGS= @CPFLAGS@ -I$(srcdir)/libesmtp
AM_LDFLAGS= @LDEFLAGS@
ACLOCAL_AMFLAGS= -I m4 -I m4-local
AM_YFLAGS= -d
@@ -23,7 +23,8 @@ localedir= $(datadir)/locale
DEFS= @DEFS@ -DLOCALEDIR=\"$(localedir)\"
noinst_LIBRARIES= libfm.a
-libfm_a_SOURCES= xmalloc.c base64.c rfc822.c report.c rfc2047e.c servport.c
+libfm_a_SOURCES= xmalloc.c base64.c rfc822.c report.c rfc2047e.c servport.c \
+ libesmtp/gethostbyname.h libesmtp/gethostbyname.c
libfm_a_LIBADD= $(EXTRAOBJ)
libfm_a_DEPENDENCIES= $(EXTRAOBJ)
LDADD = libfm.a @LIBINTL@ $(LIBOBJS)
@@ -53,7 +54,9 @@ fetchmail_SOURCES= fetchmail.h getopt.h \
opie.c rpa.c interface.c netrc.c \
unmime.c conf.c checkalias.c smbdes.c smbencrypt.c \
smbmd4.c smbutil.c lock.c \
- rcfile_l.l rcfile_y.y ucs/norm_charmap.c
+ rcfile_l.l rcfile_y.y ucs/norm_charmap.c \
+ libesmtp/getaddrinfo.h libesmtp/getaddrinfo.c \
+ KAME/getnameinfo.c
check_PROGRAMS += rfc822 unmime netrc rfc2047e mxget
diff --git a/NEWS b/NEWS
index df9afe20..3c6b3f3c 100644
--- a/NEWS
+++ b/NEWS
@@ -29,6 +29,8 @@ fetchmail 6.3.0 (not yet released officially):
obsolete, deprecated and may be removed from a future fetchmail version
without further notice. Their support for IPv6 (including IPv6-mapped IPv4)
is unspecified. Matthias Andree
+* The monitor and interface options may also be removed from a future fetchmail
+ version as they are not sufficiently portable.
# OTHER USER-VISIBLE CHANGES
* Sunil Shetye's fix to force fetchsizelimit to 1 for APOP and RPOP. (ESR)
@@ -183,6 +185,15 @@ fetchmail 6.3.0 (not yet released officially):
the prompt. Reported by Michal Marek. Matthias Andree.
* Write RFC-compliant BSMTP envelopes. Reported by Nico Golde. Matthias Andree.
* Fix --with-gssapi compilation problem. Simon Josefsson. (MA)
+* Foster protocol-independence to support IPv6 better, for instance, providing
+ IPv6 addresses in Received: headers. Matthias Andree.
+* The --enable-inet6 configure option was removed. The code is mostly protocol
+ agnostic, a fully IPv6 aware OS is expected to provide getaddrinfo(),
+ getnameinfo() and the macro AF_INET6. Matthias Andree.
+* Received: headers now enclose the for <...> destination address in angle
+ brackets for consistency with Postfix. Matthias Andree.
+* Operating systems that do not support at least one of gethostbyname,
+ gethostbyname_r, getipnodebyname are no longer supported. Matthias Andree.
# INTERNAL CHANGES
* Switched to automake. Matthias Andree.
diff --git a/checkalias.c b/checkalias.c
index 2849213e..687b5478 100644
--- a/checkalias.c
+++ b/checkalias.c
@@ -5,7 +5,6 @@
* For license terms, see the file COPYING in this directory.
*/
#include "config.h"
-#ifdef HAVE_GETHOSTBYNAME
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -23,28 +22,32 @@
#include "i18n.h"
#include "mx.h"
#include "fetchmail.h"
+#include "getaddrinfo.h"
#define MX_RETRIES 3
typedef unsigned char address_t[sizeof (struct in_addr)];
-typedef struct _address_e
+static int getaddresses(struct addrinfo **result, const char *name)
{
- struct _address_e *next;
- address_t address;
-} address_e;
+ struct addrinfo hints, *res;
-static void free_addrlst(address_e *lst)
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype=SOCK_STREAM;
+ hints.ai_protocol=PF_UNSPEC;
+ hints.ai_family=AF_UNSPEC;
+ return getaddrinfo(name, NULL, &hints, result);
+}
+
+/* XXX FIXME: doesn't detect if an IPv6-mapped IPv4 address
+ * matches a real IPv4 address */
+static int compareaddr(const struct addrinfo *a1, const struct addrinfo *a2)
{
- address_e *i;
- while(lst) {
- i = lst->next;
- free(lst);
- lst = i;
- }
+ if (a1->ai_family != a2->ai_family) return FALSE;
+ if (a1->ai_addrlen != a2->ai_addrlen) return FALSE;
+ return (!memcmp(a1->ai_addr, a2->ai_addr, a1->ai_addrlen));
}
-/* XXX FIXME: This junk isn't IPv6 aware */
static int is_ip_alias(const char *name1,const char *name2)
/*
* Given two hostnames as arguments, returns TRUE if they
@@ -53,46 +56,21 @@ static int is_ip_alias(const char *name1,const char *name2)
* the calling function does them.
*/
{
- address_e *host_a_addr=0, *host_b_addr=0;
- address_e *dummy_addr, *ii, *ij;
-
int rc = FALSE;
struct hostent *hp;
char **p;
- hp = gethostbyname((char*)name1);
-
- dummy_addr = (address_e *)NULL;
-
- if (hp)
- for (p = hp->h_addr_list; *p != 0; p++) {
- struct in_addr in;
-
- host_a_addr = xmalloc(sizeof (address_e));
- memset (host_a_addr,0, sizeof (address_e));
- host_a_addr->next = dummy_addr;
- (void) memcpy(&host_a_addr->address, *p, sizeof (in.s_addr));
- dummy_addr = host_a_addr;
- }
+ struct addrinfo *res1 = NULL, *res2 = NULL, *ii, *ij;
- hp = gethostbyname((char*)name2);
+ if (getaddresses(&res1, name1))
+ goto found;
- dummy_addr = (address_e *)NULL;
+ if (getaddresses(&res2, name2))
+ goto found;
- if (hp)
- for (p = hp->h_addr_list; *p != 0; p++) {
- struct in_addr in;
-
- host_b_addr = xmalloc(sizeof (address_e));
- memset (host_b_addr,0, sizeof (address_e));
- host_b_addr->next = dummy_addr;
- (void) memcpy(&host_b_addr->address, *p, sizeof (in.s_addr));
- dummy_addr = host_b_addr;
- }
-
- for (ii = host_a_addr ; ii ; ii = ii -> next) {
- for (ij = host_b_addr ; ij ; ij = ij -> next) {
- if (!memcmp(ii->address, ij->address, sizeof (address_t))) {
+ for (ii = res1 ; ii ; ii = ii -> ai_next) {
+ for (ij = res2 ; ij ; ij = ij -> ai_next) {
+ if (compareaddr(ii, ij)) {
rc = TRUE;
goto found;
}
@@ -100,18 +78,20 @@ static int is_ip_alias(const char *name1,const char *name2)
}
found:
- free_addrlst(host_b_addr);
- free_addrlst(host_a_addr);
+ if (res2)
+ freeaddrinfo(res2);
+ if (res1)
+ freeaddrinfo(res1);
return rc;
}
int is_host_alias(const char *name, struct query *ctl)
/* determine whether name is a DNS alias of the mailserver for this query */
{
- struct hostent *he,*he_st;
struct mxentry *mxp, *mxrecords;
struct idlist *idl;
- int namelen;
+ int namelen, e;
+ struct addrinfo hints, *res, *res_st;
struct hostdata *lead_server =
ctl->server.lead_server ? ctl->server.lead_server : &ctl->server;
@@ -175,12 +155,21 @@ int is_host_alias(const char *name, struct query *ctl)
* delivering the current message or anything else from the
* current server until it's back up.
*/
- if ((he = gethostbyname((char*)name)) != (struct hostent *)NULL)
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family=AF_UNSPEC;
+ hints.ai_protocol=PF_UNSPEC;
+ hints.ai_socktype=SOCK_STREAM;
+
+ e = getaddrinfo(name, NULL, &hints, &res);
+ if (e == 0)
{
- if (strcasecmp(ctl->server.truename, he->h_name) == 0)
+ int rr = (strcasecmp(ctl->server.truename, res->ai_canonname) == 0);
+ freeaddrinfo(res);
+ if (rr)
goto match;
- else if (((he_st = gethostbyname(ctl->server.truename)) != (struct hostent *)NULL) && ctl->server.checkalias)
+ else if (ctl->server.checkalias && 0 == getaddrinfo(ctl->server.truename, NULL, &hints, &res_st))
{
+ freeaddrinfo(res_st);
if (outlevel >= O_DEBUG)
report(stdout, GT_("Checking if %s is really the same node as %s\n"),ctl->server.truename,name);
if (is_ip_alias(ctl->server.truename,name) == TRUE)
@@ -192,28 +181,24 @@ int is_host_alias(const char *name, struct query *ctl)
if (outlevel >= O_DEBUG)
report(stdout, GT_("No, their IP addresses don't match\n"));
return(FALSE);
- }
- else
+ } else {
return(FALSE);
+ }
}
else
- switch (h_errno)
+ switch (e)
{
- case HOST_NOT_FOUND: /* specified host is unknown */
-#ifndef __BEOS__
- case NO_ADDRESS: /* valid, but does not have an IP address */
- break;
-#endif
- case NO_RECOVERY: /* non-recoverable name server error */
- case TRY_AGAIN: /* temporary error on authoritative server */
- default:
- if (outlevel != O_SILENT)
- report_complete(stdout, "\n"); /* terminate the progress message */
- report(stderr,
- GT_("nameserver failure while looking for `%s' during poll of %s.\n"),
- name, ctl->server.pollname);
- ctl->errcount++;
- break;
+ case EAI_NONAME: /* specified host is unknown */
+ break;
+
+ default:
+ if (outlevel != O_SILENT)
+ report_complete(stdout, "\n"); /* terminate the progress message */
+ report(stderr,
+ GT_("nameserver failure while looking for '%s' during poll of %s: %s\n"),
+ name, ctl->server.pollname, gai_strerror(e));
+ ctl->errcount++;
+ break;
}
/*
@@ -227,7 +212,7 @@ int is_host_alias(const char *name, struct query *ctl)
switch (h_errno)
{
case HOST_NOT_FOUND: /* specified host is unknown */
-#ifndef __BEOS__
+#ifdef NO_ADDRESS
case NO_ADDRESS: /* valid, but does not have an IP address */
return(FALSE);
#endif
@@ -240,9 +225,7 @@ int is_host_alias(const char *name, struct query *ctl)
ctl->errcount++;
break;
}
- }
- else
- {
+ } else {
for (mxp = mxrecords; mxp->name; mxp++)
if (strcasecmp(ctl->server.truename, mxp->name) == 0
|| is_ip_alias(ctl->server.truename, mxp->name) == TRUE)
@@ -256,6 +239,5 @@ int is_host_alias(const char *name, struct query *ctl)
return(TRUE);
#endif /* HAVE_RES_SEARCH */
}
-#endif /* HAVE_GETHOSTBYNAME */
/* checkalias.c ends here */
diff --git a/conf.c b/conf.c
index f286154e..476f187d 100644
--- a/conf.c
+++ b/conf.c
@@ -184,9 +184,6 @@ void dump_config(struct runctl *runp, struct query *querylist)
#ifdef OPIE_ENABLE
"'opie',"
#endif /* OPIE_ENABLE */
-#ifdef INET6_ENABLE
- "'inet6',"
-#endif /* INET6_ENABLE */
")\n";
fputs(features, stdout);
@@ -288,18 +285,18 @@ void dump_config(struct runctl *runp, struct query *querylist)
else if (ctl->server.authenticate == A_OTP)
stringdump("auth", "otp");
-#if defined(HAVE_GETHOSTBYNAME) && defined(HAVE_RES_SEARCH)
+#ifdef HAVE_RES_SEARCH
booldump("dns", ctl->server.dns);
-#endif /* HAVE_GETHOSTBYNAME && HAVE_RES_SEARCH */
+#endif /* HAVE_RES_SEARCH */
booldump("uidl", ctl->server.uidl);
listdump("aka", ctl->server.akalist);
listdump("localdomains", ctl->server.localdomains);
-#if defined(linux) || defined(__FreeBSD__)
+#ifdef CAN_MONITOR
stringdump("interface", ctl->server.interface);
stringdump("monitor", ctl->server.monitor);
-#endif /* linux || __FreeBSD__ */
+#endif
stringdump("plugin", ctl->server.plugin);
stringdump("plugout", ctl->server.plugout);
diff --git a/configure.ac b/configure.ac
index c94790c4..f12aacf0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,10 +1,11 @@
dnl Autoconfigure input file for fetchmail
dnl Eric S. Raymond <esr@thyrsus.com>
+dnl Matthias Andree <matthias.andree@gmx.de>
dnl
dnl Process this file with autoconf to produce a configure script.
dnl
-AC_INIT([fetchmail],[6.2.9-rc1])
+AC_INIT([fetchmail],[6.2.9-rc2])
AC_CONFIG_SRCDIR([fetchmail.h])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_LIBOBJ_DIR([.])
@@ -30,6 +31,7 @@ AC_HEADER_TIME
AC_TYPE_SIZE_T
AC_TYPE_PID_T
AC_TYPE_SIGNAL
+AC_CHECK_TYPE(u_int32_t,unsigned int)
AC_CHECK_HEADERS([unistd.h termios.h termio.h sgtty.h stdarg.h \
sys/itimer.h fcntl.h sys/fcntl.h memory.h sys/wait.h \
arpa/inet.h arpa/nameser.h netinet/in.h net/socket.h \
@@ -117,11 +119,10 @@ AC_FUNC_VPRINTF
AC_SUBST(EXTRAOBJ)
-AC_CHECK_FUNCS(tcsetattr stty setsid geteuid seteuid gethostbyname \
- res_search strerror syslog \
- snprintf vprintf vsnprintf vsyslog \
- atexit inet_aton strftime setrlimit socketpair sigprocmask sigaction \
- strdup)
+AC_CHECK_FUNCS(tcsetattr stty setsid geteuid seteuid dnl
+ res_search strerror syslog snprintf vprintf vsnprintf vsyslog dnl
+ atexit inet_aton strftime setrlimit socketpair sigprocmask dnl
+ sigaction strdup setlocale)
# Under Red Hat 4.0 (and many other Linuxes) -lresolv is seriously flaky
# and breaks gethostbyname(2). It's better to use the bind stuff in the C
@@ -343,18 +344,8 @@ AC_ARG_ENABLE(opie,
[with_opie=no])
test "$with_opie" = "yes" && AC_DEFINE(OPIE_ENABLE,1,Define if you want OPIE support compiled in)
-AC_ARG_ENABLE(inet6,
- [ --enable-inet6 support IPv6],
-
- [ AC_CHECK_FUNC(getaddrinfo, [with_inet6=yes],
- [ LDFLAGS="$LDFLAGS -L/usr/inet6/lib";
- AC_CHECK_LIB(inet6, getaddrinfo, [with_inet6=yes
- LIBS="$LIBS -linet6"],
- [ echo 'configure: cannot find proper glibc version or libinet6,';
- echo ' which is required for IPv6 support.';
- exit 1]) ] )],
- [with_inet6=no])
-test "$with_inet6" = "yes" && AC_DEFINE(INET6_ENABLE,1,Define if you want IPv6 support compiled in)
+AC_SEARCH_LIBS(getaddrinfo, inet6, [AC_DEFINE(HAVE_GETADDRINFO,1,[define to 1 if you have the getaddrinfo function])])
+AC_CHECK_FUNCS(getnameinfo)
# This version of the Kerberos 4 and 5 options addresses the follwing issues:
#
@@ -639,6 +630,8 @@ then
LDFLAGS="$ac_savedLDFLAGS"
fi])
+ACX_WHICH_GETHOSTBYNAME_R
+
### use option --with-hesiod=DIR to point at a HESIOD directory
AC_ma_SEARCH_PACKAGE(hesiod, hesiod_getmailhost, /usr/athena /usr /usr/local,hesiod, hesiod.h)
diff --git a/driver.c b/driver.c
index 71bf3f02..7d38c71c 100644
--- a/driver.c
+++ b/driver.c
@@ -34,17 +34,13 @@
#ifdef HAVE_NET_SOCKET_H
#include <net/socket.h>
#endif
+#include <netdb.h>
#ifdef HAVE_PKG_hesiod
#include <hesiod.h>
#endif
#include <langinfo.h>
-#if defined(HAVE_RES_SEARCH) || defined(HAVE_GETHOSTBYNAME)
-#include <netdb.h>
-#include "mx.h"
-#endif /* defined(HAVE_RES_SEARCH) || defined(HAVE_GETHOSTBYNAME) */
-
#include "kerberos.h"
#ifdef KERBEROS_V4
#include <netinet/in.h>
@@ -54,6 +50,7 @@
#include "socket.h"
#include "fetchmail.h"
+#include "getaddrinfo.h"
#include "tunable.h"
/* throw types for runtime errors */
@@ -92,7 +89,7 @@ void resetidletimeout(void)
void set_timeout(int timeleft)
/* reset the nonresponse-timeout */
{
-#if !defined(__EMX__) && !defined(__BEOS__)
+#if !defined(__EMX__) && !defined(__BEOS__)
struct itimerval ntimeout;
if (timeleft == 0)
@@ -338,12 +335,12 @@ static void send_size_warnings(struct query *ctl)
return;
stuff_warning(iana_charset, ctl,
GT_("Subject: Fetchmail oversized-messages warning"));
- stuff_warning(NULL, ctl, "");
+ stuff_warning(NULL, ctl, "%s", "");
stuff_warning(NULL, ctl,
GT_("The following oversized messages remain on the mail server %s:"),
ctl->server.pollname);
- stuff_warning(NULL, ctl, "");
+ stuff_warning(NULL, ctl, "%s", "");
if (run.poll_interval == 0)
max_warning_poll_count = 0;
@@ -368,7 +365,7 @@ static void send_size_warnings(struct query *ctl)
current->val.status.num = 0;
}
- stuff_warning(NULL, ctl, "");
+ stuff_warning(NULL, ctl, "%s", "");
close_warning_by_mail(ctl, (struct msgblk *)NULL);
}
@@ -915,7 +912,7 @@ static int do_session(
{
stuff_warning(iana_charset, ctl,
GT_("Subject: fetchmail sees repeated timeouts"));
- stuff_warning(NULL, ctl, "");
+ stuff_warning(NULL, ctl, "%s", "");
stuff_warning(NULL, ctl,
GT_("Fetchmail saw more than %d timeouts while attempting to get mail from %s@%s.\n"),
MAX_TIMEOUTS,
@@ -976,7 +973,6 @@ static int do_session(
}
#endif /* HESIOD */
-#ifdef HAVE_GETHOSTBYNAME
/*
* Canonicalize the server truename for later use. This also
* functions as a probe for whether the mailserver is accessible.
@@ -1004,7 +1000,6 @@ static int do_session(
}
else
{
-#ifdef INET6_ENABLE
struct addrinfo hints, *res;
int error;
@@ -1027,43 +1022,14 @@ static int do_session(
else
{
xfree(ctl->server.truename);
- ctl->server.truename=xstrdup(res->ai_canonname);
- ctl->server.trueaddr=xmalloc(res->ai_addrlen);
+ ctl->server.truename = xstrdup(res->ai_canonname);
+ ctl->server.trueaddr = xmalloc(res->ai_addrlen);
+ ctl->server.trueaddr_len = res->ai_addrlen;
memcpy(ctl->server.trueaddr, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
}
-#else
- struct hostent *namerec;
-
- /*
- * Get the host's IP, so we can report it like this:
- *
- * Received: from hostname [10.0.0.1]
- */
- errno = 0;
- namerec = gethostbyname(ctl->server.queryname);
- if (namerec == (struct hostent *)NULL)
- {
- report(stderr,
- GT_("couldn't find canonical DNS name of %s (%s)\n"),
- ctl->server.pollname, ctl->server.queryname);
- err = PS_DNS;
- set_timeout(0);
- phase = oldphase;
- goto closeUp;
- }
- else
- {
- ctl->server.truename=xstrdup((char *)namerec->h_name);
- ctl->server.trueaddr=xmalloc(namerec->h_length);
- memcpy(ctl->server.trueaddr,
- namerec->h_addr_list[0],
- namerec->h_length);
- }
-#endif
}
}
-#endif /* HAVE_GETHOSTBYNAME */
realhost = ctl->server.via ? ctl->server.via : ctl->server.pollname;
@@ -1075,12 +1041,7 @@ static int do_session(
ctl->server.plugin)) == -1)
{
char errbuf[BUFSIZ];
-#ifndef INET6_ENABLE
int err_no = errno;
-#ifdef HAVE_RES_SEARCH
- if (err_no != 0 && h_errno != 0)
- report(stderr, GT_("internal inconsistency\n"));
-#endif
/*
* Avoid generating a bogus error every poll cycle when we're
* in daemon mode but the connection to the outside world
@@ -1091,25 +1052,6 @@ static int do_session(
{
report_build(stderr, GT_("%s connection to %s failed"),
ctl->server.base_protocol->name, ctl->server.pollname);
-#ifdef HAVE_RES_SEARCH
- if (h_errno != 0)
- {
- if (h_errno == HOST_NOT_FOUND)
- strlcpy(errbuf, GT_("host is unknown."), sizeof(errbuf));
-#ifndef __BEOS__
- else if (h_errno == NO_ADDRESS)
- strlcpy(errbuf, GT_("name is valid but has no IP address."), sizeof(errbuf));
-#endif
- else if (h_errno == NO_RECOVERY)
- strlcpy(errbuf, GT_("unrecoverable name server error."), sizeof(errbuf));
- else if (h_errno == TRY_AGAIN)
- strlcpy(errbuf, GT_("temporary name server error."), sizeof(errbuf));
- else
- snprintf (errbuf, sizeof(errbuf),
- GT_("unknown DNS error %d."), h_errno);
- }
- else
-#endif /* HAVE_RES_SEARCH */
strlcpy(errbuf, strerror(err_no), sizeof(errbuf));
report_complete(stderr, ": %s\n", errbuf);
@@ -1133,7 +1075,6 @@ static int do_session(
}
#endif
}
-#endif /* INET6_ENABLE */
err = PS_SOCKET;
set_timeout(0);
phase = oldphase;
@@ -1241,7 +1182,7 @@ static int do_session(
stuff_warning(iana_charset, ctl,
GT_("Subject: fetchmail authentication failed on %s@%s"),
ctl->remotename, ctl->server.truename);
- stuff_warning(NULL, ctl, "");
+ stuff_warning(NULL, ctl, "%s", "");
stuff_warning(NULL, ctl,
GT_("Fetchmail could not get mail from %s@%s.\n"),
ctl->remotename,
@@ -1314,7 +1255,7 @@ is restored."));
stuff_warning(iana_charset, ctl,
GT_("Subject: fetchmail authentication OK on %s@%s"),
ctl->remotename, ctl->server.truename);
- stuff_warning(NULL, ctl, "");
+ stuff_warning(NULL, ctl, "%s", "");
stuff_warning(NULL, ctl,
GT_("Fetchmail was able to log into %s@%s.\n"),
ctl->remotename,
diff --git a/env.c b/env.c
index 17d3bc66..cccc4f11 100644
--- a/env.c
+++ b/env.c
@@ -19,11 +19,11 @@
#ifdef HAVE_NET_SOCKET_H
#include <net/socket.h>
#endif
-#ifdef HAVE_GETHOSTBYNAME
#include <netdb.h>
-#endif /* HAVE_GETHOSTBYNAME */
-#include <sys/types.h>
+#include <sys/types.h>
+#include <sys/socket.h>
#include "fetchmail.h"
+#include "getaddrinfo.h"
#include "i18n.h"
#if defined(HAVE_SETLOCALE) && defined(ENABLE_NLS) && defined(HAVE_STRFTIME)
@@ -135,7 +135,8 @@ void envquery(int argc, char **argv)
char *host_fqdn(void)
/* get the FQDN of the machine we're running */
{
- char tmpbuf[HOSTLEN+1];
+ char tmpbuf[HOSTLEN+1];
+ char *result;
if (gethostname(tmpbuf, sizeof(tmpbuf)))
{
@@ -143,27 +144,35 @@ char *host_fqdn(void)
program_name);
exit(PS_DNS);
}
-#ifdef HAVE_GETHOSTBYNAME
+
/* if we got a . in the hostname assume it is a FQDN */
if (strchr(tmpbuf, '.') == NULL)
{
- struct hostent *hp;
-
- /** XXX FIXME: use getaddrinfo instead? */
/* if we got a basename (as we do in Linux) make a FQDN of it */
- hp = gethostbyname(tmpbuf);
- if (hp == (struct hostent *) NULL)
- {
+ struct addrinfo hints, *res, *res0;
+ int e;
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags=AI_CANONNAME;
+
+ e = getaddrinfo(tmpbuf, NULL, &hints, &res);
+ if (e) {
/* exit with error message */
fprintf(stderr,
GT_("gethostbyname failed for %s\n"), tmpbuf);
+ fprintf(stderr, "%s", gai_strerror(e));
exit(PS_DNS);
}
- return(xstrdup(hp->h_name));
+
+ result = xstrdup(res->ai_canonname);
+ freeaddrinfo(res);
}
else
-#endif /* HAVE_GETHOSTBYNAME */
- return(xstrdup(tmpbuf));
+ result = xstrdup(tmpbuf);
+
+ return result;
}
static char *tzoffset(time_t *now)
diff --git a/fetchmail.c b/fetchmail.c
index 84fed2c4..379fae16 100644
--- a/fetchmail.c
+++ b/fetchmail.c
@@ -233,9 +233,6 @@ int main(int argc, char **argv)
#ifdef OPIE_ENABLE
"+OPIE"
#endif /* OPIE_ENABLE */
-#ifdef INET6_ENABLE
- "+INET6"
-#endif /* INET6_ENABLE */
#ifdef HAVE_PKG_hesiod
"+HESIOD"
#endif
@@ -528,9 +525,7 @@ int main(int argc, char **argv)
}
}
-#ifdef linux
interface_init();
-#endif /* linux */
/* beyond here we don't want more than one fetchmail running per user */
umask(0077);
@@ -645,14 +640,14 @@ int main(int argc, char **argv)
}
}
-#if (defined(linux) && !defined(INET6_ENABLE)) || defined(__FreeBSD__)
+#ifdef CAN_MONITOR
/*
* Don't do monitoring if we were woken by a signal.
* Note that interface_approve() does its own error logging.
*/
if (!interface_approve(&ctl->server, !lastsig))
continue;
-#endif /* (defined(linux) && !INET6_ENABLE) || defined(__FreeBSD__) */
+#endif /* CAN_MONITOR */
dofastuidl = 0; /* this is reset in the driver if required */
@@ -709,7 +704,7 @@ int main(int argc, char **argv)
break;
}
-#if (defined(linux) && !defined(INET6_ENABLE)) || defined (__FreeBSD__)
+#ifdef CAN_MONITOR
if (ctl->server.monitor)
{
/*
@@ -720,7 +715,7 @@ int main(int argc, char **argv)
sleep(3);
interface_note_activity(&ctl->server);
}
-#endif /* (defined(linux) && !INET6_ENABLE) || defined(__FreeBSD__) */
+#endif /* CAN_MONITOR */
}
}
@@ -853,11 +848,11 @@ static void optmerge(struct query *h2, struct query *h1, int force)
FLAG_MERGE(server.uidl);
FLAG_MERGE(server.principal);
-#if defined(linux) || defined(__FreeBSD__)
+#ifdef CAN_MONITOR
FLAG_MERGE(server.interface);
- FLAG_MERGE(server.monitor);
FLAG_MERGE(server.interface_pair);
-#endif /* linux || defined(__FreeBSD__) */
+ FLAG_MERGE(server.monitor);
+#endif
FLAG_MERGE(server.plugin);
FLAG_MERGE(server.plugout);
@@ -1151,14 +1146,14 @@ static int load_params(int argc, char **argv, int optind)
if (!ctl->localnames) /* for local delivery via SMTP */
save_str_pair(&ctl->localnames, user, NULL);
-#if !defined(HAVE_GETHOSTBYNAME) || !defined(HAVE_RES_SEARCH)
+#ifndef HAVE_RES_SEARCH
/* can't handle multidrop mailboxes unless we can do DNS lookups */
if (MULTIDROP(ctl) && ctl->server.dns)
{
ctl->server.dns = FALSE;
report(stderr, GT_("fetchmail: warning: no DNS available to check multidrop fetches from %s\n"), ctl->server.pollname);
}
-#endif /* !HAVE_GETHOSTBYNAME || !HAVE_RES_SEARCH */
+#endif /* !HAVE_RES_SEARCH */
/*
* can't handle multidrop mailboxes without "envelope"
@@ -1179,7 +1174,6 @@ static int load_params(int argc, char **argv, int optind)
if (ctl->server.timeout == -1)
ctl->server.timeout = CLIENT_TIMEOUT;
-#ifndef INET6_ENABLE
/* sanity checks */
if (ctl->server.service) {
int port = servport(ctl->server.service);
@@ -1217,10 +1211,9 @@ static int load_params(int argc, char **argv, int optind)
}
}
}
-#endif /* !INET6_ENABLE */
/*
- * "I beg to you, have mercy on the week minds like myself."
+ * "I beg to you, have mercy on the we[a]k minds like myself."
* wrote Pehr Anderson. Your petition is granted.
*/
if (ctl->fetchall && ctl->keep && run.poll_interval && !nodetach)
@@ -1417,12 +1410,7 @@ static int query_host(struct query *ctl)
report(stderr, GT_("ETRN support is not configured.\n"));
st = PS_PROTOCOL;
#else
-#ifdef HAVE_GETHOSTBYNAME
st = doETRN(ctl);
-#else
- report(stderr, GT_("Cannot support ETRN without gethostbyname(2).\n"));
- st = PS_PROTOCOL;
-#endif /* HAVE_GETHOSTBYNAME */
break;
#endif /* ETRN_ENABLE */
case P_ODMR:
@@ -1430,12 +1418,7 @@ static int query_host(struct query *ctl)
report(stderr, GT_("ODMR support is not configured.\n"));
st = PS_PROTOCOL;
#else
-#ifdef HAVE_GETHOSTBYNAME
st = doODMR(ctl);
-#else
- report(stderr, GT_("Cannot support ODMR without gethostbyname(2).\n"));
- st = PS_PROTOCOL;
-#endif /* HAVE_GETHOSTBYNAME */
#endif /* ODMR_ENABLE */
break;
default:
@@ -1825,7 +1808,7 @@ static void dump_params (struct runctl *runp,
}
}
}
-#if defined(linux) || defined(__FreeBSD__)
+#ifdef CAN_MONITOR
if (ctl->server.interface)
printf(GT_(" Connection must be through interface %s.\n"), ctl->server.interface);
else if (outlevel >= O_VERBOSE)
diff --git a/fetchmail.h b/fetchmail.h
index 7b2076d6..cefe6666 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -1,3 +1,5 @@
+#ifndef _FETCHMAIL_H
+#define _FETCHMAIL_H
/*
* For license terms, see the file COPYING in this directory.
*/
@@ -243,11 +245,15 @@ struct hostdata /* shared among all user connections to given server */
char *esmtp_name, *esmtp_password; /* ESMTP AUTH information */
#if defined(linux) || defined(__FreeBSD__)
+#define CAN_MONITOR
+#endif
+
+#ifdef CAN_MONITOR
char *interface;
char *monitor;
int monitor_io;
struct interface_pair_s *interface_pair;
-#endif /* linux */
+#endif
char *plugin,*plugout;
@@ -256,7 +262,8 @@ struct hostdata /* shared among all user connections to given server */
int poll_count; /* count of polls so far */
char *queryname; /* name to attempt DNS lookup on */
char *truename; /* "true name" of server host */
- char *trueaddr; /* IP address of truename, as char */
+ struct sockaddr *trueaddr; /* IP address of truename */
+ size_t trueaddr_len; /* size of trueaddr data */
struct hostdata *lead_server; /* ptr to lead query for this server */
int esmtp_options;
};
@@ -707,4 +714,13 @@ strlcpy(char *dst, const char *src, size_t siz);
* positive integer to a port number. Returns -1 for error. */
int servport(const char *service);
+#ifndef HAVE_GETNAMEINFO
+# define NI_NUMERICHOST 1
+# define NI_NUMERICSERV 2
+# define NI_NOFQDN 4
+# define NI_NAMEREQD 8
+# define NI_DGRAM 16
+#endif
+
+#endif
/* fetchmail.h ends here */
diff --git a/fetchmail.man b/fetchmail.man
index 48a17776..3979bdaf 100644
--- a/fetchmail.man
+++ b/fetchmail.man
@@ -596,8 +596,8 @@ See USER AUTHENTICATION below for a complete description.
.B \-I <specification> | \-\-interface <specification>
(Keyword: interface)
Require that a specific interface device be up and have a specific local
-or remote IP address (or range) before polling. Frequently
-.I fetchmail
+or remote IPv4 (IPv6 is not supported by this option yet) address (or
+range) before polling. Frequently \fIfetchmail\fP
is used over a transient point-to-point TCP/IP link established directly
to a mailserver via SLIP or PPP. That is a relatively secure channel.
But when other TCP/IP routes to the mailserver exist (e.g. when the link
@@ -609,7 +609,7 @@ the specified link is not up or is not connected to a matching IP
address, polling will be skipped. The format is:
.sp
.nf
- interface/iii.iii.iii.iii/mmm.mmm.mmm.mmm
+ interface/iii.iii.iii.iii[/mmm.mmm.mmm.mmm]
.fi
.sp
The field before the first slash is the interface name (i.e. sl0, ppp0
@@ -620,6 +620,8 @@ assumed (i.e. an exact match). This option is currently only supported
under Linux and FreeBSD. Please see the
.B monitor
section for below for FreeBSD specific information.
+.sp
+Note that this option may be removed from a future fetchmail version.
.TP
.B \-M <interface> | \-\-monitor <interface>
(Keyword: monitor)
@@ -640,6 +642,8 @@ must be installed SGID kmem. This would be a security hole, but
fetchmail runs with the effective GID set to that of the kmem group
.I only
when interface data is being collected.
+.sp
+Note that this option may be removed from a future fetchmail version.
.TP
.B \-\-auth <type>
(Keyword: auth[enticate])
@@ -2101,7 +2105,8 @@ This is a convenient but also slow method. To speed
it up, pre-declare mailserver aliases with 'aka'; these are checked
before DNS lookups are done. If you're certain your aka list contains
.B all
-DNS aliases of the mailserver (and all MX names pointing at it)
+DNS aliases of the mailserver (and all MX names pointing at it - note
+this may change in a future version)
you can declare 'no dns' to suppress DNS lookups entirely and
\fIonly\fR match against the aka list.
@@ -2241,9 +2246,11 @@ in foreground while a background fetchmail is running will do
whichever of these is appropriate to wake it up.
.SH BUGS AND KNOWN PROBLEMS
+.PP
The assumptions that the DNS and in particular the checkalias options
make are not often sustainable. For instance, it has become uncommon for
-an MX server to be a POP3 or IMAP server at the same time.
+an MX server to be a POP3 or IMAP server at the same time. Therefore the
+MX lookups may go away in a future release.
.PP
The mda and plugin options interact badly. In order to collect error
status from the MDA, fetchmail has to change its normal signal
@@ -2252,6 +2259,10 @@ of the poll cycle. This can cause resource starvation if too many
zombies accumulate. So either don't deliver to a MDA using plugins or
risk being overrun by an army of undead.
.PP
+The --interface option does not support IPv6 and it is doubtful if it
+ever will, since there is no portable way to query interface IPv6
+addresses.
+.PP
The RFC822 address parser used in multidrop mode chokes on some
@-addresses that are technically legal but bizarre. Strange uses of
quoting and embedded comments are likely to confuse it.
diff --git a/imap.c b/imap.c
index 7440abb0..4d6727b1 100644
--- a/imap.c
+++ b/imap.c
@@ -392,15 +392,18 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
if ((ctl->server.authenticate == A_ANY
|| ctl->server.authenticate == A_GSSAPI)
&& strstr(capabilities, "AUTH=GSSAPI"))
- if(ok = do_gssauth(sock, "AUTHENTICATE", "imap", ctl->server.truename, ctl->remotename))
+ {
+ if ((ok = do_gssauth(sock, "AUTHENTICATE", "imap",
+ ctl->server.truename, ctl->remotename)))
{
/* SASL cancellation of authentication */
gen_send(sock, "*");
- if(ctl->server.authenticate != A_ANY)
+ if (ctl->server.authenticate != A_ANY)
return ok;
- }
- else
+ } else {
return ok;
+ }
+ }
#endif /* GSSAPI */
#ifdef KERBEROS_V4
diff --git a/interface.c b/interface.c
index b4e7f063..d4688094 100644
--- a/interface.c
+++ b/interface.c
@@ -11,6 +11,10 @@
*
* For license terms, see the file COPYING in this directory.
*/
+
+#include "fetchmail.h"
+#ifdef CAN_MONITOR
+
#include <sys/types.h>
#include <sys/param.h>
@@ -18,9 +22,6 @@
#include <sys/utsname.h>
#endif
-#if (defined(linux) && !defined(INET6_ENABLE)) || defined(__FreeBSD__)
-
-#include "config.h"
#include <stdio.h>
#include <string.h>
#if defined(STDC_HEADERS)
@@ -48,8 +49,6 @@
#include <net/if_dl.h>
#endif
#endif
-#include "config.h"
-#include "fetchmail.h"
#include "socket.h"
#include "i18n.h"
#include "tunable.h"
@@ -74,7 +73,7 @@ static char *netdevfmt;
*/
#define MONITOR_SLOP 5
-#if defined(linux)
+#ifdef linux
void interface_init(void)
/* figure out which /proc/net/dev format to use */
@@ -545,7 +544,11 @@ get_ifinfo_end:
#endif /* __FREEBSD_USE_SYSCTL_GET_IFFINFO */
-#endif /* defined __FreeBSD__ */
+#else
+
+void interface_init(void) {};
+
+#endif
#ifndef HAVE_INET_ATON
@@ -734,4 +737,4 @@ int interface_approve(struct hostdata *hp, flag domonitor)
return(TRUE);
}
-#endif /* (defined(linux) && !defined(INET6_ENABLE)) || defined(__FreeBSD__) */
+#endif /* CAN_MONITOR */
diff --git a/options.c b/options.c
index 25c1c5e3..93557dee 100644
--- a/options.c
+++ b/options.c
@@ -160,10 +160,10 @@ static const struct option longoptions[] = {
{"principal", required_argument, (int *) 0, LA_PRINCIPAL },
-#if (defined(linux) && !defined(INET6_ENABLE)) || defined(__FreeBSD__)
+#ifdef CAN_MONITOR
{"interface", required_argument, (int *) 0, LA_INTERFACE },
{"monitor", required_argument, (int *) 0, LA_MONITOR },
-#endif /* (defined(linux) && !INET6_ENABLE) || defined(__FreeBSD__) */
+#endif /* CAN_MONITOR */
{"plugin", required_argument, (int *) 0, LA_PLUGIN },
{"plugout", required_argument, (int *) 0, LA_PLUGOUT },
@@ -547,7 +547,7 @@ struct query *ctl; /* option record to be initialized */
ctl->listener = LMTP_MODE;
break;
-#if (defined(linux) && !defined(INET6_ENABLE)) || defined(__FreeBSD__)
+#ifdef CAN_MONITOR
case 'I':
case LA_INTERFACE:
interface_parse(optarg, &ctl->server);
@@ -556,7 +556,7 @@ struct query *ctl; /* option record to be initialized */
case LA_MONITOR:
ctl->server.monitor = xstrdup(optarg);
break;
-#endif /* (defined(linux) && !INET6_ENABLE) || defined(__FreeBSD__) */
+#endif /* CAN_MONITOR */
case LA_PLUGIN:
ctl->server.plugin = xstrdup(optarg);
break;
@@ -653,7 +653,7 @@ struct query *ctl; /* option record to be initialized */
P(GT_(" -i, --idfile specify alternate UIDs file\n"));
P(GT_(" --postmaster specify recipient of last resort\n"));
P(GT_(" --nobounce redirect bounces from user to postmaster.\n"));
-#if (defined(linux) && !defined(INET6_ENABLE)) || defined(__FreeBSD__)
+#ifdef CAN_MONITOR
P(GT_(" -I, --interface interface required specification\n"));
P(GT_(" -M, --monitor monitor interface for activity\n"));
#endif
diff --git a/rcfile_y.y b/rcfile_y.y
index 518b0ecb..48ddac9d 100644
--- a/rcfile_y.y
+++ b/rcfile_y.y
@@ -200,18 +200,18 @@ serv_option : AKA alias_list
| QVIRTUAL STRING {current.server.qvirtual=xstrdup($2);}
| INTERFACE STRING {
-#if (defined(linux) && !defined(INET6_ENABLE)) || defined(__FreeBSD__)
+#ifdef CAN_MONITOR
interface_parse($2, &current.server);
-#else /* (defined(linux) && !defined(INET6_ENABLE)) || defined(__FreeBSD__) */
+#else
fprintf(stderr, GT_("fetchmail: interface option is only supported under Linux (without IPv6) and FreeBSD\n"));
-#endif /* (defined(linux) && !defined(INET6_ENABLE)) || defined(__FreeBSD__) */
+#endif
}
| MONITOR STRING {
-#if (defined(linux) && !defined(INET6_ENABLE)) || defined(__FreeBSD__)
+#ifdef CAN_MONITOR
current.server.monitor = xstrdup($2);
-#else /* (defined(linux) && !defined(INET6_ENABLE)) || defined(__FreeBSD__) */
+#else
fprintf(stderr, GT_("fetchmail: monitor option is only supported under Linux (without IPv6) and FreeBSD\n"));
-#endif /* (defined(linux) && !defined(INET6_ENABLE) || defined(__FreeBSD__)) */
+#endif
}
| PLUGIN STRING { current.server.plugin = xstrdup($2); }
| PLUGOUT STRING { current.server.plugout = xstrdup($2); }
diff --git a/servport.c b/servport.c
index 0cc9fa88..8d609bce 100644
--- a/servport.c
+++ b/servport.c
@@ -6,11 +6,13 @@
* For license terms, see the file COPYING in this directory.
*/
#include "fetchmail.h"
+#include "getaddrinfo.h"
#include "i18n.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
#include <netdb.h>
#if defined(HAVE_NETINET_IN_H)
#include <netinet/in.h>
@@ -18,6 +20,7 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
+#include <sys/socket.h>
int servport(const char *service) {
int port;
@@ -34,20 +37,30 @@ int servport(const char *service) {
errno = 0;
u = strtoul(service, &end, 10);
if (errno || end[strspn(end, POSIX_space)] != '\0') {
- struct servent *se;
+ struct addrinfo hints, *res;
/* hardcode kpop to port 1109 as per fetchmail(1)
* manual page, it's not a IANA registered service */
if (strcmp(service, "kpop") == 0)
return 1109;
- se = getservbyname(service, "tcp");
- if (se == NULL) {
- endservent();
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ if (getaddrinfo(NULL, service, &hints, &res)) {
goto err;
} else {
- port = ntohs(se->s_port);
- endservent();
+ switch(res->ai_addr->sa_family) {
+ case AF_INET:
+ port = ntohs(((struct sockaddr_in *)res->ai_addr)->sin_port);
+#ifdef AF_INET6
+ case AF_INET6:
+ port = ntohs(((struct sockaddr_in6 *)res->ai_addr)->sin6_port);
+#endif
+ default:
+ goto err;
+ }
+ freeaddrinfo(res);
}
} else {
if (u == 0 || u > 65535)
diff --git a/socket.c b/socket.c
index 698148c4..5e7aa569 100644
--- a/socket.c
+++ b/socket.c
@@ -50,6 +50,7 @@
#include "socket.h"
#include "fetchmail.h"
+#include "getaddrinfo.h"
#include "i18n.h"
/* Defines to allow BeOS and Cygwin to play nice... */
@@ -262,7 +263,6 @@ int UnixOpen(const char *path)
return sock;
}
-#ifdef INET6_ENABLE
int SockOpen(const char *host, const char *service,
const char *plugin)
{
@@ -276,8 +276,10 @@ int SockOpen(const char *host, const char *service,
memset(&req, 0, sizeof(struct addrinfo));
req.ai_socktype = SOCK_STREAM;
- if (getaddrinfo(host, service, &req, &ai0)) {
- report(stderr, GT_("fetchmail: getaddrinfo(%s.%s)\n"), host,service);
+ i = getaddrinfo(host, service, &req, &ai0);
+ if (i) {
+ report(stderr, GT_("fetchmail: getaddrinfo(\"%s\",\"%s\") error: %s\n"),
+ host, service, gai_strerror(i));
return -1;
}
@@ -308,139 +310,6 @@ int SockOpen(const char *host, const char *service,
return i;
}
-#else /* INET6_ENABLE */
-#ifndef HAVE_INET_ATON
-#ifndef INADDR_NONE
-#ifdef INADDR_BROADCAST
-#define INADDR_NONE INADDR_BROADCAST
-#else
-#define INADDR_NONE -1
-#endif
-#endif
-#endif /* HAVE_INET_ATON */
-
-int SockOpen(const char *host, const char *service,
- const char *plugin)
-{
- int sock = -1; /* pacify -Wall */
-#ifndef HAVE_INET_ATON
- unsigned long inaddr;
-#endif /* HAVE_INET_ATON */
- struct sockaddr_in ad, **pptr;
- struct hostent *hp;
- int clientPort = servport(service);
-
-#ifdef HAVE_SOCKETPAIR
- if (plugin) {
- return handle_plugin(host,service,plugin);
- }
-#endif /* HAVE_SOCKETPAIR */
-
- if (clientPort < 0)
- return sock;
-
- memset(&ad, 0, sizeof(ad));
- ad.sin_family = AF_INET;
-
- /* we'll accept a quad address */
-#ifndef HAVE_INET_ATON
- inaddr = inet_addr((char*)host);
- if (inaddr != INADDR_NONE)
- {
- memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr));
-#else
- if (inet_aton(host, &ad.sin_addr))
- {
-#endif /* HAVE_INET_ATON */
- ad.sin_port = htons(clientPort);
-
- sock = socket(AF_INET, SOCK_STREAM, 0);
- if (sock < 0)
- {
- h_errno = 0;
- return -1;
- }
-
- /* Socket opened saved. Usefull if connect timeout because
- * it can be closed
- */
- mailserver_socket_temp = sock;
-
- if (connect(sock, (struct sockaddr *) &ad, sizeof(ad)) < 0)
- {
- int olderr = errno;
- fm_close(sock); /* don't use SockClose, no traffic yet */
- h_errno = 0;
- errno = olderr;
- return -1;
- }
-
- /* No connect timeout, then no need to set mailserver_socket_temp */
- mailserver_socket_temp = -1;
-
- }
- else {
- hp = gethostbyname((char*)host);
-
- if (hp == NULL)
- {
- errno = 0;
- return -1;
- }
- /*
- * Add a check to make sure the address has a valid IPv4 or IPv6
- * length. This prevents buffer spamming by a broken DNS.
- */
- if(hp->h_length != 4 && hp->h_length != 8)
- {
- h_errno = errno = 0;
- report(stderr,
- GT_("fetchmail: illegal address length received for host %s\n"),host);
- return -1;
- }
- /*
- * Try all addresses of a possibly multihomed host until we get
- * a successful connect or until we run out of addresses.
- */
- pptr = (struct sockaddr_in **)hp->h_addr_list;
- for(; *pptr != NULL; pptr++)
- {
- sock = socket(AF_INET, SOCK_STREAM, 0);
- if (sock < 0)
- {
- h_errno = 0;
- return -1;
- }
-
- /* Socket opened saved. Usefull if connect timeout because
- * it can be closed
- */
- mailserver_socket_temp = sock;
-
- ad.sin_port = htons(clientPort);
- memcpy(&ad.sin_addr, *pptr, sizeof(struct in_addr));
- if (connect(sock, (struct sockaddr *) &ad, sizeof(ad)) == 0) {
- /* No connect timeout, then no need to set mailserver_socket_temp */
- mailserver_socket_temp = -1;
- break; /* success */
- }
- fm_close(sock); /* don't use SockClose, no traffic yet */
- memset(&ad, 0, sizeof(ad));
- ad.sin_family = AF_INET;
- }
- if(*pptr == NULL)
- {
- int olderr = errno;
- fm_close(sock); /* don't use SockClose, no traffic yet */
- h_errno = 0;
- errno = olderr;
- return -1;
- }
- }
-
- return(sock);
-}
-#endif /* INET6_ENABLE */
#if defined(HAVE_STDARG_H)
diff --git a/transact.c b/transact.c
index 63f7da80..7c348f3d 100644
--- a/transact.c
+++ b/transact.c
@@ -29,6 +29,8 @@
#ifdef HAVE_NET_SOCKET_H
#include <net/socket.h>
#endif
+#include <sys/socket.h>
+#include <netdb.h>
#include "md5.h"
#include "i18n.h"
@@ -1119,16 +1121,19 @@ int readheaders(int sock,
{
/* utter any per-message Received information we need here */
if (ctl->server.trueaddr) {
- /* XXX FIXME: IPv6 */
+ char saddr[50];
+ int e;
+
+ e = getnameinfo(ctl->server.trueaddr, ctl->server.trueaddr_len,
+ saddr, sizeof(saddr), NULL, 0,
+ NI_NUMERICHOST);
+ if (e)
+ snprintf(saddr, sizeof(saddr), "(%-.*s)", sizeof(saddr) - 3, gai_strerror(e));
snprintf(buf, sizeof(buf),
- "Received: from %s [%u.%u.%u.%u]\r\n",
- ctl->server.truename,
- (unsigned int)(unsigned char)ctl->server.trueaddr[0],
- (unsigned int)(unsigned char)ctl->server.trueaddr[1],
- (unsigned int)(unsigned char)ctl->server.trueaddr[2],
- (unsigned int)(unsigned char)ctl->server.trueaddr[3]);
+ "Received: from %s [%s]\r\n",
+ ctl->server.truename, saddr);
} else {
- snprintf(buf, sizeof(buf),
+ snprintf(buf, sizeof(buf),
"Received: from %s\r\n", ctl->server.truename);
}
n = stuffline(ctl, buf);
@@ -1157,7 +1162,7 @@ int readheaders(int sock,
buf[0] = '\t';
if (good_addresses == 0)
{
- snprintf(buf+1, sizeof(buf)-1, "for %s (by default); ",
+ snprintf(buf+1, sizeof(buf)-1, "for <%s> (by default); ",
rcpt_address (ctl, run.postmaster, 0));
}
else if (good_addresses == 1)
@@ -1166,7 +1171,7 @@ int readheaders(int sock,
if (idp->val.status.mark == XMIT_ACCEPT)
break; /* only report first address */
snprintf(buf+1, sizeof(buf)-1,
- "for %s", rcpt_address (ctl, idp->id, 1));
+ "for <%s>", rcpt_address (ctl, idp->id, 1));
snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf)-1,
" (%s); ",
MULTIDROP(ctl) ? "multi-drop" : "single-drop");