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