source: rtems-libbsd/freebsd/lib/libc/rpc/svc.c @ f41a394

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since f41a394 was 60b1d40, checked in by Sebastian Huber <sebastian.huber@…>, on 06/09/16 at 08:23:57

RPC(3): Import from FreeBSD

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