Package: finger
Version: 0.17-14
Severity: normal
Tags: patch

In the present situation with two address families supported by Finger,
it will be more common that the target system is not responding to a
finger query due to a missed configuration of a particular address.

Consider this: A name server reports an IPv4 as well as an IPv6 address
for a particular host, but in fact the host in question has not yet
activated its external IPv6 address. This would cause the Finger client
to wait for the full duration of the TCP handshake timeout, before being
able to proceed to querying the IPv4 address. The same thing goes for
a multihomed host where not every address within the same address family
is responding to finger queries.

The following patch uses the SIGALRM machinery to reduce this timeout
to five seconds before trying the next address on the resolver's
address list.

It is sometimes stated that rerouting regularly causes a delay in excess
of fifteen seconds, but taking the optional character of Finger for an
interactive user into account, I still find a short timeout of five
seconds is the appropriate amount of time. The package builder can
easily override this setting in a tailored package.


Best regards,
-- 
Mats Erik Andersson, fil. dr
<[email protected]>
Description: Decrease timeout length during connect().
 In cases where a name server is answering with A as well as AAAA records,
 but the system to be queried has lost a corresponding address, the TCP
 handshake timeout will cause a long delay before allowing the query of
 the next address family, or the next address in general.
 .
 The use of a trivial signal handler for SIGALRM allows the reduction
 of this timeout, thus producing better responsiveness for the interactive
 user of the Finger service.
Author: Mats Erik Andersson <[email protected]>
Forwarded: no
Last-Updated: 2010-03-02

--- bsd-finger-0.17/finger/net.c.debian
+++ bsd-finger-0.17/finger/net.c
@@ -49,14 +49,25 @@
 #include <string.h>
 #include <unistd.h>
 #include <ctype.h>
+#include <signal.h>
 #include "finger.h"
 
+#if ! defined(FINGER_TIMEOUT) || FINGER_TIMEOUT < 1
+# define FINGER_TIMEOUT 5
+#endif
+
+static void trivial_alarm(int sig) {
+	/* Just to trigger EINTR, and to later use it. */
+	return;
+}
+
 int netfinger(const char *name) {
 	register FILE *fp;
 	register int c, sawret, ateol;
 	struct addrinfo hints, *result, *resptr;
 	struct servent *sp;
 	struct sockaddr_storage sn;
+	struct sigaction sigact, oldsigact;
 	int s, status;
 	char *host;
 
@@ -77,6 +88,10 @@
 	hints.ai_socktype = SOCK_STREAM;
 	hints.ai_protocol = IPPROTO_TCP;
 
+	sigact.sa_handler = trivial_alarm;
+	sigemptyset(&sigact.sa_mask);
+	sigact.sa_flags = 0;
+
 	status = getaddrinfo(host, "finger", &hints, &result);
 	if (status != 0) {
 		eprintf("finger: unknown host: %s\n", host);
@@ -95,13 +110,21 @@
 		/* This should probably be removed. */
 		/* xprintf("[%s]\n", result->ai_canonname); */
 
+		sigaction(SIGALRM, &sigact, &oldsigact);
+		alarm(FINGER_TIMEOUT);
+
 		if (connect(s, resptr->ai_addr, resptr->ai_addrlen) < 0) {
+			if ( errno == EINTR )
+				errno = ETIMEDOUT;
 			close(s);
 			continue;
 		}
 
+		alarm(0);
+		sigaction(SIGALRM, &oldsigact, NULL);
+
 		/* Connection is now established.
-		/* Assemble the gained information. */
+		 * Assemble the gained information. */
 		memcpy(&sn, resptr->ai_addr, resptr->ai_addrlen);
 		break;
 	}

Attachment: signature.asc
Description: Digital signature

Reply via email to