diff options
author | Matthias Andree <matthias.andree@gmx.de> | 2006-08-14 01:28:47 +0000 |
---|---|---|
committer | Matthias Andree <matthias.andree@gmx.de> | 2006-08-14 01:28:47 +0000 |
commit | df4a264f6a4bf53592f9e273462a8861ea7e6a6d (patch) | |
tree | 7fc180164f8bc204cea413b098a9068dbdc2c792 | |
parent | c625d7a00b024fe5de26d16b6420abebb1db705c (diff) | |
download | fetchmail-df4a264f6a4bf53592f9e273462a8861ea7e6a6d.tar.gz fetchmail-df4a264f6a4bf53592f9e273462a8861ea7e6a6d.tar.bz2 fetchmail-df4a264f6a4bf53592f9e273462a8861ea7e6a6d.zip |
Wrap getaddrinfo() and block SIGALRM where needed.
Also wrap freeaddrinfo() without added functionality.
svn path=/branches/BRANCH_6-3/; revision=4895
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | checkalias.c | 14 | ||||
-rw-r--r-- | configure.ac | 20 | ||||
-rw-r--r-- | driver.c | 8 | ||||
-rw-r--r-- | env.c | 4 | ||||
-rw-r--r-- | fetchmail.h | 3 | ||||
-rw-r--r-- | fm_getaddrinfo.c | 40 | ||||
-rw-r--r-- | servport.c | 6 | ||||
-rw-r--r-- | socket.c | 4 |
10 files changed, 83 insertions, 23 deletions
diff --git a/Makefile.am b/Makefile.am index c866488c..db06fee0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -39,7 +39,7 @@ libfm_a_SOURCES= xmalloc.c base64.c rfc822.c report.c rfc2047e.c \ servport.c ntlm.h smbbyteorder.h smbdes.h smbmd4.h \ smbencrypt.h smbdes.c smbencrypt.c smbmd4.c smbutil.c \ libesmtp/gethostbyname.h libesmtp/gethostbyname.c \ - smbtypes.h + smbtypes.h fm_getaddrinfo.c libfm_a_LIBADD= $(EXTRAOBJ) libfm_a_DEPENDENCIES= $(EXTRAOBJ) LDADD = libfm.a @LIBINTL@ $(LIBOBJS) @@ -98,8 +98,9 @@ fetchmail 6.3.5 (not yet released): with new polls, and SIGHUP would be ignored for root users. SIGHUP now matches documented behavior. SIGUSR1 has always been a wakeup signal for both root (undocumented) and non-root users. See also the deprecation warning above. -* Track getaddrinfo() results to properly free them after timeouts, - reported by Uli Zappe. This MIGHT fix Debian Bug#294547 and Bug#377135. +* Track getaddrinfo() results to properly free them after timeouts and make sure + that getaddrinfo() isn't interrupted by a timeout (which breaks on MacOS X), + reported by Uli Zappe. This should fix Debian Bug#294547 and Bug#377135. * --logfile is now handled more carefully, errors opening the logfile are now reported to the TTY where fetchmail was started from. * fetchmail now complains and aborts when it cannot properly daemonize itself. diff --git a/checkalias.c b/checkalias.c index 1f0495b9..80356ed2 100644 --- a/checkalias.c +++ b/checkalias.c @@ -36,7 +36,7 @@ static int getaddresses(struct addrinfo **result, const char *name) hints.ai_socktype=SOCK_STREAM; hints.ai_protocol=PF_UNSPEC; hints.ai_family=AF_UNSPEC; - return getaddrinfo(name, NULL, &hints, result); + return fm_getaddrinfo(name, NULL, &hints, result); } /* XXX FIXME: doesn't detect if an IPv6-mapped IPv4 address @@ -77,9 +77,9 @@ static int is_ip_alias(const char *name1,const char *name2) found: if (res2) - freeaddrinfo(res2); + fm_freeaddrinfo(res2); if (res1) - freeaddrinfo(res1); + fm_freeaddrinfo(res1); return rc; } @@ -160,16 +160,16 @@ int is_host_alias(const char *name, struct query *ctl, struct addrinfo **res) hints.ai_socktype=SOCK_STREAM; hints.ai_flags=AI_CANONNAME; - e = getaddrinfo(name, NULL, &hints, res); + e = fm_getaddrinfo(name, NULL, &hints, res); if (e == 0) { int rr = (strcasecmp(ctl->server.truename, (*res)->ai_canonname) == 0); - freeaddrinfo(*res); *res = NULL; + fm_freeaddrinfo(*res); *res = NULL; if (rr) goto match; - else if (ctl->server.checkalias && 0 == getaddrinfo(ctl->server.truename, NULL, &hints, &res_st)) + else if (ctl->server.checkalias && 0 == fm_getaddrinfo(ctl->server.truename, NULL, &hints, &res_st)) { - freeaddrinfo(res_st); + fm_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) diff --git a/configure.ac b/configure.ac index 03d0b33c..e5012850 100644 --- a/configure.ac +++ b/configure.ac @@ -5,7 +5,7 @@ dnl dnl Process this file with autoconf to produce a configure script. dnl -AC_INIT([fetchmail],[6.3.5-beta1],[fetchmail-users@lists.berlios.de]) +AC_INIT([fetchmail],[6.3.5-beta2],[fetchmail-users@lists.berlios.de]) AC_CONFIG_SRCDIR([fetchmail.h]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_LIBOBJ_DIR([.]) @@ -138,7 +138,7 @@ AC_SUBST(EXTRAOBJ) AC_CHECK_FUNCS(tcsetattr stty setsid geteuid seteuid dnl strerror syslog snprintf vprintf vsnprintf vsyslog dnl - atexit inet_aton strftime setrlimit socketpair sigprocmask dnl + atexit inet_aton strftime setrlimit socketpair dnl sigaction strdup setlocale) AC_CHECK_DECLS(strerror) @@ -428,6 +428,22 @@ AC_CHECK_FUNCS(getnameinfo inet_ntop) AM_CONDITIONAL(NEED_GETADDRINFO, test "$ac_cv_search_getaddrinfo" != "none required") AM_CONDITIONAL(NEED_GETNAMEINFO, test "$ac_cv_func_getnameinfo" != yes) +dnl Check if getaddrinfo is async-signal-safe - most implementations aren't +if test "$ac_cv_search_getaddrinfo" = "none required" ; then + AC_MSG_CHECKING(if your getaddrinfo is async-signal-safe) + gai_ts=no + dnl we have getaddrinfo() - check if the OS is known to have a async-signal-safe implementation + case $target_os in + linux*) gai_ts=yes ;; + freebsd5.5|freebsd6*|freebsd7*) gai_ts=yes ;; + solaris2.8|solaris2.9|solaris2.10) gai_ts=yes ;; + esac + AC_MSG_RESULT($gai_ts) + if test $gai_ts = yes ; then + AC_DEFINE(GETADDRINFO_ASYNCSAFE, 1, [define to 1 if you know your getaddrinfo function is async-signal-safe]) + fi +fi + # This version of the Kerberos 4 and 5 options addresses the follwing issues: # # * Build correctly under Heimdal kerberos if it is compiled with db2 and @@ -862,11 +862,11 @@ static int do_session( sigprocmask(SIG_UNBLOCK, &allsigs, NULL); if (ai0) { - freeaddrinfo(ai0); ai0 = NULL; + fm_freeaddrinfo(ai0); ai0 = NULL; } if (ai1) { - freeaddrinfo(ai1); ai1 = NULL; + fm_freeaddrinfo(ai1); ai1 = NULL; } if (js == THROW_TIMEOUT) @@ -998,7 +998,7 @@ static int do_session( hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_CANONNAME; - error = getaddrinfo(ctl->server.queryname, NULL, &hints, &res); + error = fm_getaddrinfo(ctl->server.queryname, NULL, &hints, &res); if (error) { report(stderr, @@ -1024,7 +1024,7 @@ static int do_session( ctl->server.trueaddr = (struct sockaddr *)xmalloc(res->ai_addrlen); ctl->server.trueaddr_len = res->ai_addrlen; memcpy(ctl->server.trueaddr, res->ai_addr, res->ai_addrlen); - freeaddrinfo(res); + fm_freeaddrinfo(res); } } } @@ -161,7 +161,7 @@ char *host_fqdn(int required) hints.ai_socktype = SOCK_STREAM; hints.ai_flags=AI_CANONNAME; - e = getaddrinfo(tmpbuf, NULL, &hints, &res); + e = fm_getaddrinfo(tmpbuf, NULL, &hints, &res); if (e) { /* exit with error message */ fprintf(stderr, @@ -177,7 +177,7 @@ char *host_fqdn(int required) } result = xstrdup(res->ai_canonname); - freeaddrinfo(res); + fm_freeaddrinfo(res); } else result = xstrdup(tmpbuf); diff --git a/fetchmail.h b/fetchmail.h index 7c63e22a..cfe6a634 100644 --- a/fetchmail.h +++ b/fetchmail.h @@ -759,5 +759,8 @@ int servport(const char *service); # define NI_DGRAM 16 #endif +int fm_getaddrinfo(const char *node, const char *serv, const struct addrinfo *hints, struct addrinfo **res); +void fm_freeaddrinfo(struct addrinfo *ai); + #endif /* fetchmail.h ends here */ diff --git a/fm_getaddrinfo.c b/fm_getaddrinfo.c new file mode 100644 index 00000000..97cec65c --- /dev/null +++ b/fm_getaddrinfo.c @@ -0,0 +1,40 @@ +#include "config.h" +#include "fetchmail.h" +#include "i18n.h" + +#include <signal.h> +#include <errno.h> +#include <string.h> + +/** This is a getaddrinfo() replacement that blocks SIGALRM, + * to avoid issues with non-reentrant getaddrinfo() implementations + * after SIGALRM timeouts, for instance on MacOS X or NetBSD. */ +int fm_getaddrinfo(const char *node, const char *serv, const struct addrinfo *hints, struct addrinfo **res) +{ + int rc; + +#ifndef GETADDRINFO_ASYNCSAFE + sigset_t ss, os; + + sigemptyset(&ss); + sigaddset(&ss, SIGALRM); + + if (sigprocmask(SIG_BLOCK, &ss, &os)) + report(stderr, GT_("Cannot modify signal mask: %s"), strerror(errno)); +#endif + + rc = getaddrinfo(node, serv, hints, res); + +#ifndef GETADDRINFO_ASYNCSAFE + if (sigprocmask(SIG_SETMASK, &os, NULL)) + report(stderr, GT_("Cannot modify signal mask: %s"), strerror(errno)); +#endif + + return rc; +} + +/** this is a debugging freeaddrinfo() wrapper. */ +void fm_freeaddrinfo(struct addrinfo *ai) +{ + freeaddrinfo(ai); +} @@ -48,7 +48,7 @@ int servport(const char *service) { hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; - e = getaddrinfo(NULL, service, &hints, &res); + e = fm_getaddrinfo(NULL, service, &hints, &res); if (e) { report(stderr, GT_("getaddrinfo(NULL, \"%s\") error: %s\n"), service, gai_strerror(e)); @@ -64,10 +64,10 @@ int servport(const char *service) { break; #endif default: - freeaddrinfo(res); + fm_freeaddrinfo(res); goto err; } - freeaddrinfo(res); + fm_freeaddrinfo(res); } } else { if (u == 0 || u > 65535) @@ -277,7 +277,7 @@ int SockOpen(const char *host, const char *service, memset(&req, 0, sizeof(struct addrinfo)); req.ai_socktype = SOCK_STREAM; - i = getaddrinfo(host, service, &req, ai0); + i = fm_getaddrinfo(host, service, &req, ai0); if (i) { report(stderr, GT_("getaddrinfo(\"%s\",\"%s\") error: %s\n"), host, service, gai_strerror(i)); @@ -340,7 +340,7 @@ int SockOpen(const char *host, const char *service, break; } - freeaddrinfo(*ai0); + fm_freeaddrinfo(*ai0); *ai0 = NULL; if (i == -1) |