Sat Nov 7 17:34:33 2015 UTC ()
check for errors and recover instead of core-dumping.


(christos)
diff -r1.35 -r1.36 src/lib/libc/rpc/svc.c
diff -r1.23 -r1.24 src/lib/libc/rpc/svc_run.c
diff -r1.31 -r1.32 src/lib/libc/rpc/svc_vc.c

cvs diff -r1.35 -r1.36 src/lib/libc/rpc/svc.c (switch to unified diff)

--- src/lib/libc/rpc/svc.c 2015/11/06 19:34:13 1.35
+++ src/lib/libc/rpc/svc.c 2015/11/07 17:34:33 1.36
@@ -1,809 +1,812 @@ @@ -1,809 +1,812 @@
1/* $NetBSD: svc.c,v 1.35 2015/11/06 19:34:13 christos Exp $ */ 1/* $NetBSD: svc.c,v 1.36 2015/11/07 17:34:33 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2010, Oracle America, Inc. 4 * Copyright (c) 2010, Oracle America, Inc.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are 7 * modification, are permitted provided that the following conditions are
8 * met: 8 * met:
9 * 9 *
10 * * Redistributions of source code must retain the above copyright 10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above 12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following 13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials 14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution. 15 * provided with the distribution.
16 * * Neither the name of the "Oracle America, Inc." nor the names of its 16 * * Neither the name of the "Oracle America, Inc." nor the names of its
17 * contributors may be used to endorse or promote products derived 17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission. 18 * from this software without specific prior written permission.
19 * 19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */ 32 */
33 33
34#include <sys/cdefs.h> 34#include <sys/cdefs.h>
35#if defined(LIBC_SCCS) && !defined(lint)  35#if defined(LIBC_SCCS) && !defined(lint)
36#if 0 36#if 0
37static char *sccsid = "@(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro"; 37static char *sccsid = "@(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro";
38static char *sccsid = "@(#)svc.c 2.4 88/08/11 4.0 RPCSRC"; 38static char *sccsid = "@(#)svc.c 2.4 88/08/11 4.0 RPCSRC";
39#else 39#else
40__RCSID("$NetBSD: svc.c,v 1.35 2015/11/06 19:34:13 christos Exp $"); 40__RCSID("$NetBSD: svc.c,v 1.36 2015/11/07 17:34:33 christos Exp $");
41#endif 41#endif
42#endif 42#endif
43 43
44/* 44/*
45 * svc.c, Server-side remote procedure call interface. 45 * svc.c, Server-side remote procedure call interface.
46 * 46 *
47 * There are two sets of procedures here. The xprt routines are 47 * There are two sets of procedures here. The xprt routines are
48 * for handling transport handles. The svc routines handle the 48 * for handling transport handles. The svc routines handle the
49 * list of service routines. 49 * list of service routines.
50 * 50 *
51 * Copyright (C) 1984, Sun Microsystems, Inc. 51 * Copyright (C) 1984, Sun Microsystems, Inc.
52 */ 52 */
53 53
54#include "namespace.h" 54#include "namespace.h"
55#include "reentrant.h" 55#include "reentrant.h"
56#include <sys/types.h> 56#include <sys/types.h>
57#include <sys/poll.h> 57#include <sys/poll.h>
58#include <assert.h> 58#include <assert.h>
59#include <errno.h> 59#include <errno.h>
60#include <stdlib.h> 60#include <stdlib.h>
61#include <string.h> 61#include <string.h>
62#include <err.h> 62#include <err.h>
63 63
64#include <rpc/rpc.h> 64#include <rpc/rpc.h>
65#ifdef PORTMAP 65#ifdef PORTMAP
66#include <rpc/pmap_clnt.h> 66#include <rpc/pmap_clnt.h>
67#endif 67#endif
68 68
69#include "svc_fdset.h" 69#include "svc_fdset.h"
70#include "rpc_internal.h" 70#include "rpc_internal.h"
71 71
72#ifdef __weak_alias 72#ifdef __weak_alias
73__weak_alias(svc_getreq,_svc_getreq) 73__weak_alias(svc_getreq,_svc_getreq)
74__weak_alias(svc_getreqset,_svc_getreqset) 74__weak_alias(svc_getreqset,_svc_getreqset)
75__weak_alias(svc_getreq_common,_svc_getreq_common) 75__weak_alias(svc_getreq_common,_svc_getreq_common)
76__weak_alias(svc_register,_svc_register) 76__weak_alias(svc_register,_svc_register)
77__weak_alias(svc_reg,_svc_reg) 77__weak_alias(svc_reg,_svc_reg)
78__weak_alias(svc_unreg,_svc_unreg) 78__weak_alias(svc_unreg,_svc_unreg)
79__weak_alias(svc_sendreply,_svc_sendreply) 79__weak_alias(svc_sendreply,_svc_sendreply)
80__weak_alias(svc_unregister,_svc_unregister) 80__weak_alias(svc_unregister,_svc_unregister)
81__weak_alias(svcerr_auth,_svcerr_auth) 81__weak_alias(svcerr_auth,_svcerr_auth)
82__weak_alias(svcerr_decode,_svcerr_decode) 82__weak_alias(svcerr_decode,_svcerr_decode)
83__weak_alias(svcerr_noproc,_svcerr_noproc) 83__weak_alias(svcerr_noproc,_svcerr_noproc)
84__weak_alias(svcerr_noprog,_svcerr_noprog) 84__weak_alias(svcerr_noprog,_svcerr_noprog)
85__weak_alias(svcerr_progvers,_svcerr_progvers) 85__weak_alias(svcerr_progvers,_svcerr_progvers)
86__weak_alias(svcerr_systemerr,_svcerr_systemerr) 86__weak_alias(svcerr_systemerr,_svcerr_systemerr)
87__weak_alias(svcerr_weakauth,_svcerr_weakauth) 87__weak_alias(svcerr_weakauth,_svcerr_weakauth)
88__weak_alias(xprt_register,_xprt_register) 88__weak_alias(xprt_register,_xprt_register)
89__weak_alias(xprt_unregister,_xprt_unregister) 89__weak_alias(xprt_unregister,_xprt_unregister)
90__weak_alias(rpc_control,_rpc_control) 90__weak_alias(rpc_control,_rpc_control)
91#endif 91#endif
92 92
93/* __svc_xports[-1] is reserved for raw */ 93/* __svc_xports[-1] is reserved for raw */
94SVCXPRT **__svc_xports; 94SVCXPRT **__svc_xports;
95int __svc_maxxports; 95int __svc_maxxports;
96int __svc_maxrec; 96int __svc_maxrec;
97 97
98#define RQCRED_SIZE 400 /* this size is excessive */ 98#define RQCRED_SIZE 400 /* this size is excessive */
99 99
100#define SVC_VERSQUIET 0x0001 /* keep quiet about vers mismatch */ 100#define SVC_VERSQUIET 0x0001 /* keep quiet about vers mismatch */
101#define version_keepquiet(xp) ((u_long)(xp)->xp_p3 & SVC_VERSQUIET) 101#define version_keepquiet(xp) ((u_long)(xp)->xp_p3 & SVC_VERSQUIET)
102 102
103#define max(a, b) (a > b ? a : b) 103#define max(a, b) (a > b ? a : b)
104 104
105/* 105/*
106 * The services list 106 * The services list
107 * Each entry represents a set of procedures (an rpc program). 107 * Each entry represents a set of procedures (an rpc program).
108 * The dispatch routine takes request structs and runs the 108 * The dispatch routine takes request structs and runs the
109 * apropriate procedure. 109 * apropriate procedure.
110 */ 110 */
111static struct svc_callout { 111static struct svc_callout {
112 struct svc_callout *sc_next; 112 struct svc_callout *sc_next;
113 rpcprog_t sc_prog; 113 rpcprog_t sc_prog;
114 rpcvers_t sc_vers; 114 rpcvers_t sc_vers;
115 char *sc_netid; 115 char *sc_netid;
116 void (*sc_dispatch)(struct svc_req *, SVCXPRT *); 116 void (*sc_dispatch)(struct svc_req *, SVCXPRT *);
117} *svc_head; 117} *svc_head;
118 118
119#ifdef _REENTRANT 119#ifdef _REENTRANT
120extern rwlock_t svc_lock; 120extern rwlock_t svc_lock;
121extern rwlock_t svc_fd_lock; 121extern rwlock_t svc_fd_lock;
122#endif 122#endif
123 123
124static struct svc_callout *svc_find(rpcprog_t, rpcvers_t, 124static struct svc_callout *svc_find(rpcprog_t, rpcvers_t,
125 struct svc_callout **, char *); 125 struct svc_callout **, char *);
126static void __xprt_do_unregister(SVCXPRT *xprt, bool_t dolock); 126static void __xprt_do_unregister(SVCXPRT *xprt, bool_t dolock);
127 127
128/* *************** SVCXPRT related stuff **************** */ 128/* *************** SVCXPRT related stuff **************** */
129 129
130static bool_t 130static bool_t
131xprt_alloc(int sock) 131xprt_alloc(int sock)
132{ 132{
133 int maxset; 133 int maxset;
134 char *newxports; 134 char *newxports;
135 135
136 if (++sock < 0) 136 if (++sock < 0)
137 return FALSE; 137 return FALSE;
138 138
139 maxset = svc_fdset_getsize(sock); 139 maxset = svc_fdset_getsize(sock);
140 if (maxset == -1) 140 if (maxset == -1)
141 return FALSE; 141 return FALSE;
142 142
143 if (__svc_xports != NULL && maxset <= __svc_maxxports) 143 if (__svc_xports != NULL && maxset <= __svc_maxxports)
144 return TRUE; 144 return TRUE;
145 145
146 if (__svc_xports != NULL) 146 if (__svc_xports != NULL)
147 --__svc_xports; 147 --__svc_xports;
148 newxports = realloc(__svc_xports, maxset * sizeof(SVCXPRT *)); 148 newxports = realloc(__svc_xports, maxset * sizeof(SVCXPRT *));
149 if (newxports == NULL) { 149 if (newxports == NULL) {
150 warn("%s: out of memory", __func__); 150 warn("%s: out of memory", __func__);
151 return FALSE; 151 return FALSE;
152 } 152 }
153 153
154 memset(newxports + __svc_maxxports * sizeof(SVCXPRT *), 0, 154 memset(newxports + __svc_maxxports * sizeof(SVCXPRT *), 0,
155 (maxset - __svc_maxxports) * sizeof(SVCXPRT *)); 155 (maxset - __svc_maxxports) * sizeof(SVCXPRT *));
156 156
157 __svc_xports = (void *)newxports; 157 __svc_xports = (void *)newxports;
158 __svc_xports++; 158 __svc_xports++;
159 __svc_maxxports = maxset; 159 __svc_maxxports = maxset;
160 160
161 return TRUE; 161 return TRUE;
162} 162}
163 163
164/* 164/*
165 * Activate a transport handle. 165 * Activate a transport handle.
166 */ 166 */
167bool_t 167bool_t
168xprt_register(SVCXPRT *xprt) 168xprt_register(SVCXPRT *xprt)
169{ 169{
170 int sock; 170 int sock;
171 171
172 _DIAGASSERT(xprt != NULL); 172 _DIAGASSERT(xprt != NULL);
173 173
174 rwlock_wrlock(&svc_fd_lock); 174 rwlock_wrlock(&svc_fd_lock);
175 sock = xprt->xp_fd; 175 sock = xprt->xp_fd;
176 176
177 if (!xprt_alloc(sock)) 177 if (!xprt_alloc(sock))
178 goto out; 178 goto out;
179 179
180 __svc_xports[sock] = xprt; 180 __svc_xports[sock] = xprt;
181 if (sock != -1) { 181 if (sock != -1) {
182 svc_fdset_set(sock); 182 if (svc_fdset_set(sock) == -1)
 183 return FALSE;
183 } 184 }
184 rwlock_unlock(&svc_fd_lock); 185 rwlock_unlock(&svc_fd_lock);
185 return (TRUE); 186 return (TRUE);
186 187
187out: 188out:
188 rwlock_unlock(&svc_fd_lock); 189 rwlock_unlock(&svc_fd_lock);
189 return (FALSE); 190 return (FALSE);
190} 191}
191 192
192void 193void
193xprt_unregister(SVCXPRT *xprt) 194xprt_unregister(SVCXPRT *xprt)
194{ 195{
195 __xprt_do_unregister(xprt, TRUE); 196 __xprt_do_unregister(xprt, TRUE);
196} 197}
197 198
198void 199void
199__xprt_unregister_unlocked(SVCXPRT *xprt) 200__xprt_unregister_unlocked(SVCXPRT *xprt)
200{ 201{
201 __xprt_do_unregister(xprt, FALSE); 202 __xprt_do_unregister(xprt, FALSE);
202} 203}
203 204
204/* 205/*
205 * De-activate a transport handle.  206 * De-activate a transport handle.
206 */ 207 */
207static void 208static void
208__xprt_do_unregister(SVCXPRT *xprt, bool_t dolock) 209__xprt_do_unregister(SVCXPRT *xprt, bool_t dolock)
209{  210{
210 int sock, *fdmax; 211 int sock, *fdmax;
211 212
212 _DIAGASSERT(xprt != NULL); 213 _DIAGASSERT(xprt != NULL);
213 214
214 if (dolock) 215 if (dolock)
215 rwlock_wrlock(&svc_fd_lock); 216 rwlock_wrlock(&svc_fd_lock);
216 217
217 sock = xprt->xp_fd; 218 sock = xprt->xp_fd;
218 if (sock >= __svc_maxxports || __svc_xports[sock] != xprt) 219 if (sock >= __svc_maxxports || __svc_xports[sock] != xprt)
219 goto out; 220 goto out;
220 221
221 __svc_xports[sock] = NULL; 222 __svc_xports[sock] = NULL;
222 if (sock == -1) 223 if (sock == -1)
223 goto out; 224 goto out;
224 fdmax = svc_fdset_getmax(); 225 fdmax = svc_fdset_getmax();
225 if (sock < *fdmax) 226 if (fdmax == NULL || sock < *fdmax)
226 goto clr; 227 goto clr;
227 228
228 for ((*fdmax)--; *fdmax >= 0; (*fdmax)--) 229 for ((*fdmax)--; *fdmax >= 0; (*fdmax)--)
229 if (__svc_xports[*fdmax]) 230 if (__svc_xports[*fdmax])
230 break; 231 break;
231clr: 232clr:
232 svc_fdset_clr(sock); 233 svc_fdset_clr(sock);
233out: 234out:
234 if (dolock) 235 if (dolock)
235 rwlock_unlock(&svc_fd_lock); 236 rwlock_unlock(&svc_fd_lock);
236} 237}
237 238
238/* 239/*
239 * Add a service program to the callout list. 240 * Add a service program to the callout list.
240 * The dispatch routine will be called when a rpc request for this 241 * The dispatch routine will be called when a rpc request for this
241 * program number comes in. 242 * program number comes in.
242 */ 243 */
243bool_t 244bool_t
244svc_reg(SVCXPRT *xprt, const rpcprog_t prog, const rpcvers_t vers, 245svc_reg(SVCXPRT *xprt, const rpcprog_t prog, const rpcvers_t vers,
245 void (*dispatch)(struct svc_req *, SVCXPRT *), 246 void (*dispatch)(struct svc_req *, SVCXPRT *),
246 const struct netconfig *nconf) 247 const struct netconfig *nconf)
247{ 248{
248 bool_t dummy; 249 bool_t dummy;
249 struct svc_callout *prev; 250 struct svc_callout *prev;
250 struct svc_callout *s; 251 struct svc_callout *s;
251 struct netconfig *tnconf; 252 struct netconfig *tnconf;
252 char *netid = NULL; 253 char *netid = NULL;
253 int flag = 0; 254 int flag = 0;
254 255
255 _DIAGASSERT(xprt != NULL); 256 _DIAGASSERT(xprt != NULL);
256 /* XXX: dispatch may be NULL ??? */ 257 /* XXX: dispatch may be NULL ??? */
257 258
258/* VARIABLES PROTECTED BY svc_lock: s, prev, svc_head */ 259/* VARIABLES PROTECTED BY svc_lock: s, prev, svc_head */
259 260
260 if (xprt->xp_netid) { 261 if (xprt->xp_netid) {
261 netid = strdup(xprt->xp_netid); 262 netid = strdup(xprt->xp_netid);
262 flag = 1; 263 flag = 1;
263 } else if (nconf && nconf->nc_netid) { 264 } else if (nconf && nconf->nc_netid) {
264 netid = strdup(nconf->nc_netid); 265 netid = strdup(nconf->nc_netid);
265 flag = 1; 266 flag = 1;
266 } else if ((tnconf = __rpcgettp(xprt->xp_fd)) != NULL) { 267 } else if ((tnconf = __rpcgettp(xprt->xp_fd)) != NULL) {
267 netid = strdup(tnconf->nc_netid); 268 netid = strdup(tnconf->nc_netid);
268 flag = 1; 269 flag = 1;
269 freenetconfigent(tnconf); 270 freenetconfigent(tnconf);
270 } /* must have been created with svc_raw_create */ 271 } /* must have been created with svc_raw_create */
271 if ((netid == NULL) && (flag == 1)) { 272 if ((netid == NULL) && (flag == 1)) {
272 return (FALSE); 273 return (FALSE);
273 } 274 }
274 275
275 rwlock_wrlock(&svc_lock); 276 rwlock_wrlock(&svc_lock);
276 if ((s = svc_find(prog, vers, &prev, netid)) != NULL) { 277 if ((s = svc_find(prog, vers, &prev, netid)) != NULL) {
277 if (netid) 278 if (netid)
278 free(netid); 279 free(netid);
279 if (s->sc_dispatch == dispatch) 280 if (s->sc_dispatch == dispatch)
280 goto rpcb_it; /* he is registering another xptr */ 281 goto rpcb_it; /* he is registering another xptr */
281 rwlock_unlock(&svc_lock); 282 rwlock_unlock(&svc_lock);
282 return (FALSE); 283 return (FALSE);
283 } 284 }
284 s = mem_alloc(sizeof (struct svc_callout)); 285 s = mem_alloc(sizeof (struct svc_callout));
285 if (s == NULL) { 286 if (s == NULL) {
286 if (netid) 287 if (netid)
287 free(netid); 288 free(netid);
288 rwlock_unlock(&svc_lock); 289 rwlock_unlock(&svc_lock);
289 return (FALSE); 290 return (FALSE);
290 } 291 }
291 292
292 if ((xprt->xp_netid == NULL) && (flag == 1) && netid) 293 if ((xprt->xp_netid == NULL) && (flag == 1) && netid)
293 if ((((SVCXPRT *) xprt)->xp_netid = strdup(netid)) == NULL) { 294 if ((((SVCXPRT *) xprt)->xp_netid = strdup(netid)) == NULL) {
294 warn("svc_reg"); 295 warn("svc_reg");
295 mem_free(s, sizeof(struct svc_callout)); 296 mem_free(s, sizeof(struct svc_callout));
296 rwlock_unlock(&svc_lock); 297 rwlock_unlock(&svc_lock);
297 return FALSE; 298 return FALSE;
298 } 299 }
299 300
300 s->sc_prog = prog; 301 s->sc_prog = prog;
301 s->sc_vers = vers; 302 s->sc_vers = vers;
302 s->sc_dispatch = dispatch; 303 s->sc_dispatch = dispatch;
303 s->sc_netid = netid; 304 s->sc_netid = netid;
304 s->sc_next = svc_head; 305 s->sc_next = svc_head;
305 svc_head = s; 306 svc_head = s;
306 307
307rpcb_it: 308rpcb_it:
308 rwlock_unlock(&svc_lock); 309 rwlock_unlock(&svc_lock);
309 /* now register the information with the local binder service */ 310 /* now register the information with the local binder service */
310 if (nconf) { 311 if (nconf) {
311 dummy = rpcb_set(prog, vers, __UNCONST(nconf), 312 dummy = rpcb_set(prog, vers, __UNCONST(nconf),
312 &((SVCXPRT *) xprt)->xp_ltaddr); 313 &((SVCXPRT *) xprt)->xp_ltaddr);
313 return (dummy); 314 return (dummy);
314 } 315 }
315 return (TRUE); 316 return (TRUE);
316} 317}
317 318
318/* 319/*
319 * Remove a service program from the callout list. 320 * Remove a service program from the callout list.
320 */ 321 */
321void 322void
322svc_unreg(const rpcprog_t prog, const rpcvers_t vers) 323svc_unreg(const rpcprog_t prog, const rpcvers_t vers)
323{ 324{
324 struct svc_callout *prev; 325 struct svc_callout *prev;
325 struct svc_callout *s; 326 struct svc_callout *s;
326 327
327 /* unregister the information anyway */ 328 /* unregister the information anyway */
328 (void) rpcb_unset(prog, vers, NULL); 329 (void) rpcb_unset(prog, vers, NULL);
329 rwlock_wrlock(&svc_lock); 330 rwlock_wrlock(&svc_lock);
330 while ((s = svc_find(prog, vers, &prev, NULL)) != NULL) { 331 while ((s = svc_find(prog, vers, &prev, NULL)) != NULL) {
331 if (prev == NULL) { 332 if (prev == NULL) {
332 svc_head = s->sc_next; 333 svc_head = s->sc_next;
333 } else { 334 } else {
334 prev->sc_next = s->sc_next; 335 prev->sc_next = s->sc_next;
335 } 336 }
336 s->sc_next = NULL; 337 s->sc_next = NULL;
337 if (s->sc_netid) 338 if (s->sc_netid)
338 mem_free(s->sc_netid, sizeof (s->sc_netid) + 1); 339 mem_free(s->sc_netid, sizeof (s->sc_netid) + 1);
339 mem_free(s, sizeof (struct svc_callout)); 340 mem_free(s, sizeof (struct svc_callout));
340 } 341 }
341 rwlock_unlock(&svc_lock); 342 rwlock_unlock(&svc_lock);
342} 343}
343 344
344/* ********************** CALLOUT list related stuff ************* */ 345/* ********************** CALLOUT list related stuff ************* */
345 346
346#ifdef PORTMAP 347#ifdef PORTMAP
347/* 348/*
348 * Add a service program to the callout list. 349 * Add a service program to the callout list.
349 * The dispatch routine will be called when a rpc request for this 350 * The dispatch routine will be called when a rpc request for this
350 * program number comes in. 351 * program number comes in.
351 */ 352 */
352bool_t 353bool_t
353svc_register(SVCXPRT *xprt, u_long prog, u_long vers, 354svc_register(SVCXPRT *xprt, u_long prog, u_long vers,
354 void (*dispatch)(struct svc_req *, SVCXPRT *), int protocol) 355 void (*dispatch)(struct svc_req *, SVCXPRT *), int protocol)
355{ 356{
356 struct svc_callout *prev; 357 struct svc_callout *prev;
357 struct svc_callout *s; 358 struct svc_callout *s;
358 359
359 _DIAGASSERT(xprt != NULL); 360 _DIAGASSERT(xprt != NULL);
360 _DIAGASSERT(dispatch != NULL); 361 _DIAGASSERT(dispatch != NULL);
361 362
362 if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) != 363 if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) !=
363 NULL) { 364 NULL) {
364 if (s->sc_dispatch == dispatch) 365 if (s->sc_dispatch == dispatch)
365 goto pmap_it; /* he is registering another xptr */ 366 goto pmap_it; /* he is registering another xptr */
366 return (FALSE); 367 return (FALSE);
367 } 368 }
368 s = mem_alloc(sizeof(struct svc_callout)); 369 s = mem_alloc(sizeof(struct svc_callout));
369 if (s == NULL) { 370 if (s == NULL) {
370 return (FALSE); 371 return (FALSE);
371 } 372 }
372 s->sc_prog = (rpcprog_t)prog; 373 s->sc_prog = (rpcprog_t)prog;
373 s->sc_vers = (rpcvers_t)vers; 374 s->sc_vers = (rpcvers_t)vers;
374 s->sc_dispatch = dispatch; 375 s->sc_dispatch = dispatch;
375 s->sc_next = svc_head; 376 s->sc_next = svc_head;
376 svc_head = s; 377 svc_head = s;
377pmap_it: 378pmap_it:
378 /* now register the information with the local binder service */ 379 /* now register the information with the local binder service */
379 if (protocol) { 380 if (protocol) {
380 return (pmap_set(prog, vers, protocol, xprt->xp_port)); 381 return (pmap_set(prog, vers, protocol, xprt->xp_port));
381 } 382 }
382 return (TRUE); 383 return (TRUE);
383} 384}
384 385
385/* 386/*
386 * Remove a service program from the callout list. 387 * Remove a service program from the callout list.
387 */ 388 */
388void 389void
389svc_unregister(u_long prog, u_long vers) 390svc_unregister(u_long prog, u_long vers)
390{ 391{
391 struct svc_callout *prev; 392 struct svc_callout *prev;
392 struct svc_callout *s; 393 struct svc_callout *s;
393 394
394 if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) == 395 if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) ==
395 NULL) 396 NULL)
396 return; 397 return;
397 if (prev == NULL) { 398 if (prev == NULL) {
398 svc_head = s->sc_next; 399 svc_head = s->sc_next;
399 } else { 400 } else {
400 prev->sc_next = s->sc_next; 401 prev->sc_next = s->sc_next;
401 } 402 }
402 s->sc_next = NULL; 403 s->sc_next = NULL;
403 mem_free(s, sizeof(struct svc_callout)); 404 mem_free(s, sizeof(struct svc_callout));
404 /* now unregister the information with the local binder service */ 405 /* now unregister the information with the local binder service */
405 (void)pmap_unset(prog, vers); 406 (void)pmap_unset(prog, vers);
406} 407}
407#endif /* PORTMAP */ 408#endif /* PORTMAP */
408 409
409/* 410/*
410 * Search the callout list for a program number, return the callout 411 * Search the callout list for a program number, return the callout
411 * struct. 412 * struct.
412 */ 413 */
413static struct svc_callout * 414static struct svc_callout *
414svc_find(rpcprog_t prog, rpcvers_t vers, struct svc_callout **prev, char *netid) 415svc_find(rpcprog_t prog, rpcvers_t vers, struct svc_callout **prev, char *netid)
415{ 416{
416 struct svc_callout *s, *p; 417 struct svc_callout *s, *p;
417 418
418 _DIAGASSERT(prev != NULL); 419 _DIAGASSERT(prev != NULL);
419 /* netid is handled below */ 420 /* netid is handled below */
420 421
421 p = NULL; 422 p = NULL;
422 for (s = svc_head; s != NULL; s = s->sc_next) { 423 for (s = svc_head; s != NULL; s = s->sc_next) {
423 if (((s->sc_prog == prog) && (s->sc_vers == vers)) && 424 if (((s->sc_prog == prog) && (s->sc_vers == vers)) &&
424 ((netid == NULL) || (s->sc_netid == NULL) || 425 ((netid == NULL) || (s->sc_netid == NULL) ||
425 (strcmp(netid, s->sc_netid) == 0))) 426 (strcmp(netid, s->sc_netid) == 0)))
426 break; 427 break;
427 p = s; 428 p = s;
428 } 429 }
429 *prev = p; 430 *prev = p;
430 return (s); 431 return (s);
431} 432}
432 433
433/* ******************* REPLY GENERATION ROUTINES ************ */ 434/* ******************* REPLY GENERATION ROUTINES ************ */
434 435
435/* 436/*
436 * Send a reply to an rpc request 437 * Send a reply to an rpc request
437 */ 438 */
438bool_t 439bool_t
439svc_sendreply(SVCXPRT *xprt, xdrproc_t xdr_results, const char *xdr_location) 440svc_sendreply(SVCXPRT *xprt, xdrproc_t xdr_results, const char *xdr_location)
440{ 441{
441 struct rpc_msg rply;  442 struct rpc_msg rply;
442 443
443 _DIAGASSERT(xprt != NULL); 444 _DIAGASSERT(xprt != NULL);
444 445
445 rply.rm_direction = REPLY;  446 rply.rm_direction = REPLY;
446 rply.rm_reply.rp_stat = MSG_ACCEPTED;  447 rply.rm_reply.rp_stat = MSG_ACCEPTED;
447 rply.acpted_rply.ar_verf = xprt->xp_verf;  448 rply.acpted_rply.ar_verf = xprt->xp_verf;
448 rply.acpted_rply.ar_stat = SUCCESS; 449 rply.acpted_rply.ar_stat = SUCCESS;
449 rply.acpted_rply.ar_results.where = xdr_location; 450 rply.acpted_rply.ar_results.where = xdr_location;
450 rply.acpted_rply.ar_results.proc = xdr_results; 451 rply.acpted_rply.ar_results.proc = xdr_results;
451 return (SVC_REPLY(xprt, &rply));  452 return (SVC_REPLY(xprt, &rply));
452} 453}
453 454
454/* 455/*
455 * No procedure error reply 456 * No procedure error reply
456 */ 457 */
457void 458void
458svcerr_noproc(SVCXPRT *xprt) 459svcerr_noproc(SVCXPRT *xprt)
459{ 460{
460 struct rpc_msg rply; 461 struct rpc_msg rply;
461 462
462 _DIAGASSERT(xprt != NULL); 463 _DIAGASSERT(xprt != NULL);
463 464
464 rply.rm_direction = REPLY; 465 rply.rm_direction = REPLY;
465 rply.rm_reply.rp_stat = MSG_ACCEPTED; 466 rply.rm_reply.rp_stat = MSG_ACCEPTED;
466 rply.acpted_rply.ar_verf = xprt->xp_verf; 467 rply.acpted_rply.ar_verf = xprt->xp_verf;
467 rply.acpted_rply.ar_stat = PROC_UNAVAIL; 468 rply.acpted_rply.ar_stat = PROC_UNAVAIL;
468 SVC_REPLY(xprt, &rply); 469 SVC_REPLY(xprt, &rply);
469} 470}
470 471
471/* 472/*
472 * Can't decode args error reply 473 * Can't decode args error reply
473 */ 474 */
474void 475void
475svcerr_decode(SVCXPRT *xprt) 476svcerr_decode(SVCXPRT *xprt)
476{ 477{
477 struct rpc_msg rply;  478 struct rpc_msg rply;
478 479
479 _DIAGASSERT(xprt != NULL); 480 _DIAGASSERT(xprt != NULL);
480 481
481 rply.rm_direction = REPLY;  482 rply.rm_direction = REPLY;
482 rply.rm_reply.rp_stat = MSG_ACCEPTED;  483 rply.rm_reply.rp_stat = MSG_ACCEPTED;
483 rply.acpted_rply.ar_verf = xprt->xp_verf; 484 rply.acpted_rply.ar_verf = xprt->xp_verf;
484 rply.acpted_rply.ar_stat = GARBAGE_ARGS; 485 rply.acpted_rply.ar_stat = GARBAGE_ARGS;
485 SVC_REPLY(xprt, &rply);  486 SVC_REPLY(xprt, &rply);
486} 487}
487 488
488/* 489/*
489 * Some system error 490 * Some system error
490 */ 491 */
491void 492void
492svcerr_systemerr(SVCXPRT *xprt) 493svcerr_systemerr(SVCXPRT *xprt)
493{ 494{
494 struct rpc_msg rply;  495 struct rpc_msg rply;
495 496
496 _DIAGASSERT(xprt != NULL); 497 _DIAGASSERT(xprt != NULL);
497 498
498 rply.rm_direction = REPLY;  499 rply.rm_direction = REPLY;
499 rply.rm_reply.rp_stat = MSG_ACCEPTED;  500 rply.rm_reply.rp_stat = MSG_ACCEPTED;
500 rply.acpted_rply.ar_verf = xprt->xp_verf; 501 rply.acpted_rply.ar_verf = xprt->xp_verf;
501 rply.acpted_rply.ar_stat = SYSTEM_ERR; 502 rply.acpted_rply.ar_stat = SYSTEM_ERR;
502 SVC_REPLY(xprt, &rply);  503 SVC_REPLY(xprt, &rply);
503} 504}
504 505
505#if 0 506#if 0
506/* 507/*
507 * Tell RPC package to not complain about version errors to the client. This 508 * Tell RPC package to not complain about version errors to the client. This
508 * is useful when revving broadcast protocols that sit on a fixed address. 509 * is useful when revving broadcast protocols that sit on a fixed address.
509 * There is really one (or should be only one) example of this kind of 510 * There is really one (or should be only one) example of this kind of
510 * protocol: the portmapper (or rpc binder). 511 * protocol: the portmapper (or rpc binder).
511 */ 512 */
512void 513void
513__svc_versquiet_on(SVCXPRT *xprt) 514__svc_versquiet_on(SVCXPRT *xprt)
514{ 515{
515 u_long tmp; 516 u_long tmp;
516 517
517 _DIAGASSERT(xprt != NULL); 518 _DIAGASSERT(xprt != NULL);
518 519
519 tmp = ((u_long) xprt->xp_p3) | SVC_VERSQUIET; 520 tmp = ((u_long) xprt->xp_p3) | SVC_VERSQUIET;
520 xprt->xp_p3 = (caddr_t) tmp; 521 xprt->xp_p3 = (caddr_t) tmp;
521} 522}
522 523
523void 524void
524__svc_versquiet_off(SVCXPRT *xprt) 525__svc_versquiet_off(SVCXPRT *xprt)
525{ 526{
526 u_long tmp; 527 u_long tmp;
527 528
528 _DIAGASSERT(xprt != NULL); 529 _DIAGASSERT(xprt != NULL);
529 530
530 tmp = ((u_long) xprt->xp_p3) & ~SVC_VERSQUIET; 531 tmp = ((u_long) xprt->xp_p3) & ~SVC_VERSQUIET;
531 xprt->xp_p3 = (caddr_t) tmp; 532 xprt->xp_p3 = (caddr_t) tmp;
532} 533}
533 534
534void 535void
535svc_versquiet(SVCXPRT *xprt) 536svc_versquiet(SVCXPRT *xprt)
536{ 537{
537 __svc_versquiet_on(xprt); 538 __svc_versquiet_on(xprt);
538} 539}
539 540
540int 541int
541__svc_versquiet_get(SVCXPRT *xprt) 542__svc_versquiet_get(SVCXPRT *xprt)
542{ 543{
543 544
544 _DIAGASSERT(xprt != NULL); 545 _DIAGASSERT(xprt != NULL);
545 546
546 return ((int) xprt->xp_p3) & SVC_VERSQUIET; 547 return ((int) xprt->xp_p3) & SVC_VERSQUIET;
547} 548}
548#endif 549#endif
549 550
550/* 551/*
551 * Authentication error reply 552 * Authentication error reply
552 */ 553 */
553void 554void
554svcerr_auth(SVCXPRT *xprt, enum auth_stat why) 555svcerr_auth(SVCXPRT *xprt, enum auth_stat why)
555{ 556{
556 struct rpc_msg rply; 557 struct rpc_msg rply;
557 558
558 _DIAGASSERT(xprt != NULL); 559 _DIAGASSERT(xprt != NULL);
559 560
560 rply.rm_direction = REPLY; 561 rply.rm_direction = REPLY;
561 rply.rm_reply.rp_stat = MSG_DENIED; 562 rply.rm_reply.rp_stat = MSG_DENIED;
562 rply.rjcted_rply.rj_stat = AUTH_ERROR; 563 rply.rjcted_rply.rj_stat = AUTH_ERROR;
563 rply.rjcted_rply.rj_why = why; 564 rply.rjcted_rply.rj_why = why;
564 SVC_REPLY(xprt, &rply); 565 SVC_REPLY(xprt, &rply);
565} 566}
566 567
567/* 568/*
568 * Auth too weak error reply 569 * Auth too weak error reply
569 */ 570 */
570void 571void
571svcerr_weakauth(SVCXPRT *xprt) 572svcerr_weakauth(SVCXPRT *xprt)
572{ 573{
573 574
574 _DIAGASSERT(xprt != NULL); 575 _DIAGASSERT(xprt != NULL);
575 576
576 svcerr_auth(xprt, AUTH_TOOWEAK); 577 svcerr_auth(xprt, AUTH_TOOWEAK);
577} 578}
578 579
579/* 580/*
580 * Program unavailable error reply 581 * Program unavailable error reply
581 */ 582 */
582void  583void
583svcerr_noprog(SVCXPRT *xprt) 584svcerr_noprog(SVCXPRT *xprt)
584{ 585{
585 struct rpc_msg rply;  586 struct rpc_msg rply;
586 587
587 _DIAGASSERT(xprt != NULL); 588 _DIAGASSERT(xprt != NULL);
588 589
589 rply.rm_direction = REPLY;  590 rply.rm_direction = REPLY;
590 rply.rm_reply.rp_stat = MSG_ACCEPTED;  591 rply.rm_reply.rp_stat = MSG_ACCEPTED;
591 rply.acpted_rply.ar_verf = xprt->xp_verf;  592 rply.acpted_rply.ar_verf = xprt->xp_verf;
592 rply.acpted_rply.ar_stat = PROG_UNAVAIL; 593 rply.acpted_rply.ar_stat = PROG_UNAVAIL;
593 SVC_REPLY(xprt, &rply); 594 SVC_REPLY(xprt, &rply);
594} 595}
595 596
596/* 597/*
597 * Program version mismatch error reply 598 * Program version mismatch error reply
598 */ 599 */
599void  600void
600svcerr_progvers(SVCXPRT *xprt, rpcvers_t low_vers, rpcvers_t high_vers) 601svcerr_progvers(SVCXPRT *xprt, rpcvers_t low_vers, rpcvers_t high_vers)
601{ 602{
602 struct rpc_msg rply; 603 struct rpc_msg rply;
603 604
604 _DIAGASSERT(xprt != NULL); 605 _DIAGASSERT(xprt != NULL);
605 606
606 rply.rm_direction = REPLY; 607 rply.rm_direction = REPLY;
607 rply.rm_reply.rp_stat = MSG_ACCEPTED; 608 rply.rm_reply.rp_stat = MSG_ACCEPTED;
608 rply.acpted_rply.ar_verf = xprt->xp_verf; 609 rply.acpted_rply.ar_verf = xprt->xp_verf;
609 rply.acpted_rply.ar_stat = PROG_MISMATCH; 610 rply.acpted_rply.ar_stat = PROG_MISMATCH;
610 rply.acpted_rply.ar_vers.low = (u_int32_t)low_vers; 611 rply.acpted_rply.ar_vers.low = (u_int32_t)low_vers;
611 rply.acpted_rply.ar_vers.high = (u_int32_t)high_vers; 612 rply.acpted_rply.ar_vers.high = (u_int32_t)high_vers;
612 SVC_REPLY(xprt, &rply); 613 SVC_REPLY(xprt, &rply);
613} 614}
614 615
615/* ******************* SERVER INPUT STUFF ******************* */ 616/* ******************* SERVER INPUT STUFF ******************* */
616 617
617/* 618/*
618 * Get server side input from some transport. 619 * Get server side input from some transport.
619 * 620 *
620 * Statement of authentication parameters management: 621 * Statement of authentication parameters management:
621 * This function owns and manages all authentication parameters, specifically 622 * This function owns and manages all authentication parameters, specifically
622 * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and 623 * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
623 * the "cooked" credentials (rqst->rq_clntcred). 624 * the "cooked" credentials (rqst->rq_clntcred).
624 * However, this function does not know the structure of the cooked 625 * However, this function does not know the structure of the cooked
625 * credentials, so it make the following assumptions:  626 * credentials, so it make the following assumptions:
626 * a) the structure is contiguous (no pointers), and 627 * a) the structure is contiguous (no pointers), and
627 * b) the cred structure size does not exceed RQCRED_SIZE bytes.  628 * b) the cred structure size does not exceed RQCRED_SIZE bytes.
628 * In all events, all three parameters are freed upon exit from this routine. 629 * In all events, all three parameters are freed upon exit from this routine.
629 * The storage is trivially management on the call stack in user land, but 630 * The storage is trivially management on the call stack in user land, but
630 * is mallocated in kernel land. 631 * is mallocated in kernel land.
631 */ 632 */
632 633
633void 634void
634svc_getreq(int rdfds) 635svc_getreq(int rdfds)
635{ 636{
636 fd_set *readfds = svc_fdset_copy(NULL); 637 fd_set *readfds = svc_fdset_copy(NULL);
 638 if (readfds == NULL)
 639 return;
637 640
638 readfds->fds_bits[0] = (unsigned int)rdfds; 641 readfds->fds_bits[0] = (unsigned int)rdfds;
639 svc_getreqset(readfds); 642 svc_getreqset(readfds);
640 free(readfds); 643 free(readfds);
641} 644}
642 645
643void 646void
644svc_getreqset2(fd_set *readfds, int maxsize) 647svc_getreqset2(fd_set *readfds, int maxsize)
645{ 648{
646 uint32_t mask, *maskp; 649 uint32_t mask, *maskp;
647 int sock, bit, fd; 650 int sock, bit, fd;
648 651
649 _DIAGASSERT(readfds != NULL); 652 _DIAGASSERT(readfds != NULL);
650 653
651 maskp = readfds->fds_bits; 654 maskp = readfds->fds_bits;
652 for (sock = 0; sock < maxsize; sock += NFDBITS) { 655 for (sock = 0; sock < maxsize; sock += NFDBITS) {
653 for (mask = *maskp++; (bit = ffs((int)mask)) != 0; 656 for (mask = *maskp++; (bit = ffs((int)mask)) != 0;
654 mask ^= (1 << (bit - 1))) { 657 mask ^= (1 << (bit - 1))) {
655 /* sock has input waiting */ 658 /* sock has input waiting */
656 fd = sock + bit - 1; 659 fd = sock + bit - 1;
657 svc_getreq_common(fd); 660 svc_getreq_common(fd);
658 } 661 }
659 } 662 }
660} 663}
661 664
662void 665void
663svc_getreqset(fd_set *readfds) 666svc_getreqset(fd_set *readfds)
664{ 667{
665 svc_getreqset2(readfds, FD_SETSIZE); 668 svc_getreqset2(readfds, FD_SETSIZE);
666} 669}
667 670
668void 671void
669svc_getreq_common(int fd) 672svc_getreq_common(int fd)
670{ 673{
671 SVCXPRT *xprt; 674 SVCXPRT *xprt;
672 struct svc_req r; 675 struct svc_req r;
673 struct rpc_msg msg; 676 struct rpc_msg msg;
674 int prog_found; 677 int prog_found;
675 rpcvers_t low_vers; 678 rpcvers_t low_vers;
676 rpcvers_t high_vers; 679 rpcvers_t high_vers;
677 enum xprt_stat stat; 680 enum xprt_stat stat;
678 char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE]; 681 char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];
679 682
680 msg.rm_call.cb_cred.oa_base = cred_area; 683 msg.rm_call.cb_cred.oa_base = cred_area;
681 msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); 684 msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
682 r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]); 685 r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]);
683 686
684 rwlock_rdlock(&svc_fd_lock); 687 rwlock_rdlock(&svc_fd_lock);
685 xprt = __svc_xports[fd]; 688 xprt = __svc_xports[fd];
686 rwlock_unlock(&svc_fd_lock); 689 rwlock_unlock(&svc_fd_lock);
687 if (xprt == NULL) 690 if (xprt == NULL)
688 /* But do we control sock? */ 691 /* But do we control sock? */
689 return; 692 return;
690 /* now receive msgs from xprtprt (support batch calls) */ 693 /* now receive msgs from xprtprt (support batch calls) */
691 do { 694 do {
692 if (SVC_RECV(xprt, &msg)) { 695 if (SVC_RECV(xprt, &msg)) {
693 696
694 /* now find the exported program and call it */ 697 /* now find the exported program and call it */
695 struct svc_callout *s; 698 struct svc_callout *s;
696 enum auth_stat why; 699 enum auth_stat why;
697 700
698 r.rq_xprt = xprt; 701 r.rq_xprt = xprt;
699 r.rq_prog = msg.rm_call.cb_prog; 702 r.rq_prog = msg.rm_call.cb_prog;
700 r.rq_vers = msg.rm_call.cb_vers; 703 r.rq_vers = msg.rm_call.cb_vers;
701 r.rq_proc = msg.rm_call.cb_proc; 704 r.rq_proc = msg.rm_call.cb_proc;
702 r.rq_cred = msg.rm_call.cb_cred; 705 r.rq_cred = msg.rm_call.cb_cred;
703 /* first authenticate the message */ 706 /* first authenticate the message */
704 if ((why = _authenticate(&r, &msg)) != AUTH_OK) { 707 if ((why = _authenticate(&r, &msg)) != AUTH_OK) {
705 svcerr_auth(xprt, why); 708 svcerr_auth(xprt, why);
706 goto call_done; 709 goto call_done;
707 } 710 }
708 /* now match message with a registered service*/ 711 /* now match message with a registered service*/
709 prog_found = FALSE; 712 prog_found = FALSE;
710 low_vers = (rpcvers_t) -1L; 713 low_vers = (rpcvers_t) -1L;
711 high_vers = (rpcvers_t) 0L; 714 high_vers = (rpcvers_t) 0L;
712 for (s = svc_head; s != NULL; s = s->sc_next) { 715 for (s = svc_head; s != NULL; s = s->sc_next) {
713 if (s->sc_prog == r.rq_prog) { 716 if (s->sc_prog == r.rq_prog) {
714 if (s->sc_vers == r.rq_vers) { 717 if (s->sc_vers == r.rq_vers) {
715 (*s->sc_dispatch)(&r, xprt); 718 (*s->sc_dispatch)(&r, xprt);
716 goto call_done; 719 goto call_done;
717 } /* found correct version */ 720 } /* found correct version */
718 prog_found = TRUE; 721 prog_found = TRUE;
719 if (s->sc_vers < low_vers) 722 if (s->sc_vers < low_vers)
720 low_vers = s->sc_vers; 723 low_vers = s->sc_vers;
721 if (s->sc_vers > high_vers) 724 if (s->sc_vers > high_vers)
722 high_vers = s->sc_vers; 725 high_vers = s->sc_vers;
723 } /* found correct program */ 726 } /* found correct program */
724 } 727 }
725 /* 728 /*
726 * if we got here, the program or version 729 * if we got here, the program or version
727 * is not served ... 730 * is not served ...
728 */ 731 */
729 if (prog_found) 732 if (prog_found)
730 svcerr_progvers(xprt, low_vers, high_vers); 733 svcerr_progvers(xprt, low_vers, high_vers);
731 else 734 else
732 svcerr_noprog(xprt); 735 svcerr_noprog(xprt);
733 /* Fall through to ... */ 736 /* Fall through to ... */
734 } 737 }
735 /* 738 /*
736 * Check if the xprt has been disconnected in a 739 * Check if the xprt has been disconnected in a
737 * recursive call in the service dispatch routine. 740 * recursive call in the service dispatch routine.
738 * If so, then break. 741 * If so, then break.
739 */ 742 */
740 rwlock_rdlock(&svc_fd_lock); 743 rwlock_rdlock(&svc_fd_lock);
741 if (xprt != __svc_xports[fd]) { 744 if (xprt != __svc_xports[fd]) {
742 rwlock_unlock(&svc_fd_lock); 745 rwlock_unlock(&svc_fd_lock);
743 break; 746 break;
744 } 747 }
745 rwlock_unlock(&svc_fd_lock); 748 rwlock_unlock(&svc_fd_lock);
746call_done: 749call_done:
747 if ((stat = SVC_STAT(xprt)) == XPRT_DIED){ 750 if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
748 SVC_DESTROY(xprt); 751 SVC_DESTROY(xprt);
749 break; 752 break;
750 } 753 }
751 } while (stat == XPRT_MOREREQS); 754 } while (stat == XPRT_MOREREQS);
752} 755}
753 756
754 757
755void 758void
756svc_getreq_poll(struct pollfd *pfdp, int pollretval) 759svc_getreq_poll(struct pollfd *pfdp, int pollretval)
757{ 760{
758 int i; 761 int i;
759 int fds_found; 762 int fds_found;
760 763
761 _DIAGASSERT(pfdp != NULL); 764 _DIAGASSERT(pfdp != NULL);
762 765
763 for (i = fds_found = 0; fds_found < pollretval; i++) { 766 for (i = fds_found = 0; fds_found < pollretval; i++) {
764 struct pollfd *p = &pfdp[i]; 767 struct pollfd *p = &pfdp[i];
765 768
766 if (p->revents) { 769 if (p->revents) {
767 /* fd has input waiting */ 770 /* fd has input waiting */
768 fds_found++; 771 fds_found++;
769 /* 772 /*
770 * We assume that this function is only called 773 * We assume that this function is only called
771 * via someone select()ing from svc_fdset or 774 * via someone select()ing from svc_fdset or
772 * pollts()ing from svc_pollset[]. Thus it's safe 775 * pollts()ing from svc_pollset[]. Thus it's safe
773 * to handle the POLLNVAL event by simply turning 776 * to handle the POLLNVAL event by simply turning
774 * the corresponding bit off in svc_fdset. The 777 * the corresponding bit off in the fdset. The
775 * svc_pollset[] array is derived from svc_fdset 778 * svc_pollset[] array is derived from svc_fdset
776 * and so will also be updated eventually. 779 * and so will also be updated eventually.
777 * 780 *
778 * XXX Should we do an xprt_unregister() instead? 781 * XXX Should we do an xprt_unregister() instead?
779 */ 782 */
780 if (p->revents & POLLNVAL) { 783 if (p->revents & POLLNVAL) {
781 rwlock_wrlock(&svc_fd_lock); 784 rwlock_wrlock(&svc_fd_lock);
782 svc_fdset_clr(p->fd); 785 svc_fdset_clr(p->fd);
783 rwlock_unlock(&svc_fd_lock); 786 rwlock_unlock(&svc_fd_lock);
784 } else 787 } else
785 svc_getreq_common(p->fd); 788 svc_getreq_common(p->fd);
786 } 789 }
787 } 790 }
788} 791}
789 792
790bool_t 793bool_t
791rpc_control(int what, void *arg) 794rpc_control(int what, void *arg)
792{ 795{
793 int val; 796 int val;
794 797
795 switch (what) { 798 switch (what) {
796 case RPC_SVC_CONNMAXREC_SET: 799 case RPC_SVC_CONNMAXREC_SET:
797 val = *(int *)arg; 800 val = *(int *)arg;
798 if (val <= 0) 801 if (val <= 0)
799 return FALSE; 802 return FALSE;
800 __svc_maxrec = val; 803 __svc_maxrec = val;
801 return TRUE; 804 return TRUE;
802 case RPC_SVC_CONNMAXREC_GET: 805 case RPC_SVC_CONNMAXREC_GET:
803 *(int *)arg = __svc_maxrec; 806 *(int *)arg = __svc_maxrec;
804 return TRUE; 807 return TRUE;
805 default: 808 default:
806 break; 809 break;
807 } 810 }
808 return FALSE; 811 return FALSE;
809} 812}

