2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95
40 #include <sys/cdefs.h>
41 __FBSDID("$FreeBSD$");
44 * These functions support the macros and help fiddle mbuf chains for
45 * the nfs op functions. They do things like create the rpc header and
46 * copy data between mbuf chains and uio lists.
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/kernel.h>
55 #include <sys/mount.h>
56 #include <sys/vnode.h>
57 #include <sys/namei.h>
59 #include <sys/socket.h>
61 #include <sys/malloc.h>
62 #include <sys/module.h>
63 #include <sys/sysent.h>
64 #include <sys/syscall.h>
65 #include <sys/sysproto.h>
68 #include <vm/vm_object.h>
69 #include <vm/vm_extern.h>
70 #include <vm/vm_zone.h>
72 #include <nfs/rpcv2.h>
73 #include <nfs/nfsproto.h>
74 #include <nfsserver/nfs.h>
75 #include <nfs/xdr_subs.h>
76 #include <nfsserver/nfsm_subs.h>
78 #include <netinet/in.h>
81 * Data items converted to xdr at startup, since they are constant
82 * This is kinda hokey, but may save a little time doing byte swaps
84 u_int32_t nfs_xdrneg1;
85 u_int32_t rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
86 rpc_mismatch, rpc_auth_unix, rpc_msgaccepted;
87 u_int32_t nfs_prog, nfs_true, nfs_false;
89 /* And other global data */
90 static nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK,
91 NFNON, NFCHR, NFNON };
92 #define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((int32_t)(a))])
93 #define vtonfsv3_mode(m) txdr_unsigned((m) & ALLPERMS)
97 struct nfssvc_sockhead nfssvc_sockhead;
98 int nfssvc_sockhead_flag;
99 struct nfsd_head nfsd_head;
102 static int nfs_prev_nfssvc_sy_narg;
103 static sy_call_t *nfs_prev_nfssvc_sy_call;
106 * Mapping of old NFS Version 2 RPC numbers to generic numbers.
108 int nfsv3_procid[NFS_NPROCS] = {
135 * and the reverse mapping from generic to Version 2 procedure numbers
137 int nfsrvv2_procid[NFS_NPROCS] = {
164 * Maps errno values to nfs error numbers.
165 * Use NFSERR_IO as the catch all for ones not specifically defined in
168 static u_char nfsrv_v2errmap[ELAST] = {
169 NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO,
170 NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
171 NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO,
172 NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR,
173 NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
174 NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS,
175 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
176 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
177 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
178 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
179 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
180 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
181 NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO,
182 NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE,
183 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
184 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
185 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
186 NFSERR_IO /* << Last is 86 */
190 * Maps errno values to nfs error numbers.
191 * Although it is not obvious whether or not NFS clients really care if
192 * a returned error value is in the specified list for the procedure, the
193 * safest thing to do is filter them appropriately. For Version 2, the
194 * X/Open XNFS document is the only specification that defines error values
195 * for each RPC (The RFC simply lists all possible error values for all RPCs),
196 * so I have decided to not do this for Version 2.
197 * The first entry is the default error return and the rest are the valid
198 * errors for that RPC in increasing numeric order.
200 static short nfsv3err_null[] = {
205 static short nfsv3err_getattr[] = {
214 static short nfsv3err_setattr[] = {
230 static short nfsv3err_lookup[] = {
243 static short nfsv3err_access[] = {
252 static short nfsv3err_readlink[] = {
264 static short nfsv3err_read[] = {
276 static short nfsv3err_write[] = {
291 static short nfsv3err_create[] = {
308 static short nfsv3err_mkdir[] = {
325 static short nfsv3err_symlink[] = {
342 static short nfsv3err_mknod[] = {
360 static short nfsv3err_remove[] = {
374 static short nfsv3err_rmdir[] = {
392 static short nfsv3err_rename[] = {
415 static short nfsv3err_link[] = {
435 static short nfsv3err_readdir[] = {
448 static short nfsv3err_readdirplus[] = {
462 static short nfsv3err_fsstat[] = {
471 static short nfsv3err_fsinfo[] = {
479 static short nfsv3err_pathconf[] = {
487 static short nfsv3err_commit[] = {
496 static short *nfsrv_v3errmap[] = {
514 nfsv3err_readdirplus,
522 * Called once to initialize data structures...
525 nfsrv_modevent(module_t mod, int type, void *data)
530 rpc_vers = txdr_unsigned(RPC_VER2);
531 rpc_call = txdr_unsigned(RPC_CALL);
532 rpc_reply = txdr_unsigned(RPC_REPLY);
533 rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
534 rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
535 rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
536 rpc_autherr = txdr_unsigned(RPC_AUTHERR);
537 rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
538 nfs_prog = txdr_unsigned(NFS_PROG);
539 nfs_true = txdr_unsigned(TRUE);
540 nfs_false = txdr_unsigned(FALSE);
541 nfs_xdrneg1 = txdr_unsigned(-1);
542 nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
546 nfsrv_init(0); /* Init server data structures */
547 nfsrv_initcache(); /* Init the server request cache */
551 nfs_prev_nfssvc_sy_narg = sysent[SYS_nfssvc].sy_narg;
552 sysent[SYS_nfssvc].sy_narg = 2;
553 nfs_prev_nfssvc_sy_call = sysent[SYS_nfssvc].sy_call;
554 sysent[SYS_nfssvc].sy_call = (sy_call_t *)nfssvc;
559 untimeout(nfsrv_timer, (void *)NULL, nfsrv_timer_handle);
560 sysent[SYS_nfssvc].sy_narg = nfs_prev_nfssvc_sy_narg;
561 sysent[SYS_nfssvc].sy_call = nfs_prev_nfssvc_sy_call;
566 static moduledata_t nfsserver_mod = {
571 DECLARE_MODULE(nfsserver, nfsserver_mod, SI_SUB_VFS, SI_ORDER_ANY);
573 /* So that loader and kldload(2) can find us, wherever we are.. */
574 MODULE_VERSION(nfsserver, 1);
577 * Set up nameidata for a lookup() call and do it.
579 * If pubflag is set, this call is done for a lookup operation on the
580 * public filehandle. In that case we allow crossing mountpoints and
581 * absolute pathnames. However, the caller is expected to check that
582 * the lookup result is within the public fs, and deny access if
585 * nfs_namei() clears out garbage fields that namei() might leave garbage.
586 * This is mainly ni_vp and ni_dvp when an error occurs, and ni_dvp when no
587 * error occurs but the parent was not requested.
589 * dirp may be set whether an error is returned or not, and must be
590 * released by the caller.
593 nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len,
594 struct nfssvc_sock *slp, struct sockaddr *nam, struct mbuf **mdp,
595 caddr_t *dposp, struct vnode **retdirp, struct thread *td, int pubflag)
599 char *fromcp, *tocp, *cp;
603 int error, rdonly, linklen;
604 struct componentname *cnp = &ndp->ni_cnd;
606 *retdirp = (struct vnode *)0;
607 cnp->cn_pnbuf = zalloc(namei_zone);
610 * Copy the name from the mbuf list to ndp->ni_pnbuf
611 * and set the various ndp fields appropriately.
614 tocp = cnp->cn_pnbuf;
616 rem = mtod(md, caddr_t) + md->m_len - fromcp;
617 for (i = 0; i < len; i++) {
624 fromcp = mtod(md, caddr_t);
627 if (*fromcp == '\0' || (!pubflag && *fromcp == '/')) {
637 len = nfsm_rndup(len)-len;
641 else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0)
646 * Extract and set starting directory.
648 error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
649 nam, &rdonly, pubflag);
652 if (dp->v_type != VDIR) {
659 cnp->cn_flags |= RDONLY;
662 * Set return directory. Reference to dp is implicitly transfered
663 * to the returned pointer
669 * Oh joy. For WebNFS, handle those pesky '%' escapes,
670 * and the 'native path' indicator.
672 cp = zalloc(namei_zone);
673 fromcp = cnp->cn_pnbuf;
675 if ((unsigned char)*fromcp >= WEBNFS_SPECCHAR_START) {
676 switch ((unsigned char)*fromcp) {
677 case WEBNFS_NATIVE_CHAR:
679 * 'Native' path for us is the same
680 * as a path according to the NFS spec,
681 * just skip the escape char.
686 * More may be added in the future, range 0x80-0xff
690 zfree(namei_zone, cp);
695 * Translate the '%' escapes, URL-style.
697 while (*fromcp != '\0') {
698 if (*fromcp == WEBNFS_ESC_CHAR) {
699 if (fromcp[1] != '\0' && fromcp[2] != '\0') {
701 *tocp++ = HEXSTRTOI(fromcp);
706 zfree(namei_zone, cp);
713 zfree(namei_zone, cnp->cn_pnbuf);
717 ndp->ni_pathlen = (tocp - cnp->cn_pnbuf) + 1;
718 ndp->ni_segflg = UIO_SYSSPACE;
721 ndp->ni_rootdir = rootvnode;
723 if (cnp->cn_pnbuf[0] == '/')
726 cnp->cn_flags |= NOCROSSMOUNT;
730 * Initialize for scan, set ni_startdir and bump ref on dp again
731 * becuase lookup() will dereference ni_startdir.
736 ndp->ni_startdir = dp;
739 cnp->cn_nameptr = cnp->cn_pnbuf;
741 * Call lookup() to do the real work. If an error occurs,
742 * ndp->ni_vp and ni_dvp are left uninitialized or NULL and
743 * we do not have to dereference anything before returning.
744 * In either case ni_startdir will be dereferenced and NULLed
752 * Check for encountering a symbolic link. Trivial
753 * termination occurs if no symlink encountered.
754 * Note: zfree is safe because error is 0, so we will
755 * not zfree it again when we break.
757 if ((cnp->cn_flags & ISSYMLINK) == 0) {
758 nfsrv_object_create(ndp->ni_vp);
759 if (cnp->cn_flags & (SAVENAME | SAVESTART))
760 cnp->cn_flags |= HASBUF;
762 zfree(namei_zone, cnp->cn_pnbuf);
769 if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
770 VOP_UNLOCK(ndp->ni_dvp, 0, td);
776 if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
780 if (ndp->ni_pathlen > 1)
781 cp = zalloc(namei_zone);
785 aiov.iov_len = MAXPATHLEN;
786 auio.uio_iov = &aiov;
789 auio.uio_rw = UIO_READ;
790 auio.uio_segflg = UIO_SYSSPACE;
791 auio.uio_td = (struct thread *)0;
792 auio.uio_resid = MAXPATHLEN;
793 error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
796 if (ndp->ni_pathlen > 1)
797 zfree(namei_zone, cp);
803 linklen = MAXPATHLEN - auio.uio_resid;
808 if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
809 error = ENAMETOOLONG;
814 * Adjust or replace path
816 if (ndp->ni_pathlen > 1) {
817 bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
818 zfree(namei_zone, cnp->cn_pnbuf);
821 cnp->cn_pnbuf[linklen] = '\0';
822 ndp->ni_pathlen += linklen;
825 * Cleanup refs for next loop and check if root directory
826 * should replace current directory. Normally ni_dvp
827 * becomes the new base directory and is cleaned up when
828 * we loop. Explicitly null pointers after invalidation
829 * to clarify operation.
834 if (cnp->cn_pnbuf[0] == '/') {
836 ndp->ni_dvp = ndp->ni_rootdir;
839 ndp->ni_startdir = ndp->ni_dvp;
844 * nfs_namei() guarentees that fields will not contain garbage
845 * whether an error occurs or not. This allows the caller to track
846 * cleanup state trivially.
850 zfree(namei_zone, cnp->cn_pnbuf);
853 ndp->ni_startdir = NULL;
854 cnp->cn_flags &= ~HASBUF;
855 } else if ((ndp->ni_cnd.cn_flags & (WANTPARENT|LOCKPARENT)) == 0) {
862 * A fiddled version of m_adj() that ensures null fill to a long
863 * boundary and only trims off the back end
866 nfsm_adj(struct mbuf *mp, int len, int nul)
873 * Trim from tail. Scan the mbuf chain,
874 * calculating its length and finding the last mbuf.
875 * If the adjustment only affects this mbuf, then just
876 * adjust and return. Otherwise, rescan and truncate
877 * after the remaining size.
883 if (m->m_next == (struct mbuf *)0)
887 if (m->m_len > len) {
890 cp = mtod(m, caddr_t)+m->m_len-nul;
891 for (i = 0; i < nul; i++)
900 * Correct length for chain is "count".
901 * Find the mbuf with last data, adjust its length,
902 * and toss data from remaining mbufs on chain.
904 for (m = mp; m; m = m->m_next) {
905 if (m->m_len >= count) {
908 cp = mtod(m, caddr_t)+m->m_len-nul;
909 for (i = 0; i < nul; i++)
916 for (m = m->m_next;m;m = m->m_next)
921 * Make these functions instead of macros, so that the kernel text size
922 * doesn't get too big...
925 nfsm_srvwcc(struct nfsrv_descript *nfsd, int before_ret,
926 struct vattr *before_vap, int after_ret, struct vattr *after_vap,
927 struct mbuf **mbp, char **bposp)
929 struct mbuf *mb = *mbp;
934 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
937 tl = nfsm_build(u_int32_t *, 7 * NFSX_UNSIGNED);
939 txdr_hyper(before_vap->va_size, tl);
941 txdr_nfsv3time(&(before_vap->va_mtime), tl);
943 txdr_nfsv3time(&(before_vap->va_ctime), tl);
947 nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
951 nfsm_srvpostopattr(struct nfsrv_descript *nfsd, int after_ret,
952 struct vattr *after_vap, struct mbuf **mbp, char **bposp)
954 struct mbuf *mb = *mbp;
957 struct nfs_fattr *fp;
960 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
963 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED + NFSX_V3FATTR);
965 fp = (struct nfs_fattr *)tl;
966 nfsm_srvfattr(nfsd, after_vap, fp);
973 nfsm_srvfattr(struct nfsrv_descript *nfsd, struct vattr *vap,
974 struct nfs_fattr *fp)
977 fp->fa_nlink = txdr_unsigned(vap->va_nlink);
978 fp->fa_uid = txdr_unsigned(vap->va_uid);
979 fp->fa_gid = txdr_unsigned(vap->va_gid);
980 if (nfsd->nd_flag & ND_NFSV3) {
981 fp->fa_type = vtonfsv3_type(vap->va_type);
982 fp->fa_mode = vtonfsv3_mode(vap->va_mode);
983 txdr_hyper(vap->va_size, &fp->fa3_size);
984 txdr_hyper(vap->va_bytes, &fp->fa3_used);
985 fp->fa3_rdev.specdata1 = txdr_unsigned(umajor(vap->va_rdev));
986 fp->fa3_rdev.specdata2 = txdr_unsigned(uminor(vap->va_rdev));
987 fp->fa3_fsid.nfsuquad[0] = 0;
988 fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
989 fp->fa3_fileid.nfsuquad[0] = 0;
990 fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid);
991 txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
992 txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
993 txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
995 fp->fa_type = vtonfsv2_type(vap->va_type);
996 fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
997 fp->fa2_size = txdr_unsigned(vap->va_size);
998 fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
999 if (vap->va_type == VFIFO)
1000 fp->fa2_rdev = 0xffffffff;
1002 fp->fa2_rdev = txdr_unsigned(vap->va_rdev);
1003 fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
1004 fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
1005 fp->fa2_fileid = txdr_unsigned(vap->va_fileid);
1006 txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
1007 txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
1008 txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
1013 * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
1014 * - look up fsid in mount list (if not found ret error)
1015 * - get vp and export rights by calling VFS_FHTOVP()
1016 * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
1017 * - if not lockflag unlock it with VOP_UNLOCK()
1020 nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp,
1021 struct ucred *cred, struct nfssvc_sock *slp, struct sockaddr *nam,
1022 int *rdonlyp, int pubflag)
1024 struct thread *td = curthread; /* XXX */
1027 struct ucred *credanon;
1029 #ifdef MNT_EXNORESPORT /* XXX needs mountd and /etc/exports help yet */
1030 struct sockaddr_int *saddr;
1033 *vpp = (struct vnode *)0;
1035 if (nfs_ispublicfh(fhp)) {
1036 if (!pubflag || !nfs_pub.np_valid)
1038 fhp = &nfs_pub.np_handle;
1041 mp = vfs_getvfs(&fhp->fh_fsid);
1044 error = VFS_CHECKEXP(mp, nam, &exflags, &credanon);
1047 error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp);
1050 #ifdef MNT_EXNORESPORT
1051 if (!(exflags & (MNT_EXNORESPORT|MNT_EXPUBLIC))) {
1052 saddr = (struct sockaddr_in *)nam;
1053 if (saddr->sin_family == AF_INET &&
1054 ntohs(saddr->sin_port) >= IPPORT_RESERVED) {
1057 return (NFSERR_AUTHERR | AUTH_TOOWEAK);
1062 * Check/setup credentials.
1064 if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
1065 cred->cr_uid = credanon->cr_uid;
1066 for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++)
1067 cred->cr_groups[i] = credanon->cr_groups[i];
1068 cred->cr_ngroups = i;
1070 if (exflags & MNT_EXRDONLY)
1075 nfsrv_object_create(*vpp);
1078 VOP_UNLOCK(*vpp, 0, td);
1084 * WebNFS: check if a filehandle is a public filehandle. For v3, this
1085 * means a length of 0, for v2 it means all zeroes. nfsm_srvmtofh has
1086 * transformed this to all zeroes in both cases, so check for it.
1089 nfs_ispublicfh(fhandle_t *fhp)
1091 char *cp = (char *)fhp;
1094 for (i = 0; i < NFSX_V3FH; i++)
1101 * This function compares two net addresses by family and returns TRUE
1102 * if they are the same host.
1103 * If there is any doubt, return FALSE.
1104 * The AF_INET family is handled as a special case so that address mbufs
1105 * don't need to be saved to store "struct in_addr", which is only 4 bytes.
1108 netaddr_match(int family, union nethostaddr *haddr, struct sockaddr *nam)
1110 struct sockaddr_in *inetaddr;
1114 inetaddr = (struct sockaddr_in *)nam;
1115 if (inetaddr->sin_family == AF_INET &&
1116 inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
1126 * Map errnos to NFS error numbers. For Version 3 also filter out error
1127 * numbers not specified for the associated procedure.
1130 nfsrv_errmap(struct nfsrv_descript *nd, int err)
1132 short *defaulterrp, *errp;
1134 if (nd->nd_flag & ND_NFSV3) {
1135 if (nd->nd_procnum <= NFSPROC_COMMIT) {
1136 errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
1140 else if (*errp > err)
1143 return ((int)*defaulterrp);
1145 return (err & 0xffff);
1148 return ((int)nfsrv_v2errmap[err - 1]);
1153 nfsrv_object_create(struct vnode *vp)
1156 if (vp == NULL || vp->v_type != VREG)
1158 return (vfs_object_create(vp, curthread,
1159 curthread ? curthread->td_proc->p_ucred : NULL));
1163 * Sort the group list in increasing numerical order.
1164 * (Insertion sort by Chris Torek, who was grossed out by the bubble sort
1165 * that used to be here.)
1168 nfsrvw_sort(gid_t *list, int num)
1173 /* Insertion sort. */
1174 for (i = 1; i < num; i++) {
1176 /* find correct slot for value v, moving others up */
1177 for (j = i; --j >= 0 && v < list[j];)
1178 list[j + 1] = list[j];
1184 * copy credentials making sure that the result can be compared with bcmp().
1187 nfsrv_setcred(struct ucred *incred, struct ucred *outcred)
1191 bzero((caddr_t)outcred, sizeof (struct ucred));
1192 outcred->cr_ref = 1;
1193 outcred->cr_uid = incred->cr_uid;
1194 outcred->cr_ngroups = incred->cr_ngroups;
1195 for (i = 0; i < incred->cr_ngroups; i++)
1196 outcred->cr_groups[i] = incred->cr_groups[i];
1197 nfsrvw_sort(outcred->cr_groups, outcred->cr_ngroups);
1201 * Helper functions for macros.
1205 nfsm_srvfhtom_xx(fhandle_t *f, int v3,
1206 u_int32_t **tl, struct mbuf **mb, caddr_t *bpos)
1211 *tl = nfsm_build_xx(NFSX_UNSIGNED + NFSX_V3FH, mb, bpos);
1212 *(*tl)++ = txdr_unsigned(NFSX_V3FH);
1213 bcopy(f, (*tl), NFSX_V3FH);
1215 cp = nfsm_build_xx(NFSX_V2FH, mb, bpos);
1216 bcopy(f, cp, NFSX_V2FH);
1221 nfsm_srvpostop_fh_xx(fhandle_t *f,
1222 u_int32_t **tl, struct mbuf **mb, caddr_t *bpos)
1225 *tl = nfsm_build_xx(2 * NFSX_UNSIGNED + NFSX_V3FH, mb, bpos);
1226 *(*tl)++ = nfs_true;
1227 *(*tl)++ = txdr_unsigned(NFSX_V3FH);
1228 bcopy(f, (*tl), NFSX_V3FH);
1232 nfsm_srvstrsiz_xx(int *s, int m,
1233 u_int32_t **tl, struct mbuf **md, caddr_t *dpos)
1236 *tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
1239 *s = fxdr_unsigned(int32_t, **tl);
1240 if (*s > m || *s <= 0)
1246 nfsm_srvnamesiz_xx(int *s,
1247 u_int32_t **tl, struct mbuf **md, caddr_t *dpos)
1250 *tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
1253 *s = fxdr_unsigned(int32_t, **tl);
1254 if (*s > NFS_MAXNAMLEN)
1255 return NFSERR_NAMETOL;
1262 nfsm_clget_xx(u_int32_t **tl, struct mbuf *mb, struct mbuf **mp,
1263 char **bp, char **be, caddr_t bpos)
1269 (*mp)->m_len += *bp - bpos;
1270 MGET(nmp, M_TRYWAIT, MT_DATA);
1271 MCLGET(nmp, M_TRYWAIT);
1272 nmp->m_len = NFSMSIZ(nmp);
1273 (*mp)->m_next = nmp;
1275 *bp = mtod(*mp, caddr_t);
1276 *be = *bp + (*mp)->m_len;
1278 *tl = (u_int32_t *)*bp;
1282 nfsm_srvmtofh_xx(fhandle_t *f, struct nfsrv_descript *nfsd,
1283 u_int32_t **tl, struct mbuf **md, caddr_t *dpos)
1287 if (nfsd->nd_flag & ND_NFSV3) {
1288 *tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
1291 fhlen = fxdr_unsigned(int, **tl);
1292 if (fhlen != 0 && fhlen != NFSX_V3FH)
1298 *tl = nfsm_dissect_xx(fhlen, md, dpos);
1301 bcopy((caddr_t)*tl, (caddr_t)(f), fhlen);
1303 bzero((caddr_t)(f), NFSX_V3FH);
1309 nfsm_srvsattr_xx(struct vattr *a,
1310 u_int32_t **tl, struct mbuf **md, caddr_t *dpos)
1313 *tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
1316 if (**tl == nfs_true) {
1317 *tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
1320 (a)->va_mode = nfstov_mode(**tl);
1322 *tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
1325 if (**tl == nfs_true) {
1326 *tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
1329 (a)->va_uid = fxdr_unsigned(uid_t, **tl);
1331 *tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
1334 if (**tl == nfs_true) {
1335 *tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
1338 (a)->va_gid = fxdr_unsigned(gid_t, **tl);
1340 *tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
1343 if (**tl == nfs_true) {
1344 *tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
1347 (a)->va_size = fxdr_hyper(*tl);
1349 *tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
1352 switch (fxdr_unsigned(int, **tl)) {
1353 case NFSV3SATTRTIME_TOCLIENT:
1354 *tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
1357 fxdr_nfsv3time(*tl, &(a)->va_atime);
1359 case NFSV3SATTRTIME_TOSERVER:
1360 getnanotime(&(a)->va_atime);
1363 *tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
1366 switch (fxdr_unsigned(int, **tl)) {
1367 case NFSV3SATTRTIME_TOCLIENT:
1368 *tl = nfsm_dissect_xx(2 * NFSX_UNSIGNED, md, dpos);
1371 fxdr_nfsv3time(*tl, &(a)->va_mtime);
1373 case NFSV3SATTRTIME_TOSERVER:
1374 getnanotime(&(a)->va_mtime);