1 1.5 rin /* $NetBSD: nfs_nfsdkrpc.c,v 1.5 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_nfsdkrpc.c 299203 2016-05-06 23:40:37Z pfg "); */ 37 1.5 rin __RCSID("$NetBSD: nfs_nfsdkrpc.c,v 1.5 2024/07/05 04:31:52 rin Exp $"); 38 1.1 dholland 39 1.4 pgoyette #ifdef _KERNEL_OPT 40 1.1 dholland #include "opt_inet6.h" 41 1.4 pgoyette #if 0 42 1.1 dholland #include "opt_kgssapi.h" 43 1.4 pgoyette #endif 44 1.4 pgoyette #endif 45 1.1 dholland 46 1.4 pgoyette #include <fs/nfs/common/nfsport.h> 47 1.1 dholland 48 1.1 dholland #include <rpc/rpc.h> 49 1.1 dholland #include <rpc/rpcsec_gss.h> 50 1.1 dholland 51 1.4 pgoyette #include <fs/nfs/common/nfs_fha.h> 52 1.4 pgoyette #include <fs/nfs/server/nfs_fha_new.h> 53 1.1 dholland 54 1.4 pgoyette #if 0 55 1.1 dholland #include <security/mac/mac_framework.h> 56 1.4 pgoyette #endif 57 1.1 dholland 58 1.1 dholland NFSDLOCKMUTEX; 59 1.1 dholland NFSV4ROOTLOCKMUTEX; 60 1.1 dholland struct nfsv4lock nfsd_suspend_lock; 61 1.1 dholland 62 1.1 dholland /* 63 1.1 dholland * Mapping of old NFS Version 2 RPC numbers to generic numbers. 64 1.1 dholland */ 65 1.1 dholland int newnfs_nfsv3_procid[NFS_V3NPROCS] = { 66 1.1 dholland NFSPROC_NULL, 67 1.1 dholland NFSPROC_GETATTR, 68 1.1 dholland NFSPROC_SETATTR, 69 1.1 dholland NFSPROC_NOOP, 70 1.1 dholland NFSPROC_LOOKUP, 71 1.1 dholland NFSPROC_READLINK, 72 1.1 dholland NFSPROC_READ, 73 1.1 dholland NFSPROC_NOOP, 74 1.1 dholland NFSPROC_WRITE, 75 1.1 dholland NFSPROC_CREATE, 76 1.1 dholland NFSPROC_REMOVE, 77 1.1 dholland NFSPROC_RENAME, 78 1.1 dholland NFSPROC_LINK, 79 1.1 dholland NFSPROC_SYMLINK, 80 1.1 dholland NFSPROC_MKDIR, 81 1.1 dholland NFSPROC_RMDIR, 82 1.1 dholland NFSPROC_READDIR, 83 1.1 dholland NFSPROC_FSSTAT, 84 1.1 dholland NFSPROC_NOOP, 85 1.1 dholland NFSPROC_NOOP, 86 1.1 dholland NFSPROC_NOOP, 87 1.1 dholland NFSPROC_NOOP, 88 1.1 dholland }; 89 1.1 dholland 90 1.1 dholland 91 1.1 dholland SYSCTL_DECL(_vfs_nfsd); 92 1.1 dholland 93 1.1 dholland SVCPOOL *nfsrvd_pool; 94 1.1 dholland 95 1.1 dholland static int nfs_privport = 0; 96 1.3 pgoyette SYSCTL_INT(_vfs_nfsd, OID_AUTO, nfs_privport, CTLFLAG_RWTUN, 97 1.1 dholland &nfs_privport, 0, 98 1.1 dholland "Only allow clients using a privileged port for NFSv2 and 3"); 99 1.1 dholland 100 1.1 dholland static int nfs_minvers = NFS_VER2; 101 1.3 pgoyette SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_min_nfsvers, CTLFLAG_RWTUN, 102 1.1 dholland &nfs_minvers, 0, "The lowest version of NFS handled by the server"); 103 1.1 dholland 104 1.1 dholland static int nfs_maxvers = NFS_VER4; 105 1.3 pgoyette SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_max_nfsvers, CTLFLAG_RWTUN, 106 1.1 dholland &nfs_maxvers, 0, "The highest version of NFS handled by the server"); 107 1.1 dholland 108 1.3 pgoyette static int nfs_proc(struct nfsrv_descript *, u_int32_t, SVCXPRT *xprt, 109 1.3 pgoyette struct nfsrvcache **); 110 1.1 dholland 111 1.1 dholland extern u_long sb_max_adj; 112 1.1 dholland extern int newnfs_numnfsd; 113 1.1 dholland extern struct proc *nfsd_master_proc; 114 1.1 dholland 115 1.1 dholland /* 116 1.1 dholland * NFS server system calls 117 1.1 dholland */ 118 1.1 dholland 119 1.1 dholland static void 120 1.1 dholland nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt) 121 1.1 dholland { 122 1.1 dholland struct nfsrv_descript nd; 123 1.1 dholland struct nfsrvcache *rp = NULL; 124 1.1 dholland int cacherep, credflavor; 125 1.1 dholland 126 1.1 dholland memset(&nd, 0, sizeof(nd)); 127 1.1 dholland if (rqst->rq_vers == NFS_VER2) { 128 1.3 pgoyette if (rqst->rq_proc > NFSV2PROC_STATFS || 129 1.3 pgoyette newnfs_nfsv3_procid[rqst->rq_proc] == NFSPROC_NOOP) { 130 1.1 dholland svcerr_noproc(rqst); 131 1.1 dholland svc_freereq(rqst); 132 1.1 dholland goto out; 133 1.1 dholland } 134 1.1 dholland nd.nd_procnum = newnfs_nfsv3_procid[rqst->rq_proc]; 135 1.1 dholland nd.nd_flag = ND_NFSV2; 136 1.1 dholland } else if (rqst->rq_vers == NFS_VER3) { 137 1.1 dholland if (rqst->rq_proc >= NFS_V3NPROCS) { 138 1.1 dholland svcerr_noproc(rqst); 139 1.1 dholland svc_freereq(rqst); 140 1.1 dholland goto out; 141 1.1 dholland } 142 1.1 dholland nd.nd_procnum = rqst->rq_proc; 143 1.1 dholland nd.nd_flag = ND_NFSV3; 144 1.1 dholland } else { 145 1.1 dholland if (rqst->rq_proc != NFSPROC_NULL && 146 1.1 dholland rqst->rq_proc != NFSV4PROC_COMPOUND) { 147 1.1 dholland svcerr_noproc(rqst); 148 1.1 dholland svc_freereq(rqst); 149 1.1 dholland goto out; 150 1.1 dholland } 151 1.1 dholland nd.nd_procnum = rqst->rq_proc; 152 1.1 dholland nd.nd_flag = ND_NFSV4; 153 1.1 dholland } 154 1.1 dholland 155 1.1 dholland /* 156 1.1 dholland * Note: we want rq_addr, not svc_getrpccaller for nd_nam2 - 157 1.1 dholland * NFS_SRVMAXDATA uses a NULL value for nd_nam2 to detect TCP 158 1.1 dholland * mounts. 159 1.1 dholland */ 160 1.1 dholland nd.nd_mrep = rqst->rq_args; 161 1.1 dholland rqst->rq_args = NULL; 162 1.1 dholland newnfs_realign(&nd.nd_mrep, M_WAITOK); 163 1.1 dholland nd.nd_md = nd.nd_mrep; 164 1.1 dholland nd.nd_dpos = mtod(nd.nd_md, caddr_t); 165 1.1 dholland nd.nd_nam = svc_getrpccaller(rqst); 166 1.1 dholland nd.nd_nam2 = rqst->rq_addr; 167 1.1 dholland nd.nd_mreq = NULL; 168 1.1 dholland nd.nd_cred = NULL; 169 1.1 dholland 170 1.1 dholland if (nfs_privport && (nd.nd_flag & ND_NFSV4) == 0) { 171 1.1 dholland /* Check if source port is privileged */ 172 1.1 dholland u_short port; 173 1.1 dholland struct sockaddr *nam = nd.nd_nam; 174 1.1 dholland struct sockaddr_in *sin; 175 1.1 dholland 176 1.1 dholland sin = (struct sockaddr_in *)nam; 177 1.1 dholland /* 178 1.1 dholland * INET/INET6 - same code: 179 1.1 dholland * sin_port and sin6_port are at same offset 180 1.1 dholland */ 181 1.1 dholland port = ntohs(sin->sin_port); 182 1.1 dholland if (port >= IPPORT_RESERVED && 183 1.1 dholland nd.nd_procnum != NFSPROC_NULL) { 184 1.1 dholland #ifdef INET6 185 1.1 dholland char b6[INET6_ADDRSTRLEN]; 186 1.4 pgoyette #if defined(_MODULE) 187 1.1 dholland /* Do not use ip6_sprintf: the nfs module should work without INET6. */ 188 1.1 dholland #define ip6_sprintf(buf, a) \ 189 1.2 christos (snprintf((buf), sizeof(buf), "%x:%x:%x:%x:%x:%x:%x:%x", \ 190 1.1 dholland (a)->s6_addr16[0], (a)->s6_addr16[1], \ 191 1.1 dholland (a)->s6_addr16[2], (a)->s6_addr16[3], \ 192 1.1 dholland (a)->s6_addr16[4], (a)->s6_addr16[5], \ 193 1.1 dholland (a)->s6_addr16[6], (a)->s6_addr16[7]), \ 194 1.1 dholland (buf)) 195 1.1 dholland #endif 196 1.1 dholland #endif 197 1.1 dholland printf("NFS request from unprivileged port (%s:%d)\n", 198 1.1 dholland #ifdef INET6 199 1.1 dholland sin->sin_family == AF_INET6 ? 200 1.1 dholland ip6_sprintf(b6, &satosin6(sin)->sin6_addr) : 201 1.4 pgoyette #if defined(_MODULE) 202 1.1 dholland #undef ip6_sprintf 203 1.1 dholland #endif 204 1.1 dholland #endif 205 1.1 dholland inet_ntoa(sin->sin_addr), port); 206 1.1 dholland svcerr_weakauth(rqst); 207 1.1 dholland svc_freereq(rqst); 208 1.1 dholland m_freem(nd.nd_mrep); 209 1.1 dholland goto out; 210 1.1 dholland } 211 1.1 dholland } 212 1.1 dholland 213 1.1 dholland if (nd.nd_procnum != NFSPROC_NULL) { 214 1.1 dholland if (!svc_getcred(rqst, &nd.nd_cred, &credflavor)) { 215 1.1 dholland svcerr_weakauth(rqst); 216 1.1 dholland svc_freereq(rqst); 217 1.1 dholland m_freem(nd.nd_mrep); 218 1.1 dholland goto out; 219 1.1 dholland } 220 1.1 dholland 221 1.1 dholland /* Set the flag based on credflavor */ 222 1.1 dholland if (credflavor == RPCSEC_GSS_KRB5) { 223 1.1 dholland nd.nd_flag |= ND_GSS; 224 1.1 dholland } else if (credflavor == RPCSEC_GSS_KRB5I) { 225 1.1 dholland nd.nd_flag |= (ND_GSS | ND_GSSINTEGRITY); 226 1.1 dholland } else if (credflavor == RPCSEC_GSS_KRB5P) { 227 1.1 dholland nd.nd_flag |= (ND_GSS | ND_GSSPRIVACY); 228 1.1 dholland } else if (credflavor != AUTH_SYS) { 229 1.1 dholland svcerr_weakauth(rqst); 230 1.1 dholland svc_freereq(rqst); 231 1.1 dholland m_freem(nd.nd_mrep); 232 1.1 dholland goto out; 233 1.1 dholland } 234 1.1 dholland 235 1.1 dholland #ifdef MAC 236 1.1 dholland mac_cred_associate_nfsd(nd.nd_cred); 237 1.1 dholland #endif 238 1.1 dholland /* 239 1.1 dholland * Get a refcnt (shared lock) on nfsd_suspend_lock. 240 1.1 dholland * NFSSVC_SUSPENDNFSD will take an exclusive lock on 241 1.1 dholland * nfsd_suspend_lock to suspend these threads. 242 1.3 pgoyette * The call to nfsv4_lock() that precedes nfsv4_getref() 243 1.3 pgoyette * ensures that the acquisition of the exclusive lock 244 1.3 pgoyette * takes priority over acquisition of the shared lock by 245 1.3 pgoyette * waiting for any exclusive lock request to complete. 246 1.1 dholland * This must be done here, before the check of 247 1.1 dholland * nfsv4root exports by nfsvno_v4rootexport(). 248 1.1 dholland */ 249 1.1 dholland NFSLOCKV4ROOTMUTEX(); 250 1.3 pgoyette nfsv4_lock(&nfsd_suspend_lock, 0, NULL, NFSV4ROOTLOCKMUTEXPTR, 251 1.3 pgoyette NULL); 252 1.1 dholland nfsv4_getref(&nfsd_suspend_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, 253 1.1 dholland NULL); 254 1.1 dholland NFSUNLOCKV4ROOTMUTEX(); 255 1.1 dholland 256 1.1 dholland if ((nd.nd_flag & ND_NFSV4) != 0) { 257 1.1 dholland nd.nd_repstat = nfsvno_v4rootexport(&nd); 258 1.1 dholland if (nd.nd_repstat != 0) { 259 1.1 dholland NFSLOCKV4ROOTMUTEX(); 260 1.1 dholland nfsv4_relref(&nfsd_suspend_lock); 261 1.1 dholland NFSUNLOCKV4ROOTMUTEX(); 262 1.1 dholland svcerr_weakauth(rqst); 263 1.1 dholland svc_freereq(rqst); 264 1.1 dholland m_freem(nd.nd_mrep); 265 1.1 dholland goto out; 266 1.1 dholland } 267 1.1 dholland } 268 1.1 dholland 269 1.3 pgoyette cacherep = nfs_proc(&nd, rqst->rq_xid, xprt, &rp); 270 1.1 dholland NFSLOCKV4ROOTMUTEX(); 271 1.1 dholland nfsv4_relref(&nfsd_suspend_lock); 272 1.1 dholland NFSUNLOCKV4ROOTMUTEX(); 273 1.1 dholland } else { 274 1.1 dholland NFSMGET(nd.nd_mreq); 275 1.1 dholland nd.nd_mreq->m_len = 0; 276 1.1 dholland cacherep = RC_REPLY; 277 1.1 dholland } 278 1.5 rin m_freem(nd.nd_mrep); 279 1.1 dholland 280 1.1 dholland if (nd.nd_cred != NULL) 281 1.1 dholland crfree(nd.nd_cred); 282 1.1 dholland 283 1.1 dholland if (cacherep == RC_DROPIT) { 284 1.5 rin m_freem(nd.nd_mreq); 285 1.1 dholland svc_freereq(rqst); 286 1.1 dholland goto out; 287 1.1 dholland } 288 1.1 dholland 289 1.1 dholland if (nd.nd_mreq == NULL) { 290 1.1 dholland svcerr_decode(rqst); 291 1.1 dholland svc_freereq(rqst); 292 1.1 dholland goto out; 293 1.1 dholland } 294 1.1 dholland 295 1.1 dholland if (nd.nd_repstat & NFSERR_AUTHERR) { 296 1.1 dholland svcerr_auth(rqst, nd.nd_repstat & ~NFSERR_AUTHERR); 297 1.5 rin m_freem(nd.nd_mreq); 298 1.1 dholland } else if (!svc_sendreply_mbuf(rqst, nd.nd_mreq)) { 299 1.1 dholland svcerr_systemerr(rqst); 300 1.1 dholland } 301 1.3 pgoyette if (rp != NULL) { 302 1.3 pgoyette nfsrvd_sentcache(rp, (rqst->rq_reply_seq != 0 || 303 1.3 pgoyette SVC_ACK(xprt, NULL)), rqst->rq_reply_seq); 304 1.3 pgoyette } 305 1.1 dholland svc_freereq(rqst); 306 1.1 dholland 307 1.1 dholland out: 308 1.3 pgoyette if (softdep_ast_cleanup != NULL) 309 1.3 pgoyette softdep_ast_cleanup(); 310 1.1 dholland NFSEXITCODE(0); 311 1.1 dholland } 312 1.1 dholland 313 1.1 dholland /* 314 1.1 dholland * Check the cache and, optionally, do the RPC. 315 1.1 dholland * Return the appropriate cache response. 316 1.1 dholland */ 317 1.1 dholland static int 318 1.3 pgoyette nfs_proc(struct nfsrv_descript *nd, u_int32_t xid, SVCXPRT *xprt, 319 1.3 pgoyette struct nfsrvcache **rpp) 320 1.1 dholland { 321 1.1 dholland struct thread *td = curthread; 322 1.3 pgoyette int cacherep = RC_DOIT, isdgram, taglen = -1; 323 1.3 pgoyette struct mbuf *m; 324 1.3 pgoyette u_char tag[NFSV4_SMALLSTR + 1], *tagstr = NULL; 325 1.3 pgoyette u_int32_t minorvers = 0; 326 1.3 pgoyette uint32_t ack; 327 1.1 dholland 328 1.1 dholland *rpp = NULL; 329 1.1 dholland if (nd->nd_nam2 == NULL) { 330 1.1 dholland nd->nd_flag |= ND_STREAMSOCK; 331 1.1 dholland isdgram = 0; 332 1.1 dholland } else { 333 1.1 dholland isdgram = 1; 334 1.1 dholland } 335 1.1 dholland 336 1.1 dholland /* 337 1.1 dholland * Two cases: 338 1.1 dholland * 1 - For NFSv2 over UDP, if we are near our malloc/mget 339 1.1 dholland * limit, just drop the request. There is no 340 1.1 dholland * NFSERR_RESOURCE or NFSERR_DELAY for NFSv2 and the 341 1.1 dholland * client will timeout/retry over UDP in a little while. 342 1.1 dholland * 2 - nd_repstat == 0 && nd_mreq == NULL, which 343 1.1 dholland * means a normal nfs rpc, so check the cache 344 1.1 dholland */ 345 1.1 dholland if ((nd->nd_flag & ND_NFSV2) && nd->nd_nam2 != NULL && 346 1.1 dholland nfsrv_mallocmget_limit()) { 347 1.1 dholland cacherep = RC_DROPIT; 348 1.1 dholland } else { 349 1.1 dholland /* 350 1.1 dholland * For NFSv3, play it safe and assume that the client is 351 1.1 dholland * doing retries on the same TCP connection. 352 1.1 dholland */ 353 1.1 dholland if ((nd->nd_flag & (ND_NFSV4 | ND_STREAMSOCK)) == 354 1.1 dholland ND_STREAMSOCK) 355 1.1 dholland nd->nd_flag |= ND_SAMETCPCONN; 356 1.1 dholland nd->nd_retxid = xid; 357 1.1 dholland nd->nd_tcpconntime = NFSD_MONOSEC; 358 1.3 pgoyette nd->nd_sockref = xprt->xp_sockref; 359 1.3 pgoyette if ((nd->nd_flag & ND_NFSV4) != 0) 360 1.3 pgoyette nfsd_getminorvers(nd, tag, &tagstr, &taglen, 361 1.3 pgoyette &minorvers); 362 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 363 1.3 pgoyette /* NFSv4.1 caches replies in the session slots. */ 364 1.3 pgoyette cacherep = RC_DOIT; 365 1.3 pgoyette else { 366 1.3 pgoyette cacherep = nfsrvd_getcache(nd); 367 1.3 pgoyette ack = 0; 368 1.3 pgoyette SVC_ACK(xprt, &ack); 369 1.3 pgoyette nfsrc_trimcache(xprt->xp_sockref, ack, 0); 370 1.3 pgoyette } 371 1.1 dholland } 372 1.1 dholland 373 1.1 dholland /* 374 1.1 dholland * Handle the request. There are three cases. 375 1.1 dholland * RC_DOIT - do the RPC 376 1.1 dholland * RC_REPLY - return the reply already created 377 1.1 dholland * RC_DROPIT - just throw the request away 378 1.1 dholland */ 379 1.1 dholland if (cacherep == RC_DOIT) { 380 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) 381 1.3 pgoyette nd->nd_xprt = xprt; 382 1.3 pgoyette nfsrvd_dorpc(nd, isdgram, tagstr, taglen, minorvers, td); 383 1.3 pgoyette if ((nd->nd_flag & ND_NFSV41) != 0) { 384 1.3 pgoyette if (nd->nd_repstat != NFSERR_REPLYFROMCACHE && 385 1.3 pgoyette (nd->nd_flag & ND_SAVEREPLY) != 0) { 386 1.3 pgoyette /* Cache a copy of the reply. */ 387 1.3 pgoyette m = m_copym(nd->nd_mreq, 0, M_COPYALL, 388 1.3 pgoyette M_WAITOK); 389 1.3 pgoyette } else 390 1.3 pgoyette m = NULL; 391 1.3 pgoyette if ((nd->nd_flag & ND_HASSEQUENCE) != 0) 392 1.3 pgoyette nfsrv_cache_session(nd->nd_sessionid, 393 1.3 pgoyette nd->nd_slotid, nd->nd_repstat, &m); 394 1.3 pgoyette if (nd->nd_repstat == NFSERR_REPLYFROMCACHE) 395 1.3 pgoyette nd->nd_repstat = 0; 396 1.1 dholland cacherep = RC_REPLY; 397 1.3 pgoyette } else { 398 1.3 pgoyette if (nd->nd_repstat == NFSERR_DONTREPLY) 399 1.3 pgoyette cacherep = RC_DROPIT; 400 1.3 pgoyette else 401 1.3 pgoyette cacherep = RC_REPLY; 402 1.3 pgoyette *rpp = nfsrvd_updatecache(nd); 403 1.3 pgoyette } 404 1.1 dholland } 405 1.3 pgoyette if (tagstr != NULL && taglen > NFSV4_SMALLSTR) 406 1.3 pgoyette free(tagstr, M_TEMP); 407 1.1 dholland 408 1.1 dholland NFSEXITCODE2(0, nd); 409 1.1 dholland return (cacherep); 410 1.1 dholland } 411 1.1 dholland 412 1.3 pgoyette static void 413 1.3 pgoyette nfssvc_loss(SVCXPRT *xprt) 414 1.3 pgoyette { 415 1.3 pgoyette uint32_t ack; 416 1.3 pgoyette 417 1.3 pgoyette ack = 0; 418 1.3 pgoyette SVC_ACK(xprt, &ack); 419 1.3 pgoyette nfsrc_trimcache(xprt->xp_sockref, ack, 1); 420 1.3 pgoyette } 421 1.3 pgoyette 422 1.1 dholland /* 423 1.1 dholland * Adds a socket to the list for servicing by nfsds. 424 1.1 dholland */ 425 1.1 dholland int 426 1.1 dholland nfsrvd_addsock(struct file *fp) 427 1.1 dholland { 428 1.1 dholland int siz; 429 1.1 dholland struct socket *so; 430 1.1 dholland int error = 0; 431 1.1 dholland SVCXPRT *xprt; 432 1.1 dholland static u_int64_t sockref = 0; 433 1.1 dholland 434 1.1 dholland so = fp->f_data; 435 1.1 dholland 436 1.1 dholland siz = sb_max_adj; 437 1.1 dholland error = soreserve(so, siz, siz); 438 1.1 dholland if (error) 439 1.1 dholland goto out; 440 1.1 dholland 441 1.1 dholland /* 442 1.1 dholland * Steal the socket from userland so that it doesn't close 443 1.1 dholland * unexpectedly. 444 1.1 dholland */ 445 1.1 dholland if (so->so_type == SOCK_DGRAM) 446 1.1 dholland xprt = svc_dg_create(nfsrvd_pool, so, 0, 0); 447 1.1 dholland else 448 1.1 dholland xprt = svc_vc_create(nfsrvd_pool, so, 0, 0); 449 1.1 dholland if (xprt) { 450 1.1 dholland fp->f_ops = &badfileops; 451 1.1 dholland fp->f_data = NULL; 452 1.1 dholland xprt->xp_sockref = ++sockref; 453 1.1 dholland if (nfs_minvers == NFS_VER2) 454 1.1 dholland svc_reg(xprt, NFS_PROG, NFS_VER2, nfssvc_program, 455 1.1 dholland NULL); 456 1.1 dholland if (nfs_minvers <= NFS_VER3 && nfs_maxvers >= NFS_VER3) 457 1.1 dholland svc_reg(xprt, NFS_PROG, NFS_VER3, nfssvc_program, 458 1.1 dholland NULL); 459 1.1 dholland if (nfs_maxvers >= NFS_VER4) 460 1.1 dholland svc_reg(xprt, NFS_PROG, NFS_VER4, nfssvc_program, 461 1.1 dholland NULL); 462 1.3 pgoyette if (so->so_type == SOCK_STREAM) 463 1.3 pgoyette svc_loss_reg(xprt, nfssvc_loss); 464 1.1 dholland SVC_RELEASE(xprt); 465 1.1 dholland } 466 1.1 dholland 467 1.1 dholland out: 468 1.1 dholland NFSEXITCODE(error); 469 1.1 dholland return (error); 470 1.1 dholland } 471 1.1 dholland 472 1.1 dholland /* 473 1.1 dholland * Called by nfssvc() for nfsds. Just loops around servicing rpc requests 474 1.1 dholland * until it is killed by a signal. 475 1.1 dholland */ 476 1.1 dholland int 477 1.1 dholland nfsrvd_nfsd(struct thread *td, struct nfsd_nfsd_args *args) 478 1.1 dholland { 479 1.1 dholland char principal[MAXHOSTNAMELEN + 5]; 480 1.3 pgoyette struct proc *p; 481 1.1 dholland int error = 0; 482 1.1 dholland bool_t ret2, ret3, ret4; 483 1.1 dholland 484 1.1 dholland error = copyinstr(args->principal, principal, sizeof (principal), 485 1.1 dholland NULL); 486 1.1 dholland if (error) 487 1.1 dholland goto out; 488 1.1 dholland 489 1.1 dholland /* 490 1.1 dholland * Only the first nfsd actually does any work. The RPC code 491 1.1 dholland * adds threads to it as needed. Any extra processes offered 492 1.1 dholland * by nfsd just exit. If nfsd is new enough, it will call us 493 1.1 dholland * once with a structure that specifies how many threads to 494 1.1 dholland * use. 495 1.1 dholland */ 496 1.1 dholland NFSD_LOCK(); 497 1.1 dholland if (newnfs_numnfsd == 0) { 498 1.3 pgoyette p = td->td_proc; 499 1.3 pgoyette PROC_LOCK(p); 500 1.3 pgoyette p->p_flag2 |= P2_AST_SU; 501 1.3 pgoyette PROC_UNLOCK(p); 502 1.1 dholland newnfs_numnfsd++; 503 1.1 dholland 504 1.1 dholland NFSD_UNLOCK(); 505 1.1 dholland 506 1.1 dholland /* An empty string implies AUTH_SYS only. */ 507 1.1 dholland if (principal[0] != '\0') { 508 1.1 dholland ret2 = rpc_gss_set_svc_name_call(principal, 509 1.1 dholland "kerberosv5", GSS_C_INDEFINITE, NFS_PROG, NFS_VER2); 510 1.1 dholland ret3 = rpc_gss_set_svc_name_call(principal, 511 1.1 dholland "kerberosv5", GSS_C_INDEFINITE, NFS_PROG, NFS_VER3); 512 1.1 dholland ret4 = rpc_gss_set_svc_name_call(principal, 513 1.1 dholland "kerberosv5", GSS_C_INDEFINITE, NFS_PROG, NFS_VER4); 514 1.1 dholland 515 1.1 dholland if (!ret2 || !ret3 || !ret4) 516 1.1 dholland printf("nfsd: can't register svc name\n"); 517 1.1 dholland } 518 1.1 dholland 519 1.1 dholland nfsrvd_pool->sp_minthreads = args->minthreads; 520 1.1 dholland nfsrvd_pool->sp_maxthreads = args->maxthreads; 521 1.1 dholland 522 1.1 dholland svc_run(nfsrvd_pool); 523 1.1 dholland 524 1.1 dholland if (principal[0] != '\0') { 525 1.1 dholland rpc_gss_clear_svc_name_call(NFS_PROG, NFS_VER2); 526 1.1 dholland rpc_gss_clear_svc_name_call(NFS_PROG, NFS_VER3); 527 1.1 dholland rpc_gss_clear_svc_name_call(NFS_PROG, NFS_VER4); 528 1.1 dholland } 529 1.1 dholland 530 1.1 dholland NFSD_LOCK(); 531 1.1 dholland newnfs_numnfsd--; 532 1.1 dholland nfsrvd_init(1); 533 1.3 pgoyette PROC_LOCK(p); 534 1.3 pgoyette p->p_flag2 &= ~P2_AST_SU; 535 1.3 pgoyette PROC_UNLOCK(p); 536 1.1 dholland } 537 1.1 dholland NFSD_UNLOCK(); 538 1.1 dholland 539 1.1 dholland out: 540 1.1 dholland NFSEXITCODE(error); 541 1.1 dholland return (error); 542 1.1 dholland } 543 1.1 dholland 544 1.1 dholland /* 545 1.1 dholland * Initialize the data structures for the server. 546 1.1 dholland * Handshake with any new nfsds starting up to avoid any chance of 547 1.1 dholland * corruption. 548 1.1 dholland */ 549 1.1 dholland void 550 1.1 dholland nfsrvd_init(int terminating) 551 1.1 dholland { 552 1.1 dholland 553 1.1 dholland NFSD_LOCK_ASSERT(); 554 1.1 dholland 555 1.1 dholland if (terminating) { 556 1.1 dholland nfsd_master_proc = NULL; 557 1.1 dholland NFSD_UNLOCK(); 558 1.3 pgoyette nfsrv_freeallbackchannel_xprts(); 559 1.1 dholland svcpool_destroy(nfsrvd_pool); 560 1.1 dholland nfsrvd_pool = NULL; 561 1.1 dholland NFSD_LOCK(); 562 1.1 dholland } 563 1.1 dholland 564 1.1 dholland NFSD_UNLOCK(); 565 1.1 dholland 566 1.1 dholland nfsrvd_pool = svcpool_create("nfsd", SYSCTL_STATIC_CHILDREN(_vfs_nfsd)); 567 1.1 dholland nfsrvd_pool->sp_rcache = NULL; 568 1.1 dholland nfsrvd_pool->sp_assign = fhanew_assign; 569 1.1 dholland nfsrvd_pool->sp_done = fha_nd_complete; 570 1.1 dholland 571 1.1 dholland NFSD_LOCK(); 572 1.1 dholland } 573 1.1 dholland 574