1beacf11bSopenharmony_ci/**************************************************************************** 2beacf11bSopenharmony_ci * fs/nfs/rpc_clnt.c 3beacf11bSopenharmony_ci * 4beacf11bSopenharmony_ci * Copyright (C) 2012-2013, 2018 Gregory Nutt. All rights reserved. 5beacf11bSopenharmony_ci * Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved. 6beacf11bSopenharmony_ci * Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com> 7beacf11bSopenharmony_ci * Gregory Nutt <gnutt@nuttx.org> 8beacf11bSopenharmony_ci * 9beacf11bSopenharmony_ci * Leveraged from OpenBSD: 10beacf11bSopenharmony_ci * 11beacf11bSopenharmony_ci * Copyright (c) 2004 The Regents of the University of Michigan. 12beacf11bSopenharmony_ci * All rights reserved. 13beacf11bSopenharmony_ci * 14beacf11bSopenharmony_ci * Copyright (c) 2004 Weston Andros Adamson <muzzle@umich.edu>. 15beacf11bSopenharmony_ci * Copyright (c) 2004 Marius Aamodt Eriksen <marius@umich.edu>. 16beacf11bSopenharmony_ci * All rights reserved. 17beacf11bSopenharmony_ci * 18beacf11bSopenharmony_ci * Redistribution and use in source and binary forms, with or without 19beacf11bSopenharmony_ci * modification, are permitted provided that the following conditions 20beacf11bSopenharmony_ci * are met: 21beacf11bSopenharmony_ci * 22beacf11bSopenharmony_ci * 1. Redistributions of source code must retain the above copyright 23beacf11bSopenharmony_ci * notice, this list of conditions and the following disclaimer. 24beacf11bSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 25beacf11bSopenharmony_ci * notice, this list of conditions and the following disclaimer in the 26beacf11bSopenharmony_ci * documentation and/or other materials provided with the distribution. 27beacf11bSopenharmony_ci * 3. Neither the name of the University nor the names of its 28beacf11bSopenharmony_ci * contributors may be used to endorse or promote products derived 29beacf11bSopenharmony_ci * from this software without specific prior written permission. 30beacf11bSopenharmony_ci * 31beacf11bSopenharmony_ci * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 32beacf11bSopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 33beacf11bSopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 34beacf11bSopenharmony_ci * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 35beacf11bSopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 36beacf11bSopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37beacf11bSopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 38beacf11bSopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 39beacf11bSopenharmony_ci * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 40beacf11bSopenharmony_ci * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 41beacf11bSopenharmony_ci * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42beacf11bSopenharmony_ci * 43beacf11bSopenharmony_ci * Copyright (c) 1989, 1991, 1993, 1995 The Regents of the University of 44beacf11bSopenharmony_ci * California. All rights reserved. 45beacf11bSopenharmony_ci * 46beacf11bSopenharmony_ci * This code is derived from software contributed to Berkeley by Rick Macklem 47beacf11bSopenharmony_ci * at The University of Guelph. 48beacf11bSopenharmony_ci * 49beacf11bSopenharmony_ci * Redistribution and use in source and binary forms, with or without 50beacf11bSopenharmony_ci * modification, are permitted provided that the following conditions are 51beacf11bSopenharmony_ci * met: 1. Redistributions of source code must retain the above copyright 52beacf11bSopenharmony_ci * notice, this list of conditions and the following disclaimer. 2. 53beacf11bSopenharmony_ci * Redistributions in binary form must reproduce the above copyright notice, 54beacf11bSopenharmony_ci * this list of conditions and the following disclaimer in the documentation 55beacf11bSopenharmony_ci * and/or other materials provided with the distribution. 3. All advertising 56beacf11bSopenharmony_ci * materials mentioning features or use of this software must display the 57beacf11bSopenharmony_ci * following acknowledgement: This product includes software developed by the 58beacf11bSopenharmony_ci * University of California, Berkeley and its contributors. 4. Neither the 59beacf11bSopenharmony_ci * name of the University nor the names of its contributors may be used to 60beacf11bSopenharmony_ci * endorse or promote products derived from this software without specific 61beacf11bSopenharmony_ci * prior written permission. 62beacf11bSopenharmony_ci * 63beacf11bSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 64beacf11bSopenharmony_ci * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 65beacf11bSopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 66beacf11bSopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 67beacf11bSopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 68beacf11bSopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 69beacf11bSopenharmony_ci * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 70beacf11bSopenharmony_ci * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 71beacf11bSopenharmony_ci * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 72beacf11bSopenharmony_ci * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 73beacf11bSopenharmony_ci * SUCH DAMAGE. 74beacf11bSopenharmony_ci * 75beacf11bSopenharmony_ci ****************************************************************************/ 76beacf11bSopenharmony_ci 77beacf11bSopenharmony_ci/**************************************************************************** 78beacf11bSopenharmony_ci * Included Files 79beacf11bSopenharmony_ci ****************************************************************************/ 80beacf11bSopenharmony_ci 81beacf11bSopenharmony_ci#include <sys/time.h> 82beacf11bSopenharmony_ci#include <stdlib.h> 83beacf11bSopenharmony_ci#include <unistd.h> 84beacf11bSopenharmony_ci#include "lwip/opt.h" 85beacf11bSopenharmony_ci#include "lwip/sockets.h" 86beacf11bSopenharmony_ci#include "xdr_subs.h" 87beacf11bSopenharmony_ci#include "nfs_proto.h" 88beacf11bSopenharmony_ci#include "rpc.h" 89beacf11bSopenharmony_ci#include "nfs.h" 90beacf11bSopenharmony_ci 91beacf11bSopenharmony_ci/**************************************************************************** 92beacf11bSopenharmony_ci * Pre-processor Definitions 93beacf11bSopenharmony_ci ****************************************************************************/ 94beacf11bSopenharmony_ci 95beacf11bSopenharmony_ci/* Increment RPC statistics */ 96beacf11bSopenharmony_ci 97beacf11bSopenharmony_ci#ifdef CONFIG_NFS_STATISTICS 98beacf11bSopenharmony_ci# define rpc_statistics(n) do { rpcstats.n++; } while (0) 99beacf11bSopenharmony_ci#else 100beacf11bSopenharmony_ci# define rpc_statistics(n) 101beacf11bSopenharmony_ci#endif 102beacf11bSopenharmony_ci 103beacf11bSopenharmony_ci#undef OK 104beacf11bSopenharmony_ci#define OK 0 105beacf11bSopenharmony_ci 106beacf11bSopenharmony_ci#define RPCCLNT_FH_LEN 4 107beacf11bSopenharmony_ci#define RPCCLNT_RECV_BUF_MAX_LEN 64 108beacf11bSopenharmony_ci#define RPCCLNT_CONNECT_MAX_RETRY_TIMES 1024 109beacf11bSopenharmony_ci 110beacf11bSopenharmony_ci/**************************************************************************** 111beacf11bSopenharmony_ci * Private Data 112beacf11bSopenharmony_ci ****************************************************************************/ 113beacf11bSopenharmony_ci 114beacf11bSopenharmony_ci/* Static data, mostly RPC constants in XDR form */ 115beacf11bSopenharmony_ci 116beacf11bSopenharmony_cistatic uint32_t rpc_reply; 117beacf11bSopenharmony_cistatic uint32_t rpc_call; 118beacf11bSopenharmony_cistatic uint32_t rpc_vers; 119beacf11bSopenharmony_cistatic uint32_t rpc_msgdenied; 120beacf11bSopenharmony_cistatic uint32_t rpc_mismatch; 121beacf11bSopenharmony_cistatic uint32_t rpc_auth_unix; 122beacf11bSopenharmony_cistatic uint32_t rpc_msgaccepted; 123beacf11bSopenharmony_cistatic uint32_t rpc_autherr; 124beacf11bSopenharmony_cistatic uint32_t rpc_auth_null; 125beacf11bSopenharmony_cistatic uint32_t nfs_uid, nfs_gid; 126beacf11bSopenharmony_ci 127beacf11bSopenharmony_ci/* Global statics for all client instances. Cleared by NuttX on boot-up. */ 128beacf11bSopenharmony_ci 129beacf11bSopenharmony_ci#ifdef CONFIG_NFS_STATISTICS 130beacf11bSopenharmony_cistatic struct rpcstats rpcstats; 131beacf11bSopenharmony_ci#endif 132beacf11bSopenharmony_ci 133beacf11bSopenharmony_ci/**************************************************************************** 134beacf11bSopenharmony_ci * Private Function Prototypes 135beacf11bSopenharmony_ci ****************************************************************************/ 136beacf11bSopenharmony_ci 137beacf11bSopenharmony_cistatic int rpcclnt_send(struct rpcclnt *rpc, int procid, int prog, 138beacf11bSopenharmony_ci void *call, int reqlen); 139beacf11bSopenharmony_cistatic int rpcclnt_receive(struct rpcclnt *rpc, struct sockaddr *aname, 140beacf11bSopenharmony_ci int proc, int program, void *reply, size_t resplen); 141beacf11bSopenharmony_cistatic int rpcclnt_reply(struct rpcclnt *rpc, int procid, int prog, 142beacf11bSopenharmony_ci void *reply, size_t resplen); 143beacf11bSopenharmony_cistatic uint32_t rpcclnt_newxid(void); 144beacf11bSopenharmony_cistatic void rpcclnt_fmtheader(struct rpc_call_header *ch, 145beacf11bSopenharmony_ci uint32_t xid, int procid, int prog, int vers, size_t reqlen); 146beacf11bSopenharmony_cistatic int rpcclnt_reconnect(struct rpcclnt *rpc, struct sockaddr *saddr); 147beacf11bSopenharmony_ci 148beacf11bSopenharmony_ci/**************************************************************************** 149beacf11bSopenharmony_ci * Private Functions 150beacf11bSopenharmony_ci ****************************************************************************/ 151beacf11bSopenharmony_ci 152beacf11bSopenharmony_ci/**************************************************************************** 153beacf11bSopenharmony_ci * Name: rpcclnt_send 154beacf11bSopenharmony_ci * 155beacf11bSopenharmony_ci * Description: 156beacf11bSopenharmony_ci * This is the nfs send routine. 157beacf11bSopenharmony_ci * 158beacf11bSopenharmony_ci * Returned Value: 159beacf11bSopenharmony_ci * Returns zero on success or a (positive) errno value on failure. 160beacf11bSopenharmony_ci * 161beacf11bSopenharmony_ci ****************************************************************************/ 162beacf11bSopenharmony_ci 163beacf11bSopenharmony_cistatic int rpcclnt_send(struct rpcclnt *rpc, int procid, int prog, 164beacf11bSopenharmony_ci void *call, int reqlen) 165beacf11bSopenharmony_ci{ 166beacf11bSopenharmony_ci ssize_t nbytes; 167beacf11bSopenharmony_ci int ret = OK; 168beacf11bSopenharmony_ci 169beacf11bSopenharmony_ci /* Send the call message 170beacf11bSopenharmony_ci * 171beacf11bSopenharmony_ci * On success, psock_sendto returns the number of bytes sent; 172beacf11bSopenharmony_ci * On failure, it returns -1 with the specific error in errno. 173beacf11bSopenharmony_ci */ 174beacf11bSopenharmony_ci 175beacf11bSopenharmony_ci nbytes = sendto(rpc->rc_so, call, reqlen, 0, 176beacf11bSopenharmony_ci rpc->rc_name, sizeof(struct sockaddr)); 177beacf11bSopenharmony_ci if (nbytes < 0) 178beacf11bSopenharmony_ci { 179beacf11bSopenharmony_ci /* psock_sendto failed */ 180beacf11bSopenharmony_ci 181beacf11bSopenharmony_ci ret = get_errno(); 182beacf11bSopenharmony_ci nfs_debug_error("psock_sendto failed: %d\n", ret); 183beacf11bSopenharmony_ci } 184beacf11bSopenharmony_ci 185beacf11bSopenharmony_ci return ret; 186beacf11bSopenharmony_ci} 187beacf11bSopenharmony_ci 188beacf11bSopenharmony_ci#if (NFS_PROTO_TYPE == NFS_IPPROTO_UDP) 189beacf11bSopenharmony_ci#define CONFIG_NFS_RECV_TIMEOUT 200 /* udp-nfs recv timeout in milli seconds */ 190beacf11bSopenharmony_ci 191beacf11bSopenharmony_ci/**************************************************************************** 192beacf11bSopenharmony_ci * Name: rpcclnt_receive 193beacf11bSopenharmony_ci * 194beacf11bSopenharmony_ci * Description: 195beacf11bSopenharmony_ci * Receive a Sun RPC Request/Reply. Only for SOCK_DGRAM 196beacf11bSopenharmony_ci * 197beacf11bSopenharmony_ci ****************************************************************************/ 198beacf11bSopenharmony_ci 199beacf11bSopenharmony_cistatic int rpcclnt_receive(struct rpcclnt *rpc, struct sockaddr *aname, 200beacf11bSopenharmony_ci int proc, int program, void *reply, 201beacf11bSopenharmony_ci size_t resplen) 202beacf11bSopenharmony_ci{ 203beacf11bSopenharmony_ci ssize_t nbytes; 204beacf11bSopenharmony_ci int error = 0; 205beacf11bSopenharmony_ci int ret; 206beacf11bSopenharmony_ci fd_set fdreadset; 207beacf11bSopenharmony_ci struct timeval timeval = {0}; 208beacf11bSopenharmony_ci socklen_t fromlen = sizeof(struct sockaddr); 209beacf11bSopenharmony_ci uint32_t xid; 210beacf11bSopenharmony_ciretry: 211beacf11bSopenharmony_ci FD_ZERO(&fdreadset); 212beacf11bSopenharmony_ci FD_SET((uint32_t)(rpc->rc_so), &fdreadset); 213beacf11bSopenharmony_ci 214beacf11bSopenharmony_ci timeval.tv_sec = (CONFIG_NFS_RECV_TIMEOUT / 1000); 215beacf11bSopenharmony_ci timeval.tv_usec = (CONFIG_NFS_RECV_TIMEOUT % 1000) * 1000; 216beacf11bSopenharmony_ci 217beacf11bSopenharmony_ci ret = select(rpc->rc_so + 1, &fdreadset, 0, 0, &timeval); 218beacf11bSopenharmony_ci if (ret == 0) 219beacf11bSopenharmony_ci { 220beacf11bSopenharmony_ci nfs_debug_error("rpcclnt_receive select nothing\n"); 221beacf11bSopenharmony_ci return EAGAIN; 222beacf11bSopenharmony_ci } 223beacf11bSopenharmony_ci else if (ret < 0) 224beacf11bSopenharmony_ci { 225beacf11bSopenharmony_ci error = get_errno(); 226beacf11bSopenharmony_ci nfs_debug_error("rpcclnt_receive select error %d\n", error); 227beacf11bSopenharmony_ci return error; 228beacf11bSopenharmony_ci } 229beacf11bSopenharmony_ci 230beacf11bSopenharmony_ci nbytes = recvfrom(rpc->rc_so, reply, resplen, 0, aname, &fromlen); 231beacf11bSopenharmony_ci if (nbytes <= (ssize_t)sizeof(xid)) 232beacf11bSopenharmony_ci { 233beacf11bSopenharmony_ci error = get_errno(); 234beacf11bSopenharmony_ci nfs_debug_error("psock_recvfrom failed: %d\n", error); 235beacf11bSopenharmony_ci goto retry; 236beacf11bSopenharmony_ci } 237beacf11bSopenharmony_ci 238beacf11bSopenharmony_ci error = memcpy_s((void *)&xid, sizeof(xid), ((char *)reply + RPC_RMSIZE), sizeof(xid)); 239beacf11bSopenharmony_ci if (error != EOK) 240beacf11bSopenharmony_ci { 241beacf11bSopenharmony_ci return ENOBUFS; 242beacf11bSopenharmony_ci } 243beacf11bSopenharmony_ci 244beacf11bSopenharmony_ci if (fxdr_unsigned(uint32_t, xid) != rpc->xid) 245beacf11bSopenharmony_ci { 246beacf11bSopenharmony_ci nfs_debug_error("psock_recvfrom a wrong packet\n"); 247beacf11bSopenharmony_ci goto retry; 248beacf11bSopenharmony_ci } 249beacf11bSopenharmony_ci 250beacf11bSopenharmony_ci return error; 251beacf11bSopenharmony_ci} 252beacf11bSopenharmony_ci 253beacf11bSopenharmony_ci#elif (NFS_PROTO_TYPE == NFS_IPPROTO_TCP) 254beacf11bSopenharmony_ci#define CONFIG_NFS_RECV_TIMEOUT 5000 /* tcp-nfs recv timeout in milli seconds */ 255beacf11bSopenharmony_ci 256beacf11bSopenharmony_ci/**************************************************************************** 257beacf11bSopenharmony_ci * Name: rpcclnt_receive 258beacf11bSopenharmony_ci * 259beacf11bSopenharmony_ci * Description: 260beacf11bSopenharmony_ci * Receive a Sun RPC Request/Reply. Only for SOCK_STREAM 261beacf11bSopenharmony_ci * 262beacf11bSopenharmony_ci ****************************************************************************/ 263beacf11bSopenharmony_ci 264beacf11bSopenharmony_cistatic int rpcclnt_receive(struct rpcclnt *rpc, struct sockaddr *aname, 265beacf11bSopenharmony_ci int proc, int program, void *reply, 266beacf11bSopenharmony_ci size_t resplen) 267beacf11bSopenharmony_ci{ 268beacf11bSopenharmony_ci ssize_t nbytes; 269beacf11bSopenharmony_ci size_t offset = 0; 270beacf11bSopenharmony_ci size_t hdrlen = 0; 271beacf11bSopenharmony_ci uint32_t total = 0; 272beacf11bSopenharmony_ci int error; 273beacf11bSopenharmony_ci int ret; 274beacf11bSopenharmony_ci fd_set fdreadset; 275beacf11bSopenharmony_ci struct timeval timeval = {0}; 276beacf11bSopenharmony_ci socklen_t fromlen = sizeof(struct sockaddr); 277beacf11bSopenharmony_ci 278beacf11bSopenharmony_ci do 279beacf11bSopenharmony_ci { 280beacf11bSopenharmony_ci FD_ZERO(&fdreadset); 281beacf11bSopenharmony_ci FD_SET((uint32_t)(rpc->rc_so), &fdreadset); 282beacf11bSopenharmony_ci 283beacf11bSopenharmony_ci timeval.tv_sec = (CONFIG_NFS_RECV_TIMEOUT / 1000); 284beacf11bSopenharmony_ci timeval.tv_usec = (CONFIG_NFS_RECV_TIMEOUT % 1000) * 1000; 285beacf11bSopenharmony_ci 286beacf11bSopenharmony_ci ret = select(rpc->rc_so + 1, &fdreadset, 0, 0, &timeval); 287beacf11bSopenharmony_ci if (ret == 0) /* no reply */ 288beacf11bSopenharmony_ci { 289beacf11bSopenharmony_ci nfs_debug_error("rpcclnt_receive select nothing\n"); 290beacf11bSopenharmony_ci return EAGAIN; 291beacf11bSopenharmony_ci } 292beacf11bSopenharmony_ci else if (ret < 0) /* select error */ 293beacf11bSopenharmony_ci { 294beacf11bSopenharmony_ci error = get_errno(); 295beacf11bSopenharmony_ci nfs_debug_error("rpcclnt_receive select error %d\n", error); 296beacf11bSopenharmony_ci return error; 297beacf11bSopenharmony_ci } 298beacf11bSopenharmony_ci 299beacf11bSopenharmony_ci nbytes = recvfrom(rpc->rc_so, (char *)reply + offset, resplen - offset, 0, aname, &fromlen); 300beacf11bSopenharmony_ci if (nbytes < 0) 301beacf11bSopenharmony_ci { 302beacf11bSopenharmony_ci error = get_errno(); 303beacf11bSopenharmony_ci nfs_debug_error("rpcclnt_receive recvfrom error %d\n", error); 304beacf11bSopenharmony_ci return error; 305beacf11bSopenharmony_ci } 306beacf11bSopenharmony_ci else if (nbytes == 0) 307beacf11bSopenharmony_ci { 308beacf11bSopenharmony_ci /* connection closed by peer side */ 309beacf11bSopenharmony_ci 310beacf11bSopenharmony_ci nfs_debug_error("rpcclnt_receive connection closed by peer\n"); 311beacf11bSopenharmony_ci return EIO; 312beacf11bSopenharmony_ci } 313beacf11bSopenharmony_ci else 314beacf11bSopenharmony_ci { 315beacf11bSopenharmony_ci offset += nbytes; 316beacf11bSopenharmony_ci 317beacf11bSopenharmony_ci /* parse fragment header */ 318beacf11bSopenharmony_ci 319beacf11bSopenharmony_ci if (offset == 0 || hdrlen < sizeof(struct rpc_reply_header)) 320beacf11bSopenharmony_ci { 321beacf11bSopenharmony_ci hdrlen += nbytes; 322beacf11bSopenharmony_ci 323beacf11bSopenharmony_ci /* unlikely */ 324beacf11bSopenharmony_ci 325beacf11bSopenharmony_ci if (hdrlen < sizeof(struct rpc_reply_header)) 326beacf11bSopenharmony_ci { 327beacf11bSopenharmony_ci continue; 328beacf11bSopenharmony_ci } 329beacf11bSopenharmony_ci 330beacf11bSopenharmony_ci error = memcpy_s(&total, RPC_RMSIZE, reply, RPC_RMSIZE); 331beacf11bSopenharmony_ci if (error != EOK) 332beacf11bSopenharmony_ci { 333beacf11bSopenharmony_ci return ENOBUFS; 334beacf11bSopenharmony_ci } 335beacf11bSopenharmony_ci total = (fxdr_unsigned(uint32_t, total) & RPC_RM_FLAGMENT_LEN_MASK) + RPC_RMSIZE; 336beacf11bSopenharmony_ci } 337beacf11bSopenharmony_ci } 338beacf11bSopenharmony_ci } 339beacf11bSopenharmony_ci while (offset < total); 340beacf11bSopenharmony_ci 341beacf11bSopenharmony_ci return 0; 342beacf11bSopenharmony_ci} 343beacf11bSopenharmony_ci#endif 344beacf11bSopenharmony_ci 345beacf11bSopenharmony_ci/**************************************************************************** 346beacf11bSopenharmony_ci * Name: rpcclnt_reply 347beacf11bSopenharmony_ci * 348beacf11bSopenharmony_ci * Description: 349beacf11bSopenharmony_ci * Received the RPC reply on the socket. 350beacf11bSopenharmony_ci * 351beacf11bSopenharmony_ci ****************************************************************************/ 352beacf11bSopenharmony_ci 353beacf11bSopenharmony_cistatic int rpcclnt_reply(struct rpcclnt *rpc, int procid, int prog, 354beacf11bSopenharmony_ci void *reply, size_t resplen) 355beacf11bSopenharmony_ci{ 356beacf11bSopenharmony_ci int error; 357beacf11bSopenharmony_ci 358beacf11bSopenharmony_ci /* Get the next RPC reply from the socket */ 359beacf11bSopenharmony_ci 360beacf11bSopenharmony_ci error = rpcclnt_receive(rpc, rpc->rc_name, procid, prog, reply, resplen); 361beacf11bSopenharmony_ci if (error != 0) 362beacf11bSopenharmony_ci { 363beacf11bSopenharmony_ci nfs_debug_error("rpcclnt_receive returned: %d\n", error); 364beacf11bSopenharmony_ci 365beacf11bSopenharmony_ci /* For UDP, If we failed because of a timeout, then try sending the CALL 366beacf11bSopenharmony_ci * message again. While for TCP, just return errno. 367beacf11bSopenharmony_ci */ 368beacf11bSopenharmony_ci 369beacf11bSopenharmony_ci#if (NFS_PROTO_TYPE == NFS_IPPROTO_UDP) 370beacf11bSopenharmony_ci if (error == EAGAIN || error == ETIMEDOUT) 371beacf11bSopenharmony_ci { 372beacf11bSopenharmony_ci rpc->rc_timeout = true; 373beacf11bSopenharmony_ci } 374beacf11bSopenharmony_ci#endif 375beacf11bSopenharmony_ci } 376beacf11bSopenharmony_ci 377beacf11bSopenharmony_ci /* Get the xid and check that it is an RPC replysvr */ 378beacf11bSopenharmony_ci 379beacf11bSopenharmony_ci else 380beacf11bSopenharmony_ci { 381beacf11bSopenharmony_ci struct rpc_reply_header *replyheader = 382beacf11bSopenharmony_ci (struct rpc_reply_header *)reply; 383beacf11bSopenharmony_ci 384beacf11bSopenharmony_ci if (replyheader->rp_direction != rpc_reply) 385beacf11bSopenharmony_ci { 386beacf11bSopenharmony_ci nfs_debug_error("Different RPC REPLY returned\n"); 387beacf11bSopenharmony_ci rpc_statistics(rpcinvalid); 388beacf11bSopenharmony_ci error = EPROTO; 389beacf11bSopenharmony_ci } 390beacf11bSopenharmony_ci } 391beacf11bSopenharmony_ci 392beacf11bSopenharmony_ci return error; 393beacf11bSopenharmony_ci} 394beacf11bSopenharmony_ci 395beacf11bSopenharmony_ci/**************************************************************************** 396beacf11bSopenharmony_ci * Name: rpcclnt_newxid 397beacf11bSopenharmony_ci * 398beacf11bSopenharmony_ci * Description: 399beacf11bSopenharmony_ci * Get a new (non-zero) xid 400beacf11bSopenharmony_ci * 401beacf11bSopenharmony_ci ****************************************************************************/ 402beacf11bSopenharmony_ciextern VOID LOS_GetCpuCycle(UINT32 *puwCntHi, UINT32 *puwCntLo); 403beacf11bSopenharmony_ci 404beacf11bSopenharmony_cistatic uint32_t seed_gen_func(void) 405beacf11bSopenharmony_ci{ 406beacf11bSopenharmony_ci uint32_t seedhsb, seedlsb; 407beacf11bSopenharmony_ci LOS_GetCpuCycle(&seedhsb, &seedlsb); 408beacf11bSopenharmony_ci return seedlsb; 409beacf11bSopenharmony_ci} 410beacf11bSopenharmony_ci 411beacf11bSopenharmony_cistatic uint32_t rpcclnt_newxid(void) 412beacf11bSopenharmony_ci{ 413beacf11bSopenharmony_ci static uint32_t rpcclnt_xid = 0; 414beacf11bSopenharmony_ci static uint32_t rpcclnt_xid_touched = 0; 415beacf11bSopenharmony_ci 416beacf11bSopenharmony_ci if ((rpcclnt_xid == 0) && (rpcclnt_xid_touched == 0)) 417beacf11bSopenharmony_ci { 418beacf11bSopenharmony_ci unsigned int seed = seed_gen_func(); 419beacf11bSopenharmony_ci srand(seed); 420beacf11bSopenharmony_ci rpcclnt_xid = rand(); 421beacf11bSopenharmony_ci rpcclnt_xid_touched = 1; 422beacf11bSopenharmony_ci } 423beacf11bSopenharmony_ci else 424beacf11bSopenharmony_ci { 425beacf11bSopenharmony_ci int xidp = 0; 426beacf11bSopenharmony_ci do 427beacf11bSopenharmony_ci { 428beacf11bSopenharmony_ci xidp = rand(); 429beacf11bSopenharmony_ci } 430beacf11bSopenharmony_ci while ((xidp % 256) == 0); 431beacf11bSopenharmony_ci 432beacf11bSopenharmony_ci rpcclnt_xid += xidp; 433beacf11bSopenharmony_ci } 434beacf11bSopenharmony_ci 435beacf11bSopenharmony_ci return rpcclnt_xid; 436beacf11bSopenharmony_ci} 437beacf11bSopenharmony_ci 438beacf11bSopenharmony_ci/**************************************************************************** 439beacf11bSopenharmony_ci * Name: rpcclnt_alivecheck 440beacf11bSopenharmony_ci * 441beacf11bSopenharmony_ci * Description: 442beacf11bSopenharmony_ci * Check if the connection is alive 443beacf11bSopenharmony_ci * 444beacf11bSopenharmony_ci ****************************************************************************/ 445beacf11bSopenharmony_ci 446beacf11bSopenharmony_cistatic int rpcclnt_alivecheck(struct rpcclnt *rpc) 447beacf11bSopenharmony_ci{ 448beacf11bSopenharmony_ci fd_set rfd; 449beacf11bSopenharmony_ci int recvlen; 450beacf11bSopenharmony_ci char buf[RPCCLNT_RECV_BUF_MAX_LEN]; 451beacf11bSopenharmony_ci const int bufsize = RPCCLNT_RECV_BUF_MAX_LEN; 452beacf11bSopenharmony_ci int ret; 453beacf11bSopenharmony_ci int sockfd = rpc->rc_so; 454beacf11bSopenharmony_ci struct timeval timeout; 455beacf11bSopenharmony_ci 456beacf11bSopenharmony_ci FD_ZERO(&rfd); 457beacf11bSopenharmony_ci if (sockfd < 0) 458beacf11bSopenharmony_ci { 459beacf11bSopenharmony_ci return ENETDOWN; 460beacf11bSopenharmony_ci } 461beacf11bSopenharmony_ci FD_SET((uint32_t)sockfd, &rfd); 462beacf11bSopenharmony_ci 463beacf11bSopenharmony_ci timeout.tv_sec = 0; 464beacf11bSopenharmony_ci timeout.tv_usec = 0; 465beacf11bSopenharmony_ci 466beacf11bSopenharmony_ci /* no wait */ 467beacf11bSopenharmony_ci 468beacf11bSopenharmony_ci ret = select(sockfd + 1, &rfd, NULL, NULL, &timeout); 469beacf11bSopenharmony_ci if (ret < 0) 470beacf11bSopenharmony_ci { 471beacf11bSopenharmony_ci nfs_debug_error("rpc_alivecheck : select failure\n"); 472beacf11bSopenharmony_ci return get_errno(); 473beacf11bSopenharmony_ci } 474beacf11bSopenharmony_ci 475beacf11bSopenharmony_ci if (sockfd) 476beacf11bSopenharmony_ci { 477beacf11bSopenharmony_ci if (FD_ISSET((uint32_t)sockfd, &rfd)) 478beacf11bSopenharmony_ci { 479beacf11bSopenharmony_ci recvlen = recv(sockfd, buf, bufsize, 0); 480beacf11bSopenharmony_ci if (recvlen <= 0) 481beacf11bSopenharmony_ci { 482beacf11bSopenharmony_ci (void)close(rpc->rc_so); 483beacf11bSopenharmony_ci rpc->rc_so = -1; 484beacf11bSopenharmony_ci } 485beacf11bSopenharmony_ci else 486beacf11bSopenharmony_ci { 487beacf11bSopenharmony_ci nfs_debug_error("rpc_alivecheck : recv unsolocit %d data from server\n", recvlen); 488beacf11bSopenharmony_ci return ENOTSOCK; 489beacf11bSopenharmony_ci } 490beacf11bSopenharmony_ci } 491beacf11bSopenharmony_ci } 492beacf11bSopenharmony_ci 493beacf11bSopenharmony_ci return 0; 494beacf11bSopenharmony_ci} 495beacf11bSopenharmony_ci 496beacf11bSopenharmony_ci/**************************************************************************** 497beacf11bSopenharmony_ci * Name: rpcclnt_fmtheader 498beacf11bSopenharmony_ci * 499beacf11bSopenharmony_ci * Description: 500beacf11bSopenharmony_ci * Format the common part of the call header 501beacf11bSopenharmony_ci * 502beacf11bSopenharmony_ci ****************************************************************************/ 503beacf11bSopenharmony_ci 504beacf11bSopenharmony_cistatic void rpcclnt_fmtheader(struct rpc_call_header *ch, 505beacf11bSopenharmony_ci uint32_t xid, int prog, int vers, int procid, size_t reqlen) 506beacf11bSopenharmony_ci{ 507beacf11bSopenharmony_ci unsigned int high = 0; 508beacf11bSopenharmony_ci unsigned int low = 0; 509beacf11bSopenharmony_ci int error; 510beacf11bSopenharmony_ci 511beacf11bSopenharmony_ci LOS_GetCpuCycle(&high, &low); 512beacf11bSopenharmony_ci 513beacf11bSopenharmony_ci /* Format the call header */ 514beacf11bSopenharmony_ci 515beacf11bSopenharmony_ci#if (NFS_PROTO_TYPE == NFS_IPPROTO_TCP) 516beacf11bSopenharmony_ci ch->rp_recmark = txdr_unsigned(0x80000000 | (reqlen - RPC_RMSIZE)); 517beacf11bSopenharmony_ci#endif 518beacf11bSopenharmony_ci ch->rp_xid = txdr_unsigned(xid); 519beacf11bSopenharmony_ci ch->rp_direction = rpc_call; 520beacf11bSopenharmony_ci ch->rp_rpcvers = rpc_vers; 521beacf11bSopenharmony_ci ch->rp_prog = txdr_unsigned(prog); 522beacf11bSopenharmony_ci ch->rp_vers = txdr_unsigned(vers); 523beacf11bSopenharmony_ci ch->rp_proc = txdr_unsigned(procid); 524beacf11bSopenharmony_ci 525beacf11bSopenharmony_ci ch->rpc_auth.authtype = rpc_auth_unix; 526beacf11bSopenharmony_ci ch->rpc_auth.authlen = htonl(sizeof(ch->rpc_auth_unix)); 527beacf11bSopenharmony_ci ch->rpc_auth_unix.stamp = txdr_unsigned((uint32_t)(((UINT64)high << 32) + low)); 528beacf11bSopenharmony_ci ch->rpc_auth_unix.hostname_len = htonl(CONFIG_NFS_MACHINE_NAME_SIZE); 529beacf11bSopenharmony_ci (void)memset_s(ch->rpc_auth_unix.hostname, sizeof(ch->rpc_auth_unix.hostname), 530beacf11bSopenharmony_ci 0, sizeof(ch->rpc_auth_unix.hostname)); 531beacf11bSopenharmony_ci error = memcpy_s(ch->rpc_auth_unix.hostname, sizeof(ch->rpc_auth_unix.hostname), 532beacf11bSopenharmony_ci CONFIG_NFS_MACHINE_NAME, CONFIG_NFS_MACHINE_NAME_SIZE); 533beacf11bSopenharmony_ci if (error != EOK) 534beacf11bSopenharmony_ci { 535beacf11bSopenharmony_ci return; 536beacf11bSopenharmony_ci } 537beacf11bSopenharmony_ci ch->rpc_auth_unix.uid = htonl(nfs_uid); 538beacf11bSopenharmony_ci ch->rpc_auth_unix.gid = htonl(nfs_gid); 539beacf11bSopenharmony_ci ch->rpc_auth_unix.gidlist = htonl(1); 540beacf11bSopenharmony_ci ch->rpc_auth_unix.gidlist_value = nfs_gid; 541beacf11bSopenharmony_ci 542beacf11bSopenharmony_ci /* rpc_verf part (auth_null) */ 543beacf11bSopenharmony_ci 544beacf11bSopenharmony_ci ch->rpc_verf.authtype = rpc_auth_null; 545beacf11bSopenharmony_ci ch->rpc_verf.authlen = 0; 546beacf11bSopenharmony_ci} 547beacf11bSopenharmony_ci 548beacf11bSopenharmony_cistatic int rpcclnt_reconnect(struct rpcclnt *rpc, struct sockaddr *saddr) 549beacf11bSopenharmony_ci{ 550beacf11bSopenharmony_ci int errval; 551beacf11bSopenharmony_ci int error; 552beacf11bSopenharmony_ci 553beacf11bSopenharmony_ci#if (NFS_PROTO_TYPE == NFS_IPPROTO_TCP) 554beacf11bSopenharmony_ci extern long random(void); 555beacf11bSopenharmony_ci unsigned short tport = 0; 556beacf11bSopenharmony_ci unsigned short trycount = 0; 557beacf11bSopenharmony_ci struct sockaddr_in sock_in; 558beacf11bSopenharmony_ci 559beacf11bSopenharmony_ci rpcclnt_disconnect(rpc); 560beacf11bSopenharmony_ci 561beacf11bSopenharmony_ci error = socket(rpc->rc_name->sa_family, rpc->rc_sotype, IPPROTO_TCP); 562beacf11bSopenharmony_ci if (error < 0) 563beacf11bSopenharmony_ci { 564beacf11bSopenharmony_ci nfs_debug_error("psock_socket failed: %d", get_errno()); 565beacf11bSopenharmony_ci return -error; 566beacf11bSopenharmony_ci } 567beacf11bSopenharmony_ci 568beacf11bSopenharmony_ci rpc->rc_so = error; 569beacf11bSopenharmony_ci sock_in.sin_family = AF_INET; 570beacf11bSopenharmony_ci sock_in.sin_addr.s_addr = INADDR_ANY; 571beacf11bSopenharmony_ci trycount = RPCCLNT_CONNECT_MAX_RETRY_TIMES; 572beacf11bSopenharmony_ci 573beacf11bSopenharmony_ci do 574beacf11bSopenharmony_ci { 575beacf11bSopenharmony_ci errval = 0; 576beacf11bSopenharmony_ci trycount--; 577beacf11bSopenharmony_ci tport = random() % (RPCCONN_MAXPORT - RPCCONN_MINPORT) + RPCCONN_MINPORT; 578beacf11bSopenharmony_ci sock_in.sin_port = htons(tport); 579beacf11bSopenharmony_ci error = bind(rpc->rc_so, (struct sockaddr *)&sock_in, sizeof(sock_in)); 580beacf11bSopenharmony_ci if (error < 0) 581beacf11bSopenharmony_ci { 582beacf11bSopenharmony_ci errval = get_errno(); 583beacf11bSopenharmony_ci nfs_debug_error("psock_bind failed: %d\n", errval); 584beacf11bSopenharmony_ci } 585beacf11bSopenharmony_ci } 586beacf11bSopenharmony_ci while (errval == EADDRINUSE && trycount > 0); 587beacf11bSopenharmony_ci 588beacf11bSopenharmony_ci if (error) 589beacf11bSopenharmony_ci { 590beacf11bSopenharmony_ci nfs_debug_error("psock_bind failed: %d, port = %d\n", errval, tport); 591beacf11bSopenharmony_ci goto bad; 592beacf11bSopenharmony_ci } 593beacf11bSopenharmony_ci#endif 594beacf11bSopenharmony_ci error = connect(rpc->rc_so, saddr, sizeof(*saddr)); 595beacf11bSopenharmony_ci if (error < 0) 596beacf11bSopenharmony_ci { 597beacf11bSopenharmony_ci errval = get_errno(); 598beacf11bSopenharmony_ci nfs_debug_error("psock_connect failed [port=%d]: %d\n", 599beacf11bSopenharmony_ci ntohs(((struct sockaddr_in *)saddr)->sin_port), errval); 600beacf11bSopenharmony_ci goto bad; 601beacf11bSopenharmony_ci } 602beacf11bSopenharmony_ci return error; 603beacf11bSopenharmony_cibad: 604beacf11bSopenharmony_ci rpcclnt_disconnect(rpc); 605beacf11bSopenharmony_ci return errval; 606beacf11bSopenharmony_ci} 607beacf11bSopenharmony_ci 608beacf11bSopenharmony_ci/**************************************************************************** 609beacf11bSopenharmony_ci * Public Functions 610beacf11bSopenharmony_ci ****************************************************************************/ 611beacf11bSopenharmony_ci 612beacf11bSopenharmony_ci/**************************************************************************** 613beacf11bSopenharmony_ci * Name: rpcclnt_init 614beacf11bSopenharmony_ci * 615beacf11bSopenharmony_ci * Description: 616beacf11bSopenharmony_ci * Initialize the RPC client 617beacf11bSopenharmony_ci * 618beacf11bSopenharmony_ci ****************************************************************************/ 619beacf11bSopenharmony_ci 620beacf11bSopenharmony_civoid rpcclnt_init(void) 621beacf11bSopenharmony_ci{ 622beacf11bSopenharmony_ci /* RPC constants how about actually using more than one of these! */ 623beacf11bSopenharmony_ci 624beacf11bSopenharmony_ci rpc_reply = txdr_unsigned(RPC_REPLY); 625beacf11bSopenharmony_ci rpc_vers = txdr_unsigned(RPC_VER2); 626beacf11bSopenharmony_ci rpc_call = txdr_unsigned(RPC_CALL); 627beacf11bSopenharmony_ci rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED); 628beacf11bSopenharmony_ci rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED); 629beacf11bSopenharmony_ci rpc_mismatch = txdr_unsigned(RPC_MISMATCH); 630beacf11bSopenharmony_ci rpc_autherr = txdr_unsigned(RPC_AUTHERR); 631beacf11bSopenharmony_ci rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX); 632beacf11bSopenharmony_ci rpc_auth_null = txdr_unsigned(RPCAUTH_NULL); 633beacf11bSopenharmony_ci 634beacf11bSopenharmony_ci nfs_debug_info("RPC initialized\n"); 635beacf11bSopenharmony_ci} 636beacf11bSopenharmony_ci 637beacf11bSopenharmony_ci/**************************************************************************** 638beacf11bSopenharmony_ci * Name: rpcclnt_connect 639beacf11bSopenharmony_ci * 640beacf11bSopenharmony_ci * Description: 641beacf11bSopenharmony_ci * Initialize sockets for a new RPC connection. We do not free the 642beacf11bSopenharmony_ci * sockaddr if an error occurs. 643beacf11bSopenharmony_ci * 644beacf11bSopenharmony_ci ****************************************************************************/ 645beacf11bSopenharmony_ci 646beacf11bSopenharmony_ciint rpcclnt_connect(struct rpcclnt *rpc) 647beacf11bSopenharmony_ci{ 648beacf11bSopenharmony_ci extern long random(void); 649beacf11bSopenharmony_ci int error; 650beacf11bSopenharmony_ci struct sockaddr *saddr; 651beacf11bSopenharmony_ci struct sockaddr_in sin; 652beacf11bSopenharmony_ci struct sockaddr_in *sa; 653beacf11bSopenharmony_ci 654beacf11bSopenharmony_ci union 655beacf11bSopenharmony_ci { 656beacf11bSopenharmony_ci struct rpc_call_pmap sdata; 657beacf11bSopenharmony_ci struct rpc_call_mount mountd; 658beacf11bSopenharmony_ci } request; 659beacf11bSopenharmony_ci 660beacf11bSopenharmony_ci union 661beacf11bSopenharmony_ci { 662beacf11bSopenharmony_ci struct rpc_reply_pmap rdata; 663beacf11bSopenharmony_ci struct rpc_reply_mount mdata; 664beacf11bSopenharmony_ci } response; 665beacf11bSopenharmony_ci 666beacf11bSopenharmony_ci uint16_t trycount; 667beacf11bSopenharmony_ci uint16_t tport = 0; 668beacf11bSopenharmony_ci int errval; 669beacf11bSopenharmony_ci 670beacf11bSopenharmony_ci nfs_debug_info("Connecting\n"); 671beacf11bSopenharmony_ci 672beacf11bSopenharmony_ci /* Create the socket */ 673beacf11bSopenharmony_ci 674beacf11bSopenharmony_ci saddr = rpc->rc_name; 675beacf11bSopenharmony_ci 676beacf11bSopenharmony_ci /* Create an instance of the socket state structure */ 677beacf11bSopenharmony_ci 678beacf11bSopenharmony_ci error = socket(saddr->sa_family, rpc->rc_sotype, NFS_PROTOTYPE); 679beacf11bSopenharmony_ci if (error < 0) 680beacf11bSopenharmony_ci { 681beacf11bSopenharmony_ci nfs_debug_error("psock_socket failed: %d", get_errno()); 682beacf11bSopenharmony_ci return -error; 683beacf11bSopenharmony_ci } 684beacf11bSopenharmony_ci 685beacf11bSopenharmony_ci rpc->rc_so = error; 686beacf11bSopenharmony_ci sin.sin_family = AF_INET; 687beacf11bSopenharmony_ci sin.sin_addr.s_addr = INADDR_ANY; 688beacf11bSopenharmony_ci trycount = RPCCLNT_CONNECT_MAX_RETRY_TIMES; 689beacf11bSopenharmony_ci 690beacf11bSopenharmony_ci do 691beacf11bSopenharmony_ci { 692beacf11bSopenharmony_ci errval = 0; 693beacf11bSopenharmony_ci trycount--; 694beacf11bSopenharmony_ci tport = random() % (RPCCONN_MAXPORT - RPCCONN_MINPORT) + RPCCONN_MINPORT; 695beacf11bSopenharmony_ci sin.sin_port = htons(tport); 696beacf11bSopenharmony_ci 697beacf11bSopenharmony_ci error = bind(rpc->rc_so, (struct sockaddr *)&sin, sizeof(sin)); 698beacf11bSopenharmony_ci if (error < 0) 699beacf11bSopenharmony_ci { 700beacf11bSopenharmony_ci errval = get_errno(); 701beacf11bSopenharmony_ci nfs_debug_error("psock_bind failed: %d\n", errval); 702beacf11bSopenharmony_ci } 703beacf11bSopenharmony_ci } 704beacf11bSopenharmony_ci while (errval == EADDRINUSE && trycount > 0); 705beacf11bSopenharmony_ci 706beacf11bSopenharmony_ci if (error) 707beacf11bSopenharmony_ci { 708beacf11bSopenharmony_ci nfs_debug_error("psock_bind failed: %d, port = %d\n", errval, tport); 709beacf11bSopenharmony_ci goto bad; 710beacf11bSopenharmony_ci } 711beacf11bSopenharmony_ci 712beacf11bSopenharmony_ci /* Protocols that do not require connections could be optionally left 713beacf11bSopenharmony_ci * unconnected. That would allow servers to reply from a port other than 714beacf11bSopenharmony_ci * the NFS_PORT. 715beacf11bSopenharmony_ci */ 716beacf11bSopenharmony_ci 717beacf11bSopenharmony_ci error = connect(rpc->rc_so, saddr, sizeof(*saddr)); 718beacf11bSopenharmony_ci if (error < 0) 719beacf11bSopenharmony_ci { 720beacf11bSopenharmony_ci error = get_errno(); 721beacf11bSopenharmony_ci nfs_debug_error("psock_connect to PMAP port failed: %d", error); 722beacf11bSopenharmony_ci goto bad; 723beacf11bSopenharmony_ci } 724beacf11bSopenharmony_ci 725beacf11bSopenharmony_ci /* Do the RPC to get a dynamic bounding with the server using ppmap. 726beacf11bSopenharmony_ci * Get port number for MOUNTD. 727beacf11bSopenharmony_ci */ 728beacf11bSopenharmony_ci 729beacf11bSopenharmony_ci request.sdata.pmap.prog = txdr_unsigned(RPCPROG_MNT); 730beacf11bSopenharmony_ci request.sdata.pmap.vers = txdr_unsigned(RPCMNT_VER3); 731beacf11bSopenharmony_ci request.sdata.pmap.proc = txdr_unsigned(NFS_PROTOTYPE); 732beacf11bSopenharmony_ci request.sdata.pmap.port = 0; 733beacf11bSopenharmony_ci 734beacf11bSopenharmony_ci error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, 735beacf11bSopenharmony_ci (void *)&request.sdata, sizeof(struct call_args_pmap), 736beacf11bSopenharmony_ci (void *)&response.rdata, sizeof(struct rpc_reply_pmap)); 737beacf11bSopenharmony_ci if (error != 0) 738beacf11bSopenharmony_ci { 739beacf11bSopenharmony_ci nfs_error("rpcclnt_request failed: %d\n", error); 740beacf11bSopenharmony_ci goto bad; 741beacf11bSopenharmony_ci } 742beacf11bSopenharmony_ci 743beacf11bSopenharmony_ci sa = (struct sockaddr_in *)saddr; 744beacf11bSopenharmony_ci sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port)); 745beacf11bSopenharmony_ci 746beacf11bSopenharmony_ci error = rpcclnt_reconnect(rpc, saddr); 747beacf11bSopenharmony_ci if (error != 0) 748beacf11bSopenharmony_ci { 749beacf11bSopenharmony_ci nfs_error("rpcclnt_reconnect failed: %d\n", error); 750beacf11bSopenharmony_ci goto bad; 751beacf11bSopenharmony_ci } 752beacf11bSopenharmony_ci 753beacf11bSopenharmony_ci /* Do RPC to mountd. */ 754beacf11bSopenharmony_ci 755beacf11bSopenharmony_ci error = memset_s(&request, sizeof(request), 0, sizeof(request)); 756beacf11bSopenharmony_ci if (error != EOK) 757beacf11bSopenharmony_ci { 758beacf11bSopenharmony_ci error = ENOBUFS; 759beacf11bSopenharmony_ci goto bad; 760beacf11bSopenharmony_ci } 761beacf11bSopenharmony_ci error = strncpy_s(request.mountd.mount.rpath, sizeof(request.mountd.mount.rpath), 762beacf11bSopenharmony_ci rpc->rc_path, RPC_RPATH_MAXSIZE - 1); 763beacf11bSopenharmony_ci if (error != EOK) 764beacf11bSopenharmony_ci { 765beacf11bSopenharmony_ci error = ENOBUFS; 766beacf11bSopenharmony_ci goto bad; 767beacf11bSopenharmony_ci } 768beacf11bSopenharmony_ci request.mountd.mount.len = txdr_unsigned(sizeof(request.mountd.mount.rpath)); 769beacf11bSopenharmony_ci 770beacf11bSopenharmony_ci error = rpcclnt_request(rpc, RPCMNT_MOUNT, RPCPROG_MNT, RPCMNT_VER3, 771beacf11bSopenharmony_ci (void *)&request.mountd, 772beacf11bSopenharmony_ci sizeof(struct call_args_mount), 773beacf11bSopenharmony_ci (void *)&response.mdata, 774beacf11bSopenharmony_ci sizeof(struct rpc_reply_mount)); 775beacf11bSopenharmony_ci if (error != 0) 776beacf11bSopenharmony_ci { 777beacf11bSopenharmony_ci nfs_error("rpcclnt_request failed: %d\n", error); 778beacf11bSopenharmony_ci goto bad; 779beacf11bSopenharmony_ci } 780beacf11bSopenharmony_ci 781beacf11bSopenharmony_ci error = fxdr_unsigned(uint32_t, response.mdata.mount.status); 782beacf11bSopenharmony_ci if (error != 0) 783beacf11bSopenharmony_ci { 784beacf11bSopenharmony_ci nfs_debug_error("Bad mount status: %d\n", error); 785beacf11bSopenharmony_ci goto bad; 786beacf11bSopenharmony_ci } 787beacf11bSopenharmony_ci 788beacf11bSopenharmony_ci rpc->rc_fhsize = fxdr_unsigned(uint32_t, response.mdata.mount.fhandle.length); 789beacf11bSopenharmony_ci memcpy(&rpc->rc_fh, &response.mdata.mount.fhandle.handle, rpc->rc_fhsize); 790beacf11bSopenharmony_ci 791beacf11bSopenharmony_ci /* Do the RPC to get a dynamic bounding with the server using PMAP. 792beacf11bSopenharmony_ci * NFS port in the socket. 793beacf11bSopenharmony_ci */ 794beacf11bSopenharmony_ci 795beacf11bSopenharmony_ci sa->sin_port = htons(PMAPPORT); 796beacf11bSopenharmony_ci 797beacf11bSopenharmony_ci error = rpcclnt_reconnect(rpc, saddr); 798beacf11bSopenharmony_ci if (error != 0) 799beacf11bSopenharmony_ci { 800beacf11bSopenharmony_ci nfs_error("rpcclnt_reconnect failed: %d\n", error); 801beacf11bSopenharmony_ci goto bad; 802beacf11bSopenharmony_ci } 803beacf11bSopenharmony_ci 804beacf11bSopenharmony_ci request.sdata.pmap.prog = txdr_unsigned(NFS_PROG); 805beacf11bSopenharmony_ci request.sdata.pmap.vers = txdr_unsigned(NFS_VER3); 806beacf11bSopenharmony_ci request.sdata.pmap.proc = txdr_unsigned(NFS_PROTOTYPE); 807beacf11bSopenharmony_ci request.sdata.pmap.port = 0; 808beacf11bSopenharmony_ci 809beacf11bSopenharmony_ci error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, 810beacf11bSopenharmony_ci (void *)&request.sdata, 811beacf11bSopenharmony_ci sizeof(struct call_args_pmap), 812beacf11bSopenharmony_ci (void *)&response.rdata, 813beacf11bSopenharmony_ci sizeof(struct rpc_reply_pmap)); 814beacf11bSopenharmony_ci if (error != 0) 815beacf11bSopenharmony_ci { 816beacf11bSopenharmony_ci nfs_error("rpcclnt_request failed: %d\n", error); 817beacf11bSopenharmony_ci goto bad; 818beacf11bSopenharmony_ci } 819beacf11bSopenharmony_ci 820beacf11bSopenharmony_ci sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port)); 821beacf11bSopenharmony_ci 822beacf11bSopenharmony_ci error = rpcclnt_reconnect(rpc, saddr); 823beacf11bSopenharmony_ci if (error != 0) 824beacf11bSopenharmony_ci { 825beacf11bSopenharmony_ci nfs_error("rpcclnt_reconnect failed: %d\n", error); 826beacf11bSopenharmony_ci goto bad; 827beacf11bSopenharmony_ci } 828beacf11bSopenharmony_ci 829beacf11bSopenharmony_ci return OK; 830beacf11bSopenharmony_ci 831beacf11bSopenharmony_cibad: 832beacf11bSopenharmony_ci rpcclnt_disconnect(rpc); 833beacf11bSopenharmony_ci return error; 834beacf11bSopenharmony_ci} 835beacf11bSopenharmony_ci 836beacf11bSopenharmony_ci/**************************************************************************** 837beacf11bSopenharmony_ci * Name: rpcclnt_disconnect 838beacf11bSopenharmony_ci * 839beacf11bSopenharmony_ci * Description: 840beacf11bSopenharmony_ci * Disconnect from the NFS server. 841beacf11bSopenharmony_ci * 842beacf11bSopenharmony_ci ****************************************************************************/ 843beacf11bSopenharmony_ci 844beacf11bSopenharmony_civoid rpcclnt_disconnect(struct rpcclnt *rpc) 845beacf11bSopenharmony_ci{ 846beacf11bSopenharmony_ci if (rpc->rc_so != -1) 847beacf11bSopenharmony_ci { 848beacf11bSopenharmony_ci (void)lwip_close(rpc->rc_so); 849beacf11bSopenharmony_ci rpc->rc_so = -1; 850beacf11bSopenharmony_ci } 851beacf11bSopenharmony_ci} 852beacf11bSopenharmony_ci 853beacf11bSopenharmony_ci/**************************************************************************** 854beacf11bSopenharmony_ci * Name: rpcclnt_umount 855beacf11bSopenharmony_ci * 856beacf11bSopenharmony_ci * Description: 857beacf11bSopenharmony_ci * Un-mount the NFS file system. 858beacf11bSopenharmony_ci * 859beacf11bSopenharmony_ci ****************************************************************************/ 860beacf11bSopenharmony_ci 861beacf11bSopenharmony_ciint rpcclnt_umount(struct rpcclnt *rpc) 862beacf11bSopenharmony_ci{ 863beacf11bSopenharmony_ci struct sockaddr *saddr; 864beacf11bSopenharmony_ci struct sockaddr_in *sa; 865beacf11bSopenharmony_ci 866beacf11bSopenharmony_ci union 867beacf11bSopenharmony_ci { 868beacf11bSopenharmony_ci struct rpc_call_pmap sdata; 869beacf11bSopenharmony_ci struct rpc_call_umount mountd; 870beacf11bSopenharmony_ci } request; 871beacf11bSopenharmony_ci 872beacf11bSopenharmony_ci union 873beacf11bSopenharmony_ci { 874beacf11bSopenharmony_ci struct rpc_reply_pmap rdata; 875beacf11bSopenharmony_ci struct rpc_reply_umount mdata; 876beacf11bSopenharmony_ci } response; 877beacf11bSopenharmony_ci 878beacf11bSopenharmony_ci int error; 879beacf11bSopenharmony_ci 880beacf11bSopenharmony_ci saddr = rpc->rc_name; 881beacf11bSopenharmony_ci sa = (struct sockaddr_in *)saddr; 882beacf11bSopenharmony_ci 883beacf11bSopenharmony_ci /* Do the RPC to get a dynamic bounding with the server using ppmap. 884beacf11bSopenharmony_ci * Get port number for MOUNTD. 885beacf11bSopenharmony_ci */ 886beacf11bSopenharmony_ci 887beacf11bSopenharmony_ci sa->sin_port = htons(PMAPPORT); 888beacf11bSopenharmony_ci 889beacf11bSopenharmony_ci error = rpcclnt_reconnect(rpc, saddr); 890beacf11bSopenharmony_ci if (error != 0) 891beacf11bSopenharmony_ci { 892beacf11bSopenharmony_ci nfs_error("rpcclnt_reconnect failed: %d\n", error); 893beacf11bSopenharmony_ci goto bad; 894beacf11bSopenharmony_ci } 895beacf11bSopenharmony_ci 896beacf11bSopenharmony_ci request.sdata.pmap.prog = txdr_unsigned(RPCPROG_MNT); 897beacf11bSopenharmony_ci request.sdata.pmap.vers = txdr_unsigned(RPCMNT_VER3); 898beacf11bSopenharmony_ci request.sdata.pmap.proc = txdr_unsigned(NFS_PROTOTYPE); 899beacf11bSopenharmony_ci request.sdata.pmap.port = 0; 900beacf11bSopenharmony_ci 901beacf11bSopenharmony_ci error = rpcclnt_request(rpc, PMAPPROC_GETPORT, PMAPPROG, PMAPVERS, 902beacf11bSopenharmony_ci (void *)&request.sdata, 903beacf11bSopenharmony_ci sizeof(struct call_args_pmap), 904beacf11bSopenharmony_ci (void *)&response.rdata, 905beacf11bSopenharmony_ci sizeof(struct rpc_reply_pmap)); 906beacf11bSopenharmony_ci if (error != 0) 907beacf11bSopenharmony_ci { 908beacf11bSopenharmony_ci nfs_error("rpcclnt_request failed: %d\n", error); 909beacf11bSopenharmony_ci goto bad; 910beacf11bSopenharmony_ci } 911beacf11bSopenharmony_ci 912beacf11bSopenharmony_ci sa->sin_port = htons(fxdr_unsigned(uint32_t, response.rdata.pmap.port)); 913beacf11bSopenharmony_ci 914beacf11bSopenharmony_ci error = rpcclnt_reconnect(rpc, saddr); 915beacf11bSopenharmony_ci if (error != 0) 916beacf11bSopenharmony_ci { 917beacf11bSopenharmony_ci nfs_error("rpcclnt_reconnect failed: %d\n", error); 918beacf11bSopenharmony_ci goto bad; 919beacf11bSopenharmony_ci } 920beacf11bSopenharmony_ci 921beacf11bSopenharmony_ci /* Do RPC to umountd. */ 922beacf11bSopenharmony_ci 923beacf11bSopenharmony_ci (void)strncpy_s(request.mountd.umount.rpath, sizeof(request.mountd.umount.rpath), 924beacf11bSopenharmony_ci rpc->rc_path, sizeof(request.mountd.umount.rpath) - 1); 925beacf11bSopenharmony_ci request.mountd.umount.rpath[sizeof(request.mountd.umount.rpath) - 1] = 0; 926beacf11bSopenharmony_ci request.mountd.umount.len = txdr_unsigned(sizeof(request.mountd.umount.rpath)); 927beacf11bSopenharmony_ci 928beacf11bSopenharmony_ci error = rpcclnt_request(rpc, RPCMNT_UMOUNT, RPCPROG_MNT, RPCMNT_VER3, 929beacf11bSopenharmony_ci (void *)&request.mountd, 930beacf11bSopenharmony_ci sizeof(struct call_args_umount), 931beacf11bSopenharmony_ci (void *)&response.mdata, 932beacf11bSopenharmony_ci sizeof(struct rpc_reply_umount)); 933beacf11bSopenharmony_ci if (error != 0) 934beacf11bSopenharmony_ci { 935beacf11bSopenharmony_ci nfs_error("rpcclnt_request failed: %d\n", error); 936beacf11bSopenharmony_ci goto bad; 937beacf11bSopenharmony_ci } 938beacf11bSopenharmony_ci 939beacf11bSopenharmony_ci return OK; 940beacf11bSopenharmony_ci 941beacf11bSopenharmony_cibad: 942beacf11bSopenharmony_ci 943beacf11bSopenharmony_ci /* No need to close the socket here, if umount failed. user has to call nfs_unbind again */ 944beacf11bSopenharmony_ci 945beacf11bSopenharmony_ci return error; 946beacf11bSopenharmony_ci} 947beacf11bSopenharmony_ci 948beacf11bSopenharmony_ci/**************************************************************************** 949beacf11bSopenharmony_ci * Name: rpcclnt_request 950beacf11bSopenharmony_ci * 951beacf11bSopenharmony_ci * Description: 952beacf11bSopenharmony_ci * Perform the RPC request. Logic formats the RPC CALL message and calls 953beacf11bSopenharmony_ci * rpcclnt_send to send the RPC CALL message. It then calls rpcclnt_reply() 954beacf11bSopenharmony_ci * to get the response. It may attempt to re-send the CALL message on 955beacf11bSopenharmony_ci * certain errors. 956beacf11bSopenharmony_ci * 957beacf11bSopenharmony_ci * On successful receipt, it verifies the RPC level of the returned values. 958beacf11bSopenharmony_ci * (There may still be be NFS layer errors that will be deted by calling 959beacf11bSopenharmony_ci * logic). 960beacf11bSopenharmony_ci * 961beacf11bSopenharmony_ci ****************************************************************************/ 962beacf11bSopenharmony_ci 963beacf11bSopenharmony_ciint rpcclnt_request(struct rpcclnt *rpc, int procnum, int prog, 964beacf11bSopenharmony_ci int version, void *request, size_t reqlen, 965beacf11bSopenharmony_ci void *response, size_t resplen) 966beacf11bSopenharmony_ci{ 967beacf11bSopenharmony_ci struct rpc_reply_header *replymsg; 968beacf11bSopenharmony_ci uint32_t tmp; 969beacf11bSopenharmony_ci#if (NFS_PROTO_TYPE == NFS_IPPROTO_UDP) 970beacf11bSopenharmony_ci int retries; 971beacf11bSopenharmony_ci#endif 972beacf11bSopenharmony_ci int error = 0; 973beacf11bSopenharmony_ci 974beacf11bSopenharmony_ci /* Get a new (non-zero) xid */ 975beacf11bSopenharmony_ci 976beacf11bSopenharmony_ci rpc->xid = rpcclnt_newxid(); 977beacf11bSopenharmony_ci 978beacf11bSopenharmony_ci /* Get the full size of the message (the size of variable data plus the size of 979beacf11bSopenharmony_ci * the messages header). 980beacf11bSopenharmony_ci */ 981beacf11bSopenharmony_ci 982beacf11bSopenharmony_ci reqlen += sizeof(struct rpc_call_header); 983beacf11bSopenharmony_ci 984beacf11bSopenharmony_ci /* Initialize the RPC header fields */ 985beacf11bSopenharmony_ci 986beacf11bSopenharmony_ci rpcclnt_fmtheader((struct rpc_call_header *)request, 987beacf11bSopenharmony_ci rpc->xid, prog, version, procnum, reqlen); 988beacf11bSopenharmony_ci 989beacf11bSopenharmony_ci /* Send the RPC call messsages and receive the RPC response. For UDP-RPC, A limited 990beacf11bSopenharmony_ci * number of re-tries will be attempted, but only for the case of response 991beacf11bSopenharmony_ci * timeouts. While for TCP-RPC, no retry attempted. 992beacf11bSopenharmony_ci */ 993beacf11bSopenharmony_ci 994beacf11bSopenharmony_ci#if (NFS_PROTO_TYPE == NFS_IPPROTO_UDP) 995beacf11bSopenharmony_ci retries = 0; 996beacf11bSopenharmony_ci do 997beacf11bSopenharmony_ci { 998beacf11bSopenharmony_ci /* Do the client side RPC. */ 999beacf11bSopenharmony_ci 1000beacf11bSopenharmony_ci rpc_statistics(rpcrequests); 1001beacf11bSopenharmony_ci rpc->rc_timeout = false; 1002beacf11bSopenharmony_ci 1003beacf11bSopenharmony_ci /* Send the RPC CALL message */ 1004beacf11bSopenharmony_ci 1005beacf11bSopenharmony_ci error = rpcclnt_send(rpc, procnum, prog, request, reqlen); 1006beacf11bSopenharmony_ci if (error != OK) 1007beacf11bSopenharmony_ci { 1008beacf11bSopenharmony_ci nfs_debug_info("ERROR rpcclnt_send failed: %d\n", error); 1009beacf11bSopenharmony_ci } 1010beacf11bSopenharmony_ci 1011beacf11bSopenharmony_ci /* Wait for the reply from our send */ 1012beacf11bSopenharmony_ci 1013beacf11bSopenharmony_ci else 1014beacf11bSopenharmony_ci { 1015beacf11bSopenharmony_ci error = rpcclnt_reply(rpc, procnum, prog, response, resplen); 1016beacf11bSopenharmony_ci if (error != OK) 1017beacf11bSopenharmony_ci { 1018beacf11bSopenharmony_ci nfs_debug_info("ERROR rpcclnt_reply failed: %d\n", error); 1019beacf11bSopenharmony_ci } 1020beacf11bSopenharmony_ci } 1021beacf11bSopenharmony_ci 1022beacf11bSopenharmony_ci retries++; 1023beacf11bSopenharmony_ci } 1024beacf11bSopenharmony_ci while (rpc->rc_timeout && retries <= rpc->rc_retry); 1025beacf11bSopenharmony_ci 1026beacf11bSopenharmony_ci if (error != OK) 1027beacf11bSopenharmony_ci { 1028beacf11bSopenharmony_ci nfs_debug_error("RPC failed: %d\n", error); 1029beacf11bSopenharmony_ci return error; 1030beacf11bSopenharmony_ci } 1031beacf11bSopenharmony_ci 1032beacf11bSopenharmony_ci#else 1033beacf11bSopenharmony_ci 1034beacf11bSopenharmony_ci /* check tcp connection alive or not as server would close connection if long time no data transfer */ 1035beacf11bSopenharmony_ci 1036beacf11bSopenharmony_ci if (rpc->rc_so != -1) 1037beacf11bSopenharmony_ci { 1038beacf11bSopenharmony_ci error = rpcclnt_alivecheck(rpc); 1039beacf11bSopenharmony_ci if (error != OK) 1040beacf11bSopenharmony_ci { 1041beacf11bSopenharmony_ci nfs_debug_error("rpc_alivecheck failed: %d\n", error); 1042beacf11bSopenharmony_ci return error; 1043beacf11bSopenharmony_ci } 1044beacf11bSopenharmony_ci } 1045beacf11bSopenharmony_ci 1046beacf11bSopenharmony_ci /* reconnect due to previous connection down */ 1047beacf11bSopenharmony_ci 1048beacf11bSopenharmony_ci if (rpc->rc_so == -1) 1049beacf11bSopenharmony_ci { 1050beacf11bSopenharmony_ci error = rpcclnt_reconnect(rpc, rpc->rc_name); 1051beacf11bSopenharmony_ci if (error != OK) 1052beacf11bSopenharmony_ci { 1053beacf11bSopenharmony_ci nfs_debug_error("rpcclnt_send failed: %d\n", error); 1054beacf11bSopenharmony_ci return error; 1055beacf11bSopenharmony_ci } 1056beacf11bSopenharmony_ci } 1057beacf11bSopenharmony_ci 1058beacf11bSopenharmony_ci rpc_statistics(rpcrequests); 1059beacf11bSopenharmony_ci 1060beacf11bSopenharmony_ci /* Send the RPC CALL message */ 1061beacf11bSopenharmony_ci 1062beacf11bSopenharmony_ci error = rpcclnt_send(rpc, procnum, prog, request, reqlen); 1063beacf11bSopenharmony_ci if (error != OK) 1064beacf11bSopenharmony_ci { 1065beacf11bSopenharmony_ci rpcclnt_disconnect(rpc); 1066beacf11bSopenharmony_ci nfs_debug_error("rpcclnt_send failed: %d\n", error); 1067beacf11bSopenharmony_ci return error; 1068beacf11bSopenharmony_ci } 1069beacf11bSopenharmony_ci 1070beacf11bSopenharmony_ci /* Wait for the reply from our send */ 1071beacf11bSopenharmony_ci 1072beacf11bSopenharmony_ci error = rpcclnt_reply(rpc, procnum, prog, response, resplen); 1073beacf11bSopenharmony_ci if (error != OK) 1074beacf11bSopenharmony_ci { 1075beacf11bSopenharmony_ci rpcclnt_disconnect(rpc); 1076beacf11bSopenharmony_ci nfs_debug_error("rpcclnt_reply failed: %d\n", error); 1077beacf11bSopenharmony_ci return error; 1078beacf11bSopenharmony_ci } 1079beacf11bSopenharmony_ci 1080beacf11bSopenharmony_ci#endif 1081beacf11bSopenharmony_ci 1082beacf11bSopenharmony_ci /* Break down the RPC header and check if it is OK */ 1083beacf11bSopenharmony_ci 1084beacf11bSopenharmony_ci replymsg = (struct rpc_reply_header *)response; 1085beacf11bSopenharmony_ci 1086beacf11bSopenharmony_ci tmp = fxdr_unsigned(uint32_t, replymsg->type); 1087beacf11bSopenharmony_ci if (tmp == RPC_MSGDENIED) 1088beacf11bSopenharmony_ci { 1089beacf11bSopenharmony_ci tmp = fxdr_unsigned(uint32_t, replymsg->status); 1090beacf11bSopenharmony_ci switch (tmp) 1091beacf11bSopenharmony_ci { 1092beacf11bSopenharmony_ci case RPC_MISMATCH: 1093beacf11bSopenharmony_ci nfs_debug_error("RPC_MSGDENIED: RPC_MISMATCH error\n"); 1094beacf11bSopenharmony_ci return EOPNOTSUPP; 1095beacf11bSopenharmony_ci 1096beacf11bSopenharmony_ci case RPC_AUTHERR: 1097beacf11bSopenharmony_ci nfs_debug_error("RPC_MSGDENIED: RPC_AUTHERR error\n"); 1098beacf11bSopenharmony_ci return EACCES; 1099beacf11bSopenharmony_ci 1100beacf11bSopenharmony_ci default: 1101beacf11bSopenharmony_ci return EOPNOTSUPP; 1102beacf11bSopenharmony_ci } 1103beacf11bSopenharmony_ci } 1104beacf11bSopenharmony_ci else if (tmp != RPC_MSGACCEPTED) 1105beacf11bSopenharmony_ci { 1106beacf11bSopenharmony_ci return EOPNOTSUPP; 1107beacf11bSopenharmony_ci } 1108beacf11bSopenharmony_ci 1109beacf11bSopenharmony_ci tmp = fxdr_unsigned(uint32_t, replymsg->status); 1110beacf11bSopenharmony_ci if (tmp == RPC_SUCCESS) 1111beacf11bSopenharmony_ci { 1112beacf11bSopenharmony_ci nfs_debug_info("RPC_SUCCESS\n"); 1113beacf11bSopenharmony_ci } 1114beacf11bSopenharmony_ci else if (tmp == RPC_PROGMISMATCH) 1115beacf11bSopenharmony_ci { 1116beacf11bSopenharmony_ci nfs_debug_error("RPC_MSGACCEPTED: RPC_PROGMISMATCH error\n"); 1117beacf11bSopenharmony_ci return EOPNOTSUPP; 1118beacf11bSopenharmony_ci } 1119beacf11bSopenharmony_ci else if (tmp > 5) 1120beacf11bSopenharmony_ci { 1121beacf11bSopenharmony_ci nfs_debug_error("Unsupported RPC type: %d\n", tmp); 1122beacf11bSopenharmony_ci return EOPNOTSUPP; 1123beacf11bSopenharmony_ci } 1124beacf11bSopenharmony_ci 1125beacf11bSopenharmony_ci return OK; 1126beacf11bSopenharmony_ci} 1127beacf11bSopenharmony_ci 1128beacf11bSopenharmony_civoid rpcclnt_setuidgid(uint32_t uid, uint32_t gid) 1129beacf11bSopenharmony_ci{ 1130beacf11bSopenharmony_ci nfs_uid = uid; 1131beacf11bSopenharmony_ci nfs_gid = gid; 1132beacf11bSopenharmony_ci} 1133