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