This is an automated email from the ASF dual-hosted git repository. gnutt pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 7794214a7dd93ecfae02bc1b7eca94b26f7e2786 Author: Xiang Xiao <xiaoxi...@xiaomi.com> AuthorDate: Sun Mar 1 17:24:29 2020 +0800 fs/nfs: Support both IPv6 and TCP And correctly handle the retransmission --- fs/nfs/Kconfig | 2 +- fs/nfs/nfs.h | 2 +- fs/nfs/nfs_mount.h | 4 +- fs/nfs/nfs_util.c | 13 +- fs/nfs/nfs_vfsops.c | 112 +++++------- fs/nfs/rpc.h | 5 +- fs/nfs/rpc_clnt.c | 394 +++++++++++++++++++++++------------------- include/nuttx/net/netconfig.h | 1 + 8 files changed, 271 insertions(+), 262 deletions(-) diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 4a9effc..a25b3b5 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig @@ -6,7 +6,7 @@ config NFS bool "NFS client file system" default n - depends on NET_UDP && NET_IPv4 && !DISABLE_MOUNTPOINT + depends on !DISABLE_MOUNTPOINT select FS_READABLE select FS_WRITABLE ---help--- diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h index a17750c..3f17e2e 100644 --- a/fs/nfs/nfs.h +++ b/fs/nfs/nfs.h @@ -61,7 +61,7 @@ #define NFS_RETRANS 10 /* Num of retrans for soft mounts */ #define NFS_WSIZE 8192 /* Def. write data size <= 8192 */ #define NFS_RSIZE 8192 /* Def. read data size <= 8192 */ -#define NFS_READDIRSIZE 8192 /* Def. readdir size */ +#define NFS_READDIRSIZE 1024 /* Def. readdir size */ /* Ideally, NFS_DIRBLKSIZ should be bigger, but I've seen servers with * broken NFS/ethernet drivers that won't work with anything bigger (Linux..) diff --git a/fs/nfs/nfs_mount.h b/fs/nfs/nfs_mount.h index 4bab615..4c9cf54 100644 --- a/fs/nfs/nfs_mount.h +++ b/fs/nfs/nfs_mount.h @@ -73,7 +73,7 @@ struct nfsmount char nm_path[90]; /* server's path of the directory being mounted */ struct nfs_fattr nm_fattr; /* nfs file attribute cache */ FAR struct rpcclnt *nm_rpcclnt; /* RPC state */ - struct sockaddr nm_nam; /* Addr of server */ + struct sockaddr_storage nm_nam; /* Addr of server */ uint8_t nm_fhsize; /* Size of root file handle (host order) */ uint16_t nm_rsize; /* Max size of read RPC */ uint16_t nm_wsize; /* Max size of write RPC */ @@ -87,8 +87,6 @@ struct nfsmount union { - struct rpc_call_pmap pmap; - struct rpc_call_mount mountd; struct rpc_call_create create; struct rpc_call_lookup lookup; struct rpc_call_read read; diff --git a/fs/nfs/nfs_util.c b/fs/nfs/nfs_util.c index abfa796..166b661 100644 --- a/fs/nfs/nfs_util.c +++ b/fs/nfs/nfs_util.c @@ -149,18 +149,9 @@ int nfs_request(FAR struct nfsmount *nmp, int procnum, if (replyh.nfs_status != 0) { - if (fxdr_unsigned(uint32_t, replyh.nfs_status) > 32) - { - error = -EOPNOTSUPP; - } - else - { - /* NFS_ERRORS are the same as NuttX errno values */ + /* NFS_ERRORS are the same as NuttX errno values */ - error = -fxdr_unsigned(uint32_t, replyh.nfs_status); - } - - return error; + return -fxdr_unsigned(uint32_t, replyh.nfs_status); } if (replyh.rh.rpc_verfi.authtype != 0) diff --git a/fs/nfs/nfs_vfsops.c b/fs/nfs/nfs_vfsops.c index fe5cbbe..7d74670 100644 --- a/fs/nfs/nfs_vfsops.c +++ b/fs/nfs/nfs_vfsops.c @@ -66,8 +66,6 @@ #include <nuttx/fs/dirent.h> #include <nuttx/fs/fs.h> #include <nuttx/fs/nfs.h> -#include <nuttx/net/udp.h> -#include <nuttx/net/arp.h> #include <nuttx/net/netconfig.h> #include <net/if.h> @@ -1634,16 +1632,20 @@ static void nfs_decode_args(FAR struct nfs_mount_parameters *nprmt, /* Get the maximum amount of data that can be transferred in one packet */ - if ((argp->sotype == SOCK_DGRAM) != 0) + if (argp->sotype == SOCK_DGRAM) { maxio = NFS_MAXDGRAMDATA; } else { - ferr("ERROR: Only SOCK_DRAM is supported\n"); maxio = NFS_MAXDATA; } + if (maxio > MAXBSIZE) + { + maxio = MAXBSIZE; + } + /* Get the maximum amount of data that can be transferred in one write transfer */ if ((argp->flags & NFSMNT_WSIZE) != 0 && argp->wsize > 0) @@ -1664,11 +1666,6 @@ static void nfs_decode_args(FAR struct nfs_mount_parameters *nprmt, nprmt->wsize = maxio; } - if (nprmt->wsize > MAXBSIZE) - { - nprmt->wsize = MAXBSIZE; - } - /* Get the maximum amount of data that can be transferred in one read transfer */ if ((argp->flags & NFSMNT_RSIZE) != 0 && argp->rsize > 0) @@ -1689,11 +1686,6 @@ static void nfs_decode_args(FAR struct nfs_mount_parameters *nprmt, nprmt->rsize = maxio; } - if (nprmt->rsize > MAXBSIZE) - { - nprmt->rsize = MAXBSIZE; - } - /* Get the maximum amount of data that can be transferred in directory transfer */ if ((argp->flags & NFSMNT_READDIRSIZE) != 0 && argp->readdirsize > 0) @@ -1772,6 +1764,14 @@ static int nfs_bind(FAR struct inode *blkdriver, FAR const void *data, buflen = tmp; } + /* And consider the maximum size of a read dir transfer too */ + + tmp = SIZEOF_rpc_reply_readdir(nprmt.readdirsize); + if (tmp > buflen) + { + buflen = tmp; + } + /* But don't let the buffer size exceed the MSS of the socket type. * * In the case where there are multiple network devices with different @@ -1780,9 +1780,9 @@ static int nfs_bind(FAR struct inode *blkdriver, FAR const void *data, * that case. */ - if (buflen > MIN_IPv4_UDP_MSS) + if (argp->sotype == SOCK_DGRAM && buflen > MIN_UDP_MSS) { - buflen = MIN_IPv4_UDP_MSS; + buflen = MIN_UDP_MSS; } /* Create an instance of the mountpt state structure */ @@ -1824,43 +1824,36 @@ static int nfs_bind(FAR struct inode *blkdriver, FAR const void *data, strncpy(nmp->nm_path, argp->path, 90); memcpy(&nmp->nm_nam, &argp->addr, argp->addrlen); - /* Set up the sockets and per-host congestion */ + /* Create an instance of the rpc state structure */ - if (argp->sotype == SOCK_DGRAM) + rpc = (FAR struct rpcclnt *)kmm_zalloc(sizeof(struct rpcclnt)); + if (!rpc) { - /* Connection-less... connect now */ - - /* Create an instance of the rpc state structure */ - - rpc = (FAR struct rpcclnt *)kmm_zalloc(sizeof(struct rpcclnt)); - if (!rpc) - { - ferr("ERROR: Failed to allocate rpc structure\n"); - return -ENOMEM; - } + ferr("ERROR: Failed to allocate rpc structure\n"); + return -ENOMEM; + } - finfo("Connecting\n"); + finfo("Connecting\n"); - /* Translate nfsmnt flags -> rpcclnt flags */ + /* Translate nfsmnt flags -> rpcclnt flags */ - rpc->rc_path = nmp->nm_path; - rpc->rc_name = &nmp->nm_nam; - rpc->rc_sotype = argp->sotype; - rpc->rc_timeo = nprmt.timeo; - rpc->rc_retry = nprmt.retry; + rpc->rc_path = nmp->nm_path; + rpc->rc_name = &nmp->nm_nam; + rpc->rc_sotype = argp->sotype; + rpc->rc_timeo = nprmt.timeo; + rpc->rc_retry = nprmt.retry; - nmp->nm_rpcclnt = rpc; + nmp->nm_rpcclnt = rpc; - error = rpcclnt_connect(nmp->nm_rpcclnt); - if (error != OK) - { - ferr("ERROR: nfs_connect failed: %d\n", error); - goto bad; - } + error = rpcclnt_connect(nmp->nm_rpcclnt); + if (error != OK) + { + ferr("ERROR: nfs_connect failed: %d\n", error); + goto bad; } - nmp->nm_fhsize = nmp->nm_rpcclnt->rc_fhsize; - nmp->nm_fh = &nmp->nm_rpcclnt->rc_fh; + nmp->nm_fhsize = nmp->nm_rpcclnt->rc_fhsize; + nmp->nm_fh = &nmp->nm_rpcclnt->rc_fh; /* Get the file sytem info */ @@ -1880,21 +1873,18 @@ static int nfs_bind(FAR struct inode *blkdriver, FAR const void *data, return OK; bad: - if (nmp) - { - /* Disconnect from the server */ + /* Disconnect from the server */ - if (nmp->nm_rpcclnt) - { - rpcclnt_disconnect(nmp->nm_rpcclnt); - kmm_free(nmp->nm_rpcclnt); - } + if (nmp->nm_rpcclnt) + { + rpcclnt_disconnect(nmp->nm_rpcclnt); + kmm_free(nmp->nm_rpcclnt); + } - /* Free connection-related resources */ + /* Free connection-related resources */ - nxsem_destroy(&nmp->nm_sem); - kmm_free(nmp); - } + nxsem_destroy(&nmp->nm_sem); + kmm_free(nmp); return error; } @@ -1941,14 +1931,6 @@ static int nfs_unbind(FAR void *handle, FAR struct inode **blkdriver, goto errout_with_semaphore; } - /* No open file... Umount the file system. */ - - error = rpcclnt_umount(nmp->nm_rpcclnt); - if (error) - { - ferr("ERROR: rpcclnt_umount failed: %d\n", error); - } - /* Disconnect from the server */ rpcclnt_disconnect(nmp->nm_rpcclnt); @@ -1959,7 +1941,7 @@ static int nfs_unbind(FAR void *handle, FAR struct inode **blkdriver, kmm_free(nmp->nm_rpcclnt); kmm_free(nmp); - return error; + return OK; errout_with_semaphore: nfs_semgive(nmp); diff --git a/fs/nfs/rpc.h b/fs/nfs/rpc.h index 1139338..06daa96 100644 --- a/fs/nfs/rpc.h +++ b/fs/nfs/rpc.h @@ -146,7 +146,6 @@ /* RPC definitions for the portmapper. */ -#define PMAPPORT 111 #define PMAPPROG 100000 #define PMAPVERS 2 @@ -450,12 +449,13 @@ struct rpcclnt uint8_t rc_fhsize; /* File size of the root directory */ FAR char *rc_path; /* Server's path of the mounted directory */ - FAR struct sockaddr *rc_name; + FAR struct sockaddr_storage *rc_name; struct socket rc_so; /* RPC socket */ uint8_t rc_sotype; /* Type of socket */ uint8_t rc_timeo; /* Timeout value (in deciseconds) */ uint8_t rc_retry; /* Max retries */ + uint32_t rc_xid; /* Transaction id */ }; /**************************************************************************** @@ -465,7 +465,6 @@ struct rpcclnt void rpcclnt_init(void); int rpcclnt_connect(FAR struct rpcclnt *rpc); void rpcclnt_disconnect(FAR struct rpcclnt *rpc); -int rpcclnt_umount(FAR struct rpcclnt *rpc); int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, int version, FAR void *request, size_t reqlen, FAR void *response, size_t resplen); diff --git a/fs/nfs/rpc_clnt.c b/fs/nfs/rpc_clnt.c index aa40e46..43f847f 100644 --- a/fs/nfs/rpc_clnt.c +++ b/fs/nfs/rpc_clnt.c @@ -81,12 +81,9 @@ #include <sys/socket.h> #include <sys/time.h> #include <queue.h> -#include <time.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> -#include <stdio.h> -#include <stdlib.h> #include <string.h> #include <debug.h> @@ -143,13 +140,13 @@ static struct rpcstats rpcstats; * Private Function Prototypes ****************************************************************************/ +static int rpcclnt_socket(FAR struct rpcclnt *rpc, in_port_t rport); static int rpcclnt_send(FAR struct rpcclnt *rpc, FAR void *call, int reqlen); static int rpcclnt_receive(FAR struct rpcclnt *rpc, FAR void *reply, size_t resplen); -static int rpcclnt_reply(FAR struct rpcclnt *rpc, +static int rpcclnt_reply(FAR struct rpcclnt *rpc, uint32_t xid, FAR void *reply, size_t resplen); -static uint32_t rpcclnt_newxid(void); static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch, uint32_t xid, int procid, int prog, int vers); @@ -158,6 +155,132 @@ static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch, ****************************************************************************/ /**************************************************************************** + * Name: rpcclnt_socket + * + * Description: + * Close(old), create, bind and connect the socket. + * + * Returned Value: + * Returns zero on success or a (negative) errno value on failure. + * + ****************************************************************************/ + +static int rpcclnt_socket(FAR struct rpcclnt *rpc, in_port_t rport) +{ + struct sockaddr_storage raddr; + struct sockaddr_storage laddr; + FAR in_port_t *lport; + in_port_t port = 1024; + struct timeval tv; + socklen_t addrlen; + int error; + + /* Close the old socket */ + + psock_close(&rpc->rc_so); + + /* Prepare the socket address */ + + memcpy(&raddr, rpc->rc_name, sizeof(raddr)); + + laddr.ss_family = raddr.ss_family; + memset(laddr.ss_data, 0, sizeof(laddr.ss_data)); + + if (raddr.ss_family == AF_INET6) + { + FAR struct sockaddr_in6 *sin; + + addrlen = sizeof(struct sockaddr_in6); + if (rport != 0) + { + sin = (FAR struct sockaddr_in6 *)&raddr; + sin->sin6_port = htons(rport); + } + + sin = (FAR struct sockaddr_in6 *)&laddr; + lport = &sin->sin6_port; + } + else + { + FAR struct sockaddr_in *sin; + + addrlen = sizeof(struct sockaddr_in); + if (rport != 0) + { + sin = (FAR struct sockaddr_in *)&raddr; + sin->sin_port = htons(rport); + } + + sin = (FAR struct sockaddr_in *)&laddr; + lport = &sin->sin_port; + } + + /* Create the socket */ + + error = psock_socket(raddr.ss_family, rpc->rc_sotype, 0, &rpc->rc_so); + if (error < 0) + { + ferr("ERROR: psock_socket failed: %d", error); + return error; + } + + /* Always set receive timeout to detect server crash and reconnect. + * Otherwise, we can get stuck in psock_receive forever. + */ + + tv.tv_sec = rpc->rc_timeo / 10; + tv.tv_usec = (rpc->rc_timeo % 10) * 100000; + + error = psock_setsockopt(&rpc->rc_so, SOL_SOCKET, SO_RCVTIMEO, + (FAR const void *)&tv, sizeof(tv)); + if (error < 0) + { + ferr("ERROR: psock_setsockopt failed: %d\n", error); + goto bad; + } + + /* Some servers require that the client port be a reserved port + * number. We always allocate a reserved port, as this prevents + * filehandle disclosure through UDP port capture. + */ + + do + { + *lport = htons(--port); + error = psock_bind(&rpc->rc_so, (FAR struct sockaddr *)&laddr, addrlen); + if (error < 0) + { + ferr("ERROR: psock_bind failed: %d\n", error); + } + } + while (error == -EADDRINUSE && port >= 512); + + if (error) + { + ferr("ERROR: psock_bind failed: %d\n", error); + goto bad; + } + + /* Protocols that do not require connections could be optionally left + * unconnected. That would allow servers to reply from a port other than + * the NFS_PORT. + */ + + error = psock_connect(&rpc->rc_so, (FAR struct sockaddr *)&raddr, addrlen); + if (error < 0) + { + ferr("ERROR: psock_connect to PMAP port failed: %d", error); + goto bad; + } + + return OK; + +bad: + psock_close(&rpc->rc_so); + return error; +} + +/**************************************************************************** * Name: rpcclnt_send * * Description: @@ -171,26 +294,36 @@ static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch, static int rpcclnt_send(FAR struct rpcclnt *rpc, FAR void *call, int reqlen) { - ssize_t nbytes; + uint32_t mark; int ret = OK; + /* Send the record marking(RM) for stream only */ + + if (rpc->rc_sotype == SOCK_STREAM) + { + mark = txdr_unsigned(0x80000000 | reqlen); + ret = psock_send(&rpc->rc_so, &mark, sizeof(mark), 0); + if (ret < 0) + { + ferr("ERROR: psock_send mark failed: %d\n", ret); + return ret; + } + } + /* Send the call message * * On success, psock_send returns the number of bytes sent; * On failure, it returns a negated errno value. */ - nbytes = psock_send(&rpc->rc_so, call, reqlen, 0); - - if (nbytes < 0) + ret = psock_send(&rpc->rc_so, call, reqlen, 0); + if (ret < 0) { - /* psock_sendto failed */ - - ret = nbytes; - ferr("ERROR: psock_sendto failed: %d\n", ret); + ferr("ERROR: psock_send request failed: %d\n", ret); + return ret; } - return ret; + return OK; } /**************************************************************************** @@ -204,17 +337,45 @@ static int rpcclnt_send(FAR struct rpcclnt *rpc, static int rpcclnt_receive(FAR struct rpcclnt *rpc, FAR void *reply, size_t resplen) { - ssize_t nbytes; + uint32_t mark; int error = 0; - nbytes = psock_recv(&rpc->rc_so, reply, resplen, 0); - if (nbytes < 0) + /* Receive the record marking(RM) for stream only */ + + if (rpc->rc_sotype == SOCK_STREAM) + { + error = psock_recv(&rpc->rc_so, &mark, sizeof(mark), 0); + if (error < 0) + { + ferr("ERROR: psock_recv mark failed: %d\n", error); + return error; + } + + /* Limit the receive length to the marked value */ + + mark = fxdr_unsigned(uint32_t, mark); + if (!(mark & 0x80000000)) + { + return -ENOSYS; + } + + mark &= 0x7fffffff; + if (mark > resplen) + { + return -E2BIG; + } + + resplen = mark; + } + + error = psock_recv(&rpc->rc_so, reply, resplen, 0); + if (error < 0) { - error = nbytes; - ferr("ERROR: psock_recv failed: %d\n", error); + ferr("ERROR: psock_recv response failed: %d\n", error); + return error; } - return error; + return OK; } /**************************************************************************** @@ -225,11 +386,12 @@ static int rpcclnt_receive(FAR struct rpcclnt *rpc, * ****************************************************************************/ -static int rpcclnt_reply(FAR struct rpcclnt *rpc, +static int rpcclnt_reply(FAR struct rpcclnt *rpc, uint32_t xid, FAR void *reply, size_t resplen) { int error; +retry: /* Get the next RPC reply from the socket */ error = rpcclnt_receive(rpc, reply, resplen); @@ -251,43 +413,15 @@ static int rpcclnt_reply(FAR struct rpcclnt *rpc, rpc_statistics(rpcinvalid); error = -EPROTO; } - } - - return error; -} - -/**************************************************************************** - * Name: rpcclnt_newxid - * - * Description: - * Get a new (non-zero) xid - * - ****************************************************************************/ - -static uint32_t rpcclnt_newxid(void) -{ - static uint32_t rpcclnt_xid = 0; - static uint32_t rpcclnt_xid_touched = 0; - - if ((rpcclnt_xid == 0) && (rpcclnt_xid_touched == 0)) - { - srand(time(NULL)); - rpcclnt_xid = rand(); - rpcclnt_xid_touched = 1; - } - else - { - int xidp = 0; - do + else if (replyheader->rp_xid != txdr_unsigned(xid)) { - xidp = rand(); + ferr("ERROR: Different RPC XID returned\n"); + rpc_statistics(rpcinvalid); + goto retry; } - while ((xidp % 256) == 0); - - rpcclnt_xid += xidp; } - return rpcclnt_xid; + return error; } /**************************************************************************** @@ -357,9 +491,7 @@ void rpcclnt_init(void) int rpcclnt_connect(FAR struct rpcclnt *rpc) { int error; - FAR struct sockaddr *saddr; - struct sockaddr_in sin; - FAR struct sockaddr_in *sa; + int prot; union { @@ -373,76 +505,18 @@ int rpcclnt_connect(FAR struct rpcclnt *rpc) struct rpc_reply_mount mdata; } response; - struct timeval tv; - uint16_t tport; - finfo("Connecting\n"); /* Create the socket */ - saddr = rpc->rc_name; - - error = psock_socket(saddr->sa_family, rpc->rc_sotype, IPPROTO_UDP, &rpc->rc_so); + error = rpcclnt_socket(rpc, 0); if (error < 0) { - ferr("ERROR: psock_socket failed: %d", error); + ferr("ERROR: rpcclnt_socket failed: %d", error); return error; } - /* Always set receive timeout to detect server crash and reconnect. - * Otherwise, we can get stuck in psock_receive forever. - */ - - tv.tv_sec = rpc->rc_timeo / 10; - tv.tv_usec = (rpc->rc_timeo % 10) * 100000; - - error = psock_setsockopt(&rpc->rc_so, SOL_SOCKET, SO_RCVTIMEO, - (FAR const void *)&tv, sizeof(tv)); - if (error < 0) - { - ferr("ERROR: psock_setsockopt failed: %d\n", error); - goto bad; - } - - /* Some servers require that the client port be a reserved port - * number. We always allocate a reserved port, as this prevents - * filehandle disclosure through UDP port capture. - */ - - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; - tport = 1024; - - do - { - tport--; - sin.sin_port = htons(tport); - - error = psock_bind(&rpc->rc_so, (struct sockaddr *)&sin, sizeof(sin)); - if (error < 0) - { - ferr("ERROR: psock_bind failed: %d\n", error); - } - } - while (error == -EADDRINUSE && tport > 1024 / 2); - - if (error) - { - ferr("ERROR: psock_bind failed: %d\n", error); - goto bad; - } - - /* Protocols that do not require connections could be optionally left - * unconnected. That would allow servers to reply from a port other than - * the NFS_PORT. - */ - - error = psock_connect(&rpc->rc_so, saddr, sizeof(*saddr)); - if (error < 0) - { - ferr("ERROR: psock_connect to PMAP port failed: %d", error); - goto bad; - } + prot = rpc->rc_sotype == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP; /* Do the RPC to get a dynamic bounding with the server using ppmap. * Get port number for MOUNTD. @@ -450,7 +524,7 @@ int rpcclnt_connect(FAR struct rpcclnt *rpc) request.sdata.pmap.prog = txdr_unsigned(RPCPROG_MNT); request.sdata.pmap.vers = txdr_unsigned(RPCMNT_VER3); - request.sdata.pmap.prot = txdr_unsigned(IPPROTO_UDP); + request.sdata.pmap.prot = txdr_unsigned(prot); request.sdata.pmap.port = 0; error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, @@ -462,20 +536,17 @@ int rpcclnt_connect(FAR struct rpcclnt *rpc) goto bad; } - sa = (FAR struct sockaddr_in *)saddr; - sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port)); - - error = psock_connect(&rpc->rc_so, saddr, sizeof(*saddr)); + error = rpcclnt_socket(rpc, fxdr_unsigned(uint32_t, response.rdata.pmap.port)); if (error < 0) { - ferr("ERROR: psock_connect MOUNTD port failed: %d\n", error); + ferr("ERROR: rpcclnt_socket MOUNTD port failed: %d\n", error); goto bad; } /* Do RPC to mountd. */ strncpy(request.mountd.mount.rpath, rpc->rc_path, 90); - request.mountd.mount.len = txdr_unsigned(sizeof(request.mountd.mount.rpath)); + request.mountd.mount.len = txdr_unsigned(sizeof(request.mountd.mount.rpath)); error = rpcclnt_request(rpc, RPCMNT_MOUNT, RPCPROG_MNT, RPCMNT_VER3, (FAR void *)&request.mountd, @@ -488,7 +559,7 @@ int rpcclnt_connect(FAR struct rpcclnt *rpc) goto bad; } - error = fxdr_unsigned(uint32_t, response.mdata.mount.status); + error = -fxdr_unsigned(uint32_t, response.mdata.mount.status); if (error != 0) { ferr("ERROR: Bad mount status: %d\n", error); @@ -502,18 +573,16 @@ int rpcclnt_connect(FAR struct rpcclnt *rpc) * NFS port in the socket. */ - sa->sin_port = htons(PMAPPORT); - - error = psock_connect(&rpc->rc_so, saddr, sizeof(*saddr)); + error = rpcclnt_socket(rpc, 0); if (error < 0) { - ferr("ERROR: psock_connect PMAP port failed: %d\n", error); + ferr("ERROR: rpcclnt_socket PMAP port failed: %d\n", error); goto bad; } request.sdata.pmap.prog = txdr_unsigned(NFS_PROG); request.sdata.pmap.vers = txdr_unsigned(NFS_VER3); - request.sdata.pmap.prot = txdr_unsigned(IPPROTO_UDP); + request.sdata.pmap.prot = txdr_unsigned(prot); request.sdata.pmap.port = 0; error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, @@ -527,19 +596,17 @@ int rpcclnt_connect(FAR struct rpcclnt *rpc) goto bad; } - sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port)); - - error = psock_connect(&rpc->rc_so, saddr, sizeof(*saddr)); + error = rpcclnt_socket(rpc, fxdr_unsigned(uint32_t, response.rdata.pmap.port)); if (error < 0) { - ferr("ERROR: psock_connect NFS port returns %d\n", error); + ferr("ERROR: rpcclnt_socket NFS port returns %d\n", error); goto bad; } return OK; bad: - rpcclnt_disconnect(rpc); + psock_close(&rpc->rc_so); return error; } @@ -553,22 +620,6 @@ bad: void rpcclnt_disconnect(FAR struct rpcclnt *rpc) { - psock_close(&rpc->rc_so); -} - -/**************************************************************************** - * Name: rpcclnt_umount - * - * Description: - * Un-mount the NFS file system. - * - ****************************************************************************/ - -int rpcclnt_umount(FAR struct rpcclnt *rpc) -{ - FAR struct sockaddr *saddr; - FAR struct sockaddr_in *sa; - union { struct rpc_call_pmap sdata; @@ -582,27 +633,20 @@ int rpcclnt_umount(FAR struct rpcclnt *rpc) } response; int error; + int prot; - saddr = rpc->rc_name; - sa = (FAR struct sockaddr_in *)saddr; - - /* Do the RPC to get a dynamic bounding with the server using ppmap. - * Get port number for MOUNTD. - */ - - sa->sin_port = htons(PMAPPORT); - - error = psock_connect(&rpc->rc_so, saddr, sizeof(*saddr)); + error = rpcclnt_socket(rpc, 0); if (error < 0) { - ferr("ERROR: psock_connect failed [port=%d]: %d\n", - ntohs(sa->sin_port), error); + ferr("ERROR: rpcclnt_socket failed: %d\n", error); goto bad; } + prot = rpc->rc_sotype == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP; + request.sdata.pmap.prog = txdr_unsigned(RPCPROG_MNT); request.sdata.pmap.vers = txdr_unsigned(RPCMNT_VER3); - request.sdata.pmap.prot = txdr_unsigned(IPPROTO_UDP); + request.sdata.pmap.prot = txdr_unsigned(prot); request.sdata.pmap.port = 0; error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, @@ -616,20 +660,17 @@ int rpcclnt_umount(FAR struct rpcclnt *rpc) goto bad; } - sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port)); - - error = psock_connect(&rpc->rc_so, saddr, sizeof(*saddr)); + error = rpcclnt_socket(rpc, fxdr_unsigned(uint32_t, response.rdata.pmap.port)); if (error < 0) { - ferr("ERROR: psock_connect failed [port=%d]: %d\n", - ntohs(sa->sin_port), error); + ferr("ERROR: rpcclnt_socket failed: %d\n", error); goto bad; } /* Do RPC to umountd. */ - strncpy(request.mountd.umount.rpath, rpc->rc_path, 92); - request.mountd.umount.len = txdr_unsigned(sizeof(request.mountd.umount.rpath)); + strncpy(request.mountd.umount.rpath, rpc->rc_path, 90); + request.mountd.umount.len = txdr_unsigned(sizeof(request.mountd.umount.rpath)); error = rpcclnt_request(rpc, RPCMNT_UMOUNT, RPCPROG_MNT, RPCMNT_VER3, (FAR void *)&request.mountd, @@ -642,11 +683,8 @@ int rpcclnt_umount(FAR struct rpcclnt *rpc) goto bad; } - return OK; - bad: - rpcclnt_disconnect(rpc); - return error; + psock_close(&rpc->rc_so); } /**************************************************************************** @@ -676,7 +714,7 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, /* Get a new (non-zero) xid */ - xid = rpcclnt_newxid(); + xid = ++rpc->rc_xid; /* Initialize the RPC header fields */ @@ -712,7 +750,7 @@ int rpcclnt_request(FAR struct rpcclnt *rpc, int procnum, int prog, else { - error = rpcclnt_reply(rpc, response, resplen); + error = rpcclnt_reply(rpc, xid, response, resplen); if (error != OK) { finfo("ERROR rpcclnt_reply failed: %d\n", error); diff --git a/include/nuttx/net/netconfig.h b/include/nuttx/net/netconfig.h index 7ed1dbd..ae5a9c2 100644 --- a/include/nuttx/net/netconfig.h +++ b/include/nuttx/net/netconfig.h @@ -54,6 +54,7 @@ #include <stdint.h> #include <nuttx/config.h> +#include <nuttx/net/ethernet.h> /**************************************************************************** * Public Definitions