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