1 1.6 rin /* $NetBSD: nfs_nfsdserv.c,v 1.6 2024/07/05 04:31:52 rin Exp $ */ 2 1.1 dholland /*- 3 1.1 dholland * Copyright (c) 1989, 1993 4 1.1 dholland * The Regents of the University of California. All rights reserved. 5 1.1 dholland * 6 1.1 dholland * This code is derived from software contributed to Berkeley by 7 1.1 dholland * Rick Macklem at The University of Guelph. 8 1.1 dholland * 9 1.1 dholland * Redistribution and use in source and binary forms, with or without 10 1.1 dholland * modification, are permitted provided that the following conditions 11 1.1 dholland * are met: 12 1.1 dholland * 1. Redistributions of source code must retain the above copyright 13 1.1 dholland * notice, this list of conditions and the following disclaimer. 14 1.1 dholland * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 dholland * notice, this list of conditions and the following disclaimer in the 16 1.1 dholland * documentation and/or other materials provided with the distribution. 17 1.1 dholland * 4. Neither the name of the University nor the names of its contributors 18 1.1 dholland * may be used to endorse or promote products derived from this software 19 1.1 dholland * without specific prior written permission. 20 1.1 dholland * 21 1.1 dholland * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 1.1 dholland * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 1.1 dholland * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 1.1 dholland * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 1.1 dholland * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 1.1 dholland * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 1.1 dholland * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 1.1 dholland * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 1.1 dholland * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 1.1 dholland * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 1.1 dholland * SUCH DAMAGE. 32 1.1 dholland * 33 1.1 dholland */ 34 1.1 dholland 35 1.1 dholland #include <sys/cdefs.h> 36 1.3 pgoyette /* __FBSDID("FreeBSD: head/sys/fs/nfsserver/nfs_nfsdserv.c 299514 2016-05-12 05:03:12Z cem "); */ 37 1.6 rin __RCSID("$NetBSD: nfs_nfsdserv.c,v 1.6 2024/07/05 04:31:52 rin Exp $"); 38 1.1 dholland 39 1.1 dholland /* 40 1.1 dholland * nfs version 2, 3 and 4 server calls to vnode ops 41 1.1 dholland * - these routines generally have 3 phases 42 1.1 dholland * 1 - break down and validate rpc request in mbuf list 43 1.1 dholland * 2 - do the vnode ops for the request, usually by calling a nfsvno_XXX() 44 1.1 dholland * function in nfsd_port.c 45 1.1 dholland * 3 - build the rpc reply in an mbuf list 46 1.1 dholland * For nfsv4, these functions are called for each Op within the Compound RPC. 47 1.1 dholland */ 48 1.1 dholland 49 1.1 dholland #ifndef APPLEKEXT 50 1.4 pgoyette #include <fs/nfs/common/nfsport.h> 51 1.1 dholland 52 1.1 dholland /* Global vars */ 53 1.1 dholland extern u_int32_t newnfs_false, newnfs_true; 54 1.1 dholland extern enum vtype nv34tov_type[8]; 55 1.1 dholland extern struct timeval nfsboottime; 56 1.1 dholland extern int nfs_rootfhset; 57 1.1 dholland extern int nfsrv_enable_crossmntpt; 58 1.3 pgoyette extern int nfsrv_statehashsize; 59 1.1 dholland #endif /* !APPLEKEXT */ 60 1.1 dholland 61 1.1 dholland static int nfs_async = 0; 62 1.1 dholland SYSCTL_DECL(_vfs_nfsd); 63 1.1 dholland SYSCTL_INT(_vfs_nfsd, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0, 64 1.1 dholland "Tell client that writes were synced even though they were not"); 65 1.1 dholland 66 1.1 dholland /* 67 1.1 dholland * This list defines the GSS mechanisms supported. 68 1.1 dholland * (Don't ask me how you get these strings from the RFC stuff like 69 1.1 dholland * iso(1), org(3)... but someone did it, so I don't need to know.) 70 1.1 dholland */ 71 1.1 dholland static struct nfsgss_mechlist nfsgss_mechlist[] = { 72 1.1 dholland { 9, "\052\206\110\206\367\022\001\002\002", 11 }, 73 1.1 dholland { 0, "", 0 }, 74 1.1 dholland }; 75 1.1 dholland 76 1.1 dholland /* local functions */ 77 1.1 dholland static void nfsrvd_symlinksub(struct nfsrv_descript *nd, struct nameidata *ndp, 78 1.1 dholland struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp, 79 1.1 dholland vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp, 80 1.1 dholland int *diraft_retp, nfsattrbit_t *attrbitp, 81 1.1 dholland NFSACL_T *aclp, NFSPROC_T *p, struct nfsexstuff *exp, char *pathcp, 82 1.1 dholland int pathlen); 83 1.1 dholland static void nfsrvd_mkdirsub(struct nfsrv_descript *nd, struct nameidata *ndp, 84 1.1 dholland struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp, 85 1.1 dholland vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp, 86 1.1 dholland int *diraft_retp, nfsattrbit_t *attrbitp, NFSACL_T *aclp, 87 1.1 dholland NFSPROC_T *p, struct nfsexstuff *exp); 88 1.1 dholland 89 1.1 dholland /* 90 1.1 dholland * nfs access service (not a part of NFS V2) 91 1.1 dholland */ 92 1.1 dholland APPLESTATIC int 93 1.1 dholland nfsrvd_access(struct nfsrv_descript *nd, __unused int isdgram, 94 1.1 dholland vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp) 95 1.1 dholland { 96 1.1 dholland u_int32_t *tl; 97 1.1 dholland int getret, error = 0; 98 1.1 dholland struct nfsvattr nva; 99 1.1 dholland u_int32_t testmode, nfsmode, supported = 0; 100 1.1 dholland accmode_t deletebit; 101 1.1 dholland 102 1.1 dholland if (nd->nd_repstat) { 103 1.1 dholland nfsrv_postopattr(nd, 1, &nva); 104 1.1 dholland goto out; 105 1.1 dholland } 106 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 107 1.1 dholland nfsmode = fxdr_unsigned(u_int32_t, *tl); 108 1.1 dholland if ((nd->nd_flag & ND_NFSV4) && 109 1.1 dholland (nfsmode & ~(NFSACCESS_READ | NFSACCESS_LOOKUP | 110 1.1 dholland NFSACCESS_MODIFY | NFSACCESS_EXTEND | NFSACCESS_DELETE | 111 1.1 dholland NFSACCESS_EXECUTE))) { 112 1.1 dholland nd->nd_repstat = NFSERR_INVAL; 113 1.1 dholland vput(vp); 114 1.1 dholland goto out; 115 1.1 dholland } 116 1.1 dholland if (nfsmode & NFSACCESS_READ) { 117 1.1 dholland supported |= NFSACCESS_READ; 118 1.1 dholland if (nfsvno_accchk(vp, VREAD, nd->nd_cred, exp, p, 119 1.1 dholland NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported)) 120 1.1 dholland nfsmode &= ~NFSACCESS_READ; 121 1.1 dholland } 122 1.1 dholland if (nfsmode & NFSACCESS_MODIFY) { 123 1.1 dholland supported |= NFSACCESS_MODIFY; 124 1.1 dholland if (nfsvno_accchk(vp, VWRITE, nd->nd_cred, exp, p, 125 1.1 dholland NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported)) 126 1.1 dholland nfsmode &= ~NFSACCESS_MODIFY; 127 1.1 dholland } 128 1.1 dholland if (nfsmode & NFSACCESS_EXTEND) { 129 1.1 dholland supported |= NFSACCESS_EXTEND; 130 1.1 dholland if (nfsvno_accchk(vp, VWRITE | VAPPEND, nd->nd_cred, exp, p, 131 1.1 dholland NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported)) 132 1.1 dholland nfsmode &= ~NFSACCESS_EXTEND; 133 1.1 dholland } 134 1.1 dholland if (nfsmode & NFSACCESS_DELETE) { 135 1.1 dholland supported |= NFSACCESS_DELETE; 136 1.1 dholland if (vp->v_type == VDIR) 137 1.1 dholland deletebit = VDELETE_CHILD; 138 1.1 dholland else 139 1.1 dholland deletebit = VDELETE; 140 1.1 dholland if (nfsvno_accchk(vp, deletebit, nd->nd_cred, exp, p, 141 1.1 dholland NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported)) 142 1.1 dholland nfsmode &= ~NFSACCESS_DELETE; 143 1.1 dholland } 144 1.1 dholland if (vnode_vtype(vp) == VDIR) 145 1.1 dholland testmode = NFSACCESS_LOOKUP; 146 1.1 dholland else 147 1.1 dholland testmode = NFSACCESS_EXECUTE; 148 1.1 dholland if (nfsmode & testmode) { 149 1.1 dholland supported |= (nfsmode & testmode); 150 1.1 dholland if (nfsvno_accchk(vp, VEXEC, nd->nd_cred, exp, p, 151 1.1 dholland NFSACCCHK_NOOVERRIDE, NFSACCCHK_VPISLOCKED, &supported)) 152 1.1 dholland nfsmode &= ~testmode; 153 1.1 dholland } 154 1.1 dholland nfsmode &= supported; 155 1.1 dholland if (nd->nd_flag & ND_NFSV3) { 156 1.1 dholland getret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); 157 1.1 dholland nfsrv_postopattr(nd, getret, &nva); 158 1.1 dholland } 159 1.1 dholland vput(vp); 160 1.1 dholland if (nd->nd_flag & ND_NFSV4) { 161 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 162 1.1 dholland *tl++ = txdr_unsigned(supported); 163 1.1 dholland } else 164 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 165 1.1 dholland *tl = txdr_unsigned(nfsmode); 166 1.1 dholland 167 1.1 dholland out: 168 1.1 dholland NFSEXITCODE2(0, nd); 169 1.1 dholland return (0); 170 1.1 dholland nfsmout: 171 1.1 dholland vput(vp); 172 1.1 dholland NFSEXITCODE2(error, nd); 173 1.1 dholland return (error); 174 1.1 dholland } 175 1.1 dholland 176 1.1 dholland /* 177 1.1 dholland * nfs getattr service 178 1.1 dholland */ 179 1.1 dholland APPLESTATIC int 180 1.1 dholland nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram, 181 1.1 dholland vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 182 1.1 dholland { 183 1.1 dholland struct nfsvattr nva; 184 1.1 dholland fhandle_t fh; 185 1.1 dholland int at_root = 0, error = 0, supports_nfsv4acls; 186 1.1 dholland struct nfsreferral *refp; 187 1.1 dholland nfsattrbit_t attrbits, tmpbits; 188 1.1 dholland struct mount *mp; 189 1.1 dholland struct vnode *tvp = NULL; 190 1.1 dholland struct vattr va; 191 1.1 dholland uint64_t mounted_on_fileno = 0; 192 1.1 dholland accmode_t accmode; 193 1.1 dholland 194 1.1 dholland if (nd->nd_repstat) 195 1.1 dholland goto out; 196 1.1 dholland if (nd->nd_flag & ND_NFSV4) { 197 1.1 dholland error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL); 198 1.1 dholland if (error) { 199 1.1 dholland vput(vp); 200 1.1 dholland goto out; 201 1.1 dholland } 202 1.1 dholland 203 1.1 dholland /* 204 1.1 dholland * Check for a referral. 205 1.1 dholland */ 206 1.1 dholland refp = nfsv4root_getreferral(vp, NULL, 0); 207 1.1 dholland if (refp != NULL) { 208 1.1 dholland (void) nfsrv_putreferralattr(nd, &attrbits, refp, 1, 209 1.1 dholland &nd->nd_repstat); 210 1.1 dholland vput(vp); 211 1.1 dholland goto out; 212 1.1 dholland } 213 1.1 dholland if (nd->nd_repstat == 0) { 214 1.1 dholland accmode = 0; 215 1.1 dholland NFSSET_ATTRBIT(&tmpbits, &attrbits); 216 1.3 pgoyette 217 1.3 pgoyette /* 218 1.3 pgoyette * GETATTR with write-only attr time_access_set and time_modify_set 219 1.3 pgoyette * should return NFS4ERR_INVAL. 220 1.3 pgoyette */ 221 1.3 pgoyette if (NFSISSET_ATTRBIT(&tmpbits, NFSATTRBIT_TIMEACCESSSET) || 222 1.3 pgoyette NFSISSET_ATTRBIT(&tmpbits, NFSATTRBIT_TIMEMODIFYSET)){ 223 1.3 pgoyette error = NFSERR_INVAL; 224 1.3 pgoyette vput(vp); 225 1.3 pgoyette goto out; 226 1.3 pgoyette } 227 1.1 dholland if (NFSISSET_ATTRBIT(&tmpbits, NFSATTRBIT_ACL)) { 228 1.1 dholland NFSCLRBIT_ATTRBIT(&tmpbits, NFSATTRBIT_ACL); 229 1.1 dholland accmode |= VREAD_ACL; 230 1.1 dholland } 231 1.1 dholland if (NFSNONZERO_ATTRBIT(&tmpbits)) 232 1.1 dholland accmode |= VREAD_ATTRIBUTES; 233 1.1 dholland if (accmode != 0) 234 1.1 dholland nd->nd_repstat = nfsvno_accchk(vp, accmode, 235 1.1 dholland nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE, 236 1.1 dholland NFSACCCHK_VPISLOCKED, NULL); 237 1.1 dholland } 238 1.1 dholland } 239 1.1 dholland if (!nd->nd_repstat) 240 1.1 dholland nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); 241 1.1 dholland if (!nd->nd_repstat) { 242 1.1 dholland if (nd->nd_flag & ND_NFSV4) { 243 1.1 dholland if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_FILEHANDLE)) 244 1.1 dholland nd->nd_repstat = nfsvno_getfh(vp, &fh, p); 245 1.1 dholland if (!nd->nd_repstat) 246 1.1 dholland nd->nd_repstat = nfsrv_checkgetattr(nd, vp, 247 1.1 dholland &nva, &attrbits, nd->nd_cred, p); 248 1.1 dholland if (nd->nd_repstat == 0) { 249 1.1 dholland supports_nfsv4acls = nfs_supportsnfsv4acls(vp); 250 1.1 dholland mp = vp->v_mount; 251 1.1 dholland if (nfsrv_enable_crossmntpt != 0 && 252 1.1 dholland vp->v_type == VDIR && 253 1.1 dholland (vp->v_vflag & VV_ROOT) != 0 && 254 1.1 dholland vp != rootvnode) { 255 1.1 dholland tvp = mp->mnt_vnodecovered; 256 1.1 dholland VREF(tvp); 257 1.1 dholland at_root = 1; 258 1.1 dholland } else 259 1.1 dholland at_root = 0; 260 1.1 dholland vfs_ref(mp); 261 1.1 dholland NFSVOPUNLOCK(vp, 0); 262 1.1 dholland if (at_root != 0) { 263 1.1 dholland if ((nd->nd_repstat = 264 1.1 dholland NFSVOPLOCK(tvp, LK_SHARED)) == 0) { 265 1.1 dholland nd->nd_repstat = VOP_GETATTR( 266 1.1 dholland tvp, &va, nd->nd_cred); 267 1.1 dholland vput(tvp); 268 1.1 dholland } else 269 1.1 dholland vrele(tvp); 270 1.1 dholland if (nd->nd_repstat == 0) 271 1.1 dholland mounted_on_fileno = (uint64_t) 272 1.1 dholland va.va_fileid; 273 1.1 dholland else 274 1.1 dholland at_root = 0; 275 1.1 dholland } 276 1.1 dholland if (nd->nd_repstat == 0) 277 1.1 dholland nd->nd_repstat = vfs_busy(mp, 0); 278 1.1 dholland vfs_rel(mp); 279 1.1 dholland if (nd->nd_repstat == 0) { 280 1.1 dholland (void)nfsvno_fillattr(nd, mp, vp, &nva, 281 1.1 dholland &fh, 0, &attrbits, nd->nd_cred, p, 282 1.1 dholland isdgram, 1, supports_nfsv4acls, 283 1.1 dholland at_root, mounted_on_fileno); 284 1.1 dholland vfs_unbusy(mp); 285 1.1 dholland } 286 1.1 dholland vrele(vp); 287 1.1 dholland } else 288 1.1 dholland vput(vp); 289 1.1 dholland } else { 290 1.1 dholland nfsrv_fillattr(nd, &nva); 291 1.1 dholland vput(vp); 292 1.1 dholland } 293 1.1 dholland } else { 294 1.1 dholland vput(vp); 295 1.1 dholland } 296 1.1 dholland 297 1.1 dholland out: 298 1.1 dholland NFSEXITCODE2(error, nd); 299 1.1 dholland return (error); 300 1.1 dholland } 301 1.1 dholland 302 1.1 dholland /* 303 1.1 dholland * nfs setattr service 304 1.1 dholland */ 305 1.1 dholland APPLESTATIC int 306 1.1 dholland nfsrvd_setattr(struct nfsrv_descript *nd, __unused int isdgram, 307 1.1 dholland vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp) 308 1.1 dholland { 309 1.1 dholland struct nfsvattr nva, nva2; 310 1.1 dholland u_int32_t *tl; 311 1.1 dholland int preat_ret = 1, postat_ret = 1, gcheck = 0, error = 0; 312 1.1 dholland struct timespec guard = { 0, 0 }; 313 1.1 dholland nfsattrbit_t attrbits, retbits; 314 1.1 dholland nfsv4stateid_t stateid; 315 1.1 dholland NFSACL_T *aclp = NULL; 316 1.1 dholland 317 1.1 dholland if (nd->nd_repstat) { 318 1.1 dholland nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva); 319 1.1 dholland goto out; 320 1.1 dholland } 321 1.1 dholland #ifdef NFS4_ACL_EXTATTR_NAME 322 1.1 dholland aclp = acl_alloc(M_WAITOK); 323 1.1 dholland aclp->acl_cnt = 0; 324 1.1 dholland #endif 325 1.1 dholland NFSVNO_ATTRINIT(&nva); 326 1.1 dholland NFSZERO_ATTRBIT(&retbits); 327 1.1 dholland if (nd->nd_flag & ND_NFSV4) { 328 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID); 329 1.1 dholland stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 330 1.1 dholland NFSBCOPY((caddr_t)tl,(caddr_t)stateid.other,NFSX_STATEIDOTHER); 331 1.1 dholland } 332 1.3 pgoyette error = nfsrv_sattr(nd, vp, &nva, &attrbits, aclp, p); 333 1.1 dholland if (error) 334 1.1 dholland goto nfsmout; 335 1.1 dholland preat_ret = nfsvno_getattr(vp, &nva2, nd->nd_cred, p, 1); 336 1.1 dholland if (!nd->nd_repstat) 337 1.1 dholland nd->nd_repstat = preat_ret; 338 1.1 dholland if (nd->nd_flag & ND_NFSV3) { 339 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 340 1.1 dholland gcheck = fxdr_unsigned(int, *tl); 341 1.1 dholland if (gcheck) { 342 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 343 1.1 dholland fxdr_nfsv3time(tl, &guard); 344 1.1 dholland } 345 1.1 dholland if (!nd->nd_repstat && gcheck && 346 1.1 dholland (nva2.na_ctime.tv_sec != guard.tv_sec || 347 1.1 dholland nva2.na_ctime.tv_nsec != guard.tv_nsec)) 348 1.1 dholland nd->nd_repstat = NFSERR_NOT_SYNC; 349 1.1 dholland if (nd->nd_repstat) { 350 1.1 dholland vput(vp); 351 1.1 dholland #ifdef NFS4_ACL_EXTATTR_NAME 352 1.1 dholland acl_free(aclp); 353 1.1 dholland #endif 354 1.1 dholland nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva); 355 1.1 dholland goto out; 356 1.1 dholland } 357 1.1 dholland } else if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4)) 358 1.1 dholland nd->nd_repstat = nfsrv_checkuidgid(nd, &nva); 359 1.1 dholland 360 1.1 dholland /* 361 1.1 dholland * Now that we have all the fields, lets do it. 362 1.1 dholland * If the size is being changed write access is required, otherwise 363 1.1 dholland * just check for a read only file system. 364 1.1 dholland */ 365 1.1 dholland if (!nd->nd_repstat) { 366 1.1 dholland if (NFSVNO_NOTSETSIZE(&nva)) { 367 1.1 dholland if (NFSVNO_EXRDONLY(exp) || 368 1.1 dholland (vfs_flags(vnode_mount(vp)) & MNT_RDONLY)) 369 1.1 dholland nd->nd_repstat = EROFS; 370 1.1 dholland } else { 371 1.1 dholland if (vnode_vtype(vp) != VREG) 372 1.1 dholland nd->nd_repstat = EINVAL; 373 1.1 dholland else if (nva2.na_uid != nd->nd_cred->cr_uid || 374 1.1 dholland NFSVNO_EXSTRICTACCESS(exp)) 375 1.1 dholland nd->nd_repstat = nfsvno_accchk(vp, 376 1.1 dholland VWRITE, nd->nd_cred, exp, p, 377 1.1 dholland NFSACCCHK_NOOVERRIDE, 378 1.1 dholland NFSACCCHK_VPISLOCKED, NULL); 379 1.1 dholland } 380 1.1 dholland } 381 1.1 dholland if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4)) 382 1.1 dholland nd->nd_repstat = nfsrv_checksetattr(vp, nd, &stateid, 383 1.1 dholland &nva, &attrbits, exp, p); 384 1.1 dholland 385 1.1 dholland if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4)) { 386 1.1 dholland /* 387 1.5 andvar * For V4, try setting the attributes in sets, so that the 388 1.1 dholland * reply bitmap will be correct for an error case. 389 1.1 dholland */ 390 1.1 dholland if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNER) || 391 1.1 dholland NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNERGROUP)) { 392 1.1 dholland NFSVNO_ATTRINIT(&nva2); 393 1.1 dholland NFSVNO_SETATTRVAL(&nva2, uid, nva.na_uid); 394 1.1 dholland NFSVNO_SETATTRVAL(&nva2, gid, nva.na_gid); 395 1.1 dholland nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p, 396 1.1 dholland exp); 397 1.1 dholland if (!nd->nd_repstat) { 398 1.1 dholland if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNER)) 399 1.1 dholland NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_OWNER); 400 1.1 dholland if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_OWNERGROUP)) 401 1.1 dholland NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_OWNERGROUP); 402 1.1 dholland } 403 1.1 dholland } 404 1.1 dholland if (!nd->nd_repstat && 405 1.1 dholland NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_SIZE)) { 406 1.1 dholland NFSVNO_ATTRINIT(&nva2); 407 1.1 dholland NFSVNO_SETATTRVAL(&nva2, size, nva.na_size); 408 1.1 dholland nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p, 409 1.1 dholland exp); 410 1.1 dholland if (!nd->nd_repstat) 411 1.1 dholland NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_SIZE); 412 1.1 dholland } 413 1.1 dholland if (!nd->nd_repstat && 414 1.1 dholland (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESSSET) || 415 1.1 dholland NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFYSET))) { 416 1.1 dholland NFSVNO_ATTRINIT(&nva2); 417 1.1 dholland NFSVNO_SETATTRVAL(&nva2, atime, nva.na_atime); 418 1.1 dholland NFSVNO_SETATTRVAL(&nva2, mtime, nva.na_mtime); 419 1.1 dholland if (nva.na_vaflags & VA_UTIMES_NULL) { 420 1.1 dholland nva2.na_vaflags |= VA_UTIMES_NULL; 421 1.1 dholland NFSVNO_SETACTIVE(&nva2, vaflags); 422 1.1 dholland } 423 1.1 dholland nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p, 424 1.1 dholland exp); 425 1.1 dholland if (!nd->nd_repstat) { 426 1.1 dholland if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESSSET)) 427 1.1 dholland NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_TIMEACCESSSET); 428 1.1 dholland if (NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFYSET)) 429 1.1 dholland NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_TIMEMODIFYSET); 430 1.1 dholland } 431 1.1 dholland } 432 1.1 dholland if (!nd->nd_repstat && 433 1.1 dholland NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_MODE)) { 434 1.1 dholland NFSVNO_ATTRINIT(&nva2); 435 1.1 dholland NFSVNO_SETATTRVAL(&nva2, mode, nva.na_mode); 436 1.1 dholland nd->nd_repstat = nfsvno_setattr(vp, &nva2, nd->nd_cred, p, 437 1.1 dholland exp); 438 1.1 dholland if (!nd->nd_repstat) 439 1.1 dholland NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_MODE); 440 1.1 dholland } 441 1.1 dholland 442 1.1 dholland #ifdef NFS4_ACL_EXTATTR_NAME 443 1.1 dholland if (!nd->nd_repstat && aclp->acl_cnt > 0 && 444 1.1 dholland NFSISSET_ATTRBIT(&attrbits, NFSATTRBIT_ACL)) { 445 1.1 dholland nd->nd_repstat = nfsrv_setacl(vp, aclp, nd->nd_cred, p); 446 1.1 dholland if (!nd->nd_repstat) 447 1.1 dholland NFSSETBIT_ATTRBIT(&retbits, NFSATTRBIT_ACL); 448 1.1 dholland } 449 1.1 dholland #endif 450 1.1 dholland } else if (!nd->nd_repstat) { 451 1.1 dholland nd->nd_repstat = nfsvno_setattr(vp, &nva, nd->nd_cred, p, 452 1.1 dholland exp); 453 1.1 dholland } 454 1.1 dholland if (nd->nd_flag & (ND_NFSV2 | ND_NFSV3)) { 455 1.1 dholland postat_ret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); 456 1.1 dholland if (!nd->nd_repstat) 457 1.1 dholland nd->nd_repstat = postat_ret; 458 1.1 dholland } 459 1.1 dholland vput(vp); 460 1.1 dholland #ifdef NFS4_ACL_EXTATTR_NAME 461 1.1 dholland acl_free(aclp); 462 1.1 dholland #endif 463 1.1 dholland if (nd->nd_flag & ND_NFSV3) 464 1.1 dholland nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva); 465 1.1 dholland else if (nd->nd_flag & ND_NFSV4) 466 1.1 dholland (void) nfsrv_putattrbit(nd, &retbits); 467 1.1 dholland else if (!nd->nd_repstat) 468 1.1 dholland nfsrv_fillattr(nd, &nva); 469 1.1 dholland 470 1.1 dholland out: 471 1.1 dholland NFSEXITCODE2(0, nd); 472 1.1 dholland return (0); 473 1.1 dholland nfsmout: 474 1.1 dholland vput(vp); 475 1.1 dholland #ifdef NFS4_ACL_EXTATTR_NAME 476 1.1 dholland acl_free(aclp); 477 1.1 dholland #endif 478 1.1 dholland if (nd->nd_flag & ND_NFSV4) { 479 1.1 dholland /* 480 1.1 dholland * For all nd_repstat, the V4 reply includes a bitmap, 481 1.1 dholland * even NFSERR_BADXDR, which is what this will end up 482 1.1 dholland * returning. 483 1.1 dholland */ 484 1.1 dholland (void) nfsrv_putattrbit(nd, &retbits); 485 1.1 dholland } 486 1.1 dholland NFSEXITCODE2(error, nd); 487 1.1 dholland return (error); 488 1.1 dholland } 489 1.1 dholland 490 1.1 dholland /* 491 1.1 dholland * nfs lookup rpc 492 1.1 dholland * (Also performs lookup parent for v4) 493 1.1 dholland */ 494 1.1 dholland APPLESTATIC int 495 1.1 dholland nfsrvd_lookup(struct nfsrv_descript *nd, __unused int isdgram, 496 1.1 dholland vnode_t dp, vnode_t *vpp, fhandle_t *fhp, NFSPROC_T *p, 497 1.1 dholland struct nfsexstuff *exp) 498 1.1 dholland { 499 1.1 dholland struct nameidata named; 500 1.1 dholland vnode_t vp, dirp = NULL; 501 1.1 dholland int error = 0, dattr_ret = 1; 502 1.1 dholland struct nfsvattr nva, dattr; 503 1.1 dholland char *bufp; 504 1.1 dholland u_long *hashp; 505 1.1 dholland 506 1.1 dholland if (nd->nd_repstat) { 507 1.1 dholland nfsrv_postopattr(nd, dattr_ret, &dattr); 508 1.1 dholland goto out; 509 1.1 dholland } 510 1.1 dholland 511 1.1 dholland /* 512 1.1 dholland * For some reason, if dp is a symlink, the error 513 1.1 dholland * returned is supposed to be NFSERR_SYMLINK and not NFSERR_NOTDIR. 514 1.1 dholland */ 515 1.1 dholland if (dp->v_type == VLNK && (nd->nd_flag & ND_NFSV4)) { 516 1.1 dholland nd->nd_repstat = NFSERR_SYMLINK; 517 1.1 dholland vrele(dp); 518 1.1 dholland goto out; 519 1.1 dholland } 520 1.1 dholland 521 1.1 dholland NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP, 522 1.1 dholland LOCKLEAF | SAVESTART); 523 1.1 dholland nfsvno_setpathbuf(&named, &bufp, &hashp); 524 1.1 dholland error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 525 1.1 dholland if (error) { 526 1.1 dholland vrele(dp); 527 1.1 dholland nfsvno_relpathbuf(&named); 528 1.1 dholland goto out; 529 1.1 dholland } 530 1.1 dholland if (!nd->nd_repstat) { 531 1.1 dholland nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp); 532 1.1 dholland } else { 533 1.1 dholland vrele(dp); 534 1.1 dholland nfsvno_relpathbuf(&named); 535 1.1 dholland } 536 1.1 dholland if (nd->nd_repstat) { 537 1.1 dholland if (dirp) { 538 1.1 dholland if (nd->nd_flag & ND_NFSV3) 539 1.1 dholland dattr_ret = nfsvno_getattr(dirp, &dattr, 540 1.1 dholland nd->nd_cred, p, 0); 541 1.1 dholland vrele(dirp); 542 1.1 dholland } 543 1.1 dholland if (nd->nd_flag & ND_NFSV3) 544 1.1 dholland nfsrv_postopattr(nd, dattr_ret, &dattr); 545 1.1 dholland goto out; 546 1.1 dholland } 547 1.1 dholland if (named.ni_startdir) 548 1.1 dholland vrele(named.ni_startdir); 549 1.1 dholland nfsvno_relpathbuf(&named); 550 1.1 dholland vp = named.ni_vp; 551 1.1 dholland if ((nd->nd_flag & ND_NFSV4) != 0 && !NFSVNO_EXPORTED(exp) && 552 1.1 dholland vp->v_type != VDIR && vp->v_type != VLNK) 553 1.1 dholland /* 554 1.1 dholland * Only allow lookup of VDIR and VLNK for traversal of 555 1.1 dholland * non-exported volumes during NFSv4 mounting. 556 1.1 dholland */ 557 1.1 dholland nd->nd_repstat = ENOENT; 558 1.1 dholland if (nd->nd_repstat == 0) 559 1.1 dholland nd->nd_repstat = nfsvno_getfh(vp, fhp, p); 560 1.1 dholland if (!(nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) 561 1.1 dholland nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); 562 1.1 dholland if (vpp != NULL && nd->nd_repstat == 0) 563 1.1 dholland *vpp = vp; 564 1.1 dholland else 565 1.1 dholland vput(vp); 566 1.1 dholland if (dirp) { 567 1.1 dholland if (nd->nd_flag & ND_NFSV3) 568 1.1 dholland dattr_ret = nfsvno_getattr(dirp, &dattr, nd->nd_cred, 569 1.1 dholland p, 0); 570 1.1 dholland vrele(dirp); 571 1.1 dholland } 572 1.1 dholland if (nd->nd_repstat) { 573 1.1 dholland if (nd->nd_flag & ND_NFSV3) 574 1.1 dholland nfsrv_postopattr(nd, dattr_ret, &dattr); 575 1.1 dholland goto out; 576 1.1 dholland } 577 1.1 dholland if (nd->nd_flag & ND_NFSV2) { 578 1.1 dholland (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0); 579 1.1 dholland nfsrv_fillattr(nd, &nva); 580 1.1 dholland } else if (nd->nd_flag & ND_NFSV3) { 581 1.1 dholland (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0); 582 1.1 dholland nfsrv_postopattr(nd, 0, &nva); 583 1.1 dholland nfsrv_postopattr(nd, dattr_ret, &dattr); 584 1.1 dholland } 585 1.1 dholland 586 1.1 dholland out: 587 1.1 dholland NFSEXITCODE2(error, nd); 588 1.1 dholland return (error); 589 1.1 dholland } 590 1.1 dholland 591 1.1 dholland /* 592 1.1 dholland * nfs readlink service 593 1.1 dholland */ 594 1.1 dholland APPLESTATIC int 595 1.1 dholland nfsrvd_readlink(struct nfsrv_descript *nd, __unused int isdgram, 596 1.1 dholland vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 597 1.1 dholland { 598 1.1 dholland u_int32_t *tl; 599 1.1 dholland mbuf_t mp = NULL, mpend = NULL; 600 1.1 dholland int getret = 1, len; 601 1.1 dholland struct nfsvattr nva; 602 1.1 dholland 603 1.1 dholland if (nd->nd_repstat) { 604 1.1 dholland nfsrv_postopattr(nd, getret, &nva); 605 1.1 dholland goto out; 606 1.1 dholland } 607 1.1 dholland if (vnode_vtype(vp) != VLNK) { 608 1.1 dholland if (nd->nd_flag & ND_NFSV2) 609 1.1 dholland nd->nd_repstat = ENXIO; 610 1.1 dholland else 611 1.1 dholland nd->nd_repstat = EINVAL; 612 1.1 dholland } 613 1.1 dholland if (!nd->nd_repstat) 614 1.1 dholland nd->nd_repstat = nfsvno_readlink(vp, nd->nd_cred, p, 615 1.1 dholland &mp, &mpend, &len); 616 1.1 dholland if (nd->nd_flag & ND_NFSV3) 617 1.1 dholland getret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); 618 1.1 dholland vput(vp); 619 1.1 dholland if (nd->nd_flag & ND_NFSV3) 620 1.1 dholland nfsrv_postopattr(nd, getret, &nva); 621 1.1 dholland if (nd->nd_repstat) 622 1.1 dholland goto out; 623 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 624 1.1 dholland *tl = txdr_unsigned(len); 625 1.1 dholland mbuf_setnext(nd->nd_mb, mp); 626 1.1 dholland nd->nd_mb = mpend; 627 1.1 dholland nd->nd_bpos = NFSMTOD(mpend, caddr_t) + mbuf_len(mpend); 628 1.1 dholland 629 1.1 dholland out: 630 1.1 dholland NFSEXITCODE2(0, nd); 631 1.1 dholland return (0); 632 1.1 dholland } 633 1.1 dholland 634 1.1 dholland /* 635 1.1 dholland * nfs read service 636 1.1 dholland */ 637 1.1 dholland APPLESTATIC int 638 1.1 dholland nfsrvd_read(struct nfsrv_descript *nd, __unused int isdgram, 639 1.1 dholland vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp) 640 1.1 dholland { 641 1.1 dholland u_int32_t *tl; 642 1.1 dholland int error = 0, cnt, getret = 1, reqlen, eof = 0; 643 1.1 dholland mbuf_t m2, m3; 644 1.1 dholland struct nfsvattr nva; 645 1.1 dholland off_t off = 0x0; 646 1.1 dholland struct nfsstate st, *stp = &st; 647 1.1 dholland struct nfslock lo, *lop = &lo; 648 1.1 dholland nfsv4stateid_t stateid; 649 1.1 dholland nfsquad_t clientid; 650 1.1 dholland 651 1.1 dholland if (nd->nd_repstat) { 652 1.1 dholland nfsrv_postopattr(nd, getret, &nva); 653 1.1 dholland goto out; 654 1.1 dholland } 655 1.1 dholland if (nd->nd_flag & ND_NFSV2) { 656 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 657 1.1 dholland off = (off_t)fxdr_unsigned(u_int32_t, *tl++); 658 1.1 dholland reqlen = fxdr_unsigned(int, *tl); 659 1.1 dholland } else if (nd->nd_flag & ND_NFSV3) { 660 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 661 1.1 dholland off = fxdr_hyper(tl); 662 1.1 dholland tl += 2; 663 1.1 dholland reqlen = fxdr_unsigned(int, *tl); 664 1.1 dholland } else { 665 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + 3*NFSX_UNSIGNED); 666 1.1 dholland reqlen = fxdr_unsigned(int, *(tl + 6)); 667 1.1 dholland } 668 1.1 dholland if (reqlen > NFS_SRVMAXDATA(nd)) { 669 1.1 dholland reqlen = NFS_SRVMAXDATA(nd); 670 1.1 dholland } else if (reqlen < 0) { 671 1.1 dholland error = EBADRPC; 672 1.1 dholland goto nfsmout; 673 1.1 dholland } 674 1.1 dholland if (nd->nd_flag & ND_NFSV4) { 675 1.1 dholland stp->ls_flags = (NFSLCK_CHECK | NFSLCK_READACCESS); 676 1.1 dholland lop->lo_flags = NFSLCK_READ; 677 1.1 dholland stp->ls_ownerlen = 0; 678 1.1 dholland stp->ls_op = NULL; 679 1.1 dholland stp->ls_uid = nd->nd_cred->cr_uid; 680 1.1 dholland stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 681 1.1 dholland clientid.lval[0] = stp->ls_stateid.other[0] = *tl++; 682 1.1 dholland clientid.lval[1] = stp->ls_stateid.other[1] = *tl++; 683 1.3 pgoyette if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 684 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 685 1.3 pgoyette clientid.qval = nd->nd_clientid.qval; 686 1.3 pgoyette else if (nd->nd_clientid.qval != clientid.qval) 687 1.3 pgoyette printf("EEK1 multiple clids\n"); 688 1.1 dholland } else { 689 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 690 1.3 pgoyette printf("EEK! no clientid from session\n"); 691 1.1 dholland nd->nd_flag |= ND_IMPLIEDCLID; 692 1.1 dholland nd->nd_clientid.qval = clientid.qval; 693 1.1 dholland } 694 1.1 dholland stp->ls_stateid.other[2] = *tl++; 695 1.1 dholland off = fxdr_hyper(tl); 696 1.1 dholland lop->lo_first = off; 697 1.1 dholland tl += 2; 698 1.1 dholland lop->lo_end = off + reqlen; 699 1.1 dholland /* 700 1.1 dholland * Paranoia, just in case it wraps around. 701 1.1 dholland */ 702 1.1 dholland if (lop->lo_end < off) 703 1.1 dholland lop->lo_end = NFS64BITSSET; 704 1.1 dholland } 705 1.1 dholland if (vnode_vtype(vp) != VREG) { 706 1.1 dholland if (nd->nd_flag & ND_NFSV3) 707 1.1 dholland nd->nd_repstat = EINVAL; 708 1.1 dholland else 709 1.1 dholland nd->nd_repstat = (vnode_vtype(vp) == VDIR) ? EISDIR : 710 1.1 dholland EINVAL; 711 1.1 dholland } 712 1.1 dholland getret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); 713 1.1 dholland if (!nd->nd_repstat) 714 1.1 dholland nd->nd_repstat = getret; 715 1.1 dholland if (!nd->nd_repstat && 716 1.1 dholland (nva.na_uid != nd->nd_cred->cr_uid || 717 1.1 dholland NFSVNO_EXSTRICTACCESS(exp))) { 718 1.1 dholland nd->nd_repstat = nfsvno_accchk(vp, VREAD, 719 1.1 dholland nd->nd_cred, exp, p, 720 1.1 dholland NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL); 721 1.1 dholland if (nd->nd_repstat) 722 1.1 dholland nd->nd_repstat = nfsvno_accchk(vp, VEXEC, 723 1.1 dholland nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER, 724 1.1 dholland NFSACCCHK_VPISLOCKED, NULL); 725 1.1 dholland } 726 1.1 dholland if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) 727 1.1 dholland nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid, 728 1.1 dholland &stateid, exp, nd, p); 729 1.1 dholland if (nd->nd_repstat) { 730 1.1 dholland vput(vp); 731 1.1 dholland if (nd->nd_flag & ND_NFSV3) 732 1.1 dholland nfsrv_postopattr(nd, getret, &nva); 733 1.1 dholland goto out; 734 1.1 dholland } 735 1.1 dholland if (off >= nva.na_size) { 736 1.1 dholland cnt = 0; 737 1.1 dholland eof = 1; 738 1.1 dholland } else if (reqlen == 0) 739 1.1 dholland cnt = 0; 740 1.1 dholland else if ((off + reqlen) >= nva.na_size) { 741 1.1 dholland cnt = nva.na_size - off; 742 1.1 dholland eof = 1; 743 1.1 dholland } else 744 1.1 dholland cnt = reqlen; 745 1.1 dholland m3 = NULL; 746 1.1 dholland if (cnt > 0) { 747 1.1 dholland nd->nd_repstat = nfsvno_read(vp, off, cnt, nd->nd_cred, p, 748 1.1 dholland &m3, &m2); 749 1.1 dholland if (!(nd->nd_flag & ND_NFSV4)) { 750 1.1 dholland getret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); 751 1.1 dholland if (!nd->nd_repstat) 752 1.1 dholland nd->nd_repstat = getret; 753 1.1 dholland } 754 1.1 dholland if (nd->nd_repstat) { 755 1.1 dholland vput(vp); 756 1.6 rin mbuf_freem(m3); 757 1.1 dholland if (nd->nd_flag & ND_NFSV3) 758 1.1 dholland nfsrv_postopattr(nd, getret, &nva); 759 1.1 dholland goto out; 760 1.1 dholland } 761 1.1 dholland } 762 1.1 dholland vput(vp); 763 1.1 dholland if (nd->nd_flag & ND_NFSV2) { 764 1.1 dholland nfsrv_fillattr(nd, &nva); 765 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 766 1.1 dholland } else { 767 1.1 dholland if (nd->nd_flag & ND_NFSV3) { 768 1.1 dholland nfsrv_postopattr(nd, getret, &nva); 769 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 770 1.1 dholland *tl++ = txdr_unsigned(cnt); 771 1.1 dholland } else 772 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 773 1.1 dholland if (eof) 774 1.1 dholland *tl++ = newnfs_true; 775 1.1 dholland else 776 1.1 dholland *tl++ = newnfs_false; 777 1.1 dholland } 778 1.1 dholland *tl = txdr_unsigned(cnt); 779 1.1 dholland if (m3) { 780 1.1 dholland mbuf_setnext(nd->nd_mb, m3); 781 1.1 dholland nd->nd_mb = m2; 782 1.1 dholland nd->nd_bpos = NFSMTOD(m2, caddr_t) + mbuf_len(m2); 783 1.1 dholland } 784 1.1 dholland 785 1.1 dholland out: 786 1.1 dholland NFSEXITCODE2(0, nd); 787 1.1 dholland return (0); 788 1.1 dholland nfsmout: 789 1.1 dholland vput(vp); 790 1.1 dholland NFSEXITCODE2(error, nd); 791 1.1 dholland return (error); 792 1.1 dholland } 793 1.1 dholland 794 1.1 dholland /* 795 1.1 dholland * nfs write service 796 1.1 dholland */ 797 1.1 dholland APPLESTATIC int 798 1.1 dholland nfsrvd_write(struct nfsrv_descript *nd, __unused int isdgram, 799 1.1 dholland vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp) 800 1.1 dholland { 801 1.1 dholland int i, cnt; 802 1.1 dholland u_int32_t *tl; 803 1.1 dholland mbuf_t mp; 804 1.1 dholland struct nfsvattr nva, forat; 805 1.1 dholland int aftat_ret = 1, retlen, len, error = 0, forat_ret = 1; 806 1.1 dholland int stable = NFSWRITE_FILESYNC; 807 1.1 dholland off_t off; 808 1.1 dholland struct nfsstate st, *stp = &st; 809 1.1 dholland struct nfslock lo, *lop = &lo; 810 1.1 dholland nfsv4stateid_t stateid; 811 1.1 dholland nfsquad_t clientid; 812 1.1 dholland 813 1.1 dholland if (nd->nd_repstat) { 814 1.1 dholland nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva); 815 1.1 dholland goto out; 816 1.1 dholland } 817 1.1 dholland if (nd->nd_flag & ND_NFSV2) { 818 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 819 1.1 dholland off = (off_t)fxdr_unsigned(u_int32_t, *++tl); 820 1.1 dholland tl += 2; 821 1.1 dholland retlen = len = fxdr_unsigned(int32_t, *tl); 822 1.1 dholland } else if (nd->nd_flag & ND_NFSV3) { 823 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 824 1.1 dholland off = fxdr_hyper(tl); 825 1.1 dholland tl += 3; 826 1.1 dholland stable = fxdr_unsigned(int, *tl++); 827 1.1 dholland retlen = len = fxdr_unsigned(int32_t, *tl); 828 1.1 dholland } else { 829 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + 4 * NFSX_UNSIGNED); 830 1.1 dholland stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS); 831 1.1 dholland lop->lo_flags = NFSLCK_WRITE; 832 1.1 dholland stp->ls_ownerlen = 0; 833 1.1 dholland stp->ls_op = NULL; 834 1.1 dholland stp->ls_uid = nd->nd_cred->cr_uid; 835 1.1 dholland stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 836 1.1 dholland clientid.lval[0] = stp->ls_stateid.other[0] = *tl++; 837 1.1 dholland clientid.lval[1] = stp->ls_stateid.other[1] = *tl++; 838 1.3 pgoyette if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 839 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 840 1.3 pgoyette clientid.qval = nd->nd_clientid.qval; 841 1.3 pgoyette else if (nd->nd_clientid.qval != clientid.qval) 842 1.3 pgoyette printf("EEK2 multiple clids\n"); 843 1.1 dholland } else { 844 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 845 1.3 pgoyette printf("EEK! no clientid from session\n"); 846 1.1 dholland nd->nd_flag |= ND_IMPLIEDCLID; 847 1.1 dholland nd->nd_clientid.qval = clientid.qval; 848 1.1 dholland } 849 1.1 dholland stp->ls_stateid.other[2] = *tl++; 850 1.1 dholland off = fxdr_hyper(tl); 851 1.1 dholland lop->lo_first = off; 852 1.1 dholland tl += 2; 853 1.1 dholland stable = fxdr_unsigned(int, *tl++); 854 1.1 dholland retlen = len = fxdr_unsigned(int32_t, *tl); 855 1.1 dholland lop->lo_end = off + len; 856 1.1 dholland /* 857 1.1 dholland * Paranoia, just in case it wraps around, which shouldn't 858 1.1 dholland * ever happen anyhow. 859 1.1 dholland */ 860 1.1 dholland if (lop->lo_end < lop->lo_first) 861 1.1 dholland lop->lo_end = NFS64BITSSET; 862 1.1 dholland } 863 1.1 dholland 864 1.1 dholland /* 865 1.1 dholland * Loop through the mbuf chain, counting how many mbufs are a 866 1.1 dholland * part of this write operation, so the iovec size is known. 867 1.1 dholland */ 868 1.1 dholland cnt = 0; 869 1.1 dholland mp = nd->nd_md; 870 1.1 dholland i = NFSMTOD(mp, caddr_t) + mbuf_len(mp) - nd->nd_dpos; 871 1.1 dholland while (len > 0) { 872 1.1 dholland if (i > 0) { 873 1.1 dholland len -= i; 874 1.1 dholland cnt++; 875 1.1 dholland } 876 1.1 dholland mp = mbuf_next(mp); 877 1.1 dholland if (!mp) { 878 1.1 dholland if (len > 0) { 879 1.1 dholland error = EBADRPC; 880 1.1 dholland goto nfsmout; 881 1.1 dholland } 882 1.1 dholland } else 883 1.1 dholland i = mbuf_len(mp); 884 1.1 dholland } 885 1.1 dholland 886 1.3 pgoyette if (retlen > NFS_SRVMAXIO || retlen < 0) 887 1.1 dholland nd->nd_repstat = EIO; 888 1.1 dholland if (vnode_vtype(vp) != VREG && !nd->nd_repstat) { 889 1.1 dholland if (nd->nd_flag & ND_NFSV3) 890 1.1 dholland nd->nd_repstat = EINVAL; 891 1.1 dholland else 892 1.1 dholland nd->nd_repstat = (vnode_vtype(vp) == VDIR) ? EISDIR : 893 1.1 dholland EINVAL; 894 1.1 dholland } 895 1.1 dholland forat_ret = nfsvno_getattr(vp, &forat, nd->nd_cred, p, 1); 896 1.1 dholland if (!nd->nd_repstat) 897 1.1 dholland nd->nd_repstat = forat_ret; 898 1.1 dholland if (!nd->nd_repstat && 899 1.1 dholland (forat.na_uid != nd->nd_cred->cr_uid || 900 1.1 dholland NFSVNO_EXSTRICTACCESS(exp))) 901 1.1 dholland nd->nd_repstat = nfsvno_accchk(vp, VWRITE, 902 1.1 dholland nd->nd_cred, exp, p, 903 1.1 dholland NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL); 904 1.1 dholland if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) { 905 1.1 dholland nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid, 906 1.1 dholland &stateid, exp, nd, p); 907 1.1 dholland } 908 1.1 dholland if (nd->nd_repstat) { 909 1.1 dholland vput(vp); 910 1.1 dholland if (nd->nd_flag & ND_NFSV3) 911 1.1 dholland nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva); 912 1.1 dholland goto out; 913 1.1 dholland } 914 1.1 dholland 915 1.1 dholland /* 916 1.1 dholland * For NFS Version 2, it is not obvious what a write of zero length 917 1.1 dholland * should do, but I might as well be consistent with Version 3, 918 1.1 dholland * which is to return ok so long as there are no permission problems. 919 1.1 dholland */ 920 1.1 dholland if (retlen > 0) { 921 1.1 dholland nd->nd_repstat = nfsvno_write(vp, off, retlen, cnt, stable, 922 1.1 dholland nd->nd_md, nd->nd_dpos, nd->nd_cred, p); 923 1.1 dholland error = nfsm_advance(nd, NFSM_RNDUP(retlen), -1); 924 1.1 dholland if (error) 925 1.1 dholland panic("nfsrv_write mbuf"); 926 1.1 dholland } 927 1.1 dholland if (nd->nd_flag & ND_NFSV4) 928 1.1 dholland aftat_ret = 0; 929 1.1 dholland else 930 1.1 dholland aftat_ret = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); 931 1.1 dholland vput(vp); 932 1.1 dholland if (!nd->nd_repstat) 933 1.1 dholland nd->nd_repstat = aftat_ret; 934 1.1 dholland if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) { 935 1.1 dholland if (nd->nd_flag & ND_NFSV3) 936 1.1 dholland nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva); 937 1.1 dholland if (nd->nd_repstat) 938 1.1 dholland goto out; 939 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 940 1.1 dholland *tl++ = txdr_unsigned(retlen); 941 1.1 dholland /* 942 1.1 dholland * If nfs_async is set, then pretend the write was FILESYNC. 943 1.1 dholland * Warning: Doing this violates RFC1813 and runs a risk 944 1.1 dholland * of data written by a client being lost when the server 945 1.1 dholland * crashes/reboots. 946 1.1 dholland */ 947 1.1 dholland if (stable == NFSWRITE_UNSTABLE && nfs_async == 0) 948 1.1 dholland *tl++ = txdr_unsigned(stable); 949 1.1 dholland else 950 1.1 dholland *tl++ = txdr_unsigned(NFSWRITE_FILESYNC); 951 1.1 dholland /* 952 1.1 dholland * Actually, there is no need to txdr these fields, 953 1.1 dholland * but it may make the values more human readable, 954 1.1 dholland * for debugging purposes. 955 1.1 dholland */ 956 1.1 dholland *tl++ = txdr_unsigned(nfsboottime.tv_sec); 957 1.1 dholland *tl = txdr_unsigned(nfsboottime.tv_usec); 958 1.1 dholland } else if (!nd->nd_repstat) 959 1.1 dholland nfsrv_fillattr(nd, &nva); 960 1.1 dholland 961 1.1 dholland out: 962 1.1 dholland NFSEXITCODE2(0, nd); 963 1.1 dholland return (0); 964 1.1 dholland nfsmout: 965 1.1 dholland vput(vp); 966 1.1 dholland NFSEXITCODE2(error, nd); 967 1.1 dholland return (error); 968 1.1 dholland } 969 1.1 dholland 970 1.1 dholland /* 971 1.1 dholland * nfs create service (creates regular files for V2 and V3. Spec. files for V2.) 972 1.1 dholland * now does a truncate to 0 length via. setattr if it already exists 973 1.1 dholland * The core creation routine has been extracted out into nfsrv_creatsub(), 974 1.1 dholland * so it can also be used by nfsrv_open() for V4. 975 1.1 dholland */ 976 1.1 dholland APPLESTATIC int 977 1.1 dholland nfsrvd_create(struct nfsrv_descript *nd, __unused int isdgram, 978 1.1 dholland vnode_t dp, NFSPROC_T *p, struct nfsexstuff *exp) 979 1.1 dholland { 980 1.1 dholland struct nfsvattr nva, dirfor, diraft; 981 1.1 dholland struct nfsv2_sattr *sp; 982 1.1 dholland struct nameidata named; 983 1.1 dholland u_int32_t *tl; 984 1.1 dholland int error = 0, tsize, dirfor_ret = 1, diraft_ret = 1; 985 1.1 dholland int how = NFSCREATE_UNCHECKED, exclusive_flag = 0; 986 1.1 dholland NFSDEV_T rdev = 0; 987 1.1 dholland vnode_t vp = NULL, dirp = NULL; 988 1.1 dholland fhandle_t fh; 989 1.1 dholland char *bufp; 990 1.1 dholland u_long *hashp; 991 1.1 dholland enum vtype vtyp; 992 1.1 dholland int32_t cverf[2], tverf[2] = { 0, 0 }; 993 1.1 dholland 994 1.1 dholland if (nd->nd_repstat) { 995 1.1 dholland nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 996 1.1 dholland goto out; 997 1.1 dholland } 998 1.1 dholland NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, 999 1.3 pgoyette LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE); 1000 1.1 dholland nfsvno_setpathbuf(&named, &bufp, &hashp); 1001 1.1 dholland error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 1002 1.1 dholland if (error) 1003 1.1 dholland goto nfsmout; 1004 1.1 dholland if (!nd->nd_repstat) { 1005 1.1 dholland NFSVNO_ATTRINIT(&nva); 1006 1.1 dholland if (nd->nd_flag & ND_NFSV2) { 1007 1.1 dholland NFSM_DISSECT(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1008 1.1 dholland vtyp = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode)); 1009 1.1 dholland if (vtyp == VNON) 1010 1.1 dholland vtyp = VREG; 1011 1.1 dholland NFSVNO_SETATTRVAL(&nva, type, vtyp); 1012 1.1 dholland NFSVNO_SETATTRVAL(&nva, mode, 1013 1.1 dholland nfstov_mode(sp->sa_mode)); 1014 1.1 dholland switch (nva.na_type) { 1015 1.1 dholland case VREG: 1016 1.1 dholland tsize = fxdr_unsigned(int32_t, sp->sa_size); 1017 1.1 dholland if (tsize != -1) 1018 1.1 dholland NFSVNO_SETATTRVAL(&nva, size, 1019 1.1 dholland (u_quad_t)tsize); 1020 1.1 dholland break; 1021 1.1 dholland case VCHR: 1022 1.1 dholland case VBLK: 1023 1.1 dholland case VFIFO: 1024 1.1 dholland rdev = fxdr_unsigned(NFSDEV_T, sp->sa_size); 1025 1.1 dholland break; 1026 1.1 dholland default: 1027 1.1 dholland break; 1028 1.3 pgoyette } 1029 1.1 dholland } else { 1030 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 1031 1.1 dholland how = fxdr_unsigned(int, *tl); 1032 1.1 dholland switch (how) { 1033 1.1 dholland case NFSCREATE_GUARDED: 1034 1.1 dholland case NFSCREATE_UNCHECKED: 1035 1.3 pgoyette error = nfsrv_sattr(nd, NULL, &nva, NULL, NULL, p); 1036 1.1 dholland if (error) 1037 1.1 dholland goto nfsmout; 1038 1.1 dholland break; 1039 1.1 dholland case NFSCREATE_EXCLUSIVE: 1040 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF); 1041 1.1 dholland cverf[0] = *tl++; 1042 1.1 dholland cverf[1] = *tl; 1043 1.1 dholland exclusive_flag = 1; 1044 1.1 dholland break; 1045 1.3 pgoyette } 1046 1.1 dholland NFSVNO_SETATTRVAL(&nva, type, VREG); 1047 1.1 dholland } 1048 1.1 dholland } 1049 1.1 dholland if (nd->nd_repstat) { 1050 1.1 dholland nfsvno_relpathbuf(&named); 1051 1.1 dholland if (nd->nd_flag & ND_NFSV3) { 1052 1.1 dholland dirfor_ret = nfsvno_getattr(dp, &dirfor, nd->nd_cred, 1053 1.1 dholland p, 1); 1054 1.1 dholland nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, 1055 1.1 dholland &diraft); 1056 1.1 dholland } 1057 1.1 dholland vput(dp); 1058 1.1 dholland goto out; 1059 1.1 dholland } 1060 1.1 dholland 1061 1.1 dholland nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp); 1062 1.1 dholland if (dirp) { 1063 1.1 dholland if (nd->nd_flag & ND_NFSV2) { 1064 1.1 dholland vrele(dirp); 1065 1.1 dholland dirp = NULL; 1066 1.1 dholland } else { 1067 1.1 dholland dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, 1068 1.1 dholland p, 0); 1069 1.1 dholland } 1070 1.1 dholland } 1071 1.1 dholland if (nd->nd_repstat) { 1072 1.1 dholland if (nd->nd_flag & ND_NFSV3) 1073 1.1 dholland nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, 1074 1.1 dholland &diraft); 1075 1.1 dholland if (dirp) 1076 1.1 dholland vrele(dirp); 1077 1.1 dholland goto out; 1078 1.1 dholland } 1079 1.1 dholland 1080 1.1 dholland if (!(nd->nd_flag & ND_NFSV2)) { 1081 1.1 dholland switch (how) { 1082 1.1 dholland case NFSCREATE_GUARDED: 1083 1.1 dholland if (named.ni_vp) 1084 1.1 dholland nd->nd_repstat = EEXIST; 1085 1.1 dholland break; 1086 1.1 dholland case NFSCREATE_UNCHECKED: 1087 1.1 dholland break; 1088 1.1 dholland case NFSCREATE_EXCLUSIVE: 1089 1.1 dholland if (named.ni_vp == NULL) 1090 1.1 dholland NFSVNO_SETATTRVAL(&nva, mode, 0); 1091 1.1 dholland break; 1092 1.3 pgoyette } 1093 1.1 dholland } 1094 1.1 dholland 1095 1.1 dholland /* 1096 1.1 dholland * Iff doesn't exist, create it 1097 1.1 dholland * otherwise just truncate to 0 length 1098 1.1 dholland * should I set the mode too ? 1099 1.1 dholland */ 1100 1.1 dholland nd->nd_repstat = nfsvno_createsub(nd, &named, &vp, &nva, 1101 1.1 dholland &exclusive_flag, cverf, rdev, p, exp); 1102 1.1 dholland 1103 1.1 dholland if (!nd->nd_repstat) { 1104 1.1 dholland nd->nd_repstat = nfsvno_getfh(vp, &fh, p); 1105 1.1 dholland if (!nd->nd_repstat) 1106 1.1 dholland nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, 1107 1.1 dholland p, 1); 1108 1.1 dholland vput(vp); 1109 1.1 dholland if (!nd->nd_repstat) { 1110 1.1 dholland tverf[0] = nva.na_atime.tv_sec; 1111 1.1 dholland tverf[1] = nva.na_atime.tv_nsec; 1112 1.1 dholland } 1113 1.1 dholland } 1114 1.1 dholland if (nd->nd_flag & ND_NFSV2) { 1115 1.1 dholland if (!nd->nd_repstat) { 1116 1.1 dholland (void) nfsm_fhtom(nd, (u_int8_t *)&fh, 0, 0); 1117 1.1 dholland nfsrv_fillattr(nd, &nva); 1118 1.1 dholland } 1119 1.1 dholland } else { 1120 1.1 dholland if (exclusive_flag && !nd->nd_repstat && (cverf[0] != tverf[0] 1121 1.1 dholland || cverf[1] != tverf[1])) 1122 1.1 dholland nd->nd_repstat = EEXIST; 1123 1.1 dholland diraft_ret = nfsvno_getattr(dirp, &diraft, nd->nd_cred, p, 0); 1124 1.1 dholland vrele(dirp); 1125 1.1 dholland if (!nd->nd_repstat) { 1126 1.1 dholland (void) nfsm_fhtom(nd, (u_int8_t *)&fh, 0, 1); 1127 1.1 dholland nfsrv_postopattr(nd, 0, &nva); 1128 1.1 dholland } 1129 1.1 dholland nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1130 1.1 dholland } 1131 1.1 dholland 1132 1.1 dholland out: 1133 1.1 dholland NFSEXITCODE2(0, nd); 1134 1.1 dholland return (0); 1135 1.1 dholland nfsmout: 1136 1.1 dholland vput(dp); 1137 1.1 dholland nfsvno_relpathbuf(&named); 1138 1.1 dholland NFSEXITCODE2(error, nd); 1139 1.1 dholland return (error); 1140 1.1 dholland } 1141 1.1 dholland 1142 1.1 dholland /* 1143 1.1 dholland * nfs v3 mknod service (and v4 create) 1144 1.1 dholland */ 1145 1.1 dholland APPLESTATIC int 1146 1.1 dholland nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram, 1147 1.1 dholland vnode_t dp, vnode_t *vpp, fhandle_t *fhp, NFSPROC_T *p, 1148 1.1 dholland struct nfsexstuff *exp) 1149 1.1 dholland { 1150 1.1 dholland struct nfsvattr nva, dirfor, diraft; 1151 1.1 dholland u_int32_t *tl; 1152 1.1 dholland struct nameidata named; 1153 1.1 dholland int error = 0, dirfor_ret = 1, diraft_ret = 1, pathlen; 1154 1.1 dholland u_int32_t major, minor; 1155 1.1 dholland enum vtype vtyp = VNON; 1156 1.1 dholland nfstype nfs4type = NFNON; 1157 1.1 dholland vnode_t vp, dirp = NULL; 1158 1.1 dholland nfsattrbit_t attrbits; 1159 1.1 dholland char *bufp = NULL, *pathcp = NULL; 1160 1.1 dholland u_long *hashp, cnflags; 1161 1.1 dholland NFSACL_T *aclp = NULL; 1162 1.1 dholland 1163 1.1 dholland NFSVNO_ATTRINIT(&nva); 1164 1.1 dholland cnflags = (LOCKPARENT | SAVESTART); 1165 1.1 dholland if (nd->nd_repstat) { 1166 1.1 dholland nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1167 1.1 dholland goto out; 1168 1.1 dholland } 1169 1.1 dholland #ifdef NFS4_ACL_EXTATTR_NAME 1170 1.1 dholland aclp = acl_alloc(M_WAITOK); 1171 1.1 dholland aclp->acl_cnt = 0; 1172 1.1 dholland #endif 1173 1.1 dholland 1174 1.1 dholland /* 1175 1.1 dholland * For V4, the creation stuff is here, Yuck! 1176 1.1 dholland */ 1177 1.1 dholland if (nd->nd_flag & ND_NFSV4) { 1178 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 1179 1.1 dholland vtyp = nfsv34tov_type(*tl); 1180 1.1 dholland nfs4type = fxdr_unsigned(nfstype, *tl); 1181 1.1 dholland switch (nfs4type) { 1182 1.1 dholland case NFLNK: 1183 1.1 dholland error = nfsvno_getsymlink(nd, &nva, p, &pathcp, 1184 1.1 dholland &pathlen); 1185 1.1 dholland if (error) 1186 1.1 dholland goto nfsmout; 1187 1.1 dholland break; 1188 1.1 dholland case NFCHR: 1189 1.1 dholland case NFBLK: 1190 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1191 1.1 dholland major = fxdr_unsigned(u_int32_t, *tl++); 1192 1.1 dholland minor = fxdr_unsigned(u_int32_t, *tl); 1193 1.1 dholland nva.na_rdev = NFSMAKEDEV(major, minor); 1194 1.1 dholland break; 1195 1.1 dholland case NFSOCK: 1196 1.1 dholland case NFFIFO: 1197 1.1 dholland break; 1198 1.1 dholland case NFDIR: 1199 1.1 dholland cnflags = (LOCKPARENT | SAVENAME); 1200 1.1 dholland break; 1201 1.1 dholland default: 1202 1.1 dholland nd->nd_repstat = NFSERR_BADTYPE; 1203 1.1 dholland vrele(dp); 1204 1.1 dholland #ifdef NFS4_ACL_EXTATTR_NAME 1205 1.1 dholland acl_free(aclp); 1206 1.1 dholland #endif 1207 1.1 dholland goto out; 1208 1.1 dholland } 1209 1.1 dholland } 1210 1.3 pgoyette NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, cnflags | NOCACHE); 1211 1.1 dholland nfsvno_setpathbuf(&named, &bufp, &hashp); 1212 1.1 dholland error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 1213 1.1 dholland if (error) 1214 1.1 dholland goto nfsmout; 1215 1.1 dholland if (!nd->nd_repstat) { 1216 1.1 dholland if (nd->nd_flag & ND_NFSV3) { 1217 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 1218 1.1 dholland vtyp = nfsv34tov_type(*tl); 1219 1.1 dholland } 1220 1.3 pgoyette error = nfsrv_sattr(nd, NULL, &nva, &attrbits, aclp, p); 1221 1.1 dholland if (error) 1222 1.1 dholland goto nfsmout; 1223 1.1 dholland nva.na_type = vtyp; 1224 1.1 dholland if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV3) && 1225 1.1 dholland (vtyp == VCHR || vtyp == VBLK)) { 1226 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1227 1.1 dholland major = fxdr_unsigned(u_int32_t, *tl++); 1228 1.1 dholland minor = fxdr_unsigned(u_int32_t, *tl); 1229 1.1 dholland nva.na_rdev = NFSMAKEDEV(major, minor); 1230 1.1 dholland } 1231 1.1 dholland } 1232 1.1 dholland 1233 1.1 dholland dirfor_ret = nfsvno_getattr(dp, &dirfor, nd->nd_cred, p, 0); 1234 1.1 dholland if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4)) { 1235 1.1 dholland if (!dirfor_ret && NFSVNO_ISSETGID(&nva) && 1236 1.1 dholland dirfor.na_gid == nva.na_gid) 1237 1.1 dholland NFSVNO_UNSET(&nva, gid); 1238 1.1 dholland nd->nd_repstat = nfsrv_checkuidgid(nd, &nva); 1239 1.1 dholland } 1240 1.1 dholland if (nd->nd_repstat) { 1241 1.1 dholland vrele(dp); 1242 1.1 dholland #ifdef NFS4_ACL_EXTATTR_NAME 1243 1.1 dholland acl_free(aclp); 1244 1.1 dholland #endif 1245 1.1 dholland nfsvno_relpathbuf(&named); 1246 1.1 dholland if (pathcp) 1247 1.1 dholland FREE(pathcp, M_TEMP); 1248 1.1 dholland if (nd->nd_flag & ND_NFSV3) 1249 1.1 dholland nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, 1250 1.1 dholland &diraft); 1251 1.1 dholland goto out; 1252 1.1 dholland } 1253 1.1 dholland 1254 1.1 dholland /* 1255 1.1 dholland * Yuck! For V4, mkdir and link are here and some V4 clients don't fill 1256 1.1 dholland * in va_mode, so we'll have to set a default here. 1257 1.1 dholland */ 1258 1.1 dholland if (NFSVNO_NOTSETMODE(&nva)) { 1259 1.1 dholland if (vtyp == VLNK) 1260 1.1 dholland nva.na_mode = 0755; 1261 1.1 dholland else 1262 1.1 dholland nva.na_mode = 0400; 1263 1.1 dholland } 1264 1.1 dholland 1265 1.1 dholland if (vtyp == VDIR) 1266 1.1 dholland named.ni_cnd.cn_flags |= WILLBEDIR; 1267 1.1 dholland nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp); 1268 1.1 dholland if (nd->nd_repstat) { 1269 1.1 dholland if (dirp) { 1270 1.1 dholland if (nd->nd_flag & ND_NFSV3) 1271 1.1 dholland dirfor_ret = nfsvno_getattr(dirp, &dirfor, 1272 1.1 dholland nd->nd_cred, p, 0); 1273 1.1 dholland vrele(dirp); 1274 1.1 dholland } 1275 1.1 dholland #ifdef NFS4_ACL_EXTATTR_NAME 1276 1.1 dholland acl_free(aclp); 1277 1.1 dholland #endif 1278 1.1 dholland if (nd->nd_flag & ND_NFSV3) 1279 1.1 dholland nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, 1280 1.1 dholland &diraft); 1281 1.1 dholland goto out; 1282 1.1 dholland } 1283 1.1 dholland if (dirp) 1284 1.1 dholland dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, p, 0); 1285 1.1 dholland 1286 1.1 dholland if ((nd->nd_flag & ND_NFSV4) && (vtyp == VDIR || vtyp == VLNK)) { 1287 1.1 dholland if (vtyp == VDIR) { 1288 1.1 dholland nfsrvd_mkdirsub(nd, &named, &nva, fhp, vpp, dirp, 1289 1.1 dholland &dirfor, &diraft, &diraft_ret, &attrbits, aclp, p, 1290 1.1 dholland exp); 1291 1.1 dholland #ifdef NFS4_ACL_EXTATTR_NAME 1292 1.1 dholland acl_free(aclp); 1293 1.1 dholland #endif 1294 1.1 dholland goto out; 1295 1.1 dholland } else if (vtyp == VLNK) { 1296 1.1 dholland nfsrvd_symlinksub(nd, &named, &nva, fhp, vpp, dirp, 1297 1.1 dholland &dirfor, &diraft, &diraft_ret, &attrbits, 1298 1.1 dholland aclp, p, exp, pathcp, pathlen); 1299 1.1 dholland #ifdef NFS4_ACL_EXTATTR_NAME 1300 1.1 dholland acl_free(aclp); 1301 1.1 dholland #endif 1302 1.1 dholland FREE(pathcp, M_TEMP); 1303 1.1 dholland goto out; 1304 1.1 dholland } 1305 1.1 dholland } 1306 1.1 dholland 1307 1.1 dholland nd->nd_repstat = nfsvno_mknod(&named, &nva, nd->nd_cred, p); 1308 1.1 dholland if (!nd->nd_repstat) { 1309 1.1 dholland vp = named.ni_vp; 1310 1.1 dholland nfsrv_fixattr(nd, vp, &nva, aclp, p, &attrbits, exp); 1311 1.1 dholland nd->nd_repstat = nfsvno_getfh(vp, fhp, p); 1312 1.1 dholland if ((nd->nd_flag & ND_NFSV3) && !nd->nd_repstat) 1313 1.1 dholland nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, 1314 1.1 dholland p, 1); 1315 1.1 dholland if (vpp != NULL && nd->nd_repstat == 0) { 1316 1.1 dholland NFSVOPUNLOCK(vp, 0); 1317 1.1 dholland *vpp = vp; 1318 1.1 dholland } else 1319 1.1 dholland vput(vp); 1320 1.1 dholland } 1321 1.1 dholland 1322 1.1 dholland diraft_ret = nfsvno_getattr(dirp, &diraft, nd->nd_cred, p, 0); 1323 1.1 dholland vrele(dirp); 1324 1.1 dholland if (!nd->nd_repstat) { 1325 1.1 dholland if (nd->nd_flag & ND_NFSV3) { 1326 1.1 dholland (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 1); 1327 1.1 dholland nfsrv_postopattr(nd, 0, &nva); 1328 1.1 dholland } else { 1329 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 1330 1.1 dholland *tl++ = newnfs_false; 1331 1.1 dholland txdr_hyper(dirfor.na_filerev, tl); 1332 1.1 dholland tl += 2; 1333 1.1 dholland txdr_hyper(diraft.na_filerev, tl); 1334 1.1 dholland (void) nfsrv_putattrbit(nd, &attrbits); 1335 1.1 dholland } 1336 1.1 dholland } 1337 1.1 dholland if (nd->nd_flag & ND_NFSV3) 1338 1.1 dholland nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1339 1.1 dholland #ifdef NFS4_ACL_EXTATTR_NAME 1340 1.1 dholland acl_free(aclp); 1341 1.1 dholland #endif 1342 1.1 dholland 1343 1.1 dholland out: 1344 1.1 dholland NFSEXITCODE2(0, nd); 1345 1.1 dholland return (0); 1346 1.1 dholland nfsmout: 1347 1.1 dholland vrele(dp); 1348 1.1 dholland #ifdef NFS4_ACL_EXTATTR_NAME 1349 1.1 dholland acl_free(aclp); 1350 1.1 dholland #endif 1351 1.1 dholland if (bufp) 1352 1.1 dholland nfsvno_relpathbuf(&named); 1353 1.1 dholland if (pathcp) 1354 1.1 dholland FREE(pathcp, M_TEMP); 1355 1.1 dholland 1356 1.1 dholland NFSEXITCODE2(error, nd); 1357 1.1 dholland return (error); 1358 1.1 dholland } 1359 1.1 dholland 1360 1.1 dholland /* 1361 1.1 dholland * nfs remove service 1362 1.1 dholland */ 1363 1.1 dholland APPLESTATIC int 1364 1.1 dholland nfsrvd_remove(struct nfsrv_descript *nd, __unused int isdgram, 1365 1.1 dholland vnode_t dp, NFSPROC_T *p, struct nfsexstuff *exp) 1366 1.1 dholland { 1367 1.1 dholland struct nameidata named; 1368 1.1 dholland u_int32_t *tl; 1369 1.1 dholland int error = 0, dirfor_ret = 1, diraft_ret = 1; 1370 1.1 dholland vnode_t dirp = NULL; 1371 1.1 dholland struct nfsvattr dirfor, diraft; 1372 1.1 dholland char *bufp; 1373 1.1 dholland u_long *hashp; 1374 1.1 dholland 1375 1.1 dholland if (nd->nd_repstat) { 1376 1.1 dholland nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1377 1.1 dholland goto out; 1378 1.1 dholland } 1379 1.1 dholland NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, DELETE, 1380 1.1 dholland LOCKPARENT | LOCKLEAF); 1381 1.1 dholland nfsvno_setpathbuf(&named, &bufp, &hashp); 1382 1.1 dholland error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 1383 1.1 dholland if (error) { 1384 1.1 dholland vput(dp); 1385 1.1 dholland nfsvno_relpathbuf(&named); 1386 1.1 dholland goto out; 1387 1.1 dholland } 1388 1.1 dholland if (!nd->nd_repstat) { 1389 1.1 dholland nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp); 1390 1.1 dholland } else { 1391 1.1 dholland vput(dp); 1392 1.1 dholland nfsvno_relpathbuf(&named); 1393 1.1 dholland } 1394 1.1 dholland if (dirp) { 1395 1.1 dholland if (!(nd->nd_flag & ND_NFSV2)) { 1396 1.1 dholland dirfor_ret = nfsvno_getattr(dirp, &dirfor, 1397 1.1 dholland nd->nd_cred, p, 0); 1398 1.1 dholland } else { 1399 1.1 dholland vrele(dirp); 1400 1.1 dholland dirp = NULL; 1401 1.1 dholland } 1402 1.1 dholland } 1403 1.1 dholland if (!nd->nd_repstat) { 1404 1.1 dholland if (nd->nd_flag & ND_NFSV4) { 1405 1.1 dholland if (vnode_vtype(named.ni_vp) == VDIR) 1406 1.1 dholland nd->nd_repstat = nfsvno_rmdirsub(&named, 1, 1407 1.1 dholland nd->nd_cred, p, exp); 1408 1.1 dholland else 1409 1.1 dholland nd->nd_repstat = nfsvno_removesub(&named, 1, 1410 1.1 dholland nd->nd_cred, p, exp); 1411 1.1 dholland } else if (nd->nd_procnum == NFSPROC_RMDIR) { 1412 1.1 dholland nd->nd_repstat = nfsvno_rmdirsub(&named, 0, 1413 1.1 dholland nd->nd_cred, p, exp); 1414 1.1 dholland } else { 1415 1.1 dholland nd->nd_repstat = nfsvno_removesub(&named, 0, 1416 1.1 dholland nd->nd_cred, p, exp); 1417 1.1 dholland } 1418 1.1 dholland } 1419 1.1 dholland if (!(nd->nd_flag & ND_NFSV2)) { 1420 1.1 dholland if (dirp) { 1421 1.1 dholland diraft_ret = nfsvno_getattr(dirp, &diraft, nd->nd_cred, 1422 1.1 dholland p, 0); 1423 1.1 dholland vrele(dirp); 1424 1.1 dholland } 1425 1.1 dholland if (nd->nd_flag & ND_NFSV3) { 1426 1.1 dholland nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, 1427 1.1 dholland &diraft); 1428 1.1 dholland } else if (!nd->nd_repstat) { 1429 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 1430 1.1 dholland *tl++ = newnfs_false; 1431 1.1 dholland txdr_hyper(dirfor.na_filerev, tl); 1432 1.1 dholland tl += 2; 1433 1.1 dholland txdr_hyper(diraft.na_filerev, tl); 1434 1.1 dholland } 1435 1.1 dholland } 1436 1.1 dholland 1437 1.1 dholland out: 1438 1.1 dholland NFSEXITCODE2(error, nd); 1439 1.1 dholland return (error); 1440 1.1 dholland } 1441 1.1 dholland 1442 1.1 dholland /* 1443 1.1 dholland * nfs rename service 1444 1.1 dholland */ 1445 1.1 dholland APPLESTATIC int 1446 1.1 dholland nfsrvd_rename(struct nfsrv_descript *nd, int isdgram, 1447 1.1 dholland vnode_t dp, vnode_t todp, NFSPROC_T *p, struct nfsexstuff *exp, 1448 1.1 dholland struct nfsexstuff *toexp) 1449 1.1 dholland { 1450 1.1 dholland u_int32_t *tl; 1451 1.1 dholland int error = 0, fdirfor_ret = 1, fdiraft_ret = 1; 1452 1.1 dholland int tdirfor_ret = 1, tdiraft_ret = 1; 1453 1.1 dholland struct nameidata fromnd, tond; 1454 1.1 dholland vnode_t fdirp = NULL, tdirp = NULL, tdp = NULL; 1455 1.1 dholland struct nfsvattr fdirfor, fdiraft, tdirfor, tdiraft; 1456 1.1 dholland struct nfsexstuff tnes; 1457 1.1 dholland struct nfsrvfh tfh; 1458 1.1 dholland char *bufp, *tbufp = NULL; 1459 1.1 dholland u_long *hashp; 1460 1.1 dholland fhandle_t fh; 1461 1.1 dholland 1462 1.1 dholland if (nd->nd_repstat) { 1463 1.1 dholland nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft); 1464 1.1 dholland nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft); 1465 1.1 dholland goto out; 1466 1.1 dholland } 1467 1.1 dholland if (!(nd->nd_flag & ND_NFSV2)) 1468 1.1 dholland fdirfor_ret = nfsvno_getattr(dp, &fdirfor, nd->nd_cred, p, 1); 1469 1.1 dholland tond.ni_cnd.cn_nameiop = 0; 1470 1.1 dholland tond.ni_startdir = NULL; 1471 1.1 dholland NFSNAMEICNDSET(&fromnd.ni_cnd, nd->nd_cred, DELETE, WANTPARENT | SAVESTART); 1472 1.1 dholland nfsvno_setpathbuf(&fromnd, &bufp, &hashp); 1473 1.1 dholland error = nfsrv_parsename(nd, bufp, hashp, &fromnd.ni_pathlen); 1474 1.1 dholland if (error) { 1475 1.1 dholland vput(dp); 1476 1.1 dholland if (todp) 1477 1.1 dholland vrele(todp); 1478 1.1 dholland nfsvno_relpathbuf(&fromnd); 1479 1.1 dholland goto out; 1480 1.1 dholland } 1481 1.3 pgoyette /* 1482 1.3 pgoyette * Unlock dp in this code section, so it is unlocked before 1483 1.3 pgoyette * tdp gets locked. This avoids a potential LOR if tdp is the 1484 1.3 pgoyette * parent directory of dp. 1485 1.3 pgoyette */ 1486 1.1 dholland if (nd->nd_flag & ND_NFSV4) { 1487 1.1 dholland tdp = todp; 1488 1.1 dholland tnes = *toexp; 1489 1.3 pgoyette if (dp != tdp) { 1490 1.3 pgoyette NFSVOPUNLOCK(dp, 0); 1491 1.3 pgoyette tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred, 1492 1.3 pgoyette p, 0); /* Might lock tdp. */ 1493 1.3 pgoyette } else { 1494 1.3 pgoyette tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred, 1495 1.3 pgoyette p, 1); 1496 1.3 pgoyette NFSVOPUNLOCK(dp, 0); 1497 1.3 pgoyette } 1498 1.1 dholland } else { 1499 1.1 dholland tfh.nfsrvfh_len = 0; 1500 1.1 dholland error = nfsrv_mtofh(nd, &tfh); 1501 1.1 dholland if (error == 0) 1502 1.1 dholland error = nfsvno_getfh(dp, &fh, p); 1503 1.1 dholland if (error) { 1504 1.1 dholland vput(dp); 1505 1.1 dholland /* todp is always NULL except NFSv4 */ 1506 1.1 dholland nfsvno_relpathbuf(&fromnd); 1507 1.1 dholland goto out; 1508 1.1 dholland } 1509 1.1 dholland 1510 1.1 dholland /* If this is the same file handle, just VREF() the vnode. */ 1511 1.1 dholland if (tfh.nfsrvfh_len == NFSX_MYFH && 1512 1.1 dholland !NFSBCMP(tfh.nfsrvfh_data, &fh, NFSX_MYFH)) { 1513 1.1 dholland VREF(dp); 1514 1.1 dholland tdp = dp; 1515 1.1 dholland tnes = *exp; 1516 1.1 dholland tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred, 1517 1.1 dholland p, 1); 1518 1.3 pgoyette NFSVOPUNLOCK(dp, 0); 1519 1.1 dholland } else { 1520 1.3 pgoyette NFSVOPUNLOCK(dp, 0); 1521 1.1 dholland nd->nd_cred->cr_uid = nd->nd_saveduid; 1522 1.1 dholland nfsd_fhtovp(nd, &tfh, LK_EXCLUSIVE, &tdp, &tnes, NULL, 1523 1.3 pgoyette 0, p); /* Locks tdp. */ 1524 1.1 dholland if (tdp) { 1525 1.1 dholland tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, 1526 1.1 dholland nd->nd_cred, p, 1); 1527 1.1 dholland NFSVOPUNLOCK(tdp, 0); 1528 1.1 dholland } 1529 1.1 dholland } 1530 1.1 dholland } 1531 1.1 dholland NFSNAMEICNDSET(&tond.ni_cnd, nd->nd_cred, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART); 1532 1.1 dholland nfsvno_setpathbuf(&tond, &tbufp, &hashp); 1533 1.1 dholland if (!nd->nd_repstat) { 1534 1.1 dholland error = nfsrv_parsename(nd, tbufp, hashp, &tond.ni_pathlen); 1535 1.1 dholland if (error) { 1536 1.1 dholland if (tdp) 1537 1.1 dholland vrele(tdp); 1538 1.3 pgoyette vrele(dp); 1539 1.1 dholland nfsvno_relpathbuf(&fromnd); 1540 1.1 dholland nfsvno_relpathbuf(&tond); 1541 1.1 dholland goto out; 1542 1.1 dholland } 1543 1.1 dholland } 1544 1.1 dholland if (nd->nd_repstat) { 1545 1.1 dholland if (nd->nd_flag & ND_NFSV3) { 1546 1.1 dholland nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret, 1547 1.1 dholland &fdiraft); 1548 1.1 dholland nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret, 1549 1.1 dholland &tdiraft); 1550 1.1 dholland } 1551 1.1 dholland if (tdp) 1552 1.1 dholland vrele(tdp); 1553 1.3 pgoyette vrele(dp); 1554 1.1 dholland nfsvno_relpathbuf(&fromnd); 1555 1.1 dholland nfsvno_relpathbuf(&tond); 1556 1.1 dholland goto out; 1557 1.1 dholland } 1558 1.1 dholland 1559 1.1 dholland /* 1560 1.1 dholland * Done parsing, now down to business. 1561 1.1 dholland */ 1562 1.3 pgoyette nd->nd_repstat = nfsvno_namei(nd, &fromnd, dp, 0, exp, p, &fdirp); 1563 1.1 dholland if (nd->nd_repstat) { 1564 1.1 dholland if (nd->nd_flag & ND_NFSV3) { 1565 1.1 dholland nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret, 1566 1.1 dholland &fdiraft); 1567 1.1 dholland nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret, 1568 1.1 dholland &tdiraft); 1569 1.1 dholland } 1570 1.1 dholland if (fdirp) 1571 1.1 dholland vrele(fdirp); 1572 1.1 dholland if (tdp) 1573 1.1 dholland vrele(tdp); 1574 1.1 dholland nfsvno_relpathbuf(&tond); 1575 1.1 dholland goto out; 1576 1.1 dholland } 1577 1.1 dholland if (vnode_vtype(fromnd.ni_vp) == VDIR) 1578 1.1 dholland tond.ni_cnd.cn_flags |= WILLBEDIR; 1579 1.1 dholland nd->nd_repstat = nfsvno_namei(nd, &tond, tdp, 0, &tnes, p, &tdirp); 1580 1.1 dholland nd->nd_repstat = nfsvno_rename(&fromnd, &tond, nd->nd_repstat, 1581 1.1 dholland nd->nd_flag, nd->nd_cred, p); 1582 1.1 dholland if (fdirp) 1583 1.1 dholland fdiraft_ret = nfsvno_getattr(fdirp, &fdiraft, nd->nd_cred, p, 1584 1.1 dholland 0); 1585 1.1 dholland if (tdirp) 1586 1.1 dholland tdiraft_ret = nfsvno_getattr(tdirp, &tdiraft, nd->nd_cred, p, 1587 1.1 dholland 0); 1588 1.1 dholland if (fdirp) 1589 1.1 dholland vrele(fdirp); 1590 1.1 dholland if (tdirp) 1591 1.1 dholland vrele(tdirp); 1592 1.1 dholland if (nd->nd_flag & ND_NFSV3) { 1593 1.1 dholland nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft); 1594 1.1 dholland nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft); 1595 1.1 dholland } else if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) { 1596 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 10 * NFSX_UNSIGNED); 1597 1.1 dholland *tl++ = newnfs_false; 1598 1.1 dholland txdr_hyper(fdirfor.na_filerev, tl); 1599 1.1 dholland tl += 2; 1600 1.1 dholland txdr_hyper(fdiraft.na_filerev, tl); 1601 1.1 dholland tl += 2; 1602 1.1 dholland *tl++ = newnfs_false; 1603 1.1 dholland txdr_hyper(tdirfor.na_filerev, tl); 1604 1.1 dholland tl += 2; 1605 1.1 dholland txdr_hyper(tdiraft.na_filerev, tl); 1606 1.1 dholland } 1607 1.1 dholland 1608 1.1 dholland out: 1609 1.1 dholland NFSEXITCODE2(error, nd); 1610 1.1 dholland return (error); 1611 1.1 dholland } 1612 1.1 dholland 1613 1.1 dholland /* 1614 1.1 dholland * nfs link service 1615 1.1 dholland */ 1616 1.1 dholland APPLESTATIC int 1617 1.1 dholland nfsrvd_link(struct nfsrv_descript *nd, int isdgram, 1618 1.1 dholland vnode_t vp, vnode_t tovp, NFSPROC_T *p, struct nfsexstuff *exp, 1619 1.1 dholland struct nfsexstuff *toexp) 1620 1.1 dholland { 1621 1.1 dholland struct nameidata named; 1622 1.1 dholland u_int32_t *tl; 1623 1.1 dholland int error = 0, dirfor_ret = 1, diraft_ret = 1, getret = 1; 1624 1.1 dholland vnode_t dirp = NULL, dp = NULL; 1625 1.1 dholland struct nfsvattr dirfor, diraft, at; 1626 1.1 dholland struct nfsexstuff tnes; 1627 1.1 dholland struct nfsrvfh dfh; 1628 1.1 dholland char *bufp; 1629 1.1 dholland u_long *hashp; 1630 1.1 dholland 1631 1.1 dholland if (nd->nd_repstat) { 1632 1.1 dholland nfsrv_postopattr(nd, getret, &at); 1633 1.1 dholland nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1634 1.1 dholland goto out; 1635 1.1 dholland } 1636 1.1 dholland NFSVOPUNLOCK(vp, 0); 1637 1.1 dholland if (vnode_vtype(vp) == VDIR) { 1638 1.1 dholland if (nd->nd_flag & ND_NFSV4) 1639 1.1 dholland nd->nd_repstat = NFSERR_ISDIR; 1640 1.1 dholland else 1641 1.1 dholland nd->nd_repstat = NFSERR_INVAL; 1642 1.1 dholland if (tovp) 1643 1.1 dholland vrele(tovp); 1644 1.1 dholland } 1645 1.1 dholland if (!nd->nd_repstat) { 1646 1.1 dholland if (nd->nd_flag & ND_NFSV4) { 1647 1.1 dholland dp = tovp; 1648 1.1 dholland tnes = *toexp; 1649 1.1 dholland } else { 1650 1.1 dholland error = nfsrv_mtofh(nd, &dfh); 1651 1.1 dholland if (error) { 1652 1.1 dholland vrele(vp); 1653 1.1 dholland /* tovp is always NULL unless NFSv4 */ 1654 1.1 dholland goto out; 1655 1.1 dholland } 1656 1.1 dholland nfsd_fhtovp(nd, &dfh, LK_EXCLUSIVE, &dp, &tnes, NULL, 0, 1657 1.1 dholland p); 1658 1.1 dholland if (dp) 1659 1.1 dholland NFSVOPUNLOCK(dp, 0); 1660 1.1 dholland } 1661 1.1 dholland } 1662 1.1 dholland NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, 1663 1.3 pgoyette LOCKPARENT | SAVENAME | NOCACHE); 1664 1.1 dholland if (!nd->nd_repstat) { 1665 1.1 dholland nfsvno_setpathbuf(&named, &bufp, &hashp); 1666 1.1 dholland error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 1667 1.1 dholland if (error) { 1668 1.1 dholland vrele(vp); 1669 1.1 dholland if (dp) 1670 1.1 dholland vrele(dp); 1671 1.1 dholland nfsvno_relpathbuf(&named); 1672 1.1 dholland goto out; 1673 1.1 dholland } 1674 1.1 dholland if (!nd->nd_repstat) { 1675 1.1 dholland nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, &tnes, 1676 1.1 dholland p, &dirp); 1677 1.1 dholland } else { 1678 1.1 dholland if (dp) 1679 1.1 dholland vrele(dp); 1680 1.1 dholland nfsvno_relpathbuf(&named); 1681 1.1 dholland } 1682 1.1 dholland } 1683 1.1 dholland if (dirp) { 1684 1.1 dholland if (nd->nd_flag & ND_NFSV2) { 1685 1.1 dholland vrele(dirp); 1686 1.1 dholland dirp = NULL; 1687 1.1 dholland } else { 1688 1.1 dholland dirfor_ret = nfsvno_getattr(dirp, &dirfor, 1689 1.1 dholland nd->nd_cred, p, 0); 1690 1.1 dholland } 1691 1.1 dholland } 1692 1.1 dholland if (!nd->nd_repstat) 1693 1.1 dholland nd->nd_repstat = nfsvno_link(&named, vp, nd->nd_cred, p, exp); 1694 1.1 dholland if (nd->nd_flag & ND_NFSV3) 1695 1.1 dholland getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 0); 1696 1.1 dholland if (dirp) { 1697 1.1 dholland diraft_ret = nfsvno_getattr(dirp, &diraft, nd->nd_cred, p, 0); 1698 1.1 dholland vrele(dirp); 1699 1.1 dholland } 1700 1.1 dholland vrele(vp); 1701 1.1 dholland if (nd->nd_flag & ND_NFSV3) { 1702 1.1 dholland nfsrv_postopattr(nd, getret, &at); 1703 1.1 dholland nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1704 1.1 dholland } else if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) { 1705 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 1706 1.1 dholland *tl++ = newnfs_false; 1707 1.1 dholland txdr_hyper(dirfor.na_filerev, tl); 1708 1.1 dholland tl += 2; 1709 1.1 dholland txdr_hyper(diraft.na_filerev, tl); 1710 1.1 dholland } 1711 1.1 dholland 1712 1.1 dholland out: 1713 1.1 dholland NFSEXITCODE2(error, nd); 1714 1.1 dholland return (error); 1715 1.1 dholland } 1716 1.1 dholland 1717 1.1 dholland /* 1718 1.1 dholland * nfs symbolic link service 1719 1.1 dholland */ 1720 1.1 dholland APPLESTATIC int 1721 1.1 dholland nfsrvd_symlink(struct nfsrv_descript *nd, __unused int isdgram, 1722 1.1 dholland vnode_t dp, vnode_t *vpp, fhandle_t *fhp, NFSPROC_T *p, 1723 1.1 dholland struct nfsexstuff *exp) 1724 1.1 dholland { 1725 1.1 dholland struct nfsvattr nva, dirfor, diraft; 1726 1.1 dholland struct nameidata named; 1727 1.1 dholland int error = 0, dirfor_ret = 1, diraft_ret = 1, pathlen; 1728 1.1 dholland vnode_t dirp = NULL; 1729 1.1 dholland char *bufp, *pathcp = NULL; 1730 1.1 dholland u_long *hashp; 1731 1.1 dholland 1732 1.1 dholland if (nd->nd_repstat) { 1733 1.1 dholland nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1734 1.1 dholland goto out; 1735 1.1 dholland } 1736 1.1 dholland if (vpp) 1737 1.1 dholland *vpp = NULL; 1738 1.1 dholland NFSVNO_ATTRINIT(&nva); 1739 1.1 dholland NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, 1740 1.3 pgoyette LOCKPARENT | SAVESTART | NOCACHE); 1741 1.1 dholland nfsvno_setpathbuf(&named, &bufp, &hashp); 1742 1.1 dholland error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 1743 1.1 dholland if (!error && !nd->nd_repstat) 1744 1.1 dholland error = nfsvno_getsymlink(nd, &nva, p, &pathcp, &pathlen); 1745 1.1 dholland if (error) { 1746 1.1 dholland vrele(dp); 1747 1.1 dholland nfsvno_relpathbuf(&named); 1748 1.1 dholland goto out; 1749 1.1 dholland } 1750 1.1 dholland if (!nd->nd_repstat) { 1751 1.1 dholland nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp); 1752 1.1 dholland } else { 1753 1.1 dholland vrele(dp); 1754 1.1 dholland nfsvno_relpathbuf(&named); 1755 1.1 dholland } 1756 1.1 dholland if (dirp != NULL && !(nd->nd_flag & ND_NFSV3)) { 1757 1.1 dholland vrele(dirp); 1758 1.1 dholland dirp = NULL; 1759 1.1 dholland } 1760 1.1 dholland 1761 1.1 dholland /* 1762 1.1 dholland * And call nfsrvd_symlinksub() to do the common code. It will 1763 1.1 dholland * return EBADRPC upon a parsing error, 0 otherwise. 1764 1.1 dholland */ 1765 1.1 dholland if (!nd->nd_repstat) { 1766 1.1 dholland if (dirp != NULL) 1767 1.1 dholland dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, 1768 1.1 dholland p, 0); 1769 1.1 dholland nfsrvd_symlinksub(nd, &named, &nva, fhp, vpp, dirp, 1770 1.1 dholland &dirfor, &diraft, &diraft_ret, NULL, NULL, p, exp, 1771 1.1 dholland pathcp, pathlen); 1772 1.1 dholland } else if (dirp != NULL) { 1773 1.1 dholland dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, p, 0); 1774 1.1 dholland vrele(dirp); 1775 1.1 dholland } 1776 1.1 dholland if (pathcp) 1777 1.1 dholland FREE(pathcp, M_TEMP); 1778 1.1 dholland 1779 1.1 dholland if (nd->nd_flag & ND_NFSV3) { 1780 1.1 dholland if (!nd->nd_repstat) { 1781 1.1 dholland (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 1); 1782 1.1 dholland nfsrv_postopattr(nd, 0, &nva); 1783 1.1 dholland } 1784 1.1 dholland nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1785 1.1 dholland } 1786 1.1 dholland 1787 1.1 dholland out: 1788 1.1 dholland NFSEXITCODE2(error, nd); 1789 1.1 dholland return (error); 1790 1.1 dholland } 1791 1.1 dholland 1792 1.1 dholland /* 1793 1.1 dholland * Common code for creating a symbolic link. 1794 1.1 dholland */ 1795 1.1 dholland static void 1796 1.1 dholland nfsrvd_symlinksub(struct nfsrv_descript *nd, struct nameidata *ndp, 1797 1.1 dholland struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp, 1798 1.1 dholland vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp, 1799 1.1 dholland int *diraft_retp, nfsattrbit_t *attrbitp, 1800 1.1 dholland NFSACL_T *aclp, NFSPROC_T *p, struct nfsexstuff *exp, char *pathcp, 1801 1.1 dholland int pathlen) 1802 1.1 dholland { 1803 1.1 dholland u_int32_t *tl; 1804 1.1 dholland 1805 1.1 dholland nd->nd_repstat = nfsvno_symlink(ndp, nvap, pathcp, pathlen, 1806 1.1 dholland !(nd->nd_flag & ND_NFSV2), nd->nd_saveduid, nd->nd_cred, p, exp); 1807 1.1 dholland if (!nd->nd_repstat && !(nd->nd_flag & ND_NFSV2)) { 1808 1.1 dholland nfsrv_fixattr(nd, ndp->ni_vp, nvap, aclp, p, attrbitp, exp); 1809 1.1 dholland if (nd->nd_flag & ND_NFSV3) { 1810 1.1 dholland nd->nd_repstat = nfsvno_getfh(ndp->ni_vp, fhp, p); 1811 1.1 dholland if (!nd->nd_repstat) 1812 1.1 dholland nd->nd_repstat = nfsvno_getattr(ndp->ni_vp, 1813 1.1 dholland nvap, nd->nd_cred, p, 1); 1814 1.1 dholland } 1815 1.1 dholland if (vpp != NULL && nd->nd_repstat == 0) { 1816 1.1 dholland NFSVOPUNLOCK(ndp->ni_vp, 0); 1817 1.1 dholland *vpp = ndp->ni_vp; 1818 1.1 dholland } else 1819 1.1 dholland vput(ndp->ni_vp); 1820 1.1 dholland } 1821 1.1 dholland if (dirp) { 1822 1.1 dholland *diraft_retp = nfsvno_getattr(dirp, diraftp, nd->nd_cred, p, 0); 1823 1.1 dholland vrele(dirp); 1824 1.1 dholland } 1825 1.1 dholland if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) { 1826 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 1827 1.1 dholland *tl++ = newnfs_false; 1828 1.1 dholland txdr_hyper(dirforp->na_filerev, tl); 1829 1.1 dholland tl += 2; 1830 1.1 dholland txdr_hyper(diraftp->na_filerev, tl); 1831 1.1 dholland (void) nfsrv_putattrbit(nd, attrbitp); 1832 1.1 dholland } 1833 1.1 dholland 1834 1.1 dholland NFSEXITCODE2(0, nd); 1835 1.1 dholland } 1836 1.1 dholland 1837 1.1 dholland /* 1838 1.1 dholland * nfs mkdir service 1839 1.1 dholland */ 1840 1.1 dholland APPLESTATIC int 1841 1.1 dholland nfsrvd_mkdir(struct nfsrv_descript *nd, __unused int isdgram, 1842 1.1 dholland vnode_t dp, vnode_t *vpp, fhandle_t *fhp, NFSPROC_T *p, 1843 1.1 dholland struct nfsexstuff *exp) 1844 1.1 dholland { 1845 1.1 dholland struct nfsvattr nva, dirfor, diraft; 1846 1.1 dholland struct nameidata named; 1847 1.1 dholland u_int32_t *tl; 1848 1.1 dholland int error = 0, dirfor_ret = 1, diraft_ret = 1; 1849 1.1 dholland vnode_t dirp = NULL; 1850 1.1 dholland char *bufp; 1851 1.1 dholland u_long *hashp; 1852 1.1 dholland 1853 1.1 dholland if (nd->nd_repstat) { 1854 1.1 dholland nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1855 1.1 dholland goto out; 1856 1.1 dholland } 1857 1.1 dholland NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, 1858 1.3 pgoyette LOCKPARENT | SAVENAME | NOCACHE); 1859 1.1 dholland nfsvno_setpathbuf(&named, &bufp, &hashp); 1860 1.1 dholland error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 1861 1.1 dholland if (error) 1862 1.1 dholland goto nfsmout; 1863 1.1 dholland if (!nd->nd_repstat) { 1864 1.1 dholland NFSVNO_ATTRINIT(&nva); 1865 1.1 dholland if (nd->nd_flag & ND_NFSV3) { 1866 1.3 pgoyette error = nfsrv_sattr(nd, NULL, &nva, NULL, NULL, p); 1867 1.1 dholland if (error) 1868 1.1 dholland goto nfsmout; 1869 1.1 dholland } else { 1870 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 1871 1.1 dholland nva.na_mode = nfstov_mode(*tl++); 1872 1.1 dholland } 1873 1.1 dholland } 1874 1.1 dholland if (!nd->nd_repstat) { 1875 1.1 dholland nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp); 1876 1.1 dholland } else { 1877 1.1 dholland vrele(dp); 1878 1.1 dholland nfsvno_relpathbuf(&named); 1879 1.1 dholland } 1880 1.1 dholland if (dirp != NULL && !(nd->nd_flag & ND_NFSV3)) { 1881 1.1 dholland vrele(dirp); 1882 1.1 dholland dirp = NULL; 1883 1.1 dholland } 1884 1.1 dholland if (nd->nd_repstat) { 1885 1.1 dholland if (dirp != NULL) { 1886 1.1 dholland dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, 1887 1.1 dholland p, 0); 1888 1.1 dholland vrele(dirp); 1889 1.1 dholland } 1890 1.1 dholland if (nd->nd_flag & ND_NFSV3) 1891 1.1 dholland nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, 1892 1.1 dholland &diraft); 1893 1.1 dholland goto out; 1894 1.1 dholland } 1895 1.1 dholland if (dirp != NULL) 1896 1.1 dholland dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, p, 0); 1897 1.1 dholland 1898 1.1 dholland /* 1899 1.1 dholland * Call nfsrvd_mkdirsub() for the code common to V4 as well. 1900 1.1 dholland */ 1901 1.1 dholland nfsrvd_mkdirsub(nd, &named, &nva, fhp, vpp, dirp, &dirfor, &diraft, 1902 1.1 dholland &diraft_ret, NULL, NULL, p, exp); 1903 1.1 dholland 1904 1.1 dholland if (nd->nd_flag & ND_NFSV3) { 1905 1.1 dholland if (!nd->nd_repstat) { 1906 1.1 dholland (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 1); 1907 1.1 dholland nfsrv_postopattr(nd, 0, &nva); 1908 1.1 dholland } 1909 1.1 dholland nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft); 1910 1.1 dholland } else if (!nd->nd_repstat) { 1911 1.1 dholland (void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0); 1912 1.1 dholland nfsrv_fillattr(nd, &nva); 1913 1.1 dholland } 1914 1.1 dholland 1915 1.1 dholland out: 1916 1.1 dholland NFSEXITCODE2(0, nd); 1917 1.1 dholland return (0); 1918 1.1 dholland nfsmout: 1919 1.1 dholland vrele(dp); 1920 1.1 dholland nfsvno_relpathbuf(&named); 1921 1.1 dholland NFSEXITCODE2(error, nd); 1922 1.1 dholland return (error); 1923 1.1 dholland } 1924 1.1 dholland 1925 1.1 dholland /* 1926 1.1 dholland * Code common to mkdir for V2,3 and 4. 1927 1.1 dholland */ 1928 1.1 dholland static void 1929 1.1 dholland nfsrvd_mkdirsub(struct nfsrv_descript *nd, struct nameidata *ndp, 1930 1.1 dholland struct nfsvattr *nvap, fhandle_t *fhp, vnode_t *vpp, 1931 1.1 dholland vnode_t dirp, struct nfsvattr *dirforp, struct nfsvattr *diraftp, 1932 1.1 dholland int *diraft_retp, nfsattrbit_t *attrbitp, NFSACL_T *aclp, 1933 1.1 dholland NFSPROC_T *p, struct nfsexstuff *exp) 1934 1.1 dholland { 1935 1.1 dholland vnode_t vp; 1936 1.1 dholland u_int32_t *tl; 1937 1.1 dholland 1938 1.1 dholland NFSVNO_SETATTRVAL(nvap, type, VDIR); 1939 1.1 dholland nd->nd_repstat = nfsvno_mkdir(ndp, nvap, nd->nd_saveduid, 1940 1.1 dholland nd->nd_cred, p, exp); 1941 1.1 dholland if (!nd->nd_repstat) { 1942 1.1 dholland vp = ndp->ni_vp; 1943 1.1 dholland nfsrv_fixattr(nd, vp, nvap, aclp, p, attrbitp, exp); 1944 1.1 dholland nd->nd_repstat = nfsvno_getfh(vp, fhp, p); 1945 1.1 dholland if (!(nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) 1946 1.1 dholland nd->nd_repstat = nfsvno_getattr(vp, nvap, nd->nd_cred, 1947 1.1 dholland p, 1); 1948 1.1 dholland if (vpp && !nd->nd_repstat) { 1949 1.1 dholland NFSVOPUNLOCK(vp, 0); 1950 1.1 dholland *vpp = vp; 1951 1.1 dholland } else { 1952 1.1 dholland vput(vp); 1953 1.1 dholland } 1954 1.1 dholland } 1955 1.1 dholland if (dirp) { 1956 1.1 dholland *diraft_retp = nfsvno_getattr(dirp, diraftp, nd->nd_cred, p, 0); 1957 1.1 dholland vrele(dirp); 1958 1.1 dholland } 1959 1.1 dholland if ((nd->nd_flag & ND_NFSV4) && !nd->nd_repstat) { 1960 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 1961 1.1 dholland *tl++ = newnfs_false; 1962 1.1 dholland txdr_hyper(dirforp->na_filerev, tl); 1963 1.1 dholland tl += 2; 1964 1.1 dholland txdr_hyper(diraftp->na_filerev, tl); 1965 1.1 dholland (void) nfsrv_putattrbit(nd, attrbitp); 1966 1.1 dholland } 1967 1.1 dholland 1968 1.1 dholland NFSEXITCODE2(0, nd); 1969 1.1 dholland } 1970 1.1 dholland 1971 1.1 dholland /* 1972 1.1 dholland * nfs commit service 1973 1.1 dholland */ 1974 1.1 dholland APPLESTATIC int 1975 1.1 dholland nfsrvd_commit(struct nfsrv_descript *nd, __unused int isdgram, 1976 1.1 dholland vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 1977 1.1 dholland { 1978 1.1 dholland struct nfsvattr bfor, aft; 1979 1.1 dholland u_int32_t *tl; 1980 1.1 dholland int error = 0, for_ret = 1, aft_ret = 1, cnt; 1981 1.1 dholland u_int64_t off; 1982 1.1 dholland 1983 1.3 pgoyette if (nd->nd_repstat) { 1984 1.1 dholland nfsrv_wcc(nd, for_ret, &bfor, aft_ret, &aft); 1985 1.1 dholland goto out; 1986 1.1 dholland } 1987 1.3 pgoyette 1988 1.3 pgoyette /* Return NFSERR_ISDIR in NFSv4 when commit on a directory. */ 1989 1.3 pgoyette if (vp->v_type != VREG) { 1990 1.3 pgoyette if (nd->nd_flag & ND_NFSV3) 1991 1.3 pgoyette error = NFSERR_NOTSUPP; 1992 1.3 pgoyette else 1993 1.3 pgoyette error = (vp->v_type == VDIR) ? NFSERR_ISDIR : NFSERR_INVAL; 1994 1.3 pgoyette goto nfsmout; 1995 1.3 pgoyette } 1996 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 1997 1.3 pgoyette 1998 1.1 dholland /* 1999 1.1 dholland * XXX At this time VOP_FSYNC() does not accept offset and byte 2000 1.1 dholland * count parameters, so these arguments are useless (someday maybe). 2001 1.1 dholland */ 2002 1.1 dholland off = fxdr_hyper(tl); 2003 1.1 dholland tl += 2; 2004 1.1 dholland cnt = fxdr_unsigned(int, *tl); 2005 1.1 dholland if (nd->nd_flag & ND_NFSV3) 2006 1.1 dholland for_ret = nfsvno_getattr(vp, &bfor, nd->nd_cred, p, 1); 2007 1.1 dholland nd->nd_repstat = nfsvno_fsync(vp, off, cnt, nd->nd_cred, p); 2008 1.1 dholland if (nd->nd_flag & ND_NFSV3) { 2009 1.1 dholland aft_ret = nfsvno_getattr(vp, &aft, nd->nd_cred, p, 1); 2010 1.1 dholland nfsrv_wcc(nd, for_ret, &bfor, aft_ret, &aft); 2011 1.1 dholland } 2012 1.1 dholland vput(vp); 2013 1.1 dholland if (!nd->nd_repstat) { 2014 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_VERF); 2015 1.1 dholland *tl++ = txdr_unsigned(nfsboottime.tv_sec); 2016 1.1 dholland *tl = txdr_unsigned(nfsboottime.tv_usec); 2017 1.1 dholland } 2018 1.1 dholland 2019 1.1 dholland out: 2020 1.1 dholland NFSEXITCODE2(0, nd); 2021 1.1 dholland return (0); 2022 1.1 dholland nfsmout: 2023 1.1 dholland vput(vp); 2024 1.1 dholland NFSEXITCODE2(error, nd); 2025 1.1 dholland return (error); 2026 1.1 dholland } 2027 1.1 dholland 2028 1.1 dholland /* 2029 1.1 dholland * nfs statfs service 2030 1.1 dholland */ 2031 1.1 dholland APPLESTATIC int 2032 1.1 dholland nfsrvd_statfs(struct nfsrv_descript *nd, __unused int isdgram, 2033 1.1 dholland vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 2034 1.1 dholland { 2035 1.1 dholland struct statfs *sf; 2036 1.1 dholland u_int32_t *tl; 2037 1.1 dholland int getret = 1; 2038 1.1 dholland struct nfsvattr at; 2039 1.1 dholland struct statfs sfs; 2040 1.1 dholland u_quad_t tval; 2041 1.1 dholland 2042 1.1 dholland if (nd->nd_repstat) { 2043 1.1 dholland nfsrv_postopattr(nd, getret, &at); 2044 1.1 dholland goto out; 2045 1.1 dholland } 2046 1.1 dholland sf = &sfs; 2047 1.1 dholland nd->nd_repstat = nfsvno_statfs(vp, sf); 2048 1.1 dholland getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1); 2049 1.1 dholland vput(vp); 2050 1.1 dholland if (nd->nd_flag & ND_NFSV3) 2051 1.1 dholland nfsrv_postopattr(nd, getret, &at); 2052 1.1 dholland if (nd->nd_repstat) 2053 1.1 dholland goto out; 2054 1.1 dholland if (nd->nd_flag & ND_NFSV2) { 2055 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_V2STATFS); 2056 1.1 dholland *tl++ = txdr_unsigned(NFS_V2MAXDATA); 2057 1.1 dholland *tl++ = txdr_unsigned(sf->f_bsize); 2058 1.1 dholland *tl++ = txdr_unsigned(sf->f_blocks); 2059 1.1 dholland *tl++ = txdr_unsigned(sf->f_bfree); 2060 1.1 dholland *tl = txdr_unsigned(sf->f_bavail); 2061 1.1 dholland } else { 2062 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_V3STATFS); 2063 1.1 dholland tval = (u_quad_t)sf->f_blocks; 2064 1.1 dholland tval *= (u_quad_t)sf->f_bsize; 2065 1.1 dholland txdr_hyper(tval, tl); tl += 2; 2066 1.1 dholland tval = (u_quad_t)sf->f_bfree; 2067 1.1 dholland tval *= (u_quad_t)sf->f_bsize; 2068 1.1 dholland txdr_hyper(tval, tl); tl += 2; 2069 1.1 dholland tval = (u_quad_t)sf->f_bavail; 2070 1.1 dholland tval *= (u_quad_t)sf->f_bsize; 2071 1.1 dholland txdr_hyper(tval, tl); tl += 2; 2072 1.1 dholland tval = (u_quad_t)sf->f_files; 2073 1.1 dholland txdr_hyper(tval, tl); tl += 2; 2074 1.1 dholland tval = (u_quad_t)sf->f_ffree; 2075 1.1 dholland txdr_hyper(tval, tl); tl += 2; 2076 1.1 dholland tval = (u_quad_t)sf->f_ffree; 2077 1.1 dholland txdr_hyper(tval, tl); tl += 2; 2078 1.1 dholland *tl = 0; 2079 1.1 dholland } 2080 1.1 dholland 2081 1.1 dholland out: 2082 1.1 dholland NFSEXITCODE2(0, nd); 2083 1.1 dholland return (0); 2084 1.1 dholland } 2085 1.1 dholland 2086 1.1 dholland /* 2087 1.1 dholland * nfs fsinfo service 2088 1.1 dholland */ 2089 1.1 dholland APPLESTATIC int 2090 1.1 dholland nfsrvd_fsinfo(struct nfsrv_descript *nd, int isdgram, 2091 1.1 dholland vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 2092 1.1 dholland { 2093 1.1 dholland u_int32_t *tl; 2094 1.1 dholland struct nfsfsinfo fs; 2095 1.1 dholland int getret = 1; 2096 1.1 dholland struct nfsvattr at; 2097 1.1 dholland 2098 1.1 dholland if (nd->nd_repstat) { 2099 1.1 dholland nfsrv_postopattr(nd, getret, &at); 2100 1.1 dholland goto out; 2101 1.1 dholland } 2102 1.1 dholland getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1); 2103 1.1 dholland nfsvno_getfs(&fs, isdgram); 2104 1.1 dholland vput(vp); 2105 1.1 dholland nfsrv_postopattr(nd, getret, &at); 2106 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_V3FSINFO); 2107 1.1 dholland *tl++ = txdr_unsigned(fs.fs_rtmax); 2108 1.1 dholland *tl++ = txdr_unsigned(fs.fs_rtpref); 2109 1.1 dholland *tl++ = txdr_unsigned(fs.fs_rtmult); 2110 1.1 dholland *tl++ = txdr_unsigned(fs.fs_wtmax); 2111 1.1 dholland *tl++ = txdr_unsigned(fs.fs_wtpref); 2112 1.1 dholland *tl++ = txdr_unsigned(fs.fs_wtmult); 2113 1.1 dholland *tl++ = txdr_unsigned(fs.fs_dtpref); 2114 1.1 dholland txdr_hyper(fs.fs_maxfilesize, tl); 2115 1.1 dholland tl += 2; 2116 1.1 dholland txdr_nfsv3time(&fs.fs_timedelta, tl); 2117 1.1 dholland tl += 2; 2118 1.1 dholland *tl = txdr_unsigned(fs.fs_properties); 2119 1.1 dholland 2120 1.1 dholland out: 2121 1.1 dholland NFSEXITCODE2(0, nd); 2122 1.1 dholland return (0); 2123 1.1 dholland } 2124 1.1 dholland 2125 1.1 dholland /* 2126 1.1 dholland * nfs pathconf service 2127 1.1 dholland */ 2128 1.1 dholland APPLESTATIC int 2129 1.1 dholland nfsrvd_pathconf(struct nfsrv_descript *nd, __unused int isdgram, 2130 1.1 dholland vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 2131 1.1 dholland { 2132 1.1 dholland struct nfsv3_pathconf *pc; 2133 1.1 dholland int getret = 1; 2134 1.1 dholland register_t linkmax, namemax, chownres, notrunc; 2135 1.1 dholland struct nfsvattr at; 2136 1.1 dholland 2137 1.1 dholland if (nd->nd_repstat) { 2138 1.1 dholland nfsrv_postopattr(nd, getret, &at); 2139 1.1 dholland goto out; 2140 1.1 dholland } 2141 1.1 dholland nd->nd_repstat = nfsvno_pathconf(vp, _PC_LINK_MAX, &linkmax, 2142 1.1 dholland nd->nd_cred, p); 2143 1.1 dholland if (!nd->nd_repstat) 2144 1.1 dholland nd->nd_repstat = nfsvno_pathconf(vp, _PC_NAME_MAX, &namemax, 2145 1.1 dholland nd->nd_cred, p); 2146 1.1 dholland if (!nd->nd_repstat) 2147 1.1 dholland nd->nd_repstat=nfsvno_pathconf(vp, _PC_CHOWN_RESTRICTED, 2148 1.1 dholland &chownres, nd->nd_cred, p); 2149 1.1 dholland if (!nd->nd_repstat) 2150 1.1 dholland nd->nd_repstat = nfsvno_pathconf(vp, _PC_NO_TRUNC, ¬runc, 2151 1.1 dholland nd->nd_cred, p); 2152 1.1 dholland getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1); 2153 1.1 dholland vput(vp); 2154 1.1 dholland nfsrv_postopattr(nd, getret, &at); 2155 1.1 dholland if (!nd->nd_repstat) { 2156 1.1 dholland NFSM_BUILD(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF); 2157 1.1 dholland pc->pc_linkmax = txdr_unsigned(linkmax); 2158 1.1 dholland pc->pc_namemax = txdr_unsigned(namemax); 2159 1.1 dholland pc->pc_notrunc = txdr_unsigned(notrunc); 2160 1.1 dholland pc->pc_chownrestricted = txdr_unsigned(chownres); 2161 1.1 dholland 2162 1.1 dholland /* 2163 1.1 dholland * These should probably be supported by VOP_PATHCONF(), but 2164 1.1 dholland * until msdosfs is exportable (why would you want to?), the 2165 1.1 dholland * Unix defaults should be ok. 2166 1.1 dholland */ 2167 1.1 dholland pc->pc_caseinsensitive = newnfs_false; 2168 1.1 dholland pc->pc_casepreserving = newnfs_true; 2169 1.1 dholland } 2170 1.1 dholland 2171 1.1 dholland out: 2172 1.1 dholland NFSEXITCODE2(0, nd); 2173 1.1 dholland return (0); 2174 1.1 dholland } 2175 1.1 dholland 2176 1.1 dholland /* 2177 1.1 dholland * nfsv4 lock service 2178 1.1 dholland */ 2179 1.1 dholland APPLESTATIC int 2180 1.1 dholland nfsrvd_lock(struct nfsrv_descript *nd, __unused int isdgram, 2181 1.1 dholland vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp) 2182 1.1 dholland { 2183 1.1 dholland u_int32_t *tl; 2184 1.1 dholland int i; 2185 1.1 dholland struct nfsstate *stp = NULL; 2186 1.1 dholland struct nfslock *lop; 2187 1.1 dholland struct nfslockconflict cf; 2188 1.1 dholland int error = 0; 2189 1.1 dholland u_short flags = NFSLCK_LOCK, lflags; 2190 1.1 dholland u_int64_t offset, len; 2191 1.1 dholland nfsv4stateid_t stateid; 2192 1.1 dholland nfsquad_t clientid; 2193 1.1 dholland 2194 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 7 * NFSX_UNSIGNED); 2195 1.1 dholland i = fxdr_unsigned(int, *tl++); 2196 1.1 dholland switch (i) { 2197 1.1 dholland case NFSV4LOCKT_READW: 2198 1.1 dholland flags |= NFSLCK_BLOCKING; 2199 1.1 dholland case NFSV4LOCKT_READ: 2200 1.1 dholland lflags = NFSLCK_READ; 2201 1.1 dholland break; 2202 1.1 dholland case NFSV4LOCKT_WRITEW: 2203 1.1 dholland flags |= NFSLCK_BLOCKING; 2204 1.1 dholland case NFSV4LOCKT_WRITE: 2205 1.1 dholland lflags = NFSLCK_WRITE; 2206 1.1 dholland break; 2207 1.1 dholland default: 2208 1.1 dholland nd->nd_repstat = NFSERR_BADXDR; 2209 1.1 dholland goto nfsmout; 2210 1.3 pgoyette } 2211 1.1 dholland if (*tl++ == newnfs_true) 2212 1.1 dholland flags |= NFSLCK_RECLAIM; 2213 1.1 dholland offset = fxdr_hyper(tl); 2214 1.1 dholland tl += 2; 2215 1.1 dholland len = fxdr_hyper(tl); 2216 1.1 dholland tl += 2; 2217 1.1 dholland if (*tl == newnfs_true) 2218 1.1 dholland flags |= NFSLCK_OPENTOLOCK; 2219 1.1 dholland if (flags & NFSLCK_OPENTOLOCK) { 2220 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED + NFSX_STATEID); 2221 1.1 dholland i = fxdr_unsigned(int, *(tl+4+(NFSX_STATEID / NFSX_UNSIGNED))); 2222 1.1 dholland if (i <= 0 || i > NFSV4_OPAQUELIMIT) { 2223 1.1 dholland nd->nd_repstat = NFSERR_BADXDR; 2224 1.1 dholland goto nfsmout; 2225 1.1 dholland } 2226 1.1 dholland MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + i, 2227 1.1 dholland M_NFSDSTATE, M_WAITOK); 2228 1.1 dholland stp->ls_ownerlen = i; 2229 1.1 dholland stp->ls_op = nd->nd_rp; 2230 1.1 dholland stp->ls_seq = fxdr_unsigned(int, *tl++); 2231 1.1 dholland stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 2232 1.1 dholland NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other, 2233 1.1 dholland NFSX_STATEIDOTHER); 2234 1.1 dholland tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 2235 1.1 dholland stp->ls_opentolockseq = fxdr_unsigned(int, *tl++); 2236 1.1 dholland clientid.lval[0] = *tl++; 2237 1.1 dholland clientid.lval[1] = *tl++; 2238 1.3 pgoyette if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 2239 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 2240 1.3 pgoyette clientid.qval = nd->nd_clientid.qval; 2241 1.3 pgoyette else if (nd->nd_clientid.qval != clientid.qval) 2242 1.3 pgoyette printf("EEK3 multiple clids\n"); 2243 1.1 dholland } else { 2244 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 2245 1.3 pgoyette printf("EEK! no clientid from session\n"); 2246 1.1 dholland nd->nd_flag |= ND_IMPLIEDCLID; 2247 1.1 dholland nd->nd_clientid.qval = clientid.qval; 2248 1.1 dholland } 2249 1.1 dholland error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen); 2250 1.1 dholland if (error) 2251 1.1 dholland goto nfsmout; 2252 1.1 dholland } else { 2253 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED); 2254 1.1 dholland MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate), 2255 1.1 dholland M_NFSDSTATE, M_WAITOK); 2256 1.1 dholland stp->ls_ownerlen = 0; 2257 1.1 dholland stp->ls_op = nd->nd_rp; 2258 1.1 dholland stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 2259 1.1 dholland NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other, 2260 1.1 dholland NFSX_STATEIDOTHER); 2261 1.1 dholland tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 2262 1.1 dholland stp->ls_seq = fxdr_unsigned(int, *tl); 2263 1.1 dholland clientid.lval[0] = stp->ls_stateid.other[0]; 2264 1.1 dholland clientid.lval[1] = stp->ls_stateid.other[1]; 2265 1.3 pgoyette if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 2266 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 2267 1.3 pgoyette clientid.qval = nd->nd_clientid.qval; 2268 1.3 pgoyette else if (nd->nd_clientid.qval != clientid.qval) 2269 1.3 pgoyette printf("EEK4 multiple clids\n"); 2270 1.1 dholland } else { 2271 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 2272 1.3 pgoyette printf("EEK! no clientid from session\n"); 2273 1.1 dholland nd->nd_flag |= ND_IMPLIEDCLID; 2274 1.1 dholland nd->nd_clientid.qval = clientid.qval; 2275 1.1 dholland } 2276 1.1 dholland } 2277 1.1 dholland MALLOC(lop, struct nfslock *, sizeof (struct nfslock), 2278 1.1 dholland M_NFSDLOCK, M_WAITOK); 2279 1.1 dholland lop->lo_first = offset; 2280 1.1 dholland if (len == NFS64BITSSET) { 2281 1.1 dholland lop->lo_end = NFS64BITSSET; 2282 1.1 dholland } else { 2283 1.1 dholland lop->lo_end = offset + len; 2284 1.1 dholland if (lop->lo_end <= lop->lo_first) 2285 1.1 dholland nd->nd_repstat = NFSERR_INVAL; 2286 1.1 dholland } 2287 1.1 dholland lop->lo_flags = lflags; 2288 1.1 dholland stp->ls_flags = flags; 2289 1.1 dholland stp->ls_uid = nd->nd_cred->cr_uid; 2290 1.1 dholland 2291 1.1 dholland /* 2292 1.1 dholland * Do basic access checking. 2293 1.1 dholland */ 2294 1.1 dholland if (!nd->nd_repstat && vnode_vtype(vp) != VREG) { 2295 1.1 dholland if (vnode_vtype(vp) == VDIR) 2296 1.1 dholland nd->nd_repstat = NFSERR_ISDIR; 2297 1.1 dholland else 2298 1.1 dholland nd->nd_repstat = NFSERR_INVAL; 2299 1.1 dholland } 2300 1.1 dholland if (!nd->nd_repstat) { 2301 1.1 dholland if (lflags & NFSLCK_WRITE) { 2302 1.1 dholland nd->nd_repstat = nfsvno_accchk(vp, VWRITE, 2303 1.1 dholland nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER, 2304 1.1 dholland NFSACCCHK_VPISLOCKED, NULL); 2305 1.1 dholland } else { 2306 1.1 dholland nd->nd_repstat = nfsvno_accchk(vp, VREAD, 2307 1.1 dholland nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER, 2308 1.1 dholland NFSACCCHK_VPISLOCKED, NULL); 2309 1.1 dholland if (nd->nd_repstat) 2310 1.1 dholland nd->nd_repstat = nfsvno_accchk(vp, VEXEC, 2311 1.1 dholland nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER, 2312 1.1 dholland NFSACCCHK_VPISLOCKED, NULL); 2313 1.1 dholland } 2314 1.1 dholland } 2315 1.1 dholland 2316 1.1 dholland /* 2317 1.1 dholland * We call nfsrv_lockctrl() even if nd_repstat set, so that the 2318 1.1 dholland * seqid# gets updated. nfsrv_lockctrl() will return the value 2319 1.1 dholland * of nd_repstat, if it gets that far. 2320 1.1 dholland */ 2321 1.1 dholland nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, &cf, clientid, 2322 1.1 dholland &stateid, exp, nd, p); 2323 1.1 dholland if (lop) 2324 1.1 dholland FREE((caddr_t)lop, M_NFSDLOCK); 2325 1.1 dholland if (stp) 2326 1.1 dholland FREE((caddr_t)stp, M_NFSDSTATE); 2327 1.1 dholland if (!nd->nd_repstat) { 2328 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID); 2329 1.1 dholland *tl++ = txdr_unsigned(stateid.seqid); 2330 1.1 dholland NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER); 2331 1.1 dholland } else if (nd->nd_repstat == NFSERR_DENIED) { 2332 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED); 2333 1.1 dholland txdr_hyper(cf.cl_first, tl); 2334 1.1 dholland tl += 2; 2335 1.1 dholland if (cf.cl_end == NFS64BITSSET) 2336 1.1 dholland len = NFS64BITSSET; 2337 1.1 dholland else 2338 1.1 dholland len = cf.cl_end - cf.cl_first; 2339 1.1 dholland txdr_hyper(len, tl); 2340 1.1 dholland tl += 2; 2341 1.1 dholland if (cf.cl_flags == NFSLCK_WRITE) 2342 1.1 dholland *tl++ = txdr_unsigned(NFSV4LOCKT_WRITE); 2343 1.1 dholland else 2344 1.1 dholland *tl++ = txdr_unsigned(NFSV4LOCKT_READ); 2345 1.1 dholland *tl++ = stateid.other[0]; 2346 1.1 dholland *tl = stateid.other[1]; 2347 1.1 dholland (void) nfsm_strtom(nd, cf.cl_owner, cf.cl_ownerlen); 2348 1.1 dholland } 2349 1.1 dholland vput(vp); 2350 1.1 dholland NFSEXITCODE2(0, nd); 2351 1.1 dholland return (0); 2352 1.1 dholland nfsmout: 2353 1.1 dholland vput(vp); 2354 1.1 dholland if (stp) 2355 1.1 dholland free((caddr_t)stp, M_NFSDSTATE); 2356 1.1 dholland NFSEXITCODE2(error, nd); 2357 1.1 dholland return (error); 2358 1.1 dholland } 2359 1.1 dholland 2360 1.1 dholland /* 2361 1.1 dholland * nfsv4 lock test service 2362 1.1 dholland */ 2363 1.1 dholland APPLESTATIC int 2364 1.1 dholland nfsrvd_lockt(struct nfsrv_descript *nd, __unused int isdgram, 2365 1.1 dholland vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp) 2366 1.1 dholland { 2367 1.1 dholland u_int32_t *tl; 2368 1.1 dholland int i; 2369 1.1 dholland struct nfsstate *stp = NULL; 2370 1.1 dholland struct nfslock lo, *lop = &lo; 2371 1.1 dholland struct nfslockconflict cf; 2372 1.1 dholland int error = 0; 2373 1.1 dholland nfsv4stateid_t stateid; 2374 1.1 dholland nfsquad_t clientid; 2375 1.1 dholland u_int64_t len; 2376 1.1 dholland 2377 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 8 * NFSX_UNSIGNED); 2378 1.1 dholland i = fxdr_unsigned(int, *(tl + 7)); 2379 1.1 dholland if (i <= 0 || i > NFSV4_OPAQUELIMIT) { 2380 1.1 dholland nd->nd_repstat = NFSERR_BADXDR; 2381 1.1 dholland goto nfsmout; 2382 1.1 dholland } 2383 1.1 dholland MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + i, 2384 1.1 dholland M_NFSDSTATE, M_WAITOK); 2385 1.1 dholland stp->ls_ownerlen = i; 2386 1.1 dholland stp->ls_op = NULL; 2387 1.1 dholland stp->ls_flags = NFSLCK_TEST; 2388 1.1 dholland stp->ls_uid = nd->nd_cred->cr_uid; 2389 1.1 dholland i = fxdr_unsigned(int, *tl++); 2390 1.1 dholland switch (i) { 2391 1.1 dholland case NFSV4LOCKT_READW: 2392 1.1 dholland stp->ls_flags |= NFSLCK_BLOCKING; 2393 1.1 dholland case NFSV4LOCKT_READ: 2394 1.1 dholland lo.lo_flags = NFSLCK_READ; 2395 1.1 dholland break; 2396 1.1 dholland case NFSV4LOCKT_WRITEW: 2397 1.1 dholland stp->ls_flags |= NFSLCK_BLOCKING; 2398 1.1 dholland case NFSV4LOCKT_WRITE: 2399 1.1 dholland lo.lo_flags = NFSLCK_WRITE; 2400 1.1 dholland break; 2401 1.1 dholland default: 2402 1.1 dholland nd->nd_repstat = NFSERR_BADXDR; 2403 1.1 dholland goto nfsmout; 2404 1.3 pgoyette } 2405 1.1 dholland lo.lo_first = fxdr_hyper(tl); 2406 1.1 dholland tl += 2; 2407 1.1 dholland len = fxdr_hyper(tl); 2408 1.1 dholland if (len == NFS64BITSSET) { 2409 1.1 dholland lo.lo_end = NFS64BITSSET; 2410 1.1 dholland } else { 2411 1.1 dholland lo.lo_end = lo.lo_first + len; 2412 1.1 dholland if (lo.lo_end <= lo.lo_first) 2413 1.1 dholland nd->nd_repstat = NFSERR_INVAL; 2414 1.1 dholland } 2415 1.1 dholland tl += 2; 2416 1.1 dholland clientid.lval[0] = *tl++; 2417 1.1 dholland clientid.lval[1] = *tl; 2418 1.3 pgoyette if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 2419 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 2420 1.3 pgoyette clientid.qval = nd->nd_clientid.qval; 2421 1.3 pgoyette else if (nd->nd_clientid.qval != clientid.qval) 2422 1.3 pgoyette printf("EEK5 multiple clids\n"); 2423 1.1 dholland } else { 2424 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 2425 1.3 pgoyette printf("EEK! no clientid from session\n"); 2426 1.1 dholland nd->nd_flag |= ND_IMPLIEDCLID; 2427 1.1 dholland nd->nd_clientid.qval = clientid.qval; 2428 1.1 dholland } 2429 1.1 dholland error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen); 2430 1.1 dholland if (error) 2431 1.1 dholland goto nfsmout; 2432 1.1 dholland if (!nd->nd_repstat && vnode_vtype(vp) != VREG) { 2433 1.1 dholland if (vnode_vtype(vp) == VDIR) 2434 1.1 dholland nd->nd_repstat = NFSERR_ISDIR; 2435 1.1 dholland else 2436 1.1 dholland nd->nd_repstat = NFSERR_INVAL; 2437 1.1 dholland } 2438 1.1 dholland if (!nd->nd_repstat) 2439 1.1 dholland nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, &cf, clientid, 2440 1.1 dholland &stateid, exp, nd, p); 2441 1.1 dholland if (nd->nd_repstat) { 2442 1.1 dholland if (nd->nd_repstat == NFSERR_DENIED) { 2443 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED); 2444 1.1 dholland txdr_hyper(cf.cl_first, tl); 2445 1.1 dholland tl += 2; 2446 1.1 dholland if (cf.cl_end == NFS64BITSSET) 2447 1.1 dholland len = NFS64BITSSET; 2448 1.1 dholland else 2449 1.1 dholland len = cf.cl_end - cf.cl_first; 2450 1.1 dholland txdr_hyper(len, tl); 2451 1.1 dholland tl += 2; 2452 1.1 dholland if (cf.cl_flags == NFSLCK_WRITE) 2453 1.1 dholland *tl++ = txdr_unsigned(NFSV4LOCKT_WRITE); 2454 1.1 dholland else 2455 1.1 dholland *tl++ = txdr_unsigned(NFSV4LOCKT_READ); 2456 1.1 dholland *tl++ = stp->ls_stateid.other[0]; 2457 1.1 dholland *tl = stp->ls_stateid.other[1]; 2458 1.1 dholland (void) nfsm_strtom(nd, cf.cl_owner, cf.cl_ownerlen); 2459 1.1 dholland } 2460 1.1 dholland } 2461 1.1 dholland vput(vp); 2462 1.3 pgoyette if (stp) 2463 1.3 pgoyette FREE((caddr_t)stp, M_NFSDSTATE); 2464 1.1 dholland NFSEXITCODE2(0, nd); 2465 1.1 dholland return (0); 2466 1.1 dholland nfsmout: 2467 1.1 dholland vput(vp); 2468 1.1 dholland if (stp) 2469 1.1 dholland free((caddr_t)stp, M_NFSDSTATE); 2470 1.1 dholland NFSEXITCODE2(error, nd); 2471 1.1 dholland return (error); 2472 1.1 dholland } 2473 1.1 dholland 2474 1.1 dholland /* 2475 1.1 dholland * nfsv4 unlock service 2476 1.1 dholland */ 2477 1.1 dholland APPLESTATIC int 2478 1.1 dholland nfsrvd_locku(struct nfsrv_descript *nd, __unused int isdgram, 2479 1.1 dholland vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp) 2480 1.1 dholland { 2481 1.1 dholland u_int32_t *tl; 2482 1.1 dholland int i; 2483 1.1 dholland struct nfsstate *stp; 2484 1.1 dholland struct nfslock *lop; 2485 1.1 dholland int error = 0; 2486 1.1 dholland nfsv4stateid_t stateid; 2487 1.1 dholland nfsquad_t clientid; 2488 1.1 dholland u_int64_t len; 2489 1.1 dholland 2490 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED + NFSX_STATEID); 2491 1.1 dholland MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate), 2492 1.1 dholland M_NFSDSTATE, M_WAITOK); 2493 1.1 dholland MALLOC(lop, struct nfslock *, sizeof (struct nfslock), 2494 1.1 dholland M_NFSDLOCK, M_WAITOK); 2495 1.1 dholland stp->ls_flags = NFSLCK_UNLOCK; 2496 1.1 dholland lop->lo_flags = NFSLCK_UNLOCK; 2497 1.1 dholland stp->ls_op = nd->nd_rp; 2498 1.1 dholland i = fxdr_unsigned(int, *tl++); 2499 1.1 dholland switch (i) { 2500 1.1 dholland case NFSV4LOCKT_READW: 2501 1.1 dholland stp->ls_flags |= NFSLCK_BLOCKING; 2502 1.1 dholland case NFSV4LOCKT_READ: 2503 1.1 dholland break; 2504 1.1 dholland case NFSV4LOCKT_WRITEW: 2505 1.1 dholland stp->ls_flags |= NFSLCK_BLOCKING; 2506 1.1 dholland case NFSV4LOCKT_WRITE: 2507 1.1 dholland break; 2508 1.1 dholland default: 2509 1.1 dholland nd->nd_repstat = NFSERR_BADXDR; 2510 1.1 dholland free(stp, M_NFSDSTATE); 2511 1.1 dholland free(lop, M_NFSDLOCK); 2512 1.1 dholland goto nfsmout; 2513 1.3 pgoyette } 2514 1.1 dholland stp->ls_ownerlen = 0; 2515 1.1 dholland stp->ls_uid = nd->nd_cred->cr_uid; 2516 1.1 dholland stp->ls_seq = fxdr_unsigned(int, *tl++); 2517 1.1 dholland stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 2518 1.1 dholland NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other, 2519 1.1 dholland NFSX_STATEIDOTHER); 2520 1.1 dholland tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 2521 1.1 dholland lop->lo_first = fxdr_hyper(tl); 2522 1.1 dholland tl += 2; 2523 1.1 dholland len = fxdr_hyper(tl); 2524 1.1 dholland if (len == NFS64BITSSET) { 2525 1.1 dholland lop->lo_end = NFS64BITSSET; 2526 1.1 dholland } else { 2527 1.1 dholland lop->lo_end = lop->lo_first + len; 2528 1.1 dholland if (lop->lo_end <= lop->lo_first) 2529 1.1 dholland nd->nd_repstat = NFSERR_INVAL; 2530 1.1 dholland } 2531 1.1 dholland clientid.lval[0] = stp->ls_stateid.other[0]; 2532 1.1 dholland clientid.lval[1] = stp->ls_stateid.other[1]; 2533 1.3 pgoyette if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 2534 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 2535 1.3 pgoyette clientid.qval = nd->nd_clientid.qval; 2536 1.3 pgoyette else if (nd->nd_clientid.qval != clientid.qval) 2537 1.3 pgoyette printf("EEK6 multiple clids\n"); 2538 1.1 dholland } else { 2539 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 2540 1.3 pgoyette printf("EEK! no clientid from session\n"); 2541 1.1 dholland nd->nd_flag |= ND_IMPLIEDCLID; 2542 1.1 dholland nd->nd_clientid.qval = clientid.qval; 2543 1.1 dholland } 2544 1.1 dholland if (!nd->nd_repstat && vnode_vtype(vp) != VREG) { 2545 1.1 dholland if (vnode_vtype(vp) == VDIR) 2546 1.1 dholland nd->nd_repstat = NFSERR_ISDIR; 2547 1.1 dholland else 2548 1.1 dholland nd->nd_repstat = NFSERR_INVAL; 2549 1.1 dholland } 2550 1.1 dholland /* 2551 1.1 dholland * Call nfsrv_lockctrl() even if nd_repstat is set, so that the 2552 1.1 dholland * seqid# gets incremented. nfsrv_lockctrl() will return the 2553 1.1 dholland * value of nd_repstat, if it gets that far. 2554 1.1 dholland */ 2555 1.1 dholland nd->nd_repstat = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid, 2556 1.1 dholland &stateid, exp, nd, p); 2557 1.1 dholland if (stp) 2558 1.1 dholland FREE((caddr_t)stp, M_NFSDSTATE); 2559 1.1 dholland if (lop) 2560 1.1 dholland free((caddr_t)lop, M_NFSDLOCK); 2561 1.1 dholland if (!nd->nd_repstat) { 2562 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID); 2563 1.1 dholland *tl++ = txdr_unsigned(stateid.seqid); 2564 1.1 dholland NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER); 2565 1.1 dholland } 2566 1.1 dholland nfsmout: 2567 1.1 dholland vput(vp); 2568 1.1 dholland NFSEXITCODE2(error, nd); 2569 1.1 dholland return (error); 2570 1.1 dholland } 2571 1.1 dholland 2572 1.1 dholland /* 2573 1.1 dholland * nfsv4 open service 2574 1.1 dholland */ 2575 1.1 dholland APPLESTATIC int 2576 1.1 dholland nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram, 2577 1.1 dholland vnode_t dp, vnode_t *vpp, __unused fhandle_t *fhp, NFSPROC_T *p, 2578 1.1 dholland struct nfsexstuff *exp) 2579 1.1 dholland { 2580 1.1 dholland u_int32_t *tl; 2581 1.3 pgoyette int i, retext; 2582 1.1 dholland struct nfsstate *stp = NULL; 2583 1.1 dholland int error = 0, create, claim, exclusive_flag = 0; 2584 1.1 dholland u_int32_t rflags = NFSV4OPEN_LOCKTYPEPOSIX, acemask; 2585 1.1 dholland int how = NFSCREATE_UNCHECKED; 2586 1.1 dholland int32_t cverf[2], tverf[2] = { 0, 0 }; 2587 1.1 dholland vnode_t vp = NULL, dirp = NULL; 2588 1.1 dholland struct nfsvattr nva, dirfor, diraft; 2589 1.1 dholland struct nameidata named; 2590 1.1 dholland nfsv4stateid_t stateid, delegstateid; 2591 1.1 dholland nfsattrbit_t attrbits; 2592 1.1 dholland nfsquad_t clientid; 2593 1.1 dholland char *bufp = NULL; 2594 1.1 dholland u_long *hashp; 2595 1.1 dholland NFSACL_T *aclp = NULL; 2596 1.1 dholland 2597 1.1 dholland #ifdef NFS4_ACL_EXTATTR_NAME 2598 1.1 dholland aclp = acl_alloc(M_WAITOK); 2599 1.1 dholland aclp->acl_cnt = 0; 2600 1.1 dholland #endif 2601 1.1 dholland NFSZERO_ATTRBIT(&attrbits); 2602 1.1 dholland named.ni_startdir = NULL; 2603 1.1 dholland named.ni_cnd.cn_nameiop = 0; 2604 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED); 2605 1.1 dholland i = fxdr_unsigned(int, *(tl + 5)); 2606 1.1 dholland if (i <= 0 || i > NFSV4_OPAQUELIMIT) { 2607 1.1 dholland nd->nd_repstat = NFSERR_BADXDR; 2608 1.1 dholland goto nfsmout; 2609 1.1 dholland } 2610 1.1 dholland MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + i, 2611 1.1 dholland M_NFSDSTATE, M_WAITOK); 2612 1.1 dholland stp->ls_ownerlen = i; 2613 1.1 dholland stp->ls_op = nd->nd_rp; 2614 1.1 dholland stp->ls_flags = NFSLCK_OPEN; 2615 1.1 dholland stp->ls_uid = nd->nd_cred->cr_uid; 2616 1.1 dholland stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++); 2617 1.1 dholland i = fxdr_unsigned(int, *tl++); 2618 1.3 pgoyette retext = 0; 2619 1.3 pgoyette if ((i & (NFSV4OPEN_WANTDELEGMASK | NFSV4OPEN_WANTSIGNALDELEG | 2620 1.3 pgoyette NFSV4OPEN_WANTPUSHDELEG)) != 0 && (nd->nd_flag & ND_NFSV41) != 0) { 2621 1.3 pgoyette retext = 1; 2622 1.3 pgoyette /* For now, ignore these. */ 2623 1.3 pgoyette i &= ~(NFSV4OPEN_WANTPUSHDELEG | NFSV4OPEN_WANTSIGNALDELEG); 2624 1.3 pgoyette switch (i & NFSV4OPEN_WANTDELEGMASK) { 2625 1.3 pgoyette case NFSV4OPEN_WANTANYDELEG: 2626 1.3 pgoyette stp->ls_flags |= (NFSLCK_WANTRDELEG | 2627 1.3 pgoyette NFSLCK_WANTWDELEG); 2628 1.3 pgoyette i &= ~NFSV4OPEN_WANTDELEGMASK; 2629 1.3 pgoyette break; 2630 1.3 pgoyette case NFSV4OPEN_WANTREADDELEG: 2631 1.3 pgoyette stp->ls_flags |= NFSLCK_WANTRDELEG; 2632 1.3 pgoyette i &= ~NFSV4OPEN_WANTDELEGMASK; 2633 1.3 pgoyette break; 2634 1.3 pgoyette case NFSV4OPEN_WANTWRITEDELEG: 2635 1.3 pgoyette stp->ls_flags |= NFSLCK_WANTWDELEG; 2636 1.3 pgoyette i &= ~NFSV4OPEN_WANTDELEGMASK; 2637 1.3 pgoyette break; 2638 1.3 pgoyette case NFSV4OPEN_WANTNODELEG: 2639 1.3 pgoyette stp->ls_flags |= NFSLCK_WANTNODELEG; 2640 1.3 pgoyette i &= ~NFSV4OPEN_WANTDELEGMASK; 2641 1.3 pgoyette break; 2642 1.3 pgoyette case NFSV4OPEN_WANTCANCEL: 2643 1.3 pgoyette printf("NFSv4: ignore Open WantCancel\n"); 2644 1.3 pgoyette i &= ~NFSV4OPEN_WANTDELEGMASK; 2645 1.3 pgoyette break; 2646 1.3 pgoyette default: 2647 1.3 pgoyette /* nd_repstat will be set to NFSERR_INVAL below. */ 2648 1.3 pgoyette break; 2649 1.3 pgoyette } 2650 1.3 pgoyette } 2651 1.1 dholland switch (i) { 2652 1.1 dholland case NFSV4OPEN_ACCESSREAD: 2653 1.1 dholland stp->ls_flags |= NFSLCK_READACCESS; 2654 1.1 dholland break; 2655 1.1 dholland case NFSV4OPEN_ACCESSWRITE: 2656 1.1 dholland stp->ls_flags |= NFSLCK_WRITEACCESS; 2657 1.1 dholland break; 2658 1.1 dholland case NFSV4OPEN_ACCESSBOTH: 2659 1.1 dholland stp->ls_flags |= (NFSLCK_READACCESS | NFSLCK_WRITEACCESS); 2660 1.1 dholland break; 2661 1.1 dholland default: 2662 1.1 dholland nd->nd_repstat = NFSERR_INVAL; 2663 1.3 pgoyette } 2664 1.1 dholland i = fxdr_unsigned(int, *tl++); 2665 1.1 dholland switch (i) { 2666 1.1 dholland case NFSV4OPEN_DENYNONE: 2667 1.1 dholland break; 2668 1.1 dholland case NFSV4OPEN_DENYREAD: 2669 1.1 dholland stp->ls_flags |= NFSLCK_READDENY; 2670 1.1 dholland break; 2671 1.1 dholland case NFSV4OPEN_DENYWRITE: 2672 1.1 dholland stp->ls_flags |= NFSLCK_WRITEDENY; 2673 1.1 dholland break; 2674 1.1 dholland case NFSV4OPEN_DENYBOTH: 2675 1.1 dholland stp->ls_flags |= (NFSLCK_READDENY | NFSLCK_WRITEDENY); 2676 1.1 dholland break; 2677 1.1 dholland default: 2678 1.1 dholland nd->nd_repstat = NFSERR_INVAL; 2679 1.3 pgoyette } 2680 1.1 dholland clientid.lval[0] = *tl++; 2681 1.1 dholland clientid.lval[1] = *tl; 2682 1.3 pgoyette if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 2683 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 2684 1.3 pgoyette clientid.qval = nd->nd_clientid.qval; 2685 1.3 pgoyette else if (nd->nd_clientid.qval != clientid.qval) 2686 1.3 pgoyette printf("EEK7 multiple clids\n"); 2687 1.1 dholland } else { 2688 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 2689 1.3 pgoyette printf("EEK! no clientid from session\n"); 2690 1.1 dholland nd->nd_flag |= ND_IMPLIEDCLID; 2691 1.1 dholland nd->nd_clientid.qval = clientid.qval; 2692 1.1 dholland } 2693 1.1 dholland error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen); 2694 1.1 dholland if (error) 2695 1.1 dholland goto nfsmout; 2696 1.1 dholland NFSVNO_ATTRINIT(&nva); 2697 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2698 1.1 dholland create = fxdr_unsigned(int, *tl); 2699 1.1 dholland if (!nd->nd_repstat) 2700 1.1 dholland nd->nd_repstat = nfsvno_getattr(dp, &dirfor, nd->nd_cred, p, 0); 2701 1.1 dholland if (create == NFSV4OPEN_CREATE) { 2702 1.1 dholland nva.na_type = VREG; 2703 1.1 dholland nva.na_mode = 0; 2704 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2705 1.1 dholland how = fxdr_unsigned(int, *tl); 2706 1.1 dholland switch (how) { 2707 1.1 dholland case NFSCREATE_UNCHECKED: 2708 1.1 dholland case NFSCREATE_GUARDED: 2709 1.3 pgoyette error = nfsv4_sattr(nd, NULL, &nva, &attrbits, aclp, p); 2710 1.1 dholland if (error) 2711 1.1 dholland goto nfsmout; 2712 1.1 dholland /* 2713 1.1 dholland * If the na_gid being set is the same as that of 2714 1.1 dholland * the directory it is going in, clear it, since 2715 1.1 dholland * that is what will be set by default. This allows 2716 1.1 dholland * a user that isn't in that group to do the create. 2717 1.1 dholland */ 2718 1.1 dholland if (!nd->nd_repstat && NFSVNO_ISSETGID(&nva) && 2719 1.1 dholland nva.na_gid == dirfor.na_gid) 2720 1.1 dholland NFSVNO_UNSET(&nva, gid); 2721 1.1 dholland if (!nd->nd_repstat) 2722 1.1 dholland nd->nd_repstat = nfsrv_checkuidgid(nd, &nva); 2723 1.1 dholland break; 2724 1.1 dholland case NFSCREATE_EXCLUSIVE: 2725 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF); 2726 1.1 dholland cverf[0] = *tl++; 2727 1.1 dholland cverf[1] = *tl; 2728 1.1 dholland break; 2729 1.3 pgoyette case NFSCREATE_EXCLUSIVE41: 2730 1.3 pgoyette NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF); 2731 1.3 pgoyette cverf[0] = *tl++; 2732 1.3 pgoyette cverf[1] = *tl; 2733 1.3 pgoyette error = nfsv4_sattr(nd, vp, &nva, &attrbits, aclp, p); 2734 1.3 pgoyette if (error != 0) 2735 1.3 pgoyette goto nfsmout; 2736 1.3 pgoyette if (NFSISSET_ATTRBIT(&attrbits, 2737 1.3 pgoyette NFSATTRBIT_TIMEACCESSSET)) 2738 1.3 pgoyette nd->nd_repstat = NFSERR_INVAL; 2739 1.3 pgoyette /* 2740 1.3 pgoyette * If the na_gid being set is the same as that of 2741 1.3 pgoyette * the directory it is going in, clear it, since 2742 1.3 pgoyette * that is what will be set by default. This allows 2743 1.3 pgoyette * a user that isn't in that group to do the create. 2744 1.3 pgoyette */ 2745 1.3 pgoyette if (nd->nd_repstat == 0 && NFSVNO_ISSETGID(&nva) && 2746 1.3 pgoyette nva.na_gid == dirfor.na_gid) 2747 1.3 pgoyette NFSVNO_UNSET(&nva, gid); 2748 1.3 pgoyette if (nd->nd_repstat == 0) 2749 1.3 pgoyette nd->nd_repstat = nfsrv_checkuidgid(nd, &nva); 2750 1.3 pgoyette break; 2751 1.1 dholland default: 2752 1.1 dholland nd->nd_repstat = NFSERR_BADXDR; 2753 1.1 dholland goto nfsmout; 2754 1.3 pgoyette } 2755 1.1 dholland } else if (create != NFSV4OPEN_NOCREATE) { 2756 1.1 dholland nd->nd_repstat = NFSERR_BADXDR; 2757 1.1 dholland goto nfsmout; 2758 1.1 dholland } 2759 1.1 dholland 2760 1.1 dholland /* 2761 1.1 dholland * Now, handle the claim, which usually includes looking up a 2762 1.1 dholland * name in the directory referenced by dp. The exception is 2763 1.1 dholland * NFSV4OPEN_CLAIMPREVIOUS. 2764 1.1 dholland */ 2765 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2766 1.1 dholland claim = fxdr_unsigned(int, *tl); 2767 1.1 dholland if (claim == NFSV4OPEN_CLAIMDELEGATECUR) { 2768 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID); 2769 1.1 dholland stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 2770 1.1 dholland NFSBCOPY((caddr_t)tl,(caddr_t)stateid.other,NFSX_STATEIDOTHER); 2771 1.1 dholland stp->ls_flags |= NFSLCK_DELEGCUR; 2772 1.1 dholland } else if (claim == NFSV4OPEN_CLAIMDELEGATEPREV) { 2773 1.1 dholland stp->ls_flags |= NFSLCK_DELEGPREV; 2774 1.1 dholland } 2775 1.1 dholland if (claim == NFSV4OPEN_CLAIMNULL || claim == NFSV4OPEN_CLAIMDELEGATECUR 2776 1.1 dholland || claim == NFSV4OPEN_CLAIMDELEGATEPREV) { 2777 1.1 dholland if (!nd->nd_repstat && create == NFSV4OPEN_CREATE && 2778 1.1 dholland claim != NFSV4OPEN_CLAIMNULL) 2779 1.1 dholland nd->nd_repstat = NFSERR_INVAL; 2780 1.1 dholland if (nd->nd_repstat) { 2781 1.1 dholland nd->nd_repstat = nfsrv_opencheck(clientid, 2782 1.1 dholland &stateid, stp, NULL, nd, p, nd->nd_repstat); 2783 1.1 dholland goto nfsmout; 2784 1.1 dholland } 2785 1.1 dholland if (create == NFSV4OPEN_CREATE) 2786 1.1 dholland NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, 2787 1.3 pgoyette LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE); 2788 1.1 dholland else 2789 1.1 dholland NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP, 2790 1.1 dholland LOCKLEAF | SAVESTART); 2791 1.1 dholland nfsvno_setpathbuf(&named, &bufp, &hashp); 2792 1.1 dholland error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 2793 1.1 dholland if (error) { 2794 1.1 dholland vrele(dp); 2795 1.1 dholland #ifdef NFS4_ACL_EXTATTR_NAME 2796 1.1 dholland acl_free(aclp); 2797 1.1 dholland #endif 2798 1.1 dholland FREE((caddr_t)stp, M_NFSDSTATE); 2799 1.1 dholland nfsvno_relpathbuf(&named); 2800 1.1 dholland NFSEXITCODE2(error, nd); 2801 1.1 dholland return (error); 2802 1.1 dholland } 2803 1.1 dholland if (!nd->nd_repstat) { 2804 1.1 dholland nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, 2805 1.1 dholland p, &dirp); 2806 1.1 dholland } else { 2807 1.1 dholland vrele(dp); 2808 1.1 dholland nfsvno_relpathbuf(&named); 2809 1.1 dholland } 2810 1.1 dholland if (create == NFSV4OPEN_CREATE) { 2811 1.1 dholland switch (how) { 2812 1.1 dholland case NFSCREATE_UNCHECKED: 2813 1.1 dholland if (named.ni_vp) { 2814 1.1 dholland /* 2815 1.1 dholland * Clear the setable attribute bits, except 2816 1.1 dholland * for Size, if it is being truncated. 2817 1.1 dholland */ 2818 1.1 dholland NFSZERO_ATTRBIT(&attrbits); 2819 1.1 dholland if (NFSVNO_ISSETSIZE(&nva)) 2820 1.1 dholland NFSSETBIT_ATTRBIT(&attrbits, 2821 1.1 dholland NFSATTRBIT_SIZE); 2822 1.1 dholland } 2823 1.1 dholland break; 2824 1.1 dholland case NFSCREATE_GUARDED: 2825 1.1 dholland if (named.ni_vp && !nd->nd_repstat) 2826 1.1 dholland nd->nd_repstat = EEXIST; 2827 1.1 dholland break; 2828 1.1 dholland case NFSCREATE_EXCLUSIVE: 2829 1.1 dholland exclusive_flag = 1; 2830 1.1 dholland if (!named.ni_vp) 2831 1.1 dholland nva.na_mode = 0; 2832 1.3 pgoyette break; 2833 1.3 pgoyette case NFSCREATE_EXCLUSIVE41: 2834 1.3 pgoyette exclusive_flag = 1; 2835 1.3 pgoyette break; 2836 1.3 pgoyette } 2837 1.1 dholland } 2838 1.1 dholland nfsvno_open(nd, &named, clientid, &stateid, stp, 2839 1.1 dholland &exclusive_flag, &nva, cverf, create, aclp, &attrbits, 2840 1.1 dholland nd->nd_cred, p, exp, &vp); 2841 1.3 pgoyette } else if (claim == NFSV4OPEN_CLAIMPREVIOUS || claim == 2842 1.3 pgoyette NFSV4OPEN_CLAIMFH) { 2843 1.3 pgoyette if (claim == NFSV4OPEN_CLAIMPREVIOUS) { 2844 1.3 pgoyette NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 2845 1.3 pgoyette i = fxdr_unsigned(int, *tl); 2846 1.3 pgoyette switch (i) { 2847 1.3 pgoyette case NFSV4OPEN_DELEGATEREAD: 2848 1.3 pgoyette stp->ls_flags |= NFSLCK_DELEGREAD; 2849 1.3 pgoyette break; 2850 1.3 pgoyette case NFSV4OPEN_DELEGATEWRITE: 2851 1.3 pgoyette stp->ls_flags |= NFSLCK_DELEGWRITE; 2852 1.3 pgoyette case NFSV4OPEN_DELEGATENONE: 2853 1.3 pgoyette break; 2854 1.3 pgoyette default: 2855 1.3 pgoyette nd->nd_repstat = NFSERR_BADXDR; 2856 1.3 pgoyette goto nfsmout; 2857 1.3 pgoyette } 2858 1.3 pgoyette stp->ls_flags |= NFSLCK_RECLAIM; 2859 1.3 pgoyette } else { 2860 1.3 pgoyette /* CLAIM_NULL_FH */ 2861 1.3 pgoyette if (nd->nd_repstat == 0 && create == NFSV4OPEN_CREATE) 2862 1.3 pgoyette nd->nd_repstat = NFSERR_INVAL; 2863 1.3 pgoyette } 2864 1.1 dholland vp = dp; 2865 1.1 dholland NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); 2866 1.1 dholland if ((vp->v_iflag & VI_DOOMED) == 0) 2867 1.1 dholland nd->nd_repstat = nfsrv_opencheck(clientid, &stateid, 2868 1.1 dholland stp, vp, nd, p, nd->nd_repstat); 2869 1.1 dholland else 2870 1.1 dholland nd->nd_repstat = NFSERR_PERM; 2871 1.1 dholland } else { 2872 1.1 dholland nd->nd_repstat = NFSERR_BADXDR; 2873 1.1 dholland goto nfsmout; 2874 1.1 dholland } 2875 1.1 dholland 2876 1.1 dholland /* 2877 1.1 dholland * Do basic access checking. 2878 1.1 dholland */ 2879 1.1 dholland if (!nd->nd_repstat && vnode_vtype(vp) != VREG) { 2880 1.1 dholland /* 2881 1.1 dholland * The IETF working group decided that this is the correct 2882 1.1 dholland * error return for all non-regular files. 2883 1.1 dholland */ 2884 1.3 pgoyette nd->nd_repstat = (vp->v_type == VDIR) ? NFSERR_ISDIR : NFSERR_SYMLINK; 2885 1.1 dholland } 2886 1.1 dholland if (!nd->nd_repstat && (stp->ls_flags & NFSLCK_WRITEACCESS)) 2887 1.1 dholland nd->nd_repstat = nfsvno_accchk(vp, VWRITE, nd->nd_cred, 2888 1.1 dholland exp, p, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL); 2889 1.1 dholland if (!nd->nd_repstat && (stp->ls_flags & NFSLCK_READACCESS)) { 2890 1.1 dholland nd->nd_repstat = nfsvno_accchk(vp, VREAD, nd->nd_cred, 2891 1.1 dholland exp, p, NFSACCCHK_ALLOWOWNER, NFSACCCHK_VPISLOCKED, NULL); 2892 1.1 dholland if (nd->nd_repstat) 2893 1.1 dholland nd->nd_repstat = nfsvno_accchk(vp, VEXEC, 2894 1.1 dholland nd->nd_cred, exp, p, NFSACCCHK_ALLOWOWNER, 2895 1.1 dholland NFSACCCHK_VPISLOCKED, NULL); 2896 1.1 dholland } 2897 1.1 dholland 2898 1.1 dholland if (!nd->nd_repstat) { 2899 1.1 dholland nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); 2900 1.1 dholland if (!nd->nd_repstat) { 2901 1.1 dholland tverf[0] = nva.na_atime.tv_sec; 2902 1.1 dholland tverf[1] = nva.na_atime.tv_nsec; 2903 1.1 dholland } 2904 1.1 dholland } 2905 1.1 dholland if (!nd->nd_repstat && exclusive_flag && (cverf[0] != tverf[0] || 2906 1.1 dholland cverf[1] != tverf[1])) 2907 1.1 dholland nd->nd_repstat = EEXIST; 2908 1.1 dholland /* 2909 1.1 dholland * Do the open locking/delegation stuff. 2910 1.1 dholland */ 2911 1.1 dholland if (!nd->nd_repstat) 2912 1.1 dholland nd->nd_repstat = nfsrv_openctrl(nd, vp, &stp, clientid, &stateid, 2913 1.1 dholland &delegstateid, &rflags, exp, p, nva.na_filerev); 2914 1.1 dholland 2915 1.1 dholland /* 2916 1.1 dholland * vp must be unlocked before the call to nfsvno_getattr(dirp,...) 2917 1.1 dholland * below, to avoid a deadlock with the lookup in nfsvno_namei() above. 2918 1.1 dholland * (ie: Leave the NFSVOPUNLOCK() about here.) 2919 1.1 dholland */ 2920 1.1 dholland if (vp) 2921 1.1 dholland NFSVOPUNLOCK(vp, 0); 2922 1.1 dholland if (stp) 2923 1.1 dholland FREE((caddr_t)stp, M_NFSDSTATE); 2924 1.1 dholland if (!nd->nd_repstat && dirp) 2925 1.1 dholland nd->nd_repstat = nfsvno_getattr(dirp, &diraft, nd->nd_cred, p, 2926 1.1 dholland 0); 2927 1.1 dholland if (!nd->nd_repstat) { 2928 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID + 6 * NFSX_UNSIGNED); 2929 1.1 dholland *tl++ = txdr_unsigned(stateid.seqid); 2930 1.1 dholland NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER); 2931 1.1 dholland tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 2932 1.1 dholland if (claim == NFSV4OPEN_CLAIMPREVIOUS) { 2933 1.1 dholland *tl++ = newnfs_true; 2934 1.1 dholland *tl++ = 0; 2935 1.1 dholland *tl++ = 0; 2936 1.1 dholland *tl++ = 0; 2937 1.1 dholland *tl++ = 0; 2938 1.1 dholland } else { 2939 1.1 dholland *tl++ = newnfs_false; /* Since dirp is not locked */ 2940 1.1 dholland txdr_hyper(dirfor.na_filerev, tl); 2941 1.1 dholland tl += 2; 2942 1.1 dholland txdr_hyper(diraft.na_filerev, tl); 2943 1.1 dholland tl += 2; 2944 1.1 dholland } 2945 1.1 dholland *tl = txdr_unsigned(rflags & NFSV4OPEN_RFLAGS); 2946 1.1 dholland (void) nfsrv_putattrbit(nd, &attrbits); 2947 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 2948 1.1 dholland if (rflags & NFSV4OPEN_READDELEGATE) 2949 1.1 dholland *tl = txdr_unsigned(NFSV4OPEN_DELEGATEREAD); 2950 1.1 dholland else if (rflags & NFSV4OPEN_WRITEDELEGATE) 2951 1.1 dholland *tl = txdr_unsigned(NFSV4OPEN_DELEGATEWRITE); 2952 1.3 pgoyette else if (retext != 0) { 2953 1.3 pgoyette *tl = txdr_unsigned(NFSV4OPEN_DELEGATENONEEXT); 2954 1.3 pgoyette if ((rflags & NFSV4OPEN_WDCONTENTION) != 0) { 2955 1.3 pgoyette NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2956 1.3 pgoyette *tl++ = txdr_unsigned(NFSV4OPEN_CONTENTION); 2957 1.3 pgoyette *tl = newnfs_false; 2958 1.3 pgoyette } else if ((rflags & NFSV4OPEN_WDRESOURCE) != 0) { 2959 1.3 pgoyette NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2960 1.3 pgoyette *tl++ = txdr_unsigned(NFSV4OPEN_RESOURCE); 2961 1.3 pgoyette *tl = newnfs_false; 2962 1.3 pgoyette } else { 2963 1.3 pgoyette NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 2964 1.3 pgoyette *tl = txdr_unsigned(NFSV4OPEN_NOTWANTED); 2965 1.3 pgoyette } 2966 1.3 pgoyette } else 2967 1.1 dholland *tl = txdr_unsigned(NFSV4OPEN_DELEGATENONE); 2968 1.1 dholland if (rflags & (NFSV4OPEN_READDELEGATE|NFSV4OPEN_WRITEDELEGATE)) { 2969 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID+NFSX_UNSIGNED); 2970 1.1 dholland *tl++ = txdr_unsigned(delegstateid.seqid); 2971 1.1 dholland NFSBCOPY((caddr_t)delegstateid.other, (caddr_t)tl, 2972 1.1 dholland NFSX_STATEIDOTHER); 2973 1.1 dholland tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 2974 1.1 dholland if (rflags & NFSV4OPEN_RECALL) 2975 1.1 dholland *tl = newnfs_true; 2976 1.1 dholland else 2977 1.1 dholland *tl = newnfs_false; 2978 1.1 dholland if (rflags & NFSV4OPEN_WRITEDELEGATE) { 2979 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2980 1.1 dholland *tl++ = txdr_unsigned(NFSV4OPEN_LIMITSIZE); 2981 1.1 dholland txdr_hyper(nva.na_size, tl); 2982 1.1 dholland } 2983 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2984 1.1 dholland *tl++ = txdr_unsigned(NFSV4ACE_ALLOWEDTYPE); 2985 1.1 dholland *tl++ = txdr_unsigned(0x0); 2986 1.1 dholland acemask = NFSV4ACE_ALLFILESMASK; 2987 1.1 dholland if (nva.na_mode & S_IRUSR) 2988 1.1 dholland acemask |= NFSV4ACE_READMASK; 2989 1.1 dholland if (nva.na_mode & S_IWUSR) 2990 1.1 dholland acemask |= NFSV4ACE_WRITEMASK; 2991 1.1 dholland if (nva.na_mode & S_IXUSR) 2992 1.1 dholland acemask |= NFSV4ACE_EXECUTEMASK; 2993 1.1 dholland *tl = txdr_unsigned(acemask); 2994 1.1 dholland (void) nfsm_strtom(nd, "OWNER@", 6); 2995 1.1 dholland } 2996 1.1 dholland *vpp = vp; 2997 1.1 dholland } else if (vp) { 2998 1.1 dholland vrele(vp); 2999 1.1 dholland } 3000 1.1 dholland if (dirp) 3001 1.1 dholland vrele(dirp); 3002 1.1 dholland #ifdef NFS4_ACL_EXTATTR_NAME 3003 1.1 dholland acl_free(aclp); 3004 1.1 dholland #endif 3005 1.1 dholland NFSEXITCODE2(0, nd); 3006 1.1 dholland return (0); 3007 1.1 dholland nfsmout: 3008 1.1 dholland vrele(dp); 3009 1.1 dholland #ifdef NFS4_ACL_EXTATTR_NAME 3010 1.1 dholland acl_free(aclp); 3011 1.1 dholland #endif 3012 1.1 dholland if (stp) 3013 1.1 dholland FREE((caddr_t)stp, M_NFSDSTATE); 3014 1.1 dholland NFSEXITCODE2(error, nd); 3015 1.1 dholland return (error); 3016 1.1 dholland } 3017 1.1 dholland 3018 1.1 dholland /* 3019 1.1 dholland * nfsv4 close service 3020 1.1 dholland */ 3021 1.1 dholland APPLESTATIC int 3022 1.1 dholland nfsrvd_close(struct nfsrv_descript *nd, __unused int isdgram, 3023 1.1 dholland vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 3024 1.1 dholland { 3025 1.1 dholland u_int32_t *tl; 3026 1.1 dholland struct nfsstate st, *stp = &st; 3027 1.1 dholland int error = 0; 3028 1.1 dholland nfsv4stateid_t stateid; 3029 1.1 dholland nfsquad_t clientid; 3030 1.1 dholland 3031 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID); 3032 1.1 dholland stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++); 3033 1.1 dholland stp->ls_ownerlen = 0; 3034 1.1 dholland stp->ls_op = nd->nd_rp; 3035 1.1 dholland stp->ls_uid = nd->nd_cred->cr_uid; 3036 1.1 dholland stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 3037 1.1 dholland NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other, 3038 1.1 dholland NFSX_STATEIDOTHER); 3039 1.1 dholland stp->ls_flags = NFSLCK_CLOSE; 3040 1.1 dholland clientid.lval[0] = stp->ls_stateid.other[0]; 3041 1.1 dholland clientid.lval[1] = stp->ls_stateid.other[1]; 3042 1.3 pgoyette if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 3043 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 3044 1.3 pgoyette clientid.qval = nd->nd_clientid.qval; 3045 1.3 pgoyette else if (nd->nd_clientid.qval != clientid.qval) 3046 1.3 pgoyette printf("EEK8 multiple clids\n"); 3047 1.1 dholland } else { 3048 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 3049 1.3 pgoyette printf("EEK! no clientid from session\n"); 3050 1.1 dholland nd->nd_flag |= ND_IMPLIEDCLID; 3051 1.1 dholland nd->nd_clientid.qval = clientid.qval; 3052 1.1 dholland } 3053 1.1 dholland nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p); 3054 1.1 dholland vput(vp); 3055 1.1 dholland if (!nd->nd_repstat) { 3056 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID); 3057 1.1 dholland *tl++ = txdr_unsigned(stateid.seqid); 3058 1.1 dholland NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER); 3059 1.1 dholland } 3060 1.1 dholland NFSEXITCODE2(0, nd); 3061 1.1 dholland return (0); 3062 1.1 dholland nfsmout: 3063 1.1 dholland vput(vp); 3064 1.1 dholland NFSEXITCODE2(error, nd); 3065 1.1 dholland return (error); 3066 1.1 dholland } 3067 1.1 dholland 3068 1.1 dholland /* 3069 1.1 dholland * nfsv4 delegpurge service 3070 1.1 dholland */ 3071 1.1 dholland APPLESTATIC int 3072 1.1 dholland nfsrvd_delegpurge(struct nfsrv_descript *nd, __unused int isdgram, 3073 1.1 dholland __unused vnode_t vp, __unused NFSPROC_T *p, __unused struct nfsexstuff *exp) 3074 1.1 dholland { 3075 1.1 dholland u_int32_t *tl; 3076 1.1 dholland int error = 0; 3077 1.1 dholland nfsquad_t clientid; 3078 1.1 dholland 3079 1.1 dholland if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { 3080 1.1 dholland nd->nd_repstat = NFSERR_WRONGSEC; 3081 1.1 dholland goto nfsmout; 3082 1.1 dholland } 3083 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3084 1.1 dholland clientid.lval[0] = *tl++; 3085 1.1 dholland clientid.lval[1] = *tl; 3086 1.3 pgoyette if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 3087 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 3088 1.3 pgoyette clientid.qval = nd->nd_clientid.qval; 3089 1.3 pgoyette else if (nd->nd_clientid.qval != clientid.qval) 3090 1.3 pgoyette printf("EEK9 multiple clids\n"); 3091 1.1 dholland } else { 3092 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 3093 1.3 pgoyette printf("EEK! no clientid from session\n"); 3094 1.1 dholland nd->nd_flag |= ND_IMPLIEDCLID; 3095 1.1 dholland nd->nd_clientid.qval = clientid.qval; 3096 1.1 dholland } 3097 1.3 pgoyette nd->nd_repstat = nfsrv_delegupdate(nd, clientid, NULL, NULL, 3098 1.1 dholland NFSV4OP_DELEGPURGE, nd->nd_cred, p); 3099 1.1 dholland nfsmout: 3100 1.1 dholland NFSEXITCODE2(error, nd); 3101 1.1 dholland return (error); 3102 1.1 dholland } 3103 1.1 dholland 3104 1.1 dholland /* 3105 1.1 dholland * nfsv4 delegreturn service 3106 1.1 dholland */ 3107 1.1 dholland APPLESTATIC int 3108 1.1 dholland nfsrvd_delegreturn(struct nfsrv_descript *nd, __unused int isdgram, 3109 1.1 dholland vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 3110 1.1 dholland { 3111 1.1 dholland u_int32_t *tl; 3112 1.1 dholland int error = 0; 3113 1.1 dholland nfsv4stateid_t stateid; 3114 1.1 dholland nfsquad_t clientid; 3115 1.1 dholland 3116 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID); 3117 1.1 dholland stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 3118 1.1 dholland NFSBCOPY((caddr_t)tl, (caddr_t)stateid.other, NFSX_STATEIDOTHER); 3119 1.1 dholland clientid.lval[0] = stateid.other[0]; 3120 1.1 dholland clientid.lval[1] = stateid.other[1]; 3121 1.3 pgoyette if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 3122 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 3123 1.3 pgoyette clientid.qval = nd->nd_clientid.qval; 3124 1.3 pgoyette else if (nd->nd_clientid.qval != clientid.qval) 3125 1.3 pgoyette printf("EEK10 multiple clids\n"); 3126 1.1 dholland } else { 3127 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 3128 1.3 pgoyette printf("EEK! no clientid from session\n"); 3129 1.1 dholland nd->nd_flag |= ND_IMPLIEDCLID; 3130 1.1 dholland nd->nd_clientid.qval = clientid.qval; 3131 1.1 dholland } 3132 1.3 pgoyette nd->nd_repstat = nfsrv_delegupdate(nd, clientid, &stateid, vp, 3133 1.1 dholland NFSV4OP_DELEGRETURN, nd->nd_cred, p); 3134 1.1 dholland nfsmout: 3135 1.1 dholland vput(vp); 3136 1.1 dholland NFSEXITCODE2(error, nd); 3137 1.1 dholland return (error); 3138 1.1 dholland } 3139 1.1 dholland 3140 1.1 dholland /* 3141 1.1 dholland * nfsv4 get file handle service 3142 1.1 dholland */ 3143 1.1 dholland APPLESTATIC int 3144 1.1 dholland nfsrvd_getfh(struct nfsrv_descript *nd, __unused int isdgram, 3145 1.1 dholland vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 3146 1.1 dholland { 3147 1.1 dholland fhandle_t fh; 3148 1.1 dholland 3149 1.1 dholland nd->nd_repstat = nfsvno_getfh(vp, &fh, p); 3150 1.1 dholland vput(vp); 3151 1.1 dholland if (!nd->nd_repstat) 3152 1.1 dholland (void) nfsm_fhtom(nd, (u_int8_t *)&fh, 0, 0); 3153 1.1 dholland NFSEXITCODE2(0, nd); 3154 1.1 dholland return (0); 3155 1.1 dholland } 3156 1.1 dholland 3157 1.1 dholland /* 3158 1.1 dholland * nfsv4 open confirm service 3159 1.1 dholland */ 3160 1.1 dholland APPLESTATIC int 3161 1.1 dholland nfsrvd_openconfirm(struct nfsrv_descript *nd, __unused int isdgram, 3162 1.1 dholland vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 3163 1.1 dholland { 3164 1.1 dholland u_int32_t *tl; 3165 1.1 dholland struct nfsstate st, *stp = &st; 3166 1.1 dholland int error = 0; 3167 1.1 dholland nfsv4stateid_t stateid; 3168 1.1 dholland nfsquad_t clientid; 3169 1.1 dholland 3170 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) { 3171 1.3 pgoyette nd->nd_repstat = NFSERR_NOTSUPP; 3172 1.3 pgoyette goto nfsmout; 3173 1.3 pgoyette } 3174 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED); 3175 1.1 dholland stp->ls_ownerlen = 0; 3176 1.1 dholland stp->ls_op = nd->nd_rp; 3177 1.1 dholland stp->ls_uid = nd->nd_cred->cr_uid; 3178 1.1 dholland stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 3179 1.1 dholland NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other, 3180 1.1 dholland NFSX_STATEIDOTHER); 3181 1.1 dholland tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 3182 1.1 dholland stp->ls_seq = fxdr_unsigned(u_int32_t, *tl); 3183 1.1 dholland stp->ls_flags = NFSLCK_CONFIRM; 3184 1.1 dholland clientid.lval[0] = stp->ls_stateid.other[0]; 3185 1.1 dholland clientid.lval[1] = stp->ls_stateid.other[1]; 3186 1.3 pgoyette if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 3187 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 3188 1.3 pgoyette clientid.qval = nd->nd_clientid.qval; 3189 1.3 pgoyette else if (nd->nd_clientid.qval != clientid.qval) 3190 1.3 pgoyette printf("EEK11 multiple clids\n"); 3191 1.1 dholland } else { 3192 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 3193 1.3 pgoyette printf("EEK! no clientid from session\n"); 3194 1.1 dholland nd->nd_flag |= ND_IMPLIEDCLID; 3195 1.1 dholland nd->nd_clientid.qval = clientid.qval; 3196 1.1 dholland } 3197 1.1 dholland nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, nd, p); 3198 1.1 dholland if (!nd->nd_repstat) { 3199 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID); 3200 1.1 dholland *tl++ = txdr_unsigned(stateid.seqid); 3201 1.1 dholland NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER); 3202 1.1 dholland } 3203 1.1 dholland nfsmout: 3204 1.1 dholland vput(vp); 3205 1.1 dholland NFSEXITCODE2(error, nd); 3206 1.1 dholland return (error); 3207 1.1 dholland } 3208 1.1 dholland 3209 1.1 dholland /* 3210 1.1 dholland * nfsv4 open downgrade service 3211 1.1 dholland */ 3212 1.1 dholland APPLESTATIC int 3213 1.1 dholland nfsrvd_opendowngrade(struct nfsrv_descript *nd, __unused int isdgram, 3214 1.1 dholland vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 3215 1.1 dholland { 3216 1.1 dholland u_int32_t *tl; 3217 1.1 dholland int i; 3218 1.1 dholland struct nfsstate st, *stp = &st; 3219 1.1 dholland int error = 0; 3220 1.1 dholland nfsv4stateid_t stateid; 3221 1.1 dholland nfsquad_t clientid; 3222 1.1 dholland 3223 1.3 pgoyette /* opendowngrade can only work on a file object.*/ 3224 1.3 pgoyette if (vp->v_type != VREG) { 3225 1.3 pgoyette error = NFSERR_INVAL; 3226 1.3 pgoyette goto nfsmout; 3227 1.3 pgoyette } 3228 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + 3 * NFSX_UNSIGNED); 3229 1.1 dholland stp->ls_ownerlen = 0; 3230 1.1 dholland stp->ls_op = nd->nd_rp; 3231 1.1 dholland stp->ls_uid = nd->nd_cred->cr_uid; 3232 1.1 dholland stp->ls_stateid.seqid = fxdr_unsigned(u_int32_t, *tl++); 3233 1.1 dholland NFSBCOPY((caddr_t)tl, (caddr_t)stp->ls_stateid.other, 3234 1.1 dholland NFSX_STATEIDOTHER); 3235 1.1 dholland tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED); 3236 1.1 dholland stp->ls_seq = fxdr_unsigned(u_int32_t, *tl++); 3237 1.1 dholland i = fxdr_unsigned(int, *tl++); 3238 1.1 dholland switch (i) { 3239 1.1 dholland case NFSV4OPEN_ACCESSREAD: 3240 1.1 dholland stp->ls_flags = (NFSLCK_READACCESS | NFSLCK_DOWNGRADE); 3241 1.1 dholland break; 3242 1.1 dholland case NFSV4OPEN_ACCESSWRITE: 3243 1.1 dholland stp->ls_flags = (NFSLCK_WRITEACCESS | NFSLCK_DOWNGRADE); 3244 1.1 dholland break; 3245 1.1 dholland case NFSV4OPEN_ACCESSBOTH: 3246 1.1 dholland stp->ls_flags = (NFSLCK_READACCESS | NFSLCK_WRITEACCESS | 3247 1.1 dholland NFSLCK_DOWNGRADE); 3248 1.1 dholland break; 3249 1.1 dholland default: 3250 1.1 dholland nd->nd_repstat = NFSERR_BADXDR; 3251 1.3 pgoyette } 3252 1.1 dholland i = fxdr_unsigned(int, *tl); 3253 1.1 dholland switch (i) { 3254 1.1 dholland case NFSV4OPEN_DENYNONE: 3255 1.1 dholland break; 3256 1.1 dholland case NFSV4OPEN_DENYREAD: 3257 1.1 dholland stp->ls_flags |= NFSLCK_READDENY; 3258 1.1 dholland break; 3259 1.1 dholland case NFSV4OPEN_DENYWRITE: 3260 1.1 dholland stp->ls_flags |= NFSLCK_WRITEDENY; 3261 1.1 dholland break; 3262 1.1 dholland case NFSV4OPEN_DENYBOTH: 3263 1.1 dholland stp->ls_flags |= (NFSLCK_READDENY | NFSLCK_WRITEDENY); 3264 1.1 dholland break; 3265 1.1 dholland default: 3266 1.1 dholland nd->nd_repstat = NFSERR_BADXDR; 3267 1.3 pgoyette } 3268 1.1 dholland 3269 1.1 dholland clientid.lval[0] = stp->ls_stateid.other[0]; 3270 1.1 dholland clientid.lval[1] = stp->ls_stateid.other[1]; 3271 1.3 pgoyette if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 3272 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 3273 1.3 pgoyette clientid.qval = nd->nd_clientid.qval; 3274 1.3 pgoyette else if (nd->nd_clientid.qval != clientid.qval) 3275 1.3 pgoyette printf("EEK12 multiple clids\n"); 3276 1.1 dholland } else { 3277 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 3278 1.3 pgoyette printf("EEK! no clientid from session\n"); 3279 1.1 dholland nd->nd_flag |= ND_IMPLIEDCLID; 3280 1.1 dholland nd->nd_clientid.qval = clientid.qval; 3281 1.1 dholland } 3282 1.1 dholland if (!nd->nd_repstat) 3283 1.1 dholland nd->nd_repstat = nfsrv_openupdate(vp, stp, clientid, &stateid, 3284 1.1 dholland nd, p); 3285 1.1 dholland if (!nd->nd_repstat) { 3286 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID); 3287 1.1 dholland *tl++ = txdr_unsigned(stateid.seqid); 3288 1.1 dholland NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER); 3289 1.1 dholland } 3290 1.1 dholland nfsmout: 3291 1.1 dholland vput(vp); 3292 1.1 dholland NFSEXITCODE2(error, nd); 3293 1.1 dholland return (error); 3294 1.1 dholland } 3295 1.1 dholland 3296 1.1 dholland /* 3297 1.1 dholland * nfsv4 renew lease service 3298 1.1 dholland */ 3299 1.1 dholland APPLESTATIC int 3300 1.1 dholland nfsrvd_renew(struct nfsrv_descript *nd, __unused int isdgram, 3301 1.1 dholland __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 3302 1.1 dholland { 3303 1.1 dholland u_int32_t *tl; 3304 1.1 dholland int error = 0; 3305 1.1 dholland nfsquad_t clientid; 3306 1.1 dholland 3307 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) { 3308 1.3 pgoyette nd->nd_repstat = NFSERR_NOTSUPP; 3309 1.3 pgoyette goto nfsmout; 3310 1.3 pgoyette } 3311 1.1 dholland if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { 3312 1.1 dholland nd->nd_repstat = NFSERR_WRONGSEC; 3313 1.1 dholland goto nfsmout; 3314 1.1 dholland } 3315 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER); 3316 1.1 dholland clientid.lval[0] = *tl++; 3317 1.1 dholland clientid.lval[1] = *tl; 3318 1.3 pgoyette if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 3319 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 3320 1.3 pgoyette clientid.qval = nd->nd_clientid.qval; 3321 1.3 pgoyette else if (nd->nd_clientid.qval != clientid.qval) 3322 1.3 pgoyette printf("EEK13 multiple clids\n"); 3323 1.1 dholland } else { 3324 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 3325 1.3 pgoyette printf("EEK! no clientid from session\n"); 3326 1.1 dholland nd->nd_flag |= ND_IMPLIEDCLID; 3327 1.1 dholland nd->nd_clientid.qval = clientid.qval; 3328 1.1 dholland } 3329 1.1 dholland nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_RENEWOP|CLOPS_RENEW), 3330 1.3 pgoyette NULL, NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p); 3331 1.1 dholland nfsmout: 3332 1.1 dholland NFSEXITCODE2(error, nd); 3333 1.1 dholland return (error); 3334 1.1 dholland } 3335 1.1 dholland 3336 1.1 dholland /* 3337 1.1 dholland * nfsv4 security info service 3338 1.1 dholland */ 3339 1.1 dholland APPLESTATIC int 3340 1.1 dholland nfsrvd_secinfo(struct nfsrv_descript *nd, int isdgram, 3341 1.1 dholland vnode_t dp, NFSPROC_T *p, struct nfsexstuff *exp) 3342 1.1 dholland { 3343 1.1 dholland u_int32_t *tl; 3344 1.1 dholland int len; 3345 1.1 dholland struct nameidata named; 3346 1.1 dholland vnode_t dirp = NULL, vp; 3347 1.1 dholland struct nfsrvfh fh; 3348 1.1 dholland struct nfsexstuff retnes; 3349 1.1 dholland u_int32_t *sizp; 3350 1.1 dholland int error = 0, savflag, i; 3351 1.1 dholland char *bufp; 3352 1.1 dholland u_long *hashp; 3353 1.1 dholland 3354 1.1 dholland /* 3355 1.1 dholland * All this just to get the export flags for the name. 3356 1.1 dholland */ 3357 1.1 dholland NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP, 3358 1.1 dholland LOCKLEAF | SAVESTART); 3359 1.1 dholland nfsvno_setpathbuf(&named, &bufp, &hashp); 3360 1.1 dholland error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); 3361 1.1 dholland if (error) { 3362 1.1 dholland vput(dp); 3363 1.1 dholland nfsvno_relpathbuf(&named); 3364 1.1 dholland goto out; 3365 1.1 dholland } 3366 1.1 dholland if (!nd->nd_repstat) { 3367 1.1 dholland nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp); 3368 1.1 dholland } else { 3369 1.1 dholland vput(dp); 3370 1.1 dholland nfsvno_relpathbuf(&named); 3371 1.1 dholland } 3372 1.1 dholland if (dirp) 3373 1.1 dholland vrele(dirp); 3374 1.1 dholland if (nd->nd_repstat) 3375 1.1 dholland goto out; 3376 1.1 dholland vrele(named.ni_startdir); 3377 1.1 dholland nfsvno_relpathbuf(&named); 3378 1.1 dholland fh.nfsrvfh_len = NFSX_MYFH; 3379 1.1 dholland vp = named.ni_vp; 3380 1.1 dholland nd->nd_repstat = nfsvno_getfh(vp, (fhandle_t *)fh.nfsrvfh_data, p); 3381 1.1 dholland vput(vp); 3382 1.1 dholland savflag = nd->nd_flag; 3383 1.1 dholland if (!nd->nd_repstat) { 3384 1.1 dholland nfsd_fhtovp(nd, &fh, LK_SHARED, &vp, &retnes, NULL, 0, p); 3385 1.1 dholland if (vp) 3386 1.1 dholland vput(vp); 3387 1.1 dholland } 3388 1.1 dholland nd->nd_flag = savflag; 3389 1.1 dholland if (nd->nd_repstat) 3390 1.1 dholland goto out; 3391 1.1 dholland 3392 1.1 dholland /* 3393 1.1 dholland * Finally have the export flags for name, so we can create 3394 1.1 dholland * the security info. 3395 1.1 dholland */ 3396 1.1 dholland len = 0; 3397 1.1 dholland NFSM_BUILD(sizp, u_int32_t *, NFSX_UNSIGNED); 3398 1.1 dholland for (i = 0; i < retnes.nes_numsecflavor; i++) { 3399 1.1 dholland if (retnes.nes_secflavors[i] == AUTH_SYS) { 3400 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 3401 1.1 dholland *tl = txdr_unsigned(RPCAUTH_UNIX); 3402 1.1 dholland len++; 3403 1.1 dholland } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5) { 3404 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 3405 1.1 dholland *tl++ = txdr_unsigned(RPCAUTH_GSS); 3406 1.1 dholland (void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str, 3407 1.1 dholland nfsgss_mechlist[KERBV_MECH].len); 3408 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3409 1.1 dholland *tl++ = txdr_unsigned(GSS_KERBV_QOP); 3410 1.1 dholland *tl = txdr_unsigned(RPCAUTHGSS_SVCNONE); 3411 1.1 dholland len++; 3412 1.1 dholland } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5I) { 3413 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 3414 1.1 dholland *tl++ = txdr_unsigned(RPCAUTH_GSS); 3415 1.1 dholland (void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str, 3416 1.1 dholland nfsgss_mechlist[KERBV_MECH].len); 3417 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3418 1.1 dholland *tl++ = txdr_unsigned(GSS_KERBV_QOP); 3419 1.1 dholland *tl = txdr_unsigned(RPCAUTHGSS_SVCINTEGRITY); 3420 1.1 dholland len++; 3421 1.1 dholland } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5P) { 3422 1.1 dholland NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); 3423 1.1 dholland *tl++ = txdr_unsigned(RPCAUTH_GSS); 3424 1.1 dholland (void) nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str, 3425 1.1 dholland nfsgss_mechlist[KERBV_MECH].len); 3426 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3427 1.1 dholland *tl++ = txdr_unsigned(GSS_KERBV_QOP); 3428 1.1 dholland *tl = txdr_unsigned(RPCAUTHGSS_SVCPRIVACY); 3429 1.1 dholland len++; 3430 1.1 dholland } 3431 1.1 dholland } 3432 1.1 dholland *sizp = txdr_unsigned(len); 3433 1.1 dholland 3434 1.1 dholland out: 3435 1.1 dholland NFSEXITCODE2(error, nd); 3436 1.1 dholland return (error); 3437 1.1 dholland } 3438 1.1 dholland 3439 1.1 dholland /* 3440 1.1 dholland * nfsv4 set client id service 3441 1.1 dholland */ 3442 1.1 dholland APPLESTATIC int 3443 1.1 dholland nfsrvd_setclientid(struct nfsrv_descript *nd, __unused int isdgram, 3444 1.1 dholland __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 3445 1.1 dholland { 3446 1.1 dholland u_int32_t *tl; 3447 1.1 dholland int i; 3448 1.1 dholland int error = 0, idlen; 3449 1.1 dholland struct nfsclient *clp = NULL; 3450 1.1 dholland struct sockaddr_in *rad; 3451 1.1 dholland u_char *verf, *ucp, *ucp2, addrbuf[24]; 3452 1.1 dholland nfsquad_t clientid, confirm; 3453 1.1 dholland 3454 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) { 3455 1.3 pgoyette nd->nd_repstat = NFSERR_NOTSUPP; 3456 1.3 pgoyette goto nfsmout; 3457 1.3 pgoyette } 3458 1.1 dholland if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { 3459 1.1 dholland nd->nd_repstat = NFSERR_WRONGSEC; 3460 1.1 dholland goto out; 3461 1.1 dholland } 3462 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED); 3463 1.1 dholland verf = (u_char *)tl; 3464 1.1 dholland tl += (NFSX_VERF / NFSX_UNSIGNED); 3465 1.1 dholland i = fxdr_unsigned(int, *tl); 3466 1.1 dholland if (i > NFSV4_OPAQUELIMIT || i <= 0) { 3467 1.1 dholland nd->nd_repstat = NFSERR_BADXDR; 3468 1.1 dholland goto nfsmout; 3469 1.1 dholland } 3470 1.1 dholland idlen = i; 3471 1.1 dholland if (nd->nd_flag & ND_GSS) 3472 1.1 dholland i += nd->nd_princlen; 3473 1.3 pgoyette clp = malloc(sizeof(struct nfsclient) + i, M_NFSDCLIENT, M_WAITOK | 3474 1.3 pgoyette M_ZERO); 3475 1.3 pgoyette clp->lc_stateid = malloc(sizeof(struct nfsstatehead) * 3476 1.3 pgoyette nfsrv_statehashsize, M_NFSDCLIENT, M_WAITOK); 3477 1.1 dholland NFSINITSOCKMUTEX(&clp->lc_req.nr_mtx); 3478 1.1 dholland NFSSOCKADDRALLOC(clp->lc_req.nr_nam); 3479 1.1 dholland NFSSOCKADDRSIZE(clp->lc_req.nr_nam, sizeof (struct sockaddr_in)); 3480 1.1 dholland clp->lc_req.nr_cred = NULL; 3481 1.1 dholland NFSBCOPY(verf, clp->lc_verf, NFSX_VERF); 3482 1.1 dholland clp->lc_idlen = idlen; 3483 1.1 dholland error = nfsrv_mtostr(nd, clp->lc_id, idlen); 3484 1.1 dholland if (error) 3485 1.1 dholland goto nfsmout; 3486 1.1 dholland if (nd->nd_flag & ND_GSS) { 3487 1.1 dholland clp->lc_flags = LCL_GSS; 3488 1.1 dholland if (nd->nd_flag & ND_GSSINTEGRITY) 3489 1.1 dholland clp->lc_flags |= LCL_GSSINTEGRITY; 3490 1.1 dholland else if (nd->nd_flag & ND_GSSPRIVACY) 3491 1.1 dholland clp->lc_flags |= LCL_GSSPRIVACY; 3492 1.1 dholland } else { 3493 1.1 dholland clp->lc_flags = 0; 3494 1.1 dholland } 3495 1.1 dholland if ((nd->nd_flag & ND_GSS) && nd->nd_princlen > 0) { 3496 1.1 dholland clp->lc_flags |= LCL_NAME; 3497 1.1 dholland clp->lc_namelen = nd->nd_princlen; 3498 1.1 dholland clp->lc_name = &clp->lc_id[idlen]; 3499 1.1 dholland NFSBCOPY(nd->nd_principal, clp->lc_name, clp->lc_namelen); 3500 1.1 dholland } else { 3501 1.1 dholland clp->lc_uid = nd->nd_cred->cr_uid; 3502 1.1 dholland clp->lc_gid = nd->nd_cred->cr_gid; 3503 1.1 dholland } 3504 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3505 1.1 dholland clp->lc_program = fxdr_unsigned(u_int32_t, *tl); 3506 1.1 dholland error = nfsrv_getclientipaddr(nd, clp); 3507 1.1 dholland if (error) 3508 1.1 dholland goto nfsmout; 3509 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3510 1.1 dholland clp->lc_callback = fxdr_unsigned(u_int32_t, *tl); 3511 1.1 dholland 3512 1.1 dholland /* 3513 1.1 dholland * nfsrv_setclient() does the actual work of adding it to the 3514 1.1 dholland * client list. If there is no error, the structure has been 3515 1.1 dholland * linked into the client list and clp should no longer be used 3516 1.1 dholland * here. When an error is returned, it has not been linked in, 3517 1.1 dholland * so it should be free'd. 3518 1.1 dholland */ 3519 1.1 dholland nd->nd_repstat = nfsrv_setclient(nd, &clp, &clientid, &confirm, p); 3520 1.1 dholland if (nd->nd_repstat == NFSERR_CLIDINUSE) { 3521 1.1 dholland if (clp->lc_flags & LCL_TCPCALLBACK) 3522 1.1 dholland (void) nfsm_strtom(nd, "tcp", 3); 3523 1.1 dholland else 3524 1.1 dholland (void) nfsm_strtom(nd, "udp", 3); 3525 1.1 dholland rad = NFSSOCKADDR(clp->lc_req.nr_nam, struct sockaddr_in *); 3526 1.1 dholland ucp = (u_char *)&rad->sin_addr.s_addr; 3527 1.1 dholland ucp2 = (u_char *)&rad->sin_port; 3528 1.2 christos snprintf(addrbuf, sizeof(addrbuf), "%d.%d.%d.%d.%d.%d", 3529 1.2 christos ucp[0] & 0xff, ucp[1] & 0xff, ucp[2] & 0xff, ucp[3] & 0xff, 3530 1.1 dholland ucp2[0] & 0xff, ucp2[1] & 0xff); 3531 1.1 dholland (void) nfsm_strtom(nd, addrbuf, strlen(addrbuf)); 3532 1.1 dholland } 3533 1.1 dholland if (clp) { 3534 1.1 dholland NFSSOCKADDRFREE(clp->lc_req.nr_nam); 3535 1.1 dholland NFSFREEMUTEX(&clp->lc_req.nr_mtx); 3536 1.3 pgoyette free(clp->lc_stateid, M_NFSDCLIENT); 3537 1.3 pgoyette free(clp, M_NFSDCLIENT); 3538 1.1 dholland } 3539 1.1 dholland if (!nd->nd_repstat) { 3540 1.1 dholland NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_HYPER); 3541 1.1 dholland *tl++ = clientid.lval[0]; 3542 1.1 dholland *tl++ = clientid.lval[1]; 3543 1.1 dholland *tl++ = confirm.lval[0]; 3544 1.1 dholland *tl = confirm.lval[1]; 3545 1.1 dholland } 3546 1.1 dholland 3547 1.1 dholland out: 3548 1.1 dholland NFSEXITCODE2(0, nd); 3549 1.1 dholland return (0); 3550 1.1 dholland nfsmout: 3551 1.1 dholland if (clp) { 3552 1.1 dholland NFSSOCKADDRFREE(clp->lc_req.nr_nam); 3553 1.1 dholland NFSFREEMUTEX(&clp->lc_req.nr_mtx); 3554 1.3 pgoyette free(clp->lc_stateid, M_NFSDCLIENT); 3555 1.3 pgoyette free(clp, M_NFSDCLIENT); 3556 1.1 dholland } 3557 1.1 dholland NFSEXITCODE2(error, nd); 3558 1.1 dholland return (error); 3559 1.1 dholland } 3560 1.1 dholland 3561 1.1 dholland /* 3562 1.1 dholland * nfsv4 set client id confirm service 3563 1.1 dholland */ 3564 1.1 dholland APPLESTATIC int 3565 1.1 dholland nfsrvd_setclientidcfrm(struct nfsrv_descript *nd, 3566 1.1 dholland __unused int isdgram, __unused vnode_t vp, NFSPROC_T *p, 3567 1.1 dholland __unused struct nfsexstuff *exp) 3568 1.1 dholland { 3569 1.1 dholland u_int32_t *tl; 3570 1.1 dholland int error = 0; 3571 1.1 dholland nfsquad_t clientid, confirm; 3572 1.1 dholland 3573 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) { 3574 1.3 pgoyette nd->nd_repstat = NFSERR_NOTSUPP; 3575 1.3 pgoyette goto nfsmout; 3576 1.3 pgoyette } 3577 1.1 dholland if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { 3578 1.1 dholland nd->nd_repstat = NFSERR_WRONGSEC; 3579 1.1 dholland goto nfsmout; 3580 1.1 dholland } 3581 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_HYPER); 3582 1.1 dholland clientid.lval[0] = *tl++; 3583 1.1 dholland clientid.lval[1] = *tl++; 3584 1.1 dholland confirm.lval[0] = *tl++; 3585 1.1 dholland confirm.lval[1] = *tl; 3586 1.1 dholland 3587 1.1 dholland /* 3588 1.1 dholland * nfsrv_getclient() searches the client list for a match and 3589 1.1 dholland * returns the appropriate NFSERR status. 3590 1.1 dholland */ 3591 1.1 dholland nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_CONFIRM|CLOPS_RENEW), 3592 1.3 pgoyette NULL, NULL, confirm, 0, nd, p); 3593 1.1 dholland nfsmout: 3594 1.1 dholland NFSEXITCODE2(error, nd); 3595 1.1 dholland return (error); 3596 1.1 dholland } 3597 1.1 dholland 3598 1.1 dholland /* 3599 1.1 dholland * nfsv4 verify service 3600 1.1 dholland */ 3601 1.1 dholland APPLESTATIC int 3602 1.1 dholland nfsrvd_verify(struct nfsrv_descript *nd, int isdgram, 3603 1.1 dholland vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 3604 1.1 dholland { 3605 1.1 dholland int error = 0, ret, fhsize = NFSX_MYFH; 3606 1.1 dholland struct nfsvattr nva; 3607 1.1 dholland struct statfs sf; 3608 1.1 dholland struct nfsfsinfo fs; 3609 1.1 dholland fhandle_t fh; 3610 1.1 dholland 3611 1.1 dholland nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); 3612 1.1 dholland if (!nd->nd_repstat) 3613 1.1 dholland nd->nd_repstat = nfsvno_statfs(vp, &sf); 3614 1.1 dholland if (!nd->nd_repstat) 3615 1.1 dholland nd->nd_repstat = nfsvno_getfh(vp, &fh, p); 3616 1.1 dholland if (!nd->nd_repstat) { 3617 1.1 dholland nfsvno_getfs(&fs, isdgram); 3618 1.1 dholland error = nfsv4_loadattr(nd, vp, &nva, NULL, &fh, fhsize, NULL, 3619 1.1 dholland &sf, NULL, &fs, NULL, 1, &ret, NULL, NULL, p, nd->nd_cred); 3620 1.1 dholland if (!error) { 3621 1.1 dholland if (nd->nd_procnum == NFSV4OP_NVERIFY) { 3622 1.1 dholland if (ret == 0) 3623 1.1 dholland nd->nd_repstat = NFSERR_SAME; 3624 1.1 dholland else if (ret != NFSERR_NOTSAME) 3625 1.1 dholland nd->nd_repstat = ret; 3626 1.1 dholland } else if (ret) 3627 1.1 dholland nd->nd_repstat = ret; 3628 1.1 dholland } 3629 1.1 dholland } 3630 1.1 dholland vput(vp); 3631 1.1 dholland NFSEXITCODE2(error, nd); 3632 1.1 dholland return (error); 3633 1.1 dholland } 3634 1.1 dholland 3635 1.1 dholland /* 3636 1.1 dholland * nfs openattr rpc 3637 1.1 dholland */ 3638 1.1 dholland APPLESTATIC int 3639 1.1 dholland nfsrvd_openattr(struct nfsrv_descript *nd, __unused int isdgram, 3640 1.1 dholland vnode_t dp, __unused vnode_t *vpp, __unused fhandle_t *fhp, 3641 1.1 dholland __unused NFSPROC_T *p, __unused struct nfsexstuff *exp) 3642 1.1 dholland { 3643 1.1 dholland u_int32_t *tl; 3644 1.1 dholland int error = 0, createdir; 3645 1.1 dholland 3646 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); 3647 1.1 dholland createdir = fxdr_unsigned(int, *tl); 3648 1.1 dholland nd->nd_repstat = NFSERR_NOTSUPP; 3649 1.1 dholland nfsmout: 3650 1.1 dholland vrele(dp); 3651 1.1 dholland NFSEXITCODE2(error, nd); 3652 1.1 dholland return (error); 3653 1.1 dholland } 3654 1.1 dholland 3655 1.1 dholland /* 3656 1.1 dholland * nfsv4 release lock owner service 3657 1.1 dholland */ 3658 1.1 dholland APPLESTATIC int 3659 1.1 dholland nfsrvd_releaselckown(struct nfsrv_descript *nd, __unused int isdgram, 3660 1.1 dholland __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 3661 1.1 dholland { 3662 1.1 dholland u_int32_t *tl; 3663 1.1 dholland struct nfsstate *stp = NULL; 3664 1.1 dholland int error = 0, len; 3665 1.1 dholland nfsquad_t clientid; 3666 1.1 dholland 3667 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) { 3668 1.3 pgoyette nd->nd_repstat = NFSERR_NOTSUPP; 3669 1.3 pgoyette goto nfsmout; 3670 1.3 pgoyette } 3671 1.1 dholland if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { 3672 1.1 dholland nd->nd_repstat = NFSERR_WRONGSEC; 3673 1.1 dholland goto nfsmout; 3674 1.1 dholland } 3675 1.1 dholland NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 3676 1.1 dholland len = fxdr_unsigned(int, *(tl + 2)); 3677 1.1 dholland if (len <= 0 || len > NFSV4_OPAQUELIMIT) { 3678 1.1 dholland nd->nd_repstat = NFSERR_BADXDR; 3679 1.1 dholland goto nfsmout; 3680 1.1 dholland } 3681 1.1 dholland MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + len, 3682 1.1 dholland M_NFSDSTATE, M_WAITOK); 3683 1.1 dholland stp->ls_ownerlen = len; 3684 1.1 dholland stp->ls_op = NULL; 3685 1.1 dholland stp->ls_flags = NFSLCK_RELEASE; 3686 1.1 dholland stp->ls_uid = nd->nd_cred->cr_uid; 3687 1.1 dholland clientid.lval[0] = *tl++; 3688 1.1 dholland clientid.lval[1] = *tl; 3689 1.3 pgoyette if ((nd->nd_flag & ND_IMPLIEDCLID) != 0) { 3690 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 3691 1.3 pgoyette clientid.qval = nd->nd_clientid.qval; 3692 1.3 pgoyette else if (nd->nd_clientid.qval != clientid.qval) 3693 1.3 pgoyette printf("EEK14 multiple clids\n"); 3694 1.1 dholland } else { 3695 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 3696 1.3 pgoyette printf("EEK! no clientid from session\n"); 3697 1.1 dholland nd->nd_flag |= ND_IMPLIEDCLID; 3698 1.1 dholland nd->nd_clientid.qval = clientid.qval; 3699 1.1 dholland } 3700 1.1 dholland error = nfsrv_mtostr(nd, stp->ls_owner, len); 3701 1.1 dholland if (error) 3702 1.1 dholland goto nfsmout; 3703 1.1 dholland nd->nd_repstat = nfsrv_releaselckown(stp, clientid, p); 3704 1.1 dholland FREE((caddr_t)stp, M_NFSDSTATE); 3705 1.1 dholland 3706 1.1 dholland NFSEXITCODE2(0, nd); 3707 1.1 dholland return (0); 3708 1.1 dholland nfsmout: 3709 1.1 dholland if (stp) 3710 1.1 dholland free((caddr_t)stp, M_NFSDSTATE); 3711 1.1 dholland NFSEXITCODE2(error, nd); 3712 1.1 dholland return (error); 3713 1.1 dholland } 3714 1.3 pgoyette 3715 1.3 pgoyette /* 3716 1.3 pgoyette * nfsv4 exchange_id service 3717 1.3 pgoyette */ 3718 1.3 pgoyette APPLESTATIC int 3719 1.3 pgoyette nfsrvd_exchangeid(struct nfsrv_descript *nd, __unused int isdgram, 3720 1.3 pgoyette __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 3721 1.3 pgoyette { 3722 1.3 pgoyette uint32_t *tl; 3723 1.3 pgoyette int error = 0, i, idlen; 3724 1.3 pgoyette struct nfsclient *clp = NULL; 3725 1.3 pgoyette nfsquad_t clientid, confirm; 3726 1.3 pgoyette uint8_t *verf; 3727 1.3 pgoyette uint32_t sp4type, v41flags; 3728 1.3 pgoyette uint64_t owner_minor; 3729 1.3 pgoyette struct timespec verstime; 3730 1.3 pgoyette 3731 1.3 pgoyette if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { 3732 1.3 pgoyette nd->nd_repstat = NFSERR_WRONGSEC; 3733 1.3 pgoyette goto nfsmout; 3734 1.3 pgoyette } 3735 1.3 pgoyette NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED); 3736 1.3 pgoyette verf = (uint8_t *)tl; 3737 1.3 pgoyette tl += (NFSX_VERF / NFSX_UNSIGNED); 3738 1.3 pgoyette i = fxdr_unsigned(int, *tl); 3739 1.3 pgoyette if (i > NFSV4_OPAQUELIMIT || i <= 0) { 3740 1.3 pgoyette nd->nd_repstat = NFSERR_BADXDR; 3741 1.3 pgoyette goto nfsmout; 3742 1.3 pgoyette } 3743 1.3 pgoyette idlen = i; 3744 1.3 pgoyette if (nd->nd_flag & ND_GSS) 3745 1.3 pgoyette i += nd->nd_princlen; 3746 1.3 pgoyette clp = malloc(sizeof(struct nfsclient) + i, M_NFSDCLIENT, M_WAITOK | 3747 1.3 pgoyette M_ZERO); 3748 1.3 pgoyette clp->lc_stateid = malloc(sizeof(struct nfsstatehead) * 3749 1.3 pgoyette nfsrv_statehashsize, M_NFSDCLIENT, M_WAITOK); 3750 1.3 pgoyette NFSINITSOCKMUTEX(&clp->lc_req.nr_mtx); 3751 1.3 pgoyette NFSSOCKADDRALLOC(clp->lc_req.nr_nam); 3752 1.3 pgoyette NFSSOCKADDRSIZE(clp->lc_req.nr_nam, sizeof (struct sockaddr_in)); 3753 1.3 pgoyette clp->lc_req.nr_cred = NULL; 3754 1.3 pgoyette NFSBCOPY(verf, clp->lc_verf, NFSX_VERF); 3755 1.3 pgoyette clp->lc_idlen = idlen; 3756 1.3 pgoyette error = nfsrv_mtostr(nd, clp->lc_id, idlen); 3757 1.3 pgoyette if (error != 0) 3758 1.3 pgoyette goto nfsmout; 3759 1.3 pgoyette if ((nd->nd_flag & ND_GSS) != 0) { 3760 1.3 pgoyette clp->lc_flags = LCL_GSS | LCL_NFSV41; 3761 1.3 pgoyette if ((nd->nd_flag & ND_GSSINTEGRITY) != 0) 3762 1.3 pgoyette clp->lc_flags |= LCL_GSSINTEGRITY; 3763 1.3 pgoyette else if ((nd->nd_flag & ND_GSSPRIVACY) != 0) 3764 1.3 pgoyette clp->lc_flags |= LCL_GSSPRIVACY; 3765 1.3 pgoyette } else 3766 1.3 pgoyette clp->lc_flags = LCL_NFSV41; 3767 1.3 pgoyette if ((nd->nd_flag & ND_GSS) != 0 && nd->nd_princlen > 0) { 3768 1.3 pgoyette clp->lc_flags |= LCL_NAME; 3769 1.3 pgoyette clp->lc_namelen = nd->nd_princlen; 3770 1.3 pgoyette clp->lc_name = &clp->lc_id[idlen]; 3771 1.3 pgoyette NFSBCOPY(nd->nd_principal, clp->lc_name, clp->lc_namelen); 3772 1.3 pgoyette } else { 3773 1.3 pgoyette clp->lc_uid = nd->nd_cred->cr_uid; 3774 1.3 pgoyette clp->lc_gid = nd->nd_cred->cr_gid; 3775 1.3 pgoyette } 3776 1.3 pgoyette NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3777 1.3 pgoyette v41flags = fxdr_unsigned(uint32_t, *tl++); 3778 1.3 pgoyette if ((v41flags & ~(NFSV4EXCH_SUPPMOVEDREFER | NFSV4EXCH_SUPPMOVEDMIGR | 3779 1.3 pgoyette NFSV4EXCH_BINDPRINCSTATEID | NFSV4EXCH_MASKPNFS | 3780 1.3 pgoyette NFSV4EXCH_UPDCONFIRMEDRECA)) != 0) { 3781 1.3 pgoyette nd->nd_repstat = NFSERR_INVAL; 3782 1.3 pgoyette goto nfsmout; 3783 1.3 pgoyette } 3784 1.3 pgoyette if ((v41flags & NFSV4EXCH_UPDCONFIRMEDRECA) != 0) 3785 1.3 pgoyette confirm.lval[1] = 1; 3786 1.3 pgoyette else 3787 1.3 pgoyette confirm.lval[1] = 0; 3788 1.3 pgoyette v41flags = NFSV4EXCH_USENONPNFS; 3789 1.3 pgoyette sp4type = fxdr_unsigned(uint32_t, *tl); 3790 1.3 pgoyette if (sp4type != NFSV4EXCH_SP4NONE) { 3791 1.3 pgoyette nd->nd_repstat = NFSERR_NOTSUPP; 3792 1.3 pgoyette goto nfsmout; 3793 1.3 pgoyette } 3794 1.3 pgoyette 3795 1.3 pgoyette /* 3796 1.3 pgoyette * nfsrv_setclient() does the actual work of adding it to the 3797 1.3 pgoyette * client list. If there is no error, the structure has been 3798 1.3 pgoyette * linked into the client list and clp should no longer be used 3799 1.3 pgoyette * here. When an error is returned, it has not been linked in, 3800 1.3 pgoyette * so it should be free'd. 3801 1.3 pgoyette */ 3802 1.3 pgoyette nd->nd_repstat = nfsrv_setclient(nd, &clp, &clientid, &confirm, p); 3803 1.3 pgoyette if (clp != NULL) { 3804 1.3 pgoyette NFSSOCKADDRFREE(clp->lc_req.nr_nam); 3805 1.3 pgoyette NFSFREEMUTEX(&clp->lc_req.nr_mtx); 3806 1.3 pgoyette free(clp->lc_stateid, M_NFSDCLIENT); 3807 1.3 pgoyette free(clp, M_NFSDCLIENT); 3808 1.3 pgoyette } 3809 1.3 pgoyette if (nd->nd_repstat == 0) { 3810 1.3 pgoyette if (confirm.lval[1] != 0) 3811 1.3 pgoyette v41flags |= NFSV4EXCH_CONFIRMEDR; 3812 1.3 pgoyette NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + 3 * NFSX_UNSIGNED); 3813 1.3 pgoyette *tl++ = clientid.lval[0]; /* ClientID */ 3814 1.3 pgoyette *tl++ = clientid.lval[1]; 3815 1.3 pgoyette *tl++ = txdr_unsigned(confirm.lval[0]); /* SequenceID */ 3816 1.3 pgoyette *tl++ = txdr_unsigned(v41flags); /* Exch flags */ 3817 1.3 pgoyette *tl++ = txdr_unsigned(NFSV4EXCH_SP4NONE); /* No SSV */ 3818 1.3 pgoyette owner_minor = 0; /* Owner */ 3819 1.3 pgoyette txdr_hyper(owner_minor, tl); /* Minor */ 3820 1.3 pgoyette (void)nfsm_strtom(nd, nd->nd_cred->cr_prison->pr_hostuuid, 3821 1.3 pgoyette strlen(nd->nd_cred->cr_prison->pr_hostuuid)); /* Major */ 3822 1.3 pgoyette NFSM_BUILD(tl, uint32_t *, 3 * NFSX_UNSIGNED); 3823 1.3 pgoyette *tl++ = txdr_unsigned(NFSX_UNSIGNED); 3824 1.3 pgoyette *tl++ = time_uptime; /* Make scope a unique value. */ 3825 1.3 pgoyette *tl = txdr_unsigned(1); 3826 1.3 pgoyette (void)nfsm_strtom(nd, "freebsd.org", strlen("freebsd.org")); 3827 1.3 pgoyette (void)nfsm_strtom(nd, version, strlen(version)); 3828 1.3 pgoyette NFSM_BUILD(tl, uint32_t *, NFSX_V4TIME); 3829 1.3 pgoyette verstime.tv_sec = 1293840000; /* Jan 1, 2011 */ 3830 1.3 pgoyette verstime.tv_nsec = 0; 3831 1.3 pgoyette txdr_nfsv4time(&verstime, tl); 3832 1.3 pgoyette } 3833 1.3 pgoyette NFSEXITCODE2(0, nd); 3834 1.3 pgoyette return (0); 3835 1.3 pgoyette nfsmout: 3836 1.3 pgoyette if (clp != NULL) { 3837 1.3 pgoyette NFSSOCKADDRFREE(clp->lc_req.nr_nam); 3838 1.3 pgoyette NFSFREEMUTEX(&clp->lc_req.nr_mtx); 3839 1.3 pgoyette free(clp->lc_stateid, M_NFSDCLIENT); 3840 1.3 pgoyette free(clp, M_NFSDCLIENT); 3841 1.3 pgoyette } 3842 1.3 pgoyette NFSEXITCODE2(error, nd); 3843 1.3 pgoyette return (error); 3844 1.3 pgoyette } 3845 1.3 pgoyette 3846 1.3 pgoyette /* 3847 1.3 pgoyette * nfsv4 create session service 3848 1.3 pgoyette */ 3849 1.3 pgoyette APPLESTATIC int 3850 1.3 pgoyette nfsrvd_createsession(struct nfsrv_descript *nd, __unused int isdgram, 3851 1.3 pgoyette __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 3852 1.3 pgoyette { 3853 1.3 pgoyette uint32_t *tl; 3854 1.3 pgoyette int error = 0; 3855 1.3 pgoyette nfsquad_t clientid, confirm; 3856 1.3 pgoyette struct nfsdsession *sep = NULL; 3857 1.3 pgoyette uint32_t rdmacnt; 3858 1.3 pgoyette 3859 1.3 pgoyette if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { 3860 1.3 pgoyette nd->nd_repstat = NFSERR_WRONGSEC; 3861 1.3 pgoyette goto nfsmout; 3862 1.3 pgoyette } 3863 1.3 pgoyette sep = (struct nfsdsession *)malloc(sizeof(struct nfsdsession), 3864 1.3 pgoyette M_NFSDSESSION, M_WAITOK | M_ZERO); 3865 1.3 pgoyette sep->sess_refcnt = 1; 3866 1.3 pgoyette mtx_init(&sep->sess_cbsess.nfsess_mtx, "nfscbsession", NULL, MTX_DEF); 3867 1.3 pgoyette NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + 2 * NFSX_UNSIGNED); 3868 1.3 pgoyette clientid.lval[0] = *tl++; 3869 1.3 pgoyette clientid.lval[1] = *tl++; 3870 1.3 pgoyette confirm.lval[0] = fxdr_unsigned(uint32_t, *tl++); 3871 1.3 pgoyette sep->sess_crflags = fxdr_unsigned(uint32_t, *tl); 3872 1.3 pgoyette /* Persistent sessions and RDMA are not supported. */ 3873 1.3 pgoyette sep->sess_crflags &= NFSV4CRSESS_CONNBACKCHAN; 3874 1.3 pgoyette 3875 1.3 pgoyette /* Fore channel attributes. */ 3876 1.3 pgoyette NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED); 3877 1.3 pgoyette tl++; /* Header pad always 0. */ 3878 1.3 pgoyette sep->sess_maxreq = fxdr_unsigned(uint32_t, *tl++); 3879 1.3 pgoyette sep->sess_maxresp = fxdr_unsigned(uint32_t, *tl++); 3880 1.3 pgoyette sep->sess_maxrespcached = fxdr_unsigned(uint32_t, *tl++); 3881 1.3 pgoyette sep->sess_maxops = fxdr_unsigned(uint32_t, *tl++); 3882 1.3 pgoyette sep->sess_maxslots = fxdr_unsigned(uint32_t, *tl++); 3883 1.3 pgoyette if (sep->sess_maxslots > NFSV4_SLOTS) 3884 1.3 pgoyette sep->sess_maxslots = NFSV4_SLOTS; 3885 1.3 pgoyette rdmacnt = fxdr_unsigned(uint32_t, *tl); 3886 1.3 pgoyette if (rdmacnt > 1) { 3887 1.3 pgoyette nd->nd_repstat = NFSERR_BADXDR; 3888 1.3 pgoyette goto nfsmout; 3889 1.3 pgoyette } else if (rdmacnt == 1) 3890 1.3 pgoyette NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 3891 1.3 pgoyette 3892 1.3 pgoyette /* Back channel attributes. */ 3893 1.3 pgoyette NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED); 3894 1.3 pgoyette tl++; /* Header pad always 0. */ 3895 1.3 pgoyette sep->sess_cbmaxreq = fxdr_unsigned(uint32_t, *tl++); 3896 1.3 pgoyette sep->sess_cbmaxresp = fxdr_unsigned(uint32_t, *tl++); 3897 1.3 pgoyette sep->sess_cbmaxrespcached = fxdr_unsigned(uint32_t, *tl++); 3898 1.3 pgoyette sep->sess_cbmaxops = fxdr_unsigned(uint32_t, *tl++); 3899 1.3 pgoyette sep->sess_cbsess.nfsess_foreslots = fxdr_unsigned(uint32_t, *tl++); 3900 1.3 pgoyette rdmacnt = fxdr_unsigned(uint32_t, *tl); 3901 1.3 pgoyette if (rdmacnt > 1) { 3902 1.3 pgoyette nd->nd_repstat = NFSERR_BADXDR; 3903 1.3 pgoyette goto nfsmout; 3904 1.3 pgoyette } else if (rdmacnt == 1) 3905 1.3 pgoyette NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 3906 1.3 pgoyette 3907 1.3 pgoyette NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 3908 1.3 pgoyette sep->sess_cbprogram = fxdr_unsigned(uint32_t, *tl); 3909 1.3 pgoyette 3910 1.3 pgoyette /* 3911 1.3 pgoyette * nfsrv_getclient() searches the client list for a match and 3912 1.3 pgoyette * returns the appropriate NFSERR status. 3913 1.3 pgoyette */ 3914 1.3 pgoyette nd->nd_repstat = nfsrv_getclient(clientid, CLOPS_CONFIRM | CLOPS_RENEW, 3915 1.3 pgoyette NULL, sep, confirm, sep->sess_cbprogram, nd, p); 3916 1.3 pgoyette if (nd->nd_repstat == 0) { 3917 1.3 pgoyette NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID); 3918 1.3 pgoyette NFSBCOPY(sep->sess_sessionid, tl, NFSX_V4SESSIONID); 3919 1.3 pgoyette NFSM_BUILD(tl, uint32_t *, 18 * NFSX_UNSIGNED); 3920 1.3 pgoyette *tl++ = txdr_unsigned(confirm.lval[0]); /* sequenceid */ 3921 1.3 pgoyette *tl++ = txdr_unsigned(sep->sess_crflags); 3922 1.3 pgoyette 3923 1.3 pgoyette /* Fore channel attributes. */ 3924 1.3 pgoyette *tl++ = 0; 3925 1.3 pgoyette *tl++ = txdr_unsigned(sep->sess_maxreq); 3926 1.3 pgoyette *tl++ = txdr_unsigned(sep->sess_maxresp); 3927 1.3 pgoyette *tl++ = txdr_unsigned(sep->sess_maxrespcached); 3928 1.3 pgoyette *tl++ = txdr_unsigned(sep->sess_maxops); 3929 1.3 pgoyette *tl++ = txdr_unsigned(sep->sess_maxslots); 3930 1.3 pgoyette *tl++ = txdr_unsigned(1); 3931 1.3 pgoyette *tl++ = txdr_unsigned(0); /* No RDMA. */ 3932 1.3 pgoyette 3933 1.3 pgoyette /* Back channel attributes. */ 3934 1.3 pgoyette *tl++ = 0; 3935 1.3 pgoyette *tl++ = txdr_unsigned(sep->sess_cbmaxreq); 3936 1.3 pgoyette *tl++ = txdr_unsigned(sep->sess_cbmaxresp); 3937 1.3 pgoyette *tl++ = txdr_unsigned(sep->sess_cbmaxrespcached); 3938 1.3 pgoyette *tl++ = txdr_unsigned(sep->sess_cbmaxops); 3939 1.3 pgoyette *tl++ = txdr_unsigned(sep->sess_cbsess.nfsess_foreslots); 3940 1.3 pgoyette *tl++ = txdr_unsigned(1); 3941 1.3 pgoyette *tl = txdr_unsigned(0); /* No RDMA. */ 3942 1.3 pgoyette } 3943 1.3 pgoyette nfsmout: 3944 1.3 pgoyette if (nd->nd_repstat != 0 && sep != NULL) 3945 1.3 pgoyette free(sep, M_NFSDSESSION); 3946 1.3 pgoyette NFSEXITCODE2(error, nd); 3947 1.3 pgoyette return (error); 3948 1.3 pgoyette } 3949 1.3 pgoyette 3950 1.3 pgoyette /* 3951 1.3 pgoyette * nfsv4 sequence service 3952 1.3 pgoyette */ 3953 1.3 pgoyette APPLESTATIC int 3954 1.3 pgoyette nfsrvd_sequence(struct nfsrv_descript *nd, __unused int isdgram, 3955 1.3 pgoyette __unused vnode_t vp, __unused NFSPROC_T *p, __unused struct nfsexstuff *exp) 3956 1.3 pgoyette { 3957 1.3 pgoyette uint32_t *tl; 3958 1.3 pgoyette uint32_t highest_slotid, sequenceid, sflags, target_highest_slotid; 3959 1.3 pgoyette int cache_this, error = 0; 3960 1.3 pgoyette 3961 1.3 pgoyette if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { 3962 1.3 pgoyette nd->nd_repstat = NFSERR_WRONGSEC; 3963 1.3 pgoyette goto nfsmout; 3964 1.3 pgoyette } 3965 1.3 pgoyette NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID); 3966 1.3 pgoyette NFSBCOPY(tl, nd->nd_sessionid, NFSX_V4SESSIONID); 3967 1.3 pgoyette NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED); 3968 1.3 pgoyette sequenceid = fxdr_unsigned(uint32_t, *tl++); 3969 1.3 pgoyette nd->nd_slotid = fxdr_unsigned(uint32_t, *tl++); 3970 1.3 pgoyette highest_slotid = fxdr_unsigned(uint32_t, *tl++); 3971 1.3 pgoyette if (*tl == newnfs_true) 3972 1.3 pgoyette cache_this = 1; 3973 1.3 pgoyette else 3974 1.3 pgoyette cache_this = 0; 3975 1.3 pgoyette nd->nd_flag |= ND_HASSEQUENCE; 3976 1.3 pgoyette nd->nd_repstat = nfsrv_checksequence(nd, sequenceid, &highest_slotid, 3977 1.3 pgoyette &target_highest_slotid, cache_this, &sflags, p); 3978 1.3 pgoyette if (nd->nd_repstat == 0) { 3979 1.3 pgoyette NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID); 3980 1.3 pgoyette NFSBCOPY(nd->nd_sessionid, tl, NFSX_V4SESSIONID); 3981 1.3 pgoyette NFSM_BUILD(tl, uint32_t *, 5 * NFSX_UNSIGNED); 3982 1.3 pgoyette *tl++ = txdr_unsigned(sequenceid); 3983 1.3 pgoyette *tl++ = txdr_unsigned(nd->nd_slotid); 3984 1.3 pgoyette *tl++ = txdr_unsigned(highest_slotid); 3985 1.3 pgoyette *tl++ = txdr_unsigned(target_highest_slotid); 3986 1.3 pgoyette *tl = txdr_unsigned(sflags); 3987 1.3 pgoyette } 3988 1.3 pgoyette nfsmout: 3989 1.3 pgoyette NFSEXITCODE2(error, nd); 3990 1.3 pgoyette return (error); 3991 1.3 pgoyette } 3992 1.3 pgoyette 3993 1.3 pgoyette /* 3994 1.3 pgoyette * nfsv4 reclaim complete service 3995 1.3 pgoyette */ 3996 1.3 pgoyette APPLESTATIC int 3997 1.3 pgoyette nfsrvd_reclaimcomplete(struct nfsrv_descript *nd, __unused int isdgram, 3998 1.3 pgoyette __unused vnode_t vp, __unused NFSPROC_T *p, __unused struct nfsexstuff *exp) 3999 1.3 pgoyette { 4000 1.3 pgoyette uint32_t *tl; 4001 1.3 pgoyette int error = 0; 4002 1.3 pgoyette 4003 1.3 pgoyette if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { 4004 1.3 pgoyette nd->nd_repstat = NFSERR_WRONGSEC; 4005 1.3 pgoyette goto nfsmout; 4006 1.3 pgoyette } 4007 1.3 pgoyette NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); 4008 1.3 pgoyette if (*tl == newnfs_true) 4009 1.3 pgoyette nd->nd_repstat = NFSERR_NOTSUPP; 4010 1.3 pgoyette else 4011 1.3 pgoyette nd->nd_repstat = nfsrv_checkreclaimcomplete(nd); 4012 1.3 pgoyette nfsmout: 4013 1.3 pgoyette NFSEXITCODE2(error, nd); 4014 1.3 pgoyette return (error); 4015 1.3 pgoyette } 4016 1.3 pgoyette 4017 1.3 pgoyette /* 4018 1.3 pgoyette * nfsv4 destroy clientid service 4019 1.3 pgoyette */ 4020 1.3 pgoyette APPLESTATIC int 4021 1.3 pgoyette nfsrvd_destroyclientid(struct nfsrv_descript *nd, __unused int isdgram, 4022 1.3 pgoyette __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 4023 1.3 pgoyette { 4024 1.3 pgoyette uint32_t *tl; 4025 1.3 pgoyette nfsquad_t clientid; 4026 1.3 pgoyette int error = 0; 4027 1.3 pgoyette 4028 1.3 pgoyette if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { 4029 1.3 pgoyette nd->nd_repstat = NFSERR_WRONGSEC; 4030 1.3 pgoyette goto nfsmout; 4031 1.3 pgoyette } 4032 1.3 pgoyette NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); 4033 1.3 pgoyette clientid.lval[0] = *tl++; 4034 1.3 pgoyette clientid.lval[1] = *tl; 4035 1.3 pgoyette nd->nd_repstat = nfsrv_destroyclient(clientid, p); 4036 1.3 pgoyette nfsmout: 4037 1.3 pgoyette NFSEXITCODE2(error, nd); 4038 1.3 pgoyette return (error); 4039 1.3 pgoyette } 4040 1.3 pgoyette 4041 1.3 pgoyette /* 4042 1.3 pgoyette * nfsv4 destroy session service 4043 1.3 pgoyette */ 4044 1.3 pgoyette APPLESTATIC int 4045 1.3 pgoyette nfsrvd_destroysession(struct nfsrv_descript *nd, __unused int isdgram, 4046 1.3 pgoyette __unused vnode_t vp, __unused NFSPROC_T *p, __unused struct nfsexstuff *exp) 4047 1.3 pgoyette { 4048 1.3 pgoyette uint8_t *cp, sessid[NFSX_V4SESSIONID]; 4049 1.3 pgoyette int error = 0; 4050 1.3 pgoyette 4051 1.3 pgoyette if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { 4052 1.3 pgoyette nd->nd_repstat = NFSERR_WRONGSEC; 4053 1.3 pgoyette goto nfsmout; 4054 1.3 pgoyette } 4055 1.3 pgoyette NFSM_DISSECT(cp, uint8_t *, NFSX_V4SESSIONID); 4056 1.3 pgoyette NFSBCOPY(cp, sessid, NFSX_V4SESSIONID); 4057 1.3 pgoyette nd->nd_repstat = nfsrv_destroysession(nd, sessid); 4058 1.3 pgoyette nfsmout: 4059 1.3 pgoyette NFSEXITCODE2(error, nd); 4060 1.3 pgoyette return (error); 4061 1.3 pgoyette } 4062 1.3 pgoyette 4063 1.3 pgoyette /* 4064 1.3 pgoyette * nfsv4 free stateid service 4065 1.3 pgoyette */ 4066 1.3 pgoyette APPLESTATIC int 4067 1.3 pgoyette nfsrvd_freestateid(struct nfsrv_descript *nd, __unused int isdgram, 4068 1.3 pgoyette __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) 4069 1.3 pgoyette { 4070 1.3 pgoyette uint32_t *tl; 4071 1.3 pgoyette nfsv4stateid_t stateid; 4072 1.3 pgoyette int error = 0; 4073 1.3 pgoyette 4074 1.3 pgoyette if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { 4075 1.3 pgoyette nd->nd_repstat = NFSERR_WRONGSEC; 4076 1.3 pgoyette goto nfsmout; 4077 1.3 pgoyette } 4078 1.3 pgoyette NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID); 4079 1.3 pgoyette stateid.seqid = fxdr_unsigned(uint32_t, *tl++); 4080 1.3 pgoyette NFSBCOPY(tl, stateid.other, NFSX_STATEIDOTHER); 4081 1.3 pgoyette nd->nd_repstat = nfsrv_freestateid(nd, &stateid, p); 4082 1.3 pgoyette nfsmout: 4083 1.3 pgoyette NFSEXITCODE2(error, nd); 4084 1.3 pgoyette return (error); 4085 1.3 pgoyette } 4086 1.3 pgoyette 4087 1.3 pgoyette /* 4088 1.3 pgoyette * nfsv4 service not supported 4089 1.3 pgoyette */ 4090 1.3 pgoyette APPLESTATIC int 4091 1.3 pgoyette nfsrvd_notsupp(struct nfsrv_descript *nd, __unused int isdgram, 4092 1.3 pgoyette __unused vnode_t vp, __unused NFSPROC_T *p, __unused struct nfsexstuff *exp) 4093 1.3 pgoyette { 4094 1.3 pgoyette 4095 1.3 pgoyette nd->nd_repstat = NFSERR_NOTSUPP; 4096 1.3 pgoyette NFSEXITCODE2(0, nd); 4097 1.3 pgoyette return (0); 4098 1.3 pgoyette } 4099 1.3 pgoyette 4100