1    	/*
2    	 * Copyright (c) 2009, Sun Microsystems, Inc.
3    	 * Copyright (c) 2012-2018 Red Hat, Inc. and/or its affiliates.
4    	 * All rights reserved.
5    	 *
6    	 * Redistribution and use in source and binary forms, with or without
7    	 * modification, are permitted provided that the following conditions are met:
8    	 * - Redistributions of source code must retain the above copyright notice,
9    	 *   this list of conditions and the following disclaimer.
10   	 * - Redistributions in binary form must reproduce the above copyright notice,
11   	 *   this list of conditions and the following disclaimer in the documentation
12   	 *   and/or other materials provided with the distribution.
13   	 * - Neither the name of Sun Microsystems, Inc. nor the names of its
14   	 *   contributors may be used to endorse or promote products derived
15   	 *   from this software without specific prior written permission.
16   	 *
17   	 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18   	 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19   	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20   	 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21   	 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22   	 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23   	 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24   	 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25   	 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26   	 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27   	 * POSSIBILITY OF SUCH DAMAGE.
28   	 */
29   	
30   	#include "config.h"
31   	
32   	/*
33   	 * svc_vc.c, Server side for Connection Oriented RPC.
34   	 *
35   	 * Actually implements two flavors of transporter -
36   	 * a tcp rendezvouser (a listner and connection establisher)
37   	 * and a record/tcp stream.
38   	 */
39   	#include <sys/cdefs.h>
40   	#include <sys/socket.h>
41   	#ifdef RPC_VSOCK
42   	#include <linux/vm_sockets.h>
43   	#endif /* VSOCK */
44   	#include <sys/types.h>
45   	#include <sys/param.h>
46   	#include <sys/poll.h>
47   	
48   	#include <sys/un.h>
49   	#include <sys/time.h>
50   	#include <sys/uio.h>
51   	#include <netinet/in.h>
52   	#include <netinet/tcp.h>
53   	
54   	#include <assert.h>
55   	#include <err.h>
56   	#include <errno.h>
57   	#include <fcntl.h>
58   	#include <stdio.h>
59   	#include <stdlib.h>
60   	#include <string.h>
61   	#include <unistd.h>
62   	#include <signal.h>
63   	#include <getpeereid.h>
64   	
65   	#include <rpc/types.h>
66   	#include <misc/city.h>
67   	#include <misc/portable.h>
68   	#include <misc/timespec.h>
69   	#include <rpc/clnt.h>
70   	#include <rpc/rpc.h>
71   	#include <rpc/svc.h>
72   	#include <rpc/svc_auth.h>
73   	#include <rpc/svc_rqst.h>
74   	#include <rpc/xdr_ioq.h>
75   	
76   	#include "rpc_com.h"
77   	#include "clnt_internal.h"
78   	#include "svc_internal.h"
79   	#include "svc_xprt.h"
80   	#include "rpc_dplx_internal.h"
81   	#include "svc_ioq.h"
82   	
83   	static void svc_vc_rendezvous_ops(SVCXPRT *);
84   	static void svc_vc_override_ops(SVCXPRT *, SVCXPRT *);
85   	
86   	/*
87   	 * A record is composed of one or more record fragments.
88   	 * A record fragment is a four-byte header followed by zero to
89   	 * 2**32-1 bytes.  The header is treated as a long unsigned and is
90   	 * encode/decoded to the network via htonl/ntohl.  The low order 31 bits
91   	 * are a byte count of the fragment.  The highest order bit is a boolean:
92   	 * 1 => this fragment is the last fragment of the record,
93   	 * 0 => this fragment is followed by more fragment(s).
94   	 *
95   	 * The fragment/record machinery is not general;  it is constructed to
96   	 * meet the needs of xdr and rpc based on tcp.
97   	 */
98   	
99   	#define LAST_FRAG ((u_int32_t)(1 << 31))
100  	
101  	/*
102  	 * Usage:
103  	 * xprt = svc_vc_ncreate(sock, send_buf_size, recv_buf_size);
104  	 *
105  	 * Creates, registers, and returns a (rpc) tcp based transport.
106  	 * If a problem occurred, this routine returns a NULL.
107  	 *
108  	 * Since streams do buffered io similar to stdio, the caller can specify
109  	 * how big the send and receive buffers are via the second and third parms;
110  	 * 0 => use the system default.
111  	 *
112  	 * Added svc_vc_ncreatef with flags argument, has the behavior of the
113  	 * original function with flags SVC_CREATE_FLAG_CLOSE.
114  	 *
115  	 */
116  	static void
117  	svc_vc_xprt_free(struct svc_vc_xprt *xd)
118  	{
119  		XDR_DESTROY(xd->sx_dr.ioq.xdrs);
120  		rpc_dplx_rec_destroy(&xd->sx_dr);
121  		mem_free(xd, sizeof(struct svc_vc_xprt));
122  	}
123  	
124  	static struct svc_vc_xprt *
125  	svc_vc_xprt_zalloc(void)
126  	{
127  		struct svc_vc_xprt *xd = mem_zalloc(sizeof(struct svc_vc_xprt));
128  	
129  		/* Init SVCXPRT locks, etc */
130  		rpc_dplx_rec_init(&xd->sx_dr);
131  		xdr_ioq_setup(&xd->sx_dr.ioq);
132  		return (xd);
133  	}
134  	
135  	void
136  	svc_vc_xprt_setup(SVCXPRT **sxpp)
137  	{
138  		if (unlikely(*sxpp)) {
139  			svc_vc_xprt_free(VC_DR(REC_XPRT(*sxpp)));
140  			*sxpp = NULL;
141  		} else {
142  			struct svc_vc_xprt *xd = svc_vc_xprt_zalloc();
143  	
144  			*sxpp = &xd->sx_dr.xprt;
145  		}
146  	}
147  	
148  	SVCXPRT *
149  	svc_vc_ncreatef(const int fd, const u_int sendsz, const u_int recvsz,
150  			const uint32_t flags)
151  	{
152  		struct __rpc_sockinfo si;
153  		SVCXPRT *xprt;
154  		struct rpc_dplx_rec *rec;
155  		struct svc_vc_xprt *xd;
156  		const char *netid;
157  		u_int recvsize;
158  		u_int sendsize;
159  		u_int xp_flags;
160  		int rc;
161  	
162  		/* atomically find or create shared fd state; ref+1; locked */
163  		xprt = svc_xprt_lookup(fd, svc_vc_xprt_setup);
164  		if (!xprt) {
165  			__warnx(TIRPC_DEBUG_FLAG_SVC_VC,
166  				"%s: fd %d svc_xprt_lookup failed",
167  				__func__, fd);
168  			return (NULL);
169  		}
170  		rec = REC_XPRT(xprt);
171  	
172  		xp_flags = atomic_postset_uint16_t_bits(&xprt->xp_flags,
173  							(flags & SVC_XPRT_FLAG_CLOSE)
174  							| SVC_XPRT_FLAG_INITIALIZED);
175  		if (xp_flags & SVC_XPRT_FLAG_INITIALIZED) {
176  			rpc_dplx_rui(rec);
177  			XPRT_TRACE(xprt, __func__, __func__, __LINE__);
178  			return (xprt);
179  		}
180  	
181  		if (!__rpc_fd2sockinfo(fd, &si)) {
182  			atomic_clear_uint16_t_bits(&xprt->xp_flags,
183  						   SVC_XPRT_FLAG_INITIALIZED);
184  			rpc_dplx_rui(rec);
185  			__warnx(TIRPC_DEBUG_FLAG_ERROR,
186  				"%s: fd %d could not get transport information",
187  				__func__, fd);
188  			return (NULL);
189  		}
190  	
191  		if (!__rpc_sockinfo2netid(&si, &netid)) {
192  			atomic_clear_uint16_t_bits(&xprt->xp_flags,
193  						   SVC_XPRT_FLAG_INITIALIZED);
194  			rpc_dplx_rui(rec);
195  			__warnx(TIRPC_DEBUG_FLAG_ERROR,
196  				"%s: fd %d could not get network information",
197  				__func__, fd);
198  			return (NULL);
199  		}
200  	
201  		/*
202  		 * Find the receive and the send size
203  		 */
204  		sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz);
205  		recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
206  		/*
207  		 * Should be multiple of 4 for XDR.
208  		 */
209  		xd = VC_DR(rec);
210  		xd->sx_dr.sendsz = ((sendsize + 3) / 4) * 4;
211  		xd->sx_dr.recvsz = ((recvsize + 3) / 4) * 4;
212  		xd->sx_dr.pagesz = sysconf(_SC_PAGESIZE);
213  		xd->sx_dr.maxrec = __svc_maxrec;
214  	
215  		/* duplex streams are not used by the rendezvous transport */
216  		xdrmem_create(xd->sx_dr.ioq.xdrs, NULL, 0, XDR_ENCODE);
217  	
218  		svc_vc_rendezvous_ops(xprt);
219  	#ifdef RPC_VSOCK
220  		if (si.si_af == AF_VSOCK)
221  			 xprt->xp_type = XPRT_VSOCK_RENDEZVOUS;
222  	#endif /* VSOCK */
223  	
224  		/* caller should know what it's doing */
225  		if (flags & SVC_CREATE_FLAG_LISTEN) {
226  			__warnx(TIRPC_DEBUG_FLAG_SVC_VC,
227  				"%s: fd %d listen",
228  				 __func__, fd);
229  			listen(fd, SOMAXCONN);
230  		}
231  	
232  		__rpc_address_setup(&xprt->xp_local);
233  		rc = getsockname(fd, xprt->xp_local.nb.buf, &xprt->xp_local.nb.len);
234  		if (rc < 0) {
235  			atomic_clear_uint16_t_bits(&xprt->xp_flags,
236  						   SVC_XPRT_FLAG_INITIALIZED);
237  			rpc_dplx_rui(rec);
238  			__warnx(TIRPC_DEBUG_FLAG_ERROR,
239  				"%s: fd %d getsockname failed (%d)",
240  				 __func__, fd, rc);
241  			return (NULL);
242  		}
243  	
244  		xprt->xp_netid = mem_strdup(netid);
245  	
246  		/* Conditional register */
247  		if ((!(__svc_params->flags & SVC_FLAG_NOREG_XPRTS)
248  		     && !(flags & SVC_CREATE_FLAG_XPRT_NOREG))
249  		    || (flags & SVC_CREATE_FLAG_XPRT_DOREG))
250  			svc_rqst_evchan_reg(__svc_params->ev_u.evchan.id, xprt,
251  					    RPC_DPLX_LOCKED |
252  					    SVC_RQST_FLAG_CHAN_AFFINITY);
253  	
254  		/* release */
255  		rpc_dplx_rui(rec);
256  		XPRT_TRACE(xprt, __func__, __func__, __LINE__);
257  	
258  	#if defined(HAVE_BLKIN)
259  		__rpc_set_blkin_endpoint(xprt, "svc_vc");
260  	#endif
261  	
262  		return (xprt);
263  	}
264  	
265  	static SVCXPRT *
266  	makefd_xprt(const int fd, const u_int sendsz, const u_int recvsz,
267  		    struct __rpc_sockinfo *si, u_int flags)
268  	{
269  		SVCXPRT *xprt;
270  		struct svc_vc_xprt *xd;
271  		struct rpc_dplx_rec *rec;
272  		const char *netid;
273  		u_int recvsize;
274  		u_int sendsize;
275  		u_int xp_flags;
276  	
277  		assert(fd != -1);
278  	
279  		/* atomically find or create shared fd state; ref+1; locked */
280  		xprt = svc_xprt_lookup(fd, svc_vc_xprt_setup);
281  		if (!xprt) {
282  			__warnx(TIRPC_DEBUG_FLAG_SVC_VC,
283  				"%s: fd %d svc_xprt_lookup failed",
284  				__func__, fd);
285  			return (NULL);
286  		}
287  		rec = REC_XPRT(xprt);
288  	
289  		xp_flags = atomic_postset_uint16_t_bits(&xprt->xp_flags, flags
290  							| SVC_XPRT_FLAG_INITIALIZED);
291  		if (xp_flags & SVC_XPRT_FLAG_INITIALIZED) {
292  			rpc_dplx_rui(rec);
293  			XPRT_TRACE(xprt, __func__, __func__, __LINE__);
294  			return (xprt);
295  		}
296  	
297  		if (!__rpc_fd2sockinfo(fd, si)) {
298  			atomic_clear_uint16_t_bits(&xprt->xp_flags,
299  						   SVC_XPRT_FLAG_INITIALIZED);
300  			rpc_dplx_rui(rec);
301  			__warnx(TIRPC_DEBUG_FLAG_ERROR,
302  				"%s: fd %d could not get transport information",
303  				__func__, fd);
304  			return (NULL);
305  		}
306  	
307  		if (!__rpc_sockinfo2netid(si, &netid)) {
308  			atomic_clear_uint16_t_bits(&xprt->xp_flags,
309  						   SVC_XPRT_FLAG_INITIALIZED);
310  			rpc_dplx_rui(rec);
311  			__warnx(TIRPC_DEBUG_FLAG_ERROR,
312  				"%s: fd %d could not get network information",
313  				__func__, fd);
314  			return (NULL);
315  		}
316  	
317  		/*
318  		 * Find the receive and the send size
319  		 */
320  		sendsize = __rpc_get_t_size(si->si_af, si->si_proto, (int)sendsz);
321  		recvsize = __rpc_get_t_size(si->si_af, si->si_proto, (int)recvsz);
322  		/*
323  		 * Should be multiple of 4 for XDR.
324  		 */
325  		xd = VC_DR(rec);
326  		xd->sx_dr.sendsz = ((sendsize + 3) / 4) * 4;
327  		xd->sx_dr.recvsz = ((recvsize + 3) / 4) * 4;
328  		xd->sx_dr.pagesz = sysconf(_SC_PAGESIZE);
329  		xd->sx_dr.maxrec = __svc_maxrec;
330  	
331  	#ifdef RPC_VSOCK
332  		if (si->si_af == AF_VSOCK)
333  			 xprt->xp_type = XPRT_VSOCK;
334  	#endif /* VSOCK */
335  	
336  		xprt->xp_netid = mem_strdup(netid);
337  	
338  		/* release */
339  		rpc_dplx_rui(rec);
340  		XPRT_TRACE(xprt, __func__, __func__, __LINE__);
341  	
342  		return (xprt);
343  	}
344  	
345  	/*
346  	 * Like sv_fd_ncreate(), except export flags for additional control.
347  	 */
348  	SVCXPRT *
349  	svc_fd_ncreatef(const int fd, const u_int sendsize, const u_int recvsize,
350  			const uint32_t flags)
351  	{
352  		SVCXPRT *xprt;
353  		struct __rpc_sockinfo si;
354  		int rc;
355  	
356  		assert(fd != -1);
357  	
358  		xprt = makefd_xprt(fd, sendsize, recvsize, &si,
359  				   flags & SVC_XPRT_FLAG_CLOSE);
360  		if ((!xprt) || (!(xprt->xp_flags & SVC_XPRT_FLAG_INITIAL)))
361  			return (xprt);
362  	
363  		svc_vc_override_ops(xprt, NULL);
364  	
365  		__rpc_address_setup(&xprt->xp_local);
366  		rc = getsockname(fd, xprt->xp_local.nb.buf, &xprt->xp_local.nb.len);
367  		if (rc < 0) {
368  			xprt->xp_local.nb.len = sizeof(struct sockaddr_storage);
369  			memset(xprt->xp_local.nb.buf, 0xfe, xprt->xp_local.nb.len);
370  			__warnx(TIRPC_DEBUG_FLAG_ERROR,
371  				"%s: fd %d getsockname failed (%d)",
372  				 __func__, fd, rc);
373  			return (NULL);
374  		}
375  	
376  		__rpc_address_setup(&xprt->xp_remote);
377  		rc = getpeername(fd, xprt->xp_remote.nb.buf, &xprt->xp_remote.nb.len);
378  		if (rc < 0) {
379  			xprt->xp_remote.nb.len = sizeof(struct sockaddr_storage);
380  			memset(xprt->xp_remote.nb.buf, 0xfe, xprt->xp_remote.nb.len);
381  			__warnx(TIRPC_DEBUG_FLAG_ERROR,
382  				"%s: fd %d getpeername failed (%d)",
383  				 __func__, fd, rc);
384  			return (NULL);
385  		}
386  		XPRT_TRACE(xprt, __func__, __func__, __LINE__);
387  	
388  		/* Conditional register */
389  		if ((!(__svc_params->flags & SVC_FLAG_NOREG_XPRTS)
390  		     && !(flags & SVC_CREATE_FLAG_XPRT_NOREG))
391  		    || (flags & SVC_CREATE_FLAG_XPRT_DOREG))
392  			svc_rqst_evchan_reg(__svc_params->ev_u.evchan.id, xprt,
393  					    SVC_RQST_FLAG_CHAN_AFFINITY);
394  	
395  	#if defined(HAVE_BLKIN)
396  		__rpc_set_blkin_endpoint(xprt, "svc_vc");
397  	#endif
398  	
399  		return (xprt);
400  	}
401  	
402  	 /*ARGSUSED*/
403  	static enum xprt_stat
404  	svc_vc_rendezvous(SVCXPRT *xprt)
405  	{
406  		struct svc_vc_xprt *req_xd = VC_DR(REC_XPRT(xprt));
407  		SVCXPRT *newxprt;
408  		struct svc_vc_xprt *xd;
409  		struct sockaddr_storage addr;
410  		struct __rpc_sockinfo si;
411  		int fd;
412  		int rc;
413  		socklen_t len;
414  		static int n = 1;
415  		struct timeval timeval;
416  	
417  	 again:
418  		len = sizeof(addr);
419  		fd = accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr, &len);
420  		if (fd < 0) {
421  			if (errno == EINTR)
422  				goto again;
423  			/*
424  			 * Clean out the most idle file descriptor when we're
425  			 * running out.
426  			 */
427  			if (errno == EMFILE || errno == ENFILE) {
428  				switch (__svc_params->ev_type) {
429  	#if defined(TIRPC_EPOLL)
430  				case SVC_EVENT_EPOLL:
431  					break;
432  	#endif
433  				default:
434  					abort();	/* XXX */
435  					break;
436  				}	/* switch */
437  				goto again;
438  			}
439  			return (XPRT_DIED);
440  		}
441  		if (unlikely(svc_rqst_rearm_events(xprt))) {
442  			__warnx(TIRPC_DEBUG_FLAG_ERROR,
443  				"%s: %p fd %d svc_rqst_rearm_events failed (will set dead)",
444  				__func__, xprt, xprt->xp_fd);
445  			close(fd);
446  			return (XPRT_DIED);
447  		}
448  	
449  		(void) setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));
450  	
451  		/*
452  		 * make a new transport (re-uses xprt)
453  		 */
454  		newxprt = makefd_xprt(fd, req_xd->sx_dr.sendsz, req_xd->sx_dr.recvsz,
455  				      &si, SVC_XPRT_FLAG_CLOSE);
456  		if ((!newxprt) || (!(newxprt->xp_flags & SVC_XPRT_FLAG_INITIAL))) {
457  			close(fd);
458  			return (XPRT_DIED);
459  		}
460  	
461  		svc_vc_override_ops(newxprt, xprt);
462  	
463  		__rpc_address_setup(&newxprt->xp_remote);
464  		memcpy(newxprt->xp_remote.nb.buf, &addr, len);
465  		newxprt->xp_remote.nb.len = len;
466  		XPRT_TRACE(newxprt, __func__, __func__, __LINE__);
467  	
468  		/* XXX fvdl - is this useful? (Yes.  Matt) */
469  		if (si.si_proto == IPPROTO_TCP) {
470  			len = 1;
471  			(void) setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &len,
472  					  sizeof(len));
473  		}
474  	
475  		/* set SO_SNDTIMEO to deal with bad clients */
476  		timeval.tv_sec = 5;
477  		timeval.tv_usec = 0;
478  		if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeval,
479  			       sizeof(timeval))) {
480  			__warnx(TIRPC_DEBUG_FLAG_SVC_VC,
481  				"%s: fd %d SO_SNDTIMEO failed (%d)",
482  				 __func__, fd, errno);
483  		}
484  	
485  		__rpc_address_setup(&newxprt->xp_local);
486  		rc = getsockname(fd, newxprt->xp_local.nb.buf,
487  				 &newxprt->xp_local.nb.len);
488  		if (rc < 0) {
489  			newxprt->xp_local.nb.len = sizeof(struct sockaddr_storage);
490  			memset(newxprt->xp_local.nb.buf, 0xfe,
491  			       newxprt->xp_local.nb.len);
492  			__warnx(TIRPC_DEBUG_FLAG_SVC_VC,
493  				"%s: fd %d getsockname failed (%d)",
494  				 __func__, fd, rc);
495  		}
496  	
497  	#if defined(HAVE_BLKIN)
498  		__rpc_set_blkin_endpoint(newxprt, "svc_vc");
499  	#endif
500  	
501  		xd = VC_DR(REC_XPRT(newxprt));
502  		xd->sx_dr.sendsz = req_xd->sx_dr.sendsz;
503  		xd->sx_dr.recvsz = req_xd->sx_dr.recvsz;
504  		xd->sx_dr.pagesz = req_xd->sx_dr.pagesz;
505  		xd->sx_dr.maxrec = req_xd->sx_dr.maxrec;
506  	
507  		SVC_REF(xprt, SVC_REF_FLAG_NONE);
508  		newxprt->xp_parent = xprt;
509  		if (xprt->xp_dispatch.rendezvous_cb(newxprt)
510  		 || svc_rqst_xprt_register(newxprt, xprt)) {
511  			SVC_DESTROY(newxprt);
512  			/* Was never added to epoll */
513  			SVC_RELEASE(newxprt, SVC_RELEASE_FLAG_NONE);
514  			return (XPRT_DESTROYED);
515  		}
516  		return (XPRT_IDLE);
517  	}
518  	
519  	static void
520  	svc_vc_destroy_task(struct work_pool_entry *wpe)
521  	{
522  		struct rpc_dplx_rec *rec =
523  				opr_containerof(wpe, struct rpc_dplx_rec, ioq.ioq_wpe);
524  		uint16_t xp_flags;
525  	
526  		__warnx(TIRPC_DEBUG_FLAG_REFCNT,
527  			"%s() %p fd %d xp_refcnt %" PRId32,
528  			__func__, rec, rec->xprt.xp_fd, rec->xprt.xp_refcnt);
529  	
530  		if (rec->xprt.xp_refcnt) {
531  			/* instead of nanosleep */
532  			work_pool_submit(&svc_work_pool, &(rec->ioq.ioq_wpe));
533  			return;
534  		}
535  	
536  		xp_flags = atomic_postclear_uint16_t_bits(&rec->xprt.xp_flags,
537  							  SVC_XPRT_FLAG_CLOSE);
538  		if ((xp_flags & SVC_XPRT_FLAG_CLOSE)
539  		    && rec->xprt.xp_fd != RPC_ANYFD) {
540  			(void)close(rec->xprt.xp_fd);
541  			rec->xprt.xp_fd = RPC_ANYFD;
542  		}
543  	
544  		if (rec->xprt.xp_ops->xp_free_user_data)
545  			rec->xprt.xp_ops->xp_free_user_data(&rec->xprt);
546  	
547  		if (rec->xprt.xp_tp)
548  			mem_free(rec->xprt.xp_tp, 0);
549  		if (rec->xprt.xp_netid)
550  			mem_free(rec->xprt.xp_netid, 0);
551  	
552  		if (rec->xprt.xp_parent)
553  			SVC_RELEASE(rec->xprt.xp_parent, SVC_RELEASE_FLAG_NONE);
554  	
555  		svc_vc_xprt_free(VC_DR(rec));
556  	}
557  	
558  	static void
559  	svc_vc_destroy_it(SVCXPRT *xprt, u_int flags, const char *tag, const int line)
560  	{
561  		struct timespec ts = {
562  			.tv_sec = 0,
563  			.tv_nsec = 0,
564  		};
565  	
566  		svc_rqst_xprt_unregister(xprt, flags);
567  	
568  		__warnx(TIRPC_DEBUG_FLAG_REFCNT,
569  			"%s() %p fd %d xp_refcnt %" PRId32 " @%s:%d",
570  			__func__, xprt, xprt->xp_fd, xprt->xp_refcnt, tag, line);
571  	
572  		while (atomic_postset_uint16_t_bits(&(REC_XPRT(xprt)->ioq.ioq_s.qflags),
573  						    IOQ_FLAG_WORKING)
574  		       & IOQ_FLAG_WORKING) {
575  			nanosleep(&ts, NULL);
576  		}
577  	
578  		REC_XPRT(xprt)->ioq.ioq_wpe.fun = svc_vc_destroy_task;
579  		work_pool_submit(&svc_work_pool, &(REC_XPRT(xprt)->ioq.ioq_wpe));
580  	}
581  	
582  	static void
583  	svc_vc_destroy(SVCXPRT *xprt, u_int flags, const char *tag, const int line)
584  	{
585  		svc_vc_destroy_it(xprt, flags, tag, line);
586  	}
587  	
588  	extern mutex_t ops_lock;
589  	
590  	 /*ARGSUSED*/
591  	static bool
592  	svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in)
593  	{
594  		switch (rq) {
595  		case SVCGET_XP_FLAGS:
596  			*(u_int *) in = xprt->xp_flags;
597  			break;
598  		case SVCSET_XP_FLAGS:
599  			xprt->xp_flags = *(u_int *) in;
600  			break;
601  		case SVCGET_XP_FREE_USER_DATA:
602  			mutex_lock(&ops_lock);
603  			*(svc_xprt_fun_t *) in = xprt->xp_ops->xp_free_user_data;
604  			mutex_unlock(&ops_lock);
605  			break;
606  		case SVCSET_XP_FREE_USER_DATA:
607  			mutex_lock(&ops_lock);
608  			xprt->xp_ops->xp_free_user_data = *(svc_xprt_fun_t) in;
609  			mutex_unlock(&ops_lock);
610  			break;
611  		default:
612  			return (FALSE);
613  		}
614  		return (TRUE);
615  	}
616  	
617  	static bool
618  	svc_vc_rendezvous_control(SVCXPRT *xprt, const u_int rq, void *in)
619  	{
620  		struct svc_vc_xprt *xd = VC_DR(REC_XPRT(xprt));
621  	
622  		switch (rq) {
623  		case SVCGET_CONNMAXREC:
624  			*(int *)in = xd->sx_dr.maxrec;
625  			break;
626  		case SVCSET_CONNMAXREC:
627  			xd->sx_dr.maxrec = *(int *)in;
628  			break;
629  		case SVCGET_XP_FREE_USER_DATA:
630  			mutex_lock(&ops_lock);
631  			*(svc_xprt_fun_t *) in = xprt->xp_ops->xp_free_user_data;
632  			mutex_unlock(&ops_lock);
633  			break;
634  		case SVCSET_XP_FREE_USER_DATA:
635  			mutex_lock(&ops_lock);
636  			xprt->xp_ops->xp_free_user_data = *(svc_xprt_fun_t) in;
637  			mutex_unlock(&ops_lock);
638  			break;
639  		default:
640  			return (FALSE);
641  		}
642  		return (TRUE);
643  	}
644  	
645  	static enum xprt_stat
646  	svc_vc_stat(SVCXPRT *xprt)
647  	{
648  		if (xprt->xp_flags & SVC_XPRT_FLAG_DESTROYED)
649  			return (XPRT_DESTROYED);
650  	
651  		return (XPRT_IDLE);
652  	}
653  	
654  	static enum xprt_stat
655  	svc_vc_recv(SVCXPRT *xprt)
656  	{
657  		struct rpc_dplx_rec *rec = REC_XPRT(xprt);
658  		struct svc_vc_xprt *xd = VC_DR(rec);
659  		struct poolq_entry *have;
660  		struct xdr_ioq_uv *uv;
661  		struct xdr_ioq *xioq;
662  		ssize_t rlen;
663  		u_int flags;
664  		int code;
665  	
666  		/* no need for locking, only one svc_rqst_xprt_task() per event.
667  		 * depends upon svc_rqst_rearm_events() for ordering.
668  		 */
669  		have = TAILQ_LAST(&rec->ioq.ioq_uv.uvqh.qh, poolq_head_s);
(1) Event cond_true: Condition "!have", taking true branch.
670  		if (!have) {
671  			xioq = xdr_ioq_create(xd->sx_dr.pagesz, xd->sx_dr.maxrec,
672  					      UIO_FLAG_BUFQ);
673  			(rec->ioq.ioq_uv.uvqh.qcount)++;
674  			TAILQ_INSERT_TAIL(&rec->ioq.ioq_uv.uvqh.qh, &xioq->ioq_s, q);
(2) Event if_fallthrough: Falling through to end of if statement.
675  		} else {
676  			xioq = _IOQ(have);
(3) Event if_end: End of if statement.
677  		}
678  	
(4) Event cond_true: Condition "!xd->sx_fbtbc", taking true branch.
679  		if (!xd->sx_fbtbc) {
(5) Event tainted_data_argument: Calling function "recv" taints argument "xd->sx_fbtbc".
Also see events: [tainted_data_transitive][var_assign][tainted_data]
680  			rlen = recv(xprt->xp_fd, &xd->sx_fbtbc, BYTES_PER_XDR_UNIT,
681  				    MSG_WAITALL);
682  	
(6) Event cond_false: Condition "!!(rlen < 0)", taking false branch.
(7) Event cond_false: Condition "!!(rlen < 0)", taking false branch.
683  			if (unlikely(rlen < 0)) {
684  				code = errno;
685  	
686  				if (code == EAGAIN || code == EWOULDBLOCK) {
687  					__warnx(TIRPC_DEBUG_FLAG_WARN,
688  						"%s: %p fd %d recv errno %d (try again)",
689  						"svc_vc_wait", xprt, xprt->xp_fd, code);
690  					if (unlikely(svc_rqst_rearm_events(xprt))) {
691  						__warnx(TIRPC_DEBUG_FLAG_ERROR,
692  							"%s: %p fd %d svc_rqst_rearm_events failed (will set dead)",
693  							"svc_vc_wait",
694  							xprt, xprt->xp_fd);
695  						SVC_DESTROY(xprt);
696  					}
697  					return SVC_STAT(xprt);
698  				}
699  				__warnx(TIRPC_DEBUG_FLAG_WARN,
700  					"%s: %p fd %d recv errno %d (will set dead)",
701  					"svc_vc_wait", xprt, xprt->xp_fd, code);
702  				SVC_DESTROY(xprt);
703  				return SVC_STAT(xprt);
(8) Event if_end: End of if statement.
704  			}
705  	
(9) Event cond_false: Condition "!!!rlen", taking false branch.
(10) Event cond_false: Condition "!!!rlen", taking false branch.
706  			if (unlikely(!rlen)) {
707  				__warnx(TIRPC_DEBUG_FLAG_SVC_VC,
708  					"%s: %p fd %d recv closed (will set dead)",
709  					"svc_vc_wait", xprt, xprt->xp_fd);
710  				SVC_DESTROY(xprt);
711  				return SVC_STAT(xprt);
(11) Event if_end: End of if statement.
712  			}
713  	
(12) Event tainted_data_transitive: Call to function "ntohl" with tainted argument "xd->sx_fbtbc" returns tainted data.
(13) Event var_assign: Assigning: "xd->sx_fbtbc" = "ntohl", which taints "xd->sx_fbtbc".
Also see events: [tainted_data_argument][tainted_data]
714  			xd->sx_fbtbc = (int32_t)ntohl((long)xd->sx_fbtbc);
715  			flags = UIO_FLAG_FREE | UIO_FLAG_MORE;
716  	
(14) Event cond_false: Condition "xd->sx_fbtbc & 2147483648U /* (u_int32_t)(1 << 31) */", taking false branch.
717  			if (xd->sx_fbtbc & LAST_FRAG) {
718  				xd->sx_fbtbc &= (~LAST_FRAG);
719  				flags = UIO_FLAG_FREE;
(15) Event if_end: End of if statement.
720  			}
721  	
(16) Event cond_false: Condition "!!!xd->sx_fbtbc", taking false branch.
(17) Event cond_false: Condition "!!!xd->sx_fbtbc", taking false branch.
722  			if (unlikely(!xd->sx_fbtbc)) {
723  				__warnx(TIRPC_DEBUG_FLAG_ERROR,
724  					"%s: %p fd %d fragment is zero (will set dead)",
725  					__func__, xprt, xprt->xp_fd);
726  				SVC_DESTROY(xprt);
727  				return SVC_STAT(xprt);
(18) Event if_end: End of if statement.
728  			}
729  	
730  			/* one buffer per fragment */
731  			uv = xdr_ioq_uv_create(xd->sx_fbtbc, flags);
732  			(xioq->ioq_uv.uvqh.qcount)++;
733  			TAILQ_INSERT_TAIL(&xioq->ioq_uv.uvqh.qh, &uv->uvq, q);
(19) Event if_fallthrough: Falling through to end of if statement.
734  		} else {
735  			uv = IOQ_(TAILQ_LAST(&xioq->ioq_uv.uvqh.qh, poolq_head_s));
736  			flags = uv->u.uio_flags;
(20) Event if_end: End of if statement.
737  		}
738  	
(21) Event tainted_data: Passing tainted variable "xd->sx_fbtbc" to a tainted sink.
Also see events: [tainted_data_argument][tainted_data_transitive][var_assign]
739  		rlen = recv(xprt->xp_fd, uv->v.vio_tail, xd->sx_fbtbc, MSG_DONTWAIT);
740  	
741  		if (unlikely(rlen < 0)) {
742  			code = errno;
743  	
744  			if (code == EAGAIN || code == EWOULDBLOCK) {
745  				__warnx(TIRPC_DEBUG_FLAG_SVC_VC,
746  					"%s: %p fd %d recv errno %d (try again)",
747  					__func__, xprt, xprt->xp_fd, code);
748  				if (unlikely(svc_rqst_rearm_events(xprt))) {
749  					__warnx(TIRPC_DEBUG_FLAG_ERROR,
750  						"%s: %p fd %d svc_rqst_rearm_events failed (will set dead)",
751  						__func__, xprt, xprt->xp_fd);
752  					SVC_DESTROY(xprt);
753  				}
754  				return SVC_STAT(xprt);
755  			}
756  			__warnx(TIRPC_DEBUG_FLAG_ERROR,
757  				"%s: %p fd %d recv errno %d (will set dead)",
758  				__func__, xprt, xprt->xp_fd, code);
759  			SVC_DESTROY(xprt);
760  			return SVC_STAT(xprt);
761  		}
762  	
763  		if (unlikely(!rlen)) {
764  			__warnx(TIRPC_DEBUG_FLAG_SVC_VC,
765  				"%s: %p fd %d recv closed (will set dead)",
766  				__func__, xprt, xprt->xp_fd);
767  			SVC_DESTROY(xprt);
768  			return SVC_STAT(xprt);
769  		}
770  	
771  		uv->v.vio_tail += rlen;
772  		xd->sx_fbtbc -= rlen;
773  	
774  		__warnx(TIRPC_DEBUG_FLAG_SVC_VC,
775  			"%s: %p fd %d recv %zd, need %" PRIu32 ", flags %x",
776  			__func__, xprt, xprt->xp_fd, rlen, xd->sx_fbtbc, flags);
777  	
778  		if (xd->sx_fbtbc || (flags & UIO_FLAG_MORE)) {
779  			if (unlikely(svc_rqst_rearm_events(xprt))) {
780  				__warnx(TIRPC_DEBUG_FLAG_ERROR,
781  					"%s: %p fd %d svc_rqst_rearm_events failed (will set dead)",
782  					__func__, xprt, xprt->xp_fd);
783  				SVC_DESTROY(xprt);
784  			}
785  			return SVC_STAT(xprt);
786  		}
787  	
788  		/* finished a request */
789  		(rec->ioq.ioq_uv.uvqh.qcount)--;
790  		TAILQ_REMOVE(&rec->ioq.ioq_uv.uvqh.qh, &xioq->ioq_s, q);
791  		xdr_ioq_reset(xioq, 0);
792  	
793  		if (unlikely(svc_rqst_rearm_events(xprt))) {
794  			__warnx(TIRPC_DEBUG_FLAG_ERROR,
795  				"%s: %p fd %d svc_rqst_rearm_events failed (will set dead)",
796  				__func__, xprt, xprt->xp_fd);
797  			xdr_ioq_destroy(xioq, xioq->ioq_s.qsize);
798  			SVC_DESTROY(xprt);
799  			return SVC_STAT(xprt);
800  		}
801  	
802  		return svc_request(xprt, xioq->xdrs);
803  	}
804  	
805  	static enum xprt_stat
806  	svc_vc_decode(struct svc_req *req)
807  	{
808  		XDR *xdrs = req->rq_xdrs;
809  		SVCXPRT *xprt = req->rq_xprt;
810  	
811  		/* No need, already positioned to beginning ...
812  		XDR_SETPOS(xdrs, 0);
813  		 */
814  		xdrs->x_op = XDR_DECODE;
815  		rpc_msg_init(&req->rq_msg);
816  	
817  		if (!xdr_dplx_decode(xdrs, &req->rq_msg)) {
818  			/* stream is unsynchronized beyond recovery */
819  			__warnx(TIRPC_DEBUG_FLAG_ERROR,
820  				"%s: %p fd %d failed (will set dead)",
821  				__func__, xprt, xprt->xp_fd);
822  			SVC_DESTROY(xprt);
823  			return SVC_STAT(xprt);
824  		}
825  	
826  		/* in order of likelihood */
827  		if (req->rq_msg.rm_direction == CALL) {
828  			/* an ordinary call header */
829  			return xprt->xp_dispatch.process_cb(req);
830  		}
831  	
832  		if (req->rq_msg.rm_direction == REPLY) {
833  			/* reply header (xprt OK) */
834  			return clnt_req_process_reply(xprt, req);
835  		}
836  	
837  		__warnx(TIRPC_DEBUG_FLAG_WARN,
838  			"%s: %p fd %d failed direction %" PRIu32
839  			" (will set dead)",
840  			__func__, xprt, xprt->xp_fd,
841  			req->rq_msg.rm_direction);
842  		SVC_DESTROY(xprt);
843  		return SVC_STAT(xprt);
844  	}
845  	
846  	static void
847  	svc_vc_checksum(struct svc_req *req, void *data, size_t length)
848  	{
849  		req->rq_cksum =
850  	#if 1
851  		/* CithHash64 is -substantially- faster than crc32c from FreeBSD
852  		 * SCTP, so prefer it until fast crc32c bests it */
853  			CityHash64WithSeed(data, MIN(256, length), 103);
854  	#else
855  			calculate_crc32c(0, data, MIN(256, length));
856  	#endif
857  	}
858  	
859  	static enum xprt_stat
860  	svc_vc_reply(struct svc_req *req)
861  	{
862  		SVCXPRT *xprt = req->rq_xprt;
863  		struct xdr_ioq *xioq;
864  	
865  		/* XXX Until gss_get_mic and gss_wrap can be replaced with
866  		 * iov equivalents, replies with RPCSEC_GSS security must be
867  		 * encoded in a contiguous buffer.
868  		 *
869  		 * Nb, we should probably use getpagesize() on Unix.  Need
870  		 * an equivalent for Windows.
871  		 */
872  		xioq = xdr_ioq_create(RPC_MAXDATA_DEFAULT,
873  				      __svc_params->ioq.send_max + RPC_MAXDATA_DEFAULT,
874  				      (req->rq_msg.cb_cred.oa_flavor == RPCSEC_GSS)
875  				      ? UIO_FLAG_REALLOC | UIO_FLAG_FREE
876  				      : UIO_FLAG_FREE);
877  	
878  		if (!xdr_reply_encode(xioq->xdrs, &req->rq_msg)) {
879  			__warnx(TIRPC_DEBUG_FLAG_ERROR,
880  				"%s: %p fd %d xdr_reply_encode failed (will set dead)",
881  				__func__, xprt, xprt->xp_fd);
882  			return (XPRT_DIED);
883  		}
884  		xdr_tail_update(xioq->xdrs);
885  	
886  		if (req->rq_msg.rm_reply.rp_stat == MSG_ACCEPTED
887  		 && req->rq_msg.rm_reply.rp_acpt.ar_stat == SUCCESS
888  		 && req->rq_auth
889  		 && !SVCAUTH_WRAP(req, xioq->xdrs)) {
890  			__warnx(TIRPC_DEBUG_FLAG_ERROR,
891  				"%s: %p fd %d SVCAUTH_WRAP failed (will set dead)",
892  				__func__, xprt, xprt->xp_fd);
893  			return (XPRT_DIED);
894  		}
895  		xdr_tail_update(xioq->xdrs);
896  	
897  		xioq->xdrs[0].x_lib[1] = (void *)req->rq_xprt;
898  		svc_ioq_write_now(req->rq_xprt, xioq);
899  		return (XPRT_IDLE);
900  	}
901  	
902  	static void
903  	svc_vc_override_ops(SVCXPRT *xprt, SVCXPRT *rendezvous)
904  	{
905  		static struct xp_ops ops;
906  	
907  		/* VARIABLES PROTECTED BY ops_lock: ops, xp_type */
908  		mutex_lock(&ops_lock);
909  	
910  		xprt->xp_type = XPRT_TCP;
911  	
912  		if (ops.xp_recv == NULL) {
913  			ops.xp_recv = svc_vc_recv;
914  			ops.xp_stat = svc_vc_stat;
915  			ops.xp_decode = svc_vc_decode;
916  			ops.xp_reply = svc_vc_reply;
917  			ops.xp_checksum = svc_vc_checksum;
918  			ops.xp_destroy = svc_vc_destroy;
919  			ops.xp_control = svc_vc_control;
920  			ops.xp_free_user_data = NULL;	/* no default */
921  		}
922  		svc_override_ops(&ops, rendezvous);
923  		xprt->xp_ops = &ops;
924  		mutex_unlock(&ops_lock);
925  	}
926  	
927  	static void
928  	svc_vc_rendezvous_ops(SVCXPRT *xprt)
929  	{
930  		static struct xp_ops ops;
931  		extern mutex_t ops_lock;
932  	
933  		mutex_lock(&ops_lock);
934  	
935  		xprt->xp_type = XPRT_TCP_RENDEZVOUS;
936  	
937  		if (ops.xp_recv == NULL) {
938  			ops.xp_recv = svc_vc_rendezvous;
939  			ops.xp_stat = svc_rendezvous_stat;
940  			ops.xp_decode = (svc_req_fun_t)abort;
941  			ops.xp_reply = (svc_req_fun_t)abort;
942  			ops.xp_checksum = NULL;		/* not used */
943  			ops.xp_destroy = svc_vc_destroy_it;
944  			ops.xp_control = svc_vc_rendezvous_control;
945  			ops.xp_free_user_data = NULL;	/* no default */
946  		}
947  		xprt->xp_ops = &ops;
948  		mutex_unlock(&ops_lock);
949  	}
950  	
951  	/*
952  	 * Get the effective UID of the sending process. Used by rpcbind, keyserv
953  	 * and rpc.yppasswdd on AF_LOCAL.
954  	 */
955  	int
956  	__rpc_get_local_uid(SVCXPRT *transp, uid_t *uid)
957  	{
958  		int sock, ret;
959  		gid_t egid;
960  		uid_t euid;
961  		struct sockaddr *sa;
962  	
963  		sock = transp->xp_fd;
964  		sa = (struct sockaddr *)&transp->xp_remote.ss;
965  		if (sa->sa_family == AF_LOCAL) {
966  			ret = getpeereid(sock, &euid, &egid);
967  			if (ret == 0)
968  				*uid = euid;
969  			return (ret);
970  		} else
971  			return (-1);
972  	}
973