cvs diff -r1.23 -r1.24 src/lib/libc/rpc/svc_run.c (switch to unified diff)

--- src/lib/libc/rpc/svc_run.c 2015/11/06 19:34:13 1.23
+++ src/lib/libc/rpc/svc_run.c 2015/11/07 17:34:33 1.24
@@ -1,139 +1,145 @@ @@ -1,139 +1,145 @@
1/* $NetBSD: svc_run.c,v 1.23 2015/11/06 19:34:13 christos Exp $ */ 1/* $NetBSD: svc_run.c,v 1.24 2015/11/07 17:34:33 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2010, Oracle America, Inc. 4 * Copyright (c) 2010, Oracle America, Inc.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are 7 * modification, are permitted provided that the following conditions are
8 * met: 8 * met:
9 * 9 *
10 * * Redistributions of source code must retain the above copyright 10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above 12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following 13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials 14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution. 15 * provided with the distribution.
16 * * Neither the name of the "Oracle America, Inc." nor the names of its 16 * * Neither the name of the "Oracle America, Inc." nor the names of its
17 * contributors may be used to endorse or promote products derived 17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission. 18 * from this software without specific prior written permission.
19 * 19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */ 32 */
33 33
34#include <sys/cdefs.h> 34#include <sys/cdefs.h>
35#if defined(LIBC_SCCS) && !defined(lint) 35#if defined(LIBC_SCCS) && !defined(lint)
36#if 0 36#if 0
37static char *sccsid = "@(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro"; 37static char *sccsid = "@(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro";
38static char *sccsid = "@(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC"; 38static char *sccsid = "@(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC";
39#else 39#else
40__RCSID("$NetBSD: svc_run.c,v 1.23 2015/11/06 19:34:13 christos Exp $"); 40__RCSID("$NetBSD: svc_run.c,v 1.24 2015/11/07 17:34:33 christos Exp $");
41#endif 41#endif
42#endif 42#endif
43 43
44/* 44/*
45 * This is the rpc server side idle loop 45 * This is the rpc server side idle loop
46 * Wait for input, call server program. 46 * Wait for input, call server program.
47 */ 47 */
48#include "namespace.h" 48#include "namespace.h"
49#include "reentrant.h" 49#include "reentrant.h"
50#include <err.h> 50#include <err.h>
51#include <errno.h> 51#include <errno.h>
52#include <stdio.h> 52#include <stdio.h>
53#include <stdlib.h> 53#include <stdlib.h>
54#include <string.h> 54#include <string.h>
55#include <unistd.h> 55#include <unistd.h>
56 56
57#include <rpc/rpc.h> 57#include <rpc/rpc.h>
58 58
59#include "svc_fdset.h" 59#include "svc_fdset.h"
60#include "rpc_internal.h" 60#include "rpc_internal.h"
61 61
62#ifdef __weak_alias 62#ifdef __weak_alias
63__weak_alias(svc_run,_svc_run) 63__weak_alias(svc_run,_svc_run)
64__weak_alias(svc_exit,_svc_exit) 64__weak_alias(svc_exit,_svc_exit)
65#endif 65#endif
66 66
67void 67void
68svc_run(void) 68svc_run(void)
69{ 69{
70 fd_set *readfds, *cleanfds; 70 fd_set *readfds, *cleanfds;
71 struct timeval timeout; 71 struct timeval timeout;
72 int maxfd, fdsize; 72 int *maxfd, fdsize;
73#ifndef RUMP_RPC  73#ifndef RUMP_RPC
74 int probs = 0; 74 int probs = 0;
75#endif 75#endif
76#ifdef _REENTRANT 76#ifdef _REENTRANT
77 extern rwlock_t svc_fd_lock; 77 extern rwlock_t svc_fd_lock;
78#endif 78#endif
79 79
80 readfds = NULL; 80 readfds = NULL;
81 cleanfds = NULL; 81 cleanfds = NULL;
82 fdsize = 0; 82 fdsize = 0;
83 timeout.tv_sec = 30; 83 timeout.tv_sec = 30;
84 timeout.tv_usec = 0; 84 timeout.tv_usec = 0;
85 85
86 for (;;) { 86 for (;;) {
87 rwlock_rdlock(&svc_fd_lock); 87 rwlock_rdlock(&svc_fd_lock);
88 if (fdsize != svc_fdset_getsize(0)) { 88 if (fdsize != svc_fdset_getsize(0)) {
89 fdsize = svc_fdset_getsize(0); 89 fdsize = svc_fdset_getsize(0);
90 free(readfds); 90 free(readfds);
91 readfds = svc_fdset_copy(svc_fdset_get()); 91 readfds = svc_fdset_copy(svc_fdset_get());
92 free(cleanfds); 92 free(cleanfds);
93 cleanfds = svc_fdset_copy(svc_fdset_get()); 93 cleanfds = svc_fdset_copy(svc_fdset_get());
94 } 94 }
95 maxfd = *svc_fdset_getmax(); 95 maxfd = svc_fdset_getmax();
 96 if (maxfd == NULL) {
 97 warn("can't get maxfd");
 98 continue;
 99 }
96 rwlock_unlock(&svc_fd_lock); 100 rwlock_unlock(&svc_fd_lock);
97 switch (select(maxfd + 1, readfds, NULL, NULL, &timeout)) { 101 switch (select(*maxfd + 1, readfds, NULL, NULL, &timeout)) {
98 case -1: 102 case -1:
99#ifndef RUMP_RPC  103#ifndef RUMP_RPC
100 if ((errno == EINTR || errno == EBADF) && probs < 100) { 104 if ((errno == EINTR || errno == EBADF) && probs < 100) {
101 probs++; 105 probs++;
102 continue; 106 continue;
103 } 107 }
104#endif 108#endif
105 if (errno == EINTR) { 109 if (errno == EINTR) {
106 continue; 110 continue;
107 } 111 }
108 warn("%s: select failed", __func__); 112 warn("%s: select failed", __func__);
109 goto out; 113 goto out;
110 case 0: 114 case 0:
111 __svc_clean_idle(cleanfds, 30, FALSE); 115 if (cleanfds)
 116 __svc_clean_idle(cleanfds, 30, FALSE);
112 continue; 117 continue;
113 default: 118 default:
114 svc_getreqset2(readfds, fdsize); 119 if (readfds)
 120 svc_getreqset2(readfds, fdsize);
115#ifndef RUMP_RPC 121#ifndef RUMP_RPC
116 probs = 0; 122 probs = 0;
117#endif 123#endif
118 } 124 }
119 } 125 }
120out: 126out:
121 free(readfds); 127 free(readfds);
122 free(cleanfds); 128 free(cleanfds);
123} 129}
124 130
125/* 131/*
126 * This function causes svc_run() to exit by telling it that it has no 132 * This function causes svc_run() to exit by telling it that it has no
127 * more work to do. 133 * more work to do.
128 */ 134 */
129void 135void
130svc_exit(void) 136svc_exit(void)
131{ 137{
132#ifdef _REENTRANT 138#ifdef _REENTRANT
133 extern rwlock_t svc_fd_lock; 139 extern rwlock_t svc_fd_lock;
134#endif 140#endif
135 141
136 rwlock_wrlock(&svc_fd_lock); 142 rwlock_wrlock(&svc_fd_lock);
137 svc_fdset_zero(); 143 svc_fdset_zero();
138 rwlock_unlock(&svc_fd_lock); 144 rwlock_unlock(&svc_fd_lock);
139} 145}

