2012-03-22 01:51:01 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* fs/nfs/nfs_socket.c
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
|
|
|
* Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
|
|
|
|
* Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
|
|
|
|
*
|
|
|
|
* Leveraged from OpenBSD:
|
|
|
|
*
|
|
|
|
* copyright (c) 2004
|
|
|
|
* the regents of the university of michigan
|
|
|
|
* all rights reserved
|
2012-05-08 01:33:39 +02:00
|
|
|
*
|
2012-03-17 01:25:34 +01:00
|
|
|
* permission is granted to use, copy, create derivative works and redistribute
|
|
|
|
* this software and such derivative works for any purpose, so long as the name
|
|
|
|
* of the university of michigan is not used in any advertising or publicity
|
|
|
|
* pertaining to the use or distribution of this software without specific,
|
|
|
|
* written prior authorization. if the above copyright notice or any other
|
|
|
|
* identification of the university of michigan is included in any copy of any
|
|
|
|
* portion of this software, then the disclaimer below must also be included.
|
2012-05-08 01:33:39 +02:00
|
|
|
*
|
2012-03-17 01:25:34 +01:00
|
|
|
* this software is provided as is, without representation from the university
|
|
|
|
* of michigan as to its fitness for any purpose, and without warranty by the
|
|
|
|
* university of michigan of any kind, either express or implied, including
|
|
|
|
* without limitation the implied warranties of merchantability and fitness for
|
|
|
|
* a particular purpose. the regents of the university of michigan shall not be
|
|
|
|
* liable for any damages, including special, indirect, incidental, or
|
|
|
|
* consequential damages, with respect to any claim arising out of or in
|
|
|
|
* connection with the use of the software, even if it has been or is hereafter
|
|
|
|
* advised of the possibility of such damages.
|
2012-03-22 01:51:01 +01:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
2012-03-17 01:25:34 +01:00
|
|
|
|
2012-03-22 01:51:01 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* Included Files
|
|
|
|
****************************************************************************/
|
2012-03-17 01:25:34 +01:00
|
|
|
|
|
|
|
#include <sys/socket.h>
|
2012-03-22 01:51:01 +01:00
|
|
|
#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>
|
2012-05-01 01:51:23 +02:00
|
|
|
#include <nuttx/kmalloc.h>
|
2012-03-22 01:51:01 +01:00
|
|
|
|
2012-05-29 01:40:20 +02:00
|
|
|
#include "nfs_proto.h"
|
|
|
|
#include "nfs_mount.h"
|
2012-04-23 22:33:25 +02:00
|
|
|
#include "nfs.h"
|
2012-03-22 01:51:01 +01:00
|
|
|
#include "rpc.h"
|
2012-03-17 01:25:34 +01:00
|
|
|
#include "xdr_subs.h"
|
|
|
|
#include "nfs_socket.h"
|
|
|
|
|
2012-03-22 01:51:01 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* Pre-processor Definitions
|
|
|
|
****************************************************************************/
|
|
|
|
|
2012-03-17 01:25:34 +01:00
|
|
|
/* Flag translations */
|
2012-03-22 01:51:01 +01:00
|
|
|
|
2012-04-14 02:27:44 +02:00
|
|
|
#define nfsmnt_to_rpcclnt(nf, rf, name) do \
|
|
|
|
{ \
|
|
|
|
if (nf & NFSMNT_##name) \
|
|
|
|
{ \
|
|
|
|
rf |= RPCCLNT_##name; \
|
|
|
|
} \
|
|
|
|
} while(0)
|
2012-03-17 01:25:34 +01:00
|
|
|
|
2012-03-22 01:51:01 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* Private Variables
|
|
|
|
****************************************************************************/
|
2012-03-17 01:25:34 +01:00
|
|
|
|
|
|
|
static struct rpc_program nfs3_program =
|
|
|
|
{
|
|
|
|
NFS_PROG, NFS_VER3, "NFSv3"
|
|
|
|
};
|
|
|
|
|
2012-03-22 01:51:01 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* Public Variables
|
|
|
|
****************************************************************************/
|
|
|
|
|
2012-04-21 01:15:41 +02:00
|
|
|
uint32_t nfs_true;
|
|
|
|
uint32_t nfs_false;
|
|
|
|
uint32_t nfs_xdrneg1;
|
2012-03-28 02:10:43 +02:00
|
|
|
int nfs_ticks;
|
2012-04-21 01:15:41 +02:00
|
|
|
struct nfsstats nfsstats;
|
2012-03-22 01:51:01 +01:00
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Public Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
void nfs_init(void)
|
2012-03-17 01:25:34 +01:00
|
|
|
{
|
2012-04-21 01:15:41 +02:00
|
|
|
nfs_true = txdr_unsigned(TRUE);
|
|
|
|
nfs_false = txdr_unsigned(FALSE);
|
|
|
|
nfs_xdrneg1 = txdr_unsigned(-1);
|
|
|
|
|
|
|
|
nfs_ticks = (CLOCKS_PER_SEC * NFS_TICKINTVL + 500) / 1000;
|
|
|
|
if (nfs_ticks < 1)
|
|
|
|
{
|
|
|
|
nfs_ticks = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rpcclnt_init();
|
2012-03-22 01:51:01 +01:00
|
|
|
}
|
2012-03-17 01:25:34 +01:00
|
|
|
|
2012-04-21 01:15:41 +02:00
|
|
|
int nfs_connect(struct nfsmount *nmp)
|
2012-03-17 01:25:34 +01:00
|
|
|
{
|
2012-05-01 01:51:23 +02:00
|
|
|
struct rpcclnt *rpc;
|
2012-03-17 01:25:34 +01:00
|
|
|
|
|
|
|
if (nmp == NULL)
|
2012-04-14 02:27:44 +02:00
|
|
|
{
|
|
|
|
return EFAULT;
|
|
|
|
}
|
2012-03-17 01:25:34 +01:00
|
|
|
|
2012-05-01 01:51:23 +02:00
|
|
|
/* Create an instance of the rpc state structure */
|
2012-03-17 01:25:34 +01:00
|
|
|
|
2012-05-01 01:51:23 +02:00
|
|
|
rpc = (struct rpcclnt *)kzalloc(sizeof(struct rpcclnt));
|
|
|
|
if (!rpc)
|
|
|
|
{
|
2012-06-07 03:03:34 +02:00
|
|
|
fdbg("ERROR: Failed to allocate rpc structure\n");
|
2012-05-01 01:51:23 +02:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
rpc->rc_prog = &nfs3_program;
|
2012-03-17 01:25:34 +01:00
|
|
|
|
2012-06-07 03:03:34 +02:00
|
|
|
fvdbg("Connecting\n");
|
2012-03-17 01:25:34 +01:00
|
|
|
|
|
|
|
/* translate nfsmnt flags -> rpcclnt flags */
|
2012-04-14 02:27:44 +02:00
|
|
|
|
2012-05-01 01:51:23 +02:00
|
|
|
rpc->rc_flag = 0;
|
|
|
|
nfsmnt_to_rpcclnt(nmp->nm_flag, rpc->rc_flag, SOFT);
|
|
|
|
nfsmnt_to_rpcclnt(nmp->nm_flag, rpc->rc_flag, INT);
|
|
|
|
nfsmnt_to_rpcclnt(nmp->nm_flag, rpc->rc_flag, NOCONN);
|
|
|
|
nfsmnt_to_rpcclnt(nmp->nm_flag, rpc->rc_flag, DUMBTIMR);
|
2012-03-17 01:25:34 +01:00
|
|
|
|
2012-05-18 03:11:57 +02:00
|
|
|
//rpc->rc_flag |= RPCCLNT_REDIRECT; /* Make this a mount option. */
|
2012-03-17 01:25:34 +01:00
|
|
|
|
2012-05-18 03:11:57 +02:00
|
|
|
//rpc->rc_authtype = RPCAUTH_NULL; /* for now */
|
2012-05-12 02:11:24 +02:00
|
|
|
rpc->rc_path = nmp->nm_path;
|
2012-05-06 01:17:25 +02:00
|
|
|
rpc->rc_name = &nmp->nm_nam;
|
2012-05-23 02:15:53 +02:00
|
|
|
//rpc->rc_fh = nmp->nm_fh;
|
2012-03-17 01:25:34 +01:00
|
|
|
|
2012-05-01 01:51:23 +02:00
|
|
|
rpc->rc_sotype = nmp->nm_sotype;
|
|
|
|
rpc->rc_soproto = nmp->nm_soproto;
|
|
|
|
rpc->rc_rsize = (nmp->nm_rsize > nmp->nm_readdirsize) ?
|
2012-03-17 01:25:34 +01:00
|
|
|
nmp->nm_rsize : nmp->nm_readdirsize;
|
2012-05-01 01:51:23 +02:00
|
|
|
rpc->rc_wsize = nmp->nm_wsize;
|
2012-05-18 03:11:57 +02:00
|
|
|
//rpc->rc_deadthresh = nmp->nm_deadthresh;
|
2012-05-01 01:51:23 +02:00
|
|
|
rpc->rc_timeo = nmp->nm_timeo;
|
|
|
|
rpc->rc_retry = nmp->nm_retry;
|
2012-03-17 01:25:34 +01:00
|
|
|
|
2012-04-26 01:22:09 +02:00
|
|
|
/* v3 need to use this */
|
2012-04-14 02:27:44 +02:00
|
|
|
|
2012-05-01 01:51:23 +02:00
|
|
|
rpc->rc_proctlen = 0;
|
|
|
|
rpc->rc_proct = NULL;
|
2012-05-08 01:33:39 +02:00
|
|
|
|
2012-05-01 01:51:23 +02:00
|
|
|
nmp->nm_rpcclnt = rpc;
|
2012-03-17 01:25:34 +01:00
|
|
|
|
2012-05-01 01:51:23 +02:00
|
|
|
return rpcclnt_connect(rpc);
|
2012-03-17 01:25:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* NFS disconnect. Clean up and unlink. */
|
|
|
|
|
2012-04-21 01:15:41 +02:00
|
|
|
void nfs_disconnect(struct nfsmount *nmp)
|
2012-03-17 01:25:34 +01:00
|
|
|
{
|
2012-04-19 01:31:47 +02:00
|
|
|
rpcclnt_disconnect(nmp->nm_rpcclnt);
|
2012-03-17 01:25:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CONFIG_NFS_TCPIP
|
2012-04-21 01:15:41 +02:00
|
|
|
void nfs_safedisconnect(struct nfsmount *nmp)
|
2012-03-17 01:25:34 +01:00
|
|
|
{
|
2012-04-19 01:31:47 +02:00
|
|
|
rpcclnt_safedisconnect(nmp->nm_rpcclnt);
|
2012-03-17 01:25:34 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-05-18 03:11:57 +02:00
|
|
|
int nfs_request(struct nfsmount *nmp, int procnum, FAR const void *datain,
|
2012-06-07 03:03:34 +02:00
|
|
|
FAR void *dataout, size_t len)
|
2012-03-17 01:25:34 +01:00
|
|
|
{
|
2012-06-07 03:03:34 +02:00
|
|
|
struct rpcclnt *clnt= nmp->nm_rpcclnt;
|
2012-05-18 03:11:57 +02:00
|
|
|
struct rpc_reply_header replyh;
|
2012-03-22 01:51:01 +01:00
|
|
|
int trylater_delay;
|
2012-06-07 03:03:34 +02:00
|
|
|
int error;
|
2012-03-17 01:25:34 +01:00
|
|
|
|
|
|
|
tryagain:
|
|
|
|
|
2012-05-18 03:11:57 +02:00
|
|
|
memset(&replyh, 0, sizeof(struct rpc_reply_header));
|
2012-05-08 01:33:39 +02:00
|
|
|
|
2012-05-12 02:11:24 +02:00
|
|
|
error = rpcclnt_request(clnt, procnum, nmp->nm_rpcclnt->rc_prog->prog_id,
|
2012-05-18 03:11:57 +02:00
|
|
|
nmp->nm_rpcclnt->rc_prog->prog_version, dataout,
|
2012-06-07 03:03:34 +02:00
|
|
|
datain, len);
|
2012-05-12 02:11:24 +02:00
|
|
|
if (error != 0)
|
2012-04-14 02:27:44 +02:00
|
|
|
{
|
2012-06-07 03:03:34 +02:00
|
|
|
fdbg("ERROR: rpcclnt_request failed: %d\n", error);
|
2012-04-14 02:27:44 +02:00
|
|
|
goto out;
|
|
|
|
}
|
2012-03-17 01:25:34 +01:00
|
|
|
|
2012-06-07 03:03:34 +02:00
|
|
|
bcopy(dataout, &replyh, sizeof(struct rpc_reply_header));
|
2012-03-17 01:25:34 +01:00
|
|
|
|
2012-05-18 03:11:57 +02:00
|
|
|
if (replyh.rpc_verfi.authtype != 0)
|
2012-03-17 01:25:34 +01:00
|
|
|
{
|
2012-05-18 03:11:57 +02:00
|
|
|
error = fxdr_unsigned(int, replyh.rpc_verfi.authtype);
|
2012-03-22 01:51:01 +01:00
|
|
|
|
2012-03-17 01:25:34 +01:00
|
|
|
if ((nmp->nm_flag & NFSMNT_NFSV3) && error == NFSERR_TRYLATER)
|
|
|
|
{
|
|
|
|
error = 0;
|
2012-03-22 01:51:01 +01:00
|
|
|
trylater_delay *= NFS_TIMEOUTMUL;
|
|
|
|
if (trylater_delay > NFS_MAXTIMEO)
|
|
|
|
{
|
|
|
|
trylater_delay = NFS_MAXTIMEO;
|
|
|
|
}
|
2012-05-01 01:51:23 +02:00
|
|
|
|
2012-03-17 01:25:34 +01:00
|
|
|
goto tryagain;
|
|
|
|
}
|
|
|
|
|
2012-04-14 02:27:44 +02:00
|
|
|
/* If the File Handle was stale, invalidate the
|
|
|
|
* lookup cache, just in case.
|
|
|
|
*/
|
|
|
|
|
2012-03-17 01:25:34 +01:00
|
|
|
if (error == ESTALE)
|
2012-04-14 02:27:44 +02:00
|
|
|
{
|
2012-06-07 03:03:34 +02:00
|
|
|
fdbg("ERROR %s: ESTALE on mount from server\n",
|
2012-04-23 22:33:25 +02:00
|
|
|
nmp->nm_rpcclnt->rc_prog->prog_name);
|
2012-04-14 02:27:44 +02:00
|
|
|
}
|
2012-03-17 01:25:34 +01:00
|
|
|
else
|
2012-04-14 02:27:44 +02:00
|
|
|
{
|
2012-06-07 03:03:34 +02:00
|
|
|
fdbg("ERROR %s: unknown error %d from server\n",
|
2012-04-23 22:33:25 +02:00
|
|
|
nmp->nm_rpcclnt->rc_prog->prog_name, error);
|
2012-04-14 02:27:44 +02:00
|
|
|
}
|
|
|
|
|
2012-03-17 01:25:34 +01:00
|
|
|
goto out;
|
|
|
|
}
|
2012-05-01 01:51:23 +02:00
|
|
|
|
2012-04-14 02:27:44 +02:00
|
|
|
return 0;
|
2012-05-08 01:33:39 +02:00
|
|
|
|
2012-03-17 01:25:34 +01:00
|
|
|
out:
|
2012-04-14 02:27:44 +02:00
|
|
|
return error;
|
2012-03-17 01:25:34 +01:00
|
|
|
}
|
|
|
|
|
2012-05-18 03:11:57 +02:00
|
|
|
#undef COMP
|
|
|
|
#ifdef COMP
|
|
|
|
|
2012-03-17 01:25:34 +01:00
|
|
|
/* terminate any outstanding RPCs. */
|
|
|
|
|
2012-04-21 01:15:41 +02:00
|
|
|
int nfs_nmcancelreqs(struct nfsmount *nmp)
|
2012-03-17 01:25:34 +01:00
|
|
|
{
|
2012-05-18 03:11:57 +02:00
|
|
|
return 0; //rpcclnt_cancelreqs(nmp->nm_rpcclnt);
|
2012-03-17 01:25:34 +01:00
|
|
|
}
|
2012-06-06 23:51:03 +02:00
|
|
|
#endif
|