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