diff options
Diffstat (limited to 'nuttx/fs/nfs/rpc_clnt.c')
-rw-r--r-- | nuttx/fs/nfs/rpc_clnt.c | 805 |
1 files changed, 0 insertions, 805 deletions
diff --git a/nuttx/fs/nfs/rpc_clnt.c b/nuttx/fs/nfs/rpc_clnt.c deleted file mode 100644 index 9c2ada4f2..000000000 --- a/nuttx/fs/nfs/rpc_clnt.c +++ /dev/null @@ -1,805 +0,0 @@ -/**************************************************************************** - * fs/nfs/rpc_clnt.c - * - * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved. - * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. - * Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com> - * Gregory Nutt <gnutt@nuttx.org> - * - * Leveraged from OpenBSD: - * - * Copyright (c) 2004 The Regents of the University of Michigan. - * All rights reserved. - * - * Copyright (c) 2004 Weston Andros Adamson <muzzle@umich.edu>. - * Copyright (c) 2004 Marius Aamodt Eriksen <marius@umich.edu>. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Copyright (c) 1989, 1991, 1993, 1995 The Regents of the University of - * California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by Rick Macklem at - * The University of Guelph. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. 3. All advertising - * materials mentioning features or use of this software must display the - * following acknowledgement: This product includes software developed by the - * University of California, Berkeley and its contributors. 4. Neither the - * name of the University nor the names of its contributors may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include <sys/socket.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> -#include <nuttx/kmalloc.h> - -#include "xdr_subs.h" -#include "nfs_proto.h" -#include "rpc.h" - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* Increment RPC statistics */ - -#ifdef CONFIG_NFS_STATISTICS -# define rpc_statistics(n) do { rpcstats.(n)++; } while (0) -#else -# define rpc_statistics(n) -#endif - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -/* Static data, mostly RPC constants in XDR form */ - -static uint32_t rpc_reply; -static uint32_t rpc_call; -static uint32_t rpc_vers; -static uint32_t rpc_msgdenied; -static uint32_t rpc_mismatch; -static uint32_t rpc_auth_unix; -static uint32_t rpc_msgaccepted; -static uint32_t rpc_autherr; -static uint32_t rpc_auth_null; - -/* Global statics for all client instances. Cleared by NuttX on boot-up. */ - -#ifdef CONFIG_NFS_STATISTICS -static struct rpcstats rpcstats; -#endif - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog, - FAR void *call, int reqlen); -static int rpcclnt_receive(FAR struct rpcclnt *rpc, struct sockaddr *aname, - int proc, int program, void *reply, size_t resplen); -static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog, - 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); - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: rpcclnt_send - * - * Description: - * This is the nfs send routine. - * - * Returned Value: - * Returns zero on success or a (positive) errno value on failure. - * - ****************************************************************************/ - -static int rpcclnt_send(FAR struct rpcclnt *rpc, int procid, int prog, - FAR void *call, int reqlen) -{ - ssize_t nbytes; - int error = OK; - - /* Send the call message - * - * On success, psock_sendto returns the number of bytes sent; - * On failure, it returns -1 with the specific error in errno. - */ - - nbytes = psock_sendto(rpc->rc_so, call, reqlen, 0, - rpc->rc_name, sizeof(struct sockaddr)); - if (nbytes < 0) - { - /* psock_sendto failed */ - - error = errno; - fdbg("ERROR: psock_sendto failed: %d\n", error); - } - - return error; -} - -/**************************************************************************** - * Name: rpcclnt_receive - * - * Description: - * Receive a Sun RPC Request/Reply. For SOCK_DGRAM, the work is all done - * by psock_recvfrom(). - * - ****************************************************************************/ - -static int rpcclnt_receive(FAR struct rpcclnt *rpc, FAR struct sockaddr *aname, - int proc, int program, FAR void *reply, - size_t resplen) -{ - ssize_t nbytes; - int error = 0; - - socklen_t fromlen = sizeof(struct sockaddr); - nbytes = psock_recvfrom(rpc->rc_so, reply, resplen, 0, aname, &fromlen); - if (nbytes < 0) - { - error = errno; - fdbg("ERROR: psock_recvfrom failed: %d\n", error); - } - - return error; -} - -/**************************************************************************** - * Name: rpcclnt_reply - * - * Description: - * Received the RPC reply on the socket. - * - ****************************************************************************/ - -static int rpcclnt_reply(FAR struct rpcclnt *rpc, int procid, int prog, - FAR void *reply, size_t resplen) -{ - int error; - - /* Get the next RPC reply from the socket */ - - error = rpcclnt_receive(rpc, rpc->rc_name, procid, prog, reply, resplen); - if (error != 0) - { - fdbg("ERROR: rpcclnt_receive returned: %d\n", error); - - /* If we failed because of a timeout, then try sending the CALL - * message again. - */ - - if (error == EAGAIN || error == ETIMEDOUT) - { - rpc->rc_timeout = true; - } - } - - /* Get the xid and check that it is an RPC replysvr */ - - else - { - FAR struct rpc_reply_header *replyheader = - (FAR struct rpc_reply_header *)reply; - - if (replyheader->rp_direction != rpc_reply) - { - fdbg("ERROR: Different RPC REPLY returned\n"); - 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; - - srand(time(NULL)); - if ((rpcclnt_xid == 0) && (rpcclnt_xid_touched == 0)) - { - rpcclnt_xid = rand(); - rpcclnt_xid_touched = 1; - } - else - { - int xidp = 0; - do - { - xidp = rand(); - } - while ((xidp % 256) == 0); - - rpcclnt_xid += xidp; - } - - return rpcclnt_xid; -} - -/**************************************************************************** - * Name: rpcclnt_fmtheader - * - * Description: - * Format the common part of the call header - * - ****************************************************************************/ - -static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch, - uint32_t xid, int prog, int vers, int procid) -{ - /* Format the call header */ - - ch->rp_xid = txdr_unsigned(xid); - ch->rp_direction = rpc_call; - ch->rp_rpcvers = rpc_vers; - ch->rp_prog = txdr_unsigned(prog); - ch->rp_vers = txdr_unsigned(vers); - ch->rp_proc = txdr_unsigned(procid); - - /* rpc_auth part (auth_null) */ - - ch->rpc_auth.authtype = rpc_auth_null; - ch->rpc_auth.authlen = 0; - - /* rpc_verf part (auth_null) */ - - ch->rpc_verf.authtype = rpc_auth_null; - ch->rpc_verf.authlen = 0; -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: rpcclnt_init - * - * Description: - * Initialize the RPC client - * - ****************************************************************************/ - -void rpcclnt_init(void) -{ - /* RPC constants how about actually using more than one of these! */ - - rpc_reply = txdr_unsigned(RPC_REPLY); - rpc_vers = txdr_unsigned(RPC_VER2); - rpc_call = txdr_unsigned(RPC_CALL); - rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED); - rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED); - rpc_mismatch = txdr_unsigned(RPC_MISMATCH); - rpc_autherr = txdr_unsigned(RPC_AUTHERR); - rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX); - rpc_auth_null = txdr_unsigned(RPCAUTH_NULL); - - fvdbg("RPC initialized\n"); -} - -/**************************************************************************** - * Name: rpcclnt_connect - * - * Description: - * Initialize sockets for a new RPC connection. We do not free the - * sockaddr if an error occurs. - * - ****************************************************************************/ - -int rpcclnt_connect(struct rpcclnt *rpc) -{ - struct socket *so; - int error; - struct sockaddr *saddr; - struct sockaddr_in sin; - struct sockaddr_in *sa; - - union - { - struct rpc_call_pmap sdata; - struct rpc_call_mount mountd; - } request; - - union - { - struct rpc_reply_pmap rdata; - struct rpc_reply_mount mdata; - } response; - - struct timeval tv; - uint16_t tport; - int errval; - - fvdbg("Connecting\n"); - - /* Create the socket */ - - saddr = rpc->rc_name; - - /* Create an instance of the socket state structure */ - - so = (struct socket *)kzalloc(sizeof(struct socket)); - if (!so) - { - fdbg("ERROR: Failed to allocate socket structure\n"); - return ENOMEM; - } - - error = psock_socket(saddr->sa_family, rpc->rc_sotype, IPPROTO_UDP, so); - if (error < 0) - { - errval = errno; - fdbg("ERROR: psock_socket failed: %d", errval); - return error; - } - - so->s_crefs = 1; - rpc->rc_so = so; - - /* Always set receive timeout to detect server crash and reconnect. - * Otherwise, we can get stuck in psock_receive forever. - */ - - tv.tv_sec = 1; - tv.tv_usec = 0; - - error = psock_setsockopt(rpc->rc_so, SOL_SOCKET, SO_RCVTIMEO, - (const void *)&tv, sizeof(tv)); - if (error < 0) - { - errval = errno; - fdbg("ERROR: psock_setsockopt failed: %d\n", errval); - 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; - - errval = 0; - do - { - tport--; - sin.sin_port = htons(tport); - error = psock_bind(rpc->rc_so, (struct sockaddr *)&sin, sizeof(sin)); - if (error < 0) - { - errval = errno; - fdbg("ERROR: psock_bind failed: %d\n", errval); - } - } - while (errval == EADDRINUSE && tport > 1024 / 2); - - if (error) - { - fdbg("ERROR: psock_bind failed: %d\n", errval); - goto bad; - } - - /* Protocols that do not require connections may be optionally left - * unconnected for servers that reply from a port other than - * NFS_PORT. - */ - - error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr)); - if (error < 0) - { - errval = errno; - fdbg("ERROR: psock_connect to PMAP port failed: %d", errval); - goto bad; - } - - /* Do the RPC to get a dynamic bounding with the server using ppmap. - * Get port number for MOUNTD. - */ - - request.sdata.pmap.prog = txdr_unsigned(RPCPROG_MNT); - request.sdata.pmap.vers = txdr_unsigned(RPCMNT_VER1); - request.sdata.pmap.proc = txdr_unsigned(IPPROTO_UDP); - request.sdata.pmap.port = 0; - - error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, - (FAR void *)&request.sdata, sizeof(struct call_args_pmap), - (FAR void *)&response.rdata, sizeof(struct rpc_reply_pmap)); - if (error != 0) - { - fdbg("ERROR: rpcclnt_request failed: %d\n", error); - 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)); - if (error < 0) - { - errval = errno; - fdbg("ERROR: psock_connect MOUNTD port failed: %d\n", errval); - 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)); - - error = rpcclnt_request(rpc, RPCMNT_MOUNT, RPCPROG_MNT, RPCMNT_VER1, - (FAR void *)&request.mountd, sizeof(struct call_args_mount), - (FAR void *)&response.mdata, sizeof(struct rpc_reply_mount)); - if (error != 0) - { - fdbg("ERROR: rpcclnt_request failed: %d\n", error); - goto bad; - } - - error = fxdr_unsigned(uint32_t, response.mdata.mount.status); - if (error != 0) - { - fdbg("ERROR: Bad mount status: %d\n", error); - goto bad; - } - - memcpy(&rpc->rc_fh, &response.mdata.mount.fhandle, sizeof(nfsfh_t)); - - /* Do the RPC to get a dynamic bounding with the server using PMAP. - * NFS port in the socket. - */ - - sa->sin_port = htons(PMAPPORT); - - error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr)); - if (error < 0) - { - errval = errno; - fdbg("ERROR: psock_connect PMAP port failed: %d\n", errval); - goto bad; - } - - request.sdata.pmap.prog = txdr_unsigned(NFS_PROG); - request.sdata.pmap.vers = txdr_unsigned(NFS_VER3); - request.sdata.pmap.proc = txdr_unsigned(IPPROTO_UDP); - request.sdata.pmap.port = 0; - - error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, - (FAR void *)&request.sdata, sizeof(struct call_args_pmap), - (FAR void *)&response.rdata, sizeof(struct rpc_reply_pmap)); - if (error != 0) - { - fdbg("ERROR: rpcclnt_request failed: %d\n", error); - goto bad; - } - - sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port)); - - error = psock_connect(rpc->rc_so, saddr, sizeof(*saddr)); - if (error) - { - fdbg("psock_connect NFS port returns %d\n", error); - goto bad; - } - - return OK; - -bad: - rpcclnt_disconnect(rpc); - return error; -} - -/**************************************************************************** - * Name: rpcclnt_disconnect - * - * Description: - * Disconnect from the NFS server. - * - ****************************************************************************/ - -void rpcclnt_disconnect(struct rpcclnt *rpc) -{ - if (rpc->rc_so != NULL) - { - (void)psock_close(rpc->rc_so); - } -} - -/**************************************************************************** - * Name: rpcclnt_umount - * - * Description: - * Un-mount the NFS file system. - * - ****************************************************************************/ - -int rpcclnt_umount(struct rpcclnt *rpc) -{ - struct sockaddr *saddr; - struct sockaddr_in *sa; - - union - { - struct rpc_call_pmap sdata; - struct rpc_call_umount mountd; - } request; - - union - { - struct rpc_reply_pmap rdata; - struct rpc_reply_umount mdata; - } response; - - int error; - int ret; - - 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); - - ret = psock_connect(rpc->rc_so, saddr, sizeof(*saddr)); - if (ret < 0) - { - error = errno; - fdbg("ERROR: psock_connect failed [port=%d]: %d\n", - ntohs(sa->sin_port), error); - goto bad; - } - - request.sdata.pmap.prog = txdr_unsigned(RPCPROG_MNT); - request.sdata.pmap.vers = txdr_unsigned(RPCMNT_VER1); - request.sdata.pmap.proc = txdr_unsigned(IPPROTO_UDP); - request.sdata.pmap.port = 0; - - error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, - (FAR void *)&request.sdata, sizeof(struct call_args_pmap), - (FAR void *)&response.rdata, sizeof(struct rpc_reply_pmap)); - if (error != 0) - { - fdbg("ERROR: rpcclnt_request failed: %d\n", error); - goto bad; - } - - sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port)); - - ret = psock_connect(rpc->rc_so, saddr, sizeof(*saddr)); - if (ret < 0) - { - error = errno; - fdbg("ERROR: psock_connect failed [port=%d]: %d\n", - ntohs(sa->sin_port), 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)); - - error = rpcclnt_request(rpc, RPCMNT_UMOUNT, RPCPROG_MNT, RPCMNT_VER1, - (FAR void *)&request.mountd, sizeof(struct call_args_umount), - (FAR void *)&response.mdata, sizeof(struct rpc_reply_umount)); - if (error != 0) - { - fdbg("ERROR: rpcclnt_request failed: %d\n", error); - goto bad; - } - - return OK; - -bad: - rpcclnt_disconnect(rpc); - return error; -} - -/**************************************************************************** - * Name: rpcclnt_request - * - * Description: - * Perform the RPC request. Logic formats the RPC CALL message and calls - * rpcclnt_send to send the RPC CALL message. It then calls rpcclnt_reply() - * to get the response. It may attempt to re-send the CALL message on - * certain errors. - * - * On successful receipt, it verifies the RPC level of the returned values. - * (There may still be be NFS layer errors that will be deted by calling - * logic). - * - ****************************************************************************/ - -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) -{ - struct rpc_reply_header *replymsg; - uint32_t tmp; - uint32_t xid; - int retries; - int error = 0; - - /* Get a new (non-zero) xid */ - - xid = rpcclnt_newxid(); - - /* Initialize the RPC header fields */ - - rpcclnt_fmtheader((FAR struct rpc_call_header *)request, - xid, prog, version, procnum); - - /* Get the full size of the message (the size of variable data plus the size of - * the messages header). - */ - - reqlen += sizeof(struct rpc_call_header); - - /* Send the RPC call messsages and receive the RPC response. A limited - * number of re-tries will be attempted, but only for the case of response - * timeouts. - */ - - retries = 0; - do - { - /* Do the client side RPC. */ - - rpc_statistics(rpcrequests); - rpc->rc_timeout = false; - - /* Send the RPC CALL message */ - - error = rpcclnt_send(rpc, procnum, prog, request, reqlen); - if (error != OK) - { - fvdbg("ERROR rpcclnt_send failed: %d\n", error); - } - - /* Wait for the reply from our send */ - - else - { - error = rpcclnt_reply(rpc, procnum, prog, response, resplen); - if (error != OK) - { - fvdbg("ERROR rpcclnt_reply failed: %d\n", error); - } - } - - retries++; - } - while (rpc->rc_timeout && retries <= rpc->rc_retry); - - if (error != OK) - { - fdbg("ERROR: RPC failed: %d\n", error); - return error; - } - - /* Break down the RPC header and check if it is OK */ - - replymsg = (FAR struct rpc_reply_header *)response; - - tmp = fxdr_unsigned(uint32_t, replymsg->type); - if (tmp == RPC_MSGDENIED) - { - tmp = fxdr_unsigned(uint32_t, replymsg->status); - switch (tmp) - { - case RPC_MISMATCH: - fdbg("RPC_MSGDENIED: RPC_MISMATCH error\n"); - return EOPNOTSUPP; - - case RPC_AUTHERR: - fdbg("RPC_MSGDENIED: RPC_AUTHERR error\n"); - return EACCES; - - default: - return EOPNOTSUPP; - } - } - else if (tmp != RPC_MSGACCEPTED) - { - return EOPNOTSUPP; - } - - tmp = fxdr_unsigned(uint32_t, replymsg->status); - if (tmp == RPC_SUCCESS) - { - fvdbg("RPC_SUCCESS\n"); - } - else if (tmp == RPC_PROGMISMATCH) - { - fdbg("RPC_MSGACCEPTED: RPC_PROGMISMATCH error\n"); - return EOPNOTSUPP; - } - else if (tmp > 5) - { - fdbg("ERROR: Other RPC type: %d\n", tmp); - return EOPNOTSUPP; - } - - return OK; -} |