[PATCH 5/5] sm-notify: sm-notify doesn't handle localhost properly

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



It looks like the existing algorithm for verifying the passed-in bind
address is as broken as statd_matchhostname() used to be: for IP
addresses, AI_CANONNAME is useless.  We need to have getnameinfo(3) or
equivalent in there.

Clean up: extract the logic that verifies the command line bind
address into its own function, and make it handle canonical name
lookup correctly.

Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx>
---

 utils/statd/sm-notify.c |  127 ++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 102 insertions(+), 25 deletions(-)

diff --git a/utils/statd/sm-notify.c b/utils/statd/sm-notify.c
index f05eadf..2421f8b 100644
--- a/utils/statd/sm-notify.c
+++ b/utils/statd/sm-notify.c
@@ -93,6 +93,101 @@ smn_lookup(const char *name)
 	return ai;
 }
 
+#ifdef HAVE_GETNAMEINFO
+static char *
+smn_get_hostname(const struct sockaddr *sap, const socklen_t salen,
+		const char *name)
+{
+	char buf[NI_MAXHOST];
+	int error;
+
+	error = getnameinfo(sap, salen, buf, sizeof(buf), NULL, 0, NI_NAMEREQD);
+	if (error != 0) {
+		xlog(L_ERROR, "my_name '%s' is unusable: %s",
+			name, gai_strerror(error));
+		return NULL;
+	}
+	return strdup(buf);
+}
+#else	/* !HAVE_GETNAMEINFO */
+static char *
+smn_get_hostname(const struct sockaddr *sap,
+		__attribute__ ((unused)) const socklen_t salen,
+		const char *name)
+{
+	const struct sockaddr_in *sin = (const struct sockaddr_in *)(char *)sap;
+	const struct in_addr *addr = &sin->sin_addr;
+	struct hostent *hp;
+
+	if (sap->sa_family != AF_INET) {
+		xlog(L_ERROR, "my_name '%s' is unusable: Bad address family",
+			name);
+		return NULL;
+	}
+
+	hp = gethostbyaddr(addr, (socklen_t)sizeof(addr), AF_INET);
+	if (hp == NULL) {
+		xlog(L_ERROR, "my_name '%s' is unusable: %s",
+			name, hstrerror(h_errno));
+		return NULL;
+	}
+	return strdup(hp->h_name);
+}
+#endif	/* !HAVE_GETNAMEINFO */
+
+/*
+ * Presentation addresses are converted to their canonical hostnames.
+ * If the IP address does not map to a hostname, it is an error:
+ * we never send a presentation address as the argument of SM_NOTIFY.
+ *
+ * If "name" is not a presentation address, it is left alone.  This
+ * allows the administrator some flexibility if DNS isn't configured
+ * exactly how sm-notify prefers it.
+ *
+ * Returns NUL-terminated C string containing the result, or NULL
+ * if the canonical name doesn't exist or cannot be determined.
+ * The caller must free the result with free(3).
+ */
+__attribute_malloc__
+static char *
+smn_verify_my_name(const char *name)
+{
+	struct addrinfo *ai = NULL;
+	struct addrinfo hint = {
+#ifdef IPV6_SUPPORTED
+		.ai_family	= AF_UNSPEC,
+#else	/* !IPV6_SUPPORTED */
+		.ai_family	= AF_INET,
+#endif	/* !IPV6_SUPPORTED */
+		.ai_flags	= AI_NUMERICHOST,
+	};
+	char *retval;
+	int error;
+
+	error = getaddrinfo(name, NULL, &hint, &ai);
+	switch (error) {
+	case 0:
+		/* @name was a presentation address */
+		retval = smn_get_hostname(ai->ai_addr, ai->ai_addrlen, name);
+		freeaddrinfo(ai);
+		if (retval == NULL)
+			return NULL;
+		break;
+	case EAI_NONAME:
+		/* @name was not a presentation address */
+		retval = strdup(name);
+		break;
+	default:
+		xlog(L_ERROR, "my_name '%s' is unusable: %s",
+			name, gai_strerror(error));
+		return NULL;
+	}
+
+	xlog(D_GENERAL, "Canonical name for my_name '%s': %s",
+			name, retval);
+	return retval;
+}
+
 __attribute_malloc__
 static struct nsm_host *
 smn_alloc_host(const char *hostname, const char *mon_name,
@@ -416,32 +511,14 @@ usage:		fprintf(stderr,
 	}
 
 	if (opt_srcaddr != NULL) {
-		struct addrinfo *ai = NULL;
-		struct addrinfo hint = {
-			.ai_family	= AF_UNSPEC,
-			.ai_flags	= AI_NUMERICHOST,
-		};
-
-		if (getaddrinfo(opt_srcaddr, NULL, &hint, &ai))
-			/* not a presentation address - use it */
-			strncpy(nsm_hostname, opt_srcaddr, sizeof(nsm_hostname));
-		else {
-			/* was a presentation address - look it up in
-			 * /etc/hosts, so it can be used for my_name */
-			int error;
+		char *name;
 
-			freeaddrinfo(ai);
-			hint.ai_flags = AI_CANONNAME;
-			error = getaddrinfo(opt_srcaddr, NULL, &hint, &ai);
-			if (error != 0) {
-				xlog(L_ERROR, "Bind address %s is unusable: %s",
-						opt_srcaddr, gai_strerror(error));
-				exit(1);
-			}
-			strncpy(nsm_hostname, ai->ai_canonname,
-							sizeof(nsm_hostname));
-			freeaddrinfo(ai);
-		}
+		name = smn_verify_my_name(opt_srcaddr);
+		if (name == NULL)
+			exit(1);
+
+		strncpy(nsm_hostname, name, sizeof(nsm_hostname));
+		free(name);
 	}
 
 	(void)nsm_retire_monitored_hosts();

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux