]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/fs/nfsserver/nfs_nfsdsubs.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / fs / nfsserver / nfs_nfsdsubs.c
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  */
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 #ifndef APPLEKEXT
38 /*
39  * These functions support the macros and help fiddle mbuf chains for
40  * the nfs op functions. They do things like create the rpc header and
41  * copy data between mbuf chains and uio lists.
42  */
43 #include <fs/nfs/nfsport.h>
44
45 extern u_int32_t newnfs_true, newnfs_false;
46 extern int nfs_pubfhset;
47 extern struct nfsclienthashhead nfsclienthash[NFSCLIENTHASHSIZE];
48 extern struct nfslockhashhead nfslockhash[NFSLOCKHASHSIZE];
49 extern int nfsrv_useacl;
50 extern uid_t nfsrv_defaultuid;
51 extern gid_t nfsrv_defaultgid;
52
53 char nfs_v2pubfh[NFSX_V2FH];
54 static nfstype newnfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK,
55     NFNON, NFCHR, NFNON };
56 extern nfstype nfsv34_type[9];
57 #endif  /* !APPLEKEXT */
58
59 static char nfsrv_hexdigit(char, int *);
60
61 /*
62  * Maps errno values to nfs error numbers.
63  * Use NFSERR_IO as the catch all for ones not specifically defined in
64  * RFC 1094.
65  */
66 static u_char nfsrv_v2errmap[ELAST] = {
67   NFSERR_PERM,  NFSERR_NOENT,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
68   NFSERR_NXIO,  NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
69   NFSERR_IO,    NFSERR_IO,      NFSERR_ACCES,   NFSERR_IO,      NFSERR_IO,
70   NFSERR_IO,    NFSERR_EXIST,   NFSERR_IO,      NFSERR_NODEV,   NFSERR_NOTDIR,
71   NFSERR_ISDIR, NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
72   NFSERR_IO,    NFSERR_FBIG,    NFSERR_NOSPC,   NFSERR_IO,      NFSERR_ROFS,
73   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
74   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
75   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
76   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
77   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
78   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
79   NFSERR_IO,    NFSERR_IO,      NFSERR_NAMETOL, NFSERR_IO,      NFSERR_IO,
80   NFSERR_NOTEMPTY, NFSERR_IO,   NFSERR_IO,      NFSERR_DQUOT,   NFSERR_STALE,
81   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
82   NFSERR_IO,    NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
83   NFSERR_IO,
84 };
85
86 /*
87  * Maps errno values to nfs error numbers.
88  * Although it is not obvious whether or not NFS clients really care if
89  * a returned error value is in the specified list for the procedure, the
90  * safest thing to do is filter them appropriately. For Version 2, the
91  * X/Open XNFS document is the only specification that defines error values
92  * for each RPC (The RFC simply lists all possible error values for all RPCs),
93  * so I have decided to not do this for Version 2.
94  * The first entry is the default error return and the rest are the valid
95  * errors for that RPC in increasing numeric order.
96  */
97 static short nfsv3err_null[] = {
98         0,
99         0,
100 };
101
102 static short nfsv3err_getattr[] = {
103         NFSERR_IO,
104         NFSERR_IO,
105         NFSERR_STALE,
106         NFSERR_BADHANDLE,
107         NFSERR_SERVERFAULT,
108         NFSERR_DELAY,
109         0,
110 };
111
112 static short nfsv3err_setattr[] = {
113         NFSERR_IO,
114         NFSERR_ACCES,
115         NFSERR_PERM,
116         NFSERR_IO,
117         NFSERR_INVAL,
118         NFSERR_NOSPC,
119         NFSERR_ROFS,
120         NFSERR_DQUOT,
121         NFSERR_STALE,
122         NFSERR_BADHANDLE,
123         NFSERR_NOT_SYNC,
124         NFSERR_SERVERFAULT,
125         NFSERR_DELAY,
126         0,
127 };
128
129 static short nfsv3err_lookup[] = {
130         NFSERR_IO,
131         NFSERR_NOENT,
132         NFSERR_ACCES,
133         NFSERR_NAMETOL,
134         NFSERR_IO,
135         NFSERR_NOTDIR,
136         NFSERR_STALE,
137         NFSERR_BADHANDLE,
138         NFSERR_SERVERFAULT,
139         NFSERR_DELAY,
140         0,
141 };
142
143 static short nfsv3err_access[] = {
144         NFSERR_IO,
145         NFSERR_IO,
146         NFSERR_STALE,
147         NFSERR_BADHANDLE,
148         NFSERR_SERVERFAULT,
149         NFSERR_DELAY,
150         0,
151 };
152
153 static short nfsv3err_readlink[] = {
154         NFSERR_IO,
155         NFSERR_IO,
156         NFSERR_ACCES,
157         NFSERR_INVAL,
158         NFSERR_STALE,
159         NFSERR_BADHANDLE,
160         NFSERR_NOTSUPP,
161         NFSERR_SERVERFAULT,
162         NFSERR_DELAY,
163         0,
164 };
165
166 static short nfsv3err_read[] = {
167         NFSERR_IO,
168         NFSERR_IO,
169         NFSERR_NXIO,
170         NFSERR_ACCES,
171         NFSERR_INVAL,
172         NFSERR_STALE,
173         NFSERR_BADHANDLE,
174         NFSERR_SERVERFAULT,
175         NFSERR_DELAY,
176         0,
177 };
178
179 static short nfsv3err_write[] = {
180         NFSERR_IO,
181         NFSERR_IO,
182         NFSERR_ACCES,
183         NFSERR_NOSPC,
184         NFSERR_INVAL,
185         NFSERR_FBIG,
186         NFSERR_ROFS,
187         NFSERR_DQUOT,
188         NFSERR_STALE,
189         NFSERR_BADHANDLE,
190         NFSERR_SERVERFAULT,
191         NFSERR_DELAY,
192         0,
193 };
194
195 static short nfsv3err_create[] = {
196         NFSERR_IO,
197         NFSERR_EXIST,
198         NFSERR_NAMETOL,
199         NFSERR_ACCES,
200         NFSERR_IO,
201         NFSERR_NOTDIR,
202         NFSERR_NOSPC,
203         NFSERR_ROFS,
204         NFSERR_DQUOT,
205         NFSERR_STALE,
206         NFSERR_BADHANDLE,
207         NFSERR_NOTSUPP,
208         NFSERR_SERVERFAULT,
209         NFSERR_DELAY,
210         0,
211 };
212
213 static short nfsv3err_mkdir[] = {
214         NFSERR_IO,
215         NFSERR_EXIST,
216         NFSERR_ACCES,
217         NFSERR_NAMETOL,
218         NFSERR_IO,
219         NFSERR_NOTDIR,
220         NFSERR_NOSPC,
221         NFSERR_ROFS,
222         NFSERR_DQUOT,
223         NFSERR_STALE,
224         NFSERR_BADHANDLE,
225         NFSERR_NOTSUPP,
226         NFSERR_SERVERFAULT,
227         NFSERR_DELAY,
228         0,
229 };
230
231 static short nfsv3err_symlink[] = {
232         NFSERR_IO,
233         NFSERR_ACCES,
234         NFSERR_EXIST,
235         NFSERR_NAMETOL,
236         NFSERR_NOSPC,
237         NFSERR_IO,
238         NFSERR_NOTDIR,
239         NFSERR_ROFS,
240         NFSERR_DQUOT,
241         NFSERR_STALE,
242         NFSERR_BADHANDLE,
243         NFSERR_NOTSUPP,
244         NFSERR_SERVERFAULT,
245         NFSERR_DELAY,
246         0,
247 };
248
249 static short nfsv3err_mknod[] = {
250         NFSERR_IO,
251         NFSERR_ACCES,
252         NFSERR_EXIST,
253         NFSERR_NAMETOL,
254         NFSERR_NOSPC,
255         NFSERR_IO,
256         NFSERR_NOTDIR,
257         NFSERR_ROFS,
258         NFSERR_DQUOT,
259         NFSERR_STALE,
260         NFSERR_BADHANDLE,
261         NFSERR_NOTSUPP,
262         NFSERR_SERVERFAULT,
263         NFSERR_DELAY,
264         NFSERR_BADTYPE,
265         0,
266 };
267
268 static short nfsv3err_remove[] = {
269         NFSERR_IO,
270         NFSERR_NOENT,
271         NFSERR_ACCES,
272         NFSERR_NAMETOL,
273         NFSERR_IO,
274         NFSERR_NOTDIR,
275         NFSERR_ROFS,
276         NFSERR_STALE,
277         NFSERR_BADHANDLE,
278         NFSERR_SERVERFAULT,
279         NFSERR_DELAY,
280         0,
281 };
282
283 static short nfsv3err_rmdir[] = {
284         NFSERR_IO,
285         NFSERR_NOENT,
286         NFSERR_ACCES,
287         NFSERR_NOTDIR,
288         NFSERR_NAMETOL,
289         NFSERR_IO,
290         NFSERR_EXIST,
291         NFSERR_INVAL,
292         NFSERR_ROFS,
293         NFSERR_NOTEMPTY,
294         NFSERR_STALE,
295         NFSERR_BADHANDLE,
296         NFSERR_NOTSUPP,
297         NFSERR_SERVERFAULT,
298         NFSERR_DELAY,
299         0,
300 };
301
302 static short nfsv3err_rename[] = {
303         NFSERR_IO,
304         NFSERR_NOENT,
305         NFSERR_ACCES,
306         NFSERR_EXIST,
307         NFSERR_NAMETOL,
308         NFSERR_XDEV,
309         NFSERR_IO,
310         NFSERR_NOTDIR,
311         NFSERR_ISDIR,
312         NFSERR_INVAL,
313         NFSERR_NOSPC,
314         NFSERR_ROFS,
315         NFSERR_MLINK,
316         NFSERR_NOTEMPTY,
317         NFSERR_DQUOT,
318         NFSERR_STALE,
319         NFSERR_BADHANDLE,
320         NFSERR_NOTSUPP,
321         NFSERR_SERVERFAULT,
322         NFSERR_DELAY,
323         0,
324 };
325
326 static short nfsv3err_link[] = {
327         NFSERR_IO,
328         NFSERR_ACCES,
329         NFSERR_EXIST,
330         NFSERR_NAMETOL,
331         NFSERR_IO,
332         NFSERR_XDEV,
333         NFSERR_NOTDIR,
334         NFSERR_INVAL,
335         NFSERR_NOSPC,
336         NFSERR_ROFS,
337         NFSERR_MLINK,
338         NFSERR_DQUOT,
339         NFSERR_STALE,
340         NFSERR_BADHANDLE,
341         NFSERR_NOTSUPP,
342         NFSERR_SERVERFAULT,
343         NFSERR_DELAY,
344         0,
345 };
346
347 static short nfsv3err_readdir[] = {
348         NFSERR_IO,
349         NFSERR_ACCES,
350         NFSERR_NOTDIR,
351         NFSERR_IO,
352         NFSERR_STALE,
353         NFSERR_BADHANDLE,
354         NFSERR_BAD_COOKIE,
355         NFSERR_TOOSMALL,
356         NFSERR_SERVERFAULT,
357         NFSERR_DELAY,
358         0,
359 };
360
361 static short nfsv3err_readdirplus[] = {
362         NFSERR_IO,
363         NFSERR_ACCES,
364         NFSERR_NOTDIR,
365         NFSERR_IO,
366         NFSERR_STALE,
367         NFSERR_BADHANDLE,
368         NFSERR_BAD_COOKIE,
369         NFSERR_NOTSUPP,
370         NFSERR_TOOSMALL,
371         NFSERR_SERVERFAULT,
372         NFSERR_DELAY,
373         0,
374 };
375
376 static short nfsv3err_fsstat[] = {
377         NFSERR_IO,
378         NFSERR_IO,
379         NFSERR_STALE,
380         NFSERR_BADHANDLE,
381         NFSERR_SERVERFAULT,
382         NFSERR_DELAY,
383         0,
384 };
385
386 static short nfsv3err_fsinfo[] = {
387         NFSERR_STALE,
388         NFSERR_STALE,
389         NFSERR_BADHANDLE,
390         NFSERR_SERVERFAULT,
391         NFSERR_DELAY,
392         0,
393 };
394
395 static short nfsv3err_pathconf[] = {
396         NFSERR_STALE,
397         NFSERR_STALE,
398         NFSERR_BADHANDLE,
399         NFSERR_SERVERFAULT,
400         NFSERR_DELAY,
401         0,
402 };
403
404 static short nfsv3err_commit[] = {
405         NFSERR_IO,
406         NFSERR_IO,
407         NFSERR_STALE,
408         NFSERR_BADHANDLE,
409         NFSERR_SERVERFAULT,
410         NFSERR_DELAY,
411         0,
412 };
413
414 static short *nfsrv_v3errmap[] = {
415         nfsv3err_null,
416         nfsv3err_getattr,
417         nfsv3err_setattr,
418         nfsv3err_lookup,
419         nfsv3err_access,
420         nfsv3err_readlink,
421         nfsv3err_read,
422         nfsv3err_write,
423         nfsv3err_create,
424         nfsv3err_mkdir,
425         nfsv3err_symlink,
426         nfsv3err_mknod,
427         nfsv3err_remove,
428         nfsv3err_rmdir,
429         nfsv3err_rename,
430         nfsv3err_link,
431         nfsv3err_readdir,
432         nfsv3err_readdirplus,
433         nfsv3err_fsstat,
434         nfsv3err_fsinfo,
435         nfsv3err_pathconf,
436         nfsv3err_commit,
437 };
438
439 /*
440  * And the same for V4.
441  */
442 static short nfsv4err_null[] = {
443         0,
444         0,
445 };
446
447 static short nfsv4err_access[] = {
448         NFSERR_IO,
449         NFSERR_ACCES,
450         NFSERR_BADHANDLE,
451         NFSERR_BADXDR,
452         NFSERR_DELAY,
453         NFSERR_FHEXPIRED,
454         NFSERR_INVAL,
455         NFSERR_IO,
456         NFSERR_MOVED,
457         NFSERR_NOFILEHANDLE,
458         NFSERR_RESOURCE,
459         NFSERR_SERVERFAULT,
460         NFSERR_STALE,
461         0,
462 };
463
464 static short nfsv4err_close[] = {
465         NFSERR_EXPIRED,
466         NFSERR_ADMINREVOKED,
467         NFSERR_BADHANDLE,
468         NFSERR_BADSEQID,
469         NFSERR_BADSTATEID,
470         NFSERR_BADXDR,
471         NFSERR_DELAY,
472         NFSERR_EXPIRED,
473         NFSERR_FHEXPIRED,
474         NFSERR_INVAL,
475         NFSERR_ISDIR,
476         NFSERR_LEASEMOVED,
477         NFSERR_LOCKSHELD,
478         NFSERR_MOVED,
479         NFSERR_NOFILEHANDLE,
480         NFSERR_OLDSTATEID,
481         NFSERR_RESOURCE,
482         NFSERR_SERVERFAULT,
483         NFSERR_STALE,
484         NFSERR_STALESTATEID,
485         0,
486 };
487
488 static short nfsv4err_commit[] = {
489         NFSERR_IO,
490         NFSERR_ACCES,
491         NFSERR_BADHANDLE,
492         NFSERR_BADXDR,
493         NFSERR_FHEXPIRED,
494         NFSERR_INVAL,
495         NFSERR_IO,
496         NFSERR_ISDIR,
497         NFSERR_MOVED,
498         NFSERR_NOFILEHANDLE,
499         NFSERR_RESOURCE,
500         NFSERR_ROFS,
501         NFSERR_SERVERFAULT,
502         NFSERR_STALE,
503         0,
504 };
505
506 static short nfsv4err_create[] = {
507         NFSERR_IO,
508         NFSERR_ACCES,
509         NFSERR_ATTRNOTSUPP,
510         NFSERR_BADCHAR,
511         NFSERR_BADHANDLE,
512         NFSERR_BADNAME,
513         NFSERR_BADOWNER,
514         NFSERR_BADTYPE,
515         NFSERR_BADXDR,
516         NFSERR_DELAY,
517         NFSERR_DQUOT,
518         NFSERR_EXIST,
519         NFSERR_FHEXPIRED,
520         NFSERR_INVAL,
521         NFSERR_IO,
522         NFSERR_MOVED,
523         NFSERR_NAMETOL,
524         NFSERR_NOFILEHANDLE,
525         NFSERR_NOSPC,
526         NFSERR_NOTDIR,
527         NFSERR_PERM,
528         NFSERR_RESOURCE,
529         NFSERR_ROFS,
530         NFSERR_SERVERFAULT,
531         NFSERR_STALE,
532         0,
533 };
534
535 static short nfsv4err_delegpurge[] = {
536         NFSERR_SERVERFAULT,
537         NFSERR_BADXDR,
538         NFSERR_NOTSUPP,
539         NFSERR_LEASEMOVED,
540         NFSERR_MOVED,
541         NFSERR_RESOURCE,
542         NFSERR_SERVERFAULT,
543         NFSERR_STALECLIENTID,
544         0,
545 };
546
547 static short nfsv4err_delegreturn[] = {
548         NFSERR_SERVERFAULT,
549         NFSERR_ADMINREVOKED,
550         NFSERR_BADSTATEID,
551         NFSERR_BADXDR,
552         NFSERR_EXPIRED,
553         NFSERR_INVAL,
554         NFSERR_LEASEMOVED,
555         NFSERR_MOVED,
556         NFSERR_NOFILEHANDLE,
557         NFSERR_NOTSUPP,
558         NFSERR_OLDSTATEID,
559         NFSERR_RESOURCE,
560         NFSERR_SERVERFAULT,
561         NFSERR_STALE,
562         NFSERR_STALESTATEID,
563         0,
564 };
565
566 static short nfsv4err_getattr[] = {
567         NFSERR_IO,
568         NFSERR_ACCES,
569         NFSERR_BADHANDLE,
570         NFSERR_BADXDR,
571         NFSERR_DELAY,
572         NFSERR_FHEXPIRED,
573         NFSERR_INVAL,
574         NFSERR_IO,
575         NFSERR_MOVED,
576         NFSERR_NOFILEHANDLE,
577         NFSERR_RESOURCE,
578         NFSERR_SERVERFAULT,
579         NFSERR_STALE,
580         0,
581 };
582
583 static short nfsv4err_getfh[] = {
584         NFSERR_BADHANDLE,
585         NFSERR_BADHANDLE,
586         NFSERR_FHEXPIRED,
587         NFSERR_MOVED,
588         NFSERR_NOFILEHANDLE,
589         NFSERR_RESOURCE,
590         NFSERR_SERVERFAULT,
591         NFSERR_STALE,
592         0,
593 };
594
595 static short nfsv4err_link[] = {
596         NFSERR_IO,
597         NFSERR_ACCES,
598         NFSERR_BADCHAR,
599         NFSERR_BADHANDLE,
600         NFSERR_BADNAME,
601         NFSERR_BADXDR,
602         NFSERR_DELAY,
603         NFSERR_DQUOT,
604         NFSERR_EXIST,
605         NFSERR_FHEXPIRED,
606         NFSERR_FILEOPEN,
607         NFSERR_INVAL,
608         NFSERR_IO,
609         NFSERR_ISDIR,
610         NFSERR_MLINK,
611         NFSERR_MOVED,
612         NFSERR_NAMETOL,
613         NFSERR_NOENT,
614         NFSERR_NOFILEHANDLE,
615         NFSERR_NOSPC,
616         NFSERR_NOTDIR,
617         NFSERR_NOTSUPP,
618         NFSERR_RESOURCE,
619         NFSERR_ROFS,
620         NFSERR_SERVERFAULT,
621         NFSERR_STALE,
622         NFSERR_WRONGSEC,
623         NFSERR_XDEV,
624         0,
625 };
626
627 static short nfsv4err_lock[] = {
628         NFSERR_SERVERFAULT,
629         NFSERR_ACCES,
630         NFSERR_ADMINREVOKED,
631         NFSERR_BADHANDLE,
632         NFSERR_BADRANGE,
633         NFSERR_BADSEQID,
634         NFSERR_BADSTATEID,
635         NFSERR_BADXDR,
636         NFSERR_DEADLOCK,
637         NFSERR_DELAY,
638         NFSERR_DENIED,
639         NFSERR_EXPIRED,
640         NFSERR_FHEXPIRED,
641         NFSERR_GRACE,
642         NFSERR_INVAL,
643         NFSERR_ISDIR,
644         NFSERR_LEASEMOVED,
645         NFSERR_LOCKNOTSUPP,
646         NFSERR_LOCKRANGE,
647         NFSERR_MOVED,
648         NFSERR_NOFILEHANDLE,
649         NFSERR_NOGRACE,
650         NFSERR_OLDSTATEID,
651         NFSERR_OPENMODE,
652         NFSERR_RECLAIMBAD,
653         NFSERR_RECLAIMCONFLICT,
654         NFSERR_RESOURCE,
655         NFSERR_SERVERFAULT,
656         NFSERR_STALE,
657         NFSERR_STALECLIENTID,
658         NFSERR_STALESTATEID,
659         0,
660 };
661
662 static short nfsv4err_lockt[] = {
663         NFSERR_SERVERFAULT,
664         NFSERR_ACCES,
665         NFSERR_BADHANDLE,
666         NFSERR_BADRANGE,
667         NFSERR_BADXDR,
668         NFSERR_DELAY,
669         NFSERR_DENIED,
670         NFSERR_FHEXPIRED,
671         NFSERR_GRACE,
672         NFSERR_INVAL,
673         NFSERR_ISDIR,
674         NFSERR_LEASEMOVED,
675         NFSERR_LOCKRANGE,
676         NFSERR_MOVED,
677         NFSERR_NOFILEHANDLE,
678         NFSERR_RESOURCE,
679         NFSERR_SERVERFAULT,
680         NFSERR_STALE,
681         NFSERR_STALECLIENTID,
682         0,
683 };
684
685 static short nfsv4err_locku[] = {
686         NFSERR_SERVERFAULT,
687         NFSERR_ACCES,
688         NFSERR_ADMINREVOKED,
689         NFSERR_BADHANDLE,
690         NFSERR_BADRANGE,
691         NFSERR_BADSEQID,
692         NFSERR_BADSTATEID,
693         NFSERR_BADXDR,
694         NFSERR_EXPIRED,
695         NFSERR_FHEXPIRED,
696         NFSERR_GRACE,
697         NFSERR_INVAL,
698         NFSERR_ISDIR,
699         NFSERR_LEASEMOVED,
700         NFSERR_LOCKRANGE,
701         NFSERR_MOVED,
702         NFSERR_NOFILEHANDLE,
703         NFSERR_OLDSTATEID,
704         NFSERR_RESOURCE,
705         NFSERR_SERVERFAULT,
706         NFSERR_STALE,
707         NFSERR_STALESTATEID,
708         0,
709 };
710
711 static short nfsv4err_lookup[] = {
712         NFSERR_IO,
713         NFSERR_ACCES,
714         NFSERR_BADCHAR,
715         NFSERR_BADHANDLE,
716         NFSERR_BADNAME,
717         NFSERR_BADXDR,
718         NFSERR_FHEXPIRED,
719         NFSERR_INVAL,
720         NFSERR_IO,
721         NFSERR_MOVED,
722         NFSERR_NAMETOL,
723         NFSERR_NOENT,
724         NFSERR_NOFILEHANDLE,
725         NFSERR_NOTDIR,
726         NFSERR_RESOURCE,
727         NFSERR_SERVERFAULT,
728         NFSERR_STALE,
729         NFSERR_SYMLINK,
730         NFSERR_WRONGSEC,
731         0,
732 };
733
734 static short nfsv4err_lookupp[] = {
735         NFSERR_IO,
736         NFSERR_ACCES,
737         NFSERR_BADHANDLE,
738         NFSERR_FHEXPIRED,
739         NFSERR_IO,
740         NFSERR_MOVED,
741         NFSERR_NOENT,
742         NFSERR_NOFILEHANDLE,
743         NFSERR_NOTDIR,
744         NFSERR_RESOURCE,
745         NFSERR_SERVERFAULT,
746         NFSERR_STALE,
747         0,
748 };
749
750 static short nfsv4err_nverify[] = {
751         NFSERR_IO,
752         NFSERR_ACCES,
753         NFSERR_ATTRNOTSUPP,
754         NFSERR_BADCHAR,
755         NFSERR_BADHANDLE,
756         NFSERR_BADXDR,
757         NFSERR_DELAY,
758         NFSERR_FHEXPIRED,
759         NFSERR_INVAL,
760         NFSERR_IO,
761         NFSERR_MOVED,
762         NFSERR_NOFILEHANDLE,
763         NFSERR_RESOURCE,
764         NFSERR_SAME,
765         NFSERR_SERVERFAULT,
766         NFSERR_STALE,
767         0,
768 };
769
770 static short nfsv4err_open[] = {
771         NFSERR_IO,
772         NFSERR_ACCES,
773         NFSERR_ADMINREVOKED,
774         NFSERR_ATTRNOTSUPP,
775         NFSERR_BADCHAR,
776         NFSERR_BADHANDLE,
777         NFSERR_BADNAME,
778         NFSERR_BADOWNER,
779         NFSERR_BADSEQID,
780         NFSERR_BADXDR,
781         NFSERR_DELAY,
782         NFSERR_DQUOT,
783         NFSERR_EXIST,
784         NFSERR_EXPIRED,
785         NFSERR_FHEXPIRED,
786         NFSERR_GRACE,
787         NFSERR_IO,
788         NFSERR_INVAL,
789         NFSERR_ISDIR,
790         NFSERR_LEASEMOVED,
791         NFSERR_MOVED,
792         NFSERR_NAMETOL,
793         NFSERR_NOENT,
794         NFSERR_NOFILEHANDLE,
795         NFSERR_NOGRACE,
796         NFSERR_NOSPC,
797         NFSERR_NOTDIR,
798         NFSERR_NOTSUPP,
799         NFSERR_PERM,
800         NFSERR_RECLAIMBAD,
801         NFSERR_RECLAIMCONFLICT,
802         NFSERR_RESOURCE,
803         NFSERR_ROFS,
804         NFSERR_SERVERFAULT,
805         NFSERR_SHAREDENIED,
806         NFSERR_STALE,
807         NFSERR_STALECLIENTID,
808         NFSERR_SYMLINK,
809         NFSERR_WRONGSEC,
810         0,
811 };
812
813 static short nfsv4err_openattr[] = {
814         NFSERR_IO,
815         NFSERR_ACCES,
816         NFSERR_BADHANDLE,
817         NFSERR_BADXDR,
818         NFSERR_DELAY,
819         NFSERR_DQUOT,
820         NFSERR_FHEXPIRED,
821         NFSERR_IO,
822         NFSERR_MOVED,
823         NFSERR_NOENT,
824         NFSERR_NOFILEHANDLE,
825         NFSERR_NOSPC,
826         NFSERR_NOTSUPP,
827         NFSERR_RESOURCE,
828         NFSERR_ROFS,
829         NFSERR_SERVERFAULT,
830         NFSERR_STALE,
831         0,
832 };
833
834 static short nfsv4err_openconfirm[] = {
835         NFSERR_SERVERFAULT,
836         NFSERR_ADMINREVOKED,
837         NFSERR_BADHANDLE,
838         NFSERR_BADSEQID,
839         NFSERR_BADSTATEID,
840         NFSERR_BADXDR,
841         NFSERR_EXPIRED,
842         NFSERR_FHEXPIRED,
843         NFSERR_INVAL,
844         NFSERR_ISDIR,
845         NFSERR_MOVED,
846         NFSERR_NOFILEHANDLE,
847         NFSERR_OLDSTATEID,
848         NFSERR_RESOURCE,
849         NFSERR_SERVERFAULT,
850         NFSERR_STALE,
851         NFSERR_STALESTATEID,
852         0,
853 };
854
855 static short nfsv4err_opendowngrade[] = {
856         NFSERR_SERVERFAULT,
857         NFSERR_ADMINREVOKED,
858         NFSERR_BADHANDLE,
859         NFSERR_BADSEQID,
860         NFSERR_BADSTATEID,
861         NFSERR_BADXDR,
862         NFSERR_EXPIRED,
863         NFSERR_FHEXPIRED,
864         NFSERR_INVAL,
865         NFSERR_MOVED,
866         NFSERR_NOFILEHANDLE,
867         NFSERR_OLDSTATEID,
868         NFSERR_RESOURCE,
869         NFSERR_SERVERFAULT,
870         NFSERR_STALE,
871         NFSERR_STALESTATEID,
872         0,
873 };
874
875 static short nfsv4err_putfh[] = {
876         NFSERR_SERVERFAULT,
877         NFSERR_BADHANDLE,
878         NFSERR_BADXDR,
879         NFSERR_FHEXPIRED,
880         NFSERR_MOVED,
881         NFSERR_RESOURCE,
882         NFSERR_SERVERFAULT,
883         NFSERR_STALE,
884         NFSERR_WRONGSEC,
885         0,
886 };
887
888 static short nfsv4err_putpubfh[] = {
889         NFSERR_SERVERFAULT,
890         NFSERR_RESOURCE,
891         NFSERR_SERVERFAULT,
892         NFSERR_WRONGSEC,
893         0,
894 };
895
896 static short nfsv4err_putrootfh[] = {
897         NFSERR_SERVERFAULT,
898         NFSERR_RESOURCE,
899         NFSERR_SERVERFAULT,
900         NFSERR_WRONGSEC,
901         0,
902 };
903
904 static short nfsv4err_read[] = {
905         NFSERR_IO,
906         NFSERR_ACCES,
907         NFSERR_ADMINREVOKED,
908         NFSERR_BADHANDLE,
909         NFSERR_BADSTATEID,
910         NFSERR_BADXDR,
911         NFSERR_DELAY,
912         NFSERR_EXPIRED,
913         NFSERR_FHEXPIRED,
914         NFSERR_GRACE,
915         NFSERR_IO,
916         NFSERR_INVAL,
917         NFSERR_ISDIR,
918         NFSERR_LEASEMOVED,
919         NFSERR_LOCKED,
920         NFSERR_MOVED,
921         NFSERR_NOFILEHANDLE,
922         NFSERR_NXIO,
923         NFSERR_OLDSTATEID,
924         NFSERR_OPENMODE,
925         NFSERR_RESOURCE,
926         NFSERR_SERVERFAULT,
927         NFSERR_STALE,
928         NFSERR_STALESTATEID,
929         0,
930 };
931
932 static short nfsv4err_readdir[] = {
933         NFSERR_IO,
934         NFSERR_ACCES,
935         NFSERR_BADHANDLE,
936         NFSERR_BAD_COOKIE,
937         NFSERR_BADXDR,
938         NFSERR_DELAY,
939         NFSERR_FHEXPIRED,
940         NFSERR_INVAL,
941         NFSERR_IO,
942         NFSERR_MOVED,
943         NFSERR_NOFILEHANDLE,
944         NFSERR_NOTDIR,
945         NFSERR_NOTSAME,
946         NFSERR_RESOURCE,
947         NFSERR_SERVERFAULT,
948         NFSERR_STALE,
949         NFSERR_TOOSMALL,
950         0,
951 };
952
953 static short nfsv4err_readlink[] = {
954         NFSERR_IO,
955         NFSERR_ACCES,
956         NFSERR_BADHANDLE,
957         NFSERR_DELAY,
958         NFSERR_FHEXPIRED,
959         NFSERR_INVAL,
960         NFSERR_IO,
961         NFSERR_ISDIR,
962         NFSERR_MOVED,
963         NFSERR_NOFILEHANDLE,
964         NFSERR_NOTSUPP,
965         NFSERR_RESOURCE,
966         NFSERR_SERVERFAULT,
967         NFSERR_STALE,
968         0,
969 };
970
971 static short nfsv4err_remove[] = {
972         NFSERR_IO,
973         NFSERR_ACCES,
974         NFSERR_BADCHAR,
975         NFSERR_BADHANDLE,
976         NFSERR_BADNAME,
977         NFSERR_BADXDR,
978         NFSERR_DELAY,
979         NFSERR_FHEXPIRED,
980         NFSERR_FILEOPEN,
981         NFSERR_INVAL,
982         NFSERR_IO,
983         NFSERR_MOVED,
984         NFSERR_NAMETOL,
985         NFSERR_NOENT,
986         NFSERR_NOFILEHANDLE,
987         NFSERR_NOTDIR,
988         NFSERR_NOTEMPTY,
989         NFSERR_RESOURCE,
990         NFSERR_ROFS,
991         NFSERR_SERVERFAULT,
992         NFSERR_STALE,
993         0,
994 };
995
996 static short nfsv4err_rename[] = {
997         NFSERR_IO,
998         NFSERR_ACCES,
999         NFSERR_BADCHAR,
1000         NFSERR_BADHANDLE,
1001         NFSERR_BADNAME,
1002         NFSERR_BADXDR,
1003         NFSERR_DELAY,
1004         NFSERR_DQUOT,
1005         NFSERR_EXIST,
1006         NFSERR_FHEXPIRED,
1007         NFSERR_FILEOPEN,
1008         NFSERR_INVAL,
1009         NFSERR_IO,
1010         NFSERR_MOVED,
1011         NFSERR_NAMETOL,
1012         NFSERR_NOENT,
1013         NFSERR_NOFILEHANDLE,
1014         NFSERR_NOSPC,
1015         NFSERR_NOTDIR,
1016         NFSERR_NOTEMPTY,
1017         NFSERR_RESOURCE,
1018         NFSERR_ROFS,
1019         NFSERR_SERVERFAULT,
1020         NFSERR_STALE,
1021         NFSERR_WRONGSEC,
1022         NFSERR_XDEV,
1023         0,
1024 };
1025
1026 static short nfsv4err_renew[] = {
1027         NFSERR_SERVERFAULT,
1028         NFSERR_ACCES,
1029         NFSERR_ADMINREVOKED,
1030         NFSERR_BADXDR,
1031         NFSERR_CBPATHDOWN,
1032         NFSERR_EXPIRED,
1033         NFSERR_LEASEMOVED,
1034         NFSERR_RESOURCE,
1035         NFSERR_SERVERFAULT,
1036         NFSERR_STALECLIENTID,
1037         0,
1038 };
1039
1040 static short nfsv4err_restorefh[] = {
1041         NFSERR_SERVERFAULT,
1042         NFSERR_BADHANDLE,
1043         NFSERR_FHEXPIRED,
1044         NFSERR_MOVED,
1045         NFSERR_RESOURCE,
1046         NFSERR_RESTOREFH,
1047         NFSERR_SERVERFAULT,
1048         NFSERR_STALE,
1049         NFSERR_WRONGSEC,
1050         0,
1051 };
1052
1053 static short nfsv4err_savefh[] = {
1054         NFSERR_SERVERFAULT,
1055         NFSERR_BADHANDLE,
1056         NFSERR_FHEXPIRED,
1057         NFSERR_MOVED,
1058         NFSERR_NOFILEHANDLE,
1059         NFSERR_RESOURCE,
1060         NFSERR_SERVERFAULT,
1061         NFSERR_STALE,
1062         0,
1063 };
1064
1065 static short nfsv4err_secinfo[] = {
1066         NFSERR_SERVERFAULT,
1067         NFSERR_ACCES,
1068         NFSERR_BADCHAR,
1069         NFSERR_BADHANDLE,
1070         NFSERR_BADNAME,
1071         NFSERR_BADXDR,
1072         NFSERR_FHEXPIRED,
1073         NFSERR_INVAL,
1074         NFSERR_MOVED,
1075         NFSERR_NAMETOL,
1076         NFSERR_NOENT,
1077         NFSERR_NOFILEHANDLE,
1078         NFSERR_NOTDIR,
1079         NFSERR_RESOURCE,
1080         NFSERR_SERVERFAULT,
1081         NFSERR_STALE,
1082         0,
1083 };
1084
1085 static short nfsv4err_setattr[] = {
1086         NFSERR_IO,
1087         NFSERR_ACCES,
1088         NFSERR_ADMINREVOKED,
1089         NFSERR_ATTRNOTSUPP,
1090         NFSERR_BADCHAR,
1091         NFSERR_BADHANDLE,
1092         NFSERR_BADOWNER,
1093         NFSERR_BADSTATEID,
1094         NFSERR_BADXDR,
1095         NFSERR_DELAY,
1096         NFSERR_DQUOT,
1097         NFSERR_EXPIRED,
1098         NFSERR_FBIG,
1099         NFSERR_FHEXPIRED,
1100         NFSERR_GRACE,
1101         NFSERR_INVAL,
1102         NFSERR_IO,
1103         NFSERR_ISDIR,
1104         NFSERR_LOCKED,
1105         NFSERR_MOVED,
1106         NFSERR_NOFILEHANDLE,
1107         NFSERR_NOSPC,
1108         NFSERR_OLDSTATEID,
1109         NFSERR_OPENMODE,
1110         NFSERR_PERM,
1111         NFSERR_RESOURCE,
1112         NFSERR_ROFS,
1113         NFSERR_SERVERFAULT,
1114         NFSERR_STALE,
1115         NFSERR_STALESTATEID,
1116         0,
1117 };
1118
1119 static short nfsv4err_setclientid[] = {
1120         NFSERR_SERVERFAULT,
1121         NFSERR_BADXDR,
1122         NFSERR_CLIDINUSE,
1123         NFSERR_INVAL,
1124         NFSERR_RESOURCE,
1125         NFSERR_SERVERFAULT,
1126         0,
1127 };
1128
1129 static short nfsv4err_setclientidconfirm[] = {
1130         NFSERR_SERVERFAULT,
1131         NFSERR_BADXDR,
1132         NFSERR_CLIDINUSE,
1133         NFSERR_RESOURCE,
1134         NFSERR_SERVERFAULT,
1135         NFSERR_STALECLIENTID,
1136         0,
1137 };
1138
1139 static short nfsv4err_verify[] = {
1140         NFSERR_SERVERFAULT,
1141         NFSERR_ACCES,
1142         NFSERR_ATTRNOTSUPP,
1143         NFSERR_BADCHAR,
1144         NFSERR_BADHANDLE,
1145         NFSERR_BADXDR,
1146         NFSERR_DELAY,
1147         NFSERR_FHEXPIRED,
1148         NFSERR_INVAL,
1149         NFSERR_MOVED,
1150         NFSERR_NOFILEHANDLE,
1151         NFSERR_NOTSAME,
1152         NFSERR_RESOURCE,
1153         NFSERR_SERVERFAULT,
1154         NFSERR_STALE,
1155         0,
1156 };
1157
1158 static short nfsv4err_write[] = {
1159         NFSERR_IO,
1160         NFSERR_ACCES,
1161         NFSERR_ADMINREVOKED,
1162         NFSERR_BADHANDLE,
1163         NFSERR_BADSTATEID,
1164         NFSERR_BADXDR,
1165         NFSERR_DELAY,
1166         NFSERR_DQUOT,
1167         NFSERR_EXPIRED,
1168         NFSERR_FBIG,
1169         NFSERR_FHEXPIRED,
1170         NFSERR_GRACE,
1171         NFSERR_INVAL,
1172         NFSERR_IO,
1173         NFSERR_ISDIR,
1174         NFSERR_LEASEMOVED,
1175         NFSERR_LOCKED,
1176         NFSERR_MOVED,
1177         NFSERR_NOFILEHANDLE,
1178         NFSERR_NOSPC,
1179         NFSERR_NXIO,
1180         NFSERR_OLDSTATEID,
1181         NFSERR_OPENMODE,
1182         NFSERR_RESOURCE,
1183         NFSERR_ROFS,
1184         NFSERR_SERVERFAULT,
1185         NFSERR_STALE,
1186         NFSERR_STALESTATEID,
1187         0,
1188 };
1189
1190 static short nfsv4err_releaselockowner[] = {
1191         NFSERR_SERVERFAULT,
1192         NFSERR_ADMINREVOKED,
1193         NFSERR_BADXDR,
1194         NFSERR_EXPIRED,
1195         NFSERR_LEASEMOVED,
1196         NFSERR_LOCKSHELD,
1197         NFSERR_RESOURCE,
1198         NFSERR_SERVERFAULT,
1199         NFSERR_STALECLIENTID,
1200         0,
1201 };
1202
1203 static short *nfsrv_v4errmap[] = {
1204         nfsv4err_null,
1205         nfsv4err_null,
1206         nfsv4err_null,
1207         nfsv4err_access,
1208         nfsv4err_close,
1209         nfsv4err_commit,
1210         nfsv4err_create,
1211         nfsv4err_delegpurge,
1212         nfsv4err_delegreturn,
1213         nfsv4err_getattr,
1214         nfsv4err_getfh,
1215         nfsv4err_link,
1216         nfsv4err_lock,
1217         nfsv4err_lockt,
1218         nfsv4err_locku,
1219         nfsv4err_lookup,
1220         nfsv4err_lookupp,
1221         nfsv4err_nverify,
1222         nfsv4err_open,
1223         nfsv4err_openattr,
1224         nfsv4err_openconfirm,
1225         nfsv4err_opendowngrade,
1226         nfsv4err_putfh,
1227         nfsv4err_putpubfh,
1228         nfsv4err_putrootfh,
1229         nfsv4err_read,
1230         nfsv4err_readdir,
1231         nfsv4err_readlink,
1232         nfsv4err_remove,
1233         nfsv4err_rename,
1234         nfsv4err_renew,
1235         nfsv4err_restorefh,
1236         nfsv4err_savefh,
1237         nfsv4err_secinfo,
1238         nfsv4err_setattr,
1239         nfsv4err_setclientid,
1240         nfsv4err_setclientidconfirm,
1241         nfsv4err_verify,
1242         nfsv4err_write,
1243         nfsv4err_releaselockowner,
1244 };
1245
1246 /*
1247  * A fiddled version of m_adj() that ensures null fill to a long
1248  * boundary and only trims off the back end
1249  */
1250 APPLESTATIC void
1251 nfsrv_adj(mbuf_t mp, int len, int nul)
1252 {
1253         mbuf_t m;
1254         int count, i;
1255         char *cp;
1256
1257         /*
1258          * Trim from tail.  Scan the mbuf chain,
1259          * calculating its length and finding the last mbuf.
1260          * If the adjustment only affects this mbuf, then just
1261          * adjust and return.  Otherwise, rescan and truncate
1262          * after the remaining size.
1263          */
1264         count = 0;
1265         m = mp;
1266         for (;;) {
1267                 count += mbuf_len(m);
1268                 if (mbuf_next(m) == NULL)
1269                         break;
1270                 m = mbuf_next(m);
1271         }
1272         if (mbuf_len(m) > len) {
1273                 mbuf_setlen(m, mbuf_len(m) - len);
1274                 if (nul > 0) {
1275                         cp = NFSMTOD(m, caddr_t) + mbuf_len(m) - nul;
1276                         for (i = 0; i < nul; i++)
1277                                 *cp++ = '\0';
1278                 }
1279                 return;
1280         }
1281         count -= len;
1282         if (count < 0)
1283                 count = 0;
1284         /*
1285          * Correct length for chain is "count".
1286          * Find the mbuf with last data, adjust its length,
1287          * and toss data from remaining mbufs on chain.
1288          */
1289         for (m = mp; m; m = mbuf_next(m)) {
1290                 if (mbuf_len(m) >= count) {
1291                         mbuf_setlen(m, count);
1292                         if (nul > 0) {
1293                                 cp = NFSMTOD(m, caddr_t) + mbuf_len(m) - nul;
1294                                 for (i = 0; i < nul; i++)
1295                                         *cp++ = '\0';
1296                         }
1297                         break;
1298                 }
1299                 count -= mbuf_len(m);
1300         }
1301         for (m = mbuf_next(m); m; m = mbuf_next(m))
1302                 mbuf_setlen(m, 0);
1303 }
1304
1305 /*
1306  * Make these functions instead of macros, so that the kernel text size
1307  * doesn't get too big...
1308  */
1309 APPLESTATIC void
1310 nfsrv_wcc(struct nfsrv_descript *nd, int before_ret,
1311     struct nfsvattr *before_nvap, int after_ret, struct nfsvattr *after_nvap)
1312 {
1313         u_int32_t *tl;
1314
1315         if (before_ret) {
1316                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
1317                 *tl = newnfs_false;
1318         } else {
1319                 NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
1320                 *tl++ = newnfs_true;
1321                 txdr_hyper(before_nvap->na_size, tl);
1322                 tl += 2;
1323                 txdr_nfsv3time(&(before_nvap->na_mtime), tl);
1324                 tl += 2;
1325                 txdr_nfsv3time(&(before_nvap->na_ctime), tl);
1326         }
1327         nfsrv_postopattr(nd, after_ret, after_nvap);
1328 }
1329
1330 APPLESTATIC void
1331 nfsrv_postopattr(struct nfsrv_descript *nd, int after_ret,
1332     struct nfsvattr *after_nvap)
1333 {
1334         u_int32_t *tl;
1335
1336         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
1337         if (after_ret)
1338                 *tl = newnfs_false;
1339         else {
1340                 *tl = newnfs_true;
1341                 nfsrv_fillattr(nd, after_nvap);
1342         }
1343 }
1344
1345 /*
1346  * Fill in file attributes for V2 and 3. For V4, call a separate
1347  * routine that sifts through all the attribute bits.
1348  */
1349 APPLESTATIC void
1350 nfsrv_fillattr(struct nfsrv_descript *nd, struct nfsvattr *nvap)
1351 {
1352         struct nfs_fattr *fp;
1353         int fattr_size;
1354
1355         /*
1356          * Build space for the attribute structure.
1357          */
1358         if (nd->nd_flag & ND_NFSV3)
1359                 fattr_size = NFSX_V3FATTR;
1360         else
1361                 fattr_size = NFSX_V2FATTR;
1362         NFSM_BUILD(fp, struct nfs_fattr *, fattr_size);
1363
1364         /*
1365          * Now just fill it all in.
1366          */
1367         fp->fa_nlink = txdr_unsigned(nvap->na_nlink);
1368         fp->fa_uid = txdr_unsigned(nvap->na_uid);
1369         fp->fa_gid = txdr_unsigned(nvap->na_gid);
1370         if (nd->nd_flag & ND_NFSV3) {
1371                 fp->fa_type = vtonfsv34_type(nvap->na_type);
1372                 fp->fa_mode = vtonfsv34_mode(nvap->na_mode);
1373                 txdr_hyper(nvap->na_size, &fp->fa3_size);
1374                 txdr_hyper(nvap->na_bytes, &fp->fa3_used);
1375                 fp->fa3_rdev.specdata1 = txdr_unsigned(NFSMAJOR(nvap->na_rdev));
1376                 fp->fa3_rdev.specdata2 = txdr_unsigned(NFSMINOR(nvap->na_rdev));
1377                 fp->fa3_fsid.nfsuquad[0] = 0;
1378                 fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(nvap->na_fsid);
1379                 fp->fa3_fileid.nfsuquad[0] = 0;
1380                 fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(nvap->na_fileid);
1381                 txdr_nfsv3time(&nvap->na_atime, &fp->fa3_atime);
1382                 txdr_nfsv3time(&nvap->na_mtime, &fp->fa3_mtime);
1383                 txdr_nfsv3time(&nvap->na_ctime, &fp->fa3_ctime);
1384         } else {
1385                 fp->fa_type = vtonfsv2_type(nvap->na_type);
1386                 fp->fa_mode = vtonfsv2_mode(nvap->na_type, nvap->na_mode);
1387                 fp->fa2_size = txdr_unsigned(nvap->na_size);
1388                 fp->fa2_blocksize = txdr_unsigned(nvap->na_blocksize);
1389                 if (nvap->na_type == VFIFO)
1390                         fp->fa2_rdev = 0xffffffff;
1391                 else
1392                         fp->fa2_rdev = txdr_unsigned(nvap->na_rdev);
1393                 fp->fa2_blocks = txdr_unsigned(nvap->na_bytes / NFS_FABLKSIZE);
1394                 fp->fa2_fsid = txdr_unsigned(nvap->na_fsid);
1395                 fp->fa2_fileid = txdr_unsigned(nvap->na_fileid);
1396                 txdr_nfsv2time(&nvap->na_atime, &fp->fa2_atime);
1397                 txdr_nfsv2time(&nvap->na_mtime, &fp->fa2_mtime);
1398                 txdr_nfsv2time(&nvap->na_ctime, &fp->fa2_ctime);
1399         }
1400 }
1401
1402 /*
1403  * This function gets a file handle out of an mbuf list.
1404  * It returns 0 for success, EBADRPC otherwise.
1405  * If sets the third flagp argument to 1 if the file handle is
1406  * the public file handle.
1407  * For NFSv4, if the length is incorrect, set nd_repstat == NFSERR_BADHANDLE
1408  */
1409 APPLESTATIC int
1410 nfsrv_mtofh(struct nfsrv_descript *nd, struct nfsrvfh *fhp)
1411 {
1412         u_int32_t *tl;
1413         int error = 0, len, copylen;
1414
1415         if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
1416                 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1417                 len = fxdr_unsigned(int, *tl);
1418                 if (len == 0 && nfs_pubfhset && (nd->nd_flag & ND_NFSV3) &&
1419                     nd->nd_procnum == NFSPROC_LOOKUP) {
1420                         nd->nd_flag |= ND_PUBLOOKUP;
1421                         return (0);
1422                 }
1423                 if (len < NFSRV_MINFH || len > NFSRV_MAXFH) {
1424                         if (nd->nd_flag & ND_NFSV4) {
1425                             if (len > 0 && len <= NFSX_V4FHMAX) {
1426                                 error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
1427                                 if (error)
1428                                         return (error);
1429                                 nd->nd_repstat = NFSERR_BADHANDLE;
1430                                 return (0);
1431                             } else {
1432                                 return (EBADRPC);
1433                             }
1434                         } else {
1435                                 return (EBADRPC);
1436                         }
1437                 }
1438                 copylen = len;
1439         } else {
1440                 /*
1441                  * For NFSv2, the file handle is always 32 bytes on the
1442                  * wire, but this server only cares about the first
1443                  * NFSRV_MAXFH bytes.
1444                  */
1445                 len = NFSX_V2FH;
1446                 copylen = NFSRV_MAXFH;
1447         }
1448         NFSM_DISSECT(tl, u_int32_t *, len);
1449         if ((nd->nd_flag & ND_NFSV2) && nfs_pubfhset &&
1450             nd->nd_procnum == NFSPROC_LOOKUP &&
1451             !NFSBCMP((caddr_t)tl, nfs_v2pubfh, NFSX_V2FH)) {
1452                 nd->nd_flag |= ND_PUBLOOKUP;
1453                 return (0);
1454         }
1455         NFSBCOPY(tl, (caddr_t)fhp->nfsrvfh_data, copylen);
1456         fhp->nfsrvfh_len = copylen;
1457 nfsmout:
1458         return (error);
1459 }
1460
1461 /*
1462  * Map errnos to NFS error numbers. For Version 3 and 4 also filter out error
1463  * numbers not specified for the associated procedure.
1464  * NFSPROC_NOOP is a special case, where the high order bits of nd_repstat
1465  * should be cleared. NFSPROC_NOOP is used to return errors when a valid
1466  * RPC procedure is not involved.
1467  * Returns the error number in XDR.
1468  */
1469 APPLESTATIC int
1470 nfsd_errmap(struct nfsrv_descript *nd)
1471 {
1472         short *defaulterrp, *errp;
1473
1474         if (!nd->nd_repstat)
1475                 return (0);
1476         if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
1477                 if (nd->nd_procnum == NFSPROC_NOOP)
1478                         return (txdr_unsigned(nd->nd_repstat & 0xffff));
1479                 if (nd->nd_flag & ND_NFSV3)
1480                     errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
1481                 else if (nd->nd_repstat == EBADRPC)
1482                         return (txdr_unsigned(NFSERR_BADXDR));
1483                 else if (nd->nd_repstat == NFSERR_MINORVERMISMATCH ||
1484                          nd->nd_repstat == NFSERR_OPILLEGAL)
1485                         return (txdr_unsigned(nd->nd_repstat));
1486                 else
1487                     errp = defaulterrp = nfsrv_v4errmap[nd->nd_procnum];
1488                 while (*++errp)
1489                         if (*errp == nd->nd_repstat)
1490                                 return (txdr_unsigned(nd->nd_repstat));
1491                 return (txdr_unsigned(*defaulterrp));
1492         }
1493         if (nd->nd_repstat <= ELAST)
1494                 return (txdr_unsigned(nfsrv_v2errmap[nd->nd_repstat - 1]));
1495         return (txdr_unsigned(NFSERR_IO));
1496 }
1497
1498 /*
1499  * Check to see if setting a uid/gid is permitted when creating a new
1500  * file object. (Called when uid and/or gid is specified in the
1501  * settable attributes for V4.
1502  */
1503 APPLESTATIC int
1504 nfsrv_checkuidgid(struct nfsrv_descript *nd, struct nfsvattr *nvap)
1505 {
1506
1507         /*
1508          * If not setting either uid nor gid, it's OK.
1509          */
1510         if (NFSVNO_NOTSETUID(nvap) && NFSVNO_NOTSETGID(nvap))
1511                 return (0);
1512         if ((NFSVNO_ISSETUID(nvap) && nvap->na_uid == nfsrv_defaultuid)
1513             || (NFSVNO_ISSETGID(nvap) && nvap->na_gid == nfsrv_defaultgid))
1514                 return (NFSERR_BADOWNER);
1515         if (nd->nd_cred->cr_uid == 0)
1516                 return (0);
1517         if ((NFSVNO_ISSETUID(nvap) && nvap->na_uid != nd->nd_cred->cr_uid) ||
1518             (NFSVNO_ISSETGID(nvap) && nvap->na_gid != nd->nd_cred->cr_gid &&
1519             !groupmember(nvap->na_gid, nd->nd_cred)))
1520                 return (NFSERR_PERM);
1521         return (0);
1522 }
1523
1524 /*
1525  * and this routine fixes up the settable attributes for V4 if allowed
1526  * by nfsrv_checkuidgid().
1527  */
1528 APPLESTATIC void
1529 nfsrv_fixattr(struct nfsrv_descript *nd, vnode_t vp,
1530     struct nfsvattr *nvap, NFSACL_T *aclp, NFSPROC_T *p, nfsattrbit_t *attrbitp,
1531     struct nfsexstuff *exp)
1532 {
1533         int change = 0;
1534         struct nfsvattr nva;
1535         uid_t tuid;
1536         int error;
1537         nfsattrbit_t nattrbits;
1538
1539         /*
1540          * Maybe this should be done for V2 and 3 but it never has been
1541          * and nobody seems to be upset, so I think it's best not to change
1542          * the V2 and 3 semantics.
1543          */
1544         if ((nd->nd_flag & ND_NFSV4) == 0)
1545                 return;
1546         NFSVNO_ATTRINIT(&nva);
1547         NFSZERO_ATTRBIT(&nattrbits);
1548         tuid = nd->nd_cred->cr_uid;
1549         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNER) &&
1550             NFSVNO_ISSETUID(nvap) &&
1551             nvap->na_uid != nd->nd_cred->cr_uid) {
1552                 if (nd->nd_cred->cr_uid == 0) {
1553                         nva.na_uid = nvap->na_uid;
1554                         change++;
1555                         NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_OWNER);
1556                 } else {
1557                         NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_OWNER);
1558                 }
1559         }
1560         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEACCESSSET) &&
1561             NFSVNO_ISSETATIME(nvap)) {
1562                 nva.na_atime = nvap->na_atime;
1563                 change++;
1564                 NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_TIMEACCESSSET);
1565         }
1566         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEMODIFYSET) &&
1567             NFSVNO_ISSETMTIME(nvap)) {
1568                 nva.na_mtime = nvap->na_mtime;
1569                 change++;
1570                 NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_TIMEMODIFYSET);
1571         }
1572         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP) &&
1573             NFSVNO_ISSETGID(nvap)) {
1574                 if (nvap->na_gid == nd->nd_cred->cr_gid ||
1575                     groupmember(nvap->na_gid, nd->nd_cred)) {
1576                         nd->nd_cred->cr_uid = 0;
1577                         nva.na_gid = nvap->na_gid;
1578                         change++;
1579                         NFSSETBIT_ATTRBIT(&nattrbits, NFSATTRBIT_OWNERGROUP);
1580                 } else {
1581                         NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP);
1582                 }
1583         }
1584         if (change) {
1585                 error = nfsvno_setattr(vp, &nva, nd->nd_cred, p, exp);
1586                 if (error) {
1587                         NFSCLRALL_ATTRBIT(attrbitp, &nattrbits);
1588                 }
1589         }
1590         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE) &&
1591             NFSVNO_ISSETSIZE(nvap) && nvap->na_size != (u_quad_t)0) {
1592                 NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_SIZE);
1593         }
1594 #ifdef NFS4_ACL_EXTATTR_NAME
1595         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL) &&
1596             nfsrv_useacl != 0 && aclp != NULL) {
1597                 if (aclp->acl_cnt > 0) {
1598                         error = nfsrv_setacl(vp, aclp, nd->nd_cred, p);
1599                         if (error) {
1600                                 NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_ACL);
1601                         }
1602                 }
1603         } else
1604 #endif
1605         NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_ACL);
1606         nd->nd_cred->cr_uid = tuid;
1607 }
1608
1609 /*
1610  * Translate an ASCII hex digit to it's binary value. Return -1 if the
1611  * char isn't a hex digit.
1612  */
1613 static char
1614 nfsrv_hexdigit(char c, int *err)
1615 {
1616
1617         *err = 0;
1618         if (c >= '0' && c <= '9')
1619                 return (c - '0');
1620         if (c >= 'a' && c <= 'f')
1621                 return (c - 'a' + ((char)10));
1622         if (c >= 'A' && c <= 'F')
1623                 return (c - 'A' + ((char)10));
1624         /* Not valid ! */
1625         *err = 1;
1626         return (1);     /* BOGUS */
1627 }
1628
1629 /*
1630  * Check to see if NFSERR_MOVED can be returned for this op. Return 1 iff
1631  * it can be.
1632  */
1633 APPLESTATIC int
1634 nfsrv_errmoved(int op)
1635 {
1636         short *errp;
1637
1638         errp = nfsrv_v4errmap[op];
1639         while (*errp != 0) {
1640                 if (*errp == NFSERR_MOVED)
1641                         return (1);
1642                 errp++;
1643         }
1644         return (0);
1645 }
1646
1647 /*
1648  * Fill in attributes for a Referral.
1649  * (Return the number of bytes of XDR created.)
1650  */
1651 APPLESTATIC int
1652 nfsrv_putreferralattr(struct nfsrv_descript *nd, nfsattrbit_t *retbitp,
1653     struct nfsreferral *refp, int getattr, int *reterrp)
1654 {
1655         u_int32_t *tl, *retnump;
1656         u_char *cp, *cp2;
1657         int prefixnum, retnum = 0, i, len, bitpos, rderrbit = 0, nonrefbit = 0;
1658         int fslocationsbit = 0;
1659         nfsattrbit_t tmpbits, refbits;
1660
1661         NFSREFERRAL_ATTRBIT(&refbits);
1662         if (getattr)
1663                 NFSCLRBIT_ATTRBIT(&refbits, NFSATTRBIT_RDATTRERROR);
1664         else if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_RDATTRERROR))
1665                 rderrbit = 1;
1666         if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_FSLOCATIONS))
1667                 fslocationsbit = 1;
1668
1669         /*
1670          * Check for the case where unsupported referral attributes are
1671          * requested.
1672          */
1673         NFSSET_ATTRBIT(&tmpbits, retbitp);
1674         NFSCLRALL_ATTRBIT(&tmpbits, &refbits);
1675         if (NFSNONZERO_ATTRBIT(&tmpbits))
1676                 nonrefbit = 1;
1677
1678         if (nonrefbit && !fslocationsbit && (getattr || !rderrbit)) {
1679                 *reterrp = NFSERR_MOVED;
1680                 return (0);
1681         }
1682
1683         /*
1684          * Now we can fill in the attributes.
1685          */
1686         NFSSET_ATTRBIT(&tmpbits, retbitp);
1687         NFSCLRNOT_ATTRBIT(&tmpbits, &refbits);
1688
1689         /*
1690          * Put out the attribute bitmap for the ones being filled in
1691          * and get the field for the number of attributes returned.
1692          */
1693         prefixnum = nfsrv_putattrbit(nd, &tmpbits);
1694         NFSM_BUILD(retnump, u_int32_t *, NFSX_UNSIGNED);
1695         prefixnum += NFSX_UNSIGNED;
1696
1697         /*
1698          * Now, loop around filling in the attributes for each bit set.
1699          */
1700         for (bitpos = 0; bitpos < NFSATTRBIT_MAX; bitpos++) {
1701             if (NFSISSET_ATTRBIT(&tmpbits, bitpos)) {
1702                 switch (bitpos) {
1703                 case NFSATTRBIT_TYPE:
1704                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
1705                         *tl = txdr_unsigned(NFDIR);
1706                         retnum += NFSX_UNSIGNED;
1707                         break;
1708                 case NFSATTRBIT_FSID:
1709                         NFSM_BUILD(tl, u_int32_t *, NFSX_V4FSID);
1710                         *tl++ = 0;
1711                         *tl++ = txdr_unsigned(NFSV4ROOT_FSID0);
1712                         *tl++ = 0;
1713                         *tl = txdr_unsigned(NFSV4ROOT_REFERRAL);
1714                         retnum += NFSX_V4FSID;
1715                         break;
1716                 case NFSATTRBIT_RDATTRERROR:
1717                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
1718                         if (nonrefbit)
1719                                 *tl = txdr_unsigned(NFSERR_MOVED);
1720                         else
1721                                 *tl = 0;
1722                         retnum += NFSX_UNSIGNED;
1723                         break;
1724                 case NFSATTRBIT_FSLOCATIONS:
1725                         retnum += nfsm_strtom(nd, "/", 1);
1726                         NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
1727                         *tl = txdr_unsigned(refp->nfr_srvcnt);
1728                         retnum += NFSX_UNSIGNED;
1729                         cp = refp->nfr_srvlist;
1730                         for (i = 0; i < refp->nfr_srvcnt; i++) {
1731                                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
1732                                 *tl = txdr_unsigned(1);
1733                                 retnum += NFSX_UNSIGNED;
1734                                 cp2 = STRCHR(cp, ':');
1735                                 if (cp2 != NULL)
1736                                         len = cp2 - cp;
1737                                 else
1738                                         len = 1;
1739                                 retnum += nfsm_strtom(nd, cp, len);
1740                                 if (cp2 != NULL)
1741                                         cp = cp2 + 1;
1742                                 cp2 = STRCHR(cp, ',');
1743                                 if (cp2 != NULL)
1744                                         len = cp2 - cp;
1745                                 else
1746                                         len = strlen(cp);
1747                                 retnum += nfsm_strtom(nd, cp, len);
1748                                 if (cp2 != NULL)
1749                                         cp = cp2 + 1;
1750                         }
1751                         break;
1752                 case NFSATTRBIT_MOUNTEDONFILEID:
1753                         NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER);
1754                         *tl++ = 0;
1755                         *tl = txdr_unsigned(refp->nfr_dfileno);
1756                         retnum += NFSX_HYPER;
1757                         break;
1758                 default:
1759                         printf("EEK! Bad V4 refattr bitpos=%d\n", bitpos);
1760                 };
1761             }
1762         }
1763         *retnump = txdr_unsigned(retnum);
1764         return (retnum + prefixnum);
1765 }
1766
1767 /*
1768  * Parse a file name out of a request.
1769  */
1770 APPLESTATIC int
1771 nfsrv_parsename(struct nfsrv_descript *nd, char *bufp, u_long *hashp,
1772     NFSPATHLEN_T *outlenp)
1773 {
1774         char *fromcp, *tocp, val = '\0';
1775         mbuf_t md;
1776         int i;
1777         int rem, len, error = 0, pubtype = 0, outlen = 0, percent = 0;
1778         char digit;
1779         u_int32_t *tl;
1780         u_long hash = 0;
1781
1782         if (hashp != NULL)
1783                 *hashp = 0;
1784         tocp = bufp;
1785         /*
1786          * For V4, check for lookup parent.
1787          * Otherwise, get the component name.
1788          */
1789         if ((nd->nd_flag & ND_NFSV4) && nd->nd_procnum == NFSV4OP_LOOKUPP) {
1790             *tocp++ = '.';
1791             hash += ((u_char)'.');
1792             *tocp++ = '.';
1793             hash += ((u_char)'.');
1794             outlen = 2;
1795         } else {
1796             /*
1797              * First, get the name length.
1798              */
1799             NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1800             len = fxdr_unsigned(int, *tl);
1801             if (len > NFS_MAXNAMLEN) {
1802                 nd->nd_repstat = NFSERR_NAMETOL;
1803                 return (0);
1804             } else if (len <= 0) {
1805                 nd->nd_repstat = NFSERR_INVAL;
1806                 return (0);
1807             }
1808
1809             /*
1810              * Now, copy the component name into the buffer.
1811              */
1812             fromcp = nd->nd_dpos;
1813             md = nd->nd_md;
1814             rem = NFSMTOD(md, caddr_t) + mbuf_len(md) - fromcp;
1815             for (i = 0; i < len; i++) {
1816                 while (rem == 0) {
1817                         md = mbuf_next(md);
1818                         if (md == NULL)
1819                                 return (EBADRPC);
1820                         fromcp = NFSMTOD(md, caddr_t);
1821                         rem = mbuf_len(md);
1822                 }
1823                 if (*fromcp == '\0') {
1824                         nd->nd_repstat = EACCES;
1825                         return (0);
1826                 }
1827                 /*
1828                  * For lookups on the public filehandle, do some special
1829                  * processing on the name. (The public file handle is the
1830                  * root of the public file system for this server.)
1831                  */
1832                 if (nd->nd_flag & ND_PUBLOOKUP) {
1833                         /*
1834                          * If the first char is ASCII, it is a canonical
1835                          * path, otherwise it is a native path. (RFC2054
1836                          * doesn't actually state what it is if the first
1837                          * char isn't ASCII or 0x80, so I assume native.)
1838                          * pubtype == 1 -> native path
1839                          * pubtype == 2 -> canonical path
1840                          */
1841                         if (i == 0) {
1842                                 if (*fromcp & 0x80) {
1843                                         /*
1844                                          * Since RFC2054 doesn't indicate
1845                                          * that a native path of just 0x80
1846                                          * isn't allowed, I'll replace the
1847                                          * 0x80 with '/' instead of just
1848                                          * throwing it away.
1849                                          */
1850                                         *fromcp = '/';
1851                                         pubtype = 1;
1852                                 } else {
1853                                         pubtype = 2;
1854                                 }
1855                         }
1856                         /*
1857                          * '/' only allowed in a native path
1858                          */
1859                         if (*fromcp == '/' && pubtype != 1) {
1860                                 nd->nd_repstat = EACCES;
1861                                 return (0);
1862                         }
1863
1864                         /*
1865                          * For the special case of 2 hex digits after a
1866                          * '%' in an absolute path, calculate the value.
1867                          * percent == 1 -> indicates "get first hex digit"
1868                          * percent == 2 -> indicates "get second hex digit"
1869                          */
1870                         if (percent > 0) {
1871                                 digit = nfsrv_hexdigit(*fromcp, &error);
1872                                 if (error) {
1873                                         nd->nd_repstat = EACCES;
1874                                         return (0);
1875                                 }
1876                                 if (percent == 1) {
1877                                         val = (digit << 4);
1878                                         percent = 2;
1879                                 } else {
1880                                         val += digit;
1881                                         percent = 0;
1882                                         *tocp++ = val;
1883                                         hash += ((u_char)val);
1884                                         outlen++;
1885                                 }
1886                         } else {
1887                                 if (*fromcp == '%' && pubtype == 2) {
1888                                         /*
1889                                          * Must be followed by 2 hex digits
1890                                          */
1891                                         if ((len - i) < 3) {
1892                                                 nd->nd_repstat = EACCES;
1893                                                 return (0);
1894                                         }
1895                                         percent = 1;
1896                                 } else {
1897                                         *tocp++ = *fromcp;
1898                                         hash += ((u_char)*fromcp);
1899                                         outlen++;
1900                                 }
1901                         }
1902                 } else {
1903                         /*
1904                          * Normal, non lookup on public, name.
1905                          */
1906                         if (*fromcp == '/') {
1907                                 if (nd->nd_flag & ND_NFSV4)
1908                                         nd->nd_repstat = NFSERR_BADNAME;
1909                                 else
1910                                         nd->nd_repstat = EACCES;
1911                                 return (0);
1912                         }
1913                         hash += ((u_char)*fromcp);
1914                         *tocp++ = *fromcp;
1915                         outlen++;
1916                 }
1917                 fromcp++;
1918                 rem--;
1919             }
1920             nd->nd_md = md;
1921             nd->nd_dpos = fromcp;
1922             i = NFSM_RNDUP(len) - len;
1923             if (i > 0) {
1924                 if (rem >= i) {
1925                         nd->nd_dpos += i;
1926                 } else {
1927                         error = nfsm_advance(nd, i, rem);
1928                         if (error)
1929                                 return (error);
1930                 }
1931             }
1932
1933             /*
1934              * For v4, don't allow lookups of '.' or '..' and
1935              * also check for non-utf8 strings.
1936              */
1937             if (nd->nd_flag & ND_NFSV4) {
1938                 if ((outlen == 1 && bufp[0] == '.') ||
1939                     (outlen == 2 && bufp[0] == '.' &&
1940                      bufp[1] == '.')) {
1941                     nd->nd_repstat = NFSERR_BADNAME;
1942                     return (0);
1943                 }
1944                 if (nfsrv_checkutf8((u_int8_t *)bufp, outlen)) {
1945                     nd->nd_repstat = NFSERR_INVAL;
1946                     return (0);
1947                 }
1948             }
1949         }
1950         *tocp = '\0';
1951         *outlenp = (size_t)outlen;
1952         if (hashp != NULL)
1953                 *hashp = hash;
1954 nfsmout:
1955         return (error);
1956 }
1957
1958 /*
1959  * Check the tcp socket sequence number has been acknowledged.
1960  */
1961 int
1962 nfsrv_checksockseqnum(struct socket *so, tcp_seq tcpseqval)
1963 {
1964         tcp_seq maxseq, unaseq;
1965         int error, ret;
1966
1967         error = nfsrv_getsocksndseq(so, &maxseq, &unaseq);
1968         if (error)
1969                 return (0);
1970         ret = SEQ_GEQ(unaseq, tcpseqval);
1971         return (ret);
1972 }
1973
1974 /*
1975  * Get the tcp sequence number to be acknowledged.
1976  */
1977 int
1978 nfsrv_getsockseqnum(struct socket *so, tcp_seq *tcpseqp)
1979 {
1980         tcp_seq maxseq, unaseq;
1981         u_int sbcc;
1982         int error;
1983
1984         sbcc = so->so_snd.sb_cc;
1985         error = nfsrv_getsocksndseq(so, &maxseq, &unaseq);
1986         if (error)
1987                 return (0);
1988         /*
1989          * Set the seq# to a value that will
1990          * be at least the end of the reply.
1991          * When this sequence# is acknowledged
1992          * by the client, the client has received
1993          * the reply.
1994          */
1995         *tcpseqp = sbcc + maxseq;
1996         return (1);
1997 }
1998
1999 void
2000 nfsd_init(void)
2001 {
2002         int i;
2003         static int inited = 0;
2004
2005         if (inited)
2006                 return;
2007         inited = 1;
2008
2009         /*
2010          * Initialize client queues. Don't free/reinitialize
2011          * them when nfsds are restarted.
2012          */
2013         for (i = 0; i < NFSCLIENTHASHSIZE; i++)
2014                 LIST_INIT(&nfsclienthash[i]);
2015         for (i = 0; i < NFSLOCKHASHSIZE; i++)
2016                 LIST_INIT(&nfslockhash[i]);
2017
2018         /* and the v2 pubfh should be all zeros */
2019         NFSBZERO(nfs_v2pubfh, NFSX_V2FH);
2020 }
2021
2022 /*
2023  * Check the v4 root exports.
2024  * Return 0 if ok, 1 otherwise.
2025  */
2026 int
2027 nfsd_checkrootexp(struct nfsrv_descript *nd)
2028 {
2029
2030         if ((nd->nd_flag & (ND_GSS | ND_EXAUTHSYS)) == ND_EXAUTHSYS)
2031                 return (0);
2032         if ((nd->nd_flag & (ND_GSSINTEGRITY | ND_EXGSSINTEGRITY)) ==
2033             (ND_GSSINTEGRITY | ND_EXGSSINTEGRITY))
2034                 return (0);
2035         if ((nd->nd_flag & (ND_GSSPRIVACY | ND_EXGSSPRIVACY)) ==
2036             (ND_GSSPRIVACY | ND_EXGSSPRIVACY))
2037                 return (0);
2038         if ((nd->nd_flag & (ND_GSS | ND_GSSINTEGRITY | ND_GSSPRIVACY |
2039              ND_EXGSS)) == (ND_GSS | ND_EXGSS))
2040                 return (0);
2041         return (1);
2042 }
2043