xref: /netbsd-src/sys/nfs/nfs_srvsocket.c (revision 481d3881954fd794ca5f2d880b68c53a5db8620e)
1 /*	$NetBSD: nfs_srvsocket.c,v 1.6 2024/07/05 04:31:54 rin Exp $	*/
2 
3 /*
4  * Copyright (c) 1989, 1991, 1993, 1995
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Rick Macklem at The University of Guelph.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *	@(#)nfs_socket.c	8.5 (Berkeley) 3/30/95
35  */
36 
37 /*
38  * Socket operations for use by nfs
39  */
40 
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: nfs_srvsocket.c,v 1.6 2024/07/05 04:31:54 rin Exp $");
43 
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/evcnt.h>
47 #include <sys/callout.h>
48 #include <sys/proc.h>
49 #include <sys/mount.h>
50 #include <sys/kernel.h>
51 #include <sys/kmem.h>
52 #include <sys/mbuf.h>
53 #include <sys/vnode.h>
54 #include <sys/domain.h>
55 #include <sys/protosw.h>
56 #include <sys/socket.h>
57 #include <sys/socketvar.h>
58 #include <sys/syslog.h>
59 #include <sys/tprintf.h>
60 #include <sys/namei.h>
61 #include <sys/signal.h>
62 #include <sys/signalvar.h>
63 #include <sys/kauth.h>
64 
65 #include <netinet/in.h>
66 #include <netinet/tcp.h>
67 
68 #include <nfs/rpcv2.h>
69 #include <nfs/nfsproto.h>
70 #include <nfs/nfs.h>
71 #include <nfs/xdr_subs.h>
72 #include <nfs/nfsm_subs.h>
73 #include <nfs/nfsmount.h>
74 #include <nfs/nfsnode.h>
75 #include <nfs/nfsrtt.h>
76 #include <nfs/nfs_var.h>
77 
78 static void nfsrv_wakenfsd_locked(struct nfssvc_sock *);
79 
80 int (*nfsrv3_procs[NFS_NPROCS])(struct nfsrv_descript *,
81 				    struct nfssvc_sock *, struct lwp *,
82 				    struct mbuf **) = {
83 	nfsrv_null,
84 	nfsrv_getattr,
85 	nfsrv_setattr,
86 	nfsrv_lookup,
87 	nfsrv3_access,
88 	nfsrv_readlink,
89 	nfsrv_read,
90 	nfsrv_write,
91 	nfsrv_create,
92 	nfsrv_mkdir,
93 	nfsrv_symlink,
94 	nfsrv_mknod,
95 	nfsrv_remove,
96 	nfsrv_rmdir,
97 	nfsrv_rename,
98 	nfsrv_link,
99 	nfsrv_readdir,
100 	nfsrv_readdirplus,
101 	nfsrv_statfs,
102 	nfsrv_fsinfo,
103 	nfsrv_pathconf,
104 	nfsrv_commit,
105 	nfsrv_noop
106 };
107 
108 /*
109  * Socket upcall routine for the nfsd sockets.
110  * The void *arg is a pointer to the "struct nfssvc_sock".
111  */
112 void
nfsrv_soupcall(struct socket * so,void * arg,int events,int waitflag)113 nfsrv_soupcall(struct socket *so, void *arg, int events, int waitflag)
114 {
115 	struct nfssvc_sock *slp = (struct nfssvc_sock *)arg;
116 
117 	nfsdsock_setbits(slp, SLP_A_NEEDQ);
118 	nfsrv_wakenfsd(slp);
119 }
120 
121 void
nfsrv_rcv(struct nfssvc_sock * slp)122 nfsrv_rcv(struct nfssvc_sock *slp)
123 {
124 	struct socket *so;
125 	struct mbuf *m;
126 	struct mbuf *mp, *nam;
127 	struct uio auio;
128 	int flags;
129 	int error;
130 	int setflags = 0;
131 
132 	error = nfsdsock_lock(slp, true);
133 	if (error) {
134 		setflags |= SLP_A_NEEDQ;
135 		goto dorecs_unlocked;
136 	}
137 
138 	nfsdsock_clearbits(slp, SLP_A_NEEDQ);
139 
140 	so = slp->ns_so;
141 	if (so->so_type == SOCK_STREAM) {
142 		/*
143 		 * Do soreceive().
144 		 */
145 		auio.uio_resid = 1000000000;
146 		/* not need to setup uio_vmspace */
147 		flags = MSG_DONTWAIT;
148 		error = (*so->so_receive)(so, &nam, &auio, &mp, NULL, &flags);
149 		if (error || mp == NULL) {
150 			if (error == EWOULDBLOCK)
151 				setflags |= SLP_A_NEEDQ;
152 			else
153 				setflags |= SLP_A_DISCONN;
154 			goto dorecs;
155 		}
156 		m = mp;
157 		m_claimm(m, &nfs_mowner);
158 		if (slp->ns_rawend) {
159 			slp->ns_rawend->m_next = m;
160 			slp->ns_cc += 1000000000 - auio.uio_resid;
161 		} else {
162 			slp->ns_raw = m;
163 			slp->ns_cc = 1000000000 - auio.uio_resid;
164 		}
165 		while (m->m_next)
166 			m = m->m_next;
167 		slp->ns_rawend = m;
168 
169 		/*
170 		 * Now try and parse record(s) out of the raw stream data.
171 		 */
172 		error = nfsrv_getstream(slp, M_WAIT);
173 		if (error) {
174 			if (error == EPERM)
175 				setflags |= SLP_A_DISCONN;
176 			else
177 				setflags |= SLP_A_NEEDQ;
178 		}
179 	} else {
180 		do {
181 			auio.uio_resid = 1000000000;
182 			/* not need to setup uio_vmspace */
183 			flags = MSG_DONTWAIT;
184 			error = (*so->so_receive)(so, &nam, &auio, &mp, NULL,
185 			    &flags);
186 			if (mp) {
187 				if (nam) {
188 					m = nam;
189 					m->m_next = mp;
190 				} else
191 					m = mp;
192 				m_claimm(m, &nfs_mowner);
193 				if (slp->ns_recend)
194 					slp->ns_recend->m_nextpkt = m;
195 				else
196 					slp->ns_rec = m;
197 				slp->ns_recend = m;
198 				m->m_nextpkt = (struct mbuf *)0;
199 			}
200 			if (error) {
201 				if ((so->so_proto->pr_flags & PR_CONNREQUIRED)
202 				    && error != EWOULDBLOCK) {
203 					setflags |= SLP_A_DISCONN;
204 					goto dorecs;
205 				}
206 			}
207 		} while (mp);
208 	}
209 dorecs:
210 	nfsdsock_unlock(slp);
211 
212 dorecs_unlocked:
213 	if (setflags) {
214 		nfsdsock_setbits(slp, setflags);
215 	}
216 }
217 
218 int
nfsdsock_lock(struct nfssvc_sock * slp,bool waitok)219 nfsdsock_lock(struct nfssvc_sock *slp, bool waitok)
220 {
221 
222 	mutex_enter(&slp->ns_lock);
223 	while ((~slp->ns_flags & (SLP_BUSY|SLP_VALID)) == 0) {
224 		if (!waitok) {
225 			mutex_exit(&slp->ns_lock);
226 			return EWOULDBLOCK;
227 		}
228 		cv_wait(&slp->ns_cv, &slp->ns_lock);
229 	}
230 	if ((slp->ns_flags & SLP_VALID) == 0) {
231 		mutex_exit(&slp->ns_lock);
232 		return EINVAL;
233 	}
234 	KASSERT((slp->ns_flags & SLP_BUSY) == 0);
235 	slp->ns_flags |= SLP_BUSY;
236 	mutex_exit(&slp->ns_lock);
237 
238 	return 0;
239 }
240 
241 void
nfsdsock_unlock(struct nfssvc_sock * slp)242 nfsdsock_unlock(struct nfssvc_sock *slp)
243 {
244 
245 	mutex_enter(&slp->ns_lock);
246 	KASSERT((slp->ns_flags & SLP_BUSY) != 0);
247 	cv_broadcast(&slp->ns_cv);
248 	slp->ns_flags &= ~SLP_BUSY;
249 	mutex_exit(&slp->ns_lock);
250 }
251 
252 int
nfsdsock_drain(struct nfssvc_sock * slp)253 nfsdsock_drain(struct nfssvc_sock *slp)
254 {
255 	int error = 0;
256 
257 	mutex_enter(&slp->ns_lock);
258 	if ((slp->ns_flags & SLP_VALID) == 0) {
259 		error = EINVAL;
260 		goto done;
261 	}
262 	slp->ns_flags &= ~SLP_VALID;
263 	while ((slp->ns_flags & SLP_BUSY) != 0) {
264 		cv_wait(&slp->ns_cv, &slp->ns_lock);
265 	}
266 done:
267 	mutex_exit(&slp->ns_lock);
268 
269 	return error;
270 }
271 
272 /*
273  * Try and extract an RPC request from the mbuf data list received on a
274  * stream socket. The "waitflag" argument indicates whether or not it
275  * can sleep.
276  */
277 int
nfsrv_getstream(struct nfssvc_sock * slp,int waitflag)278 nfsrv_getstream(struct nfssvc_sock *slp, int waitflag)
279 {
280 	struct mbuf *m, **mpp;
281 	struct mbuf *recm;
282 	u_int32_t recmark;
283 	int error = 0;
284 
285 	KASSERT((slp->ns_flags & SLP_BUSY) != 0);
286 	for (;;) {
287 		if (slp->ns_reclen == 0) {
288 			if (slp->ns_cc < NFSX_UNSIGNED) {
289 				break;
290 			}
291 			m = slp->ns_raw;
292 			m_copydata(m, 0, NFSX_UNSIGNED, (void *)&recmark);
293 			m_adj(m, NFSX_UNSIGNED);
294 			slp->ns_cc -= NFSX_UNSIGNED;
295 			recmark = ntohl(recmark);
296 			slp->ns_reclen = recmark & ~0x80000000;
297 			if (recmark & 0x80000000)
298 				slp->ns_sflags |= SLP_S_LASTFRAG;
299 			else
300 				slp->ns_sflags &= ~SLP_S_LASTFRAG;
301 			if (slp->ns_reclen > NFS_MAXPACKET) {
302 				error = EPERM;
303 				break;
304 			}
305 		}
306 
307 		/*
308 		 * Now get the record part.
309 		 *
310 		 * Note that slp->ns_reclen may be 0.  Linux sometimes
311 		 * generates 0-length records.
312 		 */
313 		if (slp->ns_cc == slp->ns_reclen) {
314 			recm = slp->ns_raw;
315 			slp->ns_raw = slp->ns_rawend = (struct mbuf *)0;
316 			slp->ns_cc = slp->ns_reclen = 0;
317 		} else if (slp->ns_cc > slp->ns_reclen) {
318 			recm = slp->ns_raw;
319 			m = m_split(recm, slp->ns_reclen, waitflag);
320 			if (m == NULL) {
321 				error = EWOULDBLOCK;
322 				break;
323 			}
324 			m_claimm(recm, &nfs_mowner);
325 			slp->ns_raw = m;
326 			while (m->m_next)
327 				m = m->m_next;
328 			slp->ns_rawend = m;
329 			slp->ns_cc -= slp->ns_reclen;
330 			slp->ns_reclen = 0;
331 		} else {
332 			break;
333 		}
334 
335 		/*
336 		 * Accumulate the fragments into a record.
337 		 */
338 		mpp = &slp->ns_frag;
339 		while (*mpp)
340 			mpp = &((*mpp)->m_next);
341 		*mpp = recm;
342 		if (slp->ns_sflags & SLP_S_LASTFRAG) {
343 			if (slp->ns_recend)
344 				slp->ns_recend->m_nextpkt = slp->ns_frag;
345 			else
346 				slp->ns_rec = slp->ns_frag;
347 			slp->ns_recend = slp->ns_frag;
348 			slp->ns_frag = NULL;
349 		}
350 	}
351 
352 	return error;
353 }
354 
355 /*
356  * Parse an RPC header.
357  */
358 int
nfsrv_dorec(struct nfssvc_sock * slp,struct nfsd * nfsd,struct nfsrv_descript ** ndp,bool * more)359 nfsrv_dorec(struct nfssvc_sock *slp, struct nfsd *nfsd,
360     struct nfsrv_descript **ndp, bool *more)
361 {
362 	struct mbuf *m, *nam;
363 	struct nfsrv_descript *nd;
364 	int error;
365 
366 	*ndp = NULL;
367 	*more = false;
368 
369 	if (nfsdsock_lock(slp, true)) {
370 		return ENOBUFS;
371 	}
372 	m = slp->ns_rec;
373 	if (m == NULL) {
374 		nfsdsock_unlock(slp);
375 		return ENOBUFS;
376 	}
377 	slp->ns_rec = m->m_nextpkt;
378 	if (slp->ns_rec) {
379 		m->m_nextpkt = NULL;
380 		*more = true;
381 	} else {
382 		slp->ns_recend = NULL;
383 	}
384 	nfsdsock_unlock(slp);
385 
386 	if (m->m_type == MT_SONAME) {
387 		nam = m;
388 		m = m->m_next;
389 		nam->m_next = NULL;
390 	} else
391 		nam = NULL;
392 	nd = nfsdreq_alloc();
393 	nd->nd_md = nd->nd_mrep = m;
394 	nd->nd_nam2 = nam;
395 	nd->nd_dpos = mtod(m, void *);
396 	error = nfs_getreq(nd, nfsd, true);
397 	if (error) {
398 		m_freem(nam);
399 		nfsdreq_free(nd);
400 		return (error);
401 	}
402 	*ndp = nd;
403 	nfsd->nfsd_nd = nd;
404 	return (0);
405 }
406 
407 bool
nfsrv_timer(void)408 nfsrv_timer(void)
409 {
410 	struct timeval tv;
411 	struct nfssvc_sock *slp;
412 	u_quad_t cur_usec;
413 	struct nfsrv_descript *nd;
414 	bool more;
415 
416 	/*
417 	 * Scan the write gathering queues for writes that need to be
418 	 * completed now.
419 	 */
420 	getmicrotime(&tv);
421 	cur_usec = (u_quad_t)tv.tv_sec * 1000000 + (u_quad_t)tv.tv_usec;
422 	more = false;
423 	mutex_enter(&nfsd_lock);
424 	TAILQ_FOREACH(slp, &nfssvc_sockhead, ns_chain) {
425 		nd = LIST_FIRST(&slp->ns_tq);
426 		if (nd != NULL) {
427 			if (nd->nd_time <= cur_usec) {
428 				nfsrv_wakenfsd_locked(slp);
429 			}
430 			more = true;
431 		}
432 	}
433 	mutex_exit(&nfsd_lock);
434 	return more;
435 }
436 
437 /*
438  * Search for a sleeping nfsd and wake it up.
439  * SIDE EFFECT: If none found, set NFSD_CHECKSLP flag, so that one of the
440  * running nfsds will go look for the work in the nfssvc_sock list.
441  */
442 static void
nfsrv_wakenfsd_locked(struct nfssvc_sock * slp)443 nfsrv_wakenfsd_locked(struct nfssvc_sock *slp)
444 {
445 	struct nfsd *nd;
446 
447 	KASSERT(mutex_owned(&nfsd_lock));
448 
449 	if ((slp->ns_flags & SLP_VALID) == 0)
450 		return;
451 	if (slp->ns_gflags & SLP_G_DOREC)
452 		return;
453 	nd = SLIST_FIRST(&nfsd_idle_head);
454 	if (nd) {
455 		SLIST_REMOVE_HEAD(&nfsd_idle_head, nfsd_idle);
456 		if (nd->nfsd_slp)
457 			panic("nfsd wakeup");
458 		slp->ns_sref++;
459 		KASSERT(slp->ns_sref > 0);
460 		nd->nfsd_slp = slp;
461 		cv_signal(&nd->nfsd_cv);
462 	} else {
463 		slp->ns_gflags |= SLP_G_DOREC;
464 		nfsd_head_flag |= NFSD_CHECKSLP;
465 		TAILQ_INSERT_TAIL(&nfssvc_sockpending, slp, ns_pending);
466 	}
467 }
468 
469 void
nfsrv_wakenfsd(struct nfssvc_sock * slp)470 nfsrv_wakenfsd(struct nfssvc_sock *slp)
471 {
472 
473 	mutex_enter(&nfsd_lock);
474 	nfsrv_wakenfsd_locked(slp);
475 	mutex_exit(&nfsd_lock);
476 }
477 
478 int
nfsdsock_sendreply(struct nfssvc_sock * slp,struct nfsrv_descript * nd)479 nfsdsock_sendreply(struct nfssvc_sock *slp, struct nfsrv_descript *nd)
480 {
481 	int error;
482 
483 	m_freem(nd->nd_mrep);
484 	nd->nd_mrep = NULL;
485 
486 	mutex_enter(&slp->ns_lock);
487 	if ((slp->ns_flags & SLP_SENDING) != 0) {
488 		SIMPLEQ_INSERT_TAIL(&slp->ns_sendq, nd, nd_sendq);
489 		mutex_exit(&slp->ns_lock);
490 		return 0;
491 	}
492 	KASSERT(SIMPLEQ_EMPTY(&slp->ns_sendq));
493 	slp->ns_flags |= SLP_SENDING;
494 	mutex_exit(&slp->ns_lock);
495 
496 again:
497 	error = nfs_send(slp->ns_so, nd->nd_nam2, nd->nd_mreq, NULL, curlwp);
498 	if (nd->nd_nam2) {
499 		m_free(nd->nd_nam2);
500 	}
501 	nfsdreq_free(nd);
502 
503 	mutex_enter(&slp->ns_lock);
504 	KASSERT((slp->ns_flags & SLP_SENDING) != 0);
505 	nd = SIMPLEQ_FIRST(&slp->ns_sendq);
506 	if (nd != NULL) {
507 		SIMPLEQ_REMOVE_HEAD(&slp->ns_sendq, nd_sendq);
508 		mutex_exit(&slp->ns_lock);
509 		goto again;
510 	}
511 	slp->ns_flags &= ~SLP_SENDING;
512 	mutex_exit(&slp->ns_lock);
513 
514 	return error;
515 }
516 
517 void
nfsdsock_setbits(struct nfssvc_sock * slp,int bits)518 nfsdsock_setbits(struct nfssvc_sock *slp, int bits)
519 {
520 
521 	mutex_enter(&slp->ns_alock);
522 	slp->ns_aflags |= bits;
523 	mutex_exit(&slp->ns_alock);
524 }
525 
526 void
nfsdsock_clearbits(struct nfssvc_sock * slp,int bits)527 nfsdsock_clearbits(struct nfssvc_sock *slp, int bits)
528 {
529 
530 	mutex_enter(&slp->ns_alock);
531 	slp->ns_aflags &= ~bits;
532 	mutex_exit(&slp->ns_alock);
533 }
534 
535 bool
nfsdsock_testbits(struct nfssvc_sock * slp,int bits)536 nfsdsock_testbits(struct nfssvc_sock *slp, int bits)
537 {
538 
539 	return (slp->ns_aflags & bits);
540 }
541