/** * nfs_options2pmap - set up pmap structs based on mount options * @options: pointer to mount options * @nfs_pmap: OUT: pointer to pmap arguments for NFS server * @mnt_pmap: OUT: pointer to pmap arguments for mountd server * */ void nfs_options2pmap(struct mount_options *options, struct pmap *nfs_pmap, struct pmap *mnt_pmap) { nfs_pmap->pm_prog = nfs_nfs_program(options); nfs_pmap->pm_vers = nfs_nfs_version(options); nfs_pmap->pm_prot = nfs_nfs_protocol(options); nfs_pmap->pm_port = nfs_nfs_port(options); mnt_pmap->pm_prog = nfs_mount_program(options); mnt_pmap->pm_vers = nfs_mount_version(options); mnt_pmap->pm_prot = nfs_mount_protocol(options); mnt_pmap->pm_port = nfs_mount_port(options); }
/* * 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_pmap_mount_options() * doesn't recognize are left alone. * * Returns TRUE if rewriting was successful; otherwise * FALSE is returned if some failure occurred. */ static int nfs_rewrite_pmap_mount_options(struct mount_options *options, int checkv4, struct local_bind_info *local_ip) { union nfs_sockaddr nfs_address; struct sockaddr *nfs_saddr = &nfs_address.sa; socklen_t nfs_salen = sizeof(nfs_address); struct pmap nfs_pmap; union nfs_sockaddr mnt_address; struct sockaddr *mnt_saddr = &mnt_address.sa; socklen_t mnt_salen = sizeof(mnt_address); unsigned long protocol; struct pmap mnt_pmap; /* * Version and transport negotiation is not required * and does not work for RDMA mounts. */ if (!nfs_nfs_protocol(options, &protocol)) { errno = EINVAL; return 0; } if (protocol == NFSPROTO_RDMA) goto out; /* * 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; return 0; } if (!nfs_options2pmap(options, &nfs_pmap, &mnt_pmap)) { errno = EINVAL; return 0; } /* * 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, checkv4, local_ip)) { errno = ESPIPE; if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED) errno = EOPNOTSUPP; else if (rpc_createerr.cf_stat == RPC_AUTHERROR) errno = EACCES; else if (rpc_createerr.cf_stat == RPC_TIMEDOUT) errno = ETIMEDOUT; else if (rpc_createerr.cf_stat == RPC_PROGVERSMISMATCH) errno = EPROTONOSUPPORT; else if (rpc_createerr.cf_error.re_errno != 0) errno = rpc_createerr.cf_error.re_errno; return 0; } if (!nfs_construct_new_options(options, nfs_saddr, &nfs_pmap, mnt_saddr, &mnt_pmap)) { if (rpc_createerr.cf_stat == RPC_UNKNOWNPROTO) errno = EPROTONOSUPPORT; else errno = EINVAL; return 0; } out: errno = 0; return 1; }