+ /*
+ * Extract just the options needed to contact server.
+ * Bail now if any of these have bad values.
+ */
+ if (!nfs_extract_server_addresses(options, nfs_saddr, &nfs_salen,
+ mnt_saddr, &mnt_salen)) {
+ errno = EINVAL;
+ goto err;
+ }
+ if (!nfs_options2pmap(options, &nfs_pmap, &mnt_pmap)) {
+ errno = EINVAL;
+ goto err;
+ }
+
+ /*
+ * The kernel NFS client doesn't support changing the RPC
+ * program number for these services, so force the value of
+ * these fields before probing the server's ports.
+ */
+ nfs_pmap.pm_prog = NFS_PROGRAM;
+ mnt_pmap.pm_prog = MOUNTPROG;
+
+ /*
+ * If the server's rpcbind service isn't available, we can't
+ * negotiate. Bail now if we can't contact it.
+ */
+ 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;
+ }
+
+out:
+ errno = 0;
+ return options;
+
+err:
+ po_destroy(options);
+ return NULL;
+}
+
+/*
+ * Do the mount(2) system call.
+ *
+ * Returns 1 if successful, otherwise zero.
+ * "errno" is set to reflect the individual error.
+ */
+static int nfs_sys_mount(const struct nfsmount_info *mi, const char *type,
+ const char *options)
+{
+ int result;
+
+ result = mount(mi->spec, mi->node, type,
+ mi->flags & ~(MS_USER|MS_USERS), options);
+ if (verbose && result) {
+ int save = errno;
+ nfs_error(_("%s: mount(2): %s"), progname, strerror(save));
+ errno = save;
+ }
+ return !result;
+}
+
+/*
+ * Retry an NFS mount that failed because the requested service isn't
+ * available on the server.
+ *
+ * Returns 1 if successful. Otherwise, returns zero.
+ * "errno" is set to reflect the individual error.
+ *
+ * Side effect: If the retry is successful, both 'options' and
+ * 'extra_opts' are updated to reflect the mount options that worked.
+ * If the retry fails, 'options' and 'extra_opts' are left unchanged.
+ */
+static int nfs_retry_nfs23mount(struct nfsmount_info *mi)
+{
+ struct mount_options *retry_options;
+ char *retry_str = NULL;
+ char **extra_opts = mi->extra_opts;
+
+ retry_options = nfs_rewrite_mount_options(*extra_opts);
+ if (!retry_options)