mount: make FEATURE_MOUNT_NFS not needed for Linux 2.6.23+

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/util-linux/Config.src b/util-linux/Config.src
index 888bc8f..57a52ce 100644
--- a/util-linux/Config.src
+++ b/util-linux/Config.src
@@ -485,13 +485,18 @@
 	  This also enables label or uuid support for swapon.
 
 config FEATURE_MOUNT_NFS
-	bool "Support mounting NFS file systems"
-	default y
+	bool "Support mounting NFS file systems on Linux < 2.6.23"
+	default n
 	depends on MOUNT
 	select FEATURE_HAVE_RPC
 	select FEATURE_SYSLOG
 	help
-	  Enable mounting of NFS file systems.
+	  Enable mounting of NFS file systems on Linux kernels prior
+	  to version 2.6.23. Note that in this case mounting of NFS
+	  over IPv6 will not be possible.
+
+	  Note that this option links in RPC support from libc,
+	  which is rather large (~10 kbytes on uclibc).
 
 config FEATURE_MOUNT_CIFS
 	bool "Support mounting CIFS/SMB file systems"
diff --git a/util-linux/mount.c b/util-linux/mount.c
index 1dd4c0c..7ae1981 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -1144,7 +1144,7 @@
 	pathname = s + 1;
 	*s = '\0';
 	/* Ignore all but first hostname in replicated mounts
-	   until they can be fully supported. (mack@sgi.com) */
+	 * until they can be fully supported. (mack@sgi.com) */
 	s = strchr(hostname, ',');
 	if (s) {
 		*s = '\0';
@@ -1683,7 +1683,6 @@
 
 	/* Perform actual mount */
  do_mount:
-	mp->mnt_type = (char*)"nfs";
 	retval = mount_it_now(mp, vfsflags, (char*)&data);
 	goto ret;
 
@@ -1708,8 +1707,43 @@
 
 #else // !ENABLE_FEATURE_MOUNT_NFS
 
-// Never called. Call should be optimized out.
-int nfsmount(struct mntent *mp, long vfsflags, char *filteropts);
+/* Linux 2.6.23+ supports nfs mounts with options passed as a string.
+ * For older kernels, you must build busybox with ENABLE_FEATURE_MOUNT_NFS.
+ * (However, note that then you lose any chances that NFS over IPv6 would work).
+ */
+static int nfsmount(struct mntent *mp, long vfsflags, char *filteropts)
+{
+	len_and_sockaddr *lsa;
+	char *opts;
+	char *end;
+	char *dotted;
+	int ret;
+
+# if ENABLE_FEATURE_IPV6
+	end = strchr(mp->mnt_fsname, ']');
+	if (end && end[1] == ':')
+		end++;
+	else
+# endif
+		/* mount_main() guarantees that ':' is there */
+		end = strchr(mp->mnt_fsname, ':');
+
+	*end = '\0';
+	lsa = xdotted2sockaddr(mp->mnt_fsname, /*port:*/ 0);
+	*end = ':';
+	dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
+	if (ENABLE_FEATURE_CLEAN_UP) free(lsa);
+	opts = xasprintf("%s%saddr=%s",
+		filteropts ? filteropts : "",
+		filteropts ? "," : "",
+		dotted
+	);
+	if (ENABLE_FEATURE_CLEAN_UP) free(dotted);
+	ret = mount_it_now(mp, vfsflags, opts);
+	if (ENABLE_FEATURE_CLEAN_UP) free(opts);
+
+	return ret;
+}
 
 #endif // !ENABLE_FEATURE_MOUNT_NFS
 
@@ -1800,10 +1834,11 @@
 	}
 
 	// Might this be an NFS filesystem?
-	if (ENABLE_FEATURE_MOUNT_NFS
-	 && (!mp->mnt_type || strcmp(mp->mnt_type, "nfs") == 0)
+	if ((!mp->mnt_type || strncmp(mp->mnt_type, "nfs", 3) == 0)
 	 && strchr(mp->mnt_fsname, ':') != NULL
 	) {
+		if (!mp->mnt_type)
+			mp->mnt_type = (char*)"nfs";
 		rc = nfsmount(mp, vfsflags, filteropts);
 		goto report_error;
 	}