cvs diff -r1.31 -r1.32 src/lib/libc/rpc/svc_vc.c (switch to unified diff)

--- src/lib/libc/rpc/svc_vc.c 2015/11/06 19:34:13 1.31
+++ src/lib/libc/rpc/svc_vc.c 2015/11/07 17:34:33 1.32
@@ -1,809 +1,818 @@ @@ -1,809 +1,818 @@
1/* $NetBSD: svc_vc.c,v 1.31 2015/11/06 19:34:13 christos Exp $ */ 1/* $NetBSD: svc_vc.c,v 1.32 2015/11/07 17:34:33 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2010, Oracle America, Inc. 4 * Copyright (c) 2010, Oracle America, Inc.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are 7 * modification, are permitted provided that the following conditions are
8 * met: 8 * met:
9 * 9 *
10 * * Redistributions of source code must retain the above copyright 10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above 12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following 13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials 14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution. 15 * provided with the distribution.
16 * * Neither the name of the "Oracle America, Inc." nor the names of its 16 * * Neither the name of the "Oracle America, Inc." nor the names of its
17 * contributors may be used to endorse or promote products derived 17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission. 18 * from this software without specific prior written permission.
19 * 19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */ 32 */
33 33
34#include <sys/cdefs.h> 34#include <sys/cdefs.h>
35#if defined(LIBC_SCCS) && !defined(lint) 35#if defined(LIBC_SCCS) && !defined(lint)
36#if 0 36#if 0
37static char *sccsid = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro"; 37static char *sccsid = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";
38static char *sccsid = "@(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC"; 38static char *sccsid = "@(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC";
39#else 39#else
40__RCSID("$NetBSD: svc_vc.c,v 1.31 2015/11/06 19:34:13 christos Exp $"); 40__RCSID("$NetBSD: svc_vc.c,v 1.32 2015/11/07 17:34:33 christos Exp $");
41#endif 41#endif
42#endif 42#endif
43 43
44/* 44/*
45 * svc_vc.c, Server side for Connection Oriented based RPC.  45 * svc_vc.c, Server side for Connection Oriented based RPC.
46 * 46 *
47 * Actually implements two flavors of transporter - 47 * Actually implements two flavors of transporter -
48 * a tcp rendezvouser (a listner and connection establisher) 48 * a tcp rendezvouser (a listner and connection establisher)
49 * and a record/tcp stream. 49 * and a record/tcp stream.
50 */ 50 */
51 51
52#include "namespace.h" 52#include "namespace.h"
53#include "reentrant.h" 53#include "reentrant.h"
54#include <sys/types.h> 54#include <sys/types.h>
55#include <sys/param.h> 55#include <sys/param.h>
56#include <sys/poll.h> 56#include <sys/poll.h>
57#include <sys/socket.h> 57#include <sys/socket.h>
58#include <sys/un.h> 58#include <sys/un.h>
59#include <sys/time.h> 59#include <sys/time.h>
60#include <netinet/in.h> 60#include <netinet/in.h>
61 61
62#include <assert.h> 62#include <assert.h>
63#include <err.h> 63#include <err.h>
64#include <errno.h> 64#include <errno.h>
65#include <fcntl.h> 65#include <fcntl.h>
66#include <stdio.h> 66#include <stdio.h>
67#include <stdlib.h> 67#include <stdlib.h>
68#include <string.h> 68#include <string.h>
69#include <unistd.h> 69#include <unistd.h>
70 70
71#include <rpc/rpc.h> 71#include <rpc/rpc.h>
72 72
73#include "svc_fdset.h" 73#include "svc_fdset.h"
74#include "rpc_internal.h" 74#include "rpc_internal.h"
75 75
76#ifdef __weak_alias 76#ifdef __weak_alias
77__weak_alias(svc_fd_create,_svc_fd_create) 77__weak_alias(svc_fd_create,_svc_fd_create)
78__weak_alias(svc_vc_create,_svc_vc_create) 78__weak_alias(svc_vc_create,_svc_vc_create)
79#endif 79#endif
80 80
81#ifdef _REENTRANT 81#ifdef _REENTRANT
82extern rwlock_t svc_fd_lock; 82extern rwlock_t svc_fd_lock;
83#endif 83#endif
84 84
85static SVCXPRT *makefd_xprt(int, u_int, u_int); 85static SVCXPRT *makefd_xprt(int, u_int, u_int);
86static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *); 86static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *);
87static enum xprt_stat rendezvous_stat(SVCXPRT *); 87static enum xprt_stat rendezvous_stat(SVCXPRT *);
88static void svc_vc_destroy(SVCXPRT *); 88static void svc_vc_destroy(SVCXPRT *);
89static void __svc_vc_dodestroy(SVCXPRT *); 89static void __svc_vc_dodestroy(SVCXPRT *);
90static int read_vc(caddr_t, caddr_t, int); 90static int read_vc(caddr_t, caddr_t, int);
91static int write_vc(caddr_t, caddr_t, int); 91static int write_vc(caddr_t, caddr_t, int);
92static enum xprt_stat svc_vc_stat(SVCXPRT *); 92static enum xprt_stat svc_vc_stat(SVCXPRT *);
93static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *); 93static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *);
94static bool_t svc_vc_getargs(SVCXPRT *, xdrproc_t, caddr_t); 94static bool_t svc_vc_getargs(SVCXPRT *, xdrproc_t, caddr_t);
95static bool_t svc_vc_freeargs(SVCXPRT *, xdrproc_t, caddr_t); 95static bool_t svc_vc_freeargs(SVCXPRT *, xdrproc_t, caddr_t);
96static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *); 96static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *);
97static void svc_vc_rendezvous_ops(SVCXPRT *); 97static void svc_vc_rendezvous_ops(SVCXPRT *);
98static void svc_vc_ops(SVCXPRT *); 98static void svc_vc_ops(SVCXPRT *);
99static bool_t svc_vc_control(SVCXPRT *, const u_int, void *); 99static bool_t svc_vc_control(SVCXPRT *, const u_int, void *);
100static bool_t svc_vc_rendezvous_control(SVCXPRT *, const u_int, void *); 100static bool_t svc_vc_rendezvous_control(SVCXPRT *, const u_int, void *);
101 101
102struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */ 102struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */
103 u_int sendsize; 103 u_int sendsize;
104 u_int recvsize; 104 u_int recvsize;
105 int maxrec; 105 int maxrec;
106}; 106};
107 107
108struct cf_conn { /* kept in xprt->xp_p1 for actual connection */ 108struct cf_conn { /* kept in xprt->xp_p1 for actual connection */
109 enum xprt_stat strm_stat; 109 enum xprt_stat strm_stat;
110 u_int32_t x_id; 110 u_int32_t x_id;
111 XDR xdrs; 111 XDR xdrs;
112 char verf_body[MAX_AUTH_BYTES]; 112 char verf_body[MAX_AUTH_BYTES];
113 u_int sendsize; 113 u_int sendsize;
114 u_int recvsize; 114 u_int recvsize;
115 int maxrec; 115 int maxrec;
116 bool_t nonblock; 116 bool_t nonblock;
117 struct timeval last_recv_time; 117 struct timeval last_recv_time;
118}; 118};
119 119
120/* 120/*
121 * Usage: 121 * Usage:
122 * xprt = svc_vc_create(sock, send_buf_size, recv_buf_size); 122 * xprt = svc_vc_create(sock, send_buf_size, recv_buf_size);
123 * 123 *
124 * Creates, registers, and returns a (rpc) tcp based transporter. 124 * Creates, registers, and returns a (rpc) tcp based transporter.
125 * Once *xprt is initialized, it is registered as a transporter 125 * Once *xprt is initialized, it is registered as a transporter
126 * see (svc.h, xprt_register). This routine returns 126 * see (svc.h, xprt_register). This routine returns
127 * a NULL if a problem occurred. 127 * a NULL if a problem occurred.
128 * 128 *
129 * The filedescriptor passed in is expected to refer to a bound, but 129 * The filedescriptor passed in is expected to refer to a bound, but
130 * not yet connected socket. 130 * not yet connected socket.
131 * 131 *
132 * Since streams do buffered io similar to stdio, the caller can specify 132 * Since streams do buffered io similar to stdio, the caller can specify
133 * how big the send and receive buffers are via the second and third parms; 133 * how big the send and receive buffers are via the second and third parms;
134 * 0 => use the system default. 134 * 0 => use the system default.
135 */ 135 */
136SVCXPRT * 136SVCXPRT *
137svc_vc_create(int fd, u_int sendsize, u_int recvsize) 137svc_vc_create(int fd, u_int sendsize, u_int recvsize)
138{ 138{
139 SVCXPRT *xprt; 139 SVCXPRT *xprt;
140 struct cf_rendezvous *r = NULL; 140 struct cf_rendezvous *r = NULL;
141 struct __rpc_sockinfo si; 141 struct __rpc_sockinfo si;
142 struct sockaddr_storage sslocal; 142 struct sockaddr_storage sslocal;
143 socklen_t slen; 143 socklen_t slen;
144 int one = 1; 144 int one = 1;
145 145
146 if (!__rpc_fd2sockinfo(fd, &si)) 146 if (!__rpc_fd2sockinfo(fd, &si))
147 return NULL; 147 return NULL;
148 148
149 r = mem_alloc(sizeof(*r)); 149 r = mem_alloc(sizeof(*r));
150 if (r == NULL) { 150 if (r == NULL) {
151 warn("%s: out of memory", __func__); 151 warn("%s: out of memory", __func__);
152 return NULL; 152 return NULL;
153 } 153 }
154 r->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize); 154 r->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize);
155 r->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize); 155 r->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
156 r->maxrec = __svc_maxrec; 156 r->maxrec = __svc_maxrec;
157 xprt = mem_alloc(sizeof(SVCXPRT)); 157 xprt = mem_alloc(sizeof(SVCXPRT));
158 if (xprt == NULL) { 158 if (xprt == NULL) {
159 warn("%s: out of memory", __func__); 159 warn("%s: out of memory", __func__);
160 goto cleanup_svc_vc_create; 160 goto cleanup_svc_vc_create;
161 } 161 }
162 xprt->xp_tp = NULL; 162 xprt->xp_tp = NULL;
163 xprt->xp_p1 = (caddr_t)(void *)r; 163 xprt->xp_p1 = (caddr_t)(void *)r;
164 xprt->xp_p2 = NULL; 164 xprt->xp_p2 = NULL;
165 xprt->xp_p3 = NULL; 165 xprt->xp_p3 = NULL;
166 xprt->xp_verf = _null_auth; 166 xprt->xp_verf = _null_auth;
167 svc_vc_rendezvous_ops(xprt); 167 svc_vc_rendezvous_ops(xprt);
168 xprt->xp_port = (u_short)-1; /* It is the rendezvouser */ 168 xprt->xp_port = (u_short)-1; /* It is the rendezvouser */
169 xprt->xp_fd = fd; 169 xprt->xp_fd = fd;
170 170
171 slen = sizeof (struct sockaddr_storage); 171 slen = sizeof (struct sockaddr_storage);
172 if (getsockname(fd, (struct sockaddr *)(void *)&sslocal, &slen) < 0) { 172 if (getsockname(fd, (struct sockaddr *)(void *)&sslocal, &slen) < 0) {
173 warn("%s: could not retrieve local addr", __func__); 173 warn("%s: could not retrieve local addr", __func__);
174 goto cleanup_svc_vc_create; 174 goto cleanup_svc_vc_create;
175 } 175 }
176 176
177 /* 177 /*
178 * We want to be able to check credentials on local sockets. 178 * We want to be able to check credentials on local sockets.
179 */ 179 */
180 if (sslocal.ss_family == AF_LOCAL) 180 if (sslocal.ss_family == AF_LOCAL)
181 if (setsockopt(fd, 0, LOCAL_CREDS, &one, (socklen_t)sizeof one) 181 if (setsockopt(fd, 0, LOCAL_CREDS, &one, (socklen_t)sizeof one)
182 == -1) 182 == -1)
183 goto cleanup_svc_vc_create; 183 goto cleanup_svc_vc_create;
184 184
185 xprt->xp_ltaddr.maxlen = xprt->xp_ltaddr.len = sslocal.ss_len; 185 xprt->xp_ltaddr.maxlen = xprt->xp_ltaddr.len = sslocal.ss_len;
186 xprt->xp_ltaddr.buf = mem_alloc((size_t)sslocal.ss_len); 186 xprt->xp_ltaddr.buf = mem_alloc((size_t)sslocal.ss_len);
187 if (xprt->xp_ltaddr.buf == NULL) { 187 if (xprt->xp_ltaddr.buf == NULL) {
188 warn("%s: out of memory", __func__); 188 warn("%s: out of memory", __func__);
189 goto cleanup_svc_vc_create; 189 goto cleanup_svc_vc_create;
190 } 190 }
191 memcpy(xprt->xp_ltaddr.buf, &sslocal, (size_t)sslocal.ss_len); 191 memcpy(xprt->xp_ltaddr.buf, &sslocal, (size_t)sslocal.ss_len);
192 192
193 xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage); 193 xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage);
194 if (!xprt_register(xprt)) 194 if (!xprt_register(xprt))
195 goto cleanup_svc_vc_create; 195 goto cleanup_svc_vc_create;
196 return xprt; 196 return xprt;
197cleanup_svc_vc_create: 197cleanup_svc_vc_create:
198 if (xprt) 198 if (xprt)
199 mem_free(xprt, sizeof(*xprt)); 199 mem_free(xprt, sizeof(*xprt));
200 if (r != NULL) 200 if (r != NULL)
201 mem_free(r, sizeof(*r)); 201 mem_free(r, sizeof(*r));
202 return NULL; 202 return NULL;
203} 203}
204 204
205/* 205/*
206 * Like svtcp_create(), except the routine takes any *open* UNIX file 206 * Like svtcp_create(), except the routine takes any *open* UNIX file
207 * descriptor as its first input. 207 * descriptor as its first input.
208 */ 208 */
209SVCXPRT * 209SVCXPRT *
210svc_fd_create(int fd, u_int sendsize, u_int recvsize) 210svc_fd_create(int fd, u_int sendsize, u_int recvsize)
211{ 211{
212 struct sockaddr_storage ss; 212 struct sockaddr_storage ss;
213 socklen_t slen; 213 socklen_t slen;
214 SVCXPRT *ret; 214 SVCXPRT *ret;
215 215
216 _DIAGASSERT(fd != -1); 216 _DIAGASSERT(fd != -1);
217 217
218 ret = makefd_xprt(fd, sendsize, recvsize); 218 ret = makefd_xprt(fd, sendsize, recvsize);
219 if (ret == NULL) 219 if (ret == NULL)
220 return NULL; 220 return NULL;
221 221
222 slen = sizeof (struct sockaddr_storage); 222 slen = sizeof (struct sockaddr_storage);
223 if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { 223 if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
224 warn("%s: could not retrieve local addr", __func__); 224 warn("%s: could not retrieve local addr", __func__);
225 goto freedata; 225 goto freedata;
226 } 226 }
227 ret->xp_ltaddr.maxlen = ret->xp_ltaddr.len = ss.ss_len; 227 ret->xp_ltaddr.maxlen = ret->xp_ltaddr.len = ss.ss_len;
228 ret->xp_ltaddr.buf = mem_alloc((size_t)ss.ss_len); 228 ret->xp_ltaddr.buf = mem_alloc((size_t)ss.ss_len);
229 if (ret->xp_ltaddr.buf == NULL) { 229 if (ret->xp_ltaddr.buf == NULL) {
230 warn("%s: out of memory", __func__); 230 warn("%s: out of memory", __func__);
231 goto freedata; 231 goto freedata;
232 } 232 }
233 memcpy(ret->xp_ltaddr.buf, &ss, (size_t)ss.ss_len); 233 memcpy(ret->xp_ltaddr.buf, &ss, (size_t)ss.ss_len);
234 234
235 slen = sizeof (struct sockaddr_storage); 235 slen = sizeof (struct sockaddr_storage);
236 if (getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { 236 if (getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
237 warn("%s: could not retrieve remote addr", __func__); 237 warn("%s: could not retrieve remote addr", __func__);
238 goto freedata; 238 goto freedata;
239 } 239 }
240 ret->xp_rtaddr.maxlen = ret->xp_rtaddr.len = ss.ss_len; 240 ret->xp_rtaddr.maxlen = ret->xp_rtaddr.len = ss.ss_len;
241 ret->xp_rtaddr.buf = mem_alloc((size_t)ss.ss_len); 241 ret->xp_rtaddr.buf = mem_alloc((size_t)ss.ss_len);
242 if (ret->xp_rtaddr.buf == NULL) { 242 if (ret->xp_rtaddr.buf == NULL) {
243 warn("%s: out of memory", __func__); 243 warn("%s: out of memory", __func__);
244 goto freedata; 244 goto freedata;
245 } 245 }
246 memcpy(ret->xp_rtaddr.buf, &ss, (size_t)ss.ss_len); 246 memcpy(ret->xp_rtaddr.buf, &ss, (size_t)ss.ss_len);
247#ifdef PORTMAP 247#ifdef PORTMAP
248 if (ss.ss_family == AF_INET) { 248 if (ss.ss_family == AF_INET) {
249 ret->xp_raddr = *(struct sockaddr_in *)ret->xp_rtaddr.buf; 249 ret->xp_raddr = *(struct sockaddr_in *)ret->xp_rtaddr.buf;
250 ret->xp_addrlen = sizeof (struct sockaddr_in); 250 ret->xp_addrlen = sizeof (struct sockaddr_in);
251 } 251 }
252#endif 252#endif
253 253
254 return ret; 254 return ret;
255 255
256freedata: 256freedata:
257 if (ret->xp_ltaddr.buf != NULL) 257 if (ret->xp_ltaddr.buf != NULL)
258 mem_free(ret->xp_ltaddr.buf, rep->xp_ltaddr.maxlen); 258 mem_free(ret->xp_ltaddr.buf, rep->xp_ltaddr.maxlen);
259 259
260 return NULL; 260 return NULL;
261} 261}
262 262
263static SVCXPRT * 263static SVCXPRT *
264makefd_xprt(int fd, u_int sendsize, u_int recvsize) 264makefd_xprt(int fd, u_int sendsize, u_int recvsize)
265{ 265{
266 SVCXPRT *xprt; 266 SVCXPRT *xprt;
267 struct cf_conn *cd; 267 struct cf_conn *cd;
268 const char *netid; 268 const char *netid;
269 struct __rpc_sockinfo si; 269 struct __rpc_sockinfo si;
270  270
271 _DIAGASSERT(fd != -1); 271 _DIAGASSERT(fd != -1);
272 272
273 xprt = mem_alloc(sizeof(SVCXPRT)); 273 xprt = mem_alloc(sizeof(SVCXPRT));
274 if (xprt == NULL) 274 if (xprt == NULL)
275 goto outofmem; 275 goto outofmem;
276 memset(xprt, 0, sizeof *xprt); 276 memset(xprt, 0, sizeof *xprt);
277 cd = mem_alloc(sizeof(struct cf_conn)); 277 cd = mem_alloc(sizeof(struct cf_conn));
278 if (cd == NULL) 278 if (cd == NULL)
279 goto outofmem; 279 goto outofmem;
280 cd->strm_stat = XPRT_IDLE; 280 cd->strm_stat = XPRT_IDLE;
281 xdrrec_create(&(cd->xdrs), sendsize, recvsize, 281 xdrrec_create(&(cd->xdrs), sendsize, recvsize,
282 (caddr_t)(void *)xprt, read_vc, write_vc); 282 (caddr_t)(void *)xprt, read_vc, write_vc);
283 xprt->xp_p1 = (caddr_t)(void *)cd; 283 xprt->xp_p1 = (caddr_t)(void *)cd;
284 xprt->xp_verf.oa_base = cd->verf_body; 284 xprt->xp_verf.oa_base = cd->verf_body;
285 svc_vc_ops(xprt); /* truely deals with calls */ 285 svc_vc_ops(xprt); /* truely deals with calls */
286 xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ 286 xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
287 xprt->xp_fd = fd; 287 xprt->xp_fd = fd;
288 if (__rpc_fd2sockinfo(fd, &si) && __rpc_sockinfo2netid(&si, &netid)) 288 if (__rpc_fd2sockinfo(fd, &si) && __rpc_sockinfo2netid(&si, &netid))
289 if ((xprt->xp_netid = strdup(netid)) == NULL) 289 if ((xprt->xp_netid = strdup(netid)) == NULL)
290 goto outofmem; 290 goto outofmem;
291 291
292 if (!xprt_register(xprt)) 292 if (!xprt_register(xprt))
293 goto out; 293 goto out;
294 return xprt; 294 return xprt;
295 295
296outofmem: 296outofmem:
297 warn("svc_tcp: makefd_xprt"); 297 warn("svc_tcp: makefd_xprt");
298out: 298out:
299 if (xprt) 299 if (xprt)
300 mem_free(xprt, sizeof(SVCXPRT)); 300 mem_free(xprt, sizeof(SVCXPRT));
301 return NULL; 301 return NULL;
302} 302}
303 303
304/*ARGSUSED*/ 304/*ARGSUSED*/
305static bool_t 305static bool_t
306rendezvous_request(SVCXPRT *xprt, struct rpc_msg *msg) 306rendezvous_request(SVCXPRT *xprt, struct rpc_msg *msg)
307{ 307{
308 int sock, flags; 308 int sock, flags;
309 struct cf_rendezvous *r; 309 struct cf_rendezvous *r;
310 struct cf_conn *cd; 310 struct cf_conn *cd;
311 struct sockaddr_storage addr; 311 struct sockaddr_storage addr;
312 socklen_t len; 312 socklen_t len;
313 struct __rpc_sockinfo si; 313 struct __rpc_sockinfo si;
314 SVCXPRT *newxprt; 314 SVCXPRT *newxprt;
315 315
316 _DIAGASSERT(xprt != NULL); 316 _DIAGASSERT(xprt != NULL);
317 _DIAGASSERT(msg != NULL); 317 _DIAGASSERT(msg != NULL);
318 318
319 r = (struct cf_rendezvous *)xprt->xp_p1; 319 r = (struct cf_rendezvous *)xprt->xp_p1;
320again: 320again:
321 len = sizeof addr; 321 len = sizeof addr;
322 if ((sock = accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr, 322 if ((sock = accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr,
323 &len)) < 0) { 323 &len)) < 0) {
324 if (errno == EINTR) 324 if (errno == EINTR)
325 goto again; 325 goto again;
326 /* 326 /*
327 * Clean out the most idle file descriptor when we're 327 * Clean out the most idle file descriptor when we're
328 * running out. 328 * running out.
329 */ 329 */
330 if (errno == EMFILE || errno == ENFILE) { 330 if (errno == EMFILE || errno == ENFILE) {
331 fd_set *cleanfds = svc_fdset_copy(svc_fdset_get()); 331 fd_set *cleanfds = svc_fdset_copy(svc_fdset_get());
332 int rv = __svc_clean_idle(cleanfds, 0, FALSE); 332 int rv = 0;
 333 if (cleanfds)
 334 rv = __svc_clean_idle(cleanfds, 0, FALSE);
333 free(cleanfds); 335 free(cleanfds);
334 if (rv) 336 if (rv)
335 goto again; 337 goto again;
336 } 338 }
337 return FALSE; 339 return FALSE;
338 } 340 }
339 /* 341 /*
340 * make a new transporter (re-uses xprt) 342 * make a new transporter (re-uses xprt)
341 */ 343 */
342 newxprt = makefd_xprt(sock, r->sendsize, r->recvsize); 344 newxprt = makefd_xprt(sock, r->sendsize, r->recvsize);
343 if (newxprt == NULL) 345 if (newxprt == NULL)
344 goto out; 346 goto out;
345 newxprt->xp_rtaddr.buf = mem_alloc(len); 347 newxprt->xp_rtaddr.buf = mem_alloc(len);
346 if (newxprt->xp_rtaddr.buf == NULL) 348 if (newxprt->xp_rtaddr.buf == NULL)
347 goto out; 349 goto out;
348 memcpy(newxprt->xp_rtaddr.buf, &addr, len); 350 memcpy(newxprt->xp_rtaddr.buf, &addr, len);
349 newxprt->xp_rtaddr.len = len; 351 newxprt->xp_rtaddr.len = len;
350#ifdef PORTMAP 352#ifdef PORTMAP
351 if (addr.ss_family == AF_INET) { 353 if (addr.ss_family == AF_INET) {
352 newxprt->xp_raddr = *(struct sockaddr_in *)newxprt->xp_rtaddr.buf; 354 newxprt->xp_raddr = *(struct sockaddr_in *)newxprt->xp_rtaddr.buf;
353 newxprt->xp_addrlen = sizeof (struct sockaddr_in); 355 newxprt->xp_addrlen = sizeof (struct sockaddr_in);
354 } 356 }
355#endif 357#endif
356 if (__rpc_fd2sockinfo(sock, &si)) 358 if (__rpc_fd2sockinfo(sock, &si))
357 __rpc_setnodelay(sock, &si); 359 __rpc_setnodelay(sock, &si);
358 360
359 cd = (struct cf_conn *)newxprt->xp_p1; 361 cd = (struct cf_conn *)newxprt->xp_p1;
360 362
361 cd->recvsize = r->recvsize; 363 cd->recvsize = r->recvsize;
362 cd->sendsize = r->sendsize; 364 cd->sendsize = r->sendsize;
363 cd->maxrec = r->maxrec; 365 cd->maxrec = r->maxrec;
364 366
365 if (cd->maxrec != 0) { 367 if (cd->maxrec != 0) {
366 flags = fcntl(sock, F_GETFL, 0); 368 flags = fcntl(sock, F_GETFL, 0);
367 if (flags == -1) 369 if (flags == -1)
368 goto out; 370 goto out;
369 if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) 371 if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1)
370 goto out; 372 goto out;
371 if (cd->recvsize > (u_int)cd->maxrec) 373 if (cd->recvsize > (u_int)cd->maxrec)
372 cd->recvsize = cd->maxrec; 374 cd->recvsize = cd->maxrec;
373 cd->nonblock = TRUE; 375 cd->nonblock = TRUE;
374 __xdrrec_setnonblock(&cd->xdrs, cd->maxrec); 376 __xdrrec_setnonblock(&cd->xdrs, cd->maxrec);
375 } else 377 } else
376 cd->nonblock = FALSE; 378 cd->nonblock = FALSE;
377 379
378 (void)gettimeofday(&cd->last_recv_time, NULL); 380 (void)gettimeofday(&cd->last_recv_time, NULL);
379 381
380 return FALSE; /* there is never an rpc msg to be processed */ 382 return FALSE; /* there is never an rpc msg to be processed */
381out: 383out:
382 (void)close(sock); 384 (void)close(sock);
383 return FALSE; /* there was an error */ 385 return FALSE; /* there was an error */
384} 386}
385 387
386/*ARGSUSED*/ 388/*ARGSUSED*/
387static enum xprt_stat 389static enum xprt_stat
388rendezvous_stat(SVCXPRT *xprt) 390rendezvous_stat(SVCXPRT *xprt)
389{ 391{
390 392
391 return XPRT_IDLE; 393 return XPRT_IDLE;
392} 394}
393 395
394static void 396static void
395svc_vc_destroy(SVCXPRT *xprt) 397svc_vc_destroy(SVCXPRT *xprt)
396{ 398{
397 _DIAGASSERT(xprt != NULL); 399 _DIAGASSERT(xprt != NULL);
398 400
399 xprt_unregister(xprt); 401 xprt_unregister(xprt);
400 __svc_vc_dodestroy(xprt); 402 __svc_vc_dodestroy(xprt);
401} 403}
402 404
403static void 405static void
404__svc_vc_dodestroy(SVCXPRT *xprt) 406__svc_vc_dodestroy(SVCXPRT *xprt)
405{ 407{
406 struct cf_conn *cd; 408 struct cf_conn *cd;
407 struct cf_rendezvous *r; 409 struct cf_rendezvous *r;
408 410
409 cd = (struct cf_conn *)xprt->xp_p1; 411 cd = (struct cf_conn *)xprt->xp_p1;
410 412
411 if (xprt->xp_fd != RPC_ANYFD) 413 if (xprt->xp_fd != RPC_ANYFD)
412 (void)close(xprt->xp_fd); 414 (void)close(xprt->xp_fd);
413 if (xprt->xp_port != 0) { 415 if (xprt->xp_port != 0) {
414 /* a rendezvouser socket */ 416 /* a rendezvouser socket */
415 r = (struct cf_rendezvous *)xprt->xp_p1; 417 r = (struct cf_rendezvous *)xprt->xp_p1;
416 mem_free(r, sizeof (struct cf_rendezvous)); 418 mem_free(r, sizeof (struct cf_rendezvous));
417 xprt->xp_port = 0; 419 xprt->xp_port = 0;
418 } else { 420 } else {
419 /* an actual connection socket */ 421 /* an actual connection socket */
420 XDR_DESTROY(&(cd->xdrs)); 422 XDR_DESTROY(&(cd->xdrs));
421 mem_free(cd, sizeof(struct cf_conn)); 423 mem_free(cd, sizeof(struct cf_conn));
422 } 424 }
423 if (xprt->xp_rtaddr.buf) 425 if (xprt->xp_rtaddr.buf)
424 mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen); 426 mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen);
425 if (xprt->xp_ltaddr.buf) 427 if (xprt->xp_ltaddr.buf)
426 mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen); 428 mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen);
427 if (xprt->xp_tp) 429 if (xprt->xp_tp)
428 free(xprt->xp_tp); 430 free(xprt->xp_tp);
429 if (xprt->xp_netid) 431 if (xprt->xp_netid)
430 free(xprt->xp_netid); 432 free(xprt->xp_netid);
431 mem_free(xprt, sizeof(SVCXPRT)); 433 mem_free(xprt, sizeof(SVCXPRT));
432} 434}
433 435
434/*ARGSUSED*/ 436/*ARGSUSED*/
435static bool_t 437static bool_t
436svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in) 438svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in)
437{ 439{
438 return FALSE; 440 return FALSE;
439} 441}
440 442
441/*ARGSUSED*/ 443/*ARGSUSED*/
442static bool_t 444static bool_t
443svc_vc_rendezvous_control(SVCXPRT *xprt, const u_int rq, void *in) 445svc_vc_rendezvous_control(SVCXPRT *xprt, const u_int rq, void *in)
444{ 446{
445 struct cf_rendezvous *cfp; 447 struct cf_rendezvous *cfp;
446 448
447 cfp = (struct cf_rendezvous *)xprt->xp_p1; 449 cfp = (struct cf_rendezvous *)xprt->xp_p1;
448 if (cfp == NULL) 450 if (cfp == NULL)
449 return FALSE; 451 return FALSE;
450 switch (rq) { 452 switch (rq) {
451 case SVCGET_CONNMAXREC: 453 case SVCGET_CONNMAXREC:
452 *(int *)in = cfp->maxrec; 454 *(int *)in = cfp->maxrec;
453 break; 455 break;
454 case SVCSET_CONNMAXREC: 456 case SVCSET_CONNMAXREC:
455 cfp->maxrec = *(int *)in; 457 cfp->maxrec = *(int *)in;
456 break; 458 break;
457 default: 459 default:
458 return FALSE; 460 return FALSE;
459 } 461 }
460 return TRUE; 462 return TRUE;
461} 463}
462 464
463/* 465/*
464 * reads data from the tcp connection. 466 * reads data from the tcp connection.
465 * any error is fatal and the connection is closed. 467 * any error is fatal and the connection is closed.
466 * (And a read of zero bytes is a half closed stream => error.) 468 * (And a read of zero bytes is a half closed stream => error.)
467 * All read operations timeout after 35 seconds. A timeout is 469 * All read operations timeout after 35 seconds. A timeout is
468 * fatal for the connection. 470 * fatal for the connection.
469 */ 471 */
470static int 472static int
471read_vc(caddr_t xprtp, caddr_t buf, int len) 473read_vc(caddr_t xprtp, caddr_t buf, int len)
472{ 474{
473 SVCXPRT *xprt; 475 SVCXPRT *xprt;
474 int sock; 476 int sock;
475 struct pollfd pollfd; 477 struct pollfd pollfd;
476 struct sockaddr *sa; 478 struct sockaddr *sa;
477 struct msghdr msg; 479 struct msghdr msg;
478 struct cmsghdr *cmp; 480 struct cmsghdr *cmp;
479 void *crmsg = NULL; 481 void *crmsg = NULL;
480 struct sockcred *sc; 482 struct sockcred *sc;
481 socklen_t crmsgsize; 483 socklen_t crmsgsize;
482 struct cf_conn *cfp; 484 struct cf_conn *cfp;
483 static const struct timespec ts = { 35, 0 }; 485 static const struct timespec ts = { 35, 0 };
484 486
485 xprt = (SVCXPRT *)(void *)xprtp; 487 xprt = (SVCXPRT *)(void *)xprtp;
486 _DIAGASSERT(xprt != NULL); 488 _DIAGASSERT(xprt != NULL);
487 489
488 sock = xprt->xp_fd; 490 sock = xprt->xp_fd;
489 491
490 sa = (struct sockaddr *)xprt->xp_rtaddr.buf; 492 sa = (struct sockaddr *)xprt->xp_rtaddr.buf;
491 if (sa->sa_family == AF_LOCAL && xprt->xp_p2 == NULL) { 493 if (sa->sa_family == AF_LOCAL && xprt->xp_p2 == NULL) {
492 memset(&msg, 0, sizeof msg); 494 memset(&msg, 0, sizeof msg);
493 crmsgsize = CMSG_SPACE(SOCKCREDSIZE(NGROUPS)); 495 crmsgsize = CMSG_SPACE(SOCKCREDSIZE(NGROUPS));
494 crmsg = malloc(crmsgsize); 496 crmsg = malloc(crmsgsize);
495 if (crmsg == NULL) 497 if (crmsg == NULL)
496 goto fatal_err; 498 goto fatal_err;
497 memset(crmsg, 0, crmsgsize); 499 memset(crmsg, 0, crmsgsize);
498 500
499 msg.msg_control = crmsg; 501 msg.msg_control = crmsg;
500 msg.msg_controllen = crmsgsize; 502 msg.msg_controllen = crmsgsize;
501 503
502 if (recvmsg(sock, &msg, 0) < 0) 504 if (recvmsg(sock, &msg, 0) < 0)
503 goto fatal_err; 505 goto fatal_err;
504 506
505 if (msg.msg_controllen == 0 || 507 if (msg.msg_controllen == 0 ||
506 (msg.msg_flags & MSG_CTRUNC) != 0) 508 (msg.msg_flags & MSG_CTRUNC) != 0)
507 goto fatal_err; 509 goto fatal_err;
508 510
509 cmp = CMSG_FIRSTHDR(&msg); 511 cmp = CMSG_FIRSTHDR(&msg);
510 if (cmp->cmsg_level != SOL_SOCKET || 512 if (cmp->cmsg_level != SOL_SOCKET ||
511 cmp->cmsg_type != SCM_CREDS) 513 cmp->cmsg_type != SCM_CREDS)
512 goto fatal_err; 514 goto fatal_err;
513 515
514 sc = (struct sockcred *)(void *)CMSG_DATA(cmp); 516 sc = (struct sockcred *)(void *)CMSG_DATA(cmp);
515 517
516 xprt->xp_p2 = mem_alloc(SOCKCREDSIZE(sc->sc_ngroups)); 518 xprt->xp_p2 = mem_alloc(SOCKCREDSIZE(sc->sc_ngroups));
517 if (xprt->xp_p2 == NULL) 519 if (xprt->xp_p2 == NULL)
518 goto fatal_err; 520 goto fatal_err;
519 521
520 memcpy(xprt->xp_p2, sc, SOCKCREDSIZE(sc->sc_ngroups)); 522 memcpy(xprt->xp_p2, sc, SOCKCREDSIZE(sc->sc_ngroups));
521 free(crmsg); 523 free(crmsg);
522 crmsg = NULL; 524 crmsg = NULL;
523 } 525 }
524 526
525 cfp = (struct cf_conn *)xprt->xp_p1; 527 cfp = (struct cf_conn *)xprt->xp_p1;
526 528
527 if (cfp->nonblock) { 529 if (cfp->nonblock) {
528 len = (int)read(sock, buf, (size_t)len); 530 len = (int)read(sock, buf, (size_t)len);
529 if (len < 0) { 531 if (len < 0) {
530 if (errno == EAGAIN) 532 if (errno == EAGAIN)
531 len = 0; 533 len = 0;
532 else 534 else
533 goto fatal_err; 535 goto fatal_err;
534 } 536 }
535 if (len != 0) 537 if (len != 0)
536 gettimeofday(&cfp->last_recv_time, NULL); 538 gettimeofday(&cfp->last_recv_time, NULL);
537 return len; 539 return len;
538 } 540 }
539 541
540 do { 542 do {
541 pollfd.fd = sock; 543 pollfd.fd = sock;
542 pollfd.events = POLLIN; 544 pollfd.events = POLLIN;
543 switch (pollts(&pollfd, 1, &ts, NULL)) { 545 switch (pollts(&pollfd, 1, &ts, NULL)) {
544 case -1: 546 case -1:
545 if (errno == EINTR) { 547 if (errno == EINTR) {
546 continue; 548 continue;
547 } 549 }
548 /*FALLTHROUGH*/ 550 /*FALLTHROUGH*/
549 case 0: 551 case 0:
550 goto fatal_err; 552 goto fatal_err;
551 553
552 default: 554 default:
553 break; 555 break;
554 } 556 }
555 } while ((pollfd.revents & POLLIN) == 0); 557 } while ((pollfd.revents & POLLIN) == 0);
556 558
557 if ((len = (int)read(sock, buf, (size_t)len)) > 0) { 559 if ((len = (int)read(sock, buf, (size_t)len)) > 0) {
558 gettimeofday(&cfp->last_recv_time, NULL); 560 gettimeofday(&cfp->last_recv_time, NULL);
559 return len; 561 return len;
560 } 562 }
561 563
562fatal_err: 564fatal_err:
563 if (crmsg != NULL) 565 if (crmsg != NULL)
564 free(crmsg); 566 free(crmsg);
565 ((struct cf_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED; 567 ((struct cf_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
566 return -1; 568 return -1;
567} 569}
568 570
569/* 571/*
570 * writes data to the tcp connection. 572 * writes data to the tcp connection.
571 * Any error is fatal and the connection is closed. 573 * Any error is fatal and the connection is closed.
572 */ 574 */
573static int 575static int
574write_vc(caddr_t xprtp, caddr_t buf, int len) 576write_vc(caddr_t xprtp, caddr_t buf, int len)
575{ 577{
576 SVCXPRT *xprt; 578 SVCXPRT *xprt;
577 int i, cnt; 579 int i, cnt;
578 struct cf_conn *cd; 580 struct cf_conn *cd;
579 struct timeval tv0, tv1; 581 struct timeval tv0, tv1;
580 582
581 xprt = (SVCXPRT *)(void *)xprtp; 583 xprt = (SVCXPRT *)(void *)xprtp;
582 _DIAGASSERT(xprt != NULL); 584 _DIAGASSERT(xprt != NULL);
583 585
584 cd = (struct cf_conn *)xprt->xp_p1; 586 cd = (struct cf_conn *)xprt->xp_p1;
585 587
586 if (cd->nonblock) 588 if (cd->nonblock)
587 gettimeofday(&tv0, NULL); 589 gettimeofday(&tv0, NULL);
588 590
589 for (cnt = len; cnt > 0; cnt -= i, buf += i) { 591 for (cnt = len; cnt > 0; cnt -= i, buf += i) {
590 if ((i = (int)write(xprt->xp_fd, buf, (size_t)cnt)) < 0) { 592 if ((i = (int)write(xprt->xp_fd, buf, (size_t)cnt)) < 0) {
591 if (errno != EAGAIN || !cd->nonblock) { 593 if (errno != EAGAIN || !cd->nonblock) {
592 cd->strm_stat = XPRT_DIED; 594 cd->strm_stat = XPRT_DIED;
593 return -1; 595 return -1;
594 } 596 }
595 if (cd->nonblock) { 597 if (cd->nonblock) {
596 /* 598 /*
597 * For non-blocking connections, do not 599 * For non-blocking connections, do not
598 * take more than 2 seconds writing the 600 * take more than 2 seconds writing the
599 * data out. 601 * data out.
600 * 602 *
601 * XXX 2 is an arbitrary amount. 603 * XXX 2 is an arbitrary amount.
602 */ 604 */
603 gettimeofday(&tv1, NULL); 605 gettimeofday(&tv1, NULL);
604 if (tv1.tv_sec - tv0.tv_sec >= 2) { 606 if (tv1.tv_sec - tv0.tv_sec >= 2) {
605 cd->strm_stat = XPRT_DIED; 607 cd->strm_stat = XPRT_DIED;
606 return -1; 608 return -1;
607 } 609 }
608 } 610 }
609 i = 0; 611 i = 0;
610 } 612 }
611 } 613 }
612 return len; 614 return len;
613} 615}
614 616
615static enum xprt_stat 617static enum xprt_stat
616svc_vc_stat(SVCXPRT *xprt) 618svc_vc_stat(SVCXPRT *xprt)
617{ 619{
618 struct cf_conn *cd; 620 struct cf_conn *cd;
619 621
620 _DIAGASSERT(xprt != NULL); 622 _DIAGASSERT(xprt != NULL);
621 623
622 cd = (struct cf_conn *)(xprt->xp_p1); 624 cd = (struct cf_conn *)(xprt->xp_p1);
623 625
624 if (cd->strm_stat == XPRT_DIED) 626 if (cd->strm_stat == XPRT_DIED)
625 return XPRT_DIED; 627 return XPRT_DIED;
626 if (! xdrrec_eof(&(cd->xdrs))) 628 if (! xdrrec_eof(&(cd->xdrs)))
627 return XPRT_MOREREQS; 629 return XPRT_MOREREQS;
628 return XPRT_IDLE; 630 return XPRT_IDLE;
629} 631}
630 632
631static bool_t 633static bool_t
632svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg) 634svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg)
633{ 635{
634 struct cf_conn *cd; 636 struct cf_conn *cd;
635 XDR *xdrs; 637 XDR *xdrs;
636 638
637 _DIAGASSERT(xprt != NULL); 639 _DIAGASSERT(xprt != NULL);
638 _DIAGASSERT(msg != NULL); 640 _DIAGASSERT(msg != NULL);
639 641
640 cd = (struct cf_conn *)(xprt->xp_p1); 642 cd = (struct cf_conn *)(xprt->xp_p1);
641 xdrs = &(cd->xdrs); 643 xdrs = &(cd->xdrs);
642 644
643 if (cd->nonblock) { 645 if (cd->nonblock) {
644 if (!__xdrrec_getrec(xdrs, &cd->strm_stat, TRUE)) 646 if (!__xdrrec_getrec(xdrs, &cd->strm_stat, TRUE))
645 return FALSE; 647 return FALSE;
646 } 648 }
647 649
648 xdrs->x_op = XDR_DECODE; 650 xdrs->x_op = XDR_DECODE;
649 (void)xdrrec_skiprecord(xdrs); 651 (void)xdrrec_skiprecord(xdrs);
650 652
651 if (xdr_callmsg(xdrs, msg)) { 653 if (xdr_callmsg(xdrs, msg)) {
652 cd->x_id = msg->rm_xid; 654 cd->x_id = msg->rm_xid;
653 return TRUE; 655 return TRUE;
654 } 656 }
655 cd->strm_stat = XPRT_DIED; 657 cd->strm_stat = XPRT_DIED;
656 return FALSE; 658 return FALSE;
657} 659}
658 660
659static bool_t 661static bool_t
660svc_vc_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) 662svc_vc_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
661{ 663{
662 664
663 _DIAGASSERT(xprt != NULL); 665 _DIAGASSERT(xprt != NULL);
664 /* args_ptr may be NULL */ 666 /* args_ptr may be NULL */
665 667
666 return (*xdr_args)(&(((struct cf_conn *)(xprt->xp_p1))->xdrs), 668 return (*xdr_args)(&(((struct cf_conn *)(xprt->xp_p1))->xdrs),
667 args_ptr); 669 args_ptr);
668} 670}
669 671
670static bool_t 672static bool_t
671svc_vc_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) 673svc_vc_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
672{ 674{
673 XDR *xdrs; 675 XDR *xdrs;
674 676
675 _DIAGASSERT(xprt != NULL); 677 _DIAGASSERT(xprt != NULL);
676 /* args_ptr may be NULL */ 678 /* args_ptr may be NULL */
677 679
678 xdrs = &(((struct cf_conn *)(xprt->xp_p1))->xdrs); 680 xdrs = &(((struct cf_conn *)(xprt->xp_p1))->xdrs);
679 681
680 xdrs->x_op = XDR_FREE; 682 xdrs->x_op = XDR_FREE;
681 return (*xdr_args)(xdrs, args_ptr); 683 return (*xdr_args)(xdrs, args_ptr);
682} 684}
683 685
684static bool_t 686static bool_t
685svc_vc_reply(SVCXPRT *xprt, struct rpc_msg *msg) 687svc_vc_reply(SVCXPRT *xprt, struct rpc_msg *msg)
686{ 688{
687 struct cf_conn *cd; 689 struct cf_conn *cd;
688 XDR *xdrs; 690 XDR *xdrs;
689 bool_t rstat; 691 bool_t rstat;
690 692
691 _DIAGASSERT(xprt != NULL); 693 _DIAGASSERT(xprt != NULL);
692 _DIAGASSERT(msg != NULL); 694 _DIAGASSERT(msg != NULL);
693 695
694 cd = (struct cf_conn *)(xprt->xp_p1); 696 cd = (struct cf_conn *)(xprt->xp_p1);
695 xdrs = &(cd->xdrs); 697 xdrs = &(cd->xdrs);
696 698
697 xdrs->x_op = XDR_ENCODE; 699 xdrs->x_op = XDR_ENCODE;
698 msg->rm_xid = cd->x_id; 700 msg->rm_xid = cd->x_id;
699 rstat = xdr_replymsg(xdrs, msg); 701 rstat = xdr_replymsg(xdrs, msg);
700 (void)xdrrec_endofrecord(xdrs, TRUE); 702 (void)xdrrec_endofrecord(xdrs, TRUE);
701 return rstat; 703 return rstat;
702} 704}
703 705
704static void 706static void
705svc_vc_ops(SVCXPRT *xprt) 707svc_vc_ops(SVCXPRT *xprt)
706{ 708{
707 static struct xp_ops ops; 709 static struct xp_ops ops;
708 static struct xp_ops2 ops2; 710 static struct xp_ops2 ops2;
709#ifdef _REENTRANT 711#ifdef _REENTRANT
710 extern mutex_t ops_lock; 712 extern mutex_t ops_lock;
711#endif 713#endif
712 714
713/* VARIABLES PROTECTED BY ops_lock: ops, ops2 */ 715/* VARIABLES PROTECTED BY ops_lock: ops, ops2 */
714 716
715 mutex_lock(&ops_lock); 717 mutex_lock(&ops_lock);
716 if (ops.xp_recv == NULL) { 718 if (ops.xp_recv == NULL) {
717 ops.xp_recv = svc_vc_recv; 719 ops.xp_recv = svc_vc_recv;
718 ops.xp_stat = svc_vc_stat; 720 ops.xp_stat = svc_vc_stat;
719 ops.xp_getargs = svc_vc_getargs; 721 ops.xp_getargs = svc_vc_getargs;
720 ops.xp_reply = svc_vc_reply; 722 ops.xp_reply = svc_vc_reply;
721 ops.xp_freeargs = svc_vc_freeargs; 723 ops.xp_freeargs = svc_vc_freeargs;
722 ops.xp_destroy = svc_vc_destroy; 724 ops.xp_destroy = svc_vc_destroy;
723 ops2.xp_control = svc_vc_control; 725 ops2.xp_control = svc_vc_control;
724 } 726 }
725 xprt->xp_ops = &ops; 727 xprt->xp_ops = &ops;
726 xprt->xp_ops2 = &ops2; 728 xprt->xp_ops2 = &ops2;
727 mutex_unlock(&ops_lock); 729 mutex_unlock(&ops_lock);
728} 730}
729 731
730static void 732static void
731svc_vc_rendezvous_ops(SVCXPRT *xprt) 733svc_vc_rendezvous_ops(SVCXPRT *xprt)
732{ 734{
733 static struct xp_ops ops; 735 static struct xp_ops ops;
734 static struct xp_ops2 ops2; 736 static struct xp_ops2 ops2;
735#ifdef _REENTRANT 737#ifdef _REENTRANT
736 extern mutex_t ops_lock; 738 extern mutex_t ops_lock;
737#endif 739#endif
738 mutex_lock(&ops_lock); 740 mutex_lock(&ops_lock);
739 if (ops.xp_recv == NULL) { 741 if (ops.xp_recv == NULL) {
740 ops.xp_recv = rendezvous_request; 742 ops.xp_recv = rendezvous_request;
741 ops.xp_stat = rendezvous_stat; 743 ops.xp_stat = rendezvous_stat;
742 ops.xp_getargs = 744 ops.xp_getargs =
743 (bool_t (*)(SVCXPRT *, xdrproc_t, caddr_t))abort; 745 (bool_t (*)(SVCXPRT *, xdrproc_t, caddr_t))abort;
744 ops.xp_reply = 746 ops.xp_reply =
745 (bool_t (*)(SVCXPRT *, struct rpc_msg *))abort; 747 (bool_t (*)(SVCXPRT *, struct rpc_msg *))abort;
746 ops.xp_freeargs = 748 ops.xp_freeargs =
747 (bool_t (*)(SVCXPRT *, xdrproc_t, caddr_t))abort; 749 (bool_t (*)(SVCXPRT *, xdrproc_t, caddr_t))abort;
748 ops.xp_destroy = svc_vc_destroy; 750 ops.xp_destroy = svc_vc_destroy;
749 ops2.xp_control = svc_vc_rendezvous_control; 751 ops2.xp_control = svc_vc_rendezvous_control;
750 } 752 }
751 xprt->xp_ops = &ops; 753 xprt->xp_ops = &ops;
752 xprt->xp_ops2 = &ops2; 754 xprt->xp_ops2 = &ops2;
753 mutex_unlock(&ops_lock); 755 mutex_unlock(&ops_lock);
754} 756}
755 757
756/* 758/*
757 * Destroy xprts that have not have had any activity in 'timeout' seconds. 759 * Destroy xprts that have not have had any activity in 'timeout' seconds.
758 * If 'cleanblock' is true, blocking connections (the default) are also 760 * If 'cleanblock' is true, blocking connections (the default) are also
759 * cleaned. If timeout is 0, the least active connection is picked. 761 * cleaned. If timeout is 0, the least active connection is picked.
760 */ 762 */
761bool_t 763bool_t
762__svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock) 764__svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock)
763{ 765{
764 int i, ncleaned, fdmax; 766 int i, ncleaned, *fdmax;
765 SVCXPRT *xprt, *least_active; 767 SVCXPRT *xprt, *least_active;
766 struct timeval tv, tdiff, tmax; 768 struct timeval tv, tdiff, tmax;
767 struct cf_conn *cd; 769 struct cf_conn *cd;
768 770
769 gettimeofday(&tv, NULL); 771 gettimeofday(&tv, NULL);
770 tmax.tv_sec = tmax.tv_usec = 0; 772 tmax.tv_sec = tmax.tv_usec = 0;
771 least_active = NULL; 773 least_active = NULL;
772 rwlock_wrlock(&svc_fd_lock); 774 rwlock_wrlock(&svc_fd_lock);
773 fdmax = *svc_fdset_getmax(); 775 fdmax = svc_fdset_getmax();
774 for (i = ncleaned = 0; i <= fdmax; i++) { 776 if (fdmax == NULL)
775 if (!svc_fdset_isset(i)) 777 return FALSE;
 778 for (i = ncleaned = 0; i <= *fdmax; i++) {
 779 switch (svc_fdset_isset(i)) {
 780 case 0:
 781 case -1:
776 continue; 782 continue;
 783 default:
 784 break;
 785 }
777 786
778 xprt = __svc_xports[i]; 787 xprt = __svc_xports[i];
779 if (xprt == NULL || xprt->xp_ops == NULL || 788 if (xprt == NULL || xprt->xp_ops == NULL ||
780 xprt->xp_ops->xp_recv != svc_vc_recv) 789 xprt->xp_ops->xp_recv != svc_vc_recv)
781 continue; 790 continue;
782 791
783 cd = (struct cf_conn *)xprt->xp_p1; 792 cd = (struct cf_conn *)xprt->xp_p1;
784 if (!cleanblock && !cd->nonblock) 793 if (!cleanblock && !cd->nonblock)
785 continue; 794 continue;
786 795
787 if (timeout == 0) { 796 if (timeout == 0) {
788 timersub(&tv, &cd->last_recv_time, &tdiff); 797 timersub(&tv, &cd->last_recv_time, &tdiff);
789 if (timercmp(&tdiff, &tmax, >)) { 798 if (timercmp(&tdiff, &tmax, >)) {
790 tmax = tdiff; 799 tmax = tdiff;
791 least_active = xprt; 800 least_active = xprt;
792 } 801 }
793 continue; 802 continue;
794 } 803 }
795 804
796 if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) { 805 if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) {
797 __xprt_unregister_unlocked(xprt); 806 __xprt_unregister_unlocked(xprt);
798 __svc_vc_dodestroy(xprt); 807 __svc_vc_dodestroy(xprt);
799 ncleaned++; 808 ncleaned++;
800 } 809 }
801 } 810 }
802 if (timeout == 0 && least_active != NULL) { 811 if (timeout == 0 && least_active != NULL) {
803 __xprt_unregister_unlocked(least_active); 812 __xprt_unregister_unlocked(least_active);
804 __svc_vc_dodestroy(least_active); 813 __svc_vc_dodestroy(least_active);
805 ncleaned++; 814 ncleaned++;
806 } 815 }
807 rwlock_unlock(&svc_fd_lock); 816 rwlock_unlock(&svc_fd_lock);
808 return ncleaned > 0 ? TRUE : FALSE; 817 return ncleaned > 0 ? TRUE : FALSE;
809} 818}