nfs_commonsubs.c revision 1.1.1.1.4.2 1 1.1.1.1.4.2 rmind /* $NetBSD: nfs_commonsubs.c,v 1.1.1.1.4.2 2014/05/18 17:46:05 rmind Exp $ */
2 1.1.1.1.4.2 rmind /*-
3 1.1.1.1.4.2 rmind * Copyright (c) 1989, 1993
4 1.1.1.1.4.2 rmind * The Regents of the University of California. All rights reserved.
5 1.1.1.1.4.2 rmind *
6 1.1.1.1.4.2 rmind * This code is derived from software contributed to Berkeley by
7 1.1.1.1.4.2 rmind * Rick Macklem at The University of Guelph.
8 1.1.1.1.4.2 rmind *
9 1.1.1.1.4.2 rmind * Redistribution and use in source and binary forms, with or without
10 1.1.1.1.4.2 rmind * modification, are permitted provided that the following conditions
11 1.1.1.1.4.2 rmind * are met:
12 1.1.1.1.4.2 rmind * 1. Redistributions of source code must retain the above copyright
13 1.1.1.1.4.2 rmind * notice, this list of conditions and the following disclaimer.
14 1.1.1.1.4.2 rmind * 2. Redistributions in binary form must reproduce the above copyright
15 1.1.1.1.4.2 rmind * notice, this list of conditions and the following disclaimer in the
16 1.1.1.1.4.2 rmind * documentation and/or other materials provided with the distribution.
17 1.1.1.1.4.2 rmind * 4. Neither the name of the University nor the names of its contributors
18 1.1.1.1.4.2 rmind * may be used to endorse or promote products derived from this software
19 1.1.1.1.4.2 rmind * without specific prior written permission.
20 1.1.1.1.4.2 rmind *
21 1.1.1.1.4.2 rmind * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 1.1.1.1.4.2 rmind * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 1.1.1.1.4.2 rmind * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 1.1.1.1.4.2 rmind * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 1.1.1.1.4.2 rmind * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 1.1.1.1.4.2 rmind * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 1.1.1.1.4.2 rmind * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 1.1.1.1.4.2 rmind * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 1.1.1.1.4.2 rmind * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 1.1.1.1.4.2 rmind * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 1.1.1.1.4.2 rmind * SUCH DAMAGE.
32 1.1.1.1.4.2 rmind *
33 1.1.1.1.4.2 rmind */
34 1.1.1.1.4.2 rmind
35 1.1.1.1.4.2 rmind #include <sys/cdefs.h>
36 1.1.1.1.4.2 rmind /* __FBSDID("FreeBSD: head/sys/fs/nfs/nfs_commonsubs.c 253506 2013-07-20 22:35:32Z rmacklem "); */
37 1.1.1.1.4.2 rmind __RCSID("$NetBSD: nfs_commonsubs.c,v 1.1.1.1.4.2 2014/05/18 17:46:05 rmind Exp $");
38 1.1.1.1.4.2 rmind
39 1.1.1.1.4.2 rmind /*
40 1.1.1.1.4.2 rmind * These functions support the macros and help fiddle mbuf chains for
41 1.1.1.1.4.2 rmind * the nfs op functions. They do things like create the rpc header and
42 1.1.1.1.4.2 rmind * copy data between mbuf chains and uio lists.
43 1.1.1.1.4.2 rmind */
44 1.1.1.1.4.2 rmind #ifndef APPLEKEXT
45 1.1.1.1.4.2 rmind #include "opt_inet6.h"
46 1.1.1.1.4.2 rmind
47 1.1.1.1.4.2 rmind #include <fs/nfs/nfsport.h>
48 1.1.1.1.4.2 rmind
49 1.1.1.1.4.2 rmind /*
50 1.1.1.1.4.2 rmind * Data items converted to xdr at startup, since they are constant
51 1.1.1.1.4.2 rmind * This is kinda hokey, but may save a little time doing byte swaps
52 1.1.1.1.4.2 rmind */
53 1.1.1.1.4.2 rmind u_int32_t newnfs_true, newnfs_false, newnfs_xdrneg1;
54 1.1.1.1.4.2 rmind
55 1.1.1.1.4.2 rmind /* And other global data */
56 1.1.1.1.4.2 rmind nfstype nfsv34_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,
57 1.1.1.1.4.2 rmind NFFIFO, NFNON };
58 1.1.1.1.4.2 rmind enum vtype newnv2tov_type[8] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON };
59 1.1.1.1.4.2 rmind enum vtype nv34tov_type[8]={ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO };
60 1.1.1.1.4.2 rmind struct timeval nfsboottime; /* Copy boottime once, so it never changes */
61 1.1.1.1.4.2 rmind int nfscl_ticks;
62 1.1.1.1.4.2 rmind int nfsrv_useacl = 1;
63 1.1.1.1.4.2 rmind struct nfssockreq nfsrv_nfsuserdsock;
64 1.1.1.1.4.2 rmind int nfsrv_nfsuserd = 0;
65 1.1.1.1.4.2 rmind struct nfsreqhead nfsd_reqq;
66 1.1.1.1.4.2 rmind uid_t nfsrv_defaultuid;
67 1.1.1.1.4.2 rmind gid_t nfsrv_defaultgid;
68 1.1.1.1.4.2 rmind int nfsrv_lease = NFSRV_LEASE;
69 1.1.1.1.4.2 rmind int ncl_mbuf_mlen = MLEN;
70 1.1.1.1.4.2 rmind NFSNAMEIDMUTEX;
71 1.1.1.1.4.2 rmind NFSSOCKMUTEX;
72 1.1.1.1.4.2 rmind
73 1.1.1.1.4.2 rmind /*
74 1.1.1.1.4.2 rmind * This array of structures indicates, for V4:
75 1.1.1.1.4.2 rmind * retfh - which of 3 types of calling args are used
76 1.1.1.1.4.2 rmind * 0 - doesn't change cfh or use a sfh
77 1.1.1.1.4.2 rmind * 1 - replaces cfh with a new one (unless it returns an error status)
78 1.1.1.1.4.2 rmind * 2 - uses cfh and sfh
79 1.1.1.1.4.2 rmind * needscfh - if the op wants a cfh and premtime
80 1.1.1.1.4.2 rmind * 0 - doesn't use a cfh
81 1.1.1.1.4.2 rmind * 1 - uses a cfh, but doesn't want pre-op attributes
82 1.1.1.1.4.2 rmind * 2 - uses a cfh and wants pre-op attributes
83 1.1.1.1.4.2 rmind * savereply - indicates a non-idempotent Op
84 1.1.1.1.4.2 rmind * 0 - not non-idempotent
85 1.1.1.1.4.2 rmind * 1 - non-idempotent
86 1.1.1.1.4.2 rmind * Ops that are ordered via seqid# are handled separately from these
87 1.1.1.1.4.2 rmind * non-idempotent Ops.
88 1.1.1.1.4.2 rmind * Define it here, since it is used by both the client and server.
89 1.1.1.1.4.2 rmind */
90 1.1.1.1.4.2 rmind struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS] = {
91 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* undef */
92 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* undef */
93 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* undef */
94 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_SHARED, 1 }, /* Access */
95 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Close */
96 1.1.1.1.4.2 rmind { 0, 2, 0, 1, LK_EXCLUSIVE, 1 }, /* Commit */
97 1.1.1.1.4.2 rmind { 1, 2, 1, 1, LK_EXCLUSIVE, 1 }, /* Create */
98 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Delegpurge */
99 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Delegreturn */
100 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_SHARED, 1 }, /* Getattr */
101 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* GetFH */
102 1.1.1.1.4.2 rmind { 2, 1, 1, 1, LK_EXCLUSIVE, 1 }, /* Link */
103 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Lock */
104 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* LockT */
105 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* LockU */
106 1.1.1.1.4.2 rmind { 1, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Lookup */
107 1.1.1.1.4.2 rmind { 1, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Lookupp */
108 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* NVerify */
109 1.1.1.1.4.2 rmind { 1, 1, 0, 1, LK_EXCLUSIVE, 1 }, /* Open */
110 1.1.1.1.4.2 rmind { 1, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* OpenAttr */
111 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* OpenConfirm */
112 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* OpenDowngrade */
113 1.1.1.1.4.2 rmind { 1, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* PutFH */
114 1.1.1.1.4.2 rmind { 1, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* PutPubFH */
115 1.1.1.1.4.2 rmind { 1, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* PutRootFH */
116 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_SHARED, 1 }, /* Read */
117 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_SHARED, 1 }, /* Readdir */
118 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_SHARED, 1 }, /* ReadLink */
119 1.1.1.1.4.2 rmind { 0, 2, 1, 1, LK_EXCLUSIVE, 1 }, /* Remove */
120 1.1.1.1.4.2 rmind { 2, 1, 1, 1, LK_EXCLUSIVE, 1 }, /* Rename */
121 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Renew */
122 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* RestoreFH */
123 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* SaveFH */
124 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* SecInfo */
125 1.1.1.1.4.2 rmind { 0, 2, 1, 1, LK_EXCLUSIVE, 1 }, /* Setattr */
126 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* SetClientID */
127 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* SetClientIDConfirm */
128 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Verify */
129 1.1.1.1.4.2 rmind { 0, 2, 1, 1, LK_EXCLUSIVE, 1 }, /* Write */
130 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* ReleaseLockOwner */
131 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Backchannel Ctrl */
132 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Bind Conn to Sess */
133 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 0 }, /* Exchange ID */
134 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 0 }, /* Create Session */
135 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 0 }, /* Destroy Session */
136 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Free StateID */
137 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Get Dir Deleg */
138 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Get Device Info */
139 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Get Device List */
140 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Layout Commit */
141 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Layout Get */
142 1.1.1.1.4.2 rmind { 0, 1, 0, 0, LK_EXCLUSIVE, 1 }, /* Layout Return */
143 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Secinfo No name */
144 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Sequence */
145 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Set SSV */
146 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Test StateID */
147 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Want Delegation */
148 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 0 }, /* Destroy ClientID */
149 1.1.1.1.4.2 rmind { 0, 0, 0, 0, LK_EXCLUSIVE, 1 }, /* Reclaim Complete */
150 1.1.1.1.4.2 rmind };
151 1.1.1.1.4.2 rmind #endif /* !APPLEKEXT */
152 1.1.1.1.4.2 rmind
153 1.1.1.1.4.2 rmind static int ncl_mbuf_mhlen = MHLEN;
154 1.1.1.1.4.2 rmind static int nfsrv_usercnt = 0;
155 1.1.1.1.4.2 rmind static int nfsrv_dnsnamelen;
156 1.1.1.1.4.2 rmind static u_char *nfsrv_dnsname = NULL;
157 1.1.1.1.4.2 rmind static int nfsrv_usermax = 999999999;
158 1.1.1.1.4.2 rmind static struct nfsuserhashhead nfsuserhash[NFSUSERHASHSIZE];
159 1.1.1.1.4.2 rmind static struct nfsuserhashhead nfsusernamehash[NFSUSERHASHSIZE];
160 1.1.1.1.4.2 rmind static struct nfsuserhashhead nfsgrouphash[NFSGROUPHASHSIZE];
161 1.1.1.1.4.2 rmind static struct nfsuserhashhead nfsgroupnamehash[NFSGROUPHASHSIZE];
162 1.1.1.1.4.2 rmind static struct nfsuserlruhead nfsuserlruhead;
163 1.1.1.1.4.2 rmind
164 1.1.1.1.4.2 rmind /*
165 1.1.1.1.4.2 rmind * This static array indicates whether or not the RPC generates a large
166 1.1.1.1.4.2 rmind * reply. This is used by nfs_reply() to decide whether or not an mbuf
167 1.1.1.1.4.2 rmind * cluster should be allocated. (If a cluster is required by an RPC
168 1.1.1.1.4.2 rmind * marked 0 in this array, the code will still work, just not quite as
169 1.1.1.1.4.2 rmind * efficiently.)
170 1.1.1.1.4.2 rmind */
171 1.1.1.1.4.2 rmind int nfs_bigreply[NFSV41_NPROCS] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0,
172 1.1.1.1.4.2 rmind 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
173 1.1.1.1.4.2 rmind 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 };
174 1.1.1.1.4.2 rmind
175 1.1.1.1.4.2 rmind /* local functions */
176 1.1.1.1.4.2 rmind static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep);
177 1.1.1.1.4.2 rmind static void nfsv4_wanted(struct nfsv4lock *lp);
178 1.1.1.1.4.2 rmind static int nfsrv_cmpmixedcase(u_char *cp, u_char *cp2, int len);
179 1.1.1.1.4.2 rmind static int nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name,
180 1.1.1.1.4.2 rmind NFSPROC_T *p);
181 1.1.1.1.4.2 rmind static void nfsrv_removeuser(struct nfsusrgrp *usrp);
182 1.1.1.1.4.2 rmind static int nfsrv_getrefstr(struct nfsrv_descript *, u_char **, u_char **,
183 1.1.1.1.4.2 rmind int *, int *);
184 1.1.1.1.4.2 rmind static void nfsrv_refstrbigenough(int, u_char **, u_char **, int *);
185 1.1.1.1.4.2 rmind
186 1.1.1.1.4.2 rmind
187 1.1.1.1.4.2 rmind #ifndef APPLE
188 1.1.1.1.4.2 rmind /*
189 1.1.1.1.4.2 rmind * copies mbuf chain to the uio scatter/gather list
190 1.1.1.1.4.2 rmind */
191 1.1.1.1.4.2 rmind int
192 1.1.1.1.4.2 rmind nfsm_mbufuio(struct nfsrv_descript *nd, struct uio *uiop, int siz)
193 1.1.1.1.4.2 rmind {
194 1.1.1.1.4.2 rmind char *mbufcp, *uiocp;
195 1.1.1.1.4.2 rmind int xfer, left, len;
196 1.1.1.1.4.2 rmind mbuf_t mp;
197 1.1.1.1.4.2 rmind long uiosiz, rem;
198 1.1.1.1.4.2 rmind int error = 0;
199 1.1.1.1.4.2 rmind
200 1.1.1.1.4.2 rmind mp = nd->nd_md;
201 1.1.1.1.4.2 rmind mbufcp = nd->nd_dpos;
202 1.1.1.1.4.2 rmind len = NFSMTOD(mp, caddr_t) + mbuf_len(mp) - mbufcp;
203 1.1.1.1.4.2 rmind rem = NFSM_RNDUP(siz) - siz;
204 1.1.1.1.4.2 rmind while (siz > 0) {
205 1.1.1.1.4.2 rmind if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) {
206 1.1.1.1.4.2 rmind error = EBADRPC;
207 1.1.1.1.4.2 rmind goto out;
208 1.1.1.1.4.2 rmind }
209 1.1.1.1.4.2 rmind left = uiop->uio_iov->iov_len;
210 1.1.1.1.4.2 rmind uiocp = uiop->uio_iov->iov_base;
211 1.1.1.1.4.2 rmind if (left > siz)
212 1.1.1.1.4.2 rmind left = siz;
213 1.1.1.1.4.2 rmind uiosiz = left;
214 1.1.1.1.4.2 rmind while (left > 0) {
215 1.1.1.1.4.2 rmind while (len == 0) {
216 1.1.1.1.4.2 rmind mp = mbuf_next(mp);
217 1.1.1.1.4.2 rmind if (mp == NULL) {
218 1.1.1.1.4.2 rmind error = EBADRPC;
219 1.1.1.1.4.2 rmind goto out;
220 1.1.1.1.4.2 rmind }
221 1.1.1.1.4.2 rmind mbufcp = NFSMTOD(mp, caddr_t);
222 1.1.1.1.4.2 rmind len = mbuf_len(mp);
223 1.1.1.1.4.2 rmind KASSERT(len > 0, ("len %d", len));
224 1.1.1.1.4.2 rmind }
225 1.1.1.1.4.2 rmind xfer = (left > len) ? len : left;
226 1.1.1.1.4.2 rmind #ifdef notdef
227 1.1.1.1.4.2 rmind /* Not Yet.. */
228 1.1.1.1.4.2 rmind if (uiop->uio_iov->iov_op != NULL)
229 1.1.1.1.4.2 rmind (*(uiop->uio_iov->iov_op))
230 1.1.1.1.4.2 rmind (mbufcp, uiocp, xfer);
231 1.1.1.1.4.2 rmind else
232 1.1.1.1.4.2 rmind #endif
233 1.1.1.1.4.2 rmind if (uiop->uio_segflg == UIO_SYSSPACE)
234 1.1.1.1.4.2 rmind NFSBCOPY(mbufcp, uiocp, xfer);
235 1.1.1.1.4.2 rmind else
236 1.1.1.1.4.2 rmind copyout(mbufcp, CAST_USER_ADDR_T(uiocp), xfer);
237 1.1.1.1.4.2 rmind left -= xfer;
238 1.1.1.1.4.2 rmind len -= xfer;
239 1.1.1.1.4.2 rmind mbufcp += xfer;
240 1.1.1.1.4.2 rmind uiocp += xfer;
241 1.1.1.1.4.2 rmind uiop->uio_offset += xfer;
242 1.1.1.1.4.2 rmind uiop->uio_resid -= xfer;
243 1.1.1.1.4.2 rmind }
244 1.1.1.1.4.2 rmind if (uiop->uio_iov->iov_len <= siz) {
245 1.1.1.1.4.2 rmind uiop->uio_iovcnt--;
246 1.1.1.1.4.2 rmind uiop->uio_iov++;
247 1.1.1.1.4.2 rmind } else {
248 1.1.1.1.4.2 rmind uiop->uio_iov->iov_base = (void *)
249 1.1.1.1.4.2 rmind ((char *)uiop->uio_iov->iov_base + uiosiz);
250 1.1.1.1.4.2 rmind uiop->uio_iov->iov_len -= uiosiz;
251 1.1.1.1.4.2 rmind }
252 1.1.1.1.4.2 rmind siz -= uiosiz;
253 1.1.1.1.4.2 rmind }
254 1.1.1.1.4.2 rmind nd->nd_dpos = mbufcp;
255 1.1.1.1.4.2 rmind nd->nd_md = mp;
256 1.1.1.1.4.2 rmind if (rem > 0) {
257 1.1.1.1.4.2 rmind if (len < rem)
258 1.1.1.1.4.2 rmind error = nfsm_advance(nd, rem, len);
259 1.1.1.1.4.2 rmind else
260 1.1.1.1.4.2 rmind nd->nd_dpos += rem;
261 1.1.1.1.4.2 rmind }
262 1.1.1.1.4.2 rmind
263 1.1.1.1.4.2 rmind out:
264 1.1.1.1.4.2 rmind NFSEXITCODE2(error, nd);
265 1.1.1.1.4.2 rmind return (error);
266 1.1.1.1.4.2 rmind }
267 1.1.1.1.4.2 rmind #endif /* !APPLE */
268 1.1.1.1.4.2 rmind
269 1.1.1.1.4.2 rmind /*
270 1.1.1.1.4.2 rmind * Help break down an mbuf chain by setting the first siz bytes contiguous
271 1.1.1.1.4.2 rmind * pointed to by returned val.
272 1.1.1.1.4.2 rmind * This is used by the macro NFSM_DISSECT for tough
273 1.1.1.1.4.2 rmind * cases.
274 1.1.1.1.4.2 rmind */
275 1.1.1.1.4.2 rmind APPLESTATIC void *
276 1.1.1.1.4.2 rmind nfsm_dissct(struct nfsrv_descript *nd, int siz, int how)
277 1.1.1.1.4.2 rmind {
278 1.1.1.1.4.2 rmind mbuf_t mp2;
279 1.1.1.1.4.2 rmind int siz2, xfer;
280 1.1.1.1.4.2 rmind caddr_t p;
281 1.1.1.1.4.2 rmind int left;
282 1.1.1.1.4.2 rmind caddr_t retp;
283 1.1.1.1.4.2 rmind
284 1.1.1.1.4.2 rmind retp = NULL;
285 1.1.1.1.4.2 rmind left = NFSMTOD(nd->nd_md, caddr_t) + mbuf_len(nd->nd_md) - nd->nd_dpos;
286 1.1.1.1.4.2 rmind while (left == 0) {
287 1.1.1.1.4.2 rmind nd->nd_md = mbuf_next(nd->nd_md);
288 1.1.1.1.4.2 rmind if (nd->nd_md == NULL)
289 1.1.1.1.4.2 rmind return (retp);
290 1.1.1.1.4.2 rmind left = mbuf_len(nd->nd_md);
291 1.1.1.1.4.2 rmind nd->nd_dpos = NFSMTOD(nd->nd_md, caddr_t);
292 1.1.1.1.4.2 rmind }
293 1.1.1.1.4.2 rmind if (left >= siz) {
294 1.1.1.1.4.2 rmind retp = nd->nd_dpos;
295 1.1.1.1.4.2 rmind nd->nd_dpos += siz;
296 1.1.1.1.4.2 rmind } else if (mbuf_next(nd->nd_md) == NULL) {
297 1.1.1.1.4.2 rmind return (retp);
298 1.1.1.1.4.2 rmind } else if (siz > ncl_mbuf_mhlen) {
299 1.1.1.1.4.2 rmind panic("nfs S too big");
300 1.1.1.1.4.2 rmind } else {
301 1.1.1.1.4.2 rmind MGET(mp2, MT_DATA, how);
302 1.1.1.1.4.2 rmind if (mp2 == NULL)
303 1.1.1.1.4.2 rmind return (NULL);
304 1.1.1.1.4.2 rmind mbuf_setnext(mp2, mbuf_next(nd->nd_md));
305 1.1.1.1.4.2 rmind mbuf_setnext(nd->nd_md, mp2);
306 1.1.1.1.4.2 rmind mbuf_setlen(nd->nd_md, mbuf_len(nd->nd_md) - left);
307 1.1.1.1.4.2 rmind nd->nd_md = mp2;
308 1.1.1.1.4.2 rmind retp = p = NFSMTOD(mp2, caddr_t);
309 1.1.1.1.4.2 rmind NFSBCOPY(nd->nd_dpos, p, left); /* Copy what was left */
310 1.1.1.1.4.2 rmind siz2 = siz - left;
311 1.1.1.1.4.2 rmind p += left;
312 1.1.1.1.4.2 rmind mp2 = mbuf_next(mp2);
313 1.1.1.1.4.2 rmind /* Loop around copying up the siz2 bytes */
314 1.1.1.1.4.2 rmind while (siz2 > 0) {
315 1.1.1.1.4.2 rmind if (mp2 == NULL)
316 1.1.1.1.4.2 rmind return (NULL);
317 1.1.1.1.4.2 rmind xfer = (siz2 > mbuf_len(mp2)) ? mbuf_len(mp2) : siz2;
318 1.1.1.1.4.2 rmind if (xfer > 0) {
319 1.1.1.1.4.2 rmind NFSBCOPY(NFSMTOD(mp2, caddr_t), p, xfer);
320 1.1.1.1.4.2 rmind NFSM_DATAP(mp2, xfer);
321 1.1.1.1.4.2 rmind mbuf_setlen(mp2, mbuf_len(mp2) - xfer);
322 1.1.1.1.4.2 rmind p += xfer;
323 1.1.1.1.4.2 rmind siz2 -= xfer;
324 1.1.1.1.4.2 rmind }
325 1.1.1.1.4.2 rmind if (siz2 > 0)
326 1.1.1.1.4.2 rmind mp2 = mbuf_next(mp2);
327 1.1.1.1.4.2 rmind }
328 1.1.1.1.4.2 rmind mbuf_setlen(nd->nd_md, siz);
329 1.1.1.1.4.2 rmind nd->nd_md = mp2;
330 1.1.1.1.4.2 rmind nd->nd_dpos = NFSMTOD(mp2, caddr_t);
331 1.1.1.1.4.2 rmind }
332 1.1.1.1.4.2 rmind return (retp);
333 1.1.1.1.4.2 rmind }
334 1.1.1.1.4.2 rmind
335 1.1.1.1.4.2 rmind /*
336 1.1.1.1.4.2 rmind * Advance the position in the mbuf chain.
337 1.1.1.1.4.2 rmind * If offs == 0, this is a no-op, but it is simpler to just return from
338 1.1.1.1.4.2 rmind * here than check for offs > 0 for all calls to nfsm_advance.
339 1.1.1.1.4.2 rmind * If left == -1, it should be calculated here.
340 1.1.1.1.4.2 rmind */
341 1.1.1.1.4.2 rmind APPLESTATIC int
342 1.1.1.1.4.2 rmind nfsm_advance(struct nfsrv_descript *nd, int offs, int left)
343 1.1.1.1.4.2 rmind {
344 1.1.1.1.4.2 rmind int error = 0;
345 1.1.1.1.4.2 rmind
346 1.1.1.1.4.2 rmind if (offs == 0)
347 1.1.1.1.4.2 rmind goto out;
348 1.1.1.1.4.2 rmind /*
349 1.1.1.1.4.2 rmind * A negative offs should be considered a serious problem.
350 1.1.1.1.4.2 rmind */
351 1.1.1.1.4.2 rmind if (offs < 0)
352 1.1.1.1.4.2 rmind panic("nfsrv_advance");
353 1.1.1.1.4.2 rmind
354 1.1.1.1.4.2 rmind /*
355 1.1.1.1.4.2 rmind * If left == -1, calculate it here.
356 1.1.1.1.4.2 rmind */
357 1.1.1.1.4.2 rmind if (left == -1)
358 1.1.1.1.4.2 rmind left = NFSMTOD(nd->nd_md, caddr_t) + mbuf_len(nd->nd_md) -
359 1.1.1.1.4.2 rmind nd->nd_dpos;
360 1.1.1.1.4.2 rmind
361 1.1.1.1.4.2 rmind /*
362 1.1.1.1.4.2 rmind * Loop around, advancing over the mbuf data.
363 1.1.1.1.4.2 rmind */
364 1.1.1.1.4.2 rmind while (offs > left) {
365 1.1.1.1.4.2 rmind offs -= left;
366 1.1.1.1.4.2 rmind nd->nd_md = mbuf_next(nd->nd_md);
367 1.1.1.1.4.2 rmind if (nd->nd_md == NULL) {
368 1.1.1.1.4.2 rmind error = EBADRPC;
369 1.1.1.1.4.2 rmind goto out;
370 1.1.1.1.4.2 rmind }
371 1.1.1.1.4.2 rmind left = mbuf_len(nd->nd_md);
372 1.1.1.1.4.2 rmind nd->nd_dpos = NFSMTOD(nd->nd_md, caddr_t);
373 1.1.1.1.4.2 rmind }
374 1.1.1.1.4.2 rmind nd->nd_dpos += offs;
375 1.1.1.1.4.2 rmind
376 1.1.1.1.4.2 rmind out:
377 1.1.1.1.4.2 rmind NFSEXITCODE(error);
378 1.1.1.1.4.2 rmind return (error);
379 1.1.1.1.4.2 rmind }
380 1.1.1.1.4.2 rmind
381 1.1.1.1.4.2 rmind /*
382 1.1.1.1.4.2 rmind * Copy a string into mbuf(s).
383 1.1.1.1.4.2 rmind * Return the number of bytes output, including XDR overheads.
384 1.1.1.1.4.2 rmind */
385 1.1.1.1.4.2 rmind APPLESTATIC int
386 1.1.1.1.4.2 rmind nfsm_strtom(struct nfsrv_descript *nd, const char *cp, int siz)
387 1.1.1.1.4.2 rmind {
388 1.1.1.1.4.2 rmind mbuf_t m2;
389 1.1.1.1.4.2 rmind int xfer, left;
390 1.1.1.1.4.2 rmind mbuf_t m1;
391 1.1.1.1.4.2 rmind int rem, bytesize;
392 1.1.1.1.4.2 rmind u_int32_t *tl;
393 1.1.1.1.4.2 rmind char *cp2;
394 1.1.1.1.4.2 rmind
395 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
396 1.1.1.1.4.2 rmind *tl = txdr_unsigned(siz);
397 1.1.1.1.4.2 rmind rem = NFSM_RNDUP(siz) - siz;
398 1.1.1.1.4.2 rmind bytesize = NFSX_UNSIGNED + siz + rem;
399 1.1.1.1.4.2 rmind m2 = nd->nd_mb;
400 1.1.1.1.4.2 rmind cp2 = nd->nd_bpos;
401 1.1.1.1.4.2 rmind left = M_TRAILINGSPACE(m2);
402 1.1.1.1.4.2 rmind
403 1.1.1.1.4.2 rmind /*
404 1.1.1.1.4.2 rmind * Loop around copying the string to mbuf(s).
405 1.1.1.1.4.2 rmind */
406 1.1.1.1.4.2 rmind while (siz > 0) {
407 1.1.1.1.4.2 rmind if (left == 0) {
408 1.1.1.1.4.2 rmind if (siz > ncl_mbuf_mlen)
409 1.1.1.1.4.2 rmind NFSMCLGET(m1, M_WAITOK);
410 1.1.1.1.4.2 rmind else
411 1.1.1.1.4.2 rmind NFSMGET(m1);
412 1.1.1.1.4.2 rmind mbuf_setlen(m1, 0);
413 1.1.1.1.4.2 rmind mbuf_setnext(m2, m1);
414 1.1.1.1.4.2 rmind m2 = m1;
415 1.1.1.1.4.2 rmind cp2 = NFSMTOD(m2, caddr_t);
416 1.1.1.1.4.2 rmind left = M_TRAILINGSPACE(m2);
417 1.1.1.1.4.2 rmind }
418 1.1.1.1.4.2 rmind if (left >= siz)
419 1.1.1.1.4.2 rmind xfer = siz;
420 1.1.1.1.4.2 rmind else
421 1.1.1.1.4.2 rmind xfer = left;
422 1.1.1.1.4.2 rmind NFSBCOPY(cp, cp2, xfer);
423 1.1.1.1.4.2 rmind cp += xfer;
424 1.1.1.1.4.2 rmind mbuf_setlen(m2, mbuf_len(m2) + xfer);
425 1.1.1.1.4.2 rmind siz -= xfer;
426 1.1.1.1.4.2 rmind left -= xfer;
427 1.1.1.1.4.2 rmind if (siz == 0 && rem) {
428 1.1.1.1.4.2 rmind if (left < rem)
429 1.1.1.1.4.2 rmind panic("nfsm_strtom");
430 1.1.1.1.4.2 rmind NFSBZERO(cp2 + xfer, rem);
431 1.1.1.1.4.2 rmind mbuf_setlen(m2, mbuf_len(m2) + rem);
432 1.1.1.1.4.2 rmind }
433 1.1.1.1.4.2 rmind }
434 1.1.1.1.4.2 rmind nd->nd_mb = m2;
435 1.1.1.1.4.2 rmind nd->nd_bpos = NFSMTOD(m2, caddr_t) + mbuf_len(m2);
436 1.1.1.1.4.2 rmind return (bytesize);
437 1.1.1.1.4.2 rmind }
438 1.1.1.1.4.2 rmind
439 1.1.1.1.4.2 rmind /*
440 1.1.1.1.4.2 rmind * Called once to initialize data structures...
441 1.1.1.1.4.2 rmind */
442 1.1.1.1.4.2 rmind APPLESTATIC void
443 1.1.1.1.4.2 rmind newnfs_init(void)
444 1.1.1.1.4.2 rmind {
445 1.1.1.1.4.2 rmind static int nfs_inited = 0;
446 1.1.1.1.4.2 rmind
447 1.1.1.1.4.2 rmind if (nfs_inited)
448 1.1.1.1.4.2 rmind return;
449 1.1.1.1.4.2 rmind nfs_inited = 1;
450 1.1.1.1.4.2 rmind
451 1.1.1.1.4.2 rmind newnfs_true = txdr_unsigned(TRUE);
452 1.1.1.1.4.2 rmind newnfs_false = txdr_unsigned(FALSE);
453 1.1.1.1.4.2 rmind newnfs_xdrneg1 = txdr_unsigned(-1);
454 1.1.1.1.4.2 rmind nfscl_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
455 1.1.1.1.4.2 rmind if (nfscl_ticks < 1)
456 1.1.1.1.4.2 rmind nfscl_ticks = 1;
457 1.1.1.1.4.2 rmind NFSSETBOOTTIME(nfsboottime);
458 1.1.1.1.4.2 rmind
459 1.1.1.1.4.2 rmind /*
460 1.1.1.1.4.2 rmind * Initialize reply list and start timer
461 1.1.1.1.4.2 rmind */
462 1.1.1.1.4.2 rmind TAILQ_INIT(&nfsd_reqq);
463 1.1.1.1.4.2 rmind NFS_TIMERINIT;
464 1.1.1.1.4.2 rmind }
465 1.1.1.1.4.2 rmind
466 1.1.1.1.4.2 rmind /*
467 1.1.1.1.4.2 rmind * Put a file handle in an mbuf list.
468 1.1.1.1.4.2 rmind * If the size argument == 0, just use the default size.
469 1.1.1.1.4.2 rmind * set_true == 1 if there should be an newnfs_true prepended on the file handle.
470 1.1.1.1.4.2 rmind * Return the number of bytes output, including XDR overhead.
471 1.1.1.1.4.2 rmind */
472 1.1.1.1.4.2 rmind APPLESTATIC int
473 1.1.1.1.4.2 rmind nfsm_fhtom(struct nfsrv_descript *nd, u_int8_t *fhp, int size, int set_true)
474 1.1.1.1.4.2 rmind {
475 1.1.1.1.4.2 rmind u_int32_t *tl;
476 1.1.1.1.4.2 rmind u_int8_t *cp;
477 1.1.1.1.4.2 rmind int fullsiz, rem, bytesize = 0;
478 1.1.1.1.4.2 rmind
479 1.1.1.1.4.2 rmind if (size == 0)
480 1.1.1.1.4.2 rmind size = NFSX_MYFH;
481 1.1.1.1.4.2 rmind switch (nd->nd_flag & (ND_NFSV2 | ND_NFSV3 | ND_NFSV4)) {
482 1.1.1.1.4.2 rmind case ND_NFSV2:
483 1.1.1.1.4.2 rmind if (size > NFSX_V2FH)
484 1.1.1.1.4.2 rmind panic("fh size > NFSX_V2FH for NFSv2");
485 1.1.1.1.4.2 rmind NFSM_BUILD(cp, u_int8_t *, NFSX_V2FH);
486 1.1.1.1.4.2 rmind NFSBCOPY(fhp, cp, size);
487 1.1.1.1.4.2 rmind if (size < NFSX_V2FH)
488 1.1.1.1.4.2 rmind NFSBZERO(cp + size, NFSX_V2FH - size);
489 1.1.1.1.4.2 rmind bytesize = NFSX_V2FH;
490 1.1.1.1.4.2 rmind break;
491 1.1.1.1.4.2 rmind case ND_NFSV3:
492 1.1.1.1.4.2 rmind case ND_NFSV4:
493 1.1.1.1.4.2 rmind fullsiz = NFSM_RNDUP(size);
494 1.1.1.1.4.2 rmind rem = fullsiz - size;
495 1.1.1.1.4.2 rmind if (set_true) {
496 1.1.1.1.4.2 rmind bytesize = 2 * NFSX_UNSIGNED + fullsiz;
497 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
498 1.1.1.1.4.2 rmind *tl = newnfs_true;
499 1.1.1.1.4.2 rmind } else {
500 1.1.1.1.4.2 rmind bytesize = NFSX_UNSIGNED + fullsiz;
501 1.1.1.1.4.2 rmind }
502 1.1.1.1.4.2 rmind (void) nfsm_strtom(nd, fhp, size);
503 1.1.1.1.4.2 rmind break;
504 1.1.1.1.4.2 rmind };
505 1.1.1.1.4.2 rmind return (bytesize);
506 1.1.1.1.4.2 rmind }
507 1.1.1.1.4.2 rmind
508 1.1.1.1.4.2 rmind /*
509 1.1.1.1.4.2 rmind * This function compares two net addresses by family and returns TRUE
510 1.1.1.1.4.2 rmind * if they are the same host.
511 1.1.1.1.4.2 rmind * If there is any doubt, return FALSE.
512 1.1.1.1.4.2 rmind * The AF_INET family is handled as a special case so that address mbufs
513 1.1.1.1.4.2 rmind * don't need to be saved to store "struct in_addr", which is only 4 bytes.
514 1.1.1.1.4.2 rmind */
515 1.1.1.1.4.2 rmind APPLESTATIC int
516 1.1.1.1.4.2 rmind nfsaddr_match(int family, union nethostaddr *haddr, NFSSOCKADDR_T nam)
517 1.1.1.1.4.2 rmind {
518 1.1.1.1.4.2 rmind struct sockaddr_in *inetaddr;
519 1.1.1.1.4.2 rmind
520 1.1.1.1.4.2 rmind switch (family) {
521 1.1.1.1.4.2 rmind case AF_INET:
522 1.1.1.1.4.2 rmind inetaddr = NFSSOCKADDR(nam, struct sockaddr_in *);
523 1.1.1.1.4.2 rmind if (inetaddr->sin_family == AF_INET &&
524 1.1.1.1.4.2 rmind inetaddr->sin_addr.s_addr == haddr->had_inet.s_addr)
525 1.1.1.1.4.2 rmind return (1);
526 1.1.1.1.4.2 rmind break;
527 1.1.1.1.4.2 rmind #ifdef INET6
528 1.1.1.1.4.2 rmind case AF_INET6:
529 1.1.1.1.4.2 rmind {
530 1.1.1.1.4.2 rmind struct sockaddr_in6 *inetaddr6;
531 1.1.1.1.4.2 rmind
532 1.1.1.1.4.2 rmind inetaddr6 = NFSSOCKADDR(nam, struct sockaddr_in6 *);
533 1.1.1.1.4.2 rmind /* XXX - should test sin6_scope_id ? */
534 1.1.1.1.4.2 rmind if (inetaddr6->sin6_family == AF_INET6 &&
535 1.1.1.1.4.2 rmind IN6_ARE_ADDR_EQUAL(&inetaddr6->sin6_addr,
536 1.1.1.1.4.2 rmind &haddr->had_inet6))
537 1.1.1.1.4.2 rmind return (1);
538 1.1.1.1.4.2 rmind }
539 1.1.1.1.4.2 rmind break;
540 1.1.1.1.4.2 rmind #endif
541 1.1.1.1.4.2 rmind };
542 1.1.1.1.4.2 rmind return (0);
543 1.1.1.1.4.2 rmind }
544 1.1.1.1.4.2 rmind
545 1.1.1.1.4.2 rmind /*
546 1.1.1.1.4.2 rmind * Similar to the above, but takes to NFSSOCKADDR_T args.
547 1.1.1.1.4.2 rmind */
548 1.1.1.1.4.2 rmind APPLESTATIC int
549 1.1.1.1.4.2 rmind nfsaddr2_match(NFSSOCKADDR_T nam1, NFSSOCKADDR_T nam2)
550 1.1.1.1.4.2 rmind {
551 1.1.1.1.4.2 rmind struct sockaddr_in *addr1, *addr2;
552 1.1.1.1.4.2 rmind struct sockaddr *inaddr;
553 1.1.1.1.4.2 rmind
554 1.1.1.1.4.2 rmind inaddr = NFSSOCKADDR(nam1, struct sockaddr *);
555 1.1.1.1.4.2 rmind switch (inaddr->sa_family) {
556 1.1.1.1.4.2 rmind case AF_INET:
557 1.1.1.1.4.2 rmind addr1 = NFSSOCKADDR(nam1, struct sockaddr_in *);
558 1.1.1.1.4.2 rmind addr2 = NFSSOCKADDR(nam2, struct sockaddr_in *);
559 1.1.1.1.4.2 rmind if (addr2->sin_family == AF_INET &&
560 1.1.1.1.4.2 rmind addr1->sin_addr.s_addr == addr2->sin_addr.s_addr)
561 1.1.1.1.4.2 rmind return (1);
562 1.1.1.1.4.2 rmind break;
563 1.1.1.1.4.2 rmind #ifdef INET6
564 1.1.1.1.4.2 rmind case AF_INET6:
565 1.1.1.1.4.2 rmind {
566 1.1.1.1.4.2 rmind struct sockaddr_in6 *inet6addr1, *inet6addr2;
567 1.1.1.1.4.2 rmind
568 1.1.1.1.4.2 rmind inet6addr1 = NFSSOCKADDR(nam1, struct sockaddr_in6 *);
569 1.1.1.1.4.2 rmind inet6addr2 = NFSSOCKADDR(nam2, struct sockaddr_in6 *);
570 1.1.1.1.4.2 rmind /* XXX - should test sin6_scope_id ? */
571 1.1.1.1.4.2 rmind if (inet6addr2->sin6_family == AF_INET6 &&
572 1.1.1.1.4.2 rmind IN6_ARE_ADDR_EQUAL(&inet6addr1->sin6_addr,
573 1.1.1.1.4.2 rmind &inet6addr2->sin6_addr))
574 1.1.1.1.4.2 rmind return (1);
575 1.1.1.1.4.2 rmind }
576 1.1.1.1.4.2 rmind break;
577 1.1.1.1.4.2 rmind #endif
578 1.1.1.1.4.2 rmind };
579 1.1.1.1.4.2 rmind return (0);
580 1.1.1.1.4.2 rmind }
581 1.1.1.1.4.2 rmind
582 1.1.1.1.4.2 rmind
583 1.1.1.1.4.2 rmind /*
584 1.1.1.1.4.2 rmind * Trim the stuff already dissected off the mbuf list.
585 1.1.1.1.4.2 rmind */
586 1.1.1.1.4.2 rmind APPLESTATIC void
587 1.1.1.1.4.2 rmind newnfs_trimleading(nd)
588 1.1.1.1.4.2 rmind struct nfsrv_descript *nd;
589 1.1.1.1.4.2 rmind {
590 1.1.1.1.4.2 rmind mbuf_t m, n;
591 1.1.1.1.4.2 rmind int offs;
592 1.1.1.1.4.2 rmind
593 1.1.1.1.4.2 rmind /*
594 1.1.1.1.4.2 rmind * First, free up leading mbufs.
595 1.1.1.1.4.2 rmind */
596 1.1.1.1.4.2 rmind if (nd->nd_mrep != nd->nd_md) {
597 1.1.1.1.4.2 rmind m = nd->nd_mrep;
598 1.1.1.1.4.2 rmind while (mbuf_next(m) != nd->nd_md) {
599 1.1.1.1.4.2 rmind if (mbuf_next(m) == NULL)
600 1.1.1.1.4.2 rmind panic("nfsm trim leading");
601 1.1.1.1.4.2 rmind m = mbuf_next(m);
602 1.1.1.1.4.2 rmind }
603 1.1.1.1.4.2 rmind mbuf_setnext(m, NULL);
604 1.1.1.1.4.2 rmind mbuf_freem(nd->nd_mrep);
605 1.1.1.1.4.2 rmind }
606 1.1.1.1.4.2 rmind m = nd->nd_md;
607 1.1.1.1.4.2 rmind
608 1.1.1.1.4.2 rmind /*
609 1.1.1.1.4.2 rmind * Now, adjust this mbuf, based on nd_dpos.
610 1.1.1.1.4.2 rmind */
611 1.1.1.1.4.2 rmind offs = nd->nd_dpos - NFSMTOD(m, caddr_t);
612 1.1.1.1.4.2 rmind if (offs == mbuf_len(m)) {
613 1.1.1.1.4.2 rmind n = m;
614 1.1.1.1.4.2 rmind m = mbuf_next(m);
615 1.1.1.1.4.2 rmind if (m == NULL)
616 1.1.1.1.4.2 rmind panic("nfsm trim leading2");
617 1.1.1.1.4.2 rmind mbuf_setnext(n, NULL);
618 1.1.1.1.4.2 rmind mbuf_freem(n);
619 1.1.1.1.4.2 rmind } else if (offs > 0) {
620 1.1.1.1.4.2 rmind mbuf_setlen(m, mbuf_len(m) - offs);
621 1.1.1.1.4.2 rmind NFSM_DATAP(m, offs);
622 1.1.1.1.4.2 rmind } else if (offs < 0)
623 1.1.1.1.4.2 rmind panic("nfsm trimleading offs");
624 1.1.1.1.4.2 rmind nd->nd_mrep = m;
625 1.1.1.1.4.2 rmind nd->nd_md = m;
626 1.1.1.1.4.2 rmind nd->nd_dpos = NFSMTOD(m, caddr_t);
627 1.1.1.1.4.2 rmind }
628 1.1.1.1.4.2 rmind
629 1.1.1.1.4.2 rmind /*
630 1.1.1.1.4.2 rmind * Trim trailing data off the mbuf list being built.
631 1.1.1.1.4.2 rmind */
632 1.1.1.1.4.2 rmind APPLESTATIC void
633 1.1.1.1.4.2 rmind newnfs_trimtrailing(nd, mb, bpos)
634 1.1.1.1.4.2 rmind struct nfsrv_descript *nd;
635 1.1.1.1.4.2 rmind mbuf_t mb;
636 1.1.1.1.4.2 rmind caddr_t bpos;
637 1.1.1.1.4.2 rmind {
638 1.1.1.1.4.2 rmind
639 1.1.1.1.4.2 rmind if (mbuf_next(mb)) {
640 1.1.1.1.4.2 rmind mbuf_freem(mbuf_next(mb));
641 1.1.1.1.4.2 rmind mbuf_setnext(mb, NULL);
642 1.1.1.1.4.2 rmind }
643 1.1.1.1.4.2 rmind mbuf_setlen(mb, bpos - NFSMTOD(mb, caddr_t));
644 1.1.1.1.4.2 rmind nd->nd_mb = mb;
645 1.1.1.1.4.2 rmind nd->nd_bpos = bpos;
646 1.1.1.1.4.2 rmind }
647 1.1.1.1.4.2 rmind
648 1.1.1.1.4.2 rmind /*
649 1.1.1.1.4.2 rmind * Dissect a file handle on the client.
650 1.1.1.1.4.2 rmind */
651 1.1.1.1.4.2 rmind APPLESTATIC int
652 1.1.1.1.4.2 rmind nfsm_getfh(struct nfsrv_descript *nd, struct nfsfh **nfhpp)
653 1.1.1.1.4.2 rmind {
654 1.1.1.1.4.2 rmind u_int32_t *tl;
655 1.1.1.1.4.2 rmind struct nfsfh *nfhp;
656 1.1.1.1.4.2 rmind int error, len;
657 1.1.1.1.4.2 rmind
658 1.1.1.1.4.2 rmind *nfhpp = NULL;
659 1.1.1.1.4.2 rmind if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
660 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
661 1.1.1.1.4.2 rmind if ((len = fxdr_unsigned(int, *tl)) <= 0 ||
662 1.1.1.1.4.2 rmind len > NFSX_FHMAX) {
663 1.1.1.1.4.2 rmind error = EBADRPC;
664 1.1.1.1.4.2 rmind goto nfsmout;
665 1.1.1.1.4.2 rmind }
666 1.1.1.1.4.2 rmind } else
667 1.1.1.1.4.2 rmind len = NFSX_V2FH;
668 1.1.1.1.4.2 rmind MALLOC(nfhp, struct nfsfh *, sizeof (struct nfsfh) + len,
669 1.1.1.1.4.2 rmind M_NFSFH, M_WAITOK);
670 1.1.1.1.4.2 rmind error = nfsrv_mtostr(nd, nfhp->nfh_fh, len);
671 1.1.1.1.4.2 rmind if (error) {
672 1.1.1.1.4.2 rmind FREE((caddr_t)nfhp, M_NFSFH);
673 1.1.1.1.4.2 rmind goto nfsmout;
674 1.1.1.1.4.2 rmind }
675 1.1.1.1.4.2 rmind nfhp->nfh_len = len;
676 1.1.1.1.4.2 rmind *nfhpp = nfhp;
677 1.1.1.1.4.2 rmind nfsmout:
678 1.1.1.1.4.2 rmind NFSEXITCODE2(error, nd);
679 1.1.1.1.4.2 rmind return (error);
680 1.1.1.1.4.2 rmind }
681 1.1.1.1.4.2 rmind
682 1.1.1.1.4.2 rmind /*
683 1.1.1.1.4.2 rmind * Break down the nfsv4 acl.
684 1.1.1.1.4.2 rmind * If the aclp == NULL or won't fit in an acl, just discard the acl info.
685 1.1.1.1.4.2 rmind */
686 1.1.1.1.4.2 rmind APPLESTATIC int
687 1.1.1.1.4.2 rmind nfsrv_dissectacl(struct nfsrv_descript *nd, NFSACL_T *aclp, int *aclerrp,
688 1.1.1.1.4.2 rmind int *aclsizep, __unused NFSPROC_T *p)
689 1.1.1.1.4.2 rmind {
690 1.1.1.1.4.2 rmind u_int32_t *tl;
691 1.1.1.1.4.2 rmind int i, aclsize;
692 1.1.1.1.4.2 rmind int acecnt, error = 0, aceerr = 0, acesize;
693 1.1.1.1.4.2 rmind
694 1.1.1.1.4.2 rmind *aclerrp = 0;
695 1.1.1.1.4.2 rmind if (aclp)
696 1.1.1.1.4.2 rmind aclp->acl_cnt = 0;
697 1.1.1.1.4.2 rmind /*
698 1.1.1.1.4.2 rmind * Parse out the ace entries and expect them to conform to
699 1.1.1.1.4.2 rmind * what can be supported by R/W/X bits.
700 1.1.1.1.4.2 rmind */
701 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
702 1.1.1.1.4.2 rmind aclsize = NFSX_UNSIGNED;
703 1.1.1.1.4.2 rmind acecnt = fxdr_unsigned(int, *tl);
704 1.1.1.1.4.2 rmind if (acecnt > ACL_MAX_ENTRIES)
705 1.1.1.1.4.2 rmind aceerr = NFSERR_ATTRNOTSUPP;
706 1.1.1.1.4.2 rmind if (nfsrv_useacl == 0)
707 1.1.1.1.4.2 rmind aceerr = NFSERR_ATTRNOTSUPP;
708 1.1.1.1.4.2 rmind for (i = 0; i < acecnt; i++) {
709 1.1.1.1.4.2 rmind if (aclp && !aceerr)
710 1.1.1.1.4.2 rmind error = nfsrv_dissectace(nd, &aclp->acl_entry[i],
711 1.1.1.1.4.2 rmind &aceerr, &acesize, p);
712 1.1.1.1.4.2 rmind else
713 1.1.1.1.4.2 rmind error = nfsrv_skipace(nd, &acesize);
714 1.1.1.1.4.2 rmind if (error)
715 1.1.1.1.4.2 rmind goto nfsmout;
716 1.1.1.1.4.2 rmind aclsize += acesize;
717 1.1.1.1.4.2 rmind }
718 1.1.1.1.4.2 rmind if (aclp && !aceerr)
719 1.1.1.1.4.2 rmind aclp->acl_cnt = acecnt;
720 1.1.1.1.4.2 rmind if (aceerr)
721 1.1.1.1.4.2 rmind *aclerrp = aceerr;
722 1.1.1.1.4.2 rmind if (aclsizep)
723 1.1.1.1.4.2 rmind *aclsizep = aclsize;
724 1.1.1.1.4.2 rmind nfsmout:
725 1.1.1.1.4.2 rmind NFSEXITCODE2(error, nd);
726 1.1.1.1.4.2 rmind return (error);
727 1.1.1.1.4.2 rmind }
728 1.1.1.1.4.2 rmind
729 1.1.1.1.4.2 rmind /*
730 1.1.1.1.4.2 rmind * Skip over an NFSv4 ace entry. Just dissect the xdr and discard it.
731 1.1.1.1.4.2 rmind */
732 1.1.1.1.4.2 rmind static int
733 1.1.1.1.4.2 rmind nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep)
734 1.1.1.1.4.2 rmind {
735 1.1.1.1.4.2 rmind u_int32_t *tl;
736 1.1.1.1.4.2 rmind int error, len = 0;
737 1.1.1.1.4.2 rmind
738 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
739 1.1.1.1.4.2 rmind len = fxdr_unsigned(int, *(tl + 3));
740 1.1.1.1.4.2 rmind error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
741 1.1.1.1.4.2 rmind nfsmout:
742 1.1.1.1.4.2 rmind *acesizep = NFSM_RNDUP(len) + (4 * NFSX_UNSIGNED);
743 1.1.1.1.4.2 rmind NFSEXITCODE2(error, nd);
744 1.1.1.1.4.2 rmind return (error);
745 1.1.1.1.4.2 rmind }
746 1.1.1.1.4.2 rmind
747 1.1.1.1.4.2 rmind /*
748 1.1.1.1.4.2 rmind * Get attribute bits from an mbuf list.
749 1.1.1.1.4.2 rmind * Returns EBADRPC for a parsing error, 0 otherwise.
750 1.1.1.1.4.2 rmind * If the clearinvalid flag is set, clear the bits not supported.
751 1.1.1.1.4.2 rmind */
752 1.1.1.1.4.2 rmind APPLESTATIC int
753 1.1.1.1.4.2 rmind nfsrv_getattrbits(struct nfsrv_descript *nd, nfsattrbit_t *attrbitp, int *cntp,
754 1.1.1.1.4.2 rmind int *retnotsupp)
755 1.1.1.1.4.2 rmind {
756 1.1.1.1.4.2 rmind u_int32_t *tl;
757 1.1.1.1.4.2 rmind int cnt, i, outcnt;
758 1.1.1.1.4.2 rmind int error = 0;
759 1.1.1.1.4.2 rmind
760 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
761 1.1.1.1.4.2 rmind cnt = fxdr_unsigned(int, *tl);
762 1.1.1.1.4.2 rmind if (cnt < 0) {
763 1.1.1.1.4.2 rmind error = NFSERR_BADXDR;
764 1.1.1.1.4.2 rmind goto nfsmout;
765 1.1.1.1.4.2 rmind }
766 1.1.1.1.4.2 rmind if (cnt > NFSATTRBIT_MAXWORDS)
767 1.1.1.1.4.2 rmind outcnt = NFSATTRBIT_MAXWORDS;
768 1.1.1.1.4.2 rmind else
769 1.1.1.1.4.2 rmind outcnt = cnt;
770 1.1.1.1.4.2 rmind NFSZERO_ATTRBIT(attrbitp);
771 1.1.1.1.4.2 rmind if (outcnt > 0) {
772 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, outcnt * NFSX_UNSIGNED);
773 1.1.1.1.4.2 rmind for (i = 0; i < outcnt; i++)
774 1.1.1.1.4.2 rmind attrbitp->bits[i] = fxdr_unsigned(u_int32_t, *tl++);
775 1.1.1.1.4.2 rmind }
776 1.1.1.1.4.2 rmind for (i = 0; i < (cnt - outcnt); i++) {
777 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
778 1.1.1.1.4.2 rmind if (retnotsupp != NULL && *tl != 0)
779 1.1.1.1.4.2 rmind *retnotsupp = NFSERR_ATTRNOTSUPP;
780 1.1.1.1.4.2 rmind }
781 1.1.1.1.4.2 rmind if (cntp)
782 1.1.1.1.4.2 rmind *cntp = NFSX_UNSIGNED + (cnt * NFSX_UNSIGNED);
783 1.1.1.1.4.2 rmind nfsmout:
784 1.1.1.1.4.2 rmind NFSEXITCODE2(error, nd);
785 1.1.1.1.4.2 rmind return (error);
786 1.1.1.1.4.2 rmind }
787 1.1.1.1.4.2 rmind
788 1.1.1.1.4.2 rmind /*
789 1.1.1.1.4.2 rmind * Get the attributes for V4.
790 1.1.1.1.4.2 rmind * If the compare flag is true, test for any attribute changes,
791 1.1.1.1.4.2 rmind * otherwise return the attribute values.
792 1.1.1.1.4.2 rmind * These attributes cover fields in "struct vattr", "struct statfs",
793 1.1.1.1.4.2 rmind * "struct nfsfsinfo", the file handle and the lease duration.
794 1.1.1.1.4.2 rmind * The value of retcmpp is set to 1 if all attributes are the same,
795 1.1.1.1.4.2 rmind * and 0 otherwise.
796 1.1.1.1.4.2 rmind * Returns EBADRPC if it can't be parsed, 0 otherwise.
797 1.1.1.1.4.2 rmind */
798 1.1.1.1.4.2 rmind APPLESTATIC int
799 1.1.1.1.4.2 rmind nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
800 1.1.1.1.4.2 rmind struct nfsvattr *nap, struct nfsfh **nfhpp, fhandle_t *fhp, int fhsize,
801 1.1.1.1.4.2 rmind struct nfsv3_pathconf *pc, struct statfs *sbp, struct nfsstatfs *sfp,
802 1.1.1.1.4.2 rmind struct nfsfsinfo *fsp, NFSACL_T *aclp, int compare, int *retcmpp,
803 1.1.1.1.4.2 rmind u_int32_t *leasep, u_int32_t *rderrp, NFSPROC_T *p, struct ucred *cred)
804 1.1.1.1.4.2 rmind {
805 1.1.1.1.4.2 rmind u_int32_t *tl;
806 1.1.1.1.4.2 rmind int i = 0, j, k, l = 0, m, bitpos, attrsum = 0;
807 1.1.1.1.4.2 rmind int error, tfhsize, aceerr, attrsize, cnt, retnotsup;
808 1.1.1.1.4.2 rmind u_char *cp, *cp2, namestr[NFSV4_SMALLSTR + 1];
809 1.1.1.1.4.2 rmind nfsattrbit_t attrbits, retattrbits, checkattrbits;
810 1.1.1.1.4.2 rmind struct nfsfh *tnfhp;
811 1.1.1.1.4.2 rmind struct nfsreferral *refp;
812 1.1.1.1.4.2 rmind u_quad_t tquad;
813 1.1.1.1.4.2 rmind nfsquad_t tnfsquad;
814 1.1.1.1.4.2 rmind struct timespec temptime;
815 1.1.1.1.4.2 rmind uid_t uid;
816 1.1.1.1.4.2 rmind gid_t gid;
817 1.1.1.1.4.2 rmind long fid;
818 1.1.1.1.4.2 rmind u_int32_t freenum = 0, tuint;
819 1.1.1.1.4.2 rmind u_int64_t uquad = 0, thyp, thyp2;
820 1.1.1.1.4.2 rmind #ifdef QUOTA
821 1.1.1.1.4.2 rmind struct dqblk dqb;
822 1.1.1.1.4.2 rmind uid_t savuid;
823 1.1.1.1.4.2 rmind #endif
824 1.1.1.1.4.2 rmind
825 1.1.1.1.4.2 rmind if (compare) {
826 1.1.1.1.4.2 rmind retnotsup = 0;
827 1.1.1.1.4.2 rmind error = nfsrv_getattrbits(nd, &attrbits, NULL, &retnotsup);
828 1.1.1.1.4.2 rmind } else {
829 1.1.1.1.4.2 rmind error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
830 1.1.1.1.4.2 rmind }
831 1.1.1.1.4.2 rmind if (error)
832 1.1.1.1.4.2 rmind goto nfsmout;
833 1.1.1.1.4.2 rmind
834 1.1.1.1.4.2 rmind if (compare) {
835 1.1.1.1.4.2 rmind *retcmpp = retnotsup;
836 1.1.1.1.4.2 rmind } else {
837 1.1.1.1.4.2 rmind /*
838 1.1.1.1.4.2 rmind * Just set default values to some of the important ones.
839 1.1.1.1.4.2 rmind */
840 1.1.1.1.4.2 rmind if (nap != NULL) {
841 1.1.1.1.4.2 rmind nap->na_type = VREG;
842 1.1.1.1.4.2 rmind nap->na_mode = 0;
843 1.1.1.1.4.2 rmind nap->na_rdev = (NFSDEV_T)0;
844 1.1.1.1.4.2 rmind nap->na_mtime.tv_sec = 0;
845 1.1.1.1.4.2 rmind nap->na_mtime.tv_nsec = 0;
846 1.1.1.1.4.2 rmind nap->na_gen = 0;
847 1.1.1.1.4.2 rmind nap->na_flags = 0;
848 1.1.1.1.4.2 rmind nap->na_blocksize = NFS_FABLKSIZE;
849 1.1.1.1.4.2 rmind }
850 1.1.1.1.4.2 rmind if (sbp != NULL) {
851 1.1.1.1.4.2 rmind sbp->f_bsize = NFS_FABLKSIZE;
852 1.1.1.1.4.2 rmind sbp->f_blocks = 0;
853 1.1.1.1.4.2 rmind sbp->f_bfree = 0;
854 1.1.1.1.4.2 rmind sbp->f_bavail = 0;
855 1.1.1.1.4.2 rmind sbp->f_files = 0;
856 1.1.1.1.4.2 rmind sbp->f_ffree = 0;
857 1.1.1.1.4.2 rmind }
858 1.1.1.1.4.2 rmind if (fsp != NULL) {
859 1.1.1.1.4.2 rmind fsp->fs_rtmax = 8192;
860 1.1.1.1.4.2 rmind fsp->fs_rtpref = 8192;
861 1.1.1.1.4.2 rmind fsp->fs_maxname = NFS_MAXNAMLEN;
862 1.1.1.1.4.2 rmind fsp->fs_wtmax = 8192;
863 1.1.1.1.4.2 rmind fsp->fs_wtpref = 8192;
864 1.1.1.1.4.2 rmind fsp->fs_wtmult = NFS_FABLKSIZE;
865 1.1.1.1.4.2 rmind fsp->fs_dtpref = 8192;
866 1.1.1.1.4.2 rmind fsp->fs_maxfilesize = 0xffffffffffffffffull;
867 1.1.1.1.4.2 rmind fsp->fs_timedelta.tv_sec = 0;
868 1.1.1.1.4.2 rmind fsp->fs_timedelta.tv_nsec = 1;
869 1.1.1.1.4.2 rmind fsp->fs_properties = (NFSV3_FSFLINK | NFSV3_FSFSYMLINK |
870 1.1.1.1.4.2 rmind NFSV3_FSFHOMOGENEOUS | NFSV3_FSFCANSETTIME);
871 1.1.1.1.4.2 rmind }
872 1.1.1.1.4.2 rmind if (pc != NULL) {
873 1.1.1.1.4.2 rmind pc->pc_linkmax = LINK_MAX;
874 1.1.1.1.4.2 rmind pc->pc_namemax = NAME_MAX;
875 1.1.1.1.4.2 rmind pc->pc_notrunc = 0;
876 1.1.1.1.4.2 rmind pc->pc_chownrestricted = 0;
877 1.1.1.1.4.2 rmind pc->pc_caseinsensitive = 0;
878 1.1.1.1.4.2 rmind pc->pc_casepreserving = 1;
879 1.1.1.1.4.2 rmind }
880 1.1.1.1.4.2 rmind }
881 1.1.1.1.4.2 rmind
882 1.1.1.1.4.2 rmind /*
883 1.1.1.1.4.2 rmind * Loop around getting the attributes.
884 1.1.1.1.4.2 rmind */
885 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
886 1.1.1.1.4.2 rmind attrsize = fxdr_unsigned(int, *tl);
887 1.1.1.1.4.2 rmind for (bitpos = 0; bitpos < NFSATTRBIT_MAX; bitpos++) {
888 1.1.1.1.4.2 rmind if (attrsum > attrsize) {
889 1.1.1.1.4.2 rmind error = NFSERR_BADXDR;
890 1.1.1.1.4.2 rmind goto nfsmout;
891 1.1.1.1.4.2 rmind }
892 1.1.1.1.4.2 rmind if (NFSISSET_ATTRBIT(&attrbits, bitpos))
893 1.1.1.1.4.2 rmind switch (bitpos) {
894 1.1.1.1.4.2 rmind case NFSATTRBIT_SUPPORTEDATTRS:
895 1.1.1.1.4.2 rmind retnotsup = 0;
896 1.1.1.1.4.2 rmind if (compare || nap == NULL)
897 1.1.1.1.4.2 rmind error = nfsrv_getattrbits(nd, &retattrbits,
898 1.1.1.1.4.2 rmind &cnt, &retnotsup);
899 1.1.1.1.4.2 rmind else
900 1.1.1.1.4.2 rmind error = nfsrv_getattrbits(nd, &nap->na_suppattr,
901 1.1.1.1.4.2 rmind &cnt, &retnotsup);
902 1.1.1.1.4.2 rmind if (error)
903 1.1.1.1.4.2 rmind goto nfsmout;
904 1.1.1.1.4.2 rmind if (compare && !(*retcmpp)) {
905 1.1.1.1.4.2 rmind NFSSETSUPP_ATTRBIT(&checkattrbits);
906 1.1.1.1.4.2 rmind if (!NFSEQUAL_ATTRBIT(&retattrbits, &checkattrbits)
907 1.1.1.1.4.2 rmind || retnotsup)
908 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
909 1.1.1.1.4.2 rmind }
910 1.1.1.1.4.2 rmind attrsum += cnt;
911 1.1.1.1.4.2 rmind break;
912 1.1.1.1.4.2 rmind case NFSATTRBIT_TYPE:
913 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
914 1.1.1.1.4.2 rmind if (compare) {
915 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
916 1.1.1.1.4.2 rmind if (nap->na_type != nfsv34tov_type(*tl))
917 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
918 1.1.1.1.4.2 rmind }
919 1.1.1.1.4.2 rmind } else if (nap != NULL) {
920 1.1.1.1.4.2 rmind nap->na_type = nfsv34tov_type(*tl);
921 1.1.1.1.4.2 rmind }
922 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
923 1.1.1.1.4.2 rmind break;
924 1.1.1.1.4.2 rmind case NFSATTRBIT_FHEXPIRETYPE:
925 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
926 1.1.1.1.4.2 rmind if (compare && !(*retcmpp)) {
927 1.1.1.1.4.2 rmind if (fxdr_unsigned(int, *tl) !=
928 1.1.1.1.4.2 rmind NFSV4FHTYPE_PERSISTENT)
929 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
930 1.1.1.1.4.2 rmind }
931 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
932 1.1.1.1.4.2 rmind break;
933 1.1.1.1.4.2 rmind case NFSATTRBIT_CHANGE:
934 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
935 1.1.1.1.4.2 rmind if (compare) {
936 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
937 1.1.1.1.4.2 rmind if (nap->na_filerev != fxdr_hyper(tl))
938 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
939 1.1.1.1.4.2 rmind }
940 1.1.1.1.4.2 rmind } else if (nap != NULL) {
941 1.1.1.1.4.2 rmind nap->na_filerev = fxdr_hyper(tl);
942 1.1.1.1.4.2 rmind }
943 1.1.1.1.4.2 rmind attrsum += NFSX_HYPER;
944 1.1.1.1.4.2 rmind break;
945 1.1.1.1.4.2 rmind case NFSATTRBIT_SIZE:
946 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
947 1.1.1.1.4.2 rmind if (compare) {
948 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
949 1.1.1.1.4.2 rmind if (nap->na_size != fxdr_hyper(tl))
950 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
951 1.1.1.1.4.2 rmind }
952 1.1.1.1.4.2 rmind } else if (nap != NULL) {
953 1.1.1.1.4.2 rmind nap->na_size = fxdr_hyper(tl);
954 1.1.1.1.4.2 rmind }
955 1.1.1.1.4.2 rmind attrsum += NFSX_HYPER;
956 1.1.1.1.4.2 rmind break;
957 1.1.1.1.4.2 rmind case NFSATTRBIT_LINKSUPPORT:
958 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
959 1.1.1.1.4.2 rmind if (compare) {
960 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
961 1.1.1.1.4.2 rmind if (fsp->fs_properties & NFSV3_FSFLINK) {
962 1.1.1.1.4.2 rmind if (*tl == newnfs_false)
963 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
964 1.1.1.1.4.2 rmind } else {
965 1.1.1.1.4.2 rmind if (*tl == newnfs_true)
966 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
967 1.1.1.1.4.2 rmind }
968 1.1.1.1.4.2 rmind }
969 1.1.1.1.4.2 rmind } else if (fsp != NULL) {
970 1.1.1.1.4.2 rmind if (*tl == newnfs_true)
971 1.1.1.1.4.2 rmind fsp->fs_properties |= NFSV3_FSFLINK;
972 1.1.1.1.4.2 rmind else
973 1.1.1.1.4.2 rmind fsp->fs_properties &= ~NFSV3_FSFLINK;
974 1.1.1.1.4.2 rmind }
975 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
976 1.1.1.1.4.2 rmind break;
977 1.1.1.1.4.2 rmind case NFSATTRBIT_SYMLINKSUPPORT:
978 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
979 1.1.1.1.4.2 rmind if (compare) {
980 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
981 1.1.1.1.4.2 rmind if (fsp->fs_properties & NFSV3_FSFSYMLINK) {
982 1.1.1.1.4.2 rmind if (*tl == newnfs_false)
983 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
984 1.1.1.1.4.2 rmind } else {
985 1.1.1.1.4.2 rmind if (*tl == newnfs_true)
986 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
987 1.1.1.1.4.2 rmind }
988 1.1.1.1.4.2 rmind }
989 1.1.1.1.4.2 rmind } else if (fsp != NULL) {
990 1.1.1.1.4.2 rmind if (*tl == newnfs_true)
991 1.1.1.1.4.2 rmind fsp->fs_properties |= NFSV3_FSFSYMLINK;
992 1.1.1.1.4.2 rmind else
993 1.1.1.1.4.2 rmind fsp->fs_properties &= ~NFSV3_FSFSYMLINK;
994 1.1.1.1.4.2 rmind }
995 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
996 1.1.1.1.4.2 rmind break;
997 1.1.1.1.4.2 rmind case NFSATTRBIT_NAMEDATTR:
998 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
999 1.1.1.1.4.2 rmind if (compare && !(*retcmpp)) {
1000 1.1.1.1.4.2 rmind if (*tl != newnfs_false)
1001 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1002 1.1.1.1.4.2 rmind }
1003 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1004 1.1.1.1.4.2 rmind break;
1005 1.1.1.1.4.2 rmind case NFSATTRBIT_FSID:
1006 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1007 1.1.1.1.4.2 rmind thyp = fxdr_hyper(tl);
1008 1.1.1.1.4.2 rmind tl += 2;
1009 1.1.1.1.4.2 rmind thyp2 = fxdr_hyper(tl);
1010 1.1.1.1.4.2 rmind if (compare) {
1011 1.1.1.1.4.2 rmind if (*retcmpp == 0) {
1012 1.1.1.1.4.2 rmind if (thyp != (u_int64_t)
1013 1.1.1.1.4.2 rmind vfs_statfs(vnode_mount(vp))->f_fsid.val[0] ||
1014 1.1.1.1.4.2 rmind thyp2 != (u_int64_t)
1015 1.1.1.1.4.2 rmind vfs_statfs(vnode_mount(vp))->f_fsid.val[1])
1016 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1017 1.1.1.1.4.2 rmind }
1018 1.1.1.1.4.2 rmind } else if (nap != NULL) {
1019 1.1.1.1.4.2 rmind nap->na_filesid[0] = thyp;
1020 1.1.1.1.4.2 rmind nap->na_filesid[1] = thyp2;
1021 1.1.1.1.4.2 rmind }
1022 1.1.1.1.4.2 rmind attrsum += (4 * NFSX_UNSIGNED);
1023 1.1.1.1.4.2 rmind break;
1024 1.1.1.1.4.2 rmind case NFSATTRBIT_UNIQUEHANDLES:
1025 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1026 1.1.1.1.4.2 rmind if (compare && !(*retcmpp)) {
1027 1.1.1.1.4.2 rmind if (*tl != newnfs_true)
1028 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1029 1.1.1.1.4.2 rmind }
1030 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1031 1.1.1.1.4.2 rmind break;
1032 1.1.1.1.4.2 rmind case NFSATTRBIT_LEASETIME:
1033 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1034 1.1.1.1.4.2 rmind if (compare) {
1035 1.1.1.1.4.2 rmind if (fxdr_unsigned(int, *tl) != nfsrv_lease &&
1036 1.1.1.1.4.2 rmind !(*retcmpp))
1037 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1038 1.1.1.1.4.2 rmind } else if (leasep != NULL) {
1039 1.1.1.1.4.2 rmind *leasep = fxdr_unsigned(u_int32_t, *tl);
1040 1.1.1.1.4.2 rmind }
1041 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1042 1.1.1.1.4.2 rmind break;
1043 1.1.1.1.4.2 rmind case NFSATTRBIT_RDATTRERROR:
1044 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1045 1.1.1.1.4.2 rmind if (compare) {
1046 1.1.1.1.4.2 rmind if (!(*retcmpp))
1047 1.1.1.1.4.2 rmind *retcmpp = NFSERR_INVAL;
1048 1.1.1.1.4.2 rmind } else if (rderrp != NULL) {
1049 1.1.1.1.4.2 rmind *rderrp = fxdr_unsigned(u_int32_t, *tl);
1050 1.1.1.1.4.2 rmind }
1051 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1052 1.1.1.1.4.2 rmind break;
1053 1.1.1.1.4.2 rmind case NFSATTRBIT_ACL:
1054 1.1.1.1.4.2 rmind if (compare) {
1055 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1056 1.1.1.1.4.2 rmind if (nfsrv_useacl) {
1057 1.1.1.1.4.2 rmind NFSACL_T *naclp;
1058 1.1.1.1.4.2 rmind
1059 1.1.1.1.4.2 rmind naclp = acl_alloc(M_WAITOK);
1060 1.1.1.1.4.2 rmind error = nfsrv_dissectacl(nd, naclp, &aceerr,
1061 1.1.1.1.4.2 rmind &cnt, p);
1062 1.1.1.1.4.2 rmind if (error) {
1063 1.1.1.1.4.2 rmind acl_free(naclp);
1064 1.1.1.1.4.2 rmind goto nfsmout;
1065 1.1.1.1.4.2 rmind }
1066 1.1.1.1.4.2 rmind if (aceerr || aclp == NULL ||
1067 1.1.1.1.4.2 rmind nfsrv_compareacl(aclp, naclp))
1068 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1069 1.1.1.1.4.2 rmind acl_free(naclp);
1070 1.1.1.1.4.2 rmind } else {
1071 1.1.1.1.4.2 rmind error = nfsrv_dissectacl(nd, NULL, &aceerr,
1072 1.1.1.1.4.2 rmind &cnt, p);
1073 1.1.1.1.4.2 rmind *retcmpp = NFSERR_ATTRNOTSUPP;
1074 1.1.1.1.4.2 rmind }
1075 1.1.1.1.4.2 rmind }
1076 1.1.1.1.4.2 rmind } else {
1077 1.1.1.1.4.2 rmind if (vp != NULL && aclp != NULL)
1078 1.1.1.1.4.2 rmind error = nfsrv_dissectacl(nd, aclp, &aceerr,
1079 1.1.1.1.4.2 rmind &cnt, p);
1080 1.1.1.1.4.2 rmind else
1081 1.1.1.1.4.2 rmind error = nfsrv_dissectacl(nd, NULL, &aceerr,
1082 1.1.1.1.4.2 rmind &cnt, p);
1083 1.1.1.1.4.2 rmind if (error)
1084 1.1.1.1.4.2 rmind goto nfsmout;
1085 1.1.1.1.4.2 rmind }
1086 1.1.1.1.4.2 rmind attrsum += cnt;
1087 1.1.1.1.4.2 rmind break;
1088 1.1.1.1.4.2 rmind case NFSATTRBIT_ACLSUPPORT:
1089 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1090 1.1.1.1.4.2 rmind if (compare && !(*retcmpp)) {
1091 1.1.1.1.4.2 rmind if (nfsrv_useacl) {
1092 1.1.1.1.4.2 rmind if (fxdr_unsigned(u_int32_t, *tl) !=
1093 1.1.1.1.4.2 rmind NFSV4ACE_SUPTYPES)
1094 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1095 1.1.1.1.4.2 rmind } else {
1096 1.1.1.1.4.2 rmind *retcmpp = NFSERR_ATTRNOTSUPP;
1097 1.1.1.1.4.2 rmind }
1098 1.1.1.1.4.2 rmind }
1099 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1100 1.1.1.1.4.2 rmind break;
1101 1.1.1.1.4.2 rmind case NFSATTRBIT_ARCHIVE:
1102 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1103 1.1.1.1.4.2 rmind if (compare && !(*retcmpp))
1104 1.1.1.1.4.2 rmind *retcmpp = NFSERR_ATTRNOTSUPP;
1105 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1106 1.1.1.1.4.2 rmind break;
1107 1.1.1.1.4.2 rmind case NFSATTRBIT_CANSETTIME:
1108 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1109 1.1.1.1.4.2 rmind if (compare) {
1110 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1111 1.1.1.1.4.2 rmind if (fsp->fs_properties & NFSV3_FSFCANSETTIME) {
1112 1.1.1.1.4.2 rmind if (*tl == newnfs_false)
1113 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1114 1.1.1.1.4.2 rmind } else {
1115 1.1.1.1.4.2 rmind if (*tl == newnfs_true)
1116 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1117 1.1.1.1.4.2 rmind }
1118 1.1.1.1.4.2 rmind }
1119 1.1.1.1.4.2 rmind } else if (fsp != NULL) {
1120 1.1.1.1.4.2 rmind if (*tl == newnfs_true)
1121 1.1.1.1.4.2 rmind fsp->fs_properties |= NFSV3_FSFCANSETTIME;
1122 1.1.1.1.4.2 rmind else
1123 1.1.1.1.4.2 rmind fsp->fs_properties &= ~NFSV3_FSFCANSETTIME;
1124 1.1.1.1.4.2 rmind }
1125 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1126 1.1.1.1.4.2 rmind break;
1127 1.1.1.1.4.2 rmind case NFSATTRBIT_CASEINSENSITIVE:
1128 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1129 1.1.1.1.4.2 rmind if (compare) {
1130 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1131 1.1.1.1.4.2 rmind if (*tl != newnfs_false)
1132 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1133 1.1.1.1.4.2 rmind }
1134 1.1.1.1.4.2 rmind } else if (pc != NULL) {
1135 1.1.1.1.4.2 rmind pc->pc_caseinsensitive =
1136 1.1.1.1.4.2 rmind fxdr_unsigned(u_int32_t, *tl);
1137 1.1.1.1.4.2 rmind }
1138 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1139 1.1.1.1.4.2 rmind break;
1140 1.1.1.1.4.2 rmind case NFSATTRBIT_CASEPRESERVING:
1141 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1142 1.1.1.1.4.2 rmind if (compare) {
1143 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1144 1.1.1.1.4.2 rmind if (*tl != newnfs_true)
1145 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1146 1.1.1.1.4.2 rmind }
1147 1.1.1.1.4.2 rmind } else if (pc != NULL) {
1148 1.1.1.1.4.2 rmind pc->pc_casepreserving =
1149 1.1.1.1.4.2 rmind fxdr_unsigned(u_int32_t, *tl);
1150 1.1.1.1.4.2 rmind }
1151 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1152 1.1.1.1.4.2 rmind break;
1153 1.1.1.1.4.2 rmind case NFSATTRBIT_CHOWNRESTRICTED:
1154 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1155 1.1.1.1.4.2 rmind if (compare) {
1156 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1157 1.1.1.1.4.2 rmind if (*tl != newnfs_true)
1158 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1159 1.1.1.1.4.2 rmind }
1160 1.1.1.1.4.2 rmind } else if (pc != NULL) {
1161 1.1.1.1.4.2 rmind pc->pc_chownrestricted =
1162 1.1.1.1.4.2 rmind fxdr_unsigned(u_int32_t, *tl);
1163 1.1.1.1.4.2 rmind }
1164 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1165 1.1.1.1.4.2 rmind break;
1166 1.1.1.1.4.2 rmind case NFSATTRBIT_FILEHANDLE:
1167 1.1.1.1.4.2 rmind error = nfsm_getfh(nd, &tnfhp);
1168 1.1.1.1.4.2 rmind if (error)
1169 1.1.1.1.4.2 rmind goto nfsmout;
1170 1.1.1.1.4.2 rmind tfhsize = tnfhp->nfh_len;
1171 1.1.1.1.4.2 rmind if (compare) {
1172 1.1.1.1.4.2 rmind if (!(*retcmpp) &&
1173 1.1.1.1.4.2 rmind !NFSRV_CMPFH(tnfhp->nfh_fh, tfhsize,
1174 1.1.1.1.4.2 rmind fhp, fhsize))
1175 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1176 1.1.1.1.4.2 rmind FREE((caddr_t)tnfhp, M_NFSFH);
1177 1.1.1.1.4.2 rmind } else if (nfhpp != NULL) {
1178 1.1.1.1.4.2 rmind *nfhpp = tnfhp;
1179 1.1.1.1.4.2 rmind } else {
1180 1.1.1.1.4.2 rmind FREE((caddr_t)tnfhp, M_NFSFH);
1181 1.1.1.1.4.2 rmind }
1182 1.1.1.1.4.2 rmind attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(tfhsize));
1183 1.1.1.1.4.2 rmind break;
1184 1.1.1.1.4.2 rmind case NFSATTRBIT_FILEID:
1185 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1186 1.1.1.1.4.2 rmind thyp = fxdr_hyper(tl);
1187 1.1.1.1.4.2 rmind if (compare) {
1188 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1189 1.1.1.1.4.2 rmind if ((u_int64_t)nap->na_fileid != thyp)
1190 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1191 1.1.1.1.4.2 rmind }
1192 1.1.1.1.4.2 rmind } else if (nap != NULL) {
1193 1.1.1.1.4.2 rmind if (*tl++)
1194 1.1.1.1.4.2 rmind printf("NFSv4 fileid > 32bits\n");
1195 1.1.1.1.4.2 rmind nap->na_fileid = thyp;
1196 1.1.1.1.4.2 rmind }
1197 1.1.1.1.4.2 rmind attrsum += NFSX_HYPER;
1198 1.1.1.1.4.2 rmind break;
1199 1.1.1.1.4.2 rmind case NFSATTRBIT_FILESAVAIL:
1200 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1201 1.1.1.1.4.2 rmind if (compare) {
1202 1.1.1.1.4.2 rmind if (!(*retcmpp) &&
1203 1.1.1.1.4.2 rmind sfp->sf_afiles != fxdr_hyper(tl))
1204 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1205 1.1.1.1.4.2 rmind } else if (sfp != NULL) {
1206 1.1.1.1.4.2 rmind sfp->sf_afiles = fxdr_hyper(tl);
1207 1.1.1.1.4.2 rmind }
1208 1.1.1.1.4.2 rmind attrsum += NFSX_HYPER;
1209 1.1.1.1.4.2 rmind break;
1210 1.1.1.1.4.2 rmind case NFSATTRBIT_FILESFREE:
1211 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1212 1.1.1.1.4.2 rmind if (compare) {
1213 1.1.1.1.4.2 rmind if (!(*retcmpp) &&
1214 1.1.1.1.4.2 rmind sfp->sf_ffiles != fxdr_hyper(tl))
1215 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1216 1.1.1.1.4.2 rmind } else if (sfp != NULL) {
1217 1.1.1.1.4.2 rmind sfp->sf_ffiles = fxdr_hyper(tl);
1218 1.1.1.1.4.2 rmind }
1219 1.1.1.1.4.2 rmind attrsum += NFSX_HYPER;
1220 1.1.1.1.4.2 rmind break;
1221 1.1.1.1.4.2 rmind case NFSATTRBIT_FILESTOTAL:
1222 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1223 1.1.1.1.4.2 rmind if (compare) {
1224 1.1.1.1.4.2 rmind if (!(*retcmpp) &&
1225 1.1.1.1.4.2 rmind sfp->sf_tfiles != fxdr_hyper(tl))
1226 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1227 1.1.1.1.4.2 rmind } else if (sfp != NULL) {
1228 1.1.1.1.4.2 rmind sfp->sf_tfiles = fxdr_hyper(tl);
1229 1.1.1.1.4.2 rmind }
1230 1.1.1.1.4.2 rmind attrsum += NFSX_HYPER;
1231 1.1.1.1.4.2 rmind break;
1232 1.1.1.1.4.2 rmind case NFSATTRBIT_FSLOCATIONS:
1233 1.1.1.1.4.2 rmind error = nfsrv_getrefstr(nd, &cp, &cp2, &l, &m);
1234 1.1.1.1.4.2 rmind if (error)
1235 1.1.1.1.4.2 rmind goto nfsmout;
1236 1.1.1.1.4.2 rmind attrsum += l;
1237 1.1.1.1.4.2 rmind if (compare && !(*retcmpp)) {
1238 1.1.1.1.4.2 rmind refp = nfsv4root_getreferral(vp, NULL, 0);
1239 1.1.1.1.4.2 rmind if (refp != NULL) {
1240 1.1.1.1.4.2 rmind if (cp == NULL || cp2 == NULL ||
1241 1.1.1.1.4.2 rmind strcmp(cp, "/") ||
1242 1.1.1.1.4.2 rmind strcmp(cp2, refp->nfr_srvlist))
1243 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1244 1.1.1.1.4.2 rmind } else if (m == 0) {
1245 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1246 1.1.1.1.4.2 rmind }
1247 1.1.1.1.4.2 rmind }
1248 1.1.1.1.4.2 rmind if (cp != NULL)
1249 1.1.1.1.4.2 rmind free(cp, M_NFSSTRING);
1250 1.1.1.1.4.2 rmind if (cp2 != NULL)
1251 1.1.1.1.4.2 rmind free(cp2, M_NFSSTRING);
1252 1.1.1.1.4.2 rmind break;
1253 1.1.1.1.4.2 rmind case NFSATTRBIT_HIDDEN:
1254 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1255 1.1.1.1.4.2 rmind if (compare && !(*retcmpp))
1256 1.1.1.1.4.2 rmind *retcmpp = NFSERR_ATTRNOTSUPP;
1257 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1258 1.1.1.1.4.2 rmind break;
1259 1.1.1.1.4.2 rmind case NFSATTRBIT_HOMOGENEOUS:
1260 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1261 1.1.1.1.4.2 rmind if (compare) {
1262 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1263 1.1.1.1.4.2 rmind if (fsp->fs_properties &
1264 1.1.1.1.4.2 rmind NFSV3_FSFHOMOGENEOUS) {
1265 1.1.1.1.4.2 rmind if (*tl == newnfs_false)
1266 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1267 1.1.1.1.4.2 rmind } else {
1268 1.1.1.1.4.2 rmind if (*tl == newnfs_true)
1269 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1270 1.1.1.1.4.2 rmind }
1271 1.1.1.1.4.2 rmind }
1272 1.1.1.1.4.2 rmind } else if (fsp != NULL) {
1273 1.1.1.1.4.2 rmind if (*tl == newnfs_true)
1274 1.1.1.1.4.2 rmind fsp->fs_properties |= NFSV3_FSFHOMOGENEOUS;
1275 1.1.1.1.4.2 rmind else
1276 1.1.1.1.4.2 rmind fsp->fs_properties &= ~NFSV3_FSFHOMOGENEOUS;
1277 1.1.1.1.4.2 rmind }
1278 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1279 1.1.1.1.4.2 rmind break;
1280 1.1.1.1.4.2 rmind case NFSATTRBIT_MAXFILESIZE:
1281 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1282 1.1.1.1.4.2 rmind tnfsquad.qval = fxdr_hyper(tl);
1283 1.1.1.1.4.2 rmind if (compare) {
1284 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1285 1.1.1.1.4.2 rmind tquad = NFSRV_MAXFILESIZE;
1286 1.1.1.1.4.2 rmind if (tquad != tnfsquad.qval)
1287 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1288 1.1.1.1.4.2 rmind }
1289 1.1.1.1.4.2 rmind } else if (fsp != NULL) {
1290 1.1.1.1.4.2 rmind fsp->fs_maxfilesize = tnfsquad.qval;
1291 1.1.1.1.4.2 rmind }
1292 1.1.1.1.4.2 rmind attrsum += NFSX_HYPER;
1293 1.1.1.1.4.2 rmind break;
1294 1.1.1.1.4.2 rmind case NFSATTRBIT_MAXLINK:
1295 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1296 1.1.1.1.4.2 rmind if (compare) {
1297 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1298 1.1.1.1.4.2 rmind if (fxdr_unsigned(int, *tl) != LINK_MAX)
1299 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1300 1.1.1.1.4.2 rmind }
1301 1.1.1.1.4.2 rmind } else if (pc != NULL) {
1302 1.1.1.1.4.2 rmind pc->pc_linkmax = fxdr_unsigned(u_int32_t, *tl);
1303 1.1.1.1.4.2 rmind }
1304 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1305 1.1.1.1.4.2 rmind break;
1306 1.1.1.1.4.2 rmind case NFSATTRBIT_MAXNAME:
1307 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1308 1.1.1.1.4.2 rmind if (compare) {
1309 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1310 1.1.1.1.4.2 rmind if (fsp->fs_maxname !=
1311 1.1.1.1.4.2 rmind fxdr_unsigned(u_int32_t, *tl))
1312 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1313 1.1.1.1.4.2 rmind }
1314 1.1.1.1.4.2 rmind } else {
1315 1.1.1.1.4.2 rmind tuint = fxdr_unsigned(u_int32_t, *tl);
1316 1.1.1.1.4.2 rmind /*
1317 1.1.1.1.4.2 rmind * Some Linux NFSv4 servers report this
1318 1.1.1.1.4.2 rmind * as 0 or 4billion, so I'll set it to
1319 1.1.1.1.4.2 rmind * NFS_MAXNAMLEN. If a server actually creates
1320 1.1.1.1.4.2 rmind * a name longer than NFS_MAXNAMLEN, it will
1321 1.1.1.1.4.2 rmind * get an error back.
1322 1.1.1.1.4.2 rmind */
1323 1.1.1.1.4.2 rmind if (tuint == 0 || tuint > NFS_MAXNAMLEN)
1324 1.1.1.1.4.2 rmind tuint = NFS_MAXNAMLEN;
1325 1.1.1.1.4.2 rmind if (fsp != NULL)
1326 1.1.1.1.4.2 rmind fsp->fs_maxname = tuint;
1327 1.1.1.1.4.2 rmind if (pc != NULL)
1328 1.1.1.1.4.2 rmind pc->pc_namemax = tuint;
1329 1.1.1.1.4.2 rmind }
1330 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1331 1.1.1.1.4.2 rmind break;
1332 1.1.1.1.4.2 rmind case NFSATTRBIT_MAXREAD:
1333 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1334 1.1.1.1.4.2 rmind if (compare) {
1335 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1336 1.1.1.1.4.2 rmind if (fsp->fs_rtmax != fxdr_unsigned(u_int32_t,
1337 1.1.1.1.4.2 rmind *(tl + 1)) || *tl != 0)
1338 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1339 1.1.1.1.4.2 rmind }
1340 1.1.1.1.4.2 rmind } else if (fsp != NULL) {
1341 1.1.1.1.4.2 rmind fsp->fs_rtmax = fxdr_unsigned(u_int32_t, *++tl);
1342 1.1.1.1.4.2 rmind fsp->fs_rtpref = fsp->fs_rtmax;
1343 1.1.1.1.4.2 rmind fsp->fs_dtpref = fsp->fs_rtpref;
1344 1.1.1.1.4.2 rmind }
1345 1.1.1.1.4.2 rmind attrsum += NFSX_HYPER;
1346 1.1.1.1.4.2 rmind break;
1347 1.1.1.1.4.2 rmind case NFSATTRBIT_MAXWRITE:
1348 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1349 1.1.1.1.4.2 rmind if (compare) {
1350 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1351 1.1.1.1.4.2 rmind if (fsp->fs_wtmax != fxdr_unsigned(u_int32_t,
1352 1.1.1.1.4.2 rmind *(tl + 1)) || *tl != 0)
1353 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1354 1.1.1.1.4.2 rmind }
1355 1.1.1.1.4.2 rmind } else if (fsp != NULL) {
1356 1.1.1.1.4.2 rmind fsp->fs_wtmax = fxdr_unsigned(int, *++tl);
1357 1.1.1.1.4.2 rmind fsp->fs_wtpref = fsp->fs_wtmax;
1358 1.1.1.1.4.2 rmind }
1359 1.1.1.1.4.2 rmind attrsum += NFSX_HYPER;
1360 1.1.1.1.4.2 rmind break;
1361 1.1.1.1.4.2 rmind case NFSATTRBIT_MIMETYPE:
1362 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1363 1.1.1.1.4.2 rmind i = fxdr_unsigned(int, *tl);
1364 1.1.1.1.4.2 rmind attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(i));
1365 1.1.1.1.4.2 rmind error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
1366 1.1.1.1.4.2 rmind if (error)
1367 1.1.1.1.4.2 rmind goto nfsmout;
1368 1.1.1.1.4.2 rmind if (compare && !(*retcmpp))
1369 1.1.1.1.4.2 rmind *retcmpp = NFSERR_ATTRNOTSUPP;
1370 1.1.1.1.4.2 rmind break;
1371 1.1.1.1.4.2 rmind case NFSATTRBIT_MODE:
1372 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1373 1.1.1.1.4.2 rmind if (compare) {
1374 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1375 1.1.1.1.4.2 rmind if (nap->na_mode != nfstov_mode(*tl))
1376 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1377 1.1.1.1.4.2 rmind }
1378 1.1.1.1.4.2 rmind } else if (nap != NULL) {
1379 1.1.1.1.4.2 rmind nap->na_mode = nfstov_mode(*tl);
1380 1.1.1.1.4.2 rmind }
1381 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1382 1.1.1.1.4.2 rmind break;
1383 1.1.1.1.4.2 rmind case NFSATTRBIT_NOTRUNC:
1384 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1385 1.1.1.1.4.2 rmind if (compare) {
1386 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1387 1.1.1.1.4.2 rmind if (*tl != newnfs_true)
1388 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1389 1.1.1.1.4.2 rmind }
1390 1.1.1.1.4.2 rmind } else if (pc != NULL) {
1391 1.1.1.1.4.2 rmind pc->pc_notrunc = fxdr_unsigned(u_int32_t, *tl);
1392 1.1.1.1.4.2 rmind }
1393 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1394 1.1.1.1.4.2 rmind break;
1395 1.1.1.1.4.2 rmind case NFSATTRBIT_NUMLINKS:
1396 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1397 1.1.1.1.4.2 rmind tuint = fxdr_unsigned(u_int32_t, *tl);
1398 1.1.1.1.4.2 rmind if (compare) {
1399 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1400 1.1.1.1.4.2 rmind if ((u_int32_t)nap->na_nlink != tuint)
1401 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1402 1.1.1.1.4.2 rmind }
1403 1.1.1.1.4.2 rmind } else if (nap != NULL) {
1404 1.1.1.1.4.2 rmind nap->na_nlink = tuint;
1405 1.1.1.1.4.2 rmind }
1406 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1407 1.1.1.1.4.2 rmind break;
1408 1.1.1.1.4.2 rmind case NFSATTRBIT_OWNER:
1409 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1410 1.1.1.1.4.2 rmind j = fxdr_unsigned(int, *tl);
1411 1.1.1.1.4.2 rmind if (j < 0) {
1412 1.1.1.1.4.2 rmind error = NFSERR_BADXDR;
1413 1.1.1.1.4.2 rmind goto nfsmout;
1414 1.1.1.1.4.2 rmind }
1415 1.1.1.1.4.2 rmind attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(j));
1416 1.1.1.1.4.2 rmind if (j > NFSV4_SMALLSTR)
1417 1.1.1.1.4.2 rmind cp = malloc(j + 1, M_NFSSTRING, M_WAITOK);
1418 1.1.1.1.4.2 rmind else
1419 1.1.1.1.4.2 rmind cp = namestr;
1420 1.1.1.1.4.2 rmind error = nfsrv_mtostr(nd, cp, j);
1421 1.1.1.1.4.2 rmind if (error) {
1422 1.1.1.1.4.2 rmind if (j > NFSV4_SMALLSTR)
1423 1.1.1.1.4.2 rmind free(cp, M_NFSSTRING);
1424 1.1.1.1.4.2 rmind goto nfsmout;
1425 1.1.1.1.4.2 rmind }
1426 1.1.1.1.4.2 rmind if (compare) {
1427 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1428 1.1.1.1.4.2 rmind if (nfsv4_strtouid(nd, cp, j, &uid, p) ||
1429 1.1.1.1.4.2 rmind nap->na_uid != uid)
1430 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1431 1.1.1.1.4.2 rmind }
1432 1.1.1.1.4.2 rmind } else if (nap != NULL) {
1433 1.1.1.1.4.2 rmind if (nfsv4_strtouid(nd, cp, j, &uid, p))
1434 1.1.1.1.4.2 rmind nap->na_uid = nfsrv_defaultuid;
1435 1.1.1.1.4.2 rmind else
1436 1.1.1.1.4.2 rmind nap->na_uid = uid;
1437 1.1.1.1.4.2 rmind }
1438 1.1.1.1.4.2 rmind if (j > NFSV4_SMALLSTR)
1439 1.1.1.1.4.2 rmind free(cp, M_NFSSTRING);
1440 1.1.1.1.4.2 rmind break;
1441 1.1.1.1.4.2 rmind case NFSATTRBIT_OWNERGROUP:
1442 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1443 1.1.1.1.4.2 rmind j = fxdr_unsigned(int, *tl);
1444 1.1.1.1.4.2 rmind if (j < 0) {
1445 1.1.1.1.4.2 rmind error = NFSERR_BADXDR;
1446 1.1.1.1.4.2 rmind goto nfsmout;
1447 1.1.1.1.4.2 rmind }
1448 1.1.1.1.4.2 rmind attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(j));
1449 1.1.1.1.4.2 rmind if (j > NFSV4_SMALLSTR)
1450 1.1.1.1.4.2 rmind cp = malloc(j + 1, M_NFSSTRING, M_WAITOK);
1451 1.1.1.1.4.2 rmind else
1452 1.1.1.1.4.2 rmind cp = namestr;
1453 1.1.1.1.4.2 rmind error = nfsrv_mtostr(nd, cp, j);
1454 1.1.1.1.4.2 rmind if (error) {
1455 1.1.1.1.4.2 rmind if (j > NFSV4_SMALLSTR)
1456 1.1.1.1.4.2 rmind free(cp, M_NFSSTRING);
1457 1.1.1.1.4.2 rmind goto nfsmout;
1458 1.1.1.1.4.2 rmind }
1459 1.1.1.1.4.2 rmind if (compare) {
1460 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1461 1.1.1.1.4.2 rmind if (nfsv4_strtogid(nd, cp, j, &gid, p) ||
1462 1.1.1.1.4.2 rmind nap->na_gid != gid)
1463 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1464 1.1.1.1.4.2 rmind }
1465 1.1.1.1.4.2 rmind } else if (nap != NULL) {
1466 1.1.1.1.4.2 rmind if (nfsv4_strtogid(nd, cp, j, &gid, p))
1467 1.1.1.1.4.2 rmind nap->na_gid = nfsrv_defaultgid;
1468 1.1.1.1.4.2 rmind else
1469 1.1.1.1.4.2 rmind nap->na_gid = gid;
1470 1.1.1.1.4.2 rmind }
1471 1.1.1.1.4.2 rmind if (j > NFSV4_SMALLSTR)
1472 1.1.1.1.4.2 rmind free(cp, M_NFSSTRING);
1473 1.1.1.1.4.2 rmind break;
1474 1.1.1.1.4.2 rmind case NFSATTRBIT_QUOTAHARD:
1475 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1476 1.1.1.1.4.2 rmind if (sbp != NULL) {
1477 1.1.1.1.4.2 rmind if (priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA, 0))
1478 1.1.1.1.4.2 rmind freenum = sbp->f_bfree;
1479 1.1.1.1.4.2 rmind else
1480 1.1.1.1.4.2 rmind freenum = sbp->f_bavail;
1481 1.1.1.1.4.2 rmind #ifdef QUOTA
1482 1.1.1.1.4.2 rmind /*
1483 1.1.1.1.4.2 rmind * ufs_quotactl() insists that the uid argument
1484 1.1.1.1.4.2 rmind * equal p_ruid for non-root quota access, so
1485 1.1.1.1.4.2 rmind * we'll just make sure that's the case.
1486 1.1.1.1.4.2 rmind */
1487 1.1.1.1.4.2 rmind savuid = p->p_cred->p_ruid;
1488 1.1.1.1.4.2 rmind p->p_cred->p_ruid = cred->cr_uid;
1489 1.1.1.1.4.2 rmind if (!VFS_QUOTACTL(vnode_mount(vp),QCMD(Q_GETQUOTA,
1490 1.1.1.1.4.2 rmind USRQUOTA), cred->cr_uid, (caddr_t)&dqb))
1491 1.1.1.1.4.2 rmind freenum = min(dqb.dqb_bhardlimit, freenum);
1492 1.1.1.1.4.2 rmind p->p_cred->p_ruid = savuid;
1493 1.1.1.1.4.2 rmind #endif /* QUOTA */
1494 1.1.1.1.4.2 rmind uquad = (u_int64_t)freenum;
1495 1.1.1.1.4.2 rmind NFSQUOTABLKTOBYTE(uquad, sbp->f_bsize);
1496 1.1.1.1.4.2 rmind }
1497 1.1.1.1.4.2 rmind if (compare && !(*retcmpp)) {
1498 1.1.1.1.4.2 rmind if (uquad != fxdr_hyper(tl))
1499 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1500 1.1.1.1.4.2 rmind }
1501 1.1.1.1.4.2 rmind attrsum += NFSX_HYPER;
1502 1.1.1.1.4.2 rmind break;
1503 1.1.1.1.4.2 rmind case NFSATTRBIT_QUOTASOFT:
1504 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1505 1.1.1.1.4.2 rmind if (sbp != NULL) {
1506 1.1.1.1.4.2 rmind if (priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA, 0))
1507 1.1.1.1.4.2 rmind freenum = sbp->f_bfree;
1508 1.1.1.1.4.2 rmind else
1509 1.1.1.1.4.2 rmind freenum = sbp->f_bavail;
1510 1.1.1.1.4.2 rmind #ifdef QUOTA
1511 1.1.1.1.4.2 rmind /*
1512 1.1.1.1.4.2 rmind * ufs_quotactl() insists that the uid argument
1513 1.1.1.1.4.2 rmind * equal p_ruid for non-root quota access, so
1514 1.1.1.1.4.2 rmind * we'll just make sure that's the case.
1515 1.1.1.1.4.2 rmind */
1516 1.1.1.1.4.2 rmind savuid = p->p_cred->p_ruid;
1517 1.1.1.1.4.2 rmind p->p_cred->p_ruid = cred->cr_uid;
1518 1.1.1.1.4.2 rmind if (!VFS_QUOTACTL(vnode_mount(vp),QCMD(Q_GETQUOTA,
1519 1.1.1.1.4.2 rmind USRQUOTA), cred->cr_uid, (caddr_t)&dqb))
1520 1.1.1.1.4.2 rmind freenum = min(dqb.dqb_bsoftlimit, freenum);
1521 1.1.1.1.4.2 rmind p->p_cred->p_ruid = savuid;
1522 1.1.1.1.4.2 rmind #endif /* QUOTA */
1523 1.1.1.1.4.2 rmind uquad = (u_int64_t)freenum;
1524 1.1.1.1.4.2 rmind NFSQUOTABLKTOBYTE(uquad, sbp->f_bsize);
1525 1.1.1.1.4.2 rmind }
1526 1.1.1.1.4.2 rmind if (compare && !(*retcmpp)) {
1527 1.1.1.1.4.2 rmind if (uquad != fxdr_hyper(tl))
1528 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1529 1.1.1.1.4.2 rmind }
1530 1.1.1.1.4.2 rmind attrsum += NFSX_HYPER;
1531 1.1.1.1.4.2 rmind break;
1532 1.1.1.1.4.2 rmind case NFSATTRBIT_QUOTAUSED:
1533 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1534 1.1.1.1.4.2 rmind if (sbp != NULL) {
1535 1.1.1.1.4.2 rmind freenum = 0;
1536 1.1.1.1.4.2 rmind #ifdef QUOTA
1537 1.1.1.1.4.2 rmind /*
1538 1.1.1.1.4.2 rmind * ufs_quotactl() insists that the uid argument
1539 1.1.1.1.4.2 rmind * equal p_ruid for non-root quota access, so
1540 1.1.1.1.4.2 rmind * we'll just make sure that's the case.
1541 1.1.1.1.4.2 rmind */
1542 1.1.1.1.4.2 rmind savuid = p->p_cred->p_ruid;
1543 1.1.1.1.4.2 rmind p->p_cred->p_ruid = cred->cr_uid;
1544 1.1.1.1.4.2 rmind if (!VFS_QUOTACTL(vnode_mount(vp),QCMD(Q_GETQUOTA,
1545 1.1.1.1.4.2 rmind USRQUOTA), cred->cr_uid, (caddr_t)&dqb))
1546 1.1.1.1.4.2 rmind freenum = dqb.dqb_curblocks;
1547 1.1.1.1.4.2 rmind p->p_cred->p_ruid = savuid;
1548 1.1.1.1.4.2 rmind #endif /* QUOTA */
1549 1.1.1.1.4.2 rmind uquad = (u_int64_t)freenum;
1550 1.1.1.1.4.2 rmind NFSQUOTABLKTOBYTE(uquad, sbp->f_bsize);
1551 1.1.1.1.4.2 rmind }
1552 1.1.1.1.4.2 rmind if (compare && !(*retcmpp)) {
1553 1.1.1.1.4.2 rmind if (uquad != fxdr_hyper(tl))
1554 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1555 1.1.1.1.4.2 rmind }
1556 1.1.1.1.4.2 rmind attrsum += NFSX_HYPER;
1557 1.1.1.1.4.2 rmind break;
1558 1.1.1.1.4.2 rmind case NFSATTRBIT_RAWDEV:
1559 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_V4SPECDATA);
1560 1.1.1.1.4.2 rmind j = fxdr_unsigned(int, *tl++);
1561 1.1.1.1.4.2 rmind k = fxdr_unsigned(int, *tl);
1562 1.1.1.1.4.2 rmind if (compare) {
1563 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1564 1.1.1.1.4.2 rmind if (nap->na_rdev != NFSMAKEDEV(j, k))
1565 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1566 1.1.1.1.4.2 rmind }
1567 1.1.1.1.4.2 rmind } else if (nap != NULL) {
1568 1.1.1.1.4.2 rmind nap->na_rdev = NFSMAKEDEV(j, k);
1569 1.1.1.1.4.2 rmind }
1570 1.1.1.1.4.2 rmind attrsum += NFSX_V4SPECDATA;
1571 1.1.1.1.4.2 rmind break;
1572 1.1.1.1.4.2 rmind case NFSATTRBIT_SPACEAVAIL:
1573 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1574 1.1.1.1.4.2 rmind if (compare) {
1575 1.1.1.1.4.2 rmind if (!(*retcmpp) &&
1576 1.1.1.1.4.2 rmind sfp->sf_abytes != fxdr_hyper(tl))
1577 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1578 1.1.1.1.4.2 rmind } else if (sfp != NULL) {
1579 1.1.1.1.4.2 rmind sfp->sf_abytes = fxdr_hyper(tl);
1580 1.1.1.1.4.2 rmind }
1581 1.1.1.1.4.2 rmind attrsum += NFSX_HYPER;
1582 1.1.1.1.4.2 rmind break;
1583 1.1.1.1.4.2 rmind case NFSATTRBIT_SPACEFREE:
1584 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1585 1.1.1.1.4.2 rmind if (compare) {
1586 1.1.1.1.4.2 rmind if (!(*retcmpp) &&
1587 1.1.1.1.4.2 rmind sfp->sf_fbytes != fxdr_hyper(tl))
1588 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1589 1.1.1.1.4.2 rmind } else if (sfp != NULL) {
1590 1.1.1.1.4.2 rmind sfp->sf_fbytes = fxdr_hyper(tl);
1591 1.1.1.1.4.2 rmind }
1592 1.1.1.1.4.2 rmind attrsum += NFSX_HYPER;
1593 1.1.1.1.4.2 rmind break;
1594 1.1.1.1.4.2 rmind case NFSATTRBIT_SPACETOTAL:
1595 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1596 1.1.1.1.4.2 rmind if (compare) {
1597 1.1.1.1.4.2 rmind if (!(*retcmpp) &&
1598 1.1.1.1.4.2 rmind sfp->sf_tbytes != fxdr_hyper(tl))
1599 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1600 1.1.1.1.4.2 rmind } else if (sfp != NULL) {
1601 1.1.1.1.4.2 rmind sfp->sf_tbytes = fxdr_hyper(tl);
1602 1.1.1.1.4.2 rmind }
1603 1.1.1.1.4.2 rmind attrsum += NFSX_HYPER;
1604 1.1.1.1.4.2 rmind break;
1605 1.1.1.1.4.2 rmind case NFSATTRBIT_SPACEUSED:
1606 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1607 1.1.1.1.4.2 rmind thyp = fxdr_hyper(tl);
1608 1.1.1.1.4.2 rmind if (compare) {
1609 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1610 1.1.1.1.4.2 rmind if ((u_int64_t)nap->na_bytes != thyp)
1611 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1612 1.1.1.1.4.2 rmind }
1613 1.1.1.1.4.2 rmind } else if (nap != NULL) {
1614 1.1.1.1.4.2 rmind nap->na_bytes = thyp;
1615 1.1.1.1.4.2 rmind }
1616 1.1.1.1.4.2 rmind attrsum += NFSX_HYPER;
1617 1.1.1.1.4.2 rmind break;
1618 1.1.1.1.4.2 rmind case NFSATTRBIT_SYSTEM:
1619 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1620 1.1.1.1.4.2 rmind if (compare && !(*retcmpp))
1621 1.1.1.1.4.2 rmind *retcmpp = NFSERR_ATTRNOTSUPP;
1622 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1623 1.1.1.1.4.2 rmind break;
1624 1.1.1.1.4.2 rmind case NFSATTRBIT_TIMEACCESS:
1625 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
1626 1.1.1.1.4.2 rmind fxdr_nfsv4time(tl, &temptime);
1627 1.1.1.1.4.2 rmind if (compare) {
1628 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1629 1.1.1.1.4.2 rmind if (!NFS_CMPTIME(temptime, nap->na_atime))
1630 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1631 1.1.1.1.4.2 rmind }
1632 1.1.1.1.4.2 rmind } else if (nap != NULL) {
1633 1.1.1.1.4.2 rmind nap->na_atime = temptime;
1634 1.1.1.1.4.2 rmind }
1635 1.1.1.1.4.2 rmind attrsum += NFSX_V4TIME;
1636 1.1.1.1.4.2 rmind break;
1637 1.1.1.1.4.2 rmind case NFSATTRBIT_TIMEACCESSSET:
1638 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1639 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1640 1.1.1.1.4.2 rmind i = fxdr_unsigned(int, *tl);
1641 1.1.1.1.4.2 rmind if (i == NFSV4SATTRTIME_TOCLIENT) {
1642 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
1643 1.1.1.1.4.2 rmind attrsum += NFSX_V4TIME;
1644 1.1.1.1.4.2 rmind }
1645 1.1.1.1.4.2 rmind if (compare && !(*retcmpp))
1646 1.1.1.1.4.2 rmind *retcmpp = NFSERR_INVAL;
1647 1.1.1.1.4.2 rmind break;
1648 1.1.1.1.4.2 rmind case NFSATTRBIT_TIMEBACKUP:
1649 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
1650 1.1.1.1.4.2 rmind if (compare && !(*retcmpp))
1651 1.1.1.1.4.2 rmind *retcmpp = NFSERR_ATTRNOTSUPP;
1652 1.1.1.1.4.2 rmind attrsum += NFSX_V4TIME;
1653 1.1.1.1.4.2 rmind break;
1654 1.1.1.1.4.2 rmind case NFSATTRBIT_TIMECREATE:
1655 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
1656 1.1.1.1.4.2 rmind if (compare && !(*retcmpp))
1657 1.1.1.1.4.2 rmind *retcmpp = NFSERR_ATTRNOTSUPP;
1658 1.1.1.1.4.2 rmind attrsum += NFSX_V4TIME;
1659 1.1.1.1.4.2 rmind break;
1660 1.1.1.1.4.2 rmind case NFSATTRBIT_TIMEDELTA:
1661 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
1662 1.1.1.1.4.2 rmind if (fsp != NULL) {
1663 1.1.1.1.4.2 rmind if (compare) {
1664 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1665 1.1.1.1.4.2 rmind if ((u_int32_t)fsp->fs_timedelta.tv_sec !=
1666 1.1.1.1.4.2 rmind fxdr_unsigned(u_int32_t, *(tl + 1)) ||
1667 1.1.1.1.4.2 rmind (u_int32_t)fsp->fs_timedelta.tv_nsec !=
1668 1.1.1.1.4.2 rmind (fxdr_unsigned(u_int32_t, *(tl + 2)) %
1669 1.1.1.1.4.2 rmind 1000000000) ||
1670 1.1.1.1.4.2 rmind *tl != 0)
1671 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1672 1.1.1.1.4.2 rmind }
1673 1.1.1.1.4.2 rmind } else {
1674 1.1.1.1.4.2 rmind fxdr_nfsv4time(tl, &fsp->fs_timedelta);
1675 1.1.1.1.4.2 rmind }
1676 1.1.1.1.4.2 rmind }
1677 1.1.1.1.4.2 rmind attrsum += NFSX_V4TIME;
1678 1.1.1.1.4.2 rmind break;
1679 1.1.1.1.4.2 rmind case NFSATTRBIT_TIMEMETADATA:
1680 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
1681 1.1.1.1.4.2 rmind fxdr_nfsv4time(tl, &temptime);
1682 1.1.1.1.4.2 rmind if (compare) {
1683 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1684 1.1.1.1.4.2 rmind if (!NFS_CMPTIME(temptime, nap->na_ctime))
1685 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1686 1.1.1.1.4.2 rmind }
1687 1.1.1.1.4.2 rmind } else if (nap != NULL) {
1688 1.1.1.1.4.2 rmind nap->na_ctime = temptime;
1689 1.1.1.1.4.2 rmind }
1690 1.1.1.1.4.2 rmind attrsum += NFSX_V4TIME;
1691 1.1.1.1.4.2 rmind break;
1692 1.1.1.1.4.2 rmind case NFSATTRBIT_TIMEMODIFY:
1693 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
1694 1.1.1.1.4.2 rmind fxdr_nfsv4time(tl, &temptime);
1695 1.1.1.1.4.2 rmind if (compare) {
1696 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1697 1.1.1.1.4.2 rmind if (!NFS_CMPTIME(temptime, nap->na_mtime))
1698 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1699 1.1.1.1.4.2 rmind }
1700 1.1.1.1.4.2 rmind } else if (nap != NULL) {
1701 1.1.1.1.4.2 rmind nap->na_mtime = temptime;
1702 1.1.1.1.4.2 rmind }
1703 1.1.1.1.4.2 rmind attrsum += NFSX_V4TIME;
1704 1.1.1.1.4.2 rmind break;
1705 1.1.1.1.4.2 rmind case NFSATTRBIT_TIMEMODIFYSET:
1706 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1707 1.1.1.1.4.2 rmind attrsum += NFSX_UNSIGNED;
1708 1.1.1.1.4.2 rmind i = fxdr_unsigned(int, *tl);
1709 1.1.1.1.4.2 rmind if (i == NFSV4SATTRTIME_TOCLIENT) {
1710 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
1711 1.1.1.1.4.2 rmind attrsum += NFSX_V4TIME;
1712 1.1.1.1.4.2 rmind }
1713 1.1.1.1.4.2 rmind if (compare && !(*retcmpp))
1714 1.1.1.1.4.2 rmind *retcmpp = NFSERR_INVAL;
1715 1.1.1.1.4.2 rmind break;
1716 1.1.1.1.4.2 rmind case NFSATTRBIT_MOUNTEDONFILEID:
1717 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
1718 1.1.1.1.4.2 rmind thyp = fxdr_hyper(tl);
1719 1.1.1.1.4.2 rmind if (compare) {
1720 1.1.1.1.4.2 rmind if (!(*retcmpp)) {
1721 1.1.1.1.4.2 rmind if (*tl++) {
1722 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1723 1.1.1.1.4.2 rmind } else {
1724 1.1.1.1.4.2 rmind if (!vp || !nfsrv_atroot(vp, &fid))
1725 1.1.1.1.4.2 rmind fid = nap->na_fileid;
1726 1.1.1.1.4.2 rmind if ((u_int64_t)fid != thyp)
1727 1.1.1.1.4.2 rmind *retcmpp = NFSERR_NOTSAME;
1728 1.1.1.1.4.2 rmind }
1729 1.1.1.1.4.2 rmind }
1730 1.1.1.1.4.2 rmind } else if (nap != NULL) {
1731 1.1.1.1.4.2 rmind if (*tl++)
1732 1.1.1.1.4.2 rmind printf("NFSv4 mounted on fileid > 32bits\n");
1733 1.1.1.1.4.2 rmind nap->na_mntonfileno = thyp;
1734 1.1.1.1.4.2 rmind }
1735 1.1.1.1.4.2 rmind attrsum += NFSX_HYPER;
1736 1.1.1.1.4.2 rmind break;
1737 1.1.1.1.4.2 rmind default:
1738 1.1.1.1.4.2 rmind printf("EEK! nfsv4_loadattr unknown attr=%d\n",
1739 1.1.1.1.4.2 rmind bitpos);
1740 1.1.1.1.4.2 rmind if (compare && !(*retcmpp))
1741 1.1.1.1.4.2 rmind *retcmpp = NFSERR_ATTRNOTSUPP;
1742 1.1.1.1.4.2 rmind /*
1743 1.1.1.1.4.2 rmind * and get out of the loop, since we can't parse
1744 1.1.1.1.4.2 rmind * the unknown attrbute data.
1745 1.1.1.1.4.2 rmind */
1746 1.1.1.1.4.2 rmind bitpos = NFSATTRBIT_MAX;
1747 1.1.1.1.4.2 rmind break;
1748 1.1.1.1.4.2 rmind };
1749 1.1.1.1.4.2 rmind }
1750 1.1.1.1.4.2 rmind
1751 1.1.1.1.4.2 rmind /*
1752 1.1.1.1.4.2 rmind * some clients pad the attrlist, so we need to skip over the
1753 1.1.1.1.4.2 rmind * padding.
1754 1.1.1.1.4.2 rmind */
1755 1.1.1.1.4.2 rmind if (attrsum > attrsize) {
1756 1.1.1.1.4.2 rmind error = NFSERR_BADXDR;
1757 1.1.1.1.4.2 rmind } else {
1758 1.1.1.1.4.2 rmind attrsize = NFSM_RNDUP(attrsize);
1759 1.1.1.1.4.2 rmind if (attrsum < attrsize)
1760 1.1.1.1.4.2 rmind error = nfsm_advance(nd, attrsize - attrsum, -1);
1761 1.1.1.1.4.2 rmind }
1762 1.1.1.1.4.2 rmind nfsmout:
1763 1.1.1.1.4.2 rmind NFSEXITCODE2(error, nd);
1764 1.1.1.1.4.2 rmind return (error);
1765 1.1.1.1.4.2 rmind }
1766 1.1.1.1.4.2 rmind
1767 1.1.1.1.4.2 rmind /*
1768 1.1.1.1.4.2 rmind * Implement sleep locks for newnfs. The nfslock_usecnt allows for a
1769 1.1.1.1.4.2 rmind * shared lock and the NFSXXX_LOCK flag permits an exclusive lock.
1770 1.1.1.1.4.2 rmind * The first argument is a pointer to an nfsv4lock structure.
1771 1.1.1.1.4.2 rmind * The second argument is 1 iff a blocking lock is wanted.
1772 1.1.1.1.4.2 rmind * If this argument is 0, the call waits until no thread either wants nor
1773 1.1.1.1.4.2 rmind * holds an exclusive lock.
1774 1.1.1.1.4.2 rmind * It returns 1 if the lock was acquired, 0 otherwise.
1775 1.1.1.1.4.2 rmind * If several processes call this function concurrently wanting the exclusive
1776 1.1.1.1.4.2 rmind * lock, one will get the lock and the rest will return without getting the
1777 1.1.1.1.4.2 rmind * lock. (If the caller must have the lock, it simply calls this function in a
1778 1.1.1.1.4.2 rmind * loop until the function returns 1 to indicate the lock was acquired.)
1779 1.1.1.1.4.2 rmind * Any usecnt must be decremented by calling nfsv4_relref() before
1780 1.1.1.1.4.2 rmind * calling nfsv4_lock(). It was done this way, so nfsv4_lock() could
1781 1.1.1.1.4.2 rmind * be called in a loop.
1782 1.1.1.1.4.2 rmind * The isleptp argument is set to indicate if the call slept, iff not NULL
1783 1.1.1.1.4.2 rmind * and the mp argument indicates to check for a forced dismount, iff not
1784 1.1.1.1.4.2 rmind * NULL.
1785 1.1.1.1.4.2 rmind */
1786 1.1.1.1.4.2 rmind APPLESTATIC int
1787 1.1.1.1.4.2 rmind nfsv4_lock(struct nfsv4lock *lp, int iwantlock, int *isleptp,
1788 1.1.1.1.4.2 rmind void *mutex, struct mount *mp)
1789 1.1.1.1.4.2 rmind {
1790 1.1.1.1.4.2 rmind
1791 1.1.1.1.4.2 rmind if (isleptp)
1792 1.1.1.1.4.2 rmind *isleptp = 0;
1793 1.1.1.1.4.2 rmind /*
1794 1.1.1.1.4.2 rmind * If a lock is wanted, loop around until the lock is acquired by
1795 1.1.1.1.4.2 rmind * someone and then released. If I want the lock, try to acquire it.
1796 1.1.1.1.4.2 rmind * For a lock to be issued, no lock must be in force and the usecnt
1797 1.1.1.1.4.2 rmind * must be zero.
1798 1.1.1.1.4.2 rmind */
1799 1.1.1.1.4.2 rmind if (iwantlock) {
1800 1.1.1.1.4.2 rmind if (!(lp->nfslock_lock & NFSV4LOCK_LOCK) &&
1801 1.1.1.1.4.2 rmind lp->nfslock_usecnt == 0) {
1802 1.1.1.1.4.2 rmind lp->nfslock_lock &= ~NFSV4LOCK_LOCKWANTED;
1803 1.1.1.1.4.2 rmind lp->nfslock_lock |= NFSV4LOCK_LOCK;
1804 1.1.1.1.4.2 rmind return (1);
1805 1.1.1.1.4.2 rmind }
1806 1.1.1.1.4.2 rmind lp->nfslock_lock |= NFSV4LOCK_LOCKWANTED;
1807 1.1.1.1.4.2 rmind }
1808 1.1.1.1.4.2 rmind while (lp->nfslock_lock & (NFSV4LOCK_LOCK | NFSV4LOCK_LOCKWANTED)) {
1809 1.1.1.1.4.2 rmind if (mp != NULL && (mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) {
1810 1.1.1.1.4.2 rmind lp->nfslock_lock &= ~NFSV4LOCK_LOCKWANTED;
1811 1.1.1.1.4.2 rmind return (0);
1812 1.1.1.1.4.2 rmind }
1813 1.1.1.1.4.2 rmind lp->nfslock_lock |= NFSV4LOCK_WANTED;
1814 1.1.1.1.4.2 rmind if (isleptp)
1815 1.1.1.1.4.2 rmind *isleptp = 1;
1816 1.1.1.1.4.2 rmind (void) nfsmsleep(&lp->nfslock_lock, mutex,
1817 1.1.1.1.4.2 rmind PZERO - 1, "nfsv4lck", NULL);
1818 1.1.1.1.4.2 rmind if (iwantlock && !(lp->nfslock_lock & NFSV4LOCK_LOCK) &&
1819 1.1.1.1.4.2 rmind lp->nfslock_usecnt == 0) {
1820 1.1.1.1.4.2 rmind lp->nfslock_lock &= ~NFSV4LOCK_LOCKWANTED;
1821 1.1.1.1.4.2 rmind lp->nfslock_lock |= NFSV4LOCK_LOCK;
1822 1.1.1.1.4.2 rmind return (1);
1823 1.1.1.1.4.2 rmind }
1824 1.1.1.1.4.2 rmind }
1825 1.1.1.1.4.2 rmind return (0);
1826 1.1.1.1.4.2 rmind }
1827 1.1.1.1.4.2 rmind
1828 1.1.1.1.4.2 rmind /*
1829 1.1.1.1.4.2 rmind * Release the lock acquired by nfsv4_lock().
1830 1.1.1.1.4.2 rmind * The second argument is set to 1 to indicate the nfslock_usecnt should be
1831 1.1.1.1.4.2 rmind * incremented, as well.
1832 1.1.1.1.4.2 rmind */
1833 1.1.1.1.4.2 rmind APPLESTATIC void
1834 1.1.1.1.4.2 rmind nfsv4_unlock(struct nfsv4lock *lp, int incref)
1835 1.1.1.1.4.2 rmind {
1836 1.1.1.1.4.2 rmind
1837 1.1.1.1.4.2 rmind lp->nfslock_lock &= ~NFSV4LOCK_LOCK;
1838 1.1.1.1.4.2 rmind if (incref)
1839 1.1.1.1.4.2 rmind lp->nfslock_usecnt++;
1840 1.1.1.1.4.2 rmind nfsv4_wanted(lp);
1841 1.1.1.1.4.2 rmind }
1842 1.1.1.1.4.2 rmind
1843 1.1.1.1.4.2 rmind /*
1844 1.1.1.1.4.2 rmind * Release a reference cnt.
1845 1.1.1.1.4.2 rmind */
1846 1.1.1.1.4.2 rmind APPLESTATIC void
1847 1.1.1.1.4.2 rmind nfsv4_relref(struct nfsv4lock *lp)
1848 1.1.1.1.4.2 rmind {
1849 1.1.1.1.4.2 rmind
1850 1.1.1.1.4.2 rmind if (lp->nfslock_usecnt <= 0)
1851 1.1.1.1.4.2 rmind panic("nfsv4root ref cnt");
1852 1.1.1.1.4.2 rmind lp->nfslock_usecnt--;
1853 1.1.1.1.4.2 rmind if (lp->nfslock_usecnt == 0)
1854 1.1.1.1.4.2 rmind nfsv4_wanted(lp);
1855 1.1.1.1.4.2 rmind }
1856 1.1.1.1.4.2 rmind
1857 1.1.1.1.4.2 rmind /*
1858 1.1.1.1.4.2 rmind * Get a reference cnt.
1859 1.1.1.1.4.2 rmind * This function will wait for any exclusive lock to be released, but will
1860 1.1.1.1.4.2 rmind * not wait for threads that want the exclusive lock. If priority needs
1861 1.1.1.1.4.2 rmind * to be given to threads that need the exclusive lock, a call to nfsv4_lock()
1862 1.1.1.1.4.2 rmind * with the 2nd argument == 0 should be done before calling nfsv4_getref().
1863 1.1.1.1.4.2 rmind * If the mp argument is not NULL, check for MNTK_UNMOUNTF being set and
1864 1.1.1.1.4.2 rmind * return without getting a refcnt for that case.
1865 1.1.1.1.4.2 rmind */
1866 1.1.1.1.4.2 rmind APPLESTATIC void
1867 1.1.1.1.4.2 rmind nfsv4_getref(struct nfsv4lock *lp, int *isleptp, void *mutex,
1868 1.1.1.1.4.2 rmind struct mount *mp)
1869 1.1.1.1.4.2 rmind {
1870 1.1.1.1.4.2 rmind
1871 1.1.1.1.4.2 rmind if (isleptp)
1872 1.1.1.1.4.2 rmind *isleptp = 0;
1873 1.1.1.1.4.2 rmind
1874 1.1.1.1.4.2 rmind /*
1875 1.1.1.1.4.2 rmind * Wait for a lock held.
1876 1.1.1.1.4.2 rmind */
1877 1.1.1.1.4.2 rmind while (lp->nfslock_lock & NFSV4LOCK_LOCK) {
1878 1.1.1.1.4.2 rmind if (mp != NULL && (mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0)
1879 1.1.1.1.4.2 rmind return;
1880 1.1.1.1.4.2 rmind lp->nfslock_lock |= NFSV4LOCK_WANTED;
1881 1.1.1.1.4.2 rmind if (isleptp)
1882 1.1.1.1.4.2 rmind *isleptp = 1;
1883 1.1.1.1.4.2 rmind (void) nfsmsleep(&lp->nfslock_lock, mutex,
1884 1.1.1.1.4.2 rmind PZERO - 1, "nfsv4gr", NULL);
1885 1.1.1.1.4.2 rmind }
1886 1.1.1.1.4.2 rmind if (mp != NULL && (mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0)
1887 1.1.1.1.4.2 rmind return;
1888 1.1.1.1.4.2 rmind
1889 1.1.1.1.4.2 rmind lp->nfslock_usecnt++;
1890 1.1.1.1.4.2 rmind }
1891 1.1.1.1.4.2 rmind
1892 1.1.1.1.4.2 rmind /*
1893 1.1.1.1.4.2 rmind * Get a reference as above, but return failure instead of sleeping if
1894 1.1.1.1.4.2 rmind * an exclusive lock is held.
1895 1.1.1.1.4.2 rmind */
1896 1.1.1.1.4.2 rmind APPLESTATIC int
1897 1.1.1.1.4.2 rmind nfsv4_getref_nonblock(struct nfsv4lock *lp)
1898 1.1.1.1.4.2 rmind {
1899 1.1.1.1.4.2 rmind
1900 1.1.1.1.4.2 rmind if ((lp->nfslock_lock & NFSV4LOCK_LOCK) != 0)
1901 1.1.1.1.4.2 rmind return (0);
1902 1.1.1.1.4.2 rmind
1903 1.1.1.1.4.2 rmind lp->nfslock_usecnt++;
1904 1.1.1.1.4.2 rmind return (1);
1905 1.1.1.1.4.2 rmind }
1906 1.1.1.1.4.2 rmind
1907 1.1.1.1.4.2 rmind /*
1908 1.1.1.1.4.2 rmind * Test for a lock. Return 1 if locked, 0 otherwise.
1909 1.1.1.1.4.2 rmind */
1910 1.1.1.1.4.2 rmind APPLESTATIC int
1911 1.1.1.1.4.2 rmind nfsv4_testlock(struct nfsv4lock *lp)
1912 1.1.1.1.4.2 rmind {
1913 1.1.1.1.4.2 rmind
1914 1.1.1.1.4.2 rmind if ((lp->nfslock_lock & NFSV4LOCK_LOCK) == 0 &&
1915 1.1.1.1.4.2 rmind lp->nfslock_usecnt == 0)
1916 1.1.1.1.4.2 rmind return (0);
1917 1.1.1.1.4.2 rmind return (1);
1918 1.1.1.1.4.2 rmind }
1919 1.1.1.1.4.2 rmind
1920 1.1.1.1.4.2 rmind /*
1921 1.1.1.1.4.2 rmind * Wake up anyone sleeping, waiting for this lock.
1922 1.1.1.1.4.2 rmind */
1923 1.1.1.1.4.2 rmind static void
1924 1.1.1.1.4.2 rmind nfsv4_wanted(struct nfsv4lock *lp)
1925 1.1.1.1.4.2 rmind {
1926 1.1.1.1.4.2 rmind
1927 1.1.1.1.4.2 rmind if (lp->nfslock_lock & NFSV4LOCK_WANTED) {
1928 1.1.1.1.4.2 rmind lp->nfslock_lock &= ~NFSV4LOCK_WANTED;
1929 1.1.1.1.4.2 rmind wakeup((caddr_t)&lp->nfslock_lock);
1930 1.1.1.1.4.2 rmind }
1931 1.1.1.1.4.2 rmind }
1932 1.1.1.1.4.2 rmind
1933 1.1.1.1.4.2 rmind /*
1934 1.1.1.1.4.2 rmind * Copy a string from an mbuf list into a character array.
1935 1.1.1.1.4.2 rmind * Return EBADRPC if there is an mbuf error,
1936 1.1.1.1.4.2 rmind * 0 otherwise.
1937 1.1.1.1.4.2 rmind */
1938 1.1.1.1.4.2 rmind APPLESTATIC int
1939 1.1.1.1.4.2 rmind nfsrv_mtostr(struct nfsrv_descript *nd, char *str, int siz)
1940 1.1.1.1.4.2 rmind {
1941 1.1.1.1.4.2 rmind char *cp;
1942 1.1.1.1.4.2 rmind int xfer, len;
1943 1.1.1.1.4.2 rmind mbuf_t mp;
1944 1.1.1.1.4.2 rmind int rem, error = 0;
1945 1.1.1.1.4.2 rmind
1946 1.1.1.1.4.2 rmind mp = nd->nd_md;
1947 1.1.1.1.4.2 rmind cp = nd->nd_dpos;
1948 1.1.1.1.4.2 rmind len = NFSMTOD(mp, caddr_t) + mbuf_len(mp) - cp;
1949 1.1.1.1.4.2 rmind rem = NFSM_RNDUP(siz) - siz;
1950 1.1.1.1.4.2 rmind while (siz > 0) {
1951 1.1.1.1.4.2 rmind if (len > siz)
1952 1.1.1.1.4.2 rmind xfer = siz;
1953 1.1.1.1.4.2 rmind else
1954 1.1.1.1.4.2 rmind xfer = len;
1955 1.1.1.1.4.2 rmind NFSBCOPY(cp, str, xfer);
1956 1.1.1.1.4.2 rmind str += xfer;
1957 1.1.1.1.4.2 rmind siz -= xfer;
1958 1.1.1.1.4.2 rmind if (siz > 0) {
1959 1.1.1.1.4.2 rmind mp = mbuf_next(mp);
1960 1.1.1.1.4.2 rmind if (mp == NULL) {
1961 1.1.1.1.4.2 rmind error = EBADRPC;
1962 1.1.1.1.4.2 rmind goto out;
1963 1.1.1.1.4.2 rmind }
1964 1.1.1.1.4.2 rmind cp = NFSMTOD(mp, caddr_t);
1965 1.1.1.1.4.2 rmind len = mbuf_len(mp);
1966 1.1.1.1.4.2 rmind } else {
1967 1.1.1.1.4.2 rmind cp += xfer;
1968 1.1.1.1.4.2 rmind len -= xfer;
1969 1.1.1.1.4.2 rmind }
1970 1.1.1.1.4.2 rmind }
1971 1.1.1.1.4.2 rmind *str = '\0';
1972 1.1.1.1.4.2 rmind nd->nd_dpos = cp;
1973 1.1.1.1.4.2 rmind nd->nd_md = mp;
1974 1.1.1.1.4.2 rmind if (rem > 0) {
1975 1.1.1.1.4.2 rmind if (len < rem)
1976 1.1.1.1.4.2 rmind error = nfsm_advance(nd, rem, len);
1977 1.1.1.1.4.2 rmind else
1978 1.1.1.1.4.2 rmind nd->nd_dpos += rem;
1979 1.1.1.1.4.2 rmind }
1980 1.1.1.1.4.2 rmind
1981 1.1.1.1.4.2 rmind out:
1982 1.1.1.1.4.2 rmind NFSEXITCODE2(error, nd);
1983 1.1.1.1.4.2 rmind return (error);
1984 1.1.1.1.4.2 rmind }
1985 1.1.1.1.4.2 rmind
1986 1.1.1.1.4.2 rmind /*
1987 1.1.1.1.4.2 rmind * Fill in the attributes as marked by the bitmap (V4).
1988 1.1.1.1.4.2 rmind */
1989 1.1.1.1.4.2 rmind APPLESTATIC int
1990 1.1.1.1.4.2 rmind nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
1991 1.1.1.1.4.2 rmind NFSACL_T *saclp, struct vattr *vap, fhandle_t *fhp, int rderror,
1992 1.1.1.1.4.2 rmind nfsattrbit_t *attrbitp, struct ucred *cred, NFSPROC_T *p, int isdgram,
1993 1.1.1.1.4.2 rmind int reterr, int supports_nfsv4acls, int at_root, uint64_t mounted_on_fileno)
1994 1.1.1.1.4.2 rmind {
1995 1.1.1.1.4.2 rmind int bitpos, retnum = 0;
1996 1.1.1.1.4.2 rmind u_int32_t *tl;
1997 1.1.1.1.4.2 rmind int siz, prefixnum, error;
1998 1.1.1.1.4.2 rmind u_char *cp, namestr[NFSV4_SMALLSTR];
1999 1.1.1.1.4.2 rmind nfsattrbit_t attrbits, retbits;
2000 1.1.1.1.4.2 rmind nfsattrbit_t *retbitp = &retbits;
2001 1.1.1.1.4.2 rmind u_int32_t freenum, *retnump;
2002 1.1.1.1.4.2 rmind u_int64_t uquad;
2003 1.1.1.1.4.2 rmind struct statfs fs;
2004 1.1.1.1.4.2 rmind struct nfsfsinfo fsinf;
2005 1.1.1.1.4.2 rmind struct timespec temptime;
2006 1.1.1.1.4.2 rmind NFSACL_T *aclp, *naclp = NULL;
2007 1.1.1.1.4.2 rmind #ifdef QUOTA
2008 1.1.1.1.4.2 rmind struct dqblk dqb;
2009 1.1.1.1.4.2 rmind uid_t savuid;
2010 1.1.1.1.4.2 rmind #endif
2011 1.1.1.1.4.2 rmind
2012 1.1.1.1.4.2 rmind /*
2013 1.1.1.1.4.2 rmind * First, set the bits that can be filled and get fsinfo.
2014 1.1.1.1.4.2 rmind */
2015 1.1.1.1.4.2 rmind NFSSET_ATTRBIT(retbitp, attrbitp);
2016 1.1.1.1.4.2 rmind /* If p and cred are NULL, it is a client side call */
2017 1.1.1.1.4.2 rmind if (p == NULL && cred == NULL) {
2018 1.1.1.1.4.2 rmind NFSCLRNOTSETABLE_ATTRBIT(retbitp);
2019 1.1.1.1.4.2 rmind aclp = saclp;
2020 1.1.1.1.4.2 rmind } else {
2021 1.1.1.1.4.2 rmind NFSCLRNOTFILLABLE_ATTRBIT(retbitp);
2022 1.1.1.1.4.2 rmind naclp = acl_alloc(M_WAITOK);
2023 1.1.1.1.4.2 rmind aclp = naclp;
2024 1.1.1.1.4.2 rmind }
2025 1.1.1.1.4.2 rmind nfsvno_getfs(&fsinf, isdgram);
2026 1.1.1.1.4.2 rmind #ifndef APPLE
2027 1.1.1.1.4.2 rmind /*
2028 1.1.1.1.4.2 rmind * Get the VFS_STATFS(), since some attributes need them.
2029 1.1.1.1.4.2 rmind */
2030 1.1.1.1.4.2 rmind if (NFSISSETSTATFS_ATTRBIT(retbitp)) {
2031 1.1.1.1.4.2 rmind error = VFS_STATFS(mp, &fs);
2032 1.1.1.1.4.2 rmind if (error != 0) {
2033 1.1.1.1.4.2 rmind if (reterr) {
2034 1.1.1.1.4.2 rmind nd->nd_repstat = NFSERR_ACCES;
2035 1.1.1.1.4.2 rmind return (0);
2036 1.1.1.1.4.2 rmind }
2037 1.1.1.1.4.2 rmind NFSCLRSTATFS_ATTRBIT(retbitp);
2038 1.1.1.1.4.2 rmind }
2039 1.1.1.1.4.2 rmind }
2040 1.1.1.1.4.2 rmind #endif
2041 1.1.1.1.4.2 rmind
2042 1.1.1.1.4.2 rmind /*
2043 1.1.1.1.4.2 rmind * And the NFSv4 ACL...
2044 1.1.1.1.4.2 rmind */
2045 1.1.1.1.4.2 rmind if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_ACLSUPPORT) &&
2046 1.1.1.1.4.2 rmind (nfsrv_useacl == 0 || ((cred != NULL || p != NULL) &&
2047 1.1.1.1.4.2 rmind supports_nfsv4acls == 0))) {
2048 1.1.1.1.4.2 rmind NFSCLRBIT_ATTRBIT(retbitp, NFSATTRBIT_ACLSUPPORT);
2049 1.1.1.1.4.2 rmind }
2050 1.1.1.1.4.2 rmind if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_ACL)) {
2051 1.1.1.1.4.2 rmind if (nfsrv_useacl == 0 || ((cred != NULL || p != NULL) &&
2052 1.1.1.1.4.2 rmind supports_nfsv4acls == 0)) {
2053 1.1.1.1.4.2 rmind NFSCLRBIT_ATTRBIT(retbitp, NFSATTRBIT_ACL);
2054 1.1.1.1.4.2 rmind } else if (naclp != NULL) {
2055 1.1.1.1.4.2 rmind if (NFSVOPLOCK(vp, LK_SHARED) == 0) {
2056 1.1.1.1.4.2 rmind error = VOP_ACCESSX(vp, VREAD_ACL, cred, p);
2057 1.1.1.1.4.2 rmind if (error == 0)
2058 1.1.1.1.4.2 rmind error = VOP_GETACL(vp, ACL_TYPE_NFS4,
2059 1.1.1.1.4.2 rmind naclp, cred, p);
2060 1.1.1.1.4.2 rmind NFSVOPUNLOCK(vp, 0);
2061 1.1.1.1.4.2 rmind } else
2062 1.1.1.1.4.2 rmind error = NFSERR_PERM;
2063 1.1.1.1.4.2 rmind if (error != 0) {
2064 1.1.1.1.4.2 rmind if (reterr) {
2065 1.1.1.1.4.2 rmind nd->nd_repstat = NFSERR_ACCES;
2066 1.1.1.1.4.2 rmind return (0);
2067 1.1.1.1.4.2 rmind }
2068 1.1.1.1.4.2 rmind NFSCLRBIT_ATTRBIT(retbitp, NFSATTRBIT_ACL);
2069 1.1.1.1.4.2 rmind }
2070 1.1.1.1.4.2 rmind }
2071 1.1.1.1.4.2 rmind }
2072 1.1.1.1.4.2 rmind /*
2073 1.1.1.1.4.2 rmind * Put out the attribute bitmap for the ones being filled in
2074 1.1.1.1.4.2 rmind * and get the field for the number of attributes returned.
2075 1.1.1.1.4.2 rmind */
2076 1.1.1.1.4.2 rmind prefixnum = nfsrv_putattrbit(nd, retbitp);
2077 1.1.1.1.4.2 rmind NFSM_BUILD(retnump, u_int32_t *, NFSX_UNSIGNED);
2078 1.1.1.1.4.2 rmind prefixnum += NFSX_UNSIGNED;
2079 1.1.1.1.4.2 rmind
2080 1.1.1.1.4.2 rmind /*
2081 1.1.1.1.4.2 rmind * Now, loop around filling in the attributes for each bit set.
2082 1.1.1.1.4.2 rmind */
2083 1.1.1.1.4.2 rmind for (bitpos = 0; bitpos < NFSATTRBIT_MAX; bitpos++) {
2084 1.1.1.1.4.2 rmind if (NFSISSET_ATTRBIT(retbitp, bitpos)) {
2085 1.1.1.1.4.2 rmind switch (bitpos) {
2086 1.1.1.1.4.2 rmind case NFSATTRBIT_SUPPORTEDATTRS:
2087 1.1.1.1.4.2 rmind NFSSETSUPP_ATTRBIT(&attrbits);
2088 1.1.1.1.4.2 rmind if (nfsrv_useacl == 0 || ((cred != NULL || p != NULL)
2089 1.1.1.1.4.2 rmind && supports_nfsv4acls == 0)) {
2090 1.1.1.1.4.2 rmind NFSCLRBIT_ATTRBIT(&attrbits,NFSATTRBIT_ACLSUPPORT);
2091 1.1.1.1.4.2 rmind NFSCLRBIT_ATTRBIT(&attrbits,NFSATTRBIT_ACL);
2092 1.1.1.1.4.2 rmind }
2093 1.1.1.1.4.2 rmind retnum += nfsrv_putattrbit(nd, &attrbits);
2094 1.1.1.1.4.2 rmind break;
2095 1.1.1.1.4.2 rmind case NFSATTRBIT_TYPE:
2096 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2097 1.1.1.1.4.2 rmind *tl = vtonfsv34_type(vap->va_type);
2098 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2099 1.1.1.1.4.2 rmind break;
2100 1.1.1.1.4.2 rmind case NFSATTRBIT_FHEXPIRETYPE:
2101 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2102 1.1.1.1.4.2 rmind *tl = txdr_unsigned(NFSV4FHTYPE_PERSISTENT);
2103 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2104 1.1.1.1.4.2 rmind break;
2105 1.1.1.1.4.2 rmind case NFSATTRBIT_CHANGE:
2106 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2107 1.1.1.1.4.2 rmind txdr_hyper(vap->va_filerev, tl);
2108 1.1.1.1.4.2 rmind retnum += NFSX_HYPER;
2109 1.1.1.1.4.2 rmind break;
2110 1.1.1.1.4.2 rmind case NFSATTRBIT_SIZE:
2111 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2112 1.1.1.1.4.2 rmind txdr_hyper(vap->va_size, tl);
2113 1.1.1.1.4.2 rmind retnum += NFSX_HYPER;
2114 1.1.1.1.4.2 rmind break;
2115 1.1.1.1.4.2 rmind case NFSATTRBIT_LINKSUPPORT:
2116 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2117 1.1.1.1.4.2 rmind if (fsinf.fs_properties & NFSV3FSINFO_LINK)
2118 1.1.1.1.4.2 rmind *tl = newnfs_true;
2119 1.1.1.1.4.2 rmind else
2120 1.1.1.1.4.2 rmind *tl = newnfs_false;
2121 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2122 1.1.1.1.4.2 rmind break;
2123 1.1.1.1.4.2 rmind case NFSATTRBIT_SYMLINKSUPPORT:
2124 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2125 1.1.1.1.4.2 rmind if (fsinf.fs_properties & NFSV3FSINFO_SYMLINK)
2126 1.1.1.1.4.2 rmind *tl = newnfs_true;
2127 1.1.1.1.4.2 rmind else
2128 1.1.1.1.4.2 rmind *tl = newnfs_false;
2129 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2130 1.1.1.1.4.2 rmind break;
2131 1.1.1.1.4.2 rmind case NFSATTRBIT_NAMEDATTR:
2132 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2133 1.1.1.1.4.2 rmind *tl = newnfs_false;
2134 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2135 1.1.1.1.4.2 rmind break;
2136 1.1.1.1.4.2 rmind case NFSATTRBIT_FSID:
2137 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_V4FSID);
2138 1.1.1.1.4.2 rmind *tl++ = 0;
2139 1.1.1.1.4.2 rmind *tl++ = txdr_unsigned(mp->mnt_stat.f_fsid.val[0]);
2140 1.1.1.1.4.2 rmind *tl++ = 0;
2141 1.1.1.1.4.2 rmind *tl = txdr_unsigned(mp->mnt_stat.f_fsid.val[1]);
2142 1.1.1.1.4.2 rmind retnum += NFSX_V4FSID;
2143 1.1.1.1.4.2 rmind break;
2144 1.1.1.1.4.2 rmind case NFSATTRBIT_UNIQUEHANDLES:
2145 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2146 1.1.1.1.4.2 rmind *tl = newnfs_true;
2147 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2148 1.1.1.1.4.2 rmind break;
2149 1.1.1.1.4.2 rmind case NFSATTRBIT_LEASETIME:
2150 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2151 1.1.1.1.4.2 rmind *tl = txdr_unsigned(nfsrv_lease);
2152 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2153 1.1.1.1.4.2 rmind break;
2154 1.1.1.1.4.2 rmind case NFSATTRBIT_RDATTRERROR:
2155 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2156 1.1.1.1.4.2 rmind *tl = txdr_unsigned(rderror);
2157 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2158 1.1.1.1.4.2 rmind break;
2159 1.1.1.1.4.2 rmind /*
2160 1.1.1.1.4.2 rmind * Recommended Attributes. (Only the supported ones.)
2161 1.1.1.1.4.2 rmind */
2162 1.1.1.1.4.2 rmind case NFSATTRBIT_ACL:
2163 1.1.1.1.4.2 rmind retnum += nfsrv_buildacl(nd, aclp, vnode_vtype(vp), p);
2164 1.1.1.1.4.2 rmind break;
2165 1.1.1.1.4.2 rmind case NFSATTRBIT_ACLSUPPORT:
2166 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2167 1.1.1.1.4.2 rmind *tl = txdr_unsigned(NFSV4ACE_SUPTYPES);
2168 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2169 1.1.1.1.4.2 rmind break;
2170 1.1.1.1.4.2 rmind case NFSATTRBIT_CANSETTIME:
2171 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2172 1.1.1.1.4.2 rmind if (fsinf.fs_properties & NFSV3FSINFO_CANSETTIME)
2173 1.1.1.1.4.2 rmind *tl = newnfs_true;
2174 1.1.1.1.4.2 rmind else
2175 1.1.1.1.4.2 rmind *tl = newnfs_false;
2176 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2177 1.1.1.1.4.2 rmind break;
2178 1.1.1.1.4.2 rmind case NFSATTRBIT_CASEINSENSITIVE:
2179 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2180 1.1.1.1.4.2 rmind *tl = newnfs_false;
2181 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2182 1.1.1.1.4.2 rmind break;
2183 1.1.1.1.4.2 rmind case NFSATTRBIT_CASEPRESERVING:
2184 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2185 1.1.1.1.4.2 rmind *tl = newnfs_true;
2186 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2187 1.1.1.1.4.2 rmind break;
2188 1.1.1.1.4.2 rmind case NFSATTRBIT_CHOWNRESTRICTED:
2189 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2190 1.1.1.1.4.2 rmind *tl = newnfs_true;
2191 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2192 1.1.1.1.4.2 rmind break;
2193 1.1.1.1.4.2 rmind case NFSATTRBIT_FILEHANDLE:
2194 1.1.1.1.4.2 rmind retnum += nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0);
2195 1.1.1.1.4.2 rmind break;
2196 1.1.1.1.4.2 rmind case NFSATTRBIT_FILEID:
2197 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2198 1.1.1.1.4.2 rmind *tl++ = 0;
2199 1.1.1.1.4.2 rmind *tl = txdr_unsigned(vap->va_fileid);
2200 1.1.1.1.4.2 rmind retnum += NFSX_HYPER;
2201 1.1.1.1.4.2 rmind break;
2202 1.1.1.1.4.2 rmind case NFSATTRBIT_FILESAVAIL:
2203 1.1.1.1.4.2 rmind /*
2204 1.1.1.1.4.2 rmind * Check quota and use min(quota, f_ffree).
2205 1.1.1.1.4.2 rmind */
2206 1.1.1.1.4.2 rmind freenum = fs.f_ffree;
2207 1.1.1.1.4.2 rmind #ifdef QUOTA
2208 1.1.1.1.4.2 rmind /*
2209 1.1.1.1.4.2 rmind * ufs_quotactl() insists that the uid argument
2210 1.1.1.1.4.2 rmind * equal p_ruid for non-root quota access, so
2211 1.1.1.1.4.2 rmind * we'll just make sure that's the case.
2212 1.1.1.1.4.2 rmind */
2213 1.1.1.1.4.2 rmind savuid = p->p_cred->p_ruid;
2214 1.1.1.1.4.2 rmind p->p_cred->p_ruid = cred->cr_uid;
2215 1.1.1.1.4.2 rmind if (!VFS_QUOTACTL(mp, QCMD(Q_GETQUOTA,USRQUOTA),
2216 1.1.1.1.4.2 rmind cred->cr_uid, (caddr_t)&dqb))
2217 1.1.1.1.4.2 rmind freenum = min(dqb.dqb_isoftlimit-dqb.dqb_curinodes,
2218 1.1.1.1.4.2 rmind freenum);
2219 1.1.1.1.4.2 rmind p->p_cred->p_ruid = savuid;
2220 1.1.1.1.4.2 rmind #endif /* QUOTA */
2221 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2222 1.1.1.1.4.2 rmind *tl++ = 0;
2223 1.1.1.1.4.2 rmind *tl = txdr_unsigned(freenum);
2224 1.1.1.1.4.2 rmind retnum += NFSX_HYPER;
2225 1.1.1.1.4.2 rmind break;
2226 1.1.1.1.4.2 rmind case NFSATTRBIT_FILESFREE:
2227 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2228 1.1.1.1.4.2 rmind *tl++ = 0;
2229 1.1.1.1.4.2 rmind *tl = txdr_unsigned(fs.f_ffree);
2230 1.1.1.1.4.2 rmind retnum += NFSX_HYPER;
2231 1.1.1.1.4.2 rmind break;
2232 1.1.1.1.4.2 rmind case NFSATTRBIT_FILESTOTAL:
2233 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2234 1.1.1.1.4.2 rmind *tl++ = 0;
2235 1.1.1.1.4.2 rmind *tl = txdr_unsigned(fs.f_files);
2236 1.1.1.1.4.2 rmind retnum += NFSX_HYPER;
2237 1.1.1.1.4.2 rmind break;
2238 1.1.1.1.4.2 rmind case NFSATTRBIT_FSLOCATIONS:
2239 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2240 1.1.1.1.4.2 rmind *tl++ = 0;
2241 1.1.1.1.4.2 rmind *tl = 0;
2242 1.1.1.1.4.2 rmind retnum += 2 * NFSX_UNSIGNED;
2243 1.1.1.1.4.2 rmind break;
2244 1.1.1.1.4.2 rmind case NFSATTRBIT_HOMOGENEOUS:
2245 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2246 1.1.1.1.4.2 rmind if (fsinf.fs_properties & NFSV3FSINFO_HOMOGENEOUS)
2247 1.1.1.1.4.2 rmind *tl = newnfs_true;
2248 1.1.1.1.4.2 rmind else
2249 1.1.1.1.4.2 rmind *tl = newnfs_false;
2250 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2251 1.1.1.1.4.2 rmind break;
2252 1.1.1.1.4.2 rmind case NFSATTRBIT_MAXFILESIZE:
2253 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2254 1.1.1.1.4.2 rmind uquad = NFSRV_MAXFILESIZE;
2255 1.1.1.1.4.2 rmind txdr_hyper(uquad, tl);
2256 1.1.1.1.4.2 rmind retnum += NFSX_HYPER;
2257 1.1.1.1.4.2 rmind break;
2258 1.1.1.1.4.2 rmind case NFSATTRBIT_MAXLINK:
2259 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2260 1.1.1.1.4.2 rmind *tl = txdr_unsigned(LINK_MAX);
2261 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2262 1.1.1.1.4.2 rmind break;
2263 1.1.1.1.4.2 rmind case NFSATTRBIT_MAXNAME:
2264 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2265 1.1.1.1.4.2 rmind *tl = txdr_unsigned(NFS_MAXNAMLEN);
2266 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2267 1.1.1.1.4.2 rmind break;
2268 1.1.1.1.4.2 rmind case NFSATTRBIT_MAXREAD:
2269 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2270 1.1.1.1.4.2 rmind *tl++ = 0;
2271 1.1.1.1.4.2 rmind *tl = txdr_unsigned(fsinf.fs_rtmax);
2272 1.1.1.1.4.2 rmind retnum += NFSX_HYPER;
2273 1.1.1.1.4.2 rmind break;
2274 1.1.1.1.4.2 rmind case NFSATTRBIT_MAXWRITE:
2275 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2276 1.1.1.1.4.2 rmind *tl++ = 0;
2277 1.1.1.1.4.2 rmind *tl = txdr_unsigned(fsinf.fs_wtmax);
2278 1.1.1.1.4.2 rmind retnum += NFSX_HYPER;
2279 1.1.1.1.4.2 rmind break;
2280 1.1.1.1.4.2 rmind case NFSATTRBIT_MODE:
2281 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2282 1.1.1.1.4.2 rmind *tl = vtonfsv34_mode(vap->va_mode);
2283 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2284 1.1.1.1.4.2 rmind break;
2285 1.1.1.1.4.2 rmind case NFSATTRBIT_NOTRUNC:
2286 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2287 1.1.1.1.4.2 rmind *tl = newnfs_true;
2288 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2289 1.1.1.1.4.2 rmind break;
2290 1.1.1.1.4.2 rmind case NFSATTRBIT_NUMLINKS:
2291 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2292 1.1.1.1.4.2 rmind *tl = txdr_unsigned(vap->va_nlink);
2293 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2294 1.1.1.1.4.2 rmind break;
2295 1.1.1.1.4.2 rmind case NFSATTRBIT_OWNER:
2296 1.1.1.1.4.2 rmind cp = namestr;
2297 1.1.1.1.4.2 rmind nfsv4_uidtostr(vap->va_uid, &cp, &siz, p);
2298 1.1.1.1.4.2 rmind retnum += nfsm_strtom(nd, cp, siz);
2299 1.1.1.1.4.2 rmind if (cp != namestr)
2300 1.1.1.1.4.2 rmind free(cp, M_NFSSTRING);
2301 1.1.1.1.4.2 rmind break;
2302 1.1.1.1.4.2 rmind case NFSATTRBIT_OWNERGROUP:
2303 1.1.1.1.4.2 rmind cp = namestr;
2304 1.1.1.1.4.2 rmind nfsv4_gidtostr(vap->va_gid, &cp, &siz, p);
2305 1.1.1.1.4.2 rmind retnum += nfsm_strtom(nd, cp, siz);
2306 1.1.1.1.4.2 rmind if (cp != namestr)
2307 1.1.1.1.4.2 rmind free(cp, M_NFSSTRING);
2308 1.1.1.1.4.2 rmind break;
2309 1.1.1.1.4.2 rmind case NFSATTRBIT_QUOTAHARD:
2310 1.1.1.1.4.2 rmind if (priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA, 0))
2311 1.1.1.1.4.2 rmind freenum = fs.f_bfree;
2312 1.1.1.1.4.2 rmind else
2313 1.1.1.1.4.2 rmind freenum = fs.f_bavail;
2314 1.1.1.1.4.2 rmind #ifdef QUOTA
2315 1.1.1.1.4.2 rmind /*
2316 1.1.1.1.4.2 rmind * ufs_quotactl() insists that the uid argument
2317 1.1.1.1.4.2 rmind * equal p_ruid for non-root quota access, so
2318 1.1.1.1.4.2 rmind * we'll just make sure that's the case.
2319 1.1.1.1.4.2 rmind */
2320 1.1.1.1.4.2 rmind savuid = p->p_cred->p_ruid;
2321 1.1.1.1.4.2 rmind p->p_cred->p_ruid = cred->cr_uid;
2322 1.1.1.1.4.2 rmind if (!VFS_QUOTACTL(mp, QCMD(Q_GETQUOTA,USRQUOTA),
2323 1.1.1.1.4.2 rmind cred->cr_uid, (caddr_t)&dqb))
2324 1.1.1.1.4.2 rmind freenum = min(dqb.dqb_bhardlimit, freenum);
2325 1.1.1.1.4.2 rmind p->p_cred->p_ruid = savuid;
2326 1.1.1.1.4.2 rmind #endif /* QUOTA */
2327 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2328 1.1.1.1.4.2 rmind uquad = (u_int64_t)freenum;
2329 1.1.1.1.4.2 rmind NFSQUOTABLKTOBYTE(uquad, fs.f_bsize);
2330 1.1.1.1.4.2 rmind txdr_hyper(uquad, tl);
2331 1.1.1.1.4.2 rmind retnum += NFSX_HYPER;
2332 1.1.1.1.4.2 rmind break;
2333 1.1.1.1.4.2 rmind case NFSATTRBIT_QUOTASOFT:
2334 1.1.1.1.4.2 rmind if (priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA, 0))
2335 1.1.1.1.4.2 rmind freenum = fs.f_bfree;
2336 1.1.1.1.4.2 rmind else
2337 1.1.1.1.4.2 rmind freenum = fs.f_bavail;
2338 1.1.1.1.4.2 rmind #ifdef QUOTA
2339 1.1.1.1.4.2 rmind /*
2340 1.1.1.1.4.2 rmind * ufs_quotactl() insists that the uid argument
2341 1.1.1.1.4.2 rmind * equal p_ruid for non-root quota access, so
2342 1.1.1.1.4.2 rmind * we'll just make sure that's the case.
2343 1.1.1.1.4.2 rmind */
2344 1.1.1.1.4.2 rmind savuid = p->p_cred->p_ruid;
2345 1.1.1.1.4.2 rmind p->p_cred->p_ruid = cred->cr_uid;
2346 1.1.1.1.4.2 rmind if (!VFS_QUOTACTL(mp, QCMD(Q_GETQUOTA,USRQUOTA),
2347 1.1.1.1.4.2 rmind cred->cr_uid, (caddr_t)&dqb))
2348 1.1.1.1.4.2 rmind freenum = min(dqb.dqb_bsoftlimit, freenum);
2349 1.1.1.1.4.2 rmind p->p_cred->p_ruid = savuid;
2350 1.1.1.1.4.2 rmind #endif /* QUOTA */
2351 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2352 1.1.1.1.4.2 rmind uquad = (u_int64_t)freenum;
2353 1.1.1.1.4.2 rmind NFSQUOTABLKTOBYTE(uquad, fs.f_bsize);
2354 1.1.1.1.4.2 rmind txdr_hyper(uquad, tl);
2355 1.1.1.1.4.2 rmind retnum += NFSX_HYPER;
2356 1.1.1.1.4.2 rmind break;
2357 1.1.1.1.4.2 rmind case NFSATTRBIT_QUOTAUSED:
2358 1.1.1.1.4.2 rmind freenum = 0;
2359 1.1.1.1.4.2 rmind #ifdef QUOTA
2360 1.1.1.1.4.2 rmind /*
2361 1.1.1.1.4.2 rmind * ufs_quotactl() insists that the uid argument
2362 1.1.1.1.4.2 rmind * equal p_ruid for non-root quota access, so
2363 1.1.1.1.4.2 rmind * we'll just make sure that's the case.
2364 1.1.1.1.4.2 rmind */
2365 1.1.1.1.4.2 rmind savuid = p->p_cred->p_ruid;
2366 1.1.1.1.4.2 rmind p->p_cred->p_ruid = cred->cr_uid;
2367 1.1.1.1.4.2 rmind if (!VFS_QUOTACTL(mp, QCMD(Q_GETQUOTA,USRQUOTA),
2368 1.1.1.1.4.2 rmind cred->cr_uid, (caddr_t)&dqb))
2369 1.1.1.1.4.2 rmind freenum = dqb.dqb_curblocks;
2370 1.1.1.1.4.2 rmind p->p_cred->p_ruid = savuid;
2371 1.1.1.1.4.2 rmind #endif /* QUOTA */
2372 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2373 1.1.1.1.4.2 rmind uquad = (u_int64_t)freenum;
2374 1.1.1.1.4.2 rmind NFSQUOTABLKTOBYTE(uquad, fs.f_bsize);
2375 1.1.1.1.4.2 rmind txdr_hyper(uquad, tl);
2376 1.1.1.1.4.2 rmind retnum += NFSX_HYPER;
2377 1.1.1.1.4.2 rmind break;
2378 1.1.1.1.4.2 rmind case NFSATTRBIT_RAWDEV:
2379 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_V4SPECDATA);
2380 1.1.1.1.4.2 rmind *tl++ = txdr_unsigned(NFSMAJOR(vap->va_rdev));
2381 1.1.1.1.4.2 rmind *tl = txdr_unsigned(NFSMINOR(vap->va_rdev));
2382 1.1.1.1.4.2 rmind retnum += NFSX_V4SPECDATA;
2383 1.1.1.1.4.2 rmind break;
2384 1.1.1.1.4.2 rmind case NFSATTRBIT_SPACEAVAIL:
2385 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2386 1.1.1.1.4.2 rmind if (priv_check_cred(cred, PRIV_VFS_BLOCKRESERVE, 0))
2387 1.1.1.1.4.2 rmind uquad = (u_int64_t)fs.f_bfree;
2388 1.1.1.1.4.2 rmind else
2389 1.1.1.1.4.2 rmind uquad = (u_int64_t)fs.f_bavail;
2390 1.1.1.1.4.2 rmind uquad *= fs.f_bsize;
2391 1.1.1.1.4.2 rmind txdr_hyper(uquad, tl);
2392 1.1.1.1.4.2 rmind retnum += NFSX_HYPER;
2393 1.1.1.1.4.2 rmind break;
2394 1.1.1.1.4.2 rmind case NFSATTRBIT_SPACEFREE:
2395 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2396 1.1.1.1.4.2 rmind uquad = (u_int64_t)fs.f_bfree;
2397 1.1.1.1.4.2 rmind uquad *= fs.f_bsize;
2398 1.1.1.1.4.2 rmind txdr_hyper(uquad, tl);
2399 1.1.1.1.4.2 rmind retnum += NFSX_HYPER;
2400 1.1.1.1.4.2 rmind break;
2401 1.1.1.1.4.2 rmind case NFSATTRBIT_SPACETOTAL:
2402 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2403 1.1.1.1.4.2 rmind uquad = (u_int64_t)fs.f_blocks;
2404 1.1.1.1.4.2 rmind uquad *= fs.f_bsize;
2405 1.1.1.1.4.2 rmind txdr_hyper(uquad, tl);
2406 1.1.1.1.4.2 rmind retnum += NFSX_HYPER;
2407 1.1.1.1.4.2 rmind break;
2408 1.1.1.1.4.2 rmind case NFSATTRBIT_SPACEUSED:
2409 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2410 1.1.1.1.4.2 rmind txdr_hyper(vap->va_bytes, tl);
2411 1.1.1.1.4.2 rmind retnum += NFSX_HYPER;
2412 1.1.1.1.4.2 rmind break;
2413 1.1.1.1.4.2 rmind case NFSATTRBIT_TIMEACCESS:
2414 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_V4TIME);
2415 1.1.1.1.4.2 rmind txdr_nfsv4time(&vap->va_atime, tl);
2416 1.1.1.1.4.2 rmind retnum += NFSX_V4TIME;
2417 1.1.1.1.4.2 rmind break;
2418 1.1.1.1.4.2 rmind case NFSATTRBIT_TIMEACCESSSET:
2419 1.1.1.1.4.2 rmind if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) {
2420 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_V4SETTIME);
2421 1.1.1.1.4.2 rmind *tl++ = txdr_unsigned(NFSV4SATTRTIME_TOCLIENT);
2422 1.1.1.1.4.2 rmind txdr_nfsv4time(&vap->va_atime, tl);
2423 1.1.1.1.4.2 rmind retnum += NFSX_V4SETTIME;
2424 1.1.1.1.4.2 rmind } else {
2425 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2426 1.1.1.1.4.2 rmind *tl = txdr_unsigned(NFSV4SATTRTIME_TOSERVER);
2427 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2428 1.1.1.1.4.2 rmind }
2429 1.1.1.1.4.2 rmind break;
2430 1.1.1.1.4.2 rmind case NFSATTRBIT_TIMEDELTA:
2431 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_V4TIME);
2432 1.1.1.1.4.2 rmind temptime.tv_sec = 0;
2433 1.1.1.1.4.2 rmind temptime.tv_nsec = 1000000000 / hz;
2434 1.1.1.1.4.2 rmind txdr_nfsv4time(&temptime, tl);
2435 1.1.1.1.4.2 rmind retnum += NFSX_V4TIME;
2436 1.1.1.1.4.2 rmind break;
2437 1.1.1.1.4.2 rmind case NFSATTRBIT_TIMEMETADATA:
2438 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_V4TIME);
2439 1.1.1.1.4.2 rmind txdr_nfsv4time(&vap->va_ctime, tl);
2440 1.1.1.1.4.2 rmind retnum += NFSX_V4TIME;
2441 1.1.1.1.4.2 rmind break;
2442 1.1.1.1.4.2 rmind case NFSATTRBIT_TIMEMODIFY:
2443 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_V4TIME);
2444 1.1.1.1.4.2 rmind txdr_nfsv4time(&vap->va_mtime, tl);
2445 1.1.1.1.4.2 rmind retnum += NFSX_V4TIME;
2446 1.1.1.1.4.2 rmind break;
2447 1.1.1.1.4.2 rmind case NFSATTRBIT_TIMEMODIFYSET:
2448 1.1.1.1.4.2 rmind if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) {
2449 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_V4SETTIME);
2450 1.1.1.1.4.2 rmind *tl++ = txdr_unsigned(NFSV4SATTRTIME_TOCLIENT);
2451 1.1.1.1.4.2 rmind txdr_nfsv4time(&vap->va_mtime, tl);
2452 1.1.1.1.4.2 rmind retnum += NFSX_V4SETTIME;
2453 1.1.1.1.4.2 rmind } else {
2454 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2455 1.1.1.1.4.2 rmind *tl = txdr_unsigned(NFSV4SATTRTIME_TOSERVER);
2456 1.1.1.1.4.2 rmind retnum += NFSX_UNSIGNED;
2457 1.1.1.1.4.2 rmind }
2458 1.1.1.1.4.2 rmind break;
2459 1.1.1.1.4.2 rmind case NFSATTRBIT_MOUNTEDONFILEID:
2460 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
2461 1.1.1.1.4.2 rmind if (at_root != 0)
2462 1.1.1.1.4.2 rmind uquad = mounted_on_fileno;
2463 1.1.1.1.4.2 rmind else
2464 1.1.1.1.4.2 rmind uquad = (u_int64_t)vap->va_fileid;
2465 1.1.1.1.4.2 rmind txdr_hyper(uquad, tl);
2466 1.1.1.1.4.2 rmind retnum += NFSX_HYPER;
2467 1.1.1.1.4.2 rmind break;
2468 1.1.1.1.4.2 rmind default:
2469 1.1.1.1.4.2 rmind printf("EEK! Bad V4 attribute bitpos=%d\n", bitpos);
2470 1.1.1.1.4.2 rmind };
2471 1.1.1.1.4.2 rmind }
2472 1.1.1.1.4.2 rmind }
2473 1.1.1.1.4.2 rmind if (naclp != NULL)
2474 1.1.1.1.4.2 rmind acl_free(naclp);
2475 1.1.1.1.4.2 rmind *retnump = txdr_unsigned(retnum);
2476 1.1.1.1.4.2 rmind return (retnum + prefixnum);
2477 1.1.1.1.4.2 rmind }
2478 1.1.1.1.4.2 rmind
2479 1.1.1.1.4.2 rmind /*
2480 1.1.1.1.4.2 rmind * Put the attribute bits onto an mbuf list.
2481 1.1.1.1.4.2 rmind * Return the number of bytes of output generated.
2482 1.1.1.1.4.2 rmind */
2483 1.1.1.1.4.2 rmind APPLESTATIC int
2484 1.1.1.1.4.2 rmind nfsrv_putattrbit(struct nfsrv_descript *nd, nfsattrbit_t *attrbitp)
2485 1.1.1.1.4.2 rmind {
2486 1.1.1.1.4.2 rmind u_int32_t *tl;
2487 1.1.1.1.4.2 rmind int cnt, i, bytesize;
2488 1.1.1.1.4.2 rmind
2489 1.1.1.1.4.2 rmind for (cnt = NFSATTRBIT_MAXWORDS; cnt > 0; cnt--)
2490 1.1.1.1.4.2 rmind if (attrbitp->bits[cnt - 1])
2491 1.1.1.1.4.2 rmind break;
2492 1.1.1.1.4.2 rmind bytesize = (cnt + 1) * NFSX_UNSIGNED;
2493 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, bytesize);
2494 1.1.1.1.4.2 rmind *tl++ = txdr_unsigned(cnt);
2495 1.1.1.1.4.2 rmind for (i = 0; i < cnt; i++)
2496 1.1.1.1.4.2 rmind *tl++ = txdr_unsigned(attrbitp->bits[i]);
2497 1.1.1.1.4.2 rmind return (bytesize);
2498 1.1.1.1.4.2 rmind }
2499 1.1.1.1.4.2 rmind
2500 1.1.1.1.4.2 rmind /*
2501 1.1.1.1.4.2 rmind * Convert a uid to a string.
2502 1.1.1.1.4.2 rmind * If the lookup fails, just output the digits.
2503 1.1.1.1.4.2 rmind * uid - the user id
2504 1.1.1.1.4.2 rmind * cpp - points to a buffer of size NFSV4_SMALLSTR
2505 1.1.1.1.4.2 rmind * (malloc a larger one, as required)
2506 1.1.1.1.4.2 rmind * retlenp - pointer to length to be returned
2507 1.1.1.1.4.2 rmind */
2508 1.1.1.1.4.2 rmind APPLESTATIC void
2509 1.1.1.1.4.2 rmind nfsv4_uidtostr(uid_t uid, u_char **cpp, int *retlenp, NFSPROC_T *p)
2510 1.1.1.1.4.2 rmind {
2511 1.1.1.1.4.2 rmind int i;
2512 1.1.1.1.4.2 rmind struct nfsusrgrp *usrp;
2513 1.1.1.1.4.2 rmind u_char *cp = *cpp;
2514 1.1.1.1.4.2 rmind uid_t tmp;
2515 1.1.1.1.4.2 rmind int cnt, hasampersand, len = NFSV4_SMALLSTR, ret;
2516 1.1.1.1.4.2 rmind
2517 1.1.1.1.4.2 rmind cnt = 0;
2518 1.1.1.1.4.2 rmind tryagain:
2519 1.1.1.1.4.2 rmind NFSLOCKNAMEID();
2520 1.1.1.1.4.2 rmind if (nfsrv_dnsname) {
2521 1.1.1.1.4.2 rmind /*
2522 1.1.1.1.4.2 rmind * Always map nfsrv_defaultuid to "nobody".
2523 1.1.1.1.4.2 rmind */
2524 1.1.1.1.4.2 rmind if (uid == nfsrv_defaultuid) {
2525 1.1.1.1.4.2 rmind i = nfsrv_dnsnamelen + 7;
2526 1.1.1.1.4.2 rmind if (i > len) {
2527 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2528 1.1.1.1.4.2 rmind if (len > NFSV4_SMALLSTR)
2529 1.1.1.1.4.2 rmind free(cp, M_NFSSTRING);
2530 1.1.1.1.4.2 rmind cp = malloc(i, M_NFSSTRING, M_WAITOK);
2531 1.1.1.1.4.2 rmind *cpp = cp;
2532 1.1.1.1.4.2 rmind len = i;
2533 1.1.1.1.4.2 rmind goto tryagain;
2534 1.1.1.1.4.2 rmind }
2535 1.1.1.1.4.2 rmind *retlenp = i;
2536 1.1.1.1.4.2 rmind NFSBCOPY("nobody@", cp, 7);
2537 1.1.1.1.4.2 rmind cp += 7;
2538 1.1.1.1.4.2 rmind NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
2539 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2540 1.1.1.1.4.2 rmind return;
2541 1.1.1.1.4.2 rmind }
2542 1.1.1.1.4.2 rmind hasampersand = 0;
2543 1.1.1.1.4.2 rmind LIST_FOREACH(usrp, NFSUSERHASH(uid), lug_numhash) {
2544 1.1.1.1.4.2 rmind if (usrp->lug_uid == uid) {
2545 1.1.1.1.4.2 rmind if (usrp->lug_expiry < NFSD_MONOSEC)
2546 1.1.1.1.4.2 rmind break;
2547 1.1.1.1.4.2 rmind /*
2548 1.1.1.1.4.2 rmind * If the name doesn't already have an '@'
2549 1.1.1.1.4.2 rmind * in it, append @domainname to it.
2550 1.1.1.1.4.2 rmind */
2551 1.1.1.1.4.2 rmind for (i = 0; i < usrp->lug_namelen; i++) {
2552 1.1.1.1.4.2 rmind if (usrp->lug_name[i] == '@') {
2553 1.1.1.1.4.2 rmind hasampersand = 1;
2554 1.1.1.1.4.2 rmind break;
2555 1.1.1.1.4.2 rmind }
2556 1.1.1.1.4.2 rmind }
2557 1.1.1.1.4.2 rmind if (hasampersand)
2558 1.1.1.1.4.2 rmind i = usrp->lug_namelen;
2559 1.1.1.1.4.2 rmind else
2560 1.1.1.1.4.2 rmind i = usrp->lug_namelen +
2561 1.1.1.1.4.2 rmind nfsrv_dnsnamelen + 1;
2562 1.1.1.1.4.2 rmind if (i > len) {
2563 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2564 1.1.1.1.4.2 rmind if (len > NFSV4_SMALLSTR)
2565 1.1.1.1.4.2 rmind free(cp, M_NFSSTRING);
2566 1.1.1.1.4.2 rmind cp = malloc(i, M_NFSSTRING, M_WAITOK);
2567 1.1.1.1.4.2 rmind *cpp = cp;
2568 1.1.1.1.4.2 rmind len = i;
2569 1.1.1.1.4.2 rmind goto tryagain;
2570 1.1.1.1.4.2 rmind }
2571 1.1.1.1.4.2 rmind *retlenp = i;
2572 1.1.1.1.4.2 rmind NFSBCOPY(usrp->lug_name, cp, usrp->lug_namelen);
2573 1.1.1.1.4.2 rmind if (!hasampersand) {
2574 1.1.1.1.4.2 rmind cp += usrp->lug_namelen;
2575 1.1.1.1.4.2 rmind *cp++ = '@';
2576 1.1.1.1.4.2 rmind NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
2577 1.1.1.1.4.2 rmind }
2578 1.1.1.1.4.2 rmind TAILQ_REMOVE(&nfsuserlruhead, usrp, lug_lru);
2579 1.1.1.1.4.2 rmind TAILQ_INSERT_TAIL(&nfsuserlruhead, usrp, lug_lru);
2580 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2581 1.1.1.1.4.2 rmind return;
2582 1.1.1.1.4.2 rmind }
2583 1.1.1.1.4.2 rmind }
2584 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2585 1.1.1.1.4.2 rmind cnt++;
2586 1.1.1.1.4.2 rmind ret = nfsrv_getuser(RPCNFSUSERD_GETUID, uid, (gid_t)0,
2587 1.1.1.1.4.2 rmind NULL, p);
2588 1.1.1.1.4.2 rmind if (ret == 0 && cnt < 2)
2589 1.1.1.1.4.2 rmind goto tryagain;
2590 1.1.1.1.4.2 rmind } else {
2591 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2592 1.1.1.1.4.2 rmind }
2593 1.1.1.1.4.2 rmind
2594 1.1.1.1.4.2 rmind /*
2595 1.1.1.1.4.2 rmind * No match, just return a string of digits.
2596 1.1.1.1.4.2 rmind */
2597 1.1.1.1.4.2 rmind tmp = uid;
2598 1.1.1.1.4.2 rmind i = 0;
2599 1.1.1.1.4.2 rmind while (tmp || i == 0) {
2600 1.1.1.1.4.2 rmind tmp /= 10;
2601 1.1.1.1.4.2 rmind i++;
2602 1.1.1.1.4.2 rmind }
2603 1.1.1.1.4.2 rmind len = (i > len) ? len : i;
2604 1.1.1.1.4.2 rmind *retlenp = len;
2605 1.1.1.1.4.2 rmind cp += (len - 1);
2606 1.1.1.1.4.2 rmind tmp = uid;
2607 1.1.1.1.4.2 rmind for (i = 0; i < len; i++) {
2608 1.1.1.1.4.2 rmind *cp-- = '0' + (tmp % 10);
2609 1.1.1.1.4.2 rmind tmp /= 10;
2610 1.1.1.1.4.2 rmind }
2611 1.1.1.1.4.2 rmind return;
2612 1.1.1.1.4.2 rmind }
2613 1.1.1.1.4.2 rmind
2614 1.1.1.1.4.2 rmind /*
2615 1.1.1.1.4.2 rmind * Convert a string to a uid.
2616 1.1.1.1.4.2 rmind * If no conversion is possible return NFSERR_BADOWNER, otherwise
2617 1.1.1.1.4.2 rmind * return 0.
2618 1.1.1.1.4.2 rmind * If this is called from a client side mount using AUTH_SYS and the
2619 1.1.1.1.4.2 rmind * string is made up entirely of digits, just convert the string to
2620 1.1.1.1.4.2 rmind * a number.
2621 1.1.1.1.4.2 rmind */
2622 1.1.1.1.4.2 rmind APPLESTATIC int
2623 1.1.1.1.4.2 rmind nfsv4_strtouid(struct nfsrv_descript *nd, u_char *str, int len, uid_t *uidp,
2624 1.1.1.1.4.2 rmind NFSPROC_T *p)
2625 1.1.1.1.4.2 rmind {
2626 1.1.1.1.4.2 rmind int i;
2627 1.1.1.1.4.2 rmind char *cp, *endstr, *str0;
2628 1.1.1.1.4.2 rmind struct nfsusrgrp *usrp;
2629 1.1.1.1.4.2 rmind int cnt, ret;
2630 1.1.1.1.4.2 rmind int error = 0;
2631 1.1.1.1.4.2 rmind uid_t tuid;
2632 1.1.1.1.4.2 rmind
2633 1.1.1.1.4.2 rmind if (len == 0) {
2634 1.1.1.1.4.2 rmind error = NFSERR_BADOWNER;
2635 1.1.1.1.4.2 rmind goto out;
2636 1.1.1.1.4.2 rmind }
2637 1.1.1.1.4.2 rmind /* If a string of digits and an AUTH_SYS mount, just convert it. */
2638 1.1.1.1.4.2 rmind str0 = str;
2639 1.1.1.1.4.2 rmind tuid = (uid_t)strtoul(str0, &endstr, 10);
2640 1.1.1.1.4.2 rmind if ((endstr - str0) == len &&
2641 1.1.1.1.4.2 rmind (nd->nd_flag & (ND_KERBV | ND_NFSCL)) == ND_NFSCL) {
2642 1.1.1.1.4.2 rmind *uidp = tuid;
2643 1.1.1.1.4.2 rmind goto out;
2644 1.1.1.1.4.2 rmind }
2645 1.1.1.1.4.2 rmind /*
2646 1.1.1.1.4.2 rmind * Look for an '@'.
2647 1.1.1.1.4.2 rmind */
2648 1.1.1.1.4.2 rmind cp = strchr(str0, '@');
2649 1.1.1.1.4.2 rmind if (cp != NULL)
2650 1.1.1.1.4.2 rmind i = (int)(cp++ - str0);
2651 1.1.1.1.4.2 rmind else
2652 1.1.1.1.4.2 rmind i = len;
2653 1.1.1.1.4.2 rmind
2654 1.1.1.1.4.2 rmind cnt = 0;
2655 1.1.1.1.4.2 rmind tryagain:
2656 1.1.1.1.4.2 rmind NFSLOCKNAMEID();
2657 1.1.1.1.4.2 rmind /*
2658 1.1.1.1.4.2 rmind * If an '@' is found and the domain name matches, search for the name
2659 1.1.1.1.4.2 rmind * with dns stripped off.
2660 1.1.1.1.4.2 rmind * Mixed case alpahbetics will match for the domain name, but all
2661 1.1.1.1.4.2 rmind * upper case will not.
2662 1.1.1.1.4.2 rmind */
2663 1.1.1.1.4.2 rmind if (cnt == 0 && i < len && i > 0 && nfsrv_dnsname &&
2664 1.1.1.1.4.2 rmind (len - 1 - i) == nfsrv_dnsnamelen &&
2665 1.1.1.1.4.2 rmind !nfsrv_cmpmixedcase(cp, nfsrv_dnsname, nfsrv_dnsnamelen)) {
2666 1.1.1.1.4.2 rmind len -= (nfsrv_dnsnamelen + 1);
2667 1.1.1.1.4.2 rmind *(cp - 1) = '\0';
2668 1.1.1.1.4.2 rmind }
2669 1.1.1.1.4.2 rmind
2670 1.1.1.1.4.2 rmind /*
2671 1.1.1.1.4.2 rmind * Check for the special case of "nobody".
2672 1.1.1.1.4.2 rmind */
2673 1.1.1.1.4.2 rmind if (len == 6 && !NFSBCMP(str, "nobody", 6)) {
2674 1.1.1.1.4.2 rmind *uidp = nfsrv_defaultuid;
2675 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2676 1.1.1.1.4.2 rmind error = 0;
2677 1.1.1.1.4.2 rmind goto out;
2678 1.1.1.1.4.2 rmind }
2679 1.1.1.1.4.2 rmind
2680 1.1.1.1.4.2 rmind LIST_FOREACH(usrp, NFSUSERNAMEHASH(str, len), lug_namehash) {
2681 1.1.1.1.4.2 rmind if (usrp->lug_namelen == len &&
2682 1.1.1.1.4.2 rmind !NFSBCMP(usrp->lug_name, str, len)) {
2683 1.1.1.1.4.2 rmind if (usrp->lug_expiry < NFSD_MONOSEC)
2684 1.1.1.1.4.2 rmind break;
2685 1.1.1.1.4.2 rmind *uidp = usrp->lug_uid;
2686 1.1.1.1.4.2 rmind TAILQ_REMOVE(&nfsuserlruhead, usrp, lug_lru);
2687 1.1.1.1.4.2 rmind TAILQ_INSERT_TAIL(&nfsuserlruhead, usrp, lug_lru);
2688 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2689 1.1.1.1.4.2 rmind error = 0;
2690 1.1.1.1.4.2 rmind goto out;
2691 1.1.1.1.4.2 rmind }
2692 1.1.1.1.4.2 rmind }
2693 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2694 1.1.1.1.4.2 rmind cnt++;
2695 1.1.1.1.4.2 rmind ret = nfsrv_getuser(RPCNFSUSERD_GETUSER, (uid_t)0, (gid_t)0,
2696 1.1.1.1.4.2 rmind str, p);
2697 1.1.1.1.4.2 rmind if (ret == 0 && cnt < 2)
2698 1.1.1.1.4.2 rmind goto tryagain;
2699 1.1.1.1.4.2 rmind error = NFSERR_BADOWNER;
2700 1.1.1.1.4.2 rmind
2701 1.1.1.1.4.2 rmind out:
2702 1.1.1.1.4.2 rmind NFSEXITCODE(error);
2703 1.1.1.1.4.2 rmind return (error);
2704 1.1.1.1.4.2 rmind }
2705 1.1.1.1.4.2 rmind
2706 1.1.1.1.4.2 rmind /*
2707 1.1.1.1.4.2 rmind * Convert a gid to a string.
2708 1.1.1.1.4.2 rmind * gid - the group id
2709 1.1.1.1.4.2 rmind * cpp - points to a buffer of size NFSV4_SMALLSTR
2710 1.1.1.1.4.2 rmind * (malloc a larger one, as required)
2711 1.1.1.1.4.2 rmind * retlenp - pointer to length to be returned
2712 1.1.1.1.4.2 rmind */
2713 1.1.1.1.4.2 rmind APPLESTATIC void
2714 1.1.1.1.4.2 rmind nfsv4_gidtostr(gid_t gid, u_char **cpp, int *retlenp, NFSPROC_T *p)
2715 1.1.1.1.4.2 rmind {
2716 1.1.1.1.4.2 rmind int i;
2717 1.1.1.1.4.2 rmind struct nfsusrgrp *usrp;
2718 1.1.1.1.4.2 rmind u_char *cp = *cpp;
2719 1.1.1.1.4.2 rmind gid_t tmp;
2720 1.1.1.1.4.2 rmind int cnt, hasampersand, len = NFSV4_SMALLSTR, ret;
2721 1.1.1.1.4.2 rmind
2722 1.1.1.1.4.2 rmind cnt = 0;
2723 1.1.1.1.4.2 rmind tryagain:
2724 1.1.1.1.4.2 rmind NFSLOCKNAMEID();
2725 1.1.1.1.4.2 rmind if (nfsrv_dnsname) {
2726 1.1.1.1.4.2 rmind /*
2727 1.1.1.1.4.2 rmind * Always map nfsrv_defaultgid to "nogroup".
2728 1.1.1.1.4.2 rmind */
2729 1.1.1.1.4.2 rmind if (gid == nfsrv_defaultgid) {
2730 1.1.1.1.4.2 rmind i = nfsrv_dnsnamelen + 8;
2731 1.1.1.1.4.2 rmind if (i > len) {
2732 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2733 1.1.1.1.4.2 rmind if (len > NFSV4_SMALLSTR)
2734 1.1.1.1.4.2 rmind free(cp, M_NFSSTRING);
2735 1.1.1.1.4.2 rmind cp = malloc(i, M_NFSSTRING, M_WAITOK);
2736 1.1.1.1.4.2 rmind *cpp = cp;
2737 1.1.1.1.4.2 rmind len = i;
2738 1.1.1.1.4.2 rmind goto tryagain;
2739 1.1.1.1.4.2 rmind }
2740 1.1.1.1.4.2 rmind *retlenp = i;
2741 1.1.1.1.4.2 rmind NFSBCOPY("nogroup@", cp, 8);
2742 1.1.1.1.4.2 rmind cp += 8;
2743 1.1.1.1.4.2 rmind NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
2744 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2745 1.1.1.1.4.2 rmind return;
2746 1.1.1.1.4.2 rmind }
2747 1.1.1.1.4.2 rmind hasampersand = 0;
2748 1.1.1.1.4.2 rmind LIST_FOREACH(usrp, NFSGROUPHASH(gid), lug_numhash) {
2749 1.1.1.1.4.2 rmind if (usrp->lug_gid == gid) {
2750 1.1.1.1.4.2 rmind if (usrp->lug_expiry < NFSD_MONOSEC)
2751 1.1.1.1.4.2 rmind break;
2752 1.1.1.1.4.2 rmind /*
2753 1.1.1.1.4.2 rmind * If the name doesn't already have an '@'
2754 1.1.1.1.4.2 rmind * in it, append @domainname to it.
2755 1.1.1.1.4.2 rmind */
2756 1.1.1.1.4.2 rmind for (i = 0; i < usrp->lug_namelen; i++) {
2757 1.1.1.1.4.2 rmind if (usrp->lug_name[i] == '@') {
2758 1.1.1.1.4.2 rmind hasampersand = 1;
2759 1.1.1.1.4.2 rmind break;
2760 1.1.1.1.4.2 rmind }
2761 1.1.1.1.4.2 rmind }
2762 1.1.1.1.4.2 rmind if (hasampersand)
2763 1.1.1.1.4.2 rmind i = usrp->lug_namelen;
2764 1.1.1.1.4.2 rmind else
2765 1.1.1.1.4.2 rmind i = usrp->lug_namelen +
2766 1.1.1.1.4.2 rmind nfsrv_dnsnamelen + 1;
2767 1.1.1.1.4.2 rmind if (i > len) {
2768 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2769 1.1.1.1.4.2 rmind if (len > NFSV4_SMALLSTR)
2770 1.1.1.1.4.2 rmind free(cp, M_NFSSTRING);
2771 1.1.1.1.4.2 rmind cp = malloc(i, M_NFSSTRING, M_WAITOK);
2772 1.1.1.1.4.2 rmind *cpp = cp;
2773 1.1.1.1.4.2 rmind len = i;
2774 1.1.1.1.4.2 rmind goto tryagain;
2775 1.1.1.1.4.2 rmind }
2776 1.1.1.1.4.2 rmind *retlenp = i;
2777 1.1.1.1.4.2 rmind NFSBCOPY(usrp->lug_name, cp, usrp->lug_namelen);
2778 1.1.1.1.4.2 rmind if (!hasampersand) {
2779 1.1.1.1.4.2 rmind cp += usrp->lug_namelen;
2780 1.1.1.1.4.2 rmind *cp++ = '@';
2781 1.1.1.1.4.2 rmind NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
2782 1.1.1.1.4.2 rmind }
2783 1.1.1.1.4.2 rmind TAILQ_REMOVE(&nfsuserlruhead, usrp, lug_lru);
2784 1.1.1.1.4.2 rmind TAILQ_INSERT_TAIL(&nfsuserlruhead, usrp, lug_lru);
2785 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2786 1.1.1.1.4.2 rmind return;
2787 1.1.1.1.4.2 rmind }
2788 1.1.1.1.4.2 rmind }
2789 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2790 1.1.1.1.4.2 rmind cnt++;
2791 1.1.1.1.4.2 rmind ret = nfsrv_getuser(RPCNFSUSERD_GETGID, (uid_t)0, gid,
2792 1.1.1.1.4.2 rmind NULL, p);
2793 1.1.1.1.4.2 rmind if (ret == 0 && cnt < 2)
2794 1.1.1.1.4.2 rmind goto tryagain;
2795 1.1.1.1.4.2 rmind } else {
2796 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2797 1.1.1.1.4.2 rmind }
2798 1.1.1.1.4.2 rmind
2799 1.1.1.1.4.2 rmind /*
2800 1.1.1.1.4.2 rmind * No match, just return a string of digits.
2801 1.1.1.1.4.2 rmind */
2802 1.1.1.1.4.2 rmind tmp = gid;
2803 1.1.1.1.4.2 rmind i = 0;
2804 1.1.1.1.4.2 rmind while (tmp || i == 0) {
2805 1.1.1.1.4.2 rmind tmp /= 10;
2806 1.1.1.1.4.2 rmind i++;
2807 1.1.1.1.4.2 rmind }
2808 1.1.1.1.4.2 rmind len = (i > len) ? len : i;
2809 1.1.1.1.4.2 rmind *retlenp = len;
2810 1.1.1.1.4.2 rmind cp += (len - 1);
2811 1.1.1.1.4.2 rmind tmp = gid;
2812 1.1.1.1.4.2 rmind for (i = 0; i < len; i++) {
2813 1.1.1.1.4.2 rmind *cp-- = '0' + (tmp % 10);
2814 1.1.1.1.4.2 rmind tmp /= 10;
2815 1.1.1.1.4.2 rmind }
2816 1.1.1.1.4.2 rmind return;
2817 1.1.1.1.4.2 rmind }
2818 1.1.1.1.4.2 rmind
2819 1.1.1.1.4.2 rmind /*
2820 1.1.1.1.4.2 rmind * Convert a string to a gid.
2821 1.1.1.1.4.2 rmind * If no conversion is possible return NFSERR_BADOWNER, otherwise
2822 1.1.1.1.4.2 rmind * return 0.
2823 1.1.1.1.4.2 rmind * If this is called from a client side mount using AUTH_SYS and the
2824 1.1.1.1.4.2 rmind * string is made up entirely of digits, just convert the string to
2825 1.1.1.1.4.2 rmind * a number.
2826 1.1.1.1.4.2 rmind */
2827 1.1.1.1.4.2 rmind APPLESTATIC int
2828 1.1.1.1.4.2 rmind nfsv4_strtogid(struct nfsrv_descript *nd, u_char *str, int len, gid_t *gidp,
2829 1.1.1.1.4.2 rmind NFSPROC_T *p)
2830 1.1.1.1.4.2 rmind {
2831 1.1.1.1.4.2 rmind int i;
2832 1.1.1.1.4.2 rmind char *cp, *endstr, *str0;
2833 1.1.1.1.4.2 rmind struct nfsusrgrp *usrp;
2834 1.1.1.1.4.2 rmind int cnt, ret;
2835 1.1.1.1.4.2 rmind int error = 0;
2836 1.1.1.1.4.2 rmind gid_t tgid;
2837 1.1.1.1.4.2 rmind
2838 1.1.1.1.4.2 rmind if (len == 0) {
2839 1.1.1.1.4.2 rmind error = NFSERR_BADOWNER;
2840 1.1.1.1.4.2 rmind goto out;
2841 1.1.1.1.4.2 rmind }
2842 1.1.1.1.4.2 rmind /* If a string of digits and an AUTH_SYS mount, just convert it. */
2843 1.1.1.1.4.2 rmind str0 = str;
2844 1.1.1.1.4.2 rmind tgid = (gid_t)strtoul(str0, &endstr, 10);
2845 1.1.1.1.4.2 rmind if ((endstr - str0) == len &&
2846 1.1.1.1.4.2 rmind (nd->nd_flag & (ND_KERBV | ND_NFSCL)) == ND_NFSCL) {
2847 1.1.1.1.4.2 rmind *gidp = tgid;
2848 1.1.1.1.4.2 rmind goto out;
2849 1.1.1.1.4.2 rmind }
2850 1.1.1.1.4.2 rmind /*
2851 1.1.1.1.4.2 rmind * Look for an '@'.
2852 1.1.1.1.4.2 rmind */
2853 1.1.1.1.4.2 rmind cp = strchr(str0, '@');
2854 1.1.1.1.4.2 rmind if (cp != NULL)
2855 1.1.1.1.4.2 rmind i = (int)(cp++ - str0);
2856 1.1.1.1.4.2 rmind else
2857 1.1.1.1.4.2 rmind i = len;
2858 1.1.1.1.4.2 rmind
2859 1.1.1.1.4.2 rmind cnt = 0;
2860 1.1.1.1.4.2 rmind tryagain:
2861 1.1.1.1.4.2 rmind NFSLOCKNAMEID();
2862 1.1.1.1.4.2 rmind /*
2863 1.1.1.1.4.2 rmind * If an '@' is found and the dns name matches, search for the name
2864 1.1.1.1.4.2 rmind * with the dns stripped off.
2865 1.1.1.1.4.2 rmind */
2866 1.1.1.1.4.2 rmind if (cnt == 0 && i < len && i > 0 && nfsrv_dnsname &&
2867 1.1.1.1.4.2 rmind (len - 1 - i) == nfsrv_dnsnamelen &&
2868 1.1.1.1.4.2 rmind !nfsrv_cmpmixedcase(cp, nfsrv_dnsname, nfsrv_dnsnamelen)) {
2869 1.1.1.1.4.2 rmind len -= (nfsrv_dnsnamelen + 1);
2870 1.1.1.1.4.2 rmind *(cp - 1) = '\0';
2871 1.1.1.1.4.2 rmind }
2872 1.1.1.1.4.2 rmind
2873 1.1.1.1.4.2 rmind /*
2874 1.1.1.1.4.2 rmind * Check for the special case of "nogroup".
2875 1.1.1.1.4.2 rmind */
2876 1.1.1.1.4.2 rmind if (len == 7 && !NFSBCMP(str, "nogroup", 7)) {
2877 1.1.1.1.4.2 rmind *gidp = nfsrv_defaultgid;
2878 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2879 1.1.1.1.4.2 rmind error = 0;
2880 1.1.1.1.4.2 rmind goto out;
2881 1.1.1.1.4.2 rmind }
2882 1.1.1.1.4.2 rmind
2883 1.1.1.1.4.2 rmind LIST_FOREACH(usrp, NFSGROUPNAMEHASH(str, len), lug_namehash) {
2884 1.1.1.1.4.2 rmind if (usrp->lug_namelen == len &&
2885 1.1.1.1.4.2 rmind !NFSBCMP(usrp->lug_name, str, len)) {
2886 1.1.1.1.4.2 rmind if (usrp->lug_expiry < NFSD_MONOSEC)
2887 1.1.1.1.4.2 rmind break;
2888 1.1.1.1.4.2 rmind *gidp = usrp->lug_gid;
2889 1.1.1.1.4.2 rmind TAILQ_REMOVE(&nfsuserlruhead, usrp, lug_lru);
2890 1.1.1.1.4.2 rmind TAILQ_INSERT_TAIL(&nfsuserlruhead, usrp, lug_lru);
2891 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2892 1.1.1.1.4.2 rmind error = 0;
2893 1.1.1.1.4.2 rmind goto out;
2894 1.1.1.1.4.2 rmind }
2895 1.1.1.1.4.2 rmind }
2896 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2897 1.1.1.1.4.2 rmind cnt++;
2898 1.1.1.1.4.2 rmind ret = nfsrv_getuser(RPCNFSUSERD_GETGROUP, (uid_t)0, (gid_t)0,
2899 1.1.1.1.4.2 rmind str, p);
2900 1.1.1.1.4.2 rmind if (ret == 0 && cnt < 2)
2901 1.1.1.1.4.2 rmind goto tryagain;
2902 1.1.1.1.4.2 rmind error = NFSERR_BADOWNER;
2903 1.1.1.1.4.2 rmind
2904 1.1.1.1.4.2 rmind out:
2905 1.1.1.1.4.2 rmind NFSEXITCODE(error);
2906 1.1.1.1.4.2 rmind return (error);
2907 1.1.1.1.4.2 rmind }
2908 1.1.1.1.4.2 rmind
2909 1.1.1.1.4.2 rmind /*
2910 1.1.1.1.4.2 rmind * Cmp len chars, allowing mixed case in the first argument to match lower
2911 1.1.1.1.4.2 rmind * case in the second, but not if the first argument is all upper case.
2912 1.1.1.1.4.2 rmind * Return 0 for a match, 1 otherwise.
2913 1.1.1.1.4.2 rmind */
2914 1.1.1.1.4.2 rmind static int
2915 1.1.1.1.4.2 rmind nfsrv_cmpmixedcase(u_char *cp, u_char *cp2, int len)
2916 1.1.1.1.4.2 rmind {
2917 1.1.1.1.4.2 rmind int i;
2918 1.1.1.1.4.2 rmind u_char tmp;
2919 1.1.1.1.4.2 rmind int fndlower = 0;
2920 1.1.1.1.4.2 rmind
2921 1.1.1.1.4.2 rmind for (i = 0; i < len; i++) {
2922 1.1.1.1.4.2 rmind if (*cp >= 'A' && *cp <= 'Z') {
2923 1.1.1.1.4.2 rmind tmp = *cp++ + ('a' - 'A');
2924 1.1.1.1.4.2 rmind } else {
2925 1.1.1.1.4.2 rmind tmp = *cp++;
2926 1.1.1.1.4.2 rmind if (tmp >= 'a' && tmp <= 'z')
2927 1.1.1.1.4.2 rmind fndlower = 1;
2928 1.1.1.1.4.2 rmind }
2929 1.1.1.1.4.2 rmind if (tmp != *cp2++)
2930 1.1.1.1.4.2 rmind return (1);
2931 1.1.1.1.4.2 rmind }
2932 1.1.1.1.4.2 rmind if (fndlower)
2933 1.1.1.1.4.2 rmind return (0);
2934 1.1.1.1.4.2 rmind else
2935 1.1.1.1.4.2 rmind return (1);
2936 1.1.1.1.4.2 rmind }
2937 1.1.1.1.4.2 rmind
2938 1.1.1.1.4.2 rmind /*
2939 1.1.1.1.4.2 rmind * Set the port for the nfsuserd.
2940 1.1.1.1.4.2 rmind */
2941 1.1.1.1.4.2 rmind APPLESTATIC int
2942 1.1.1.1.4.2 rmind nfsrv_nfsuserdport(u_short port, NFSPROC_T *p)
2943 1.1.1.1.4.2 rmind {
2944 1.1.1.1.4.2 rmind struct nfssockreq *rp;
2945 1.1.1.1.4.2 rmind struct sockaddr_in *ad;
2946 1.1.1.1.4.2 rmind int error;
2947 1.1.1.1.4.2 rmind
2948 1.1.1.1.4.2 rmind NFSLOCKNAMEID();
2949 1.1.1.1.4.2 rmind if (nfsrv_nfsuserd) {
2950 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2951 1.1.1.1.4.2 rmind error = EPERM;
2952 1.1.1.1.4.2 rmind goto out;
2953 1.1.1.1.4.2 rmind }
2954 1.1.1.1.4.2 rmind nfsrv_nfsuserd = 1;
2955 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2956 1.1.1.1.4.2 rmind /*
2957 1.1.1.1.4.2 rmind * Set up the socket record and connect.
2958 1.1.1.1.4.2 rmind */
2959 1.1.1.1.4.2 rmind rp = &nfsrv_nfsuserdsock;
2960 1.1.1.1.4.2 rmind rp->nr_client = NULL;
2961 1.1.1.1.4.2 rmind rp->nr_sotype = SOCK_DGRAM;
2962 1.1.1.1.4.2 rmind rp->nr_soproto = IPPROTO_UDP;
2963 1.1.1.1.4.2 rmind rp->nr_lock = (NFSR_RESERVEDPORT | NFSR_LOCALHOST);
2964 1.1.1.1.4.2 rmind rp->nr_cred = NULL;
2965 1.1.1.1.4.2 rmind NFSSOCKADDRALLOC(rp->nr_nam);
2966 1.1.1.1.4.2 rmind NFSSOCKADDRSIZE(rp->nr_nam, sizeof (struct sockaddr_in));
2967 1.1.1.1.4.2 rmind ad = NFSSOCKADDR(rp->nr_nam, struct sockaddr_in *);
2968 1.1.1.1.4.2 rmind ad->sin_family = AF_INET;
2969 1.1.1.1.4.2 rmind ad->sin_addr.s_addr = htonl((u_int32_t)0x7f000001); /* 127.0.0.1 */
2970 1.1.1.1.4.2 rmind ad->sin_port = port;
2971 1.1.1.1.4.2 rmind rp->nr_prog = RPCPROG_NFSUSERD;
2972 1.1.1.1.4.2 rmind rp->nr_vers = RPCNFSUSERD_VERS;
2973 1.1.1.1.4.2 rmind error = newnfs_connect(NULL, rp, NFSPROCCRED(p), p, 0);
2974 1.1.1.1.4.2 rmind if (error) {
2975 1.1.1.1.4.2 rmind NFSSOCKADDRFREE(rp->nr_nam);
2976 1.1.1.1.4.2 rmind nfsrv_nfsuserd = 0;
2977 1.1.1.1.4.2 rmind }
2978 1.1.1.1.4.2 rmind out:
2979 1.1.1.1.4.2 rmind NFSEXITCODE(error);
2980 1.1.1.1.4.2 rmind return (error);
2981 1.1.1.1.4.2 rmind }
2982 1.1.1.1.4.2 rmind
2983 1.1.1.1.4.2 rmind /*
2984 1.1.1.1.4.2 rmind * Delete the nfsuserd port.
2985 1.1.1.1.4.2 rmind */
2986 1.1.1.1.4.2 rmind APPLESTATIC void
2987 1.1.1.1.4.2 rmind nfsrv_nfsuserddelport(void)
2988 1.1.1.1.4.2 rmind {
2989 1.1.1.1.4.2 rmind
2990 1.1.1.1.4.2 rmind NFSLOCKNAMEID();
2991 1.1.1.1.4.2 rmind if (nfsrv_nfsuserd == 0) {
2992 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2993 1.1.1.1.4.2 rmind return;
2994 1.1.1.1.4.2 rmind }
2995 1.1.1.1.4.2 rmind nfsrv_nfsuserd = 0;
2996 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
2997 1.1.1.1.4.2 rmind newnfs_disconnect(&nfsrv_nfsuserdsock);
2998 1.1.1.1.4.2 rmind NFSSOCKADDRFREE(nfsrv_nfsuserdsock.nr_nam);
2999 1.1.1.1.4.2 rmind }
3000 1.1.1.1.4.2 rmind
3001 1.1.1.1.4.2 rmind /*
3002 1.1.1.1.4.2 rmind * Do upcalls to the nfsuserd, for cache misses of the owner/ownergroup
3003 1.1.1.1.4.2 rmind * name<-->id cache.
3004 1.1.1.1.4.2 rmind * Returns 0 upon success, non-zero otherwise.
3005 1.1.1.1.4.2 rmind */
3006 1.1.1.1.4.2 rmind static int
3007 1.1.1.1.4.2 rmind nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name, NFSPROC_T *p)
3008 1.1.1.1.4.2 rmind {
3009 1.1.1.1.4.2 rmind u_int32_t *tl;
3010 1.1.1.1.4.2 rmind struct nfsrv_descript *nd;
3011 1.1.1.1.4.2 rmind int len;
3012 1.1.1.1.4.2 rmind struct nfsrv_descript nfsd;
3013 1.1.1.1.4.2 rmind struct ucred *cred;
3014 1.1.1.1.4.2 rmind int error;
3015 1.1.1.1.4.2 rmind
3016 1.1.1.1.4.2 rmind NFSLOCKNAMEID();
3017 1.1.1.1.4.2 rmind if (nfsrv_nfsuserd == 0) {
3018 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
3019 1.1.1.1.4.2 rmind error = EPERM;
3020 1.1.1.1.4.2 rmind goto out;
3021 1.1.1.1.4.2 rmind }
3022 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
3023 1.1.1.1.4.2 rmind nd = &nfsd;
3024 1.1.1.1.4.2 rmind cred = newnfs_getcred();
3025 1.1.1.1.4.2 rmind nd->nd_flag = ND_GSSINITREPLY;
3026 1.1.1.1.4.2 rmind nfsrvd_rephead(nd);
3027 1.1.1.1.4.2 rmind
3028 1.1.1.1.4.2 rmind nd->nd_procnum = procnum;
3029 1.1.1.1.4.2 rmind if (procnum == RPCNFSUSERD_GETUID || procnum == RPCNFSUSERD_GETGID) {
3030 1.1.1.1.4.2 rmind NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
3031 1.1.1.1.4.2 rmind if (procnum == RPCNFSUSERD_GETUID)
3032 1.1.1.1.4.2 rmind *tl = txdr_unsigned(uid);
3033 1.1.1.1.4.2 rmind else
3034 1.1.1.1.4.2 rmind *tl = txdr_unsigned(gid);
3035 1.1.1.1.4.2 rmind } else {
3036 1.1.1.1.4.2 rmind len = strlen(name);
3037 1.1.1.1.4.2 rmind (void) nfsm_strtom(nd, name, len);
3038 1.1.1.1.4.2 rmind }
3039 1.1.1.1.4.2 rmind error = newnfs_request(nd, NULL, NULL, &nfsrv_nfsuserdsock, NULL, NULL,
3040 1.1.1.1.4.2 rmind cred, RPCPROG_NFSUSERD, RPCNFSUSERD_VERS, NULL, 0, NULL, NULL);
3041 1.1.1.1.4.2 rmind NFSFREECRED(cred);
3042 1.1.1.1.4.2 rmind if (!error) {
3043 1.1.1.1.4.2 rmind mbuf_freem(nd->nd_mrep);
3044 1.1.1.1.4.2 rmind error = nd->nd_repstat;
3045 1.1.1.1.4.2 rmind }
3046 1.1.1.1.4.2 rmind out:
3047 1.1.1.1.4.2 rmind NFSEXITCODE(error);
3048 1.1.1.1.4.2 rmind return (error);
3049 1.1.1.1.4.2 rmind }
3050 1.1.1.1.4.2 rmind
3051 1.1.1.1.4.2 rmind /*
3052 1.1.1.1.4.2 rmind * This function is called from the nfssvc(2) system call, to update the
3053 1.1.1.1.4.2 rmind * kernel user/group name list(s) for the V4 owner and ownergroup attributes.
3054 1.1.1.1.4.2 rmind */
3055 1.1.1.1.4.2 rmind APPLESTATIC int
3056 1.1.1.1.4.2 rmind nfssvc_idname(struct nfsd_idargs *nidp)
3057 1.1.1.1.4.2 rmind {
3058 1.1.1.1.4.2 rmind struct nfsusrgrp *nusrp, *usrp, *newusrp;
3059 1.1.1.1.4.2 rmind struct nfsuserhashhead *hp;
3060 1.1.1.1.4.2 rmind int i;
3061 1.1.1.1.4.2 rmind int error = 0;
3062 1.1.1.1.4.2 rmind u_char *cp;
3063 1.1.1.1.4.2 rmind
3064 1.1.1.1.4.2 rmind if (nidp->nid_flag & NFSID_INITIALIZE) {
3065 1.1.1.1.4.2 rmind cp = (u_char *)malloc(nidp->nid_namelen + 1,
3066 1.1.1.1.4.2 rmind M_NFSSTRING, M_WAITOK);
3067 1.1.1.1.4.2 rmind error = copyin(CAST_USER_ADDR_T(nidp->nid_name), cp,
3068 1.1.1.1.4.2 rmind nidp->nid_namelen);
3069 1.1.1.1.4.2 rmind NFSLOCKNAMEID();
3070 1.1.1.1.4.2 rmind if (nfsrv_dnsname) {
3071 1.1.1.1.4.2 rmind /*
3072 1.1.1.1.4.2 rmind * Free up all the old stuff and reinitialize hash lists.
3073 1.1.1.1.4.2 rmind */
3074 1.1.1.1.4.2 rmind TAILQ_FOREACH_SAFE(usrp, &nfsuserlruhead, lug_lru, nusrp) {
3075 1.1.1.1.4.2 rmind nfsrv_removeuser(usrp);
3076 1.1.1.1.4.2 rmind }
3077 1.1.1.1.4.2 rmind free(nfsrv_dnsname, M_NFSSTRING);
3078 1.1.1.1.4.2 rmind nfsrv_dnsname = NULL;
3079 1.1.1.1.4.2 rmind }
3080 1.1.1.1.4.2 rmind TAILQ_INIT(&nfsuserlruhead);
3081 1.1.1.1.4.2 rmind for (i = 0; i < NFSUSERHASHSIZE; i++)
3082 1.1.1.1.4.2 rmind LIST_INIT(&nfsuserhash[i]);
3083 1.1.1.1.4.2 rmind for (i = 0; i < NFSGROUPHASHSIZE; i++)
3084 1.1.1.1.4.2 rmind LIST_INIT(&nfsgrouphash[i]);
3085 1.1.1.1.4.2 rmind for (i = 0; i < NFSUSERHASHSIZE; i++)
3086 1.1.1.1.4.2 rmind LIST_INIT(&nfsusernamehash[i]);
3087 1.1.1.1.4.2 rmind for (i = 0; i < NFSGROUPHASHSIZE; i++)
3088 1.1.1.1.4.2 rmind LIST_INIT(&nfsgroupnamehash[i]);
3089 1.1.1.1.4.2 rmind
3090 1.1.1.1.4.2 rmind /*
3091 1.1.1.1.4.2 rmind * Put name in "DNS" string.
3092 1.1.1.1.4.2 rmind */
3093 1.1.1.1.4.2 rmind if (!error) {
3094 1.1.1.1.4.2 rmind nfsrv_dnsname = cp;
3095 1.1.1.1.4.2 rmind nfsrv_dnsnamelen = nidp->nid_namelen;
3096 1.1.1.1.4.2 rmind nfsrv_defaultuid = nidp->nid_uid;
3097 1.1.1.1.4.2 rmind nfsrv_defaultgid = nidp->nid_gid;
3098 1.1.1.1.4.2 rmind nfsrv_usercnt = 0;
3099 1.1.1.1.4.2 rmind nfsrv_usermax = nidp->nid_usermax;
3100 1.1.1.1.4.2 rmind }
3101 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
3102 1.1.1.1.4.2 rmind if (error)
3103 1.1.1.1.4.2 rmind free(cp, M_NFSSTRING);
3104 1.1.1.1.4.2 rmind goto out;
3105 1.1.1.1.4.2 rmind }
3106 1.1.1.1.4.2 rmind
3107 1.1.1.1.4.2 rmind /*
3108 1.1.1.1.4.2 rmind * malloc the new one now, so any potential sleep occurs before
3109 1.1.1.1.4.2 rmind * manipulation of the lists.
3110 1.1.1.1.4.2 rmind */
3111 1.1.1.1.4.2 rmind MALLOC(newusrp, struct nfsusrgrp *, sizeof (struct nfsusrgrp) +
3112 1.1.1.1.4.2 rmind nidp->nid_namelen, M_NFSUSERGROUP, M_WAITOK);
3113 1.1.1.1.4.2 rmind error = copyin(CAST_USER_ADDR_T(nidp->nid_name), newusrp->lug_name,
3114 1.1.1.1.4.2 rmind nidp->nid_namelen);
3115 1.1.1.1.4.2 rmind if (error) {
3116 1.1.1.1.4.2 rmind free((caddr_t)newusrp, M_NFSUSERGROUP);
3117 1.1.1.1.4.2 rmind goto out;
3118 1.1.1.1.4.2 rmind }
3119 1.1.1.1.4.2 rmind newusrp->lug_namelen = nidp->nid_namelen;
3120 1.1.1.1.4.2 rmind
3121 1.1.1.1.4.2 rmind NFSLOCKNAMEID();
3122 1.1.1.1.4.2 rmind /*
3123 1.1.1.1.4.2 rmind * Delete old entries, as required.
3124 1.1.1.1.4.2 rmind */
3125 1.1.1.1.4.2 rmind if (nidp->nid_flag & (NFSID_DELUID | NFSID_ADDUID)) {
3126 1.1.1.1.4.2 rmind hp = NFSUSERHASH(nidp->nid_uid);
3127 1.1.1.1.4.2 rmind LIST_FOREACH_SAFE(usrp, hp, lug_numhash, nusrp) {
3128 1.1.1.1.4.2 rmind if (usrp->lug_uid == nidp->nid_uid)
3129 1.1.1.1.4.2 rmind nfsrv_removeuser(usrp);
3130 1.1.1.1.4.2 rmind }
3131 1.1.1.1.4.2 rmind }
3132 1.1.1.1.4.2 rmind if (nidp->nid_flag & (NFSID_DELUSERNAME | NFSID_ADDUSERNAME)) {
3133 1.1.1.1.4.2 rmind hp = NFSUSERNAMEHASH(newusrp->lug_name, newusrp->lug_namelen);
3134 1.1.1.1.4.2 rmind LIST_FOREACH_SAFE(usrp, hp, lug_namehash, nusrp) {
3135 1.1.1.1.4.2 rmind if (usrp->lug_namelen == newusrp->lug_namelen &&
3136 1.1.1.1.4.2 rmind !NFSBCMP(usrp->lug_name, newusrp->lug_name,
3137 1.1.1.1.4.2 rmind usrp->lug_namelen))
3138 1.1.1.1.4.2 rmind nfsrv_removeuser(usrp);
3139 1.1.1.1.4.2 rmind }
3140 1.1.1.1.4.2 rmind }
3141 1.1.1.1.4.2 rmind if (nidp->nid_flag & (NFSID_DELGID | NFSID_ADDGID)) {
3142 1.1.1.1.4.2 rmind hp = NFSGROUPHASH(nidp->nid_gid);
3143 1.1.1.1.4.2 rmind LIST_FOREACH_SAFE(usrp, hp, lug_numhash, nusrp) {
3144 1.1.1.1.4.2 rmind if (usrp->lug_gid == nidp->nid_gid)
3145 1.1.1.1.4.2 rmind nfsrv_removeuser(usrp);
3146 1.1.1.1.4.2 rmind }
3147 1.1.1.1.4.2 rmind }
3148 1.1.1.1.4.2 rmind if (nidp->nid_flag & (NFSID_DELGROUPNAME | NFSID_ADDGROUPNAME)) {
3149 1.1.1.1.4.2 rmind hp = NFSGROUPNAMEHASH(newusrp->lug_name, newusrp->lug_namelen);
3150 1.1.1.1.4.2 rmind LIST_FOREACH_SAFE(usrp, hp, lug_namehash, nusrp) {
3151 1.1.1.1.4.2 rmind if (usrp->lug_namelen == newusrp->lug_namelen &&
3152 1.1.1.1.4.2 rmind !NFSBCMP(usrp->lug_name, newusrp->lug_name,
3153 1.1.1.1.4.2 rmind usrp->lug_namelen))
3154 1.1.1.1.4.2 rmind nfsrv_removeuser(usrp);
3155 1.1.1.1.4.2 rmind }
3156 1.1.1.1.4.2 rmind }
3157 1.1.1.1.4.2 rmind TAILQ_FOREACH_SAFE(usrp, &nfsuserlruhead, lug_lru, nusrp) {
3158 1.1.1.1.4.2 rmind if (usrp->lug_expiry < NFSD_MONOSEC)
3159 1.1.1.1.4.2 rmind nfsrv_removeuser(usrp);
3160 1.1.1.1.4.2 rmind }
3161 1.1.1.1.4.2 rmind while (nfsrv_usercnt >= nfsrv_usermax) {
3162 1.1.1.1.4.2 rmind usrp = TAILQ_FIRST(&nfsuserlruhead);
3163 1.1.1.1.4.2 rmind nfsrv_removeuser(usrp);
3164 1.1.1.1.4.2 rmind }
3165 1.1.1.1.4.2 rmind
3166 1.1.1.1.4.2 rmind /*
3167 1.1.1.1.4.2 rmind * Now, we can add the new one.
3168 1.1.1.1.4.2 rmind */
3169 1.1.1.1.4.2 rmind if (nidp->nid_usertimeout)
3170 1.1.1.1.4.2 rmind newusrp->lug_expiry = NFSD_MONOSEC + nidp->nid_usertimeout;
3171 1.1.1.1.4.2 rmind else
3172 1.1.1.1.4.2 rmind newusrp->lug_expiry = NFSD_MONOSEC + 5;
3173 1.1.1.1.4.2 rmind if (nidp->nid_flag & (NFSID_ADDUID | NFSID_ADDUSERNAME)) {
3174 1.1.1.1.4.2 rmind newusrp->lug_uid = nidp->nid_uid;
3175 1.1.1.1.4.2 rmind LIST_INSERT_HEAD(NFSUSERHASH(newusrp->lug_uid), newusrp,
3176 1.1.1.1.4.2 rmind lug_numhash);
3177 1.1.1.1.4.2 rmind LIST_INSERT_HEAD(NFSUSERNAMEHASH(newusrp->lug_name,
3178 1.1.1.1.4.2 rmind newusrp->lug_namelen), newusrp, lug_namehash);
3179 1.1.1.1.4.2 rmind TAILQ_INSERT_TAIL(&nfsuserlruhead, newusrp, lug_lru);
3180 1.1.1.1.4.2 rmind nfsrv_usercnt++;
3181 1.1.1.1.4.2 rmind } else if (nidp->nid_flag & (NFSID_ADDGID | NFSID_ADDGROUPNAME)) {
3182 1.1.1.1.4.2 rmind newusrp->lug_gid = nidp->nid_gid;
3183 1.1.1.1.4.2 rmind LIST_INSERT_HEAD(NFSGROUPHASH(newusrp->lug_gid), newusrp,
3184 1.1.1.1.4.2 rmind lug_numhash);
3185 1.1.1.1.4.2 rmind LIST_INSERT_HEAD(NFSGROUPNAMEHASH(newusrp->lug_name,
3186 1.1.1.1.4.2 rmind newusrp->lug_namelen), newusrp, lug_namehash);
3187 1.1.1.1.4.2 rmind TAILQ_INSERT_TAIL(&nfsuserlruhead, newusrp, lug_lru);
3188 1.1.1.1.4.2 rmind nfsrv_usercnt++;
3189 1.1.1.1.4.2 rmind } else
3190 1.1.1.1.4.2 rmind FREE((caddr_t)newusrp, M_NFSUSERGROUP);
3191 1.1.1.1.4.2 rmind NFSUNLOCKNAMEID();
3192 1.1.1.1.4.2 rmind out:
3193 1.1.1.1.4.2 rmind NFSEXITCODE(error);
3194 1.1.1.1.4.2 rmind return (error);
3195 1.1.1.1.4.2 rmind }
3196 1.1.1.1.4.2 rmind
3197 1.1.1.1.4.2 rmind /*
3198 1.1.1.1.4.2 rmind * Remove a user/group name element.
3199 1.1.1.1.4.2 rmind */
3200 1.1.1.1.4.2 rmind static void
3201 1.1.1.1.4.2 rmind nfsrv_removeuser(struct nfsusrgrp *usrp)
3202 1.1.1.1.4.2 rmind {
3203 1.1.1.1.4.2 rmind
3204 1.1.1.1.4.2 rmind NFSNAMEIDREQUIRED();
3205 1.1.1.1.4.2 rmind LIST_REMOVE(usrp, lug_numhash);
3206 1.1.1.1.4.2 rmind LIST_REMOVE(usrp, lug_namehash);
3207 1.1.1.1.4.2 rmind TAILQ_REMOVE(&nfsuserlruhead, usrp, lug_lru);
3208 1.1.1.1.4.2 rmind nfsrv_usercnt--;
3209 1.1.1.1.4.2 rmind FREE((caddr_t)usrp, M_NFSUSERGROUP);
3210 1.1.1.1.4.2 rmind }
3211 1.1.1.1.4.2 rmind
3212 1.1.1.1.4.2 rmind /*
3213 1.1.1.1.4.2 rmind * This function scans a byte string and checks for UTF-8 compliance.
3214 1.1.1.1.4.2 rmind * It returns 0 if it conforms and NFSERR_INVAL if not.
3215 1.1.1.1.4.2 rmind */
3216 1.1.1.1.4.2 rmind APPLESTATIC int
3217 1.1.1.1.4.2 rmind nfsrv_checkutf8(u_int8_t *cp, int len)
3218 1.1.1.1.4.2 rmind {
3219 1.1.1.1.4.2 rmind u_int32_t val = 0x0;
3220 1.1.1.1.4.2 rmind int cnt = 0, gotd = 0, shift = 0;
3221 1.1.1.1.4.2 rmind u_int8_t byte;
3222 1.1.1.1.4.2 rmind static int utf8_shift[5] = { 7, 11, 16, 21, 26 };
3223 1.1.1.1.4.2 rmind int error = 0;
3224 1.1.1.1.4.2 rmind
3225 1.1.1.1.4.2 rmind /*
3226 1.1.1.1.4.2 rmind * Here are what the variables are used for:
3227 1.1.1.1.4.2 rmind * val - the calculated value of a multibyte char, used to check
3228 1.1.1.1.4.2 rmind * that it was coded with the correct range
3229 1.1.1.1.4.2 rmind * cnt - the number of 10xxxxxx bytes to follow
3230 1.1.1.1.4.2 rmind * gotd - set for a char of Dxxx, so D800<->DFFF can be checked for
3231 1.1.1.1.4.2 rmind * shift - lower order bits of range (ie. "val >> shift" should
3232 1.1.1.1.4.2 rmind * not be 0, in other words, dividing by the lower bound
3233 1.1.1.1.4.2 rmind * of the range should get a non-zero value)
3234 1.1.1.1.4.2 rmind * byte - used to calculate cnt
3235 1.1.1.1.4.2 rmind */
3236 1.1.1.1.4.2 rmind while (len > 0) {
3237 1.1.1.1.4.2 rmind if (cnt > 0) {
3238 1.1.1.1.4.2 rmind /* This handles the 10xxxxxx bytes */
3239 1.1.1.1.4.2 rmind if ((*cp & 0xc0) != 0x80 ||
3240 1.1.1.1.4.2 rmind (gotd && (*cp & 0x20))) {
3241 1.1.1.1.4.2 rmind error = NFSERR_INVAL;
3242 1.1.1.1.4.2 rmind goto out;
3243 1.1.1.1.4.2 rmind }
3244 1.1.1.1.4.2 rmind gotd = 0;
3245 1.1.1.1.4.2 rmind val <<= 6;
3246 1.1.1.1.4.2 rmind val |= (*cp & 0x3f);
3247 1.1.1.1.4.2 rmind cnt--;
3248 1.1.1.1.4.2 rmind if (cnt == 0 && (val >> shift) == 0x0) {
3249 1.1.1.1.4.2 rmind error = NFSERR_INVAL;
3250 1.1.1.1.4.2 rmind goto out;
3251 1.1.1.1.4.2 rmind }
3252 1.1.1.1.4.2 rmind } else if (*cp & 0x80) {
3253 1.1.1.1.4.2 rmind /* first byte of multi byte char */
3254 1.1.1.1.4.2 rmind byte = *cp;
3255 1.1.1.1.4.2 rmind while ((byte & 0x40) && cnt < 6) {
3256 1.1.1.1.4.2 rmind cnt++;
3257 1.1.1.1.4.2 rmind byte <<= 1;
3258 1.1.1.1.4.2 rmind }
3259 1.1.1.1.4.2 rmind if (cnt == 0 || cnt == 6) {
3260 1.1.1.1.4.2 rmind error = NFSERR_INVAL;
3261 1.1.1.1.4.2 rmind goto out;
3262 1.1.1.1.4.2 rmind }
3263 1.1.1.1.4.2 rmind val = (*cp & (0x3f >> cnt));
3264 1.1.1.1.4.2 rmind shift = utf8_shift[cnt - 1];
3265 1.1.1.1.4.2 rmind if (cnt == 2 && val == 0xd)
3266 1.1.1.1.4.2 rmind /* Check for the 0xd800-0xdfff case */
3267 1.1.1.1.4.2 rmind gotd = 1;
3268 1.1.1.1.4.2 rmind }
3269 1.1.1.1.4.2 rmind cp++;
3270 1.1.1.1.4.2 rmind len--;
3271 1.1.1.1.4.2 rmind }
3272 1.1.1.1.4.2 rmind if (cnt > 0)
3273 1.1.1.1.4.2 rmind error = NFSERR_INVAL;
3274 1.1.1.1.4.2 rmind
3275 1.1.1.1.4.2 rmind out:
3276 1.1.1.1.4.2 rmind NFSEXITCODE(error);
3277 1.1.1.1.4.2 rmind return (error);
3278 1.1.1.1.4.2 rmind }
3279 1.1.1.1.4.2 rmind
3280 1.1.1.1.4.2 rmind /*
3281 1.1.1.1.4.2 rmind * Parse the xdr for an NFSv4 FsLocations attribute. Return two malloc'd
3282 1.1.1.1.4.2 rmind * strings, one with the root path in it and the other with the list of
3283 1.1.1.1.4.2 rmind * locations. The list is in the same format as is found in nfr_refs.
3284 1.1.1.1.4.2 rmind * It is a "," separated list of entries, where each of them is of the
3285 1.1.1.1.4.2 rmind * form <server>:<rootpath>. For example
3286 1.1.1.1.4.2 rmind * "nfsv4-test:/sub2,nfsv4-test2:/user/mnt,nfsv4-test2:/user/mnt2"
3287 1.1.1.1.4.2 rmind * The nilp argument is set to 1 for the special case of a null fs_root
3288 1.1.1.1.4.2 rmind * and an empty server list.
3289 1.1.1.1.4.2 rmind * It returns NFSERR_BADXDR, if the xdr can't be parsed and returns the
3290 1.1.1.1.4.2 rmind * number of xdr bytes parsed in sump.
3291 1.1.1.1.4.2 rmind */
3292 1.1.1.1.4.2 rmind static int
3293 1.1.1.1.4.2 rmind nfsrv_getrefstr(struct nfsrv_descript *nd, u_char **fsrootp, u_char **srvp,
3294 1.1.1.1.4.2 rmind int *sump, int *nilp)
3295 1.1.1.1.4.2 rmind {
3296 1.1.1.1.4.2 rmind u_int32_t *tl;
3297 1.1.1.1.4.2 rmind u_char *cp = NULL, *cp2 = NULL, *cp3, *str;
3298 1.1.1.1.4.2 rmind int i, j, len, stringlen, cnt, slen, siz, xdrsum, error = 0, nsrv;
3299 1.1.1.1.4.2 rmind struct list {
3300 1.1.1.1.4.2 rmind SLIST_ENTRY(list) next;
3301 1.1.1.1.4.2 rmind int len;
3302 1.1.1.1.4.2 rmind u_char host[1];
3303 1.1.1.1.4.2 rmind } *lsp, *nlsp;
3304 1.1.1.1.4.2 rmind SLIST_HEAD(, list) head;
3305 1.1.1.1.4.2 rmind
3306 1.1.1.1.4.2 rmind *fsrootp = NULL;
3307 1.1.1.1.4.2 rmind *srvp = NULL;
3308 1.1.1.1.4.2 rmind *nilp = 0;
3309 1.1.1.1.4.2 rmind
3310 1.1.1.1.4.2 rmind /*
3311 1.1.1.1.4.2 rmind * Get the fs_root path and check for the special case of null path
3312 1.1.1.1.4.2 rmind * and 0 length server list.
3313 1.1.1.1.4.2 rmind */
3314 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3315 1.1.1.1.4.2 rmind len = fxdr_unsigned(int, *tl);
3316 1.1.1.1.4.2 rmind if (len < 0 || len > 10240) {
3317 1.1.1.1.4.2 rmind error = NFSERR_BADXDR;
3318 1.1.1.1.4.2 rmind goto nfsmout;
3319 1.1.1.1.4.2 rmind }
3320 1.1.1.1.4.2 rmind if (len == 0) {
3321 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3322 1.1.1.1.4.2 rmind if (*tl != 0) {
3323 1.1.1.1.4.2 rmind error = NFSERR_BADXDR;
3324 1.1.1.1.4.2 rmind goto nfsmout;
3325 1.1.1.1.4.2 rmind }
3326 1.1.1.1.4.2 rmind *nilp = 1;
3327 1.1.1.1.4.2 rmind *sump = 2 * NFSX_UNSIGNED;
3328 1.1.1.1.4.2 rmind error = 0;
3329 1.1.1.1.4.2 rmind goto nfsmout;
3330 1.1.1.1.4.2 rmind }
3331 1.1.1.1.4.2 rmind cp = malloc(len + 1, M_NFSSTRING, M_WAITOK);
3332 1.1.1.1.4.2 rmind error = nfsrv_mtostr(nd, cp, len);
3333 1.1.1.1.4.2 rmind if (!error) {
3334 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3335 1.1.1.1.4.2 rmind cnt = fxdr_unsigned(int, *tl);
3336 1.1.1.1.4.2 rmind if (cnt <= 0)
3337 1.1.1.1.4.2 rmind error = NFSERR_BADXDR;
3338 1.1.1.1.4.2 rmind }
3339 1.1.1.1.4.2 rmind if (error)
3340 1.1.1.1.4.2 rmind goto nfsmout;
3341 1.1.1.1.4.2 rmind
3342 1.1.1.1.4.2 rmind /*
3343 1.1.1.1.4.2 rmind * Now, loop through the location list and make up the srvlist.
3344 1.1.1.1.4.2 rmind */
3345 1.1.1.1.4.2 rmind xdrsum = (2 * NFSX_UNSIGNED) + NFSM_RNDUP(len);
3346 1.1.1.1.4.2 rmind cp2 = cp3 = malloc(1024, M_NFSSTRING, M_WAITOK);
3347 1.1.1.1.4.2 rmind slen = 1024;
3348 1.1.1.1.4.2 rmind siz = 0;
3349 1.1.1.1.4.2 rmind for (i = 0; i < cnt; i++) {
3350 1.1.1.1.4.2 rmind SLIST_INIT(&head);
3351 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3352 1.1.1.1.4.2 rmind nsrv = fxdr_unsigned(int, *tl);
3353 1.1.1.1.4.2 rmind if (nsrv <= 0) {
3354 1.1.1.1.4.2 rmind error = NFSERR_BADXDR;
3355 1.1.1.1.4.2 rmind goto nfsmout;
3356 1.1.1.1.4.2 rmind }
3357 1.1.1.1.4.2 rmind
3358 1.1.1.1.4.2 rmind /*
3359 1.1.1.1.4.2 rmind * Handle the first server by putting it in the srvstr.
3360 1.1.1.1.4.2 rmind */
3361 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3362 1.1.1.1.4.2 rmind len = fxdr_unsigned(int, *tl);
3363 1.1.1.1.4.2 rmind if (len <= 0 || len > 1024) {
3364 1.1.1.1.4.2 rmind error = NFSERR_BADXDR;
3365 1.1.1.1.4.2 rmind goto nfsmout;
3366 1.1.1.1.4.2 rmind }
3367 1.1.1.1.4.2 rmind nfsrv_refstrbigenough(siz + len + 3, &cp2, &cp3, &slen);
3368 1.1.1.1.4.2 rmind if (cp3 != cp2) {
3369 1.1.1.1.4.2 rmind *cp3++ = ',';
3370 1.1.1.1.4.2 rmind siz++;
3371 1.1.1.1.4.2 rmind }
3372 1.1.1.1.4.2 rmind error = nfsrv_mtostr(nd, cp3, len);
3373 1.1.1.1.4.2 rmind if (error)
3374 1.1.1.1.4.2 rmind goto nfsmout;
3375 1.1.1.1.4.2 rmind cp3 += len;
3376 1.1.1.1.4.2 rmind *cp3++ = ':';
3377 1.1.1.1.4.2 rmind siz += (len + 1);
3378 1.1.1.1.4.2 rmind xdrsum += (2 * NFSX_UNSIGNED) + NFSM_RNDUP(len);
3379 1.1.1.1.4.2 rmind for (j = 1; j < nsrv; j++) {
3380 1.1.1.1.4.2 rmind /*
3381 1.1.1.1.4.2 rmind * Yuck, put them in an slist and process them later.
3382 1.1.1.1.4.2 rmind */
3383 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3384 1.1.1.1.4.2 rmind len = fxdr_unsigned(int, *tl);
3385 1.1.1.1.4.2 rmind if (len <= 0 || len > 1024) {
3386 1.1.1.1.4.2 rmind error = NFSERR_BADXDR;
3387 1.1.1.1.4.2 rmind goto nfsmout;
3388 1.1.1.1.4.2 rmind }
3389 1.1.1.1.4.2 rmind lsp = (struct list *)malloc(sizeof (struct list)
3390 1.1.1.1.4.2 rmind + len, M_TEMP, M_WAITOK);
3391 1.1.1.1.4.2 rmind error = nfsrv_mtostr(nd, lsp->host, len);
3392 1.1.1.1.4.2 rmind if (error)
3393 1.1.1.1.4.2 rmind goto nfsmout;
3394 1.1.1.1.4.2 rmind xdrsum += NFSX_UNSIGNED + NFSM_RNDUP(len);
3395 1.1.1.1.4.2 rmind lsp->len = len;
3396 1.1.1.1.4.2 rmind SLIST_INSERT_HEAD(&head, lsp, next);
3397 1.1.1.1.4.2 rmind }
3398 1.1.1.1.4.2 rmind
3399 1.1.1.1.4.2 rmind /*
3400 1.1.1.1.4.2 rmind * Finally, we can get the path.
3401 1.1.1.1.4.2 rmind */
3402 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3403 1.1.1.1.4.2 rmind len = fxdr_unsigned(int, *tl);
3404 1.1.1.1.4.2 rmind if (len <= 0 || len > 1024) {
3405 1.1.1.1.4.2 rmind error = NFSERR_BADXDR;
3406 1.1.1.1.4.2 rmind goto nfsmout;
3407 1.1.1.1.4.2 rmind }
3408 1.1.1.1.4.2 rmind nfsrv_refstrbigenough(siz + len + 1, &cp2, &cp3, &slen);
3409 1.1.1.1.4.2 rmind error = nfsrv_mtostr(nd, cp3, len);
3410 1.1.1.1.4.2 rmind if (error)
3411 1.1.1.1.4.2 rmind goto nfsmout;
3412 1.1.1.1.4.2 rmind xdrsum += NFSX_UNSIGNED + NFSM_RNDUP(len);
3413 1.1.1.1.4.2 rmind str = cp3;
3414 1.1.1.1.4.2 rmind stringlen = len;
3415 1.1.1.1.4.2 rmind cp3 += len;
3416 1.1.1.1.4.2 rmind siz += len;
3417 1.1.1.1.4.2 rmind SLIST_FOREACH_SAFE(lsp, &head, next, nlsp) {
3418 1.1.1.1.4.2 rmind nfsrv_refstrbigenough(siz + lsp->len + stringlen + 3,
3419 1.1.1.1.4.2 rmind &cp2, &cp3, &slen);
3420 1.1.1.1.4.2 rmind *cp3++ = ',';
3421 1.1.1.1.4.2 rmind NFSBCOPY(lsp->host, cp3, lsp->len);
3422 1.1.1.1.4.2 rmind cp3 += lsp->len;
3423 1.1.1.1.4.2 rmind *cp3++ = ':';
3424 1.1.1.1.4.2 rmind NFSBCOPY(str, cp3, stringlen);
3425 1.1.1.1.4.2 rmind cp3 += stringlen;
3426 1.1.1.1.4.2 rmind *cp3 = '\0';
3427 1.1.1.1.4.2 rmind siz += (lsp->len + stringlen + 2);
3428 1.1.1.1.4.2 rmind free((caddr_t)lsp, M_TEMP);
3429 1.1.1.1.4.2 rmind }
3430 1.1.1.1.4.2 rmind }
3431 1.1.1.1.4.2 rmind *fsrootp = cp;
3432 1.1.1.1.4.2 rmind *srvp = cp2;
3433 1.1.1.1.4.2 rmind *sump = xdrsum;
3434 1.1.1.1.4.2 rmind NFSEXITCODE2(0, nd);
3435 1.1.1.1.4.2 rmind return (0);
3436 1.1.1.1.4.2 rmind nfsmout:
3437 1.1.1.1.4.2 rmind if (cp != NULL)
3438 1.1.1.1.4.2 rmind free(cp, M_NFSSTRING);
3439 1.1.1.1.4.2 rmind if (cp2 != NULL)
3440 1.1.1.1.4.2 rmind free(cp2, M_NFSSTRING);
3441 1.1.1.1.4.2 rmind NFSEXITCODE2(error, nd);
3442 1.1.1.1.4.2 rmind return (error);
3443 1.1.1.1.4.2 rmind }
3444 1.1.1.1.4.2 rmind
3445 1.1.1.1.4.2 rmind /*
3446 1.1.1.1.4.2 rmind * Make the malloc'd space large enough. This is a pain, but the xdr
3447 1.1.1.1.4.2 rmind * doesn't set an upper bound on the side, so...
3448 1.1.1.1.4.2 rmind */
3449 1.1.1.1.4.2 rmind static void
3450 1.1.1.1.4.2 rmind nfsrv_refstrbigenough(int siz, u_char **cpp, u_char **cpp2, int *slenp)
3451 1.1.1.1.4.2 rmind {
3452 1.1.1.1.4.2 rmind u_char *cp;
3453 1.1.1.1.4.2 rmind int i;
3454 1.1.1.1.4.2 rmind
3455 1.1.1.1.4.2 rmind if (siz <= *slenp)
3456 1.1.1.1.4.2 rmind return;
3457 1.1.1.1.4.2 rmind cp = malloc(siz + 1024, M_NFSSTRING, M_WAITOK);
3458 1.1.1.1.4.2 rmind NFSBCOPY(*cpp, cp, *slenp);
3459 1.1.1.1.4.2 rmind free(*cpp, M_NFSSTRING);
3460 1.1.1.1.4.2 rmind i = *cpp2 - *cpp;
3461 1.1.1.1.4.2 rmind *cpp = cp;
3462 1.1.1.1.4.2 rmind *cpp2 = cp + i;
3463 1.1.1.1.4.2 rmind *slenp = siz + 1024;
3464 1.1.1.1.4.2 rmind }
3465 1.1.1.1.4.2 rmind
3466 1.1.1.1.4.2 rmind /*
3467 1.1.1.1.4.2 rmind * Initialize the reply header data structures.
3468 1.1.1.1.4.2 rmind */
3469 1.1.1.1.4.2 rmind APPLESTATIC void
3470 1.1.1.1.4.2 rmind nfsrvd_rephead(struct nfsrv_descript *nd)
3471 1.1.1.1.4.2 rmind {
3472 1.1.1.1.4.2 rmind mbuf_t mreq;
3473 1.1.1.1.4.2 rmind
3474 1.1.1.1.4.2 rmind /*
3475 1.1.1.1.4.2 rmind * If this is a big reply, use a cluster.
3476 1.1.1.1.4.2 rmind */
3477 1.1.1.1.4.2 rmind if ((nd->nd_flag & ND_GSSINITREPLY) == 0 &&
3478 1.1.1.1.4.2 rmind nfs_bigreply[nd->nd_procnum]) {
3479 1.1.1.1.4.2 rmind NFSMCLGET(mreq, M_WAITOK);
3480 1.1.1.1.4.2 rmind nd->nd_mreq = mreq;
3481 1.1.1.1.4.2 rmind nd->nd_mb = mreq;
3482 1.1.1.1.4.2 rmind } else {
3483 1.1.1.1.4.2 rmind NFSMGET(mreq);
3484 1.1.1.1.4.2 rmind nd->nd_mreq = mreq;
3485 1.1.1.1.4.2 rmind nd->nd_mb = mreq;
3486 1.1.1.1.4.2 rmind }
3487 1.1.1.1.4.2 rmind nd->nd_bpos = NFSMTOD(mreq, caddr_t);
3488 1.1.1.1.4.2 rmind mbuf_setlen(mreq, 0);
3489 1.1.1.1.4.2 rmind
3490 1.1.1.1.4.2 rmind if ((nd->nd_flag & ND_GSSINITREPLY) == 0)
3491 1.1.1.1.4.2 rmind NFSM_BUILD(nd->nd_errp, int *, NFSX_UNSIGNED);
3492 1.1.1.1.4.2 rmind }
3493 1.1.1.1.4.2 rmind
3494 1.1.1.1.4.2 rmind /*
3495 1.1.1.1.4.2 rmind * Lock a socket against others.
3496 1.1.1.1.4.2 rmind * Currently used to serialize connect/disconnect attempts.
3497 1.1.1.1.4.2 rmind */
3498 1.1.1.1.4.2 rmind int
3499 1.1.1.1.4.2 rmind newnfs_sndlock(int *flagp)
3500 1.1.1.1.4.2 rmind {
3501 1.1.1.1.4.2 rmind struct timespec ts;
3502 1.1.1.1.4.2 rmind
3503 1.1.1.1.4.2 rmind NFSLOCKSOCK();
3504 1.1.1.1.4.2 rmind while (*flagp & NFSR_SNDLOCK) {
3505 1.1.1.1.4.2 rmind *flagp |= NFSR_WANTSND;
3506 1.1.1.1.4.2 rmind ts.tv_sec = 0;
3507 1.1.1.1.4.2 rmind ts.tv_nsec = 0;
3508 1.1.1.1.4.2 rmind (void) nfsmsleep((caddr_t)flagp, NFSSOCKMUTEXPTR,
3509 1.1.1.1.4.2 rmind PZERO - 1, "nfsndlck", &ts);
3510 1.1.1.1.4.2 rmind }
3511 1.1.1.1.4.2 rmind *flagp |= NFSR_SNDLOCK;
3512 1.1.1.1.4.2 rmind NFSUNLOCKSOCK();
3513 1.1.1.1.4.2 rmind return (0);
3514 1.1.1.1.4.2 rmind }
3515 1.1.1.1.4.2 rmind
3516 1.1.1.1.4.2 rmind /*
3517 1.1.1.1.4.2 rmind * Unlock the stream socket for others.
3518 1.1.1.1.4.2 rmind */
3519 1.1.1.1.4.2 rmind void
3520 1.1.1.1.4.2 rmind newnfs_sndunlock(int *flagp)
3521 1.1.1.1.4.2 rmind {
3522 1.1.1.1.4.2 rmind
3523 1.1.1.1.4.2 rmind NFSLOCKSOCK();
3524 1.1.1.1.4.2 rmind if ((*flagp & NFSR_SNDLOCK) == 0)
3525 1.1.1.1.4.2 rmind panic("nfs sndunlock");
3526 1.1.1.1.4.2 rmind *flagp &= ~NFSR_SNDLOCK;
3527 1.1.1.1.4.2 rmind if (*flagp & NFSR_WANTSND) {
3528 1.1.1.1.4.2 rmind *flagp &= ~NFSR_WANTSND;
3529 1.1.1.1.4.2 rmind wakeup((caddr_t)flagp);
3530 1.1.1.1.4.2 rmind }
3531 1.1.1.1.4.2 rmind NFSUNLOCKSOCK();
3532 1.1.1.1.4.2 rmind }
3533 1.1.1.1.4.2 rmind
3534 1.1.1.1.4.2 rmind APPLESTATIC int
3535 1.1.1.1.4.2 rmind nfsv4_getipaddr(struct nfsrv_descript *nd, struct sockaddr_storage *sa,
3536 1.1.1.1.4.2 rmind int *isudp)
3537 1.1.1.1.4.2 rmind {
3538 1.1.1.1.4.2 rmind struct sockaddr_in *sad;
3539 1.1.1.1.4.2 rmind struct sockaddr_in6 *sad6;
3540 1.1.1.1.4.2 rmind struct in_addr saddr;
3541 1.1.1.1.4.2 rmind uint32_t portnum, *tl;
3542 1.1.1.1.4.2 rmind int af = 0, i, j, k;
3543 1.1.1.1.4.2 rmind char addr[64], protocol[5], *cp;
3544 1.1.1.1.4.2 rmind int cantparse = 0, error = 0;
3545 1.1.1.1.4.2 rmind uint16_t portv;
3546 1.1.1.1.4.2 rmind
3547 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3548 1.1.1.1.4.2 rmind i = fxdr_unsigned(int, *tl);
3549 1.1.1.1.4.2 rmind if (i >= 3 && i <= 4) {
3550 1.1.1.1.4.2 rmind error = nfsrv_mtostr(nd, protocol, i);
3551 1.1.1.1.4.2 rmind if (error)
3552 1.1.1.1.4.2 rmind goto nfsmout;
3553 1.1.1.1.4.2 rmind if (strcmp(protocol, "tcp") == 0) {
3554 1.1.1.1.4.2 rmind af = AF_INET;
3555 1.1.1.1.4.2 rmind *isudp = 0;
3556 1.1.1.1.4.2 rmind } else if (strcmp(protocol, "udp") == 0) {
3557 1.1.1.1.4.2 rmind af = AF_INET;
3558 1.1.1.1.4.2 rmind *isudp = 1;
3559 1.1.1.1.4.2 rmind } else if (strcmp(protocol, "tcp6") == 0) {
3560 1.1.1.1.4.2 rmind af = AF_INET6;
3561 1.1.1.1.4.2 rmind *isudp = 0;
3562 1.1.1.1.4.2 rmind } else if (strcmp(protocol, "udp6") == 0) {
3563 1.1.1.1.4.2 rmind af = AF_INET6;
3564 1.1.1.1.4.2 rmind *isudp = 1;
3565 1.1.1.1.4.2 rmind } else
3566 1.1.1.1.4.2 rmind cantparse = 1;
3567 1.1.1.1.4.2 rmind } else {
3568 1.1.1.1.4.2 rmind cantparse = 1;
3569 1.1.1.1.4.2 rmind if (i > 0) {
3570 1.1.1.1.4.2 rmind error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
3571 1.1.1.1.4.2 rmind if (error)
3572 1.1.1.1.4.2 rmind goto nfsmout;
3573 1.1.1.1.4.2 rmind }
3574 1.1.1.1.4.2 rmind }
3575 1.1.1.1.4.2 rmind NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3576 1.1.1.1.4.2 rmind i = fxdr_unsigned(int, *tl);
3577 1.1.1.1.4.2 rmind if (i < 0) {
3578 1.1.1.1.4.2 rmind error = NFSERR_BADXDR;
3579 1.1.1.1.4.2 rmind goto nfsmout;
3580 1.1.1.1.4.2 rmind } else if (cantparse == 0 && i >= 11 && i < 64) {
3581 1.1.1.1.4.2 rmind /*
3582 1.1.1.1.4.2 rmind * The shortest address is 11chars and the longest is < 64.
3583 1.1.1.1.4.2 rmind */
3584 1.1.1.1.4.2 rmind error = nfsrv_mtostr(nd, addr, i);
3585 1.1.1.1.4.2 rmind if (error)
3586 1.1.1.1.4.2 rmind goto nfsmout;
3587 1.1.1.1.4.2 rmind
3588 1.1.1.1.4.2 rmind /* Find the port# at the end and extract that. */
3589 1.1.1.1.4.2 rmind i = strlen(addr);
3590 1.1.1.1.4.2 rmind k = 0;
3591 1.1.1.1.4.2 rmind cp = &addr[i - 1];
3592 1.1.1.1.4.2 rmind /* Count back two '.'s from end to get port# field. */
3593 1.1.1.1.4.2 rmind for (j = 0; j < i; j++) {
3594 1.1.1.1.4.2 rmind if (*cp == '.') {
3595 1.1.1.1.4.2 rmind k++;
3596 1.1.1.1.4.2 rmind if (k == 2)
3597 1.1.1.1.4.2 rmind break;
3598 1.1.1.1.4.2 rmind }
3599 1.1.1.1.4.2 rmind cp--;
3600 1.1.1.1.4.2 rmind }
3601 1.1.1.1.4.2 rmind if (k == 2) {
3602 1.1.1.1.4.2 rmind /*
3603 1.1.1.1.4.2 rmind * The NFSv4 port# is appended as .N.N, where N is
3604 1.1.1.1.4.2 rmind * a decimal # in the range 0-255, just like an inet4
3605 1.1.1.1.4.2 rmind * address. Cheat and use inet_aton(), which will
3606 1.1.1.1.4.2 rmind * return a Class A address and then shift the high
3607 1.1.1.1.4.2 rmind * order 8bits over to convert it to the port#.
3608 1.1.1.1.4.2 rmind */
3609 1.1.1.1.4.2 rmind *cp++ = '\0';
3610 1.1.1.1.4.2 rmind if (inet_aton(cp, &saddr) == 1) {
3611 1.1.1.1.4.2 rmind portnum = ntohl(saddr.s_addr);
3612 1.1.1.1.4.2 rmind portv = (uint16_t)((portnum >> 16) |
3613 1.1.1.1.4.2 rmind (portnum & 0xff));
3614 1.1.1.1.4.2 rmind } else
3615 1.1.1.1.4.2 rmind cantparse = 1;
3616 1.1.1.1.4.2 rmind } else
3617 1.1.1.1.4.2 rmind cantparse = 1;
3618 1.1.1.1.4.2 rmind if (cantparse == 0) {
3619 1.1.1.1.4.2 rmind if (af == AF_INET) {
3620 1.1.1.1.4.2 rmind sad = (struct sockaddr_in *)sa;
3621 1.1.1.1.4.2 rmind if (inet_pton(af, addr, &sad->sin_addr) == 1) {
3622 1.1.1.1.4.2 rmind sad->sin_len = sizeof(*sad);
3623 1.1.1.1.4.2 rmind sad->sin_family = AF_INET;
3624 1.1.1.1.4.2 rmind sad->sin_port = htons(portv);
3625 1.1.1.1.4.2 rmind return (0);
3626 1.1.1.1.4.2 rmind }
3627 1.1.1.1.4.2 rmind } else {
3628 1.1.1.1.4.2 rmind sad6 = (struct sockaddr_in6 *)sa;
3629 1.1.1.1.4.2 rmind if (inet_pton(af, addr, &sad6->sin6_addr)
3630 1.1.1.1.4.2 rmind == 1) {
3631 1.1.1.1.4.2 rmind sad6->sin6_len = sizeof(*sad6);
3632 1.1.1.1.4.2 rmind sad6->sin6_family = AF_INET6;
3633 1.1.1.1.4.2 rmind sad6->sin6_port = htons(portv);
3634 1.1.1.1.4.2 rmind return (0);
3635 1.1.1.1.4.2 rmind }
3636 1.1.1.1.4.2 rmind }
3637 1.1.1.1.4.2 rmind }
3638 1.1.1.1.4.2 rmind } else {
3639 1.1.1.1.4.2 rmind if (i > 0) {
3640 1.1.1.1.4.2 rmind error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
3641 1.1.1.1.4.2 rmind if (error)
3642 1.1.1.1.4.2 rmind goto nfsmout;
3643 1.1.1.1.4.2 rmind }
3644 1.1.1.1.4.2 rmind }
3645 1.1.1.1.4.2 rmind error = EPERM;
3646 1.1.1.1.4.2 rmind nfsmout:
3647 1.1.1.1.4.2 rmind return (error);
3648 1.1.1.1.4.2 rmind }
3649 1.1.1.1.4.2 rmind
3650 1.1.1.1.4.2 rmind /*
3651 1.1.1.1.4.2 rmind * Handle an NFSv4.1 Sequence request for the session.
3652 1.1.1.1.4.2 rmind */
3653 1.1.1.1.4.2 rmind int
3654 1.1.1.1.4.2 rmind nfsv4_seqsession(uint32_t seqid, uint32_t slotid, uint32_t highslot,
3655 1.1.1.1.4.2 rmind struct nfsslot *slots, struct mbuf **reply, uint16_t maxslot)
3656 1.1.1.1.4.2 rmind {
3657 1.1.1.1.4.2 rmind int error;
3658 1.1.1.1.4.2 rmind
3659 1.1.1.1.4.2 rmind error = 0;
3660 1.1.1.1.4.2 rmind *reply = NULL;
3661 1.1.1.1.4.2 rmind if (slotid > maxslot)
3662 1.1.1.1.4.2 rmind return (NFSERR_BADSLOT);
3663 1.1.1.1.4.2 rmind if (seqid == slots[slotid].nfssl_seq) {
3664 1.1.1.1.4.2 rmind /* A retry. */
3665 1.1.1.1.4.2 rmind if (slots[slotid].nfssl_inprog != 0)
3666 1.1.1.1.4.2 rmind error = NFSERR_DELAY;
3667 1.1.1.1.4.2 rmind else if (slots[slotid].nfssl_reply != NULL) {
3668 1.1.1.1.4.2 rmind *reply = slots[slotid].nfssl_reply;
3669 1.1.1.1.4.2 rmind slots[slotid].nfssl_reply = NULL;
3670 1.1.1.1.4.2 rmind slots[slotid].nfssl_inprog = 1;
3671 1.1.1.1.4.2 rmind } else
3672 1.1.1.1.4.2 rmind error = NFSERR_SEQMISORDERED;
3673 1.1.1.1.4.2 rmind } else if ((slots[slotid].nfssl_seq + 1) == seqid) {
3674 1.1.1.1.4.2 rmind m_freem(slots[slotid].nfssl_reply);
3675 1.1.1.1.4.2 rmind slots[slotid].nfssl_reply = NULL;
3676 1.1.1.1.4.2 rmind slots[slotid].nfssl_inprog = 1;
3677 1.1.1.1.4.2 rmind slots[slotid].nfssl_seq++;
3678 1.1.1.1.4.2 rmind } else
3679 1.1.1.1.4.2 rmind error = NFSERR_SEQMISORDERED;
3680 1.1.1.1.4.2 rmind return (error);
3681 1.1.1.1.4.2 rmind }
3682 1.1.1.1.4.2 rmind
3683 1.1.1.1.4.2 rmind /*
3684 1.1.1.1.4.2 rmind * Cache this reply for the slot.
3685 1.1.1.1.4.2 rmind */
3686 1.1.1.1.4.2 rmind void
3687 1.1.1.1.4.2 rmind nfsv4_seqsess_cacherep(uint32_t slotid, struct nfsslot *slots, struct mbuf *rep)
3688 1.1.1.1.4.2 rmind {
3689 1.1.1.1.4.2 rmind
3690 1.1.1.1.4.2 rmind slots[slotid].nfssl_reply = rep;
3691 1.1.1.1.4.2 rmind slots[slotid].nfssl_inprog = 0;
3692 1.1.1.1.4.2 rmind }
3693 1.1.1.1.4.2 rmind
3694 1.1.1.1.4.2 rmind /*
3695 1.1.1.1.4.2 rmind * Generate the xdr for an NFSv4.1 Sequence Operation.
3696 1.1.1.1.4.2 rmind */
3697 1.1.1.1.4.2 rmind APPLESTATIC void
3698 1.1.1.1.4.2 rmind nfsv4_setsequence(struct nfsrv_descript *nd, struct nfsclsession *sep,
3699 1.1.1.1.4.2 rmind int dont_replycache)
3700 1.1.1.1.4.2 rmind {
3701 1.1.1.1.4.2 rmind uint32_t *tl, slotseq = 0;
3702 1.1.1.1.4.2 rmind int i, maxslot, slotpos;
3703 1.1.1.1.4.2 rmind uint64_t bitval;
3704 1.1.1.1.4.2 rmind uint8_t sessionid[NFSX_V4SESSIONID];
3705 1.1.1.1.4.2 rmind
3706 1.1.1.1.4.2 rmind /* Find an unused slot. */
3707 1.1.1.1.4.2 rmind slotpos = -1;
3708 1.1.1.1.4.2 rmind maxslot = -1;
3709 1.1.1.1.4.2 rmind mtx_lock(&sep->nfsess_mtx);
3710 1.1.1.1.4.2 rmind do {
3711 1.1.1.1.4.2 rmind bitval = 1;
3712 1.1.1.1.4.2 rmind for (i = 0; i < sep->nfsess_foreslots; i++) {
3713 1.1.1.1.4.2 rmind if ((bitval & sep->nfsess_slots) == 0) {
3714 1.1.1.1.4.2 rmind slotpos = i;
3715 1.1.1.1.4.2 rmind sep->nfsess_slots |= bitval;
3716 1.1.1.1.4.2 rmind sep->nfsess_slotseq[i]++;
3717 1.1.1.1.4.2 rmind slotseq = sep->nfsess_slotseq[i];
3718 1.1.1.1.4.2 rmind break;
3719 1.1.1.1.4.2 rmind }
3720 1.1.1.1.4.2 rmind bitval <<= 1;
3721 1.1.1.1.4.2 rmind }
3722 1.1.1.1.4.2 rmind if (slotpos == -1)
3723 1.1.1.1.4.2 rmind (void)mtx_sleep(&sep->nfsess_slots, &sep->nfsess_mtx,
3724 1.1.1.1.4.2 rmind PZERO, "nfsclseq", 0);
3725 1.1.1.1.4.2 rmind } while (slotpos == -1);
3726 1.1.1.1.4.2 rmind /* Now, find the highest slot in use. (nfsc_slots is 64bits) */
3727 1.1.1.1.4.2 rmind bitval = 1;
3728 1.1.1.1.4.2 rmind for (i = 0; i < 64; i++) {
3729 1.1.1.1.4.2 rmind if ((bitval & sep->nfsess_slots) != 0)
3730 1.1.1.1.4.2 rmind maxslot = i;
3731 1.1.1.1.4.2 rmind bitval <<= 1;
3732 1.1.1.1.4.2 rmind }
3733 1.1.1.1.4.2 rmind bcopy(sep->nfsess_sessionid, sessionid, NFSX_V4SESSIONID);
3734 1.1.1.1.4.2 rmind mtx_unlock(&sep->nfsess_mtx);
3735 1.1.1.1.4.2 rmind KASSERT(maxslot >= 0, ("nfscl_setsequence neg maxslot"));
3736 1.1.1.1.4.2 rmind
3737 1.1.1.1.4.2 rmind /* Build the Sequence arguments. */
3738 1.1.1.1.4.2 rmind NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 4 * NFSX_UNSIGNED);
3739 1.1.1.1.4.2 rmind bcopy(sessionid, tl, NFSX_V4SESSIONID);
3740 1.1.1.1.4.2 rmind tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
3741 1.1.1.1.4.2 rmind nd->nd_slotseq = tl;
3742 1.1.1.1.4.2 rmind *tl++ = txdr_unsigned(slotseq);
3743 1.1.1.1.4.2 rmind *tl++ = txdr_unsigned(slotpos);
3744 1.1.1.1.4.2 rmind *tl++ = txdr_unsigned(maxslot);
3745 1.1.1.1.4.2 rmind if (dont_replycache == 0)
3746 1.1.1.1.4.2 rmind *tl = newnfs_true;
3747 1.1.1.1.4.2 rmind else
3748 1.1.1.1.4.2 rmind *tl = newnfs_false;
3749 1.1.1.1.4.2 rmind nd->nd_flag |= ND_HASSEQUENCE;
3750 1.1.1.1.4.2 rmind }
3751 1.1.1.1.4.2 rmind
3752 1.1.1.1.4.2 rmind /*
3753 1.1.1.1.4.2 rmind * Free a session slot.
3754 1.1.1.1.4.2 rmind */
3755 1.1.1.1.4.2 rmind APPLESTATIC void
3756 1.1.1.1.4.2 rmind nfsv4_freeslot(struct nfsclsession *sep, int slot)
3757 1.1.1.1.4.2 rmind {
3758 1.1.1.1.4.2 rmind uint64_t bitval;
3759 1.1.1.1.4.2 rmind
3760 1.1.1.1.4.2 rmind bitval = 1;
3761 1.1.1.1.4.2 rmind if (slot > 0)
3762 1.1.1.1.4.2 rmind bitval <<= slot;
3763 1.1.1.1.4.2 rmind mtx_lock(&sep->nfsess_mtx);
3764 1.1.1.1.4.2 rmind if ((bitval & sep->nfsess_slots) == 0)
3765 1.1.1.1.4.2 rmind printf("freeing free slot!!\n");
3766 1.1.1.1.4.2 rmind sep->nfsess_slots &= ~bitval;
3767 1.1.1.1.4.2 rmind wakeup(&sep->nfsess_slots);
3768 1.1.1.1.4.2 rmind mtx_unlock(&sep->nfsess_mtx);
3769 1.1.1.1.4.2 rmind }
3770 1.1.1.1.4.2 rmind
3771