diff options
author | Matthias Andree <matthias.andree@gmx.de> | 2006-08-07 08:38:52 +0000 |
---|---|---|
committer | Matthias Andree <matthias.andree@gmx.de> | 2006-08-07 08:38:52 +0000 |
commit | c37b5d80dcbc0b30427ac7671b9eccd8856b1579 (patch) | |
tree | fce7689e312b4747523da39ab5975dc0d90b6bb0 | |
parent | 00428859b66df7161ee4a0d3f55afaa03aa7a2c3 (diff) | |
download | fetchmail-c37b5d80dcbc0b30427ac7671b9eccd8856b1579.tar.gz fetchmail-c37b5d80dcbc0b30427ac7671b9eccd8856b1579.tar.bz2 fetchmail-c37b5d80dcbc0b30427ac7671b9eccd8856b1579.zip |
Freeaddrinfo() fix for Uli Zappe's bug.
This might fix Debian Bug#294547 and Bug#377135.
svn path=/branches/BRANCH_6-3/; revision=4880
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | TODO.txt | 3 | ||||
-rw-r--r-- | checkalias.c | 10 | ||||
-rw-r--r-- | driver.c | 12 | ||||
-rw-r--r-- | fetchmail-FAQ.html | 12 | ||||
-rw-r--r-- | fetchmail.h | 11 | ||||
-rw-r--r-- | sink.c | 6 | ||||
-rw-r--r-- | socket.c | 12 | ||||
-rw-r--r-- | socket.h | 10 | ||||
-rw-r--r-- | transact.c | 5 |
10 files changed, 55 insertions, 30 deletions
@@ -34,6 +34,8 @@ change. MA = Matthias Andree, ESR = Eric S. Raymond, RF = Rob Funk.) * Kerberos IV support may be removed from a future fetchmail release. * SIGHUP wakeup may be removed from a future fetchmail release and cause it to terminate. +* Support for operating systems that are not sufficiently POSIX compliant may be + removed or operation on such systems may be suboptimal for future releases. -------------------------------------------------------------------------------- @@ -100,6 +102,8 @@ fetchmail 6.3.5 (not yet released): service name and the port number. Log the latter when trying to connect in verbose mode, too. * Keep syslog output at one line per message (this works if no errors occur). +* Track getaddrinfo() results to properly free them after timeouts, + reported by Uli Zappe. This MIGHT fix Debian Bug#294547 and Bug#377135. # CHANGES: * Rename all fetchmail-internal lock_* functions to fm_lock_*. Obsoletes @@ -1,4 +1,3 @@ -- debian bug #377135/freeaddrinfo()? - log/print warning if fetchmail uses TLS without configuration, to avoid users being surprised (see Debian Bug#294547). - allow full user@domain mappings in multidrop matching @@ -6,8 +5,6 @@ multidrop problems on fetchmail-users - Patterson: --logfile w/ ~/blah confuses fetchmail; see thread [fetchmail-users] option -v not working... -- Uli Zappe: [fetchmail-users] [BUG] fetchmail daemon does not resume - fetching after a network outage (has probable analysis) - check recent list mail - check Debian BTS and other bug trackers - better logging (log all headers) diff --git a/checkalias.c b/checkalias.c index 8214b40a..1f0495b9 100644 --- a/checkalias.c +++ b/checkalias.c @@ -83,14 +83,14 @@ found: return rc; } -int is_host_alias(const char *name, struct query *ctl) +int is_host_alias(const char *name, struct query *ctl, struct addrinfo **res) /* determine whether name is a DNS alias of the mailserver for this query */ { struct mxentry *mxp, *mxrecords; struct idlist *idl; size_t namelen; int e; - struct addrinfo hints, *res, *res_st; + struct addrinfo hints, *res_st; struct hostdata *lead_server = ctl->server.lead_server ? ctl->server.lead_server : &ctl->server; @@ -160,11 +160,11 @@ int is_host_alias(const char *name, struct query *ctl) hints.ai_socktype=SOCK_STREAM; hints.ai_flags=AI_CANONNAME; - e = getaddrinfo(name, NULL, &hints, &res); + e = getaddrinfo(name, NULL, &hints, res); if (e == 0) { - int rr = (strcasecmp(ctl->server.truename, res->ai_canonname) == 0); - freeaddrinfo(res); + int rr = (strcasecmp(ctl->server.truename, (*res)->ai_canonname) == 0); + freeaddrinfo(*res); *res = NULL; if (rr) goto match; else if (ctl->server.checkalias && 0 == getaddrinfo(ctl->server.truename, NULL, &hints, &res_st)) @@ -70,6 +70,8 @@ int batchcount; /* count of messages sent in current batch */ flag peek_capable; /* can we peek for better error recovery? */ int mailserver_socket_temp = -1; /* socket to free if connect timeout */ +struct addrinfo *ai0, *ai1; /* clean these up after signal */ + static volatile int timeoutcount = 0; /* count consecutive timeouts */ static volatile int idletimeout = 0; /* timeout occured in idle stage? */ @@ -878,6 +880,14 @@ static int do_session( sigfillset(&allsigs); sigprocmask(SIG_UNBLOCK, &allsigs, NULL); #endif /* HAVE_SIGPROCMASK */ + + if (ai0) { + freeaddrinfo(ai0); ai0 = NULL; + } + + if (ai1) { + freeaddrinfo(ai1); ai1 = NULL; + } if (js == THROW_SIGPIPE) { @@ -1053,7 +1063,7 @@ static int do_session( (void)sleep(1); if ((mailserver_socket = SockOpen(realhost, ctl->server.service ? ctl->server.service : ( ctl->use_ssl ? ctl->server.base_protocol->sslservice : ctl->server.base_protocol->service ), - ctl->server.plugin)) == -1) + ctl->server.plugin, &ai0)) == -1) { char errbuf[BUFSIZ]; int err_no = errno; diff --git a/fetchmail-FAQ.html b/fetchmail-FAQ.html index dce7b38c..df7d3f8c 100644 --- a/fetchmail-FAQ.html +++ b/fetchmail-FAQ.html @@ -2487,15 +2487,9 @@ declaration <tt>auth password</tt> in your .fetchmailrc.</p> <h2><a id="R13" name="R13">R13. What does "Interrupted system call" mean?</a></h2> -<p>Fetchmail 6.3.5 and newer gave up on the older timeout handling which -could cause unstable behavior. Instead, timeouts now interrupt -long-running functions and are reported as "Interrupted system -call".</p> - -<p>While this loses accuracy of timeout reporting, there is -unfortunately no safe way for C to make extensive use of error -reporting, and the amount of code that would need to be added is too -large for a stable series as 6.3.X is.</p> +<p>Non-fatal signals (such as timers set by fetchmail itself) can +interrupt long-running functions and will then be reported as +"Interrupted system call". These can sometimes be timeouts.</p> <hr/> <h1>Hangs and lockups</h1> diff --git a/fetchmail.h b/fetchmail.h index 1191bd34..2ea7972e 100644 --- a/fetchmail.h +++ b/fetchmail.h @@ -23,6 +23,13 @@ # endif #endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_NET_SOCKET_H +#include <net/socket.h> +#endif +#include <netdb.h> #include <stdio.h> /* Import Trio if needed */ @@ -651,7 +658,9 @@ void escapes(const char *, char *); char *visbuf(const char *); const char *showproto(int); void dump_config(struct runctl *runp, struct query *querylist); -int is_host_alias(const char *, struct query *); +int is_host_alias(const char *, struct query *, struct addrinfo **); + +extern struct addrinfo *ai0, *ai1; /** Try to obtain fully qualified hostname of current host. Exit with * PS_DNS if \a required is true and there is a DNS error. Exit with @@ -141,7 +141,7 @@ int smtp_open(struct query *ctl) portnum = cp; } if ((ctl->smtp_socket = SockOpen(parsed_host,portnum, - ctl->server.plugout)) == -1) + ctl->server.plugout, &ai1)) == -1) { xfree(parsed_host); continue; @@ -179,7 +179,7 @@ int smtp_open(struct query *ctl) else { if ((ctl->smtp_socket = SockOpen(parsed_host,portnum, - ctl->server.plugout)) == -1) + ctl->server.plugout, &ai1)) == -1) { xfree(parsed_host); continue; @@ -279,7 +279,7 @@ static int send_bouncemail(struct query *ctl, struct msgblk *msg, /* we need only SMTP for this purpose */ /* XXX FIXME: hardcoding localhost is nonsense if smtphost can be * configured */ - if ((sock = SockOpen("localhost", SMTP_PORT, NULL)) == -1) + if ((sock = SockOpen("localhost", SMTP_PORT, NULL, &ai1)) == -1) return(FALSE); if (SMTP_ok(sock, SMTP_MODE) != SM_OK) @@ -264,19 +264,20 @@ int UnixOpen(const char *path) } int SockOpen(const char *host, const char *service, - const char *plugin) + const char *plugin, struct addrinfo **ai0) { - struct addrinfo *ai, *ai0, req; + struct addrinfo *ai, req; int i, acterr = 0; #ifdef HAVE_SOCKETPAIR if (plugin) return handle_plugin(host,service,plugin); #endif /* HAVE_SOCKETPAIR */ + memset(&req, 0, sizeof(struct addrinfo)); req.ai_socktype = SOCK_STREAM; - i = getaddrinfo(host, service, &req, &ai0); + i = getaddrinfo(host, service, &req, ai0); if (i) { report(stderr, GT_("getaddrinfo(\"%s\",\"%s\") error: %s\n"), host, service, gai_strerror(i)); @@ -286,7 +287,7 @@ int SockOpen(const char *host, const char *service, } i = -1; - for (ai = ai0; ai; ai = ai->ai_next) { + for (ai = *ai0; ai; ai = ai->ai_next) { char buf[80],pb[80]; int gnie; @@ -339,7 +340,8 @@ int SockOpen(const char *host, const char *service, break; } - freeaddrinfo(ai0); + freeaddrinfo(*ai0); + *ai0 = NULL; if (i == -1) errno = acterr; @@ -7,8 +7,16 @@ #ifndef SOCKET__ #define SOCKET__ +#include <config.h> +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#elif HAVE_NET_SOCKET_H +#include <net/socket.h> +#endif +#include <netdb.h> + /* Create a new client socket; returns -1 on error */ -int SockOpen(const char *host, const char *service, const char *plugin); +int SockOpen(const char *host, const char *service, const char *plugin, struct addrinfo **); /* Returns 1 if this socket is OK, 0 if it isn't select()able * on - probably because it's been closed. You should @@ -150,7 +150,7 @@ static void find_server_names(const char *hdr, * not, skip this name. If it is, we'll keep * going and try to find a mapping to a client name. */ - if (!is_host_alias(atsign+1, ctl)) + if (!is_host_alias(atsign+1, ctl, &ai0)) { save_str(xmit_names, cp, XMIT_REJECT); reject_count++; @@ -190,6 +190,7 @@ static char *parse_received(struct query *ctl, char *bufp) { char *base, *ok = (char *)NULL; static char rbuf[HOSTLEN + USERNAMELEN + 4]; + struct addrinfo *ai0; #define RBUF_WRITE(value) if (tp < rbuf+sizeof(rbuf)-1) *tp++=value @@ -237,7 +238,7 @@ static char *parse_received(struct query *ctl, char *bufp) * recipient name after a following "for". Otherwise * punt. */ - if (is_host_alias(rbuf, ctl)) + if (is_host_alias(rbuf, ctl, &ai0)) { if (outlevel >= O_DEBUG) report(stdout, |