svn commit: r336795 - head/usr.sbin/nfsd

Rick Macklem rmacklem at FreeBSD.org
Fri Jul 27 23:10:29 UTC 2018


Author: rmacklem
Date: Fri Jul 27 23:10:28 2018
New Revision: 336795
URL: https://svnweb.freebsd.org/changeset/base/336795

Log:
  Add support for IPv6 addresses to the pNFS "-p" option.
  
  This patch adds code to handle IPv6 addresses returned by getaddrinfo()
  for the host entries in the "-p" command line argument.
  If the IPv6 address is a link local address, only use it if it is the
  only address for the host. This is done since there is no way to know
  if the NFSv4.1 pNFS client is in the same scope zone as the MDS.
  inet_ntop() is used for the IPv6 address translation, since the client
  will have no use for the scope zone suffix and inet_ntop() does not
  put this in the address string.
  
  Discussed with:	bu7cher at yandex.ru

Modified:
  head/usr.sbin/nfsd/nfsd.c

Modified: head/usr.sbin/nfsd/nfsd.c
==============================================================================
--- head/usr.sbin/nfsd/nfsd.c	Fri Jul 27 22:46:42 2018	(r336794)
+++ head/usr.sbin/nfsd/nfsd.c	Fri Jul 27 23:10:28 2018	(r336795)
@@ -1179,14 +1179,16 @@ backup_stable(__unused int signo)
 static void
 parse_dsserver(const char *optionarg, struct nfsd_nfsd_args *nfsdargp)
 {
-	char *ad, *cp, *cp2, *dsaddr, *dshost, *dspath, *dsvol, nfsprt[9];
-	char *mdspath, *mdsp;
+	char *cp, *cp2, *dsaddr, *dshost, *dspath, *dsvol, nfsprt[9];
+	char *mdspath, *mdsp, ip6[INET6_ADDRSTRLEN];
+	const char *ad;
 	int ecode;
 	u_int adsiz, dsaddrcnt, dshostcnt, dspathcnt, hostsiz, pathsiz;
 	u_int mdspathcnt;
 	size_t dsaddrsiz, dshostsiz, dspathsiz, nfsprtsiz, mdspathsiz;
-	struct addrinfo hints, *ai_tcp;
+	struct addrinfo hints, *ai_tcp, *res;
 	struct sockaddr_in sin;
+	struct sockaddr_in6 sin6;
 
 	cp = strdup(optionarg);
 	if (cp == NULL)
@@ -1275,22 +1277,55 @@ parse_dsserver(const char *optionarg, struct nfsd_nfsd
 
 		/* Get the fully qualified domain name and IP address. */
 		memset(&hints, 0, sizeof(hints));
-		hints.ai_flags = AI_CANONNAME;
-		hints.ai_family = AF_INET;
+		hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
+		hints.ai_family = PF_UNSPEC;
 		hints.ai_socktype = SOCK_STREAM;
 		hints.ai_protocol = IPPROTO_TCP;
 		ecode = getaddrinfo(cp, NULL, &hints, &ai_tcp);
 		if (ecode != 0)
 			err(1, "getaddrinfo pnfs: %s %s", cp,
 			    gai_strerror(ecode));
-		if (ai_tcp->ai_addr->sa_family != AF_INET ||
-		    ai_tcp->ai_addrlen < sizeof(sin))
-			err(1, "getaddrinfo() returned non-INET address");
-		/* Mips cares about sockaddr_in alignment, so copy the addr. */
-		memcpy(&sin, ai_tcp->ai_addr, sizeof(sin));
+		ad = NULL;
+		for (res = ai_tcp; res != NULL; res = res->ai_next) {
+			if (res->ai_addr->sa_family == AF_INET) {
+				if (res->ai_addrlen < sizeof(sin))
+					err(1, "getaddrinfo() returned "
+					    "undersized IPv4 address");
+				/*
+				 * Mips cares about sockaddr_in alignment,
+				 * so copy the address.
+				 */
+				memcpy(&sin, res->ai_addr, sizeof(sin));
+				ad = inet_ntoa(sin.sin_addr);
+				break;
+			} else if (res->ai_family == AF_INET6) {
+				if (res->ai_addrlen < sizeof(sin6))
+					err(1, "getaddrinfo() returned "
+					    "undersized IPv6 address");
+				/*
+				 * Mips cares about sockaddr_in6 alignment,
+				 * so copy the address.
+				 */
+				memcpy(&sin6, res->ai_addr, sizeof(sin6));
+				ad = inet_ntop(AF_INET6, &sin6.sin6_addr, ip6,
+				    sizeof(ip6));
 
+				/*
+				 * XXX
+				 * Since a link local address will only
+				 * work if the client and DS are in the
+				 * same scope zone, only use it if it is
+				 * the only address.
+				 */
+				if (ad != NULL &&
+				    !IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr))
+					break;
+			}
+		}
+		if (ad == NULL)
+			err(1, "No IP address for %s", cp);
+
 		/* Append this address to dsaddr. */
-		ad = inet_ntoa(sin.sin_addr);
 		adsiz = strlen(ad);
 		if (dsaddrcnt + adsiz + nfsprtsiz + 1 > dsaddrsiz) {
 			dsaddrsiz *= 2;


More information about the svn-src-head mailing list