From: Chuck Lever <chuck.lever@oracle.com>
To: linux-nfs@vger.kernel.org
Subject: [PATCH 3/5] statd: statd_matchhostname() doesn't handle localhost properly
Date: Wed, 24 Aug 2011 11:34:13 -0400 [thread overview]
Message-ID: <20110824153413.3138.44194.stgit@matisse.1015granger.net> (raw)
In-Reply-To: <20110824153024.3138.63294.stgit@matisse.1015granger.net>
The job of statd_matchhostname() is to work hard at matching two
hostnames or presentation IP addresses that may refer to the same
host.
statd_matchhostname() turns the hostname of the local system into a
list of addresses containing only the loopback address. The actual
DNS registered address of the system does not appear in that list.
Presentation IP addresses, on the other hand, are soundly ignored by
the AI_CANONNAME option of getaddrinfo(3). The ai_canonname string
that is returned is just the same presentation IP address. And the
resulting list of addresses contains just that IP address.
So if the DNS registered IP address of the local host is passed in as
one argument, and the local hostname is passed as the other argument,
statd_matchhostname() whiffs and believes there is no match. To fix
this, the logic needs to be smarter about deriving a hostname from an
IP address.
This appears to cause no end of trouble: monitor records pile up in
/var/lib/nfs/sm and sm.bak, notifications are missed, and so on. This
has likely been around since commit cbd3a131 "statd: Introduce statd
version of matchhostname()" (Jan 14, 2010).
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
utils/statd/hostname.c | 55 +++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 47 insertions(+), 8 deletions(-)
diff --git a/utils/statd/hostname.c b/utils/statd/hostname.c
index 616a3cb..746ecc7 100644
--- a/utils/statd/hostname.c
+++ b/utils/statd/hostname.c
@@ -225,6 +225,49 @@ statd_canonical_name(const char *hostname)
return strdup(buf);
}
+/*
+ * Take care to perform an explicit reverse lookup on presentation
+ * addresses. Otherwise we don't get a real canonical name or a
+ * complete list of addresses.
+ *
+ * Returns an addrinfo list that has ai_canonname filled in, or
+ * NULL if some error occurs. Caller must free the returned
+ * list with freeaddrinfo(3).
+ */
+__attribute_malloc__
+static struct addrinfo *
+statd_canonical_list(const char *hostname)
+{
+ struct addrinfo hint = {
+#ifdef IPV6_SUPPORTED
+ .ai_family = AF_UNSPEC,
+#else /* !IPV6_SUPPORTED */
+ .ai_family = AF_INET,
+#endif /* !IPV6_SUPPORTED */
+ .ai_flags = AI_NUMERICHOST,
+ .ai_protocol = (int)IPPROTO_UDP,
+ };
+ char buf[NI_MAXHOST];
+ struct addrinfo *ai;
+
+ ai = get_addrinfo(hostname, &hint);
+ if (ai != NULL) {
+ /* @hostname was a presentation address */
+ _Bool result;
+ result = get_nameinfo(ai->ai_addr, ai->ai_addrlen,
+ buf, (socklen_t)sizeof(buf));
+ freeaddrinfo(ai);
+ if (result)
+ goto out;
+ }
+ /* @hostname was a hostname or had no reverse mapping */
+ strcpy(buf, hostname);
+
+out:
+ hint.ai_flags = AI_CANONNAME;
+ return get_addrinfo(buf, &hint);
+}
+
/**
* statd_matchhostname - check if two hostnames are equivalent
* @hostname1: C string containing hostname
@@ -241,11 +284,6 @@ _Bool
statd_matchhostname(const char *hostname1, const char *hostname2)
{
struct addrinfo *ai1, *ai2, *results1 = NULL, *results2 = NULL;
- struct addrinfo hint = {
- .ai_family = AF_UNSPEC,
- .ai_flags = AI_CANONNAME,
- .ai_protocol = (int)IPPROTO_UDP,
- };
_Bool result = false;
if (strcasecmp(hostname1, hostname2) == 0) {
@@ -253,10 +291,10 @@ statd_matchhostname(const char *hostname1, const char *hostname2)
goto out;
}
- results1 = get_addrinfo(hostname1, &hint);
+ results1 = statd_canonical_list(hostname1);
if (results1 == NULL)
goto out;
- results2 = get_addrinfo(hostname2, &hint);
+ results2 = statd_canonical_list(hostname2);
if (results2 == NULL)
goto out;
@@ -276,7 +314,8 @@ out:
freeaddrinfo(results2);
freeaddrinfo(results1);
- xlog(D_CALL, "%s: hostnames %s", __func__,
+ xlog(D_CALL, "%s: hostnames %s and %s %s", __func__,
+ hostname1, hostname2,
(result ? "matched" : "did not match"));
return result;
}
next prev parent reply other threads:[~2011-08-24 15:34 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-08-24 15:33 [PATCH 0/5] Possible fixes for statd / sm-notify / exportfs Chuck Lever
2011-08-24 15:33 ` [PATCH 1/5] statd: Report count of loaded hosts correctly Chuck Lever
2011-08-24 15:34 ` [PATCH 2/5] sm-notify: Disable syslog messages when debugging is enabled Chuck Lever
2011-08-24 15:34 ` Chuck Lever [this message]
2011-08-24 15:34 ` [PATCH 4/5] exportfs: matchhostname() doesn't handle localhost properly Chuck Lever
2011-08-24 15:34 ` [PATCH 5/5] sm-notify: sm-notify " Chuck Lever
2011-08-29 17:48 ` [PATCH 0/5] Possible fixes for statd / sm-notify / exportfs Steve Dickson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110824153413.3138.44194.stgit@matisse.1015granger.net \
--to=chuck.lever@oracle.com \
--cc=linux-nfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).