]>
Commit | Line | Data |
---|---|---|
28f540f4 RM |
1 | /* |
2 | * svc.c, Server-side remote procedure call interface. | |
3 | * | |
4 | * There are two sets of procedures here. The xprt routines are | |
5 | * for handling transport handles. The svc routines handle the | |
6 | * list of service routines. | |
bfff8b1b | 7 | * Copyright (C) 2002-2017 Free Software Foundation, Inc. |
14bc93a9 JL |
8 | * This file is part of the GNU C Library. |
9 | * Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. | |
10 | * | |
11 | * The GNU C Library is free software; you can redistribute it and/or | |
12 | * modify it under the terms of the GNU Lesser General Public | |
13 | * License as published by the Free Software Foundation; either | |
14 | * version 2.1 of the License, or (at your option) any later version. | |
15 | * | |
16 | * The GNU C Library is distributed in the hope that it will be useful, | |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
19 | * Lesser General Public License for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU Lesser General Public | |
22 | * License along with the GNU C Library; if not, see | |
23 | * <http://www.gnu.org/licenses/>. | |
28f540f4 | 24 | * |
a7ab6ec8 UD |
25 | * Copyright (c) 2010, Oracle America, Inc. |
26 | * | |
27 | * Redistribution and use in source and binary forms, with or without | |
28 | * modification, are permitted provided that the following conditions are | |
29 | * met: | |
30 | * | |
31 | * * Redistributions of source code must retain the above copyright | |
32 | * notice, this list of conditions and the following disclaimer. | |
33 | * * Redistributions in binary form must reproduce the above | |
34 | * copyright notice, this list of conditions and the following | |
35 | * disclaimer in the documentation and/or other materials | |
36 | * provided with the distribution. | |
37 | * * Neither the name of the "Oracle America, Inc." nor the names of its | |
38 | * contributors may be used to endorse or promote products derived | |
39 | * from this software without specific prior written permission. | |
40 | * | |
41 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
42 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
43 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
44 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
45 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |
46 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
47 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | |
48 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
49 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
50 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
51 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
52 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
28f540f4 RM |
53 | */ |
54 | ||
e7fd8a39 | 55 | #include <errno.h> |
bdb04ee8 | 56 | #include <unistd.h> |
28f540f4 | 57 | #include <rpc/rpc.h> |
e7fd8a39 | 58 | #include <rpc/svc.h> |
28f540f4 | 59 | #include <rpc/pmap_clnt.h> |
bdb04ee8 | 60 | #include <sys/poll.h> |
14bc93a9 | 61 | #include <time.h> |
28f540f4 | 62 | |
f1e4a4a4 | 63 | #ifdef _RPC_THREAD_SAFE_ |
1bc1a2b9 | 64 | #define xports RPC_THREAD_VARIABLE(svc_xports_s) |
f1e4a4a4 | 65 | #else |
28f540f4 | 66 | static SVCXPRT **xports; |
f1e4a4a4 | 67 | #endif |
28f540f4 RM |
68 | |
69 | #define NULL_SVC ((struct svc_callout *)0) | |
e7fd8a39 | 70 | #define RQCRED_SIZE 400 /* this size is excessive */ |
28f540f4 | 71 | |
bdb04ee8 UD |
72 | /* The services list |
73 | Each entry represents a set of procedures (an rpc program). | |
74 | The dispatch routine takes request structs and runs the | |
75 | appropriate procedure. */ | |
f1e4a4a4 | 76 | struct svc_callout { |
bdb04ee8 UD |
77 | struct svc_callout *sc_next; |
78 | rpcprog_t sc_prog; | |
79 | rpcvers_t sc_vers; | |
80 | void (*sc_dispatch) (struct svc_req *, SVCXPRT *); | |
71894681 | 81 | bool_t sc_mapped; |
f1e4a4a4 UD |
82 | }; |
83 | #ifdef _RPC_THREAD_SAFE_ | |
1bc1a2b9 | 84 | #define svc_head RPC_THREAD_VARIABLE(svc_head_s) |
f1e4a4a4 UD |
85 | #else |
86 | static struct svc_callout *svc_head; | |
87 | #endif | |
28f540f4 RM |
88 | |
89 | /* *************** SVCXPRT related stuff **************** */ | |
90 | ||
bdb04ee8 | 91 | /* Activate a transport handle. */ |
28f540f4 | 92 | void |
e7fd8a39 | 93 | xprt_register (SVCXPRT *xprt) |
28f540f4 | 94 | { |
e7fd8a39 | 95 | register int sock = xprt->xp_sock; |
bdb04ee8 | 96 | register int i; |
28f540f4 | 97 | |
e7fd8a39 UD |
98 | if (xports == NULL) |
99 | { | |
ed6b0fe7 BH |
100 | xports = (SVCXPRT **) calloc (_rpc_dtablesize (), sizeof (SVCXPRT *)); |
101 | if (xports == NULL) /* Don't add handle */ | |
bdb04ee8 | 102 | return; |
e7fd8a39 | 103 | } |
bdb04ee8 | 104 | |
e7fd8a39 UD |
105 | if (sock < _rpc_dtablesize ()) |
106 | { | |
d1dddedf UD |
107 | struct pollfd *new_svc_pollfd; |
108 | ||
e7fd8a39 | 109 | xports[sock] = xprt; |
bdb04ee8 UD |
110 | if (sock < FD_SETSIZE) |
111 | FD_SET (sock, &svc_fdset); | |
112 | ||
113 | /* Check if we have an empty slot */ | |
114 | for (i = 0; i < svc_max_pollfd; ++i) | |
115 | if (svc_pollfd[i].fd == -1) | |
116 | { | |
117 | svc_pollfd[i].fd = sock; | |
118 | svc_pollfd[i].events = (POLLIN | POLLPRI | | |
119 | POLLRDNORM | POLLRDBAND); | |
120 | return; | |
121 | } | |
122 | ||
d1dddedf UD |
123 | new_svc_pollfd = (struct pollfd *) realloc (svc_pollfd, |
124 | sizeof (struct pollfd) | |
125 | * (svc_max_pollfd + 1)); | |
126 | if (new_svc_pollfd == NULL) /* Out of memory */ | |
bdb04ee8 | 127 | return; |
d1dddedf UD |
128 | svc_pollfd = new_svc_pollfd; |
129 | ++svc_max_pollfd; | |
bdb04ee8 UD |
130 | |
131 | svc_pollfd[svc_max_pollfd - 1].fd = sock; | |
132 | svc_pollfd[svc_max_pollfd - 1].events = (POLLIN | POLLPRI | | |
133 | POLLRDNORM | POLLRDBAND); | |
e7fd8a39 | 134 | } |
28f540f4 | 135 | } |
021db4be | 136 | libc_hidden_nolink_sunrpc (xprt_register, GLIBC_2_0) |
28f540f4 | 137 | |
bdb04ee8 | 138 | /* De-activate a transport handle. */ |
28f540f4 | 139 | void |
bdb04ee8 | 140 | xprt_unregister (SVCXPRT *xprt) |
c4029823 | 141 | { |
e7fd8a39 | 142 | register int sock = xprt->xp_sock; |
bdb04ee8 | 143 | register int i; |
28f540f4 | 144 | |
e7fd8a39 UD |
145 | if ((sock < _rpc_dtablesize ()) && (xports[sock] == xprt)) |
146 | { | |
147 | xports[sock] = (SVCXPRT *) 0; | |
bdb04ee8 UD |
148 | |
149 | if (sock < FD_SETSIZE) | |
150 | FD_CLR (sock, &svc_fdset); | |
151 | ||
152 | for (i = 0; i < svc_max_pollfd; ++i) | |
153 | if (svc_pollfd[i].fd == sock) | |
154 | svc_pollfd[i].fd = -1; | |
e7fd8a39 | 155 | } |
28f540f4 | 156 | } |
7b57bfe5 | 157 | #ifdef EXPORT_RPC_SYMBOLS |
cd4c174b | 158 | libc_hidden_def (xprt_unregister) |
7b57bfe5 | 159 | #else |
021db4be | 160 | libc_hidden_nolink_sunrpc (xprt_unregister, GLIBC_2_0) |
7b57bfe5 | 161 | #endif |
28f540f4 RM |
162 | |
163 | ||
164 | /* ********************** CALLOUT list related stuff ************* */ | |
165 | ||
bdb04ee8 UD |
166 | /* Search the callout list for a program number, return the callout |
167 | struct. */ | |
168 | static struct svc_callout * | |
169 | svc_find (rpcprog_t prog, rpcvers_t vers, struct svc_callout **prev) | |
170 | { | |
171 | register struct svc_callout *s, *p; | |
172 | ||
173 | p = NULL_SVC; | |
174 | for (s = svc_head; s != NULL_SVC; s = s->sc_next) | |
175 | { | |
176 | if ((s->sc_prog == prog) && (s->sc_vers == vers)) | |
177 | goto done; | |
178 | p = s; | |
179 | } | |
180 | done: | |
181 | *prev = p; | |
182 | return s; | |
183 | } | |
184 | ||
71894681 UD |
185 | |
186 | static bool_t | |
187 | svc_is_mapped (rpcprog_t prog, rpcvers_t vers) | |
188 | { | |
189 | struct svc_callout *prev; | |
190 | register struct svc_callout *s; | |
191 | s = svc_find (prog, vers, &prev); | |
192 | return s!= NULL_SVC && s->sc_mapped; | |
193 | } | |
194 | ||
195 | ||
bdb04ee8 UD |
196 | /* Add a service program to the callout list. |
197 | The dispatch routine will be called when a rpc request for this | |
198 | program number comes in. */ | |
28f540f4 | 199 | bool_t |
bdb04ee8 UD |
200 | svc_register (SVCXPRT * xprt, rpcprog_t prog, rpcvers_t vers, |
201 | void (*dispatch) (struct svc_req *, SVCXPRT *), | |
202 | rpcproc_t protocol) | |
28f540f4 | 203 | { |
e7fd8a39 UD |
204 | struct svc_callout *prev; |
205 | register struct svc_callout *s; | |
206 | ||
207 | if ((s = svc_find (prog, vers, &prev)) != NULL_SVC) | |
208 | { | |
209 | if (s->sc_dispatch == dispatch) | |
210 | goto pmap_it; /* he is registering another xptr */ | |
211 | return FALSE; | |
212 | } | |
213 | s = (struct svc_callout *) mem_alloc (sizeof (struct svc_callout)); | |
214 | if (s == (struct svc_callout *) 0) | |
bdb04ee8 UD |
215 | return FALSE; |
216 | ||
e7fd8a39 UD |
217 | s->sc_prog = prog; |
218 | s->sc_vers = vers; | |
219 | s->sc_dispatch = dispatch; | |
220 | s->sc_next = svc_head; | |
71894681 | 221 | s->sc_mapped = FALSE; |
e7fd8a39 | 222 | svc_head = s; |
bdb04ee8 | 223 | |
28f540f4 | 224 | pmap_it: |
e7fd8a39 UD |
225 | /* now register the information with the local binder service */ |
226 | if (protocol) | |
71894681 UD |
227 | { |
228 | if (! pmap_set (prog, vers, protocol, xprt->xp_port)) | |
229 | return FALSE; | |
230 | ||
231 | s->sc_mapped = TRUE; | |
232 | } | |
bdb04ee8 | 233 | |
e7fd8a39 | 234 | return TRUE; |
28f540f4 | 235 | } |
7b57bfe5 | 236 | #ifdef EXPORT_RPC_SYMBOLS |
e2ec9b4d | 237 | libc_hidden_def (svc_register) |
7b57bfe5 | 238 | #else |
021db4be | 239 | libc_hidden_nolink_sunrpc (svc_register, GLIBC_2_0) |
7b57bfe5 | 240 | #endif |
28f540f4 | 241 | |
bdb04ee8 | 242 | /* Remove a service program from the callout list. */ |
28f540f4 | 243 | void |
bdb04ee8 | 244 | svc_unregister (rpcprog_t prog, rpcvers_t vers) |
28f540f4 | 245 | { |
e7fd8a39 UD |
246 | struct svc_callout *prev; |
247 | register struct svc_callout *s; | |
248 | ||
249 | if ((s = svc_find (prog, vers, &prev)) == NULL_SVC) | |
250 | return; | |
bdb04ee8 | 251 | |
e7fd8a39 | 252 | if (prev == NULL_SVC) |
bdb04ee8 | 253 | svc_head = s->sc_next; |
e7fd8a39 | 254 | else |
bdb04ee8 UD |
255 | prev->sc_next = s->sc_next; |
256 | ||
e7fd8a39 UD |
257 | s->sc_next = NULL_SVC; |
258 | mem_free ((char *) s, (u_int) sizeof (struct svc_callout)); | |
259 | /* now unregister the information with the local binder service */ | |
71894681 UD |
260 | if (! svc_is_mapped (prog, vers)) |
261 | pmap_unset (prog, vers); | |
28f540f4 | 262 | } |
021db4be | 263 | libc_hidden_nolink_sunrpc (svc_unregister, GLIBC_2_0) |
28f540f4 RM |
264 | |
265 | /* ******************* REPLY GENERATION ROUTINES ************ */ | |
266 | ||
bdb04ee8 | 267 | /* Send a reply to an rpc request */ |
28f540f4 | 268 | bool_t |
bdb04ee8 UD |
269 | svc_sendreply (register SVCXPRT *xprt, xdrproc_t xdr_results, |
270 | caddr_t xdr_location) | |
28f540f4 | 271 | { |
e7fd8a39 UD |
272 | struct rpc_msg rply; |
273 | ||
274 | rply.rm_direction = REPLY; | |
275 | rply.rm_reply.rp_stat = MSG_ACCEPTED; | |
276 | rply.acpted_rply.ar_verf = xprt->xp_verf; | |
277 | rply.acpted_rply.ar_stat = SUCCESS; | |
278 | rply.acpted_rply.ar_results.where = xdr_location; | |
279 | rply.acpted_rply.ar_results.proc = xdr_results; | |
280 | return SVC_REPLY (xprt, &rply); | |
28f540f4 | 281 | } |
7b57bfe5 UD |
282 | #ifdef EXPORT_RPC_SYMBOLS |
283 | libc_hidden_def (svc_sendreply) | |
284 | #else | |
021db4be | 285 | libc_hidden_nolink_sunrpc (svc_sendreply, GLIBC_2_0) |
7b57bfe5 | 286 | #endif |
28f540f4 | 287 | |
bdb04ee8 | 288 | /* No procedure error reply */ |
28f540f4 | 289 | void |
bdb04ee8 | 290 | svcerr_noproc (register SVCXPRT *xprt) |
28f540f4 | 291 | { |
e7fd8a39 | 292 | struct rpc_msg rply; |
28f540f4 | 293 | |
e7fd8a39 UD |
294 | rply.rm_direction = REPLY; |
295 | rply.rm_reply.rp_stat = MSG_ACCEPTED; | |
296 | rply.acpted_rply.ar_verf = xprt->xp_verf; | |
297 | rply.acpted_rply.ar_stat = PROC_UNAVAIL; | |
298 | SVC_REPLY (xprt, &rply); | |
28f540f4 | 299 | } |
7b57bfe5 UD |
300 | #ifdef EXPORT_RPC_SYMBOLS |
301 | libc_hidden_def (svcerr_noproc) | |
302 | #else | |
021db4be | 303 | libc_hidden_nolink_sunrpc (svcerr_noproc, GLIBC_2_0) |
7b57bfe5 | 304 | #endif |
28f540f4 | 305 | |
bdb04ee8 | 306 | /* Can't decode args error reply */ |
28f540f4 | 307 | void |
bdb04ee8 | 308 | svcerr_decode (register SVCXPRT *xprt) |
28f540f4 | 309 | { |
e7fd8a39 | 310 | struct rpc_msg rply; |
28f540f4 | 311 | |
e7fd8a39 UD |
312 | rply.rm_direction = REPLY; |
313 | rply.rm_reply.rp_stat = MSG_ACCEPTED; | |
314 | rply.acpted_rply.ar_verf = xprt->xp_verf; | |
315 | rply.acpted_rply.ar_stat = GARBAGE_ARGS; | |
316 | SVC_REPLY (xprt, &rply); | |
28f540f4 | 317 | } |
7b57bfe5 UD |
318 | #ifdef EXPORT_RPC_SYMBOLS |
319 | libc_hidden_def (svcerr_decode) | |
320 | #else | |
021db4be | 321 | libc_hidden_nolink_sunrpc (svcerr_decode, GLIBC_2_0) |
7b57bfe5 | 322 | #endif |
28f540f4 | 323 | |
bdb04ee8 | 324 | /* Some system error */ |
28f540f4 | 325 | void |
bdb04ee8 | 326 | svcerr_systemerr (register SVCXPRT *xprt) |
28f540f4 | 327 | { |
e7fd8a39 | 328 | struct rpc_msg rply; |
28f540f4 | 329 | |
e7fd8a39 UD |
330 | rply.rm_direction = REPLY; |
331 | rply.rm_reply.rp_stat = MSG_ACCEPTED; | |
332 | rply.acpted_rply.ar_verf = xprt->xp_verf; | |
333 | rply.acpted_rply.ar_stat = SYSTEM_ERR; | |
334 | SVC_REPLY (xprt, &rply); | |
28f540f4 | 335 | } |
7b57bfe5 UD |
336 | #ifdef EXPORT_RPC_SYMBOLS |
337 | libc_hidden_def (svcerr_systemerr) | |
338 | #else | |
021db4be | 339 | libc_hidden_nolink_sunrpc (svcerr_systemerr, GLIBC_2_0) |
7b57bfe5 | 340 | #endif |
28f540f4 | 341 | |
bdb04ee8 | 342 | /* Authentication error reply */ |
28f540f4 | 343 | void |
bdb04ee8 | 344 | svcerr_auth (SVCXPRT *xprt, enum auth_stat why) |
28f540f4 | 345 | { |
e7fd8a39 | 346 | struct rpc_msg rply; |
28f540f4 | 347 | |
e7fd8a39 UD |
348 | rply.rm_direction = REPLY; |
349 | rply.rm_reply.rp_stat = MSG_DENIED; | |
350 | rply.rjcted_rply.rj_stat = AUTH_ERROR; | |
351 | rply.rjcted_rply.rj_why = why; | |
352 | SVC_REPLY (xprt, &rply); | |
28f540f4 | 353 | } |
021db4be | 354 | libc_hidden_nolink_sunrpc (svcerr_auth, GLIBC_2_0) |
28f540f4 | 355 | |
bdb04ee8 | 356 | /* Auth too weak error reply */ |
28f540f4 | 357 | void |
bdb04ee8 | 358 | svcerr_weakauth (SVCXPRT *xprt) |
28f540f4 | 359 | { |
e7fd8a39 | 360 | svcerr_auth (xprt, AUTH_TOOWEAK); |
28f540f4 | 361 | } |
021db4be | 362 | libc_hidden_nolink_sunrpc (svcerr_weakauth, GLIBC_2_0) |
28f540f4 | 363 | |
bdb04ee8 | 364 | /* Program unavailable error reply */ |
c4029823 | 365 | void |
bdb04ee8 | 366 | svcerr_noprog (register SVCXPRT *xprt) |
28f540f4 | 367 | { |
e7fd8a39 | 368 | struct rpc_msg rply; |
28f540f4 | 369 | |
e7fd8a39 UD |
370 | rply.rm_direction = REPLY; |
371 | rply.rm_reply.rp_stat = MSG_ACCEPTED; | |
372 | rply.acpted_rply.ar_verf = xprt->xp_verf; | |
373 | rply.acpted_rply.ar_stat = PROG_UNAVAIL; | |
374 | SVC_REPLY (xprt, &rply); | |
28f540f4 | 375 | } |
021db4be | 376 | libc_hidden_nolink_sunrpc (svcerr_noprog, GLIBC_2_0) |
28f540f4 | 377 | |
bdb04ee8 | 378 | /* Program version mismatch error reply */ |
c4029823 | 379 | void |
bdb04ee8 UD |
380 | svcerr_progvers (register SVCXPRT *xprt, rpcvers_t low_vers, |
381 | rpcvers_t high_vers) | |
28f540f4 | 382 | { |
e7fd8a39 UD |
383 | struct rpc_msg rply; |
384 | ||
385 | rply.rm_direction = REPLY; | |
386 | rply.rm_reply.rp_stat = MSG_ACCEPTED; | |
387 | rply.acpted_rply.ar_verf = xprt->xp_verf; | |
388 | rply.acpted_rply.ar_stat = PROG_MISMATCH; | |
389 | rply.acpted_rply.ar_vers.low = low_vers; | |
390 | rply.acpted_rply.ar_vers.high = high_vers; | |
391 | SVC_REPLY (xprt, &rply); | |
28f540f4 | 392 | } |
021db4be | 393 | libc_hidden_nolink_sunrpc (svcerr_progvers, GLIBC_2_0) |
28f540f4 RM |
394 | |
395 | /* ******************* SERVER INPUT STUFF ******************* */ | |
396 | ||
397 | /* | |
398 | * Get server side input from some transport. | |
399 | * | |
400 | * Statement of authentication parameters management: | |
401 | * This function owns and manages all authentication parameters, specifically | |
402 | * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and | |
403 | * the "cooked" credentials (rqst->rq_clntcred). | |
404 | * However, this function does not know the structure of the cooked | |
c4029823 | 405 | * credentials, so it make the following assumptions: |
28f540f4 | 406 | * a) the structure is contiguous (no pointers), and |
c4029823 | 407 | * b) the cred structure size does not exceed RQCRED_SIZE bytes. |
28f540f4 RM |
408 | * In all events, all three parameters are freed upon exit from this routine. |
409 | * The storage is trivially management on the call stack in user land, but | |
410 | * is mallocated in kernel land. | |
411 | */ | |
412 | ||
413 | void | |
91eee4dd | 414 | svc_getreq (int rdfds) |
28f540f4 | 415 | { |
e7fd8a39 | 416 | fd_set readfds; |
28f540f4 | 417 | |
e7fd8a39 UD |
418 | FD_ZERO (&readfds); |
419 | readfds.fds_bits[0] = rdfds; | |
7b57bfe5 | 420 | svc_getreqset (&readfds); |
bdb04ee8 | 421 | } |
021db4be | 422 | libc_hidden_nolink_sunrpc (svc_getreq, GLIBC_2_0) |
28f540f4 | 423 | |
bdb04ee8 UD |
424 | void |
425 | svc_getreqset (fd_set *readfds) | |
426 | { | |
0994e2b8 UD |
427 | register fd_mask mask; |
428 | register fd_mask *maskp; | |
bdb04ee8 UD |
429 | register int setsize; |
430 | register int sock; | |
431 | register int bit; | |
432 | ||
433 | setsize = _rpc_dtablesize (); | |
0994e2b8 UD |
434 | if (setsize > FD_SETSIZE) |
435 | setsize = FD_SETSIZE; | |
436 | maskp = readfds->fds_bits; | |
437 | for (sock = 0; sock < setsize; sock += NFDBITS) | |
77c4d115 | 438 | for (mask = *maskp++; (bit = ffsl (mask)); mask ^= (1L << (bit - 1))) |
7b57bfe5 | 439 | svc_getreq_common (sock + bit - 1); |
28f540f4 | 440 | } |
021db4be | 441 | libc_hidden_nolink_sunrpc (svc_getreqset, GLIBC_2_0) |
28f540f4 RM |
442 | |
443 | void | |
bdb04ee8 | 444 | svc_getreq_poll (struct pollfd *pfdp, int pollretval) |
28f540f4 | 445 | { |
30199a66 UD |
446 | if (pollretval == 0) |
447 | return; | |
a334319f | 448 | |
30199a66 UD |
449 | register int fds_found; |
450 | for (int i = fds_found = 0; i < svc_max_pollfd; ++i) | |
bdb04ee8 UD |
451 | { |
452 | register struct pollfd *p = &pfdp[i]; | |
453 | ||
454 | if (p->fd != -1 && p->revents) | |
455 | { | |
456 | /* fd has input waiting */ | |
bdb04ee8 | 457 | if (p->revents & POLLNVAL) |
e79137b2 | 458 | xprt_unregister (xports[p->fd]); |
bdb04ee8 | 459 | else |
7b57bfe5 | 460 | svc_getreq_common (p->fd); |
30199a66 UD |
461 | |
462 | if (++fds_found >= pollretval) | |
463 | break; | |
bdb04ee8 UD |
464 | } |
465 | } | |
466 | } | |
7b57bfe5 UD |
467 | #ifdef EXPORT_RPC_SYMBOLS |
468 | libc_hidden_def (svc_getreq_poll) | |
469 | #else | |
021db4be | 470 | libc_hidden_nolink_sunrpc (svc_getreq_poll, GLIBC_2_2) |
7b57bfe5 | 471 | #endif |
bdb04ee8 UD |
472 | |
473 | ||
474 | void | |
475 | svc_getreq_common (const int fd) | |
28f540f4 | 476 | { |
e7fd8a39 UD |
477 | enum xprt_stat stat; |
478 | struct rpc_msg msg; | |
e7fd8a39 | 479 | register SVCXPRT *xprt; |
e7fd8a39 UD |
480 | char cred_area[2 * MAX_AUTH_BYTES + RQCRED_SIZE]; |
481 | msg.rm_call.cb_cred.oa_base = cred_area; | |
482 | msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); | |
28f540f4 | 483 | |
bdb04ee8 UD |
484 | xprt = xports[fd]; |
485 | /* Do we control fd? */ | |
486 | if (xprt == NULL) | |
487 | return; | |
28f540f4 | 488 | |
bdb04ee8 UD |
489 | /* now receive msgs from xprtprt (support batch calls) */ |
490 | do | |
e7fd8a39 | 491 | { |
bdb04ee8 | 492 | if (SVC_RECV (xprt, &msg)) |
e7fd8a39 | 493 | { |
bdb04ee8 UD |
494 | /* now find the exported program and call it */ |
495 | struct svc_callout *s; | |
496 | struct svc_req r; | |
497 | enum auth_stat why; | |
498 | rpcvers_t low_vers; | |
499 | rpcvers_t high_vers; | |
500 | int prog_found; | |
501 | ||
502 | r.rq_clntcred = &(cred_area[2 * MAX_AUTH_BYTES]); | |
503 | r.rq_xprt = xprt; | |
504 | r.rq_prog = msg.rm_call.cb_prog; | |
505 | r.rq_vers = msg.rm_call.cb_vers; | |
506 | r.rq_proc = msg.rm_call.cb_proc; | |
507 | r.rq_cred = msg.rm_call.cb_cred; | |
508 | ||
509 | /* first authenticate the message */ | |
510 | /* Check for null flavor and bypass these calls if possible */ | |
511 | ||
512 | if (msg.rm_call.cb_cred.oa_flavor == AUTH_NULL) | |
e7fd8a39 | 513 | { |
bdb04ee8 UD |
514 | r.rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; |
515 | r.rq_xprt->xp_verf.oa_length = 0; | |
516 | } | |
7b57bfe5 | 517 | else if ((why = _authenticate (&r, &msg)) != AUTH_OK) |
bdb04ee8 UD |
518 | { |
519 | svcerr_auth (xprt, why); | |
520 | goto call_done; | |
521 | } | |
522 | ||
523 | /* now match message with a registered service */ | |
524 | prog_found = FALSE; | |
525 | low_vers = 0 - 1; | |
526 | high_vers = 0; | |
e7fd8a39 | 527 | |
bdb04ee8 UD |
528 | for (s = svc_head; s != NULL_SVC; s = s->sc_next) |
529 | { | |
530 | if (s->sc_prog == r.rq_prog) | |
531 | { | |
532 | if (s->sc_vers == r.rq_vers) | |
e7fd8a39 | 533 | { |
bdb04ee8 | 534 | (*s->sc_dispatch) (&r, xprt); |
e7fd8a39 UD |
535 | goto call_done; |
536 | } | |
bdb04ee8 UD |
537 | /* found correct version */ |
538 | prog_found = TRUE; | |
539 | if (s->sc_vers < low_vers) | |
540 | low_vers = s->sc_vers; | |
541 | if (s->sc_vers > high_vers) | |
542 | high_vers = s->sc_vers; | |
e7fd8a39 | 543 | } |
bdb04ee8 | 544 | /* found correct program */ |
28f540f4 | 545 | } |
bdb04ee8 UD |
546 | /* if we got here, the program or version |
547 | is not served ... */ | |
548 | if (prog_found) | |
549 | svcerr_progvers (xprt, low_vers, high_vers); | |
550 | else | |
551 | svcerr_noprog (xprt); | |
552 | /* Fall through to ... */ | |
553 | } | |
554 | call_done: | |
555 | if ((stat = SVC_STAT (xprt)) == XPRT_DIED) | |
556 | { | |
557 | SVC_DESTROY (xprt); | |
558 | break; | |
28f540f4 | 559 | } |
e7fd8a39 | 560 | } |
bdb04ee8 | 561 | while (stat == XPRT_MOREREQS); |
28f540f4 | 562 | } |
021db4be | 563 | libc_hidden_nolink_sunrpc (svc_getreq_common, GLIBC_2_2) |
f1e4a4a4 | 564 | |
14bc93a9 JL |
565 | /* If there are no file descriptors available, then accept will fail. |
566 | We want to delay here so the connection request can be dequeued; | |
567 | otherwise we can bounce between polling and accepting, never giving the | |
568 | request a chance to dequeue and eating an enormous amount of cpu time | |
569 | in svc_run if we're polling on many file descriptors. */ | |
570 | void | |
571 | __svc_accept_failed (void) | |
572 | { | |
573 | if (errno == EMFILE) | |
574 | { | |
575 | struct timespec ts = { .tv_sec = 0, .tv_nsec = 50000000 }; | |
576 | __nanosleep (&ts, NULL); | |
577 | } | |
578 | } | |
579 | ||
f1e4a4a4 UD |
580 | #ifdef _RPC_THREAD_SAFE_ |
581 | ||
582 | void | |
583 | __rpc_thread_svc_cleanup (void) | |
584 | { | |
585 | struct svc_callout *svcp; | |
586 | ||
587 | while ((svcp = svc_head) != NULL) | |
588 | svc_unregister (svcp->sc_prog, svcp->sc_vers); | |
589 | } | |
590 | ||
591 | #endif /* _RPC_THREAD_SAFE_ */ |