1 /*-
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rick Macklem at The University of Guelph.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 4. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  *	@(#)nfs_serv.c  8.8 (Berkeley) 7/31/95
33  */
34 
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD: stable/10/sys/nfsserver/nfs_serv.c 276500 2015-01-01 10:44:20Z kib $");
37 
38 /*
39  * nfs version 2 and 3 server calls to vnode ops
40  * - these routines generally have 3 phases
41  *   1 - break down and validate rpc request in mbuf list
42  *   2 - do the vnode ops for the request
43  *       (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
44  *   3 - build the rpc reply in an mbuf list
45  *   nb:
46  *	- do not mix the phases, since the nfsm_?? macros can return failures
47  *	  on a bad rpc or similar and do not do any vrele() or vput()'s
48  *
49  *      - the nfsm_reply() macro generates an nfs rpc reply with the nfs
50  *	error number iff error != 0 whereas
51  *	returning an error from the server function implies a fatal error
52  *	such as a badly constructed rpc request that should be dropped without
53  *	a reply.
54  *	For nfsm_reply(), the case where error == EBADRPC is treated
55  *	specially; after constructing a reply, it does an immediate
56  *	`goto nfsmout' to avoid getting any V3 post-op status appended.
57  *
58  * Other notes:
59  *	Warning: always pay careful attention to resource cleanup on return
60  *	and note that nfsm_*() macros can terminate a procedure on certain
61  *	errors.
62  *
63  *	lookup() and namei()
64  *	may return garbage in various structural fields/return elements
65  *	if an error is returned, and may garbage up nd.ni_dvp even if no
66  *	error is returned and you did not request LOCKPARENT or WANTPARENT.
67  *
68  *	We use the ni_cnd.cn_flags 'HASBUF' flag to track whether the name
69  *	buffer has been freed or not.
70  */
71 
72 #include <sys/param.h>
73 #include <sys/systm.h>
74 #include <sys/proc.h>
75 #include <sys/namei.h>
76 #include <sys/unistd.h>
77 #include <sys/vnode.h>
78 #include <sys/mount.h>
79 #include <sys/socket.h>
80 #include <sys/socketvar.h>
81 #include <sys/malloc.h>
82 #include <sys/mbuf.h>
83 #include <sys/priv.h>
84 #include <sys/dirent.h>
85 #include <sys/stat.h>
86 #include <sys/kernel.h>
87 #include <sys/sysctl.h>
88 #include <sys/bio.h>
89 #include <sys/buf.h>
90 #include <sys/rwlock.h>
91 
92 #include <vm/vm.h>
93 #include <vm/vm_extern.h>
94 #include <vm/vm_object.h>
95 
96 #include <nfs/nfsproto.h>
97 #include <nfsserver/nfs.h>
98 #include <nfs/xdr_subs.h>
99 #include <nfsserver/nfsm_subs.h>
100 
101 FEATURE(nfsserver, "NFS server");
102 
103 #ifdef NFSRV_DEBUG
104 #define nfsdbprintf(info)	printf info
105 #else
106 #define nfsdbprintf(info)
107 #endif
108 
109 #define MAX_COMMIT_COUNT	(1024 * 1024)
110 
111 #define	MAX_REORDERED_RPC	16
112 #define NUM_HEURISTIC		1031
113 #define NHUSE_INIT		64
114 #define NHUSE_INC		16
115 #define NHUSE_MAX		2048
116 
117 static struct nfsheur {
118 	struct vnode *nh_vp;	/* vp to match (unreferenced pointer) */
119 	off_t nh_nextoff;	/* next offset for sequential detection */
120 	int nh_use;		/* use count for selection */
121 	int nh_seqcount;	/* heuristic */
122 } nfsheur[NUM_HEURISTIC];
123 
124 /* Global vars */
125 
126 int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
127 int nfsrvw_procrastinate_v3 = 0;
128 
129 static struct timeval	nfsver = { 0 };
130 
131 SYSCTL_NODE(_vfs, OID_AUTO, nfsrv, CTLFLAG_RW, 0, "NFS server");
132 
133 static int nfs_async;
134 static int nfs_commit_blks;
135 static int nfs_commit_miss;
136 SYSCTL_INT(_vfs_nfsrv, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0,
137     "Tell client that writes were synced even though they were not");
138 SYSCTL_INT(_vfs_nfsrv, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 0,
139     "Number of completed commits");
140 SYSCTL_INT(_vfs_nfsrv, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, 0, "");
141 
142 struct nfsrvstats nfsrvstats;
143 SYSCTL_STRUCT(_vfs_nfsrv, NFS_NFSRVSTATS, nfsrvstats, CTLFLAG_RW,
144 	&nfsrvstats, nfsrvstats, "S,nfsrvstats");
145 
146 static int	nfsrv_access(struct vnode *, accmode_t, struct ucred *,
147 		    int, int);
148 
149 /*
150  * Clear nameidata fields that are tested in nsfmout cleanup code prior
151  * to using first nfsm macro (that might jump to the cleanup code).
152  */
153 
154 static __inline void
ndclear(struct nameidata * nd)155 ndclear(struct nameidata *nd)
156 {
157 
158 	nd->ni_cnd.cn_flags = 0;
159 	nd->ni_vp = NULL;
160 	nd->ni_dvp = NULL;
161 	nd->ni_startdir = NULL;
162 	nd->ni_strictrelative = 0;
163 }
164 
165 /*
166  * Heuristic to detect sequential operation.
167  */
168 static struct nfsheur *
nfsrv_sequential_heuristic(struct uio * uio,struct vnode * vp)169 nfsrv_sequential_heuristic(struct uio *uio, struct vnode *vp)
170 {
171 	struct nfsheur *nh;
172 	int hi, try;
173 
174 	/* Locate best candidate. */
175 	try = 32;
176 	hi = ((int)(vm_offset_t)vp / sizeof(struct vnode)) % NUM_HEURISTIC;
177 	nh = &nfsheur[hi];
178 	while (try--) {
179 		if (nfsheur[hi].nh_vp == vp) {
180 			nh = &nfsheur[hi];
181 			break;
182 		}
183 		if (nfsheur[hi].nh_use > 0)
184 			--nfsheur[hi].nh_use;
185 		hi = (hi + 1) % NUM_HEURISTIC;
186 		if (nfsheur[hi].nh_use < nh->nh_use)
187 			nh = &nfsheur[hi];
188 	}
189 
190 	/* Initialize hint if this is a new file. */
191 	if (nh->nh_vp != vp) {
192 		nh->nh_vp = vp;
193 		nh->nh_nextoff = uio->uio_offset;
194 		nh->nh_use = NHUSE_INIT;
195 		if (uio->uio_offset == 0)
196 			nh->nh_seqcount = 4;
197 		else
198 			nh->nh_seqcount = 1;
199 	}
200 
201 	/* Calculate heuristic. */
202 	if ((uio->uio_offset == 0 && nh->nh_seqcount > 0) ||
203 	    uio->uio_offset == nh->nh_nextoff) {
204 		/* See comments in vfs_vnops.c:sequential_heuristic(). */
205 		nh->nh_seqcount += howmany(uio->uio_resid, 16384);
206 		if (nh->nh_seqcount > IO_SEQMAX)
207 			nh->nh_seqcount = IO_SEQMAX;
208 	} else if (qabs(uio->uio_offset - nh->nh_nextoff) <= MAX_REORDERED_RPC *
209 	    imax(vp->v_mount->mnt_stat.f_iosize, uio->uio_resid)) {
210 		/* Probably a reordered RPC, leave seqcount alone. */
211 	} else if (nh->nh_seqcount > 1) {
212 		nh->nh_seqcount /= 2;
213 	} else {
214 		nh->nh_seqcount = 0;
215 	}
216 	nh->nh_use += NHUSE_INC;
217 	if (nh->nh_use > NHUSE_MAX)
218 		nh->nh_use = NHUSE_MAX;
219 	return (nh);
220 }
221 
222 /*
223  * nfs v3 access service
224  */
225 int
nfsrv3_access(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)226 nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
227     struct mbuf **mrq)
228 {
229 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
230 	struct sockaddr *nam = nfsd->nd_nam;
231 	caddr_t dpos = nfsd->nd_dpos;
232 	struct ucred *cred = nfsd->nd_cr;
233 	struct vnode *vp = NULL;
234 	nfsfh_t nfh;
235 	fhandle_t *fhp;
236 	u_int32_t *tl;
237 	caddr_t bpos;
238 	int error = 0, rdonly, getret;
239 	struct mbuf *mb, *mreq;
240 	struct vattr vattr, *vap = &vattr;
241 	u_long testmode, nfsmode;
242 	int v3 = (nfsd->nd_flag & ND_NFSV3);
243 
244 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
245 	if (!v3)
246 		panic("nfsrv3_access: v3 proc called on a v2 connection");
247 	fhp = &nfh.fh_generic;
248 	nfsm_srvmtofh(fhp);
249 	tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
250 	error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
251 	if (error) {
252 		nfsm_reply(NFSX_UNSIGNED);
253 		nfsm_srvpostop_attr(1, NULL);
254 		error = 0;
255 		goto nfsmout;
256 	}
257 	nfsmode = fxdr_unsigned(u_int32_t, *tl);
258 	if ((nfsmode & NFSV3ACCESS_READ) &&
259 		nfsrv_access(vp, VREAD, cred, rdonly, 0))
260 		nfsmode &= ~NFSV3ACCESS_READ;
261 	if (vp->v_type == VDIR)
262 		testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
263 			NFSV3ACCESS_DELETE);
264 	else
265 		testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
266 	if ((nfsmode & testmode) &&
267 		nfsrv_access(vp, VWRITE, cred, rdonly, 0))
268 		nfsmode &= ~testmode;
269 	if (vp->v_type == VDIR)
270 		testmode = NFSV3ACCESS_LOOKUP;
271 	else
272 		testmode = NFSV3ACCESS_EXECUTE;
273 	if ((nfsmode & testmode) &&
274 		nfsrv_access(vp, VEXEC, cred, rdonly, 0))
275 		nfsmode &= ~testmode;
276 	getret = VOP_GETATTR(vp, vap, cred);
277 	vput(vp);
278 	vp = NULL;
279 	nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
280 	nfsm_srvpostop_attr(getret, vap);
281 	tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
282 	*tl = txdr_unsigned(nfsmode);
283 nfsmout:
284 	if (vp)
285 		vput(vp);
286 	return(error);
287 }
288 
289 /*
290  * nfs getattr service
291  */
292 int
nfsrv_getattr(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)293 nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
294     struct mbuf **mrq)
295 {
296 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
297 	struct sockaddr *nam = nfsd->nd_nam;
298 	caddr_t dpos = nfsd->nd_dpos;
299 	struct ucred *cred = nfsd->nd_cr;
300 	struct nfs_fattr *fp;
301 	struct vattr va;
302 	struct vattr *vap = &va;
303 	struct vnode *vp = NULL;
304 	nfsfh_t nfh;
305 	fhandle_t *fhp;
306 	caddr_t bpos;
307 	int error = 0, rdonly;
308 	struct mbuf *mb, *mreq;
309 
310 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
311 	fhp = &nfh.fh_generic;
312 	nfsm_srvmtofh(fhp);
313 	error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
314 	if (error) {
315 		nfsm_reply(0);
316 		error = 0;
317 		goto nfsmout;
318 	}
319 	error = VOP_GETATTR(vp, vap, cred);
320 	vput(vp);
321 	vp = NULL;
322 	nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
323 	if (error) {
324 		error = 0;
325 		goto nfsmout;
326 	}
327 	fp = nfsm_build(struct nfs_fattr *,
328 	    NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
329 	nfsm_srvfillattr(vap, fp);
330 	/* fall through */
331 
332 nfsmout:
333 	if (vp)
334 		vput(vp);
335 	return(error);
336 }
337 
338 /*
339  * nfs setattr service
340  */
341 int
nfsrv_setattr(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)342 nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
343     struct mbuf **mrq)
344 {
345 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
346 	struct sockaddr *nam = nfsd->nd_nam;
347 	caddr_t dpos = nfsd->nd_dpos;
348 	struct ucred *cred = nfsd->nd_cr;
349 	struct vattr va, preat;
350 	struct vattr *vap = &va;
351 	struct nfsv2_sattr *sp;
352 	struct nfs_fattr *fp;
353 	struct vnode *vp = NULL;
354 	nfsfh_t nfh;
355 	fhandle_t *fhp;
356 	u_int32_t *tl;
357 	caddr_t bpos;
358 	int error = 0, rdonly, preat_ret = 1, postat_ret = 1;
359 	int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0;
360 	struct mbuf *mb, *mreq;
361 	struct timespec guard = { 0, 0 };
362 	struct mount *mp = NULL;
363 
364 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
365 	fhp = &nfh.fh_generic;
366 	nfsm_srvmtofh(fhp);
367 	if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
368 		error = ESTALE;
369 		goto out;
370 	}
371 	(void) vn_start_write(NULL, &mp, V_WAIT);
372 	vfs_rel(mp);		/* The write holds a ref. */
373 	VATTR_NULL(vap);
374 	if (v3) {
375 		nfsm_srvsattr(vap);
376 		tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
377 		gcheck = fxdr_unsigned(int, *tl);
378 		if (gcheck) {
379 			tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
380 			fxdr_nfsv3time(tl, &guard);
381 		}
382 	} else {
383 		sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
384 		/*
385 		 * Nah nah nah nah na nah
386 		 * There is a bug in the Sun client that puts 0xffff in the mode
387 		 * field of sattr when it should put in 0xffffffff. The u_short
388 		 * doesn't sign extend.
389 		 * --> check the low order 2 bytes for 0xffff
390 		 */
391 		if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
392 			vap->va_mode = nfstov_mode(sp->sa_mode);
393 		if (sp->sa_uid != nfsrv_nfs_xdrneg1)
394 			vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
395 		if (sp->sa_gid != nfsrv_nfs_xdrneg1)
396 			vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
397 		if (sp->sa_size != nfsrv_nfs_xdrneg1)
398 			vap->va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
399 		if (sp->sa_atime.nfsv2_sec != nfsrv_nfs_xdrneg1) {
400 #ifdef notyet
401 			fxdr_nfsv2time(&sp->sa_atime, &vap->va_atime);
402 #else
403 			vap->va_atime.tv_sec =
404 				fxdr_unsigned(int32_t, sp->sa_atime.nfsv2_sec);
405 			vap->va_atime.tv_nsec = 0;
406 #endif
407 		}
408 		if (sp->sa_mtime.nfsv2_sec != nfsrv_nfs_xdrneg1)
409 			fxdr_nfsv2time(&sp->sa_mtime, &vap->va_mtime);
410 
411 	}
412 
413 	/*
414 	 * Now that we have all the fields, lets do it.
415 	 */
416 	error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
417 	if (error) {
418 		nfsm_reply(2 * NFSX_UNSIGNED);
419 		if (v3)
420 			nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
421 		error = 0;
422 		goto nfsmout;
423 	}
424 
425 	/*
426 	 * vp now an active resource, pay careful attention to cleanup
427 	 */
428 	if (v3) {
429 		error = preat_ret = VOP_GETATTR(vp, &preat, cred);
430 		if (!error && gcheck &&
431 			(preat.va_ctime.tv_sec != guard.tv_sec ||
432 			 preat.va_ctime.tv_nsec != guard.tv_nsec))
433 			error = NFSERR_NOT_SYNC;
434 		if (error) {
435 			vput(vp);
436 			vp = NULL;
437 			nfsm_reply(NFSX_WCCDATA(v3));
438 			if (v3)
439 				nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
440 			error = 0;
441 			goto nfsmout;
442 		}
443 	}
444 
445 	/*
446 	 * If the size is being changed write acces is required, otherwise
447 	 * just check for a read only filesystem.
448 	 */
449 	if (vap->va_size == ((u_quad_t)((quad_t) -1))) {
450 		if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
451 			error = EROFS;
452 			goto out;
453 		}
454 	} else {
455 		if (vp->v_type == VDIR) {
456 			error = EISDIR;
457 			goto out;
458 		} else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
459 		    0)) != 0)
460 			goto out;
461 	}
462 	error = VOP_SETATTR(vp, vap, cred);
463 	postat_ret = VOP_GETATTR(vp, vap, cred);
464 	if (!error)
465 		error = postat_ret;
466 out:
467 	if (vp != NULL)
468 		vput(vp);
469 
470 	vp = NULL;
471 	nfsm_reply(NFSX_WCCORFATTR(v3));
472 	if (v3) {
473 		nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
474 	} else if (!error) {
475 		/* v2 non-error case. */
476 		fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
477 		nfsm_srvfillattr(vap, fp);
478 	}
479 	error = 0;
480 	/* fall through */
481 
482 nfsmout:
483 	if (vp)
484 		vput(vp);
485 	vn_finished_write(mp);
486 	return(error);
487 }
488 
489 /*
490  * nfs lookup rpc
491  */
492 int
nfsrv_lookup(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)493 nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
494     struct mbuf **mrq)
495 {
496 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
497 	struct sockaddr *nam = nfsd->nd_nam;
498 	caddr_t dpos = nfsd->nd_dpos;
499 	struct ucred *cred = nfsd->nd_cr;
500 	struct nfs_fattr *fp;
501 	struct nameidata nd, ind, *ndp = &nd;
502 	struct vnode *vp, *dirp = NULL;
503 	nfsfh_t nfh;
504 	fhandle_t *fhp;
505 	caddr_t bpos;
506 	int error = 0, len, dirattr_ret = 1;
507 	int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
508 	struct mbuf *mb, *mreq;
509 	struct vattr va, dirattr, *vap = &va;
510 
511 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
512 	ndclear(&nd);
513 
514 	fhp = &nfh.fh_generic;
515 	nfsm_srvmtofh(fhp);
516 	nfsm_srvnamesiz(len);
517 
518 	pubflag = nfs_ispublicfh(fhp);
519 
520 	nd.ni_cnd.cn_cred = cred;
521 	nd.ni_cnd.cn_nameiop = LOOKUP;
522 	nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
523 	error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
524 		&dirp, v3, &dirattr, &dirattr_ret, pubflag);
525 
526 	/*
527 	 * namei failure, only dirp to cleanup.  Clear out garbarge from
528 	 * structure in case macros jump to nfsmout.
529 	 */
530 
531 	if (error) {
532 		if (dirp) {
533 			vrele(dirp);
534 			dirp = NULL;
535 		}
536 		nfsm_reply(NFSX_POSTOPATTR(v3));
537 		if (v3)
538 			nfsm_srvpostop_attr(dirattr_ret, &dirattr);
539 		error = 0;
540 		goto nfsmout;
541 	}
542 
543 	/*
544 	 * Locate index file for public filehandle
545 	 *
546 	 * error is 0 on entry and 0 on exit from this block.
547 	 */
548 
549 	if (pubflag) {
550 		if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL) {
551 			/*
552 			 * Setup call to lookup() to see if we can find
553 			 * the index file. Arguably, this doesn't belong
554 			 * in a kernel.. Ugh.  If an error occurs, do not
555 			 * try to install an index file and then clear the
556 			 * error.
557 			 *
558 			 * When we replace nd with ind and redirect ndp,
559 			 * maintenance of ni_startdir and ni_vp shift to
560 			 * ind and we have to clean them up in the old nd.
561 			 * However, the cnd resource continues to be maintained
562 			 * via the original nd.  Confused?  You aren't alone!
563 			 */
564 			ind = nd;
565 			VOP_UNLOCK(nd.ni_vp, 0);
566 			ind.ni_pathlen = strlen(nfs_pub.np_index);
567 			ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf =
568 			    nfs_pub.np_index;
569 			ind.ni_startdir = nd.ni_vp;
570 			VREF(ind.ni_startdir);
571 			error = lookup(&ind);
572 			ind.ni_dvp = NULL;
573 
574 			if (error == 0) {
575 				/*
576 				 * Found an index file. Get rid of
577 				 * the old references.  transfer nd.ni_vp'
578 				 */
579 				if (dirp)
580 					vrele(dirp);
581 				dirp = nd.ni_vp;
582 				nd.ni_vp = NULL;
583 				vrele(nd.ni_startdir);
584 				nd.ni_startdir = NULL;
585 				ndp = &ind;
586 			}
587 			error = 0;
588 		}
589 		/*
590 		 * If the public filehandle was used, check that this lookup
591 		 * didn't result in a filehandle outside the publicly exported
592 		 * filesystem.  We clear the poor vp here to avoid lockups due
593 		 * to NFS I/O.
594 		 */
595 
596 		if (ndp->ni_vp->v_mount != nfs_pub.np_mount) {
597 			vput(nd.ni_vp);
598 			nd.ni_vp = NULL;
599 			error = EPERM;
600 		}
601 	}
602 
603 	/*
604 	 * Resources at this point:
605 	 *	ndp->ni_vp	may not be NULL
606 	 */
607 
608 	if (error) {
609 		nfsm_reply(NFSX_POSTOPATTR(v3));
610 		if (v3)
611 			nfsm_srvpostop_attr(dirattr_ret, &dirattr);
612 		error = 0;
613 		goto nfsmout;
614 	}
615 
616 	/*
617 	 * Get underlying attribute, then release remaining resources ( for
618 	 * the same potential blocking reason ) and reply.
619 	 */
620 	vp = ndp->ni_vp;
621 	bzero((caddr_t)fhp, sizeof(nfh));
622 	fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
623 	error = VOP_VPTOFH(vp, &fhp->fh_fid);
624 	if (!error)
625 		error = VOP_GETATTR(vp, vap, cred);
626 
627 	vput(vp);
628 	vrele(ndp->ni_startdir);
629 	vrele(dirp);
630 	ndp->ni_vp = NULL;
631 	ndp->ni_startdir = NULL;
632 	dirp = NULL;
633 	nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
634 	if (error) {
635 		if (v3)
636 			nfsm_srvpostop_attr(dirattr_ret, &dirattr);
637 		error = 0;
638 		goto nfsmout;
639 	}
640 	nfsm_srvfhtom(fhp, v3);
641 	if (v3) {
642 		nfsm_srvpostop_attr(0, vap);
643 		nfsm_srvpostop_attr(dirattr_ret, &dirattr);
644 	} else {
645 		fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
646 		nfsm_srvfillattr(vap, fp);
647 	}
648 
649 nfsmout:
650 	if (ndp->ni_vp || dirp || ndp->ni_startdir) {
651 		if (ndp->ni_vp)
652 			vput(ndp->ni_vp);
653 		if (dirp)
654 			vrele(dirp);
655 		if (ndp->ni_startdir)
656 			vrele(ndp->ni_startdir);
657 	}
658 	NDFREE(&nd, NDF_ONLY_PNBUF);
659 	return (error);
660 }
661 
662 /*
663  * nfs readlink service
664  */
665 int
nfsrv_readlink(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)666 nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
667     struct mbuf **mrq)
668 {
669 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
670 	struct sockaddr *nam = nfsd->nd_nam;
671 	caddr_t dpos = nfsd->nd_dpos;
672 	struct ucred *cred = nfsd->nd_cr;
673 	struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
674 	struct iovec *ivp = iv;
675 	struct mbuf *mp;
676 	u_int32_t *tl;
677 	caddr_t bpos;
678 	int error = 0, rdonly, i, tlen, len, getret;
679 	int v3 = (nfsd->nd_flag & ND_NFSV3);
680 	struct mbuf *mb, *mp3, *nmp, *mreq;
681 	struct vnode *vp = NULL;
682 	struct vattr attr;
683 	nfsfh_t nfh;
684 	fhandle_t *fhp;
685 	struct uio io, *uiop = &io;
686 
687 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
688 #ifndef nolint
689 	mp = NULL;
690 #endif
691 	mp3 = NULL;
692 	fhp = &nfh.fh_generic;
693 	nfsm_srvmtofh(fhp);
694 	len = 0;
695 	i = 0;
696 	while (len < NFS_MAXPATHLEN) {
697 		MGET(nmp, M_WAITOK, MT_DATA);
698 		MCLGET(nmp, M_WAITOK);
699 		nmp->m_len = NFSMSIZ(nmp);
700 		if (len == 0)
701 			mp3 = mp = nmp;
702 		else {
703 			mp->m_next = nmp;
704 			mp = nmp;
705 		}
706 		if ((len + mp->m_len) > NFS_MAXPATHLEN) {
707 			mp->m_len = NFS_MAXPATHLEN - len;
708 			len = NFS_MAXPATHLEN;
709 		} else
710 			len += mp->m_len;
711 		ivp->iov_base = mtod(mp, caddr_t);
712 		ivp->iov_len = mp->m_len;
713 		i++;
714 		ivp++;
715 	}
716 	uiop->uio_iov = iv;
717 	uiop->uio_iovcnt = i;
718 	uiop->uio_offset = 0;
719 	uiop->uio_resid = len;
720 	uiop->uio_rw = UIO_READ;
721 	uiop->uio_segflg = UIO_SYSSPACE;
722 	uiop->uio_td = NULL;
723 	error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
724 	if (error) {
725 		nfsm_reply(2 * NFSX_UNSIGNED);
726 		if (v3)
727 			nfsm_srvpostop_attr(1, NULL);
728 		error = 0;
729 		goto nfsmout;
730 	}
731 	if (vp->v_type != VLNK) {
732 		if (v3)
733 			error = EINVAL;
734 		else
735 			error = ENXIO;
736 	} else
737 		error = VOP_READLINK(vp, uiop, cred);
738 	getret = VOP_GETATTR(vp, &attr, cred);
739 	vput(vp);
740 	vp = NULL;
741 	nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
742 	if (v3)
743 		nfsm_srvpostop_attr(getret, &attr);
744 	if (error) {
745 		error = 0;
746 		goto nfsmout;
747 	}
748 	if (uiop->uio_resid > 0) {
749 		len -= uiop->uio_resid;
750 		tlen = nfsm_rndup(len);
751 		nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
752 	}
753 	tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
754 	*tl = txdr_unsigned(len);
755 	mb->m_next = mp3;
756 	mp3 = NULL;
757 nfsmout:
758 	if (mp3)
759 		m_freem(mp3);
760 	if (vp)
761 		vput(vp);
762 	return(error);
763 }
764 
765 /*
766  * nfs read service
767  */
768 int
nfsrv_read(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)769 nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
770     struct mbuf **mrq)
771 {
772 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
773 	struct sockaddr *nam = nfsd->nd_nam;
774 	caddr_t dpos = nfsd->nd_dpos;
775 	struct ucred *cred = nfsd->nd_cr;
776 	struct iovec *iv;
777 	struct iovec *iv2;
778 	struct mbuf *m;
779 	struct nfs_fattr *fp;
780 	u_int32_t *tl;
781 	int i;
782 	caddr_t bpos;
783 	int error = 0, rdonly, cnt, len, left, siz, tlen, getret;
784 	int v3 = (nfsd->nd_flag & ND_NFSV3), reqlen;
785 	struct mbuf *mb, *mreq;
786 	struct mbuf *m2;
787 	struct vnode *vp = NULL;
788 	nfsfh_t nfh;
789 	fhandle_t *fhp;
790 	struct uio io, *uiop = &io;
791 	struct vattr va, *vap = &va;
792 	struct nfsheur *nh;
793 	off_t off;
794 	int ioflag = 0;
795 
796 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
797 	fhp = &nfh.fh_generic;
798 	nfsm_srvmtofh(fhp);
799 	if (v3) {
800 		tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
801 		off = fxdr_hyper(tl);
802 	} else {
803 		tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
804 		off = (off_t)fxdr_unsigned(u_int32_t, *tl);
805 	}
806 	nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd));
807 
808 	/*
809 	 * Reference vp.  If an error occurs, vp will be invalid, but we
810 	 * have to NULL it just in case.  The macros might goto nfsmout
811 	 * as well.
812 	 */
813 
814 	error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
815 	if (error) {
816 		vp = NULL;
817 		nfsm_reply(2 * NFSX_UNSIGNED);
818 		if (v3)
819 			nfsm_srvpostop_attr(1, NULL);
820 		error = 0;
821 		goto nfsmout;
822 	}
823 
824 	if (vp->v_type != VREG) {
825 		if (v3)
826 			error = EINVAL;
827 		else
828 			error = (vp->v_type == VDIR) ? EISDIR : EACCES;
829 	}
830 	if (!error) {
831 		if ((error = nfsrv_access(vp, VREAD, cred, rdonly, 1)) != 0)
832 			error = nfsrv_access(vp, VEXEC, cred, rdonly, 1);
833 	}
834 	getret = VOP_GETATTR(vp, vap, cred);
835 	if (!error)
836 		error = getret;
837 	if (error) {
838 		vput(vp);
839 		vp = NULL;
840 		nfsm_reply(NFSX_POSTOPATTR(v3));
841 		if (v3)
842 			nfsm_srvpostop_attr(getret, vap);
843 		error = 0;
844 		goto nfsmout;
845 	}
846 
847 	/*
848 	 * Calculate byte count to read
849 	 */
850 	if (off >= vap->va_size)
851 		cnt = 0;
852 	else if ((off + reqlen) > vap->va_size)
853 		cnt = vap->va_size - off;
854 	else
855 		cnt = reqlen;
856 
857 	nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
858 	if (v3) {
859 		tl = nfsm_build(u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
860 		*tl++ = nfsrv_nfs_true;
861 		fp = (struct nfs_fattr *)tl;
862 		tl += (NFSX_V3FATTR / sizeof (u_int32_t));
863 	} else {
864 		tl = nfsm_build(u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED);
865 		fp = (struct nfs_fattr *)tl;
866 		tl += (NFSX_V2FATTR / sizeof (u_int32_t));
867 	}
868 	len = left = nfsm_rndup(cnt);
869 	if (cnt > 0) {
870 		/*
871 		 * Generate the mbuf list with the uio_iov ref. to it.
872 		 */
873 		i = 0;
874 		m = m2 = mb;
875 		while (left > 0) {
876 			siz = min(M_TRAILINGSPACE(m), left);
877 			if (siz > 0) {
878 				left -= siz;
879 				i++;
880 			}
881 			if (left > 0) {
882 				MGET(m, M_WAITOK, MT_DATA);
883 				MCLGET(m, M_WAITOK);
884 				m->m_len = 0;
885 				m2->m_next = m;
886 				m2 = m;
887 			}
888 		}
889 		iv = malloc(i * sizeof (struct iovec),
890 		       M_TEMP, M_WAITOK);
891 		uiop->uio_iov = iv2 = iv;
892 		m = mb;
893 		left = len;
894 		i = 0;
895 		while (left > 0) {
896 			if (m == NULL)
897 				panic("nfsrv_read iov");
898 			siz = min(M_TRAILINGSPACE(m), left);
899 			if (siz > 0) {
900 				iv->iov_base = mtod(m, caddr_t) + m->m_len;
901 				iv->iov_len = siz;
902 				m->m_len += siz;
903 				left -= siz;
904 				iv++;
905 				i++;
906 			}
907 			m = m->m_next;
908 		}
909 		uiop->uio_iovcnt = i;
910 		uiop->uio_offset = off;
911 		uiop->uio_resid = len;
912 		uiop->uio_rw = UIO_READ;
913 		uiop->uio_segflg = UIO_SYSSPACE;
914 		uiop->uio_td = NULL;
915 		nh = nfsrv_sequential_heuristic(uiop, vp);
916 		ioflag |= nh->nh_seqcount << IO_SEQSHIFT;
917 		error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred);
918 		if (error == 0)
919 			nh->nh_nextoff = uiop->uio_offset;
920 		free((caddr_t)iv2, M_TEMP);
921 		if (error || (getret = VOP_GETATTR(vp, vap, cred))) {
922 			if (!error)
923 				error = getret;
924 			m_freem(mreq);
925 			vput(vp);
926 			vp = NULL;
927 			nfsm_reply(NFSX_POSTOPATTR(v3));
928 			if (v3)
929 				nfsm_srvpostop_attr(getret, vap);
930 			error = 0;
931 			goto nfsmout;
932 		}
933 	} else
934 		uiop->uio_resid = 0;
935 	vput(vp);
936 	vp = NULL;
937 	nfsm_srvfillattr(vap, fp);
938 	tlen = len - uiop->uio_resid;
939 	cnt = cnt < tlen ? cnt : tlen;
940 	tlen = nfsm_rndup(cnt);
941 	if (len != tlen || tlen != cnt)
942 		nfsm_adj(mb, len - tlen, tlen - cnt);
943 	if (v3) {
944 		*tl++ = txdr_unsigned(cnt);
945 		if (cnt < reqlen)
946 			*tl++ = nfsrv_nfs_true;
947 		else
948 			*tl++ = nfsrv_nfs_false;
949 	}
950 	*tl = txdr_unsigned(cnt);
951 nfsmout:
952 	if (vp)
953 		vput(vp);
954 	return(error);
955 }
956 
957 /*
958  * nfs write service
959  */
960 int
nfsrv_write(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)961 nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
962     struct mbuf **mrq)
963 {
964 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
965 	struct sockaddr *nam = nfsd->nd_nam;
966 	caddr_t dpos = nfsd->nd_dpos;
967 	struct ucred *cred = nfsd->nd_cr;
968 	struct iovec *ivp;
969 	int i, cnt;
970 	struct mbuf *mp;
971 	struct nfs_fattr *fp;
972 	struct iovec *iv;
973 	struct vattr va, forat;
974 	struct vattr *vap = &va;
975 	u_int32_t *tl;
976 	caddr_t bpos;
977 	int error = 0, rdonly, len, forat_ret = 1;
978 	int ioflags, aftat_ret = 1, retlen = 0, zeroing, adjust;
979 	int stable = NFSV3WRITE_FILESYNC;
980 	int v3 = (nfsd->nd_flag & ND_NFSV3);
981 	struct mbuf *mb, *mreq;
982 	struct vnode *vp = NULL;
983 	struct nfsheur *nh;
984 	nfsfh_t nfh;
985 	fhandle_t *fhp;
986 	struct uio io, *uiop = &io;
987 	off_t off;
988 	struct mount *mntp = NULL;
989 
990 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
991 	if (mrep == NULL) {
992 		*mrq = NULL;
993 		error = 0;
994 		goto nfsmout;
995 	}
996 	fhp = &nfh.fh_generic;
997 	nfsm_srvmtofh(fhp);
998 	if ((mntp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
999 		error = ESTALE;
1000 		goto ereply;
1001 	}
1002 	(void) vn_start_write(NULL, &mntp, V_WAIT);
1003 	vfs_rel(mntp);		/* The write holds a ref. */
1004 	if (v3) {
1005 		tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED);
1006 		off = fxdr_hyper(tl);
1007 		tl += 3;
1008 		stable = fxdr_unsigned(int, *tl++);
1009 	} else {
1010 		tl = nfsm_dissect_nonblock(u_int32_t *, 4 * NFSX_UNSIGNED);
1011 		off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
1012 		tl += 2;
1013 		if (nfs_async)
1014 	    		stable = NFSV3WRITE_UNSTABLE;
1015 	}
1016 	retlen = len = fxdr_unsigned(int32_t, *tl);
1017 	cnt = i = 0;
1018 
1019 	/*
1020 	 * For NFS Version 2, it is not obvious what a write of zero length
1021 	 * should do, but I might as well be consistent with Version 3,
1022 	 * which is to return ok so long as there are no permission problems.
1023 	 */
1024 	if (len > 0) {
1025 	    zeroing = 1;
1026 	    mp = mrep;
1027 	    while (mp) {
1028 		if (mp == md) {
1029 			zeroing = 0;
1030 			adjust = dpos - mtod(mp, caddr_t);
1031 			mp->m_len -= adjust;
1032 			if (mp->m_len > 0 && adjust > 0)
1033 				mp->m_data += adjust;
1034 		}
1035 		if (zeroing)
1036 			mp->m_len = 0;
1037 		else if (mp->m_len > 0) {
1038 			i += mp->m_len;
1039 			if (i > len) {
1040 				mp->m_len -= (i - len);
1041 				zeroing	= 1;
1042 			}
1043 			if (mp->m_len > 0)
1044 				cnt++;
1045 		}
1046 		mp = mp->m_next;
1047 	    }
1048 	}
1049 	if (len > NFS_MAXDATA || len < 0 || i < len) {
1050 		error = EIO;
1051 		nfsm_reply(2 * NFSX_UNSIGNED);
1052 		if (v3)
1053 			nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1054 		error = 0;
1055 		goto nfsmout;
1056 	}
1057 	error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
1058 	if (error) {
1059 		vp = NULL;
1060 		nfsm_reply(2 * NFSX_UNSIGNED);
1061 		if (v3)
1062 			nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1063 		error = 0;
1064 		goto nfsmout;
1065 	}
1066 	if (v3)
1067 		forat_ret = VOP_GETATTR(vp, &forat, cred);
1068 	if (vp->v_type != VREG) {
1069 		if (v3)
1070 			error = EINVAL;
1071 		else
1072 			error = (vp->v_type == VDIR) ? EISDIR : EACCES;
1073 	}
1074 	if (!error)
1075 		error = nfsrv_access(vp, VWRITE, cred, rdonly, 1);
1076 	if (error) {
1077 		vput(vp);
1078 		vp = NULL;
1079 		nfsm_reply(NFSX_WCCDATA(v3));
1080 		if (v3)
1081 			nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1082 		error = 0;
1083 		goto nfsmout;
1084 	}
1085 
1086 	if (len > 0) {
1087 	    ivp = malloc(cnt * sizeof (struct iovec), M_TEMP,
1088 		M_WAITOK);
1089 	    uiop->uio_iov = iv = ivp;
1090 	    uiop->uio_iovcnt = cnt;
1091 	    mp = mrep;
1092 	    while (mp) {
1093 		if (mp->m_len > 0) {
1094 			ivp->iov_base = mtod(mp, caddr_t);
1095 			ivp->iov_len = mp->m_len;
1096 			ivp++;
1097 		}
1098 		mp = mp->m_next;
1099 	    }
1100 
1101 	    /*
1102 	     * XXX
1103 	     * The IO_METASYNC flag indicates that all metadata (and not just
1104 	     * enough to ensure data integrity) mus be written to stable storage
1105 	     * synchronously.
1106 	     * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
1107 	     */
1108 	    if (stable == NFSV3WRITE_UNSTABLE)
1109 		ioflags = IO_NODELOCKED;
1110 	    else if (stable == NFSV3WRITE_DATASYNC)
1111 		ioflags = (IO_SYNC | IO_NODELOCKED);
1112 	    else
1113 		ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
1114 	    uiop->uio_resid = len;
1115 	    uiop->uio_rw = UIO_WRITE;
1116 	    uiop->uio_segflg = UIO_SYSSPACE;
1117 	    uiop->uio_td = NULL;
1118 	    uiop->uio_offset = off;
1119 	    nh = nfsrv_sequential_heuristic(uiop, vp);
1120 	    ioflags |= nh->nh_seqcount << IO_SEQSHIFT;
1121 	    error = VOP_WRITE(vp, uiop, ioflags, cred);
1122 	    if (error == 0)
1123 		    nh->nh_nextoff = uiop->uio_offset;
1124 	    /* Unlocked write. */
1125 	    nfsrvstats.srvvop_writes++;
1126 	    free((caddr_t)iv, M_TEMP);
1127 	}
1128 	aftat_ret = VOP_GETATTR(vp, vap, cred);
1129 	vput(vp);
1130 	vp = NULL;
1131 	if (!error)
1132 		error = aftat_ret;
1133 ereply:
1134 	nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
1135 		2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
1136 	if (v3) {
1137 		nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1138 		if (error) {
1139 			error = 0;
1140 			goto nfsmout;
1141 		}
1142 		tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
1143 		*tl++ = txdr_unsigned(retlen);
1144 		/*
1145 		 * If nfs_async is set, then pretend the write was FILESYNC.
1146 		 */
1147 		if (stable == NFSV3WRITE_UNSTABLE && !nfs_async)
1148 			*tl++ = txdr_unsigned(stable);
1149 		else
1150 			*tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
1151 		/*
1152 		 * Actually, there is no need to txdr these fields,
1153 		 * but it may make the values more human readable,
1154 		 * for debugging purposes.
1155 		 */
1156 		if (nfsver.tv_sec == 0)
1157 			nfsver = boottime;
1158 		*tl++ = txdr_unsigned(nfsver.tv_sec);
1159 		*tl = txdr_unsigned(nfsver.tv_usec);
1160 	} else if (!error) {
1161 		/* v2 non-error case. */
1162 		fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
1163 		nfsm_srvfillattr(vap, fp);
1164 	}
1165 	error = 0;
1166 nfsmout:
1167 	if (vp)
1168 		vput(vp);
1169 	vn_finished_write(mntp);
1170 	return(error);
1171 }
1172 
1173 /*
1174  * nfs create service
1175  * now does a truncate to 0 length via. setattr if it already exists
1176  */
1177 int
nfsrv_create(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)1178 nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1179     struct mbuf **mrq)
1180 {
1181 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1182 	struct sockaddr *nam = nfsd->nd_nam;
1183 	caddr_t dpos = nfsd->nd_dpos;
1184 	struct ucred *cred = nfsd->nd_cr;
1185 	struct nfs_fattr *fp;
1186 	struct vattr va, dirfor, diraft;
1187 	struct vattr *vap = &va;
1188 	struct nfsv2_sattr *sp;
1189 	u_int32_t *tl;
1190 	struct nameidata nd;
1191 	caddr_t bpos;
1192 	int error = 0, rdev, len, tsize, dirfor_ret = 1, diraft_ret = 1;
1193 	int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
1194 	struct mbuf *mb, *mreq;
1195 	struct vnode *dirp = NULL;
1196 	nfsfh_t nfh;
1197 	fhandle_t *fhp;
1198 	u_quad_t tempsize;
1199 	struct timespec cverf;
1200 	struct mount *mp = NULL;
1201 
1202 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1203 #ifndef nolint
1204 	rdev = 0;
1205 #endif
1206 	ndclear(&nd);
1207 
1208 	fhp = &nfh.fh_generic;
1209 	nfsm_srvmtofh(fhp);
1210 	if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
1211 		error = ESTALE;
1212 		goto ereply;
1213 	}
1214 	(void) vn_start_write(NULL, &mp, V_WAIT);
1215 	vfs_rel(mp);		/* The write holds a ref. */
1216 	nfsm_srvnamesiz(len);
1217 
1218 	nd.ni_cnd.cn_cred = cred;
1219 	nd.ni_cnd.cn_nameiop = CREATE;
1220 	nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE;
1221 
1222 	/*
1223 	 * Call namei and do initial cleanup to get a few things
1224 	 * out of the way.  If we get an initial error we cleanup
1225 	 * and return here to avoid special-casing the invalid nd
1226 	 * structure through the rest of the case.  dirp may be
1227 	 * set even if an error occurs, but the nd structure will not
1228 	 * be valid at all if an error occurs so we have to invalidate it
1229 	 * prior to calling nfsm_reply ( which might goto nfsmout ).
1230 	 */
1231 	error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
1232 		&dirp, v3, &dirfor, &dirfor_ret, FALSE);
1233 	if (dirp && !v3) {
1234 		vrele(dirp);
1235 		dirp = NULL;
1236 	}
1237 	if (error) {
1238 		nfsm_reply(NFSX_WCCDATA(v3));
1239 		if (v3)
1240 			nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1241 		error = 0;
1242 		goto nfsmout;
1243 	}
1244 
1245 	/*
1246 	 * No error.  Continue.  State:
1247 	 *
1248 	 *	startdir	is valid ( we release this immediately )
1249 	 *	dirp 		may be valid
1250 	 *	nd.ni_vp	may be valid
1251 	 *	nd.ni_dvp	is valid
1252 	 *
1253 	 * The error state is set through the code and we may also do some
1254 	 * opportunistic releasing of vnodes to avoid holding locks through
1255 	 * NFS I/O.  The cleanup at the end is a catch-all
1256 	 */
1257 
1258 	VATTR_NULL(vap);
1259 	if (v3) {
1260 		tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
1261 		how = fxdr_unsigned(int, *tl);
1262 		switch (how) {
1263 		case NFSV3CREATE_GUARDED:
1264 			if (nd.ni_vp) {
1265 				error = EEXIST;
1266 				break;
1267 			}
1268 			/* fall through */
1269 		case NFSV3CREATE_UNCHECKED:
1270 			nfsm_srvsattr(vap);
1271 			break;
1272 		case NFSV3CREATE_EXCLUSIVE:
1273 			tl = nfsm_dissect_nonblock(u_int32_t *,
1274 			    NFSX_V3CREATEVERF);
1275 			/* Unique bytes, endianness is not important. */
1276 			cverf.tv_sec  = (int32_t)tl[0];
1277 			cverf.tv_nsec = tl[1];
1278 			exclusive_flag = 1;
1279 			break;
1280 		};
1281 		vap->va_type = VREG;
1282 	} else {
1283 		sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
1284 		vap->va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
1285 		if (vap->va_type == VNON)
1286 			vap->va_type = VREG;
1287 		vap->va_mode = nfstov_mode(sp->sa_mode);
1288 		switch (vap->va_type) {
1289 		case VREG:
1290 			tsize = fxdr_unsigned(int32_t, sp->sa_size);
1291 			if (tsize != -1)
1292 				vap->va_size = (u_quad_t)tsize;
1293 			break;
1294 		case VCHR:
1295 		case VBLK:
1296 		case VFIFO:
1297 			rdev = fxdr_unsigned(long, sp->sa_size);
1298 			break;
1299 		default:
1300 			break;
1301 		};
1302 	}
1303 
1304 	/*
1305 	 * Iff doesn't exist, create it
1306 	 * otherwise just truncate to 0 length
1307 	 *   should I set the mode too ?
1308 	 *
1309 	 * The only possible error we can have at this point is EEXIST.
1310 	 * nd.ni_vp will also be non-NULL in that case.
1311 	 */
1312 	if (nd.ni_vp == NULL) {
1313 		if (vap->va_mode == (mode_t)VNOVAL)
1314 			vap->va_mode = 0;
1315 		if (vap->va_type == VREG || vap->va_type == VSOCK) {
1316 			error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
1317 			if (error)
1318 				NDFREE(&nd, NDF_ONLY_PNBUF);
1319 			else {
1320 				if (exclusive_flag) {
1321 					exclusive_flag = 0;
1322 					VATTR_NULL(vap);
1323 					vap->va_atime = cverf;
1324 					error = VOP_SETATTR(nd.ni_vp, vap,
1325 					    cred);
1326 				}
1327 			}
1328 		} else if (vap->va_type == VCHR || vap->va_type == VBLK ||
1329 		    vap->va_type == VFIFO) {
1330 			/*
1331 			 * NFSv2-specific code for creating device nodes
1332 			 * and fifos.
1333 			 *
1334 			 * Handle SysV FIFO node special cases.  All other
1335 			 * devices require super user to access.
1336 			 */
1337 			if (vap->va_type == VCHR && rdev == 0xffffffff)
1338 				vap->va_type = VFIFO;
1339                         if (vap->va_type != VFIFO &&
1340 			    (error = priv_check_cred(cred, PRIV_VFS_MKNOD_DEV,
1341 			    0))) {
1342 				goto ereply;
1343                         }
1344 			vap->va_rdev = rdev;
1345 			error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
1346 			if (error) {
1347 				NDFREE(&nd, NDF_ONLY_PNBUF);
1348 				goto ereply;
1349 			}
1350 			vput(nd.ni_vp);
1351 			nd.ni_vp = NULL;
1352 
1353 			/*
1354 			 * release dvp prior to lookup
1355 			 */
1356 			vput(nd.ni_dvp);
1357 			nd.ni_dvp = NULL;
1358 			/*
1359 			 * Setup for lookup.
1360 			 *
1361 			 * Even though LOCKPARENT was cleared, ni_dvp may
1362 			 * be garbage.
1363 			 */
1364 			nd.ni_cnd.cn_nameiop = LOOKUP;
1365 			nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
1366 			nd.ni_cnd.cn_thread = curthread;
1367 			nd.ni_cnd.cn_cred = cred;
1368 			error = lookup(&nd);
1369 			nd.ni_dvp = NULL;
1370 			if (error)
1371 				goto ereply;
1372 
1373 			if (nd.ni_cnd.cn_flags & ISSYMLINK) {
1374 				error = EINVAL;
1375 				goto ereply;
1376 			}
1377 		} else {
1378 			error = ENXIO;
1379 		}
1380 	} else {
1381 		if (vap->va_size != -1) {
1382 			error = nfsrv_access(nd.ni_vp, VWRITE,
1383 			    cred, (nd.ni_cnd.cn_flags & RDONLY), 0);
1384 			if (!error) {
1385 				tempsize = vap->va_size;
1386 				VATTR_NULL(vap);
1387 				vap->va_size = tempsize;
1388 				error = VOP_SETATTR(nd.ni_vp, vap, cred);
1389 			}
1390 		}
1391 	}
1392 
1393 	if (!error) {
1394 		bzero((caddr_t)fhp, sizeof(nfh));
1395 		fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
1396 		error = VOP_VPTOFH(nd.ni_vp, &fhp->fh_fid);
1397 		if (!error)
1398 			error = VOP_GETATTR(nd.ni_vp, vap, cred);
1399 	}
1400 	if (v3) {
1401 		if (exclusive_flag && !error &&
1402 		    bcmp(&cverf, &vap->va_atime, sizeof (cverf)))
1403 			error = EEXIST;
1404 		if (dirp == nd.ni_dvp)
1405 			diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
1406 		else {
1407 			/* Drop the other locks to avoid deadlock. */
1408 			if (nd.ni_dvp) {
1409 				if (nd.ni_dvp == nd.ni_vp)
1410 					vrele(nd.ni_dvp);
1411 				else
1412 					vput(nd.ni_dvp);
1413 			}
1414 			if (nd.ni_vp)
1415 				vput(nd.ni_vp);
1416 			nd.ni_dvp = NULL;
1417 			nd.ni_vp = NULL;
1418 
1419 			vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
1420 			diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
1421 			VOP_UNLOCK(dirp, 0);
1422 		}
1423 	}
1424 ereply:
1425 	nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
1426 	if (v3) {
1427 		if (!error) {
1428 			nfsm_srvpostop_fh(fhp);
1429 			nfsm_srvpostop_attr(0, vap);
1430 		}
1431 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1432 	} else if (!error) {
1433 		/* v2 non-error case. */
1434 		nfsm_srvfhtom(fhp, v3);
1435 		fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
1436 		nfsm_srvfillattr(vap, fp);
1437 	}
1438 	error = 0;
1439 
1440 nfsmout:
1441 	if (nd.ni_dvp) {
1442 		if (nd.ni_dvp == nd.ni_vp)
1443 			vrele(nd.ni_dvp);
1444 		else
1445 			vput(nd.ni_dvp);
1446 	}
1447 	if (nd.ni_vp)
1448 		vput(nd.ni_vp);
1449 	if (nd.ni_startdir) {
1450 		vrele(nd.ni_startdir);
1451 		nd.ni_startdir = NULL;
1452 	}
1453 	if (dirp)
1454 		vrele(dirp);
1455 	NDFREE(&nd, NDF_ONLY_PNBUF);
1456 	vn_finished_write(mp);
1457 	return (error);
1458 }
1459 
1460 /*
1461  * nfs v3 mknod service
1462  */
1463 int
nfsrv_mknod(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)1464 nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1465     struct mbuf **mrq)
1466 {
1467 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1468 	struct sockaddr *nam = nfsd->nd_nam;
1469 	caddr_t dpos = nfsd->nd_dpos;
1470 	struct ucred *cred = nfsd->nd_cr;
1471 	struct vattr va, dirfor, diraft;
1472 	struct vattr *vap = &va;
1473 	struct thread *td = curthread;
1474 	u_int32_t *tl;
1475 	struct nameidata nd;
1476 	caddr_t bpos;
1477 	int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
1478 	u_int32_t major, minor;
1479 	enum vtype vtyp;
1480 	struct mbuf *mb, *mreq;
1481 	struct vnode *vp, *dirp = NULL;
1482 	nfsfh_t nfh;
1483 	fhandle_t *fhp;
1484 	struct mount *mp = NULL;
1485 	int v3 = (nfsd->nd_flag & ND_NFSV3);
1486 
1487 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1488 	if (!v3)
1489 		panic("nfsrv_mknod: v3 proc called on a v2 connection");
1490 	ndclear(&nd);
1491 
1492 	fhp = &nfh.fh_generic;
1493 	nfsm_srvmtofh(fhp);
1494 	if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
1495 		error = ESTALE;
1496 		goto ereply;
1497 	}
1498 	(void) vn_start_write(NULL, &mp, V_WAIT);
1499 	vfs_rel(mp);		/* The write holds a ref. */
1500 	nfsm_srvnamesiz(len);
1501 
1502 	nd.ni_cnd.cn_cred = cred;
1503 	nd.ni_cnd.cn_nameiop = CREATE;
1504 	nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE;
1505 
1506 	/*
1507 	 * Handle nfs_namei() call.  If an error occurs, the nd structure
1508 	 * is not valid.  However, nfsm_*() routines may still jump to
1509 	 * nfsmout.
1510 	 */
1511 
1512 	error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
1513 		&dirp, v3, &dirfor, &dirfor_ret, FALSE);
1514 	if (error) {
1515 		nfsm_reply(NFSX_WCCDATA(1));
1516 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1517 		error = 0;
1518 		goto nfsmout;
1519 	}
1520 	tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
1521 	vtyp = nfsv3tov_type(*tl);
1522 	if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
1523 		error = NFSERR_BADTYPE;
1524 		goto out;
1525 	}
1526 	VATTR_NULL(vap);
1527 	nfsm_srvsattr(vap);
1528 	if (vtyp == VCHR || vtyp == VBLK) {
1529 		tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
1530 		major = fxdr_unsigned(u_int32_t, *tl++);
1531 		minor = fxdr_unsigned(u_int32_t, *tl);
1532 		vap->va_rdev = makedev(major, minor);
1533 	}
1534 
1535 	/*
1536 	 * Iff doesn't exist, create it.
1537 	 */
1538 	if (nd.ni_vp) {
1539 		error = EEXIST;
1540 		goto out;
1541 	}
1542 	vap->va_type = vtyp;
1543 	if (vap->va_mode == (mode_t)VNOVAL)
1544 		vap->va_mode = 0;
1545 	if (vtyp == VSOCK) {
1546 		vrele(nd.ni_startdir);
1547 		nd.ni_startdir = NULL;
1548 		error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
1549 		if (error)
1550 			NDFREE(&nd, NDF_ONLY_PNBUF);
1551 	} else {
1552 		if (vtyp != VFIFO && (error = priv_check_cred(cred,
1553 		    PRIV_VFS_MKNOD_DEV, 0)))
1554 			goto out;
1555 		error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
1556 		if (error) {
1557 			NDFREE(&nd, NDF_ONLY_PNBUF);
1558 			goto out;
1559 		}
1560 		vput(nd.ni_vp);
1561 		nd.ni_vp = NULL;
1562 
1563 		/*
1564 		 * Release dvp prior to lookup
1565 		 */
1566 		vput(nd.ni_dvp);
1567 		nd.ni_dvp = NULL;
1568 
1569 		nd.ni_cnd.cn_nameiop = LOOKUP;
1570 		nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
1571 		nd.ni_cnd.cn_thread = td;
1572 		nd.ni_cnd.cn_cred = td->td_ucred;
1573 		error = lookup(&nd);
1574 		nd.ni_dvp = NULL;
1575 
1576 		if (error)
1577 			goto out;
1578 		if (nd.ni_cnd.cn_flags & ISSYMLINK)
1579 			error = EINVAL;
1580 	}
1581 
1582 	/*
1583 	 * send response, cleanup, return.
1584 	 */
1585 out:
1586 	vp = nd.ni_vp;
1587 	if (!error) {
1588 		bzero((caddr_t)fhp, sizeof(nfh));
1589 		fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1590 		error = VOP_VPTOFH(vp, &fhp->fh_fid);
1591 		if (!error)
1592 			error = VOP_GETATTR(vp, vap, cred);
1593 	}
1594 	if (nd.ni_dvp) {
1595 		if (nd.ni_dvp == nd.ni_vp)
1596 			vrele(nd.ni_dvp);
1597 		else
1598 			vput(nd.ni_dvp);
1599 		nd.ni_dvp = NULL;
1600 	}
1601 	if (vp) {
1602 		vput(vp);
1603 		vp = NULL;
1604 		nd.ni_vp = NULL;
1605 	}
1606 	if (nd.ni_startdir) {
1607 		vrele(nd.ni_startdir);
1608 		nd.ni_startdir = NULL;
1609 	}
1610 	NDFREE(&nd, NDF_ONLY_PNBUF);
1611 	if (dirp) {
1612 		vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
1613 		diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
1614 		vput(dirp);
1615 	}
1616 ereply:
1617 	nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
1618 	if (v3) {
1619 		if (!error) {
1620 			nfsm_srvpostop_fh(fhp);
1621 			nfsm_srvpostop_attr(0, vap);
1622 		}
1623 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1624 	}
1625 	vn_finished_write(mp);
1626 	return (0);
1627 nfsmout:
1628 	if (nd.ni_dvp) {
1629 		if (nd.ni_dvp == nd.ni_vp)
1630 			vrele(nd.ni_dvp);
1631 		else
1632 			vput(nd.ni_dvp);
1633 	}
1634 	if (nd.ni_vp)
1635 		vput(nd.ni_vp);
1636 	if (dirp)
1637 		vrele(dirp);
1638 	if (nd.ni_startdir)
1639 		vrele(nd.ni_startdir);
1640 	NDFREE(&nd, NDF_ONLY_PNBUF);
1641 	vn_finished_write(mp);
1642 	return (error);
1643 }
1644 
1645 /*
1646  * nfs remove service
1647  */
1648 int
nfsrv_remove(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)1649 nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1650     struct mbuf **mrq)
1651 {
1652 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1653 	struct sockaddr *nam = nfsd->nd_nam;
1654 	caddr_t dpos = nfsd->nd_dpos;
1655 	struct ucred *cred = nfsd->nd_cr;
1656 	struct nameidata nd;
1657 	caddr_t bpos;
1658 	int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
1659 	int v3 = (nfsd->nd_flag & ND_NFSV3);
1660 	struct mbuf *mb, *mreq;
1661 	struct vnode *dirp;
1662 	struct vattr dirfor, diraft;
1663 	nfsfh_t nfh;
1664 	fhandle_t *fhp;
1665 	struct mount *mp = NULL;
1666 
1667 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1668 	ndclear(&nd);
1669 
1670 	fhp = &nfh.fh_generic;
1671 	nfsm_srvmtofh(fhp);
1672 	if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
1673 		error = ESTALE;
1674 		goto ereply;
1675 	}
1676 	(void) vn_start_write(NULL, &mp, V_WAIT);
1677 	vfs_rel(mp);		/* The write holds a ref. */
1678 	nfsm_srvnamesiz(len);
1679 
1680 	nd.ni_cnd.cn_cred = cred;
1681 	nd.ni_cnd.cn_nameiop = DELETE;
1682 	nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
1683 	error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
1684 		&dirp, v3,  &dirfor, &dirfor_ret, FALSE);
1685 	if (dirp && !v3) {
1686 		vrele(dirp);
1687 		dirp = NULL;
1688 	}
1689 	if (error == 0) {
1690 		if (nd.ni_vp->v_type == VDIR) {
1691 			error = EPERM;		/* POSIX */
1692 			goto out;
1693 		}
1694 		/*
1695 		 * The root of a mounted filesystem cannot be deleted.
1696 		 */
1697 		if (nd.ni_vp->v_vflag & VV_ROOT) {
1698 			error = EBUSY;
1699 			goto out;
1700 		}
1701 out:
1702 		if (!error) {
1703 			error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1704 			NDFREE(&nd, NDF_ONLY_PNBUF);
1705 		}
1706 	}
1707 	if (dirp && v3) {
1708 		if (dirp == nd.ni_dvp)
1709 			diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
1710 		else {
1711 			/* Drop the other locks to avoid deadlock. */
1712 			if (nd.ni_dvp) {
1713 				if (nd.ni_dvp == nd.ni_vp)
1714 					vrele(nd.ni_dvp);
1715 				else
1716 					vput(nd.ni_dvp);
1717 			}
1718 			if (nd.ni_vp)
1719 				vput(nd.ni_vp);
1720 			nd.ni_dvp = NULL;
1721 			nd.ni_vp = NULL;
1722 
1723 			vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
1724 			diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
1725 			VOP_UNLOCK(dirp, 0);
1726 		}
1727 		vrele(dirp);
1728 		dirp = NULL;
1729 	}
1730 ereply:
1731 	nfsm_reply(NFSX_WCCDATA(v3));
1732 	if (v3)
1733 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1734 	error = 0;
1735 nfsmout:
1736 	NDFREE(&nd, NDF_ONLY_PNBUF);
1737 	if (nd.ni_dvp) {
1738 		if (nd.ni_dvp == nd.ni_vp)
1739 			vrele(nd.ni_dvp);
1740 		else
1741 			vput(nd.ni_dvp);
1742 	}
1743 	if (nd.ni_vp)
1744 		vput(nd.ni_vp);
1745 	vn_finished_write(mp);
1746 	return(error);
1747 }
1748 
1749 /*
1750  * nfs rename service
1751  */
1752 int
nfsrv_rename(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)1753 nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1754     struct mbuf **mrq)
1755 {
1756 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1757 	struct sockaddr *nam = nfsd->nd_nam;
1758 	caddr_t dpos = nfsd->nd_dpos;
1759 	struct ucred *cred = nfsd->nd_cr;
1760 	caddr_t bpos;
1761 	int error = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
1762 	int tdirfor_ret = 1, tdiraft_ret = 1;
1763 	int v3 = (nfsd->nd_flag & ND_NFSV3);
1764 	struct mbuf *mb, *mreq;
1765 	struct nameidata fromnd, tond;
1766 	struct vnode *fvp, *tvp, *tdvp, *fdirp = NULL;
1767 	struct vnode *tdirp = NULL;
1768 	struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
1769 	nfsfh_t fnfh, tnfh;
1770 	fhandle_t *ffhp, *tfhp;
1771 	uid_t saved_uid;
1772 	struct mount *mp = NULL;
1773 
1774 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1775 #ifndef nolint
1776 	fvp = NULL;
1777 #endif
1778 	ffhp = &fnfh.fh_generic;
1779 	tfhp = &tnfh.fh_generic;
1780 
1781 	/*
1782 	 * Clear fields incase goto nfsmout occurs from macro.
1783 	 */
1784 
1785 	ndclear(&fromnd);
1786 	ndclear(&tond);
1787 
1788 	nfsm_srvmtofh(ffhp);
1789 	if ((mp = vfs_getvfs(&ffhp->fh_fsid)) == NULL) {
1790 		error = ESTALE;
1791 		goto out1;
1792 	}
1793 	(void) vn_start_write(NULL, &mp, V_WAIT);
1794 	vfs_rel(mp);		/* The write holds a ref. */
1795 	nfsm_srvnamesiz(len);
1796 	/*
1797 	 * Remember our original uid so that we can reset cr_uid before
1798 	 * the second nfs_namei() call, in case it is remapped.
1799 	 */
1800 	saved_uid = cred->cr_uid;
1801 	fromnd.ni_cnd.cn_cred = cred;
1802 	fromnd.ni_cnd.cn_nameiop = DELETE;
1803 	fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
1804 	error = nfs_namei(&fromnd, nfsd, ffhp, len, slp, nam, &md,
1805 		&dpos, &fdirp, v3, &fdirfor, &fdirfor_ret, FALSE);
1806 	if (fdirp && !v3) {
1807 		vrele(fdirp);
1808 		fdirp = NULL;
1809 	}
1810 	if (error) {
1811 		nfsm_reply(2 * NFSX_WCCDATA(v3));
1812 		if (v3) {
1813 			nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
1814 			nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
1815 		}
1816 		error = 0;
1817 		goto nfsmout;
1818 	}
1819 	fvp = fromnd.ni_vp;
1820 	nfsm_srvmtofh(tfhp);
1821 	nfsm_srvnamesiz(len2);
1822 	cred->cr_uid = saved_uid;
1823 	tond.ni_cnd.cn_cred = cred;
1824 	tond.ni_cnd.cn_nameiop = RENAME;
1825 	tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
1826 	error = nfs_namei(&tond, nfsd, tfhp, len2, slp, nam, &md,
1827 		&dpos, &tdirp, v3, &tdirfor, &tdirfor_ret, FALSE);
1828 	if (tdirp && !v3) {
1829 		vrele(tdirp);
1830 		tdirp = NULL;
1831 	}
1832 	if (error)
1833 		goto out1;
1834 
1835 	tdvp = tond.ni_dvp;
1836 	tvp = tond.ni_vp;
1837 	if (tvp != NULL) {
1838 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1839 			if (v3)
1840 				error = EEXIST;
1841 			else
1842 				error = EISDIR;
1843 			goto out;
1844 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1845 			if (v3)
1846 				error = EEXIST;
1847 			else
1848 				error = ENOTDIR;
1849 			goto out;
1850 		}
1851 		if (tvp->v_type == VDIR && tvp->v_mountedhere) {
1852 			if (v3)
1853 				error = EXDEV;
1854 			else
1855 				error = ENOTEMPTY;
1856 			goto out;
1857 		}
1858 	}
1859 	if (fvp->v_type == VDIR && fvp->v_mountedhere) {
1860 		if (v3)
1861 			error = EXDEV;
1862 		else
1863 			error = ENOTEMPTY;
1864 		goto out;
1865 	}
1866 	if (fvp->v_mount != tdvp->v_mount) {
1867 		if (v3)
1868 			error = EXDEV;
1869 		else
1870 			error = ENOTEMPTY;
1871 		goto out;
1872 	}
1873 	if (fvp == tdvp) {
1874 		if (v3)
1875 			error = EINVAL;
1876 		else
1877 			error = ENOTEMPTY;
1878 	}
1879 	/*
1880 	 * If source is the same as the destination (that is the
1881 	 * same vnode with the same name in the same directory),
1882 	 * then there is nothing to do.
1883 	 */
1884 	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1885 	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1886 	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1887 	      fromnd.ni_cnd.cn_namelen))
1888 		error = -1;
1889 out:
1890 	if (!error) {
1891 		/*
1892 		 * The VOP_RENAME function releases all vnode references &
1893 		 * locks prior to returning so we need to clear the pointers
1894 		 * to bypass cleanup code later on.
1895 		 */
1896 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1897 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1898 		fromnd.ni_dvp = NULL;
1899 		fromnd.ni_vp = NULL;
1900 		tond.ni_dvp = NULL;
1901 		tond.ni_vp = NULL;
1902 		if (error) {
1903 			NDFREE(&fromnd, NDF_ONLY_PNBUF);
1904 			NDFREE(&tond, NDF_ONLY_PNBUF);
1905 		}
1906 	} else {
1907 		if (error == -1)
1908 			error = 0;
1909 	}
1910 	/* fall through */
1911 out1:
1912 	nfsm_reply(2 * NFSX_WCCDATA(v3));
1913 	if (v3) {
1914 		/* Release existing locks to prevent deadlock. */
1915 		if (tond.ni_dvp) {
1916 			if (tond.ni_dvp == tond.ni_vp)
1917 				vrele(tond.ni_dvp);
1918 			else
1919 				vput(tond.ni_dvp);
1920 		}
1921 		if (tond.ni_vp)
1922 			vput(tond.ni_vp);
1923 		tond.ni_dvp = NULL;
1924 		tond.ni_vp = NULL;
1925 
1926 		if (fdirp) {
1927 			vn_lock(fdirp, LK_EXCLUSIVE | LK_RETRY);
1928 			fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred);
1929 			VOP_UNLOCK(fdirp, 0);
1930 		}
1931 		if (tdirp) {
1932 			vn_lock(tdirp, LK_EXCLUSIVE | LK_RETRY);
1933 			tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred);
1934 			VOP_UNLOCK(tdirp, 0);
1935 		}
1936 		nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
1937 		nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
1938 	}
1939 	error = 0;
1940 	/* fall through */
1941 
1942 nfsmout:
1943 	/*
1944 	 * Clear out tond related fields
1945 	 */
1946 	if (tond.ni_dvp) {
1947 		if (tond.ni_dvp == tond.ni_vp)
1948 			vrele(tond.ni_dvp);
1949 		else
1950 			vput(tond.ni_dvp);
1951 	}
1952 	if (tond.ni_vp)
1953 		vput(tond.ni_vp);
1954 	if (tdirp)
1955 		vrele(tdirp);
1956 	if (tond.ni_startdir)
1957 		vrele(tond.ni_startdir);
1958 	NDFREE(&tond, NDF_ONLY_PNBUF);
1959 	/*
1960 	 * Clear out fromnd related fields
1961 	 */
1962 	if (fdirp)
1963 		vrele(fdirp);
1964 	if (fromnd.ni_startdir)
1965 		vrele(fromnd.ni_startdir);
1966 	NDFREE(&fromnd, NDF_ONLY_PNBUF);
1967 	if (fromnd.ni_dvp)
1968 		vrele(fromnd.ni_dvp);
1969 	if (fromnd.ni_vp)
1970 		vrele(fromnd.ni_vp);
1971 
1972 	vn_finished_write(mp);
1973 	return (error);
1974 }
1975 
1976 /*
1977  * nfs link service
1978  */
1979 int
nfsrv_link(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)1980 nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1981     struct mbuf **mrq)
1982 {
1983 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1984 	struct sockaddr *nam = nfsd->nd_nam;
1985 	caddr_t dpos = nfsd->nd_dpos;
1986 	struct ucred *cred = nfsd->nd_cr;
1987 	struct nameidata nd;
1988 	caddr_t bpos;
1989 	int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1;
1990 	int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
1991 	struct mbuf *mb, *mreq;
1992 	struct vnode *vp = NULL, *xp, *dirp = NULL;
1993 	struct vattr dirfor, diraft, at;
1994 	nfsfh_t nfh, dnfh;
1995 	fhandle_t *fhp, *dfhp;
1996 	struct mount *mp = NULL;
1997 
1998 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1999 	ndclear(&nd);
2000 
2001 	fhp = &nfh.fh_generic;
2002 	dfhp = &dnfh.fh_generic;
2003 	nfsm_srvmtofh(fhp);
2004 	if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2005 		error = ESTALE;
2006 		goto ereply;
2007 	}
2008 	(void) vn_start_write(NULL, &mp, V_WAIT);
2009 	vfs_rel(mp);		/* The write holds a ref. */
2010 	nfsm_srvmtofh(dfhp);
2011 	nfsm_srvnamesiz(len);
2012 
2013 	error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
2014 	if (error) {
2015 		nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2016 		if (v3) {
2017 			nfsm_srvpostop_attr(getret, &at);
2018 			nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2019 		}
2020 		vp = NULL;
2021 		error = 0;
2022 		goto nfsmout;
2023 	}
2024 	if (v3)
2025 		getret = VOP_GETATTR(vp, &at, cred);
2026 	if (vp->v_type == VDIR) {
2027 		error = EPERM;		/* POSIX */
2028 		goto out1;
2029 	}
2030 	VOP_UNLOCK(vp, 0);
2031 	nd.ni_cnd.cn_cred = cred;
2032 	nd.ni_cnd.cn_nameiop = CREATE;
2033 	nd.ni_cnd.cn_flags = LOCKPARENT | NOCACHE;
2034 	error = nfs_namei(&nd, nfsd, dfhp, len, slp, nam, &md, &dpos,
2035 		&dirp, v3, &dirfor, &dirfor_ret, FALSE);
2036 	if (dirp && !v3) {
2037 		vrele(dirp);
2038 		dirp = NULL;
2039 	}
2040 	if (error) {
2041 		vrele(vp);
2042 		vp = NULL;
2043 		goto out2;
2044 	}
2045 	xp = nd.ni_vp;
2046 	if (xp != NULL) {
2047 		error = EEXIST;
2048 		vrele(vp);
2049 		vp = NULL;
2050 		goto out2;
2051 	}
2052 	xp = nd.ni_dvp;
2053 	if (vp->v_mount != xp->v_mount) {
2054 		error = EXDEV;
2055 		vrele(vp);
2056 		vp = NULL;
2057 		goto out2;
2058 	}
2059 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2060 	error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
2061 	NDFREE(&nd, NDF_ONLY_PNBUF);
2062 	/* fall through */
2063 
2064 out1:
2065 	if (v3)
2066 		getret = VOP_GETATTR(vp, &at, cred);
2067 out2:
2068 	if (dirp) {
2069 		if (dirp == nd.ni_dvp)
2070 			diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2071 		else {
2072 			/* Release existing locks to prevent deadlock. */
2073 			if (nd.ni_dvp) {
2074 				if (nd.ni_dvp == nd.ni_vp)
2075 					vrele(nd.ni_dvp);
2076 				else
2077 					vput(nd.ni_dvp);
2078 			}
2079 			if (nd.ni_vp)
2080 				vrele(nd.ni_vp);
2081 			nd.ni_dvp = NULL;
2082 			nd.ni_vp = NULL;
2083 
2084 			vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
2085 			diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2086 			VOP_UNLOCK(dirp, 0);
2087 		}
2088 	}
2089 ereply:
2090 	nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2091 	if (v3) {
2092 		nfsm_srvpostop_attr(getret, &at);
2093 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2094 	}
2095 	error = 0;
2096 	/* fall through */
2097 
2098 nfsmout:
2099 	NDFREE(&nd, NDF_ONLY_PNBUF);
2100 	if (vp)
2101 		vput(vp);
2102 	if (nd.ni_dvp) {
2103 		if (nd.ni_dvp == nd.ni_vp)
2104 			vrele(nd.ni_dvp);
2105 		else
2106 			vput(nd.ni_dvp);
2107 	}
2108 	if (dirp)
2109 		vrele(dirp);
2110 	if (nd.ni_vp)
2111 		vrele(nd.ni_vp);
2112 	vn_finished_write(mp);
2113 	return(error);
2114 }
2115 
2116 /*
2117  * nfs symbolic link service
2118  */
2119 int
nfsrv_symlink(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)2120 nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2121     struct mbuf **mrq)
2122 {
2123 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2124 	struct sockaddr *nam = nfsd->nd_nam;
2125 	caddr_t dpos = nfsd->nd_dpos;
2126 	struct ucred *cred = nfsd->nd_cr;
2127 	struct vattr va, dirfor, diraft;
2128 	struct nameidata nd;
2129 	struct vattr *vap = &va;
2130 	struct nfsv2_sattr *sp;
2131 	char *bpos, *pathcp = NULL;
2132 	struct uio io;
2133 	struct iovec iv;
2134 	int error = 0, len, len2, dirfor_ret = 1, diraft_ret = 1;
2135 	int v3 = (nfsd->nd_flag & ND_NFSV3);
2136 	struct mbuf *mb, *mreq;
2137 	struct vnode *dirp = NULL;
2138 	nfsfh_t nfh;
2139 	fhandle_t *fhp;
2140 	struct mount *mp = NULL;
2141 
2142 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2143 	ndclear(&nd);
2144 
2145 	fhp = &nfh.fh_generic;
2146 	nfsm_srvmtofh(fhp);
2147 	if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2148 		error = ESTALE;
2149 		goto out;
2150 	}
2151 	(void) vn_start_write(NULL, &mp, V_WAIT);
2152 	vfs_rel(mp);		/* The write holds a ref. */
2153 	nfsm_srvnamesiz(len);
2154 	nd.ni_cnd.cn_cred = cred;
2155 	nd.ni_cnd.cn_nameiop = CREATE;
2156 	nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART | NOCACHE;
2157 	error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
2158 		&dirp, v3, &dirfor, &dirfor_ret, FALSE);
2159 	if (error == 0) {
2160 		VATTR_NULL(vap);
2161 		if (v3)
2162 			nfsm_srvsattr(vap);
2163 		nfsm_srvpathsiz(len2);
2164 	}
2165 	if (dirp && !v3) {
2166 		vrele(dirp);
2167 		dirp = NULL;
2168 	}
2169 	if (error)
2170 		goto out;
2171 	pathcp = malloc(len2 + 1, M_TEMP, M_WAITOK);
2172 	iv.iov_base = pathcp;
2173 	iv.iov_len = len2;
2174 	io.uio_resid = len2;
2175 	io.uio_offset = 0;
2176 	io.uio_iov = &iv;
2177 	io.uio_iovcnt = 1;
2178 	io.uio_segflg = UIO_SYSSPACE;
2179 	io.uio_rw = UIO_READ;
2180 	io.uio_td = NULL;
2181 	nfsm_mtouio(&io, len2);
2182 	if (!v3) {
2183 		sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
2184 		vap->va_mode = nfstov_mode(sp->sa_mode);
2185 	}
2186 	*(pathcp + len2) = '\0';
2187 	if (nd.ni_vp) {
2188 		error = EEXIST;
2189 		goto out;
2190 	}
2191 
2192 	/*
2193 	 * issue symlink op.  SAVESTART is set so the underlying path component
2194 	 * is only freed by the VOP if an error occurs.
2195 	 */
2196 	if (vap->va_mode == (mode_t)VNOVAL)
2197 		vap->va_mode = 0;
2198 	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp);
2199 	if (error)
2200 		NDFREE(&nd, NDF_ONLY_PNBUF);
2201 	else
2202 		vput(nd.ni_vp);
2203 	nd.ni_vp = NULL;
2204 	/*
2205 	 * releases directory prior to potential lookup op.
2206 	 */
2207 	vput(nd.ni_dvp);
2208 	nd.ni_dvp = NULL;
2209 
2210 	if (error == 0) {
2211 	    if (v3) {
2212 		/*
2213 		 * Issue lookup.  Leave SAVESTART set so we can easily free
2214 		 * the name buffer later on.
2215 		 *
2216 		 * since LOCKPARENT is not set, ni_dvp will be garbage on
2217 		 * return whether an error occurs or not.
2218 		 */
2219 		nd.ni_cnd.cn_nameiop = LOOKUP;
2220 		nd.ni_cnd.cn_flags &= ~(LOCKPARENT | FOLLOW);
2221 		nd.ni_cnd.cn_flags |= (NOFOLLOW | LOCKLEAF);
2222 		nd.ni_cnd.cn_thread = curthread;
2223 		nd.ni_cnd.cn_cred = cred;
2224 		error = lookup(&nd);
2225 		nd.ni_dvp = NULL;
2226 
2227 		if (error == 0) {
2228 			bzero((caddr_t)fhp, sizeof(nfh));
2229 			fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
2230 			error = VOP_VPTOFH(nd.ni_vp, &fhp->fh_fid);
2231 			if (!error)
2232 				error = VOP_GETATTR(nd.ni_vp, vap, cred);
2233 			vput(nd.ni_vp);
2234 			nd.ni_vp = NULL;
2235 		}
2236 	    }
2237 	}
2238 out:
2239 	/*
2240 	 * These releases aren't strictly required, does even doing them
2241 	 * make any sense? XXX can nfsm_reply() block?
2242 	 */
2243 	if (pathcp) {
2244 		free(pathcp, M_TEMP);
2245 		pathcp = NULL;
2246 	}
2247 	if (dirp) {
2248 		vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
2249 		diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2250 		VOP_UNLOCK(dirp, 0);
2251 	}
2252 	if (nd.ni_startdir) {
2253 		vrele(nd.ni_startdir);
2254 		nd.ni_startdir = NULL;
2255 	}
2256 	nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2257 	if (v3) {
2258 		if (!error) {
2259 			nfsm_srvpostop_fh(fhp);
2260 			nfsm_srvpostop_attr(0, vap);
2261 		}
2262 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2263 	}
2264 	error = 0;
2265 	/* fall through */
2266 
2267 nfsmout:
2268 	NDFREE(&nd, NDF_ONLY_PNBUF);
2269 	if (nd.ni_dvp) {
2270 		if (nd.ni_dvp == nd.ni_vp)
2271 			vrele(nd.ni_dvp);
2272 		else
2273 			vput(nd.ni_dvp);
2274 	}
2275 	if (nd.ni_vp)
2276 		vrele(nd.ni_vp);
2277 	if (nd.ni_startdir)
2278 		vrele(nd.ni_startdir);
2279 	if (dirp)
2280 		vrele(dirp);
2281 	if (pathcp)
2282 		free(pathcp, M_TEMP);
2283 
2284 	vn_finished_write(mp);
2285 	return (error);
2286 }
2287 
2288 /*
2289  * nfs mkdir service
2290  */
2291 int
nfsrv_mkdir(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)2292 nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2293     struct mbuf **mrq)
2294 {
2295 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2296 	struct sockaddr *nam = nfsd->nd_nam;
2297 	caddr_t dpos = nfsd->nd_dpos;
2298 	struct ucred *cred = nfsd->nd_cr;
2299 	struct vattr va, dirfor, diraft;
2300 	struct vattr *vap = &va;
2301 	struct nfs_fattr *fp;
2302 	struct nameidata nd;
2303 	u_int32_t *tl;
2304 	caddr_t bpos;
2305 	int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2306 	int v3 = (nfsd->nd_flag & ND_NFSV3);
2307 	struct mbuf *mb, *mreq;
2308 	struct vnode *dirp = NULL;
2309 	int vpexcl = 0;
2310 	nfsfh_t nfh;
2311 	fhandle_t *fhp;
2312 	struct mount *mp = NULL;
2313 
2314 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2315 	ndclear(&nd);
2316 
2317 	fhp = &nfh.fh_generic;
2318 	nfsm_srvmtofh(fhp);
2319 	if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2320 		error = ESTALE;
2321 		goto out;
2322 	}
2323 	(void) vn_start_write(NULL, &mp, V_WAIT);
2324 	vfs_rel(mp);		/* The write holds a ref. */
2325 	nfsm_srvnamesiz(len);
2326 	nd.ni_cnd.cn_cred = cred;
2327 	nd.ni_cnd.cn_nameiop = CREATE;
2328 	nd.ni_cnd.cn_flags = LOCKPARENT | NOCACHE;
2329 
2330 	error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
2331 		&dirp, v3, &dirfor, &dirfor_ret, FALSE);
2332 	if (dirp && !v3) {
2333 		vrele(dirp);
2334 		dirp = NULL;
2335 	}
2336 	if (error) {
2337 		nfsm_reply(NFSX_WCCDATA(v3));
2338 		if (v3)
2339 			nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2340 		error = 0;
2341 		goto nfsmout;
2342 	}
2343 	VATTR_NULL(vap);
2344 	if (v3) {
2345 		nfsm_srvsattr(vap);
2346 	} else {
2347 		tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
2348 		vap->va_mode = nfstov_mode(*tl++);
2349 	}
2350 
2351 	/*
2352 	 * At this point nd.ni_dvp is referenced and exclusively locked and
2353 	 * nd.ni_vp, if it exists, is referenced but not locked.
2354 	 */
2355 
2356 	vap->va_type = VDIR;
2357 	if (nd.ni_vp != NULL) {
2358 		NDFREE(&nd, NDF_ONLY_PNBUF);
2359 		error = EEXIST;
2360 		goto out;
2361 	}
2362 
2363 	/*
2364 	 * Issue mkdir op.  Since SAVESTART is not set, the pathname
2365 	 * component is freed by the VOP call.  This will fill-in
2366 	 * nd.ni_vp, reference, and exclusively lock it.
2367 	 */
2368 	if (vap->va_mode == (mode_t)VNOVAL)
2369 		vap->va_mode = 0;
2370 	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
2371 	NDFREE(&nd, NDF_ONLY_PNBUF);
2372 	vpexcl = 1;
2373 
2374 	vput(nd.ni_dvp);
2375 	nd.ni_dvp = NULL;
2376 
2377 	if (!error) {
2378 		bzero((caddr_t)fhp, sizeof(nfh));
2379 		fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
2380 		error = VOP_VPTOFH(nd.ni_vp, &fhp->fh_fid);
2381 		if (!error)
2382 			error = VOP_GETATTR(nd.ni_vp, vap, cred);
2383 	}
2384 out:
2385 	if (dirp) {
2386 		if (dirp == nd.ni_dvp) {
2387 			diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2388 		} else {
2389 			/* Release existing locks to prevent deadlock. */
2390 			if (nd.ni_dvp) {
2391 				NDFREE(&nd, NDF_ONLY_PNBUF);
2392 				if (nd.ni_dvp == nd.ni_vp && vpexcl)
2393 					vrele(nd.ni_dvp);
2394 				else
2395 					vput(nd.ni_dvp);
2396 			}
2397 			if (nd.ni_vp) {
2398 				if (vpexcl)
2399 					vput(nd.ni_vp);
2400 				else
2401 					vrele(nd.ni_vp);
2402 			}
2403 			nd.ni_dvp = NULL;
2404 			nd.ni_vp = NULL;
2405 			vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
2406 			diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2407 			VOP_UNLOCK(dirp, 0);
2408 		}
2409 	}
2410 	nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2411 	if (v3) {
2412 		if (!error) {
2413 			nfsm_srvpostop_fh(fhp);
2414 			nfsm_srvpostop_attr(0, vap);
2415 		}
2416 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2417 	} else if (!error) {
2418 		/* v2 non-error case. */
2419 		nfsm_srvfhtom(fhp, v3);
2420 		fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
2421 		nfsm_srvfillattr(vap, fp);
2422 	}
2423 	error = 0;
2424 	/* fall through */
2425 
2426 nfsmout:
2427 	if (nd.ni_dvp) {
2428 		NDFREE(&nd, NDF_ONLY_PNBUF);
2429 		if (nd.ni_dvp == nd.ni_vp && vpexcl)
2430 			vrele(nd.ni_dvp);
2431 		else
2432 			vput(nd.ni_dvp);
2433 	}
2434 	if (nd.ni_vp) {
2435 		if (vpexcl)
2436 			vput(nd.ni_vp);
2437 		else
2438 			vrele(nd.ni_vp);
2439 	}
2440 	if (dirp)
2441 		vrele(dirp);
2442 	vn_finished_write(mp);
2443 	return (error);
2444 }
2445 
2446 /*
2447  * nfs rmdir service
2448  */
2449 int
nfsrv_rmdir(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)2450 nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2451     struct mbuf **mrq)
2452 {
2453 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2454 	struct sockaddr *nam = nfsd->nd_nam;
2455 	caddr_t dpos = nfsd->nd_dpos;
2456 	struct ucred *cred = nfsd->nd_cr;
2457 	caddr_t bpos;
2458 	int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2459 	int v3 = (nfsd->nd_flag & ND_NFSV3);
2460 	struct mbuf *mb, *mreq;
2461 	struct vnode *vp, *dirp = NULL;
2462 	struct vattr dirfor, diraft;
2463 	nfsfh_t nfh;
2464 	fhandle_t *fhp;
2465 	struct nameidata nd;
2466 	struct mount *mp = NULL;
2467 
2468 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2469 	ndclear(&nd);
2470 
2471 	fhp = &nfh.fh_generic;
2472 	nfsm_srvmtofh(fhp);
2473 	if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2474 		error = ESTALE;
2475 		goto out;
2476 	}
2477 	(void) vn_start_write(NULL, &mp, V_WAIT);
2478 	vfs_rel(mp);		/* The write holds a ref. */
2479 	nfsm_srvnamesiz(len);
2480 	nd.ni_cnd.cn_cred = cred;
2481 	nd.ni_cnd.cn_nameiop = DELETE;
2482 	nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
2483 	error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
2484 		&dirp, v3, &dirfor, &dirfor_ret, FALSE);
2485 	if (dirp && !v3) {
2486 		vrele(dirp);
2487 		dirp = NULL;
2488 	}
2489 	if (error) {
2490 		nfsm_reply(NFSX_WCCDATA(v3));
2491 		if (v3)
2492 			nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2493 		error = 0;
2494 		goto nfsmout;
2495 	}
2496 	vp = nd.ni_vp;
2497 	if (vp->v_type != VDIR) {
2498 		error = ENOTDIR;
2499 		goto out;
2500 	}
2501 	/*
2502 	 * No rmdir "." please.
2503 	 */
2504 	if (nd.ni_dvp == vp) {
2505 		error = EINVAL;
2506 		goto out;
2507 	}
2508 	/*
2509 	 * The root of a mounted filesystem cannot be deleted.
2510 	 */
2511 	if (vp->v_vflag & VV_ROOT)
2512 		error = EBUSY;
2513 out:
2514 	/*
2515 	 * Issue or abort op.  Since SAVESTART is not set, path name
2516 	 * component is freed by the VOP after either.
2517 	 */
2518 	if (!error)
2519 		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2520 	NDFREE(&nd, NDF_ONLY_PNBUF);
2521 
2522 	if (dirp) {
2523 		if (dirp == nd.ni_dvp)
2524 			diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2525 		else {
2526 			/* Release existing locks to prevent deadlock. */
2527 			if (nd.ni_dvp) {
2528 				if (nd.ni_dvp == nd.ni_vp)
2529 					vrele(nd.ni_dvp);
2530 				else
2531 					vput(nd.ni_dvp);
2532 			}
2533 			if (nd.ni_vp)
2534 				vput(nd.ni_vp);
2535 			nd.ni_dvp = NULL;
2536 			nd.ni_vp = NULL;
2537 			vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
2538 			diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2539 			VOP_UNLOCK(dirp, 0);
2540 		}
2541 	}
2542 	nfsm_reply(NFSX_WCCDATA(v3));
2543 	error = 0;
2544 	if (v3)
2545 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2546 	/* fall through */
2547 
2548 nfsmout:
2549 	NDFREE(&nd, NDF_ONLY_PNBUF);
2550 	if (nd.ni_dvp) {
2551 		if (nd.ni_dvp == nd.ni_vp)
2552 			vrele(nd.ni_dvp);
2553 		else
2554 			vput(nd.ni_dvp);
2555 	}
2556 	if (nd.ni_vp)
2557 		vput(nd.ni_vp);
2558 	if (dirp)
2559 		vrele(dirp);
2560 
2561 	vn_finished_write(mp);
2562 	return(error);
2563 }
2564 
2565 /*
2566  * nfs readdir service
2567  * - mallocs what it thinks is enough to read
2568  *	count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
2569  * - calls VOP_READDIR()
2570  * - loops around building the reply
2571  *	if the output generated exceeds count break out of loop
2572  *	The nfsm_clget macro is used here so that the reply will be packed
2573  *	tightly in mbuf clusters.
2574  * - it only knows that it has encountered eof when the VOP_READDIR()
2575  *	reads nothing
2576  * - as such one readdir rpc will return eof false although you are there
2577  *	and then the next will return eof
2578  * - it trims out records with d_fileno == 0
2579  *	this doesn't matter for Unix clients, but they might confuse clients
2580  *	for other os'.
2581  * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
2582  *	than requested, but this may not apply to all filesystems. For
2583  *	example, client NFS does not { although it is never remote mounted
2584  *	anyhow }
2585  *     The alternate call nfsrv_readdirplus() does lookups as well.
2586  * PS: The NFS protocol spec. does not clarify what the "count" byte
2587  *	argument is a count of.. just name strings and file id's or the
2588  *	entire reply rpc or ...
2589  *	I tried just file name and id sizes and it confused the Sun client,
2590  *	so I am using the full rpc size now. The "paranoia.." comment refers
2591  *	to including the status longwords that are not a part of the dir.
2592  *	"entry" structures, but are in the rpc.
2593  */
2594 struct flrep {
2595 	nfsuint64	fl_off;
2596 	u_int32_t	fl_postopok;
2597 	u_int32_t	fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
2598 	u_int32_t	fl_fhok;
2599 	u_int32_t	fl_fhsize;
2600 	u_int32_t	fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
2601 };
2602 
2603 int
nfsrv_readdir(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)2604 nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2605     struct mbuf **mrq)
2606 {
2607 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2608 	struct sockaddr *nam = nfsd->nd_nam;
2609 	caddr_t dpos = nfsd->nd_dpos;
2610 	struct ucred *cred = nfsd->nd_cr;
2611 	char *bp, *be;
2612 	struct mbuf *mp;
2613 	struct dirent *dp;
2614 	caddr_t cp;
2615 	u_int32_t *tl;
2616 	caddr_t bpos;
2617 	struct mbuf *mb, *mreq;
2618 	char *cpos, *cend, *rbuf;
2619 	struct vnode *vp = NULL;
2620 	struct vattr at;
2621 	nfsfh_t nfh;
2622 	fhandle_t *fhp;
2623 	struct uio io;
2624 	struct iovec iv;
2625 	int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
2626 	int siz, cnt, fullsiz, eofflag, rdonly, ncookies;
2627 	int v3 = (nfsd->nd_flag & ND_NFSV3);
2628 	u_quad_t off, toff, verf;
2629 	u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
2630 	int is_ufs;
2631 
2632 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2633 	fhp = &nfh.fh_generic;
2634 	nfsm_srvmtofh(fhp);
2635 	if (v3) {
2636 		tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED);
2637 		toff = fxdr_hyper(tl);
2638 		tl += 2;
2639 		verf = fxdr_hyper(tl);
2640 		tl += 2;
2641 	} else {
2642 		tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
2643 		toff = fxdr_unsigned(u_quad_t, *tl++);
2644 		verf = 0;	/* shut up gcc */
2645 	}
2646 	off = toff;
2647 	cnt = fxdr_unsigned(int, *tl);
2648 	siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
2649 	xfer = NFS_SRVMAXDATA(nfsd);
2650 	if (cnt > xfer)
2651 		cnt = xfer;
2652 	if (siz > xfer)
2653 		siz = xfer;
2654 	fullsiz = siz;
2655 	error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
2656 	if (!error && vp->v_type != VDIR) {
2657 		error = ENOTDIR;
2658 		vput(vp);
2659 		vp = NULL;
2660 	}
2661 	if (error) {
2662 		nfsm_reply(NFSX_UNSIGNED);
2663 		if (v3)
2664 			nfsm_srvpostop_attr(getret, &at);
2665 		error = 0;
2666 		goto nfsmout;
2667 	}
2668 
2669 	/*
2670 	 * Obtain lock on vnode for this section of the code
2671 	 */
2672 	if (v3) {
2673 		error = getret = VOP_GETATTR(vp, &at, cred);
2674 #if 0
2675 		/*
2676 		 * XXX This check may be too strict for Solaris 2.5 clients.
2677 		 */
2678 		if (!error && toff && verf && verf != at.va_filerev)
2679 			error = NFSERR_BAD_COOKIE;
2680 #endif
2681 	}
2682 	if (!error)
2683 		error = nfsrv_access(vp, VEXEC, cred, rdonly, 0);
2684 	if (error) {
2685 		vput(vp);
2686 		vp = NULL;
2687 		nfsm_reply(NFSX_POSTOPATTR(v3));
2688 		if (v3)
2689 			nfsm_srvpostop_attr(getret, &at);
2690 		error = 0;
2691 		goto nfsmout;
2692 	}
2693 	is_ufs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "ufs") == 0;
2694 	VOP_UNLOCK(vp, 0);
2695 
2696 	/*
2697 	 * end section.  Allocate rbuf and continue
2698 	 */
2699 	rbuf = malloc(siz, M_TEMP, M_WAITOK);
2700 again:
2701 	iv.iov_base = rbuf;
2702 	iv.iov_len = fullsiz;
2703 	io.uio_iov = &iv;
2704 	io.uio_iovcnt = 1;
2705 	io.uio_offset = (off_t)off;
2706 	io.uio_resid = fullsiz;
2707 	io.uio_segflg = UIO_SYSSPACE;
2708 	io.uio_rw = UIO_READ;
2709 	io.uio_td = NULL;
2710 	eofflag = 0;
2711 	if (cookies) {
2712 		free((caddr_t)cookies, M_TEMP);
2713 		cookies = NULL;
2714 	}
2715 	vn_lock(vp, LK_SHARED | LK_RETRY);
2716 	error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
2717 	off = (off_t)io.uio_offset;
2718 	if (!cookies && !error)
2719 		error = NFSERR_PERM;
2720 	if (v3) {
2721 		getret = VOP_GETATTR(vp, &at, cred);
2722 		if (!error)
2723 			error = getret;
2724 	}
2725 	VOP_UNLOCK(vp, 0);
2726 	if (error) {
2727 		vrele(vp);
2728 		vp = NULL;
2729 		free((caddr_t)rbuf, M_TEMP);
2730 		if (cookies)
2731 			free((caddr_t)cookies, M_TEMP);
2732 		nfsm_reply(NFSX_POSTOPATTR(v3));
2733 		if (v3)
2734 			nfsm_srvpostop_attr(getret, &at);
2735 		error = 0;
2736 		goto nfsmout;
2737 	}
2738 	if (io.uio_resid) {
2739 		siz -= io.uio_resid;
2740 
2741 		/*
2742 		 * If nothing read, return eof
2743 		 * rpc reply
2744 		 */
2745 		if (siz == 0) {
2746 			vrele(vp);
2747 			vp = NULL;
2748 			nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
2749 				2 * NFSX_UNSIGNED);
2750 			if (v3) {
2751 				nfsm_srvpostop_attr(getret, &at);
2752 				tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
2753 				txdr_hyper(at.va_filerev, tl);
2754 				tl += 2;
2755 			} else
2756 				tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
2757 			*tl++ = nfsrv_nfs_false;
2758 			*tl = nfsrv_nfs_true;
2759 			free((caddr_t)rbuf, M_TEMP);
2760 			free((caddr_t)cookies, M_TEMP);
2761 			error = 0;
2762 			goto nfsmout;
2763 		}
2764 	}
2765 
2766 	/*
2767 	 * Check for degenerate cases of nothing useful read.
2768 	 * If so go try again
2769 	 */
2770 	cpos = rbuf;
2771 	cend = rbuf + siz;
2772 	dp = (struct dirent *)cpos;
2773 	cookiep = cookies;
2774 	/*
2775 	 * For some reason FreeBSD's ufs_readdir() chooses to back the
2776 	 * directory offset up to a block boundary, so it is necessary to
2777 	 * skip over the records that precede the requested offset. This
2778 	 * requires the assumption that file offset cookies monotonically
2779 	 * increase.
2780 	 */
2781 	while (cpos < cend && ncookies > 0 &&
2782 		(dp->d_fileno == 0 || dp->d_type == DT_WHT ||
2783 		 (is_ufs == 1 && ((u_quad_t)(*cookiep)) <= toff))) {
2784 		cpos += dp->d_reclen;
2785 		dp = (struct dirent *)cpos;
2786 		cookiep++;
2787 		ncookies--;
2788 	}
2789 	if (cpos >= cend || ncookies == 0) {
2790 		toff = off;
2791 		siz = fullsiz;
2792 		goto again;
2793 	}
2794 
2795 	len = 3 * NFSX_UNSIGNED;	/* paranoia, probably can be 0 */
2796 	nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
2797 	if (v3) {
2798 		nfsm_srvpostop_attr(getret, &at);
2799 		tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
2800 		txdr_hyper(at.va_filerev, tl);
2801 	}
2802 	mp = mb;
2803 	bp = bpos;
2804 	be = bp + M_TRAILINGSPACE(mp);
2805 
2806 	/* Loop through the records and build reply */
2807 	while (cpos < cend && ncookies > 0) {
2808 		if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
2809 			nlen = dp->d_namlen;
2810 			rem = nfsm_rndup(nlen) - nlen;
2811 			len += (4 * NFSX_UNSIGNED + nlen + rem);
2812 			if (v3)
2813 				len += 2 * NFSX_UNSIGNED;
2814 			if (len > cnt) {
2815 				eofflag = 0;
2816 				break;
2817 			}
2818 			/*
2819 			 * Build the directory record xdr from
2820 			 * the dirent entry.
2821 			 */
2822 			nfsm_clget;
2823 			*tl = nfsrv_nfs_true;
2824 			bp += NFSX_UNSIGNED;
2825 			if (v3) {
2826 				nfsm_clget;
2827 				*tl = 0;
2828 				bp += NFSX_UNSIGNED;
2829 			}
2830 			nfsm_clget;
2831 			*tl = txdr_unsigned(dp->d_fileno);
2832 			bp += NFSX_UNSIGNED;
2833 			nfsm_clget;
2834 			*tl = txdr_unsigned(nlen);
2835 			bp += NFSX_UNSIGNED;
2836 
2837 			/* And loop around copying the name */
2838 			xfer = nlen;
2839 			cp = dp->d_name;
2840 			while (xfer > 0) {
2841 				nfsm_clget;
2842 				if ((bp+xfer) > be)
2843 					tsiz = be-bp;
2844 				else
2845 					tsiz = xfer;
2846 				bcopy(cp, bp, tsiz);
2847 				bp += tsiz;
2848 				xfer -= tsiz;
2849 				if (xfer > 0)
2850 					cp += tsiz;
2851 			}
2852 			/* And null pad to an int32_t boundary. */
2853 			for (i = 0; i < rem; i++)
2854 				*bp++ = '\0';
2855 			nfsm_clget;
2856 
2857 			/* Finish off the record */
2858 			if (v3) {
2859 				*tl = 0;
2860 				bp += NFSX_UNSIGNED;
2861 				nfsm_clget;
2862 			}
2863 			*tl = txdr_unsigned(*cookiep);
2864 			bp += NFSX_UNSIGNED;
2865 		}
2866 		cpos += dp->d_reclen;
2867 		dp = (struct dirent *)cpos;
2868 		cookiep++;
2869 		ncookies--;
2870 	}
2871 	vrele(vp);
2872 	vp = NULL;
2873 	nfsm_clget;
2874 	*tl = nfsrv_nfs_false;
2875 	bp += NFSX_UNSIGNED;
2876 	nfsm_clget;
2877 	if (eofflag)
2878 		*tl = nfsrv_nfs_true;
2879 	else
2880 		*tl = nfsrv_nfs_false;
2881 	bp += NFSX_UNSIGNED;
2882 	if (mp != mb) {
2883 		if (bp < be)
2884 			mp->m_len = bp - mtod(mp, caddr_t);
2885 	} else
2886 		mp->m_len += bp - bpos;
2887 	free((caddr_t)rbuf, M_TEMP);
2888 	free((caddr_t)cookies, M_TEMP);
2889 
2890 nfsmout:
2891 	if (vp)
2892 		vrele(vp);
2893 	return(error);
2894 }
2895 
2896 int
nfsrv_readdirplus(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)2897 nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2898     struct mbuf **mrq)
2899 {
2900 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2901 	struct sockaddr *nam = nfsd->nd_nam;
2902 	caddr_t dpos = nfsd->nd_dpos;
2903 	struct ucred *cred = nfsd->nd_cr;
2904 	char *bp, *be;
2905 	struct mbuf *mp;
2906 	struct dirent *dp;
2907 	caddr_t cp;
2908 	u_int32_t *tl;
2909 	caddr_t bpos;
2910 	struct mbuf *mb, *mreq;
2911 	char *cpos, *cend, *rbuf;
2912 	struct vnode *vp = NULL, *nvp;
2913 	struct flrep fl;
2914 	nfsfh_t nfh;
2915 	fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
2916 	struct uio io;
2917 	struct iovec iv;
2918 	struct vattr va, at, *vap = &va;
2919 	struct nfs_fattr *fp;
2920 	int len, nlen, rem, xfer, tsiz, i, error = 0, error1, getret = 1;
2921 	int vp_locked;
2922 	int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies;
2923 	u_quad_t off, toff, verf;
2924 	u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
2925 	int v3 = (nfsd->nd_flag & ND_NFSV3);
2926 	int usevget = 1;
2927 	struct componentname cn;
2928 	struct mount *mntp = NULL;
2929 	int is_ufs;
2930 
2931 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2932 	vp_locked = 0;
2933 	if (!v3)
2934 		panic("nfsrv_readdirplus: v3 proc called on a v2 connection");
2935 	fhp = &nfh.fh_generic;
2936 	nfsm_srvmtofh(fhp);
2937 	tl = nfsm_dissect_nonblock(u_int32_t *, 6 * NFSX_UNSIGNED);
2938 	toff = fxdr_hyper(tl);
2939 	tl += 2;
2940 	verf = fxdr_hyper(tl);
2941 	tl += 2;
2942 	siz = fxdr_unsigned(int, *tl++);
2943 	cnt = fxdr_unsigned(int, *tl);
2944 	off = toff;
2945 	siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
2946 	xfer = NFS_SRVMAXDATA(nfsd);
2947 	if (cnt > xfer)
2948 		cnt = xfer;
2949 	if (siz > xfer)
2950 		siz = xfer;
2951 	fullsiz = siz;
2952 	error = nfsrv_fhtovp(fhp, NFSRV_FLAG_BUSY, &vp, nfsd, slp,
2953 	    nam, &rdonly);
2954 	if (!error) {
2955 		vp_locked = 1;
2956 		mntp = vp->v_mount;
2957 		if (vp->v_type != VDIR) {
2958 			error = ENOTDIR;
2959 			vput(vp);
2960 			vp = NULL;
2961 			vp_locked = 0;
2962 		}
2963 	}
2964 	if (error) {
2965 		nfsm_reply(NFSX_UNSIGNED);
2966 		nfsm_srvpostop_attr(getret, &at);
2967 		error = 0;
2968 		goto nfsmout;
2969 	}
2970 	error = getret = VOP_GETATTR(vp, &at, cred);
2971 #if 0
2972 	/*
2973 	 * XXX This check may be too strict for Solaris 2.5 clients.
2974 	 */
2975 	if (!error && toff && verf && verf != at.va_filerev)
2976 		error = NFSERR_BAD_COOKIE;
2977 #endif
2978 	if (!error)
2979 		error = nfsrv_access(vp, VEXEC, cred, rdonly, 0);
2980 	if (error) {
2981 		vput(vp);
2982 		vp_locked = 0;
2983 		vp = NULL;
2984 		nfsm_reply(NFSX_V3POSTOPATTR);
2985 		nfsm_srvpostop_attr(getret, &at);
2986 		error = 0;
2987 		goto nfsmout;
2988 	}
2989 	is_ufs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "ufs") == 0;
2990 	VOP_UNLOCK(vp, 0);
2991 	vp_locked = 0;
2992 	rbuf = malloc(siz, M_TEMP, M_WAITOK);
2993 again:
2994 	iv.iov_base = rbuf;
2995 	iv.iov_len = fullsiz;
2996 	io.uio_iov = &iv;
2997 	io.uio_iovcnt = 1;
2998 	io.uio_offset = (off_t)off;
2999 	io.uio_resid = fullsiz;
3000 	io.uio_segflg = UIO_SYSSPACE;
3001 	io.uio_rw = UIO_READ;
3002 	io.uio_td = NULL;
3003 	eofflag = 0;
3004 	vp_locked = 1;
3005 	if (cookies) {
3006 		free((caddr_t)cookies, M_TEMP);
3007 		cookies = NULL;
3008 	}
3009 	vn_lock(vp, LK_SHARED | LK_RETRY);
3010 	error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
3011 	off = (u_quad_t)io.uio_offset;
3012 	getret = VOP_GETATTR(vp, &at, cred);
3013 	VOP_UNLOCK(vp, 0);
3014 	vp_locked = 0;
3015 	if (!cookies && !error)
3016 		error = NFSERR_PERM;
3017 	if (!error)
3018 		error = getret;
3019 	if (error) {
3020 		vrele(vp);
3021 		vp = NULL;
3022 		if (cookies)
3023 			free((caddr_t)cookies, M_TEMP);
3024 		free((caddr_t)rbuf, M_TEMP);
3025 		nfsm_reply(NFSX_V3POSTOPATTR);
3026 		nfsm_srvpostop_attr(getret, &at);
3027 		error = 0;
3028 		goto nfsmout;
3029 	}
3030 	if (io.uio_resid) {
3031 		siz -= io.uio_resid;
3032 
3033 		/*
3034 		 * If nothing read, return eof
3035 		 * rpc reply
3036 		 */
3037 		if (siz == 0) {
3038 			vrele(vp);
3039 			vp = NULL;
3040 			nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
3041 				2 * NFSX_UNSIGNED);
3042 			nfsm_srvpostop_attr(getret, &at);
3043 			tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
3044 			txdr_hyper(at.va_filerev, tl);
3045 			tl += 2;
3046 			*tl++ = nfsrv_nfs_false;
3047 			*tl = nfsrv_nfs_true;
3048 			free((caddr_t)cookies, M_TEMP);
3049 			free((caddr_t)rbuf, M_TEMP);
3050 			error = 0;
3051 			goto nfsmout;
3052 		}
3053 	}
3054 
3055 	/*
3056 	 * Check for degenerate cases of nothing useful read.
3057 	 * If so go try again
3058 	 */
3059 	cpos = rbuf;
3060 	cend = rbuf + siz;
3061 	dp = (struct dirent *)cpos;
3062 	cookiep = cookies;
3063 	/*
3064 	 * For some reason FreeBSD's ufs_readdir() chooses to back the
3065 	 * directory offset up to a block boundary, so it is necessary to
3066 	 * skip over the records that precede the requested offset. This
3067 	 * requires the assumption that file offset cookies monotonically
3068 	 * increase.
3069 	 */
3070 	while (cpos < cend && ncookies > 0 &&
3071 		(dp->d_fileno == 0 || dp->d_type == DT_WHT ||
3072 		 (is_ufs == 1 && ((u_quad_t)(*cookiep)) <= toff))) {
3073 		cpos += dp->d_reclen;
3074 		dp = (struct dirent *)cpos;
3075 		cookiep++;
3076 		ncookies--;
3077 	}
3078 	if (cpos >= cend || ncookies == 0) {
3079 		toff = off;
3080 		siz = fullsiz;
3081 		goto again;
3082 	}
3083 
3084 	dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
3085 	    2 * NFSX_UNSIGNED;
3086 	nfsm_reply(cnt);
3087 	nfsm_srvpostop_attr(getret, &at);
3088 	tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
3089 	txdr_hyper(at.va_filerev, tl);
3090 	mp = mb;
3091 	bp = bpos;
3092 	be = bp + M_TRAILINGSPACE(mp);
3093 
3094 	/* Loop through the records and build reply */
3095 	while (cpos < cend && ncookies > 0) {
3096 		if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
3097 			nlen = dp->d_namlen;
3098 			rem = nfsm_rndup(nlen)-nlen;
3099 
3100 			if (usevget) {
3101 				/*
3102 				 * For readdir_and_lookup get the vnode using
3103 				 * the file number.
3104 				 */
3105 				error = VFS_VGET(mntp, dp->d_fileno, LK_SHARED,
3106 				    &nvp);
3107 				if (error != 0 && error != EOPNOTSUPP) {
3108 					error = 0;
3109 					goto invalid;
3110 				} else if (error == EOPNOTSUPP) {
3111 					/*
3112 					 * VFS_VGET() not supported?
3113 					 * Let's switch to VOP_LOOKUP().
3114 					 */
3115 					error = 0;
3116 					usevget = 0;
3117 					cn.cn_nameiop = LOOKUP;
3118 					cn.cn_flags = ISLASTCN | NOFOLLOW | \
3119 					    LOCKSHARED | LOCKLEAF;
3120 					cn.cn_lkflags = LK_SHARED | LK_RETRY;
3121 					cn.cn_cred = cred;
3122 					cn.cn_thread = curthread;
3123 				}
3124 			}
3125 			if (!usevget) {
3126 				cn.cn_nameptr = dp->d_name;
3127 				cn.cn_namelen = dp->d_namlen;
3128 				if (dp->d_namlen == 2 &&
3129 				    dp->d_name[0] == '.' &&
3130 				    dp->d_name[1] == '.') {
3131 					cn.cn_flags |= ISDOTDOT;
3132 				} else {
3133 					cn.cn_flags &= ~ISDOTDOT;
3134 				}
3135 				if (!vp_locked) {
3136 					vn_lock(vp, LK_SHARED | LK_RETRY);
3137 					vp_locked = 1;
3138 				}
3139 				if ((vp->v_vflag & VV_ROOT) != 0 &&
3140 				    (cn.cn_flags & ISDOTDOT) != 0) {
3141 					vref(vp);
3142 					nvp = vp;
3143 				} else if (VOP_LOOKUP(vp, &nvp, &cn) != 0)
3144 					goto invalid;
3145 			}
3146 
3147 			bzero((caddr_t)nfhp, NFSX_V3FH);
3148 			nfhp->fh_fsid = nvp->v_mount->mnt_stat.f_fsid;
3149 			if ((error1 = VOP_VPTOFH(nvp, &nfhp->fh_fid)) == 0)
3150 				error1 = VOP_GETATTR(nvp, vap, cred);
3151 			if (!usevget && vp == nvp)
3152 				vunref(nvp);
3153 			else
3154 				vput(nvp);
3155 			nvp = NULL;
3156 			if (error1 != 0)
3157 				goto invalid;
3158 
3159 			/*
3160 			 * If either the dircount or maxcount will be
3161 			 * exceeded, get out now. Both of these lengths
3162 			 * are calculated conservatively, including all
3163 			 * XDR overheads.
3164 			 */
3165 			len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
3166 				NFSX_V3POSTOPATTR);
3167 			dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
3168 			if (len > cnt || dirlen > fullsiz) {
3169 				eofflag = 0;
3170 				break;
3171 			}
3172 
3173 			/*
3174 			 * Build the directory record xdr from
3175 			 * the dirent entry.
3176 			 */
3177 			fp = (struct nfs_fattr *)&fl.fl_fattr;
3178 			nfsm_srvfillattr(vap, fp);
3179 			fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
3180 			fl.fl_fhok = nfsrv_nfs_true;
3181 			fl.fl_postopok = nfsrv_nfs_true;
3182 			fl.fl_off.nfsuquad[0] = 0;
3183 			fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep);
3184 
3185 			nfsm_clget;
3186 			*tl = nfsrv_nfs_true;
3187 			bp += NFSX_UNSIGNED;
3188 			nfsm_clget;
3189 			*tl = 0;
3190 			bp += NFSX_UNSIGNED;
3191 			nfsm_clget;
3192 			*tl = txdr_unsigned(dp->d_fileno);
3193 			bp += NFSX_UNSIGNED;
3194 			nfsm_clget;
3195 			*tl = txdr_unsigned(nlen);
3196 			bp += NFSX_UNSIGNED;
3197 
3198 			/* And loop around copying the name */
3199 			xfer = nlen;
3200 			cp = dp->d_name;
3201 			while (xfer > 0) {
3202 				nfsm_clget;
3203 				if ((bp + xfer) > be)
3204 					tsiz = be - bp;
3205 				else
3206 					tsiz = xfer;
3207 				bcopy(cp, bp, tsiz);
3208 				bp += tsiz;
3209 				xfer -= tsiz;
3210 				if (xfer > 0)
3211 					cp += tsiz;
3212 			}
3213 			/* And null pad to an int32_t boundary. */
3214 			for (i = 0; i < rem; i++)
3215 				*bp++ = '\0';
3216 
3217 			/*
3218 			 * Now copy the flrep structure out.
3219 			 */
3220 			xfer = sizeof (struct flrep);
3221 			cp = (caddr_t)&fl;
3222 			while (xfer > 0) {
3223 				nfsm_clget;
3224 				if ((bp + xfer) > be)
3225 					tsiz = be - bp;
3226 				else
3227 					tsiz = xfer;
3228 				bcopy(cp, bp, tsiz);
3229 				bp += tsiz;
3230 				xfer -= tsiz;
3231 				if (xfer > 0)
3232 					cp += tsiz;
3233 			}
3234 		}
3235 invalid:
3236 		cpos += dp->d_reclen;
3237 		dp = (struct dirent *)cpos;
3238 		cookiep++;
3239 		ncookies--;
3240 	}
3241 	if (!usevget && vp_locked)
3242 		vput(vp);
3243 	else
3244 		vrele(vp);
3245 	vp = NULL;
3246 	nfsm_clget;
3247 	*tl = nfsrv_nfs_false;
3248 	bp += NFSX_UNSIGNED;
3249 	nfsm_clget;
3250 	if (eofflag)
3251 		*tl = nfsrv_nfs_true;
3252 	else
3253 		*tl = nfsrv_nfs_false;
3254 	bp += NFSX_UNSIGNED;
3255 	if (mp != mb) {
3256 		if (bp < be)
3257 			mp->m_len = bp - mtod(mp, caddr_t);
3258 	} else
3259 		mp->m_len += bp - bpos;
3260 	free((caddr_t)cookies, M_TEMP);
3261 	free((caddr_t)rbuf, M_TEMP);
3262 nfsmout:
3263 	if (vp)
3264 		vrele(vp);
3265 	if (mntp)
3266 		vfs_unbusy(mntp);
3267 	return(error);
3268 }
3269 
3270 /*
3271  * nfs commit service
3272  */
3273 int
nfsrv_commit(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)3274 nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3275     struct mbuf **mrq)
3276 {
3277 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3278 	struct sockaddr *nam = nfsd->nd_nam;
3279 	caddr_t dpos = nfsd->nd_dpos;
3280 	struct ucred *cred = nfsd->nd_cr;
3281 	struct vattr bfor, aft;
3282 	struct vnode *vp = NULL;
3283 	nfsfh_t nfh;
3284 	fhandle_t *fhp;
3285 	u_int32_t *tl;
3286 	caddr_t bpos;
3287 	int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt;
3288 	struct mbuf *mb, *mreq;
3289 	u_quad_t off;
3290 	struct mount *mp = NULL;
3291 	int v3 = (nfsd->nd_flag & ND_NFSV3);
3292 
3293 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3294 	if (!v3)
3295 		panic("nfsrv_commit: v3 proc called on a v2 connection");
3296 	fhp = &nfh.fh_generic;
3297 	nfsm_srvmtofh(fhp);
3298 	if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
3299 		error = ESTALE;
3300 		goto ereply;
3301 	}
3302 	(void) vn_start_write(NULL, &mp, V_WAIT);
3303 	vfs_rel(mp);		/* The write holds a ref. */
3304 	tl = nfsm_dissect_nonblock(u_int32_t *, 3 * NFSX_UNSIGNED);
3305 
3306 	/*
3307 	 * XXX At this time VOP_FSYNC() does not accept offset and byte
3308 	 * count parameters, so these arguments are useless (someday maybe).
3309 	 */
3310 	off = fxdr_hyper(tl);
3311 	tl += 2;
3312 	cnt = fxdr_unsigned(int, *tl);
3313 	error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
3314 	if (error) {
3315 		nfsm_reply(2 * NFSX_UNSIGNED);
3316 		nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
3317 		error = 0;
3318 		goto nfsmout;
3319 	}
3320 	for_ret = VOP_GETATTR(vp, &bfor, cred);
3321 
3322 	/*
3323 	 * RFC 1813 3.3.21: if count is 0, a flush from offset to the end of file
3324 	 * is done.  At this time VOP_FSYNC does not accept offset and byte count
3325 	 * parameters so call VOP_FSYNC the whole file for now.
3326 	 */
3327 	if (cnt == 0 || cnt > MAX_COMMIT_COUNT) {
3328 		/*
3329 		 * Give up and do the whole thing
3330 		 */
3331 		if (vp->v_object &&
3332 		   (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
3333 			VM_OBJECT_WLOCK(vp->v_object);
3334 			vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC);
3335 			VM_OBJECT_WUNLOCK(vp->v_object);
3336 		}
3337 		error = VOP_FSYNC(vp, MNT_WAIT, curthread);
3338 	} else {
3339 		/*
3340 		 * Locate and synchronously write any buffers that fall
3341 		 * into the requested range.  Note:  we are assuming that
3342 		 * f_iosize is a power of 2.
3343 		 */
3344 		int iosize = vp->v_mount->mnt_stat.f_iosize;
3345 		int iomask = iosize - 1;
3346 		struct bufobj *bo;
3347 		daddr_t lblkno;
3348 
3349 		/*
3350 		 * Align to iosize boundry, super-align to page boundry.
3351 		 */
3352 		if (off & iomask) {
3353 			cnt += off & iomask;
3354 			off &= ~(u_quad_t)iomask;
3355 		}
3356 		if (off & PAGE_MASK) {
3357 			cnt += off & PAGE_MASK;
3358 			off &= ~(u_quad_t)PAGE_MASK;
3359 		}
3360 		lblkno = off / iosize;
3361 
3362 		if (vp->v_object &&
3363 		   (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
3364 			VM_OBJECT_WLOCK(vp->v_object);
3365 			vm_object_page_clean(vp->v_object, off, off + cnt,
3366 			    OBJPC_SYNC);
3367 			VM_OBJECT_WUNLOCK(vp->v_object);
3368 		}
3369 
3370 		bo = &vp->v_bufobj;
3371 		BO_LOCK(bo);
3372 		while (cnt > 0) {
3373 			struct buf *bp;
3374 
3375 			/*
3376 			 * If we have a buffer and it is marked B_DELWRI we
3377 			 * have to lock and write it.  Otherwise the prior
3378 			 * write is assumed to have already been committed.
3379 			 *
3380 			 * gbincore() can return invalid buffers now so we
3381 			 * have to check that bit as well (though B_DELWRI
3382 			 * should not be set if B_INVAL is set there could be
3383 			 * a race here since we haven't locked the buffer).
3384 			 */
3385 			if ((bp = gbincore(&vp->v_bufobj, lblkno)) != NULL) {
3386 				if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL |
3387 				    LK_INTERLOCK, BO_LOCKPTR(bo)) == ENOLCK) {
3388 					BO_LOCK(bo);
3389 					continue; /* retry */
3390 				}
3391 			    	if ((bp->b_flags & (B_DELWRI|B_INVAL)) ==
3392 				    B_DELWRI) {
3393 					bremfree(bp);
3394 					bp->b_flags &= ~B_ASYNC;
3395 					bwrite(bp);
3396 					++nfs_commit_miss;
3397 				} else
3398 					BUF_UNLOCK(bp);
3399 				BO_LOCK(bo);
3400 			}
3401 			++nfs_commit_blks;
3402 			if (cnt < iosize)
3403 				break;
3404 			cnt -= iosize;
3405 			++lblkno;
3406 		}
3407 		BO_UNLOCK(bo);
3408 	}
3409 
3410 	aft_ret = VOP_GETATTR(vp, &aft, cred);
3411 	vput(vp);
3412 	vp = NULL;
3413 ereply:
3414 	nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
3415 	nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
3416 	if (!error) {
3417 		tl = nfsm_build(u_int32_t *, NFSX_V3WRITEVERF);
3418 		if (nfsver.tv_sec == 0)
3419 			nfsver = boottime;
3420 		*tl++ = txdr_unsigned(nfsver.tv_sec);
3421 		*tl = txdr_unsigned(nfsver.tv_usec);
3422 	} else {
3423 		error = 0;
3424 	}
3425 nfsmout:
3426 	if (vp)
3427 		vput(vp);
3428 	vn_finished_write(mp);
3429 	return(error);
3430 }
3431 
3432 /*
3433  * nfs statfs service
3434  */
3435 int
nfsrv_statfs(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)3436 nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3437     struct mbuf **mrq)
3438 {
3439 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3440 	struct sockaddr *nam = nfsd->nd_nam;
3441 	caddr_t dpos = nfsd->nd_dpos;
3442 	struct ucred *cred = nfsd->nd_cr;
3443 	struct statfs *sf;
3444 	struct nfs_statfs *sfp;
3445 	caddr_t bpos;
3446 	int error = 0, rdonly, getret = 1;
3447 	int v3 = (nfsd->nd_flag & ND_NFSV3);
3448 	struct mbuf *mb, *mreq;
3449 	struct vnode *vp = NULL;
3450 	struct vattr at;
3451 	nfsfh_t nfh;
3452 	fhandle_t *fhp;
3453 	struct statfs statfs;
3454 	u_quad_t tval;
3455 
3456 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3457 	fhp = &nfh.fh_generic;
3458 	nfsm_srvmtofh(fhp);
3459 	error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
3460 	if (error) {
3461 		nfsm_reply(NFSX_UNSIGNED);
3462 		if (v3)
3463 			nfsm_srvpostop_attr(getret, &at);
3464 		error = 0;
3465 		goto nfsmout;
3466 	}
3467 	sf = &statfs;
3468 	error = VFS_STATFS(vp->v_mount, sf);
3469 	getret = VOP_GETATTR(vp, &at, cred);
3470 	vput(vp);
3471 	vp = NULL;
3472 	nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
3473 	if (v3)
3474 		nfsm_srvpostop_attr(getret, &at);
3475 	if (error) {
3476 		error = 0;
3477 		goto nfsmout;
3478 	}
3479 	sfp = nfsm_build(struct nfs_statfs *, NFSX_STATFS(v3));
3480 	if (v3) {
3481 		tval = (u_quad_t)sf->f_blocks;
3482 		tval *= (u_quad_t)sf->f_bsize;
3483 		txdr_hyper(tval, &sfp->sf_tbytes);
3484 		tval = (u_quad_t)sf->f_bfree;
3485 		tval *= (u_quad_t)sf->f_bsize;
3486 		txdr_hyper(tval, &sfp->sf_fbytes);
3487 		/*
3488 		 * Don't send negative values for available space,
3489 		 * since this field is unsigned in the NFS protocol.
3490 		 * Otherwise, the client would see absurdly high
3491 		 * numbers for free space.
3492 		 */
3493 		if (sf->f_bavail < 0)
3494 			tval = 0;
3495 		else
3496 			tval = (u_quad_t)sf->f_bavail;
3497 		tval *= (u_quad_t)sf->f_bsize;
3498 		txdr_hyper(tval, &sfp->sf_abytes);
3499 		sfp->sf_tfiles.nfsuquad[0] = 0;
3500 		sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files);
3501 		sfp->sf_ffiles.nfsuquad[0] = 0;
3502 		sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
3503 		sfp->sf_afiles.nfsuquad[0] = 0;
3504 		sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
3505 		sfp->sf_invarsec = 0;
3506 	} else {
3507 		sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
3508 		sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
3509 		sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
3510 		sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
3511 		if (sf->f_bavail < 0)
3512 			sfp->sf_bavail = 0;
3513 		else
3514 			sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
3515 	}
3516 nfsmout:
3517 	if (vp)
3518 		vput(vp);
3519 	return(error);
3520 }
3521 
3522 /*
3523  * nfs fsinfo service
3524  */
3525 int
nfsrv_fsinfo(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)3526 nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3527     struct mbuf **mrq)
3528 {
3529 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3530 	struct sockaddr *nam = nfsd->nd_nam;
3531 	caddr_t dpos = nfsd->nd_dpos;
3532 	struct ucred *cred = nfsd->nd_cr;
3533 	struct nfsv3_fsinfo *sip;
3534 	caddr_t bpos;
3535 	int error = 0, rdonly, getret = 1, pref;
3536 	struct mbuf *mb, *mreq;
3537 	struct vnode *vp = NULL;
3538 	struct vattr at;
3539 	nfsfh_t nfh;
3540 	fhandle_t *fhp;
3541 	u_quad_t maxfsize;
3542 	struct statfs sb;
3543 	int v3 = (nfsd->nd_flag & ND_NFSV3);
3544 
3545 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3546 	if (!v3)
3547 		panic("nfsrv_fsinfo: v3 proc called on a v2 connection");
3548 	fhp = &nfh.fh_generic;
3549 	nfsm_srvmtofh(fhp);
3550 	error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
3551 	if (error) {
3552 		nfsm_reply(NFSX_UNSIGNED);
3553 		nfsm_srvpostop_attr(getret, &at);
3554 		error = 0;
3555 		goto nfsmout;
3556 	}
3557 
3558 	/* XXX Try to make a guess on the max file size. */
3559 	VFS_STATFS(vp->v_mount, &sb);
3560 	maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
3561 
3562 	getret = VOP_GETATTR(vp, &at, cred);
3563 	vput(vp);
3564 	vp = NULL;
3565 	nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
3566 	nfsm_srvpostop_attr(getret, &at);
3567 	sip = nfsm_build(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
3568 
3569 	/*
3570 	 * XXX
3571 	 * There should be filesystem VFS OP(s) to get this information.
3572 	 * For now, assume ufs.
3573 	 */
3574 	pref = NFS_SRVMAXDATA(nfsd);
3575 	sip->fs_rtmax = txdr_unsigned(pref);
3576 	sip->fs_rtpref = txdr_unsigned(pref);
3577 	sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
3578 	sip->fs_wtmax = txdr_unsigned(pref);
3579 	sip->fs_wtpref = txdr_unsigned(pref);
3580 	sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
3581 	sip->fs_dtpref = txdr_unsigned(pref);
3582 	txdr_hyper(maxfsize, &sip->fs_maxfilesize);
3583 	sip->fs_timedelta.nfsv3_sec = 0;
3584 	sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
3585 	sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
3586 		NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
3587 		NFSV3FSINFO_CANSETTIME);
3588 nfsmout:
3589 	if (vp)
3590 		vput(vp);
3591 	return(error);
3592 }
3593 
3594 /*
3595  * nfs pathconf service
3596  */
3597 int
nfsrv_pathconf(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)3598 nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3599     struct mbuf **mrq)
3600 {
3601 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3602 	struct sockaddr *nam = nfsd->nd_nam;
3603 	caddr_t dpos = nfsd->nd_dpos;
3604 	struct ucred *cred = nfsd->nd_cr;
3605 	struct nfsv3_pathconf *pc;
3606 	caddr_t bpos;
3607 	int error = 0, rdonly, getret = 1;
3608 	register_t linkmax, namemax, chownres, notrunc;
3609 	struct mbuf *mb, *mreq;
3610 	struct vnode *vp = NULL;
3611 	struct vattr at;
3612 	nfsfh_t nfh;
3613 	fhandle_t *fhp;
3614 	int v3 = (nfsd->nd_flag & ND_NFSV3);
3615 
3616 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3617 	if (!v3)
3618 		panic("nfsrv_pathconf: v3 proc called on a v2 connection");
3619 	fhp = &nfh.fh_generic;
3620 	nfsm_srvmtofh(fhp);
3621 	error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
3622 	if (error) {
3623 		nfsm_reply(NFSX_UNSIGNED);
3624 		nfsm_srvpostop_attr(getret, &at);
3625 		error = 0;
3626 		goto nfsmout;
3627 	}
3628 	error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
3629 	if (!error)
3630 		error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
3631 	if (!error)
3632 		error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
3633 	if (!error)
3634 		error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &notrunc);
3635 	getret = VOP_GETATTR(vp, &at, cred);
3636 	vput(vp);
3637 	vp = NULL;
3638 	nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
3639 	nfsm_srvpostop_attr(getret, &at);
3640 	if (error) {
3641 		error = 0;
3642 		goto nfsmout;
3643 	}
3644 	pc = nfsm_build(struct nfsv3_pathconf *, NFSX_V3PATHCONF);
3645 
3646 	pc->pc_linkmax = txdr_unsigned(linkmax);
3647 	pc->pc_namemax = txdr_unsigned(namemax);
3648 	pc->pc_notrunc = txdr_unsigned(notrunc);
3649 	pc->pc_chownrestricted = txdr_unsigned(chownres);
3650 
3651 	/*
3652 	 * These should probably be supported by VOP_PATHCONF(), but
3653 	 * until msdosfs is exportable (why would you want to?), the
3654 	 * Unix defaults should be ok.
3655 	 */
3656 	pc->pc_caseinsensitive = nfsrv_nfs_false;
3657 	pc->pc_casepreserving = nfsrv_nfs_true;
3658 nfsmout:
3659 	if (vp)
3660 		vput(vp);
3661 	return(error);
3662 }
3663 
3664 /*
3665  * Null operation, used by clients to ping server
3666  */
3667 /* ARGSUSED */
3668 int
nfsrv_null(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)3669 nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3670     struct mbuf **mrq)
3671 {
3672 	struct mbuf *mrep = nfsd->nd_mrep;
3673 	caddr_t bpos;
3674 	int error = NFSERR_RETVOID;
3675 	struct mbuf *mb, *mreq;
3676 
3677 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3678 	nfsm_reply(0);
3679 nfsmout:
3680 	return (error);
3681 }
3682 
3683 /*
3684  * No operation, used for obsolete procedures
3685  */
3686 /* ARGSUSED */
3687 int
nfsrv_noop(struct nfsrv_descript * nfsd,struct nfssvc_sock * slp,struct mbuf ** mrq)3688 nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3689     struct mbuf **mrq)
3690 {
3691 	struct mbuf *mrep = nfsd->nd_mrep;
3692 	caddr_t bpos;
3693 	int error;
3694 	struct mbuf *mb, *mreq;
3695 
3696 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3697 	if (nfsd->nd_repstat)
3698 		error = nfsd->nd_repstat;
3699 	else
3700 		error = EPROCUNAVAIL;
3701 	nfsm_reply(0);
3702 	error = 0;
3703 nfsmout:
3704 	return (error);
3705 }
3706 
3707 /*
3708  * Perform access checking for vnodes obtained from file handles that would
3709  * refer to files already opened by a Unix client. You cannot just use
3710  * vn_writechk() and VOP_ACCESS() for two reasons.
3711  * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write
3712  *     case.
3713  * 2 - The owner is to be given access irrespective of mode bits for some
3714  *     operations, so that processes that chmod after opening a file don't
3715  *     break. I don't like this because it opens a security hole, but since
3716  *     the nfs server opens a security hole the size of a barn door anyhow,
3717  *     what the heck.
3718  *
3719  * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
3720  * will return EPERM instead of EACCES. EPERM is always an error.
3721  */
3722 static int
nfsrv_access(struct vnode * vp,accmode_t accmode,struct ucred * cred,int rdonly,int override)3723 nfsrv_access(struct vnode *vp, accmode_t accmode, struct ucred *cred,
3724     int rdonly, int override)
3725 {
3726 	struct vattr vattr;
3727 	int error;
3728 
3729 	nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3730 
3731 	if (accmode & VWRITE) {
3732 		/* Just vn_writechk() changed to check rdonly */
3733 		/*
3734 		 * Disallow write attempts on read-only filesystems;
3735 		 * unless the file is a socket or a block or character
3736 		 * device resident on the filesystem.
3737 		 */
3738 		if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3739 			switch (vp->v_type) {
3740 			case VREG:
3741 			case VDIR:
3742 			case VLNK:
3743 				return (EROFS);
3744 			default:
3745 				break;
3746 			}
3747 		}
3748 		/*
3749 		 * If there's shared text associated with
3750 		 * the inode, we can't allow writing.
3751 		 */
3752 		if (VOP_IS_TEXT(vp))
3753 			return (ETXTBSY);
3754 	}
3755 
3756 	error = VOP_GETATTR(vp, &vattr, cred);
3757 	if (error)
3758 		return (error);
3759 	error = VOP_ACCESS(vp, accmode, cred, curthread);
3760 	/*
3761 	 * Allow certain operations for the owner (reads and writes
3762 	 * on files that are already open).
3763 	 */
3764 	if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
3765 		error = 0;
3766 	return (error);
3767 }
3768