+ po_remove_all(options, "mountvers");
+ snprintf(new_option, sizeof(new_option) - 1,
+ "mountvers=%lu", mnt_pmap->pm_vers);
+ if (po_append(options, new_option) == PO_FAILED)
+ return 0;
+
+ po_remove_all(options, "mountproto");
+ switch (mnt_pmap->pm_prot) {
+ case IPPROTO_TCP:
+ snprintf(new_option, sizeof(new_option) - 1,
+ "mountproto=tcp");
+ if (po_append(options, new_option) == PO_FAILED)
+ return 0;
+ break;
+ case IPPROTO_UDP:
+ snprintf(new_option, sizeof(new_option) - 1,
+ "mountproto=udp");
+ if (po_append(options, new_option) == PO_FAILED)
+ return 0;
+ break;
+ }
+
+ po_remove_all(options, "mountport");
+ snprintf(new_option, sizeof(new_option) - 1,
+ "mountport=%lu", mnt_pmap->pm_port);
+ if (po_append(options, new_option) == PO_FAILED)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Reconstruct the mount option string based on a portmapper probe
+ * of the server. Returns one if the server's portmapper returned
+ * something we can use, otherwise zero.
+ *
+ * To handle version and transport protocol fallback properly, we
+ * need to parse some of the mount options in order to set up a
+ * portmap probe. Mount options that nfs_rewrite_mount_options()
+ * doesn't recognize are left alone.
+ *
+ * Returns a new group of mount options if successful; otherwise
+ * NULL is returned if some failure occurred.
+ */
+static struct mount_options *nfs_rewrite_mount_options(char *str)
+{
+ struct mount_options *options;
+ struct sockaddr_storage nfs_address;
+ struct sockaddr *nfs_saddr = (struct sockaddr *)&nfs_address;
+ socklen_t nfs_salen;
+ struct pmap nfs_pmap;
+ struct sockaddr_storage mnt_address;
+ struct sockaddr *mnt_saddr = (struct sockaddr *)&mnt_address;
+ socklen_t mnt_salen;
+ struct pmap mnt_pmap;
+
+ options = po_split(str);
+ if (!options) {
+ errno = EFAULT;
+ return NULL;
+ }
+
+ if (!nfs_extract_server_addresses(options, nfs_saddr, &nfs_salen,
+ mnt_saddr, &mnt_salen)) {
+ errno = EINVAL;
+ goto err;
+ }
+
+ nfs_options2pmap(options, &nfs_pmap, &mnt_pmap);
+
+ /* The kernel NFS client doesn't support changing the RPC program
+ * number for these services, so reset these fields before probing
+ * the server's ports. */
+ nfs_pmap.pm_prog = NFS_PROGRAM;
+ mnt_pmap.pm_prog = MOUNTPROG;
+
+ if (!nfs_probe_bothports(mnt_saddr, mnt_salen, &mnt_pmap,
+ nfs_saddr, nfs_salen, &nfs_pmap)) {
+ errno = ESPIPE;
+ goto err;
+ }
+
+ if (!nfs_construct_new_options(options, &nfs_pmap, &mnt_pmap)) {
+ errno = EINVAL;
+ goto err;