diff options
author | Matthias Andree <matthias.andree@gmx.de> | 2005-08-28 15:12:39 +0000 |
---|---|---|
committer | Matthias Andree <matthias.andree@gmx.de> | 2005-08-28 15:12:39 +0000 |
commit | 4680b0f8c728a69a24e7089b777f03899bab6c9f (patch) | |
tree | 15ca79e508d206308b3aaa65a747ddb1d54d32fc | |
parent | 865694ffd4df6b32eb81722fa6b851fb73a45271 (diff) | |
download | fetchmail-4680b0f8c728a69a24e7089b777f03899bab6c9f.tar.gz fetchmail-4680b0f8c728a69a24e7089b777f03899bab6c9f.tar.bz2 fetchmail-4680b0f8c728a69a24e7089b777f03899bab6c9f.zip |
Large protocol independence patch.
svn path=/trunk/; revision=4280
-rw-r--r-- | COPYING | 6 | ||||
-rw-r--r-- | Makefile.am | 9 | ||||
-rw-r--r-- | NEWS | 11 | ||||
-rw-r--r-- | checkalias.c | 134 | ||||
-rw-r--r-- | conf.c | 11 | ||||
-rw-r--r-- | configure.ac | 29 | ||||
-rw-r--r-- | driver.c | 83 | ||||
-rw-r--r-- | env.c | 37 | ||||
-rw-r--r-- | fetchmail.c | 39 | ||||
-rw-r--r-- | fetchmail.h | 20 | ||||
-rw-r--r-- | fetchmail.man | 21 | ||||
-rw-r--r-- | imap.c | 11 | ||||
-rw-r--r-- | interface.c | 19 | ||||
-rw-r--r-- | options.c | 10 | ||||
-rw-r--r-- | rcfile_y.y | 12 | ||||
-rw-r--r-- | servport.c | 25 | ||||
-rw-r--r-- | socket.c | 141 | ||||
-rw-r--r-- | transact.c | 25 |
18 files changed, 244 insertions, 399 deletions
@@ -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 @@ -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 */ @@ -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) @@ -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, @@ -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. @@ -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 */ @@ -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 @@ -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, ¤t.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); } @@ -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) @@ -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) @@ -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"); |