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