aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Andree <matthias.andree@gmx.de>2006-08-07 08:38:52 +0000
committerMatthias Andree <matthias.andree@gmx.de>2006-08-07 08:38:52 +0000
commitc37b5d80dcbc0b30427ac7671b9eccd8856b1579 (patch)
treefce7689e312b4747523da39ab5975dc0d90b6bb0
parent00428859b66df7161ee4a0d3f55afaa03aa7a2c3 (diff)
downloadfetchmail-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--NEWS4
-rw-r--r--TODO.txt3
-rw-r--r--checkalias.c10
-rw-r--r--driver.c12
-rw-r--r--fetchmail-FAQ.html12
-rw-r--r--fetchmail.h11
-rw-r--r--sink.c6
-rw-r--r--socket.c12
-rw-r--r--socket.h10
-rw-r--r--transact.c5
10 files changed, 55 insertions, 30 deletions
diff --git a/NEWS b/NEWS
index bcb00beb..f278b29a 100644
--- a/NEWS
+++ b/NEWS
@@ -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
diff --git a/TODO.txt b/TODO.txt
index 2156f2d2..f8993ce4 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -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))
diff --git a/driver.c b/driver.c
index 5d765986..c9d3e6a0 100644
--- a/driver.c
+++ b/driver.c
@@ -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
diff --git a/sink.c b/sink.c
index 3e0ac359..2e36e57e 100644
--- a/sink.c
+++ b/sink.c
@@ -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)
diff --git a/socket.c b/socket.c
index ee9600fd..080f1888 100644
--- a/socket.c
+++ b/socket.c
@@ -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;
diff --git a/socket.h b/socket.h
index d4fc947e..fb86b17e 100644
--- a/socket.h
+++ b/socket.h
@@ -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
diff --git a/transact.c b/transact.c
index b16f4238..f29fa5b9 100644
--- a/transact.c
+++ b/transact.c
@@ -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,