check for errors and recover instead of core-dumping.diff -r1.35 -r1.36 src/lib/libc/rpc/svc.c
(christos)
--- 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 | |
37 | static char *sccsid = "@(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro"; | 37 | static char *sccsid = "@(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro"; | |
38 | static char *sccsid = "@(#)svc.c 2.4 88/08/11 4.0 RPCSRC"; | 38 | static 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 */ | |
94 | SVCXPRT **__svc_xports; | 94 | SVCXPRT **__svc_xports; | |
95 | int __svc_maxxports; | 95 | int __svc_maxxports; | |
96 | int __svc_maxrec; | 96 | int __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 | */ | |
111 | static struct svc_callout { | 111 | static 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 | |
120 | extern rwlock_t svc_lock; | 120 | extern rwlock_t svc_lock; | |
121 | extern rwlock_t svc_fd_lock; | 121 | extern rwlock_t svc_fd_lock; | |
122 | #endif | 122 | #endif | |
123 | 123 | |||
124 | static struct svc_callout *svc_find(rpcprog_t, rpcvers_t, | 124 | static struct svc_callout *svc_find(rpcprog_t, rpcvers_t, | |
125 | struct svc_callout **, char *); | 125 | struct svc_callout **, char *); | |
126 | static void __xprt_do_unregister(SVCXPRT *xprt, bool_t dolock); | 126 | static void __xprt_do_unregister(SVCXPRT *xprt, bool_t dolock); | |
127 | 127 | |||
128 | /* *************** SVCXPRT related stuff **************** */ | 128 | /* *************** SVCXPRT related stuff **************** */ | |
129 | 129 | |||
130 | static bool_t | 130 | static bool_t | |
131 | xprt_alloc(int sock) | 131 | xprt_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 | */ | |
167 | bool_t | 167 | bool_t | |
168 | xprt_register(SVCXPRT *xprt) | 168 | xprt_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 | |||
187 | out: | 188 | out: | |
188 | rwlock_unlock(&svc_fd_lock); | 189 | rwlock_unlock(&svc_fd_lock); | |
189 | return (FALSE); | 190 | return (FALSE); | |
190 | } | 191 | } | |
191 | 192 | |||
192 | void | 193 | void | |
193 | xprt_unregister(SVCXPRT *xprt) | 194 | xprt_unregister(SVCXPRT *xprt) | |
194 | { | 195 | { | |
195 | __xprt_do_unregister(xprt, TRUE); | 196 | __xprt_do_unregister(xprt, TRUE); | |
196 | } | 197 | } | |
197 | 198 | |||
198 | void | 199 | void | |
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 | */ | |
207 | static void | 208 | static 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; | |
231 | clr: | 232 | clr: | |
232 | svc_fdset_clr(sock); | 233 | svc_fdset_clr(sock); | |
233 | out: | 234 | out: | |
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 | */ | |
243 | bool_t | 244 | bool_t | |
244 | svc_reg(SVCXPRT *xprt, const rpcprog_t prog, const rpcvers_t vers, | 245 | svc_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 | |||
307 | rpcb_it: | 308 | rpcb_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 | */ | |
321 | void | 322 | void | |
322 | svc_unreg(const rpcprog_t prog, const rpcvers_t vers) | 323 | svc_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 | */ | |
352 | bool_t | 353 | bool_t | |
353 | svc_register(SVCXPRT *xprt, u_long prog, u_long vers, | 354 | svc_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; | |
377 | pmap_it: | 378 | pmap_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 | */ | |
388 | void | 389 | void | |
389 | svc_unregister(u_long prog, u_long vers) | 390 | svc_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 | */ | |
413 | static struct svc_callout * | 414 | static struct svc_callout * | |
414 | svc_find(rpcprog_t prog, rpcvers_t vers, struct svc_callout **prev, char *netid) | 415 | svc_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 | */ | |
438 | bool_t | 439 | bool_t | |
439 | svc_sendreply(SVCXPRT *xprt, xdrproc_t xdr_results, const char *xdr_location) | 440 | svc_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 | */ | |
457 | void | 458 | void | |
458 | svcerr_noproc(SVCXPRT *xprt) | 459 | svcerr_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 | */ | |
474 | void | 475 | void | |
475 | svcerr_decode(SVCXPRT *xprt) | 476 | svcerr_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 | */ | |
491 | void | 492 | void | |
492 | svcerr_systemerr(SVCXPRT *xprt) | 493 | svcerr_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 | */ | |
512 | void | 513 | void | |
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 | |||
523 | void | 524 | void | |
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 | |||
534 | void | 535 | void | |
535 | svc_versquiet(SVCXPRT *xprt) | 536 | svc_versquiet(SVCXPRT *xprt) | |
536 | { | 537 | { | |
537 | __svc_versquiet_on(xprt); | 538 | __svc_versquiet_on(xprt); | |
538 | } | 539 | } | |
539 | 540 | |||
540 | int | 541 | int | |
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 | */ | |
553 | void | 554 | void | |
554 | svcerr_auth(SVCXPRT *xprt, enum auth_stat why) | 555 | svcerr_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 | */ | |
570 | void | 571 | void | |
571 | svcerr_weakauth(SVCXPRT *xprt) | 572 | svcerr_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 | */ | |
582 | void | 583 | void | |
583 | svcerr_noprog(SVCXPRT *xprt) | 584 | svcerr_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 | */ | |
599 | void | 600 | void | |
600 | svcerr_progvers(SVCXPRT *xprt, rpcvers_t low_vers, rpcvers_t high_vers) | 601 | svcerr_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 | |||
633 | void | 634 | void | |
634 | svc_getreq(int rdfds) | 635 | svc_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 | |||
643 | void | 646 | void | |
644 | svc_getreqset2(fd_set *readfds, int maxsize) | 647 | svc_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 | |||
662 | void | 665 | void | |
663 | svc_getreqset(fd_set *readfds) | 666 | svc_getreqset(fd_set *readfds) | |
664 | { | 667 | { | |
665 | svc_getreqset2(readfds, FD_SETSIZE); | 668 | svc_getreqset2(readfds, FD_SETSIZE); | |
666 | } | 669 | } | |
667 | 670 | |||
668 | void | 671 | void | |
669 | svc_getreq_common(int fd) | 672 | svc_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); | |
746 | call_done: | 749 | call_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 | |||
755 | void | 758 | void | |
756 | svc_getreq_poll(struct pollfd *pfdp, int pollretval) | 759 | svc_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 | |||
790 | bool_t | 793 | bool_t | |
791 | rpc_control(int what, void *arg) | 794 | rpc_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 | } |
--- 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 | |
37 | static char *sccsid = "@(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro"; | 37 | static char *sccsid = "@(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro"; | |
38 | static char *sccsid = "@(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC"; | 38 | static 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 | |||
67 | void | 67 | void | |
68 | svc_run(void) | 68 | svc_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 | } | |
120 | out: | 126 | out: | |
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 | */ | |
129 | void | 135 | void | |
130 | svc_exit(void) | 136 | svc_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 | } |
--- 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 | |
37 | static char *sccsid = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro"; | 37 | static char *sccsid = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro"; | |
38 | static char *sccsid = "@(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC"; | 38 | static 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 | |
82 | extern rwlock_t svc_fd_lock; | 82 | extern rwlock_t svc_fd_lock; | |
83 | #endif | 83 | #endif | |
84 | 84 | |||
85 | static SVCXPRT *makefd_xprt(int, u_int, u_int); | 85 | static SVCXPRT *makefd_xprt(int, u_int, u_int); | |
86 | static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *); | 86 | static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *); | |
87 | static enum xprt_stat rendezvous_stat(SVCXPRT *); | 87 | static enum xprt_stat rendezvous_stat(SVCXPRT *); | |
88 | static void svc_vc_destroy(SVCXPRT *); | 88 | static void svc_vc_destroy(SVCXPRT *); | |
89 | static void __svc_vc_dodestroy(SVCXPRT *); | 89 | static void __svc_vc_dodestroy(SVCXPRT *); | |
90 | static int read_vc(caddr_t, caddr_t, int); | 90 | static int read_vc(caddr_t, caddr_t, int); | |
91 | static int write_vc(caddr_t, caddr_t, int); | 91 | static int write_vc(caddr_t, caddr_t, int); | |
92 | static enum xprt_stat svc_vc_stat(SVCXPRT *); | 92 | static enum xprt_stat svc_vc_stat(SVCXPRT *); | |
93 | static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *); | 93 | static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *); | |
94 | static bool_t svc_vc_getargs(SVCXPRT *, xdrproc_t, caddr_t); | 94 | static bool_t svc_vc_getargs(SVCXPRT *, xdrproc_t, caddr_t); | |
95 | static bool_t svc_vc_freeargs(SVCXPRT *, xdrproc_t, caddr_t); | 95 | static bool_t svc_vc_freeargs(SVCXPRT *, xdrproc_t, caddr_t); | |
96 | static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *); | 96 | static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *); | |
97 | static void svc_vc_rendezvous_ops(SVCXPRT *); | 97 | static void svc_vc_rendezvous_ops(SVCXPRT *); | |
98 | static void svc_vc_ops(SVCXPRT *); | 98 | static void svc_vc_ops(SVCXPRT *); | |
99 | static bool_t svc_vc_control(SVCXPRT *, const u_int, void *); | 99 | static bool_t svc_vc_control(SVCXPRT *, const u_int, void *); | |
100 | static bool_t svc_vc_rendezvous_control(SVCXPRT *, const u_int, void *); | 100 | static bool_t svc_vc_rendezvous_control(SVCXPRT *, const u_int, void *); | |
101 | 101 | |||
102 | struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */ | 102 | struct 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 | |||
108 | struct cf_conn { /* kept in xprt->xp_p1 for actual connection */ | 108 | struct 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 | */ | |
136 | SVCXPRT * | 136 | SVCXPRT * | |
137 | svc_vc_create(int fd, u_int sendsize, u_int recvsize) | 137 | svc_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; | |
197 | cleanup_svc_vc_create: | 197 | cleanup_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 | */ | |
209 | SVCXPRT * | 209 | SVCXPRT * | |
210 | svc_fd_create(int fd, u_int sendsize, u_int recvsize) | 210 | svc_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 | |||
256 | freedata: | 256 | freedata: | |
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 | |||
263 | static SVCXPRT * | 263 | static SVCXPRT * | |
264 | makefd_xprt(int fd, u_int sendsize, u_int recvsize) | 264 | makefd_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 | |||
296 | outofmem: | 296 | outofmem: | |
297 | warn("svc_tcp: makefd_xprt"); | 297 | warn("svc_tcp: makefd_xprt"); | |
298 | out: | 298 | out: | |
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*/ | |
305 | static bool_t | 305 | static bool_t | |
306 | rendezvous_request(SVCXPRT *xprt, struct rpc_msg *msg) | 306 | rendezvous_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; | |
320 | again: | 320 | again: | |
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 */ | |
381 | out: | 383 | out: | |
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*/ | |
387 | static enum xprt_stat | 389 | static enum xprt_stat | |
388 | rendezvous_stat(SVCXPRT *xprt) | 390 | rendezvous_stat(SVCXPRT *xprt) | |
389 | { | 391 | { | |
390 | 392 | |||
391 | return XPRT_IDLE; | 393 | return XPRT_IDLE; | |
392 | } | 394 | } | |
393 | 395 | |||
394 | static void | 396 | static void | |
395 | svc_vc_destroy(SVCXPRT *xprt) | 397 | svc_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 | |||
403 | static void | 405 | static 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*/ | |
435 | static bool_t | 437 | static bool_t | |
436 | svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in) | 438 | svc_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*/ | |
442 | static bool_t | 444 | static bool_t | |
443 | svc_vc_rendezvous_control(SVCXPRT *xprt, const u_int rq, void *in) | 445 | svc_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 | */ | |
470 | static int | 472 | static int | |
471 | read_vc(caddr_t xprtp, caddr_t buf, int len) | 473 | read_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 | |||
562 | fatal_err: | 564 | fatal_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 | */ | |
573 | static int | 575 | static int | |
574 | write_vc(caddr_t xprtp, caddr_t buf, int len) | 576 | write_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 | |||
615 | static enum xprt_stat | 617 | static enum xprt_stat | |
616 | svc_vc_stat(SVCXPRT *xprt) | 618 | svc_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 | |||
631 | static bool_t | 633 | static bool_t | |
632 | svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg) | 634 | svc_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 | |||
659 | static bool_t | 661 | static bool_t | |
660 | svc_vc_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) | 662 | svc_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 | |||
670 | static bool_t | 672 | static bool_t | |
671 | svc_vc_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) | 673 | svc_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 | |||
684 | static bool_t | 686 | static bool_t | |
685 | svc_vc_reply(SVCXPRT *xprt, struct rpc_msg *msg) | 687 | svc_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 | |||
704 | static void | 706 | static void | |
705 | svc_vc_ops(SVCXPRT *xprt) | 707 | svc_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 | |||
730 | static void | 732 | static void | |
731 | svc_vc_rendezvous_ops(SVCXPRT *xprt) | 733 | svc_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 | */ | |
761 | bool_t | 763 | bool_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 | } |