Add the support of IPv6 in the NFS commands on the client.
This allows the mount command to mount NFS file systems
using either IPv4 or IPv6 addresses.

Signed-off-by: Gilles Quillard <gilles.quillard@bull.net>
---

diff -Nru util-linux-2.12-3/mount/Makefile util-linux-2.12-3-gq/mount/Makefile
--- util-linux-2.12-3/mount/Makefile	2005-02-17 10:47:55.303086000 +0100
+++ util-linux-2.123-gq/mount/Makefile	2005-02-17 11:28:16.406022784 +0100
@@ -7,8 +7,9 @@
 RPC_CFLAGS = -Wno-unused 
 RPCGEN = rpcgen
 
-COMPILE = $(CC) -c $(CFLAGS) $(DEFINES)
-LINK = $(CC) $(LDFLAGS)
+COMPILE = $(CC) -I/usr/include/tirpc -c $(CFLAGS) $(DEFINES)
+LINK = $(CC)
+LDFLAGS = -l pthread -l tirpc
 
 ifeq "$(OS)" "linux"
 SUID_PROGS = mount umount
@@ -47,11 +48,11 @@
 mount: mount.o fstab.o sundries.o realpath.o mntent.o version.o \
        mount_guess_fstype.o get_label_uuid.o mount_by_label.o getusername.o \
        $(LIB)/setproctitle.o $(LIB)/env.o $(NFS_OBJS) $(LO_OBJS)
-	$(LINK) $^ -o $@
+	$(LINK) $^ -o $@ $(LDFLAGS)
 
 umount: umount.o fstab.o sundries.o realpath.o mntent.o getusername.o \
 	get_label_uuid.o version.o $(LIB)/env.o $(NFS_OBJS) $(LO_OBJS)
-	$(LINK) $^ -o $@
+	$(LINK) $^ -o $@ $(LDFLAGS)
 
 swapon:	swapon.o version.o
 	$(LINK) $^ -o $@
diff -Nru util-linux-2.12-3/mount/nfs4mount.c util-linux-2.12-3-gq/mount/nfs4mount.c
--- util-linux-2.12-3/mount/nfs4mount.c	2005-01-18 13:12:55.000000000 +0100
+++ util-linux-2.12-3-gq/mount/nfs4mount.c	2005-01-24 10:27:07.936237744 +0100
@@ -36,6 +36,7 @@
 #include <sys/stat.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <resolv.h>
 #include <rpc/auth.h>
 #ifdef HAVE_rpcsvc_nfs_prot_h
 #include <rpcsvc/nfs_prot.h>
@@ -55,9 +56,11 @@
 #define NFS_PORT 2049
 #endif
 
-extern int clnt_ping(struct sockaddr_in *, const u_long, const u_long, const u_int);
+extern int clnt_ping(struct sockaddr_in6 *, const u_long, const u_long, const u_int);
 extern void rpc_strerror(void);
 
