+ errno = EINVAL;
+ option = po_get(options, "addr");
+ if (option) {
+ nfs_server.saddr.sin_family = AF_INET;
+ if (!inet_aton((const char *)option, &nfs_server.saddr.sin_addr))
+ goto err;
+ } else
+ goto err;
+
+ option = po_get(options, "mountaddr");
+ if (option) {
+ mnt_server.saddr.sin_family = AF_INET;
+ if (!inet_aton((const char *)option, &mnt_server.saddr.sin_addr))
+ goto err;
+ } else
+ memcpy(&mnt_server.saddr, &nfs_server.saddr,
+ sizeof(mnt_server.saddr));
+
+ nfs_options2pmap(options, &nfs_server.pmap, &mnt_server.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_server.pmap.pm_prog = NFS_PROGRAM;
+ mnt_server.pmap.pm_prog = MOUNTPROG;
+
+ if (!probe_bothports(&mnt_server, &nfs_server)) {
+ errno = ESPIPE;
+ goto err;
+ }
+
+ snprintf(new_option, sizeof(new_option) - 1,
+ "nfsvers=%lu", nfs_server.pmap.pm_vers);
+ if (po_append(options, new_option) == PO_FAILED)
+ goto err;
+
+ if (nfs_server.pmap.pm_prot == IPPROTO_TCP)
+ snprintf(new_option, sizeof(new_option) - 1,
+ "proto=tcp");
+ else
+ snprintf(new_option, sizeof(new_option) - 1,
+ "proto=udp");
+ if (po_append(options, new_option) == PO_FAILED)
+ goto err;
+
+ if (nfs_server.pmap.pm_port != NFS_PORT) {
+ snprintf(new_option, sizeof(new_option) - 1,
+ "port=%lu", nfs_server.pmap.pm_port);
+ if (po_append(options, new_option) == PO_FAILED)
+ goto err;
+
+ }
+
+ if (mnt_server.pmap.pm_prot == IPPROTO_TCP)
+ snprintf(new_option, sizeof(new_option) - 1,
+ "mountproto=tcp");
+ else
+ snprintf(new_option, sizeof(new_option) - 1,
+ "mountproto=udp");
+ if (po_append(options, new_option) == PO_FAILED)
+ goto err;
+
+ snprintf(new_option, sizeof(new_option) - 1,
+ "mountport=%lu", mnt_server.pmap.pm_port);
+ if (po_append(options, new_option) == PO_FAILED)
+ goto err;
+
+ errno = 0;
+ return options;
+
+err:
+ po_destroy(options);
+ return NULL;