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