+int fill_ipv6_sockaddr(const char *, struct sockaddr_in6 *);
+
 struct {
 	char    *flavour;
 	int     fnum;
@@ -113,7 +116,7 @@
 {
 	char *s;
 
-	if (!(s = strchr(hostdir, ':'))) {
+	if (!(s = strrchr(hostdir, ':'))) {
 		fprintf(stderr,
 			_("mount: "
 			  "directory to mount not in host:dir format\n"));
@@ -133,40 +136,50 @@
 	return 0;
 }
 
-static int fill_ipv4_sockaddr(const char *hostname, struct sockaddr_in *addr)
+int fill_ipv6_sockaddr(const char *hostname, struct sockaddr_in6 *addr)
 {
 	struct hostent *hp;
-	addr->sin_family = AF_INET;
 
-	if (inet_aton(hostname, &addr->sin_addr))
-		return 0;
-	if ((hp = gethostbyname(hostname)) == NULL) {
-		fprintf(stderr, _("mount: can't get address for %s\n"),
-			hostname);
-		return -1;
-	}
-	if (hp->h_length > sizeof(struct in_addr)) {
-		fprintf(stderr,
-			_("mount: got bad hp->h_length\n"));
-		hp->h_length = sizeof(struct in_addr);
+	addr->sin6_family = AF_INET6;
+	if (inet_pton(AF_INET6, hostname, &addr->sin6_addr) <= 0) {
+		if (inet_pton(AF_INET, hostname, &addr->sin6_addr.s6_addr32[3]) > 0) {
+			addr->sin6_addr.s6_addr32[0] = 0;
+			addr->sin6_addr.s6_addr32[1] = 0;
+			addr->sin6_addr.s6_addr32[2] = htonl(0xffff);
+		}
+		else if ((hp = gethostbyname(hostname)) != NULL) {
+			if (hp->h_length > sizeof(struct in6_addr)) {
+				fprintf(stderr,
+						_("mount: got bad hp->h_length\n"));
+				hp->h_length = sizeof(struct in6_addr);
+			}
+			memcpy(&addr->sin6_addr, hp->h_addr, hp->h_length);
+		}
+		else {
+			fprintf(stderr, _("mount: can't get address for %s\n"),
+					hostname);
+			return -1;
+		}
 	}
-	memcpy(&addr->sin_addr, hp->h_addr, hp->h_length);
 	return 0;
 }
 
-static int get_my_ipv4addr(char *ip_addr, int len)
+static int get_my_ipv6addr(char *ip_addr, int len)
 {
 	char myname[1024];
-	struct sockaddr_in myaddr;
+	struct sockaddr_in6 myaddr;
 
 	if (gethostname(myname, sizeof(myname))) {
 		fprintf(stderr, _("mount: can't determine client address\n"));
 		return -1;
 	}
-	if (fill_ipv4_sockaddr(myname, &myaddr))
+	if (fill_ipv6_sockaddr(myname, &myaddr))
 		return -1;
-	snprintf(ip_addr, len, "%s", inet_ntoa(myaddr.sin_addr));
-	ip_addr[len-1] = '\0';
+	if (IN6_IS_ADDR_V4MAPPED(&myaddr.sin6_addr))
+		inet_ntop(AF_INET, (void *)&myaddr.sin6_addr.s6_addr32[3],
+			ip_addr, len);
+	else
+		inet_ntop(AF_INET6, (void *)&myaddr.sin6_addr, ip_addr, len);
 	return 0;
 }
 
@@ -176,15 +189,15 @@
 {
 	static struct nfs4_mount_data data;
 	static char hostdir[1024];
-	static char ip_addr[16] = "127.0.0.1";
-	static struct sockaddr_in server_addr;
+	static char ip_addr[40] = "::1";
+	static struct sockaddr_in6 server_addr;
 	static int pseudoflavour[MAX_USER_FLAVOUR];
 	int num_flavour = 0;
 
 	char *hostname, *dirname, *old_opts;
 	char new_opts[1024];
 	char *opt, *opteq;
-	char *s;
+	char s[40];
 	int val;
 	int bg, soft, intr;
 	int nocto, noac;
@@ -201,13 +214,20 @@
 	if (parse_devname(hostdir, &hostname, &dirname))
 		goto fail;
 
-	if (fill_ipv4_sockaddr(hostname, &server_addr))
+	res_init();
+	_res.options |= RES_USE_INET6;
+
+	if (fill_ipv6_sockaddr(hostname, &server_addr))
 		goto fail;
-	if (get_my_ipv4addr(ip_addr, sizeof(ip_addr)))
+	if (get_my_ipv6addr(ip_addr, sizeof(ip_addr)))
 		goto fail;
 
 	/* add IP address to mtab options for use when unmounting */
-	s = inet_ntoa(server_addr.sin_addr);
+	if (IN6_IS_ADDR_V4MAPPED(&server_addr.sin6_addr))
+		inet_ntop(AF_INET, (void *)&server_addr.sin6_addr.s6_addr32[3],
+			  s, sizeof(s));
+	else
+		inet_ntop(AF_INET6, &server_addr.sin6_addr, s, sizeof(s));
 	old_opts = *extra_opts;
 	if (!old_opts)
 		old_opts = "";
@@ -242,7 +262,7 @@
 	/*
 	 * NFSv4 specifies that the default port should be 2049
 	 */
-	server_addr.sin_port = htons(NFS_PORT);
+	server_addr.sin6_port = htons(NFS_PORT);
 
 	/* parse options */
 
@@ -275,7 +295,7 @@
 			else if (!strcmp(opt, "retry"))
 				retry = val;
 			else if (!strcmp(opt, "port"))
-				server_addr.sin_port = htons(val);
+				server_addr.sin6_port = htons(val);
 			else if (!strcmp(opt, "proto")) {
 				if (!strncmp(opteq+1, "tcp", 3))
 					data.proto = IPPROTO_TCP;
@@ -357,7 +377,7 @@
 	printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n",
 	       data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
 	printf("port = %d, bg = %d, retry = %d, flags = %.8x\n",
-	       ntohs(server_addr.sin_port), bg, retry, data.flags);
+	       ntohs(server_addr.sin6_port), bg, retry, data.flags);
 	printf("soft = %d, intr = %d, nocto = %d, noac = %d\n",
 	       (data.flags & NFS4_MOUNT_SOFT) != 0,
 	       (data.flags & NFS4_MOUNT_INTR) != 0,
@@ -383,8 +403,7 @@
 
 	data.version = NFS4_MOUNT_VERSION;
 
-	clnt_ping(&server_addr, NFS_PROGRAM, 4, data.proto);
-	if (rpc_createerr.cf_stat) {
+	if (clnt_ping(&server_addr, NFS_PROGRAM, 4, data.proto) == 0) {
 		fprintf(stderr, "mount to NFS server '%s' failed.\n", data.hostname.data);
 		goto fail;
 	}
diff -Nru util-linux-2.12-3/mount/nfs_mount4.h util-linux-2.12-3-gq/mount/nfs_mount4.h
--- util-linux-2.12-3/mount/nfs_mount4.h	2005-01-18 13:12:55.000000000 +0100
+++ util-linux-2.12-3-gq/mount/nfs_mount4.h	2005-01-24 10:34:22.256211072 +0100
@@ -8,7 +8,7 @@
  * so it is easiest to ignore the kernel altogether (at compile time).
  */
 
-#define NFS_MOUNT_VERSION 6
+#define NFS_MOUNT_VERSION 7
 #define NFS_MAX_CONTEXT_LEN   256
 
 
@@ -40,7 +40,7 @@
 	struct nfs3_fh	root;			/* 4 */
 	int		pseudoflavor;		/* 5 */
 	char    context[NFS_MAX_CONTEXT_LEN + 1]; /* 6 */
-
+	struct sockaddr_in6 addr6;		/* 7 */
 };
 
 /* bits in the flags field */
diff -Nru util-linux-2.12-3/mount/nfsmount.c util-linux-2.12-3-gq/mount/nfsmount.c
--- util-linux-2.12-3/mount/nfsmount.c	2005-01-18 13:12:55.000000000 +0100
+++ util-linux-2.12-3-gq/mount/nfsmount.c	2005-01-24 10:27:09.023072520 +0100
@@ -64,6 +64,9 @@
 #include "mount_constants.h"
 #include "nfs_mount4.h"
 
+#include <resolv.h>
+#include <netconfig.h>
+
 #include "nls.h"
 
 #ifndef NFS_PORT
@@ -101,7 +104,7 @@
 
 typedef struct {
 	char **hostname;
-	struct sockaddr_in saddr;
+	struct sockaddr_storage saddr;
 	struct pmap pmap;
 } clnt_addr_t;
 
@@ -111,7 +114,10 @@
 
 static int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp);
 
-int clnt_ping(struct sockaddr_in *, const u_long, const u_long, const u_int);
+int clnt_ping(struct sockaddr_in6 *, const u_long, const u_long, const u_int);
+void rpc_strerror(void);
+
+extern int fill_ipv6_sockaddr(char *, struct sockaddr_in6 *);
 
 /* Convert RPC errors into strings */
 void rpc_strerror(void)
@@ -242,29 +248,6 @@
 	return mnt_version;
 }
 
-static int
-nfs_gethostbyname(const char *hostname, struct sockaddr_in *saddr)
-{
-	struct hostent *hp;
-
-	saddr->sin_family = AF_INET;
-	if (!inet_aton(hostname, &saddr->sin_addr)) {
-		if ((hp = gethostbyname(hostname)) == NULL) {
-			fprintf(stderr, _("mount: can't get address for %s\n"),
-				hostname);
-			return 0;
-		} else {
-			if (hp->h_length > sizeof(*saddr)) {
-				fprintf(stderr,
-					_("mount: got bad hp->h_length\n"));
-				hp->h_length = sizeof(*saddr);
-			}
-			memcpy(&saddr->sin_addr, hp->h_addr, hp->h_length);
-		}
-	}
-	return 1;
-}
-
 /*
  * Sigh... pmap_getport() doesn't actually check the version number.
  * In order to make sure that the server actually supports the service
@@ -272,37 +255,45 @@
  * RPC call.
  */
 int
-clnt_ping(struct sockaddr_in *saddr, const u_long prog, const u_long vers,
+clnt_ping(struct sockaddr_in6 *saddr6, const u_long prog, const u_long vers,
 	  const u_int prot)
 {
-	CLIENT *clnt=NULL;
-	int sock, stat;
+	CLIENT *clnt = NULL;
+	struct sockaddr_in saddr;
+	struct netconfig *nconf = NULL;
+	struct netbuf bindaddr;
+	int stat;
 	static char clnt_res;
 
 	rpc_createerr.cf_stat = stat = 0;
-	sock = RPC_ANYSOCK;
-	switch(prot) {
-	case IPPROTO_UDP:
-		clnt = clntudp_bufcreate(saddr, prog, vers,
-					 RETRY_TIMEOUT, &sock,
-					 RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
-		break;
-	case IPPROTO_TCP:
-		clnt = clnttcp_create(saddr, prog, vers, &sock,
-				      RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
-		break;
-	default:
+	if (IN6_IS_ADDR_V4MAPPED(&saddr6->sin6_addr)) {
+		saddr.sin_family = AF_INET;
+		saddr.sin_port = saddr6->sin6_port;
+		saddr.sin_addr.s_addr = saddr6->sin6_addr.s6_addr32[3];
+		nconf = getnetconfigent(prot == IPPROTO_TCP ? "tcp" : "udp");
+		bindaddr.maxlen = bindaddr.len =  sizeof (struct sockaddr_in);
+		bindaddr.buf = &saddr;
+	} else {
+		nconf = getnetconfigent(prot == IPPROTO_TCP ? "tcp6" : "udp6");
+		bindaddr.maxlen = bindaddr.len =  sizeof (struct sockaddr_in6);
+		bindaddr.buf = saddr6;
+	}
+	if (nconf == NULL) {
+		fprintf(stderr, "getnetconfigent failed\n");
 		goto out_bad;
 	}
-	if (!clnt)
+
+	clnt = clnt_tli_create(RPC_ANYFD, nconf, &bindaddr, prog, vers,
+			       RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+	if (clnt == NULL) {
 		goto out_bad;
+	}
 	memset(&clnt_res, 0, sizeof(clnt_res));
 	stat = clnt_call(clnt, NULLPROC,
 			 (xdrproc_t)xdr_void, (caddr_t)NULL,
 			 (xdrproc_t)xdr_void, (caddr_t)&clnt_res,
 			 TIMEOUT);
 	clnt_destroy(clnt);
-	close(sock);
 	if (stat != RPC_PROGVERSMISMATCH)
 		return 1;
 
@@ -320,7 +311,7 @@
 	   const u_long *versions,
 	   const u_int *protos)
 {
-	struct sockaddr_in *saddr = &server->saddr;
+	struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)&server->saddr;
 	struct pmap *pmap = &server->pmap;
 	const u_long prog = pmap->pm_prog,
 		vers = pmap->pm_vers,
@@ -331,18 +322,47 @@
 	u_short p_port;
 	p_prot = prot ? &prot : protos;
 	p_vers = vers ? &vers : versions;
+	struct netconfig *nconf, *nconf_tcp, *nconf_udp;
+	char host[64];
+	struct netbuf addr;
+
 	rpc_createerr.cf_stat = 0;
+
+	if (IN6_IS_ADDR_V4MAPPED(&saddr->sin6_addr)) {
+		inet_ntop(AF_INET,
+			  (void *)&saddr->sin6_addr.s6_addr32[3],
+			  host, sizeof(host));
+		nconf_udp = getnetconfigent("udp");
+		nconf_tcp = getnetconfigent("tcp");
+		addr.maxlen = sizeof(struct sockaddr_in);
+	} else {
+		inet_ntop(AF_INET6,
+			  (void *)&saddr->sin6_addr, host, sizeof(host));
+		nconf_udp = getnetconfigent("udp6");
+		nconf_tcp = getnetconfigent("tcp6");
+		addr.maxlen = sizeof(struct sockaddr_in6);
+	}
+	addr.buf = (char *) malloc(addr.maxlen);
+
 	for (;;) {
-		saddr->sin_port = htons(PMAPPORT);
-		p_port = pmap_getport(saddr, prog, *p_vers, *p_prot);
-		if (p_port) {
-			if (!port || port == p_port) {
-				saddr->sin_port = htons(port);
-				if (clnt_ping(saddr, prog, *p_vers, *p_prot))
-					goto out_ok;
+		nconf = IPPROTO_TCP ? nconf_tcp : nconf_udp;
+		if (nconf && rpcb_getaddr(prog, *p_vers, nconf, &addr, host)) {
+			if (addr.len == sizeof(struct sockaddr_in6)) {
+				p_port = ((struct sockaddr_in6 *)addr.buf)->sin6_port;
+			} else {
+				p_port = ((struct sockaddr_in *)addr.buf)->sin_port;
 			}
-		} else if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED)
-			break;
+			p_port = htons(p_port);
+			if (p_port) {
+				if (!port || port == p_port) {
+					saddr->sin6_port = htons(p_port);
+					if (clnt_ping(saddr, prog, *p_vers, *p_prot))
+						goto out_ok;
+				}
+			}
+			else if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED)
+				break;
+		}
 		if (!prot) {
 			if (*++p_prot)
 				continue;
@@ -429,35 +449,49 @@
 }
 
 static CLIENT *
-mnt_openclnt(clnt_addr_t *mnt_server, int *msock, const int report_errs)
+mnt_openclnt(clnt_addr_t *mnt_server, const int report_errs)
 {
-	struct sockaddr_in *mnt_saddr = &mnt_server->saddr;
+	struct sockaddr_in6 *mnt_saddr = (struct sockaddr_in6 *)&mnt_server->saddr;
 	struct pmap *mnt_pmap = &mnt_server->pmap;
+	struct netconfig *nconf;
+	struct hostent *hp;
+	struct timeval pertry;
 	CLIENT *clnt;
 
-	/* contact the mount daemon via TCP */
-	mnt_saddr->sin_port = htons((u_short)mnt_pmap->pm_port);
-	*msock = RPC_ANYSOCK;
-
+	/* contact the mount daemon */
+	mnt_saddr->sin6_port = htons((u_short)mnt_pmap->pm_port);
 	switch (mnt_pmap->pm_prot) {
 	case IPPROTO_UDP:
-		clnt = clntudp_bufcreate(mnt_saddr,
-					 mnt_pmap->pm_prog, mnt_pmap->pm_vers,
-					 RETRY_TIMEOUT, msock,
-					 MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
+		nconf = getnetconfigent(
+				IN6_IS_ADDR_V4MAPPED(&mnt_saddr->sin6_addr) ?
+				"udp" : "udp6");
 		break;
 	case IPPROTO_TCP:
-		clnt = clnttcp_create(mnt_saddr,
-				      mnt_pmap->pm_prog, mnt_pmap->pm_vers,
-				      msock,
-				      MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
+		nconf = getnetconfigent(
+				IN6_IS_ADDR_V4MAPPED(&mnt_saddr->sin6_addr) ?
+				"tcp" : "tcp6");
 		break;
 	default:
 		goto out_bad;
 	}
+	if (!nconf) {
+		if (report_errs)
+			nc_perror("mount");
+		goto out_bad;
+	}
+	hp = gethostbyaddr(&mnt_saddr->sin6_addr, sizeof(struct in6_addr),
+	 			AF_INET6);
+	if (hp == NULL)
+		goto out_bad;
+	clnt = clnt_tp_create(hp->h_name, mnt_pmap->pm_prog, mnt_pmap->pm_vers,
+				nconf);
 	if (!clnt)
 		goto report_err;
-	/* try to mount hostname:dirname */
+	if (strcmp(nconf->nc_proto, "udp")) {
+		pertry.tv_sec = 3;
+		pertry.tv_usec = 0;
+		clnt_control(clnt, CLSET_TIMEOUT, (char *) &pertry);
+	}
 	clnt->cl_auth = authunix_create_default();
 	return clnt;
  report_err:
@@ -468,11 +502,10 @@
 }
 
 static inline void
-mnt_closeclnt(CLIENT *clnt, int msock)
+mnt_closeclnt(CLIENT *clnt)
 {
 	auth_destroy(clnt->cl_auth);
 	clnt_destroy(clnt);
-	close(msock);
 }
 
 static inline enum clnt_stat
@@ -499,7 +532,6 @@
 {
 	CLIENT *clnt;
 	enum clnt_stat stat;
-	int msock;
 
 	if (!probe_bothports(mnt_server, nfs_server)) {
 		if (report_errs) {
@@ -521,7 +553,7 @@
 		goto out_bad;
 	}
 
-	clnt = mnt_openclnt(mnt_server, &msock, report_errs);
+	clnt = mnt_openclnt(mnt_server, report_errs);
 	if (!clnt)
 		goto out_bad;
 	/* make pointers in xdr_mountres3 NULL so
@@ -541,7 +573,7 @@
 	}
 	if (stat != RPC_SUCCESS && report_errs)
 		clnt_perror(clnt, "mount");
-	mnt_closeclnt(clnt, msock);
+	mnt_closeclnt(clnt);
 	if (stat == RPC_SUCCESS)
 		return 1;
  out_bad:
@@ -553,7 +585,7 @@
 	      int *bg, int *retry, clnt_addr_t *mnt_server,
 	      clnt_addr_t *nfs_server, char *new_opts, const int opt_size)
 {
-	struct sockaddr_in *mnt_saddr = &mnt_server->saddr;
+	struct sockaddr_in6 *mnt_saddr = (struct sockaddr_in6 *)&mnt_server->saddr;
 	struct pmap *mnt_pmap = &mnt_server->pmap;
 	struct pmap *nfs_pmap = &nfs_server->pmap;
 	int len;
@@ -757,7 +789,7 @@
 					data->flags |= NFS_MOUNT_BROKEN_SUID;
 				}
 #endif
-			} else if (!sloppy) {
+ 			} else if (!sloppy) {
 			bad_option:
 				printf(_("Unsupported nfs mount option: "
 					 "%s%s\n"), val ? "" : "no", opt);
@@ -774,7 +806,7 @@
 	}
 	/* See if the nfs host = mount host. */
 	if (mounthost) {
-		if (!nfs_gethostbyname(mounthost, mnt_saddr))
+		if (fill_ipv6_sockaddr(mounthost, mnt_saddr) == -1)
 			goto out_bad;
 		*mnt_server->hostname = mounthost;
 	}
@@ -822,7 +854,7 @@
 
 	clnt_addr_t mnt_server = { &mounthost, };
 	clnt_addr_t nfs_server = { &hostname, };
-	struct sockaddr_in *nfs_saddr = &nfs_server.saddr;
+	struct sockaddr_in6 *nfs_saddr = (struct sockaddr_in6 *)&nfs_server.saddr;
 	struct pmap  *mnt_pmap = &mnt_server.pmap,
 		     *nfs_pmap = &nfs_server.pmap;
 	struct pmap  save_mnt, save_nfs;
@@ -833,6 +865,7 @@
 
 	struct stat statbuf;
 	char *s;
+	char str[64];
 	int bg, retry;
 	int retval;
 	time_t t;
@@ -845,6 +878,9 @@
 		*nfs_mount_vers = find_kernel_nfs_mount_version();
 	nfs_mount_version = *nfs_mount_vers;
 
+	res_init();
+	_res.options |= RES_USE_INET6;
+
 	retval = EX_FAIL;
 	fsock = -1;
 	if (strlen(spec) >= sizeof(hostdir)) {
@@ -853,7 +889,7 @@
 		goto fail;
 	}
 	strcpy(hostdir, spec);
-	if ((s = strchr(hostdir, ':'))) {
+	if ((s = strrchr(hostdir, ':'))) {
 		hostname = hostdir;
 		dirname = s + 1;
 		*s = '\0';
@@ -872,14 +908,11 @@
 		goto fail;
 	}
 
-	if (!nfs_gethostbyname(hostname, nfs_saddr))
+	if (fill_ipv6_sockaddr(hostname, nfs_saddr) == -1)
 		goto fail;
 	mounthost = hostname;
 	memcpy (&mnt_server.saddr, nfs_saddr, sizeof (mnt_server.saddr));
 
-	/* add IP address to mtab options for use when unmounting */
-
-	s = inet_ntoa(nfs_saddr->sin_addr);
 	old_opts = *extra_opts;
 	if (!old_opts)
 		old_opts = "";
@@ -1091,9 +1124,9 @@
 	/* create nfs socket for kernel */
 
 	if (nfs_pmap->pm_prot == IPPROTO_TCP)
-		fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+		fsock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
 	else
-		fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+		fsock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
 	if (fsock < 0) {
 		perror(_("nfs socket"));
 		goto fail;
@@ -1105,7 +1138,7 @@
 #ifdef NFS_MOUNT_DEBUG
 	printf(_("using port %d for nfs deamon\n"), nfs_pmap->pm_port);
 #endif
-	nfs_saddr->sin_port = htons(nfs_pmap->pm_port);
+	nfs_saddr->sin6_port = htons(nfs_pmap->pm_port);
 	/*
 	 * connect() the socket for kernels 1.3.10 and below only,
 	 * to avoid problems with multihomed hosts.
@@ -1128,18 +1161,30 @@
 	/* prepare data structure for kernel */
 
 	data.fd = fsock;
-	memcpy((char *) &data.addr, (char *) nfs_saddr, sizeof(data.addr));
+	data.addr.sin_family = AF_INET6;	/* to indicate that the address
+						   is in the addr6 field */
+	memcpy((char *) &data.addr6, (char *) nfs_saddr, sizeof(data.addr6));
 	strncpy(data.hostname, hostname, sizeof(data.hostname));
 
  out_ok:
+	/* add IP address to mtab options for use when unmounting */
+
+	if (IN6_IS_ADDR_V4MAPPED(&nfs_saddr->sin6_addr))
+		inet_ntop(AF_INET,
+			  (void *)&nfs_saddr->sin6_addr.s6_addr32[3],
+			  str, sizeof(str));
+	else
+		inet_ntop(AF_INET6,
+			  (void *)&nfs_saddr->sin6_addr,
+			  str, sizeof(str));
 	/* Ensure we have enough padding for the following strcat()s */
-	if (strlen(new_opts) + strlen(s) + 30 >= sizeof(new_opts)) {
+	if (strlen(new_opts) + strlen(str) + 30 >= sizeof(new_opts)) {
 		fprintf(stderr, _("mount: "
 				  "excessively long option argument\n"));
 		goto fail;
 	}
 
-	sprintf(cbuf, "addr=%s", s);
+	sprintf(cbuf, "addr=%s", str);
 	strcat(new_opts, cbuf);
 
 	*extra_opts = xstrdup(new_opts);
@@ -1179,9 +1224,8 @@
 {
 	CLIENT *clnt;
 	enum clnt_stat res = 0;
-	int msock;
 
-	clnt = mnt_openclnt(mnt_server, &msock, 1);
+	clnt = mnt_openclnt(mnt_server, 1);
 	if (!clnt)
 		goto out_bad;
 	switch (mnt_server->pmap.pm_vers) {
@@ -1195,7 +1239,7 @@
 	default:
 		break;
 	}
-	mnt_closeclnt(clnt, msock);
+	mnt_closeclnt(clnt);
 	if (res == RPC_SUCCESS)
 		return 1;
  out_bad:
@@ -1212,7 +1256,7 @@
 	char *p;
 
 	nfs_mount_version = find_kernel_nfs_mount_version();
-	if (spec == NULL || (p = strchr(spec,':')) == NULL)
+	if (spec == NULL || (p = strrchr(spec,':')) == NULL)
 		goto out_bad;
 	hostname = xstrndup(spec, p-spec);
 	dirname = xstrdup(p+1);
@@ -1251,7 +1295,7 @@
 	if (opts && (p = strstr(opts, "mountvers=")) && isdigit(*(p+10)))
 		pmap->pm_vers = atoi(p+10);
 
-	if (!nfs_gethostbyname(hostname, &mnt_server.saddr))
+	if (fill_ipv6_sockaddr(hostname, (struct sockaddr_in6 *)&mnt_server.saddr) == -1)
 		goto out_bad;
 	if (!probe_mntport(&mnt_server))
 		goto out_bad;
