1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26 /*
27 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
28 */
29
30 /*
31 * svc_door.c, Server side for doors IPC based RPC.
32 */
33
34 #include "mt.h"
35 #include "rpc_mt.h"
36 #include <stdio.h>
37 #include <unistd.h>
38 #include <sys/types.h>
39 #include <rpc/rpc.h>
40 #include <errno.h>
41 #include <syslog.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <sys/stat.h>
45 #include <door.h>
46 #include <alloca.h>
47 #include <dlfcn.h>
48 #include <limits.h>
49 #include <rpc/svc_mt.h>
50
51 static void svc_door_destroy_pvt();
52 static int return_xprt_copy();
53
54 int __rpc_default_door_buf_size = 16000;
55 int __rpc_min_door_buf_size = 1000;
56
57 static struct xp_ops *svc_door_ops();
58
59 mutex_t svc_door_mutex = DEFAULTMUTEX;
60 cond_t svc_door_waitcv = DEFAULTCV;
61 int svc_ndoorfds = 0;
62
63 /*
64 * Dispatch information for door calls.
65 */
66 typedef struct {
67 rpcprog_t prognum;
68 rpcvers_t versnum;
69 void (*dispatch)();
70 } call_info_t;
71
72 /*
73 * kept in xprt->xp_p2
74 */
75 struct svc_door_data {
76 uint_t su_iosz; /* size of send/recv buffer */
77 uint32_t su_xid; /* transaction id */
78 XDR su_xdrs; /* XDR handle */
79 char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */
80 call_info_t call_info; /* dispatch info */
81 char *argbuf; /* argument buffer */
82 size_t arglen; /* argument length */
83 char *buf; /* result buffer */
84 int len; /* result length */
85 };
86 #define su_data(xprt) ((struct svc_door_data *)(xprt->xp_p2))
87
88 static SVCXPRT *get_xprt_copy();
89 static bool_t svc_door_recv();
90 static void svc_door_destroy();
91
92 static SVCXPRT_LIST *dxlist; /* list of door based service handles */
93
94 /*
95 * List management routines.
96 */
97 bool_t
__svc_add_to_xlist(SVCXPRT_LIST ** list,SVCXPRT * xprt,mutex_t * lockp)98 __svc_add_to_xlist(SVCXPRT_LIST **list, SVCXPRT *xprt, mutex_t *lockp)
99 {
100 SVCXPRT_LIST *l;
101
102 if ((l = malloc(sizeof (*l))) == NULL)
103 return (FALSE);
104 l->xprt = xprt;
105 if (lockp != NULL)
106 (void) mutex_lock(lockp);
107 l->next = *list;
108 *list = l;
109 if (lockp != NULL)
110 (void) mutex_unlock(lockp);
111 return (TRUE);
112 }
113
114 void
__svc_rm_from_xlist(SVCXPRT_LIST ** list,SVCXPRT * xprt,mutex_t * lockp)115 __svc_rm_from_xlist(SVCXPRT_LIST **list, SVCXPRT *xprt, mutex_t *lockp)
116 {
117 SVCXPRT_LIST **l, *tmp;
118
119 if (lockp != NULL)
120 (void) mutex_lock(lockp);
121 for (l = list; *l != NULL; l = &(*l)->next) {
122 if ((*l)->xprt == xprt) {
123 tmp = (*l)->next;
124 free(*l);
125 *l = tmp;
126 break;
127 }
128 }
129 if (lockp != NULL)
130 (void) mutex_unlock(lockp);
131 }
132
133 void
__svc_free_xlist(SVCXPRT_LIST ** list,mutex_t * lockp)134 __svc_free_xlist(SVCXPRT_LIST **list, mutex_t *lockp)
135 {
136 SVCXPRT_LIST *tmp;
137
138 if (lockp != NULL)
139 (void) mutex_lock(lockp);
140 while (*list != NULL) {
141 tmp = (*list)->next;
142 free(*list);
143 *list = tmp;
144 }
145 if (lockp != NULL)
146 (void) mutex_unlock(lockp);
147 }
148
149 /*
150 * Destroy all door based service handles.
151 */
152 void
__svc_cleanup_door_xprts(void)153 __svc_cleanup_door_xprts(void)
154 {
155 SVCXPRT_LIST *l, *tmp = NULL;
156
157 (void) mutex_lock(&svc_door_mutex);
158 for (l = dxlist; l != NULL; l = tmp) {
159 tmp = l->next;
160 svc_door_destroy_pvt(l->xprt);
161 }
162 (void) mutex_unlock(&svc_door_mutex);
163 }
164
165 static bool_t
make_tmp_dir(void)166 make_tmp_dir(void)
167 {
168 struct stat statbuf;
169
170 if (stat(RPC_DOOR_DIR, &statbuf) < 0) {
171 (void) mkdir(RPC_DOOR_DIR, (mode_t)0755);
172 (void) chmod(RPC_DOOR_DIR, (mode_t)01777);
173 if (stat(RPC_DOOR_DIR, &statbuf) < 0)
174 return (FALSE);
175 }
176 return ((statbuf.st_mode & S_IFMT) == S_IFDIR &&
177 (statbuf.st_mode & 01777) == 01777);
178 }
179
180 static void
svc_door_dispatch(SVCXPRT * xprt,struct rpc_msg * msg,struct svc_req * r)181 svc_door_dispatch(SVCXPRT *xprt, struct rpc_msg *msg, struct svc_req *r)
182 {
183 enum auth_stat why;
184 /* LINTED pointer alignment */
185 struct svc_door_data *su = su_data(xprt);
186 bool_t nd;
187
188 r->rq_xprt = xprt;
189 r->rq_prog = msg->rm_call.cb_prog;
190 r->rq_vers = msg->rm_call.cb_vers;
191 r->rq_proc = msg->rm_call.cb_proc;
192 r->rq_cred = msg->rm_call.cb_cred;
193
194 if (msg->rm_call.cb_cred.oa_flavor == AUTH_NULL) {
195 r->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
196 r->rq_xprt->xp_verf.oa_length = 0;
197
198 } else if ((why = __gss_authenticate(r, msg, &nd)) != AUTH_OK) {
199 svcerr_auth(xprt, why);
200 return;
201 }
202
203 if (su->call_info.prognum == r->rq_prog && su->call_info.versnum ==
204 r->rq_vers) {
205 (*su->call_info.dispatch)(r, xprt);
206 return;
207 }
208
209 /*
210 * if we got here, the program or version
211 * is not served ...
212 */
213 if (su->call_info.prognum == r->rq_prog)
214 svcerr_progvers(xprt, su->call_info.versnum,
215 su->call_info.versnum);
216 else
217 svcerr_noprog(xprt);
218 }
219
220 /*
221 * This is the door server procedure.
222 */
223 /* ARGSUSED */
224 static void
door_server(void * cookie,char * argp,size_t arg_size,door_desc_t * dp,uint_t n_did)225 door_server(void *cookie, char *argp, size_t arg_size,
226 door_desc_t *dp, uint_t n_did)
227 {
228 SVCXPRT *parent = (SVCXPRT *)cookie;
229 SVCXPRT *xprt;
230 struct rpc_msg *msg;
231 struct svc_req *r;
232 char *cred_area;
233 char *result_buf;
234 int len;
235 struct svc_door_data *su;
236
237 /*
238 * allocate result buffer
239 */
240 /* LINTED pointer alignment */
241 result_buf = alloca(su_data(parent)->su_iosz);
242 if (result_buf == NULL) {
243 (void) syslog(LOG_ERR, "door_server: alloca failed");
244 (void) door_return(NULL, 0, NULL, 0);
245 /*NOTREACHED*/
246 }
247
248 (void) mutex_lock(&svc_door_mutex);
249 if ((xprt = get_xprt_copy(parent, result_buf)) == NULL) {
250 (void) syslog(LOG_ERR,
251 "door_server: memory allocation failure");
252 (void) mutex_unlock(&svc_door_mutex);
253 (void) door_return(NULL, 0, NULL, 0);
254 /*NOTREACHED*/
255 }
256 (void) mutex_unlock(&svc_door_mutex);
257
258 /* LINTED pointer alignment */
259 msg = SVCEXT(xprt)->msg;
260 /* LINTED pointer alignment */
261 r = SVCEXT(xprt)->req;
262 /* LINTED pointer alignment */
263 cred_area = SVCEXT(xprt)->cred_area;
264
265 msg->rm_call.cb_cred.oa_base = cred_area;
266 msg->rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
267 r->rq_clntcred = &(cred_area[2 * MAX_AUTH_BYTES]);
268
269 /* LINTED pointer alignment */
270 su = su_data(xprt);
271 su->argbuf = argp;
272 su->arglen = arg_size;
273
274 if (svc_door_recv(xprt, msg))
275 svc_door_dispatch(xprt, msg, r);
276
277 if ((len = return_xprt_copy(xprt)) > 0) {
278 (void) door_return(result_buf, (size_t)len, NULL, 0);
279 /*NOTREACHED*/
280 } else {
281 (void) door_return(NULL, 0, NULL, 0);
282 /*NOTREACHED*/
283 }
284 }
285
286 /*
287 * Usage:
288 * xprt = svc_door_create(dispatch, prognum, versnum, sendsize);
289 * Once *xprt is initialized, it is registered.
290 * see (svc.h, xprt_register). If recvsize or sendsize are 0 suitable
291 * system defaults are chosen.
292 * The routines returns NULL if a problem occurred.
293 */
294
295 void
svc_door_xprtfree(SVCXPRT * xprt)296 svc_door_xprtfree(SVCXPRT *xprt)
297 {
298 /* LINTED pointer alignment */
299 struct svc_door_data *su = xprt ? su_data(xprt) : NULL;
300
301 if (xprt == NULL)
302 return;
303 if (xprt->xp_netid)
304 free(xprt->xp_netid);
305 if (xprt->xp_tp)
306 free(xprt->xp_tp);
307 if (su != NULL)
308 free(su);
309 svc_xprt_free(xprt);
310 }
311
312 SVCXPRT *
svc_door_create(void (* dispatch)(),const rpcprog_t prognum,const rpcvers_t versnum,const uint_t sendsize)313 svc_door_create(void (*dispatch)(), const rpcprog_t prognum,
314 const rpcvers_t versnum, const uint_t sendsize)
315 {
316 SVCXPRT *xprt;
317 struct svc_door_data *su = NULL;
318 char rendezvous[128] = "";
319 int fd;
320 int did = -1;
321 mode_t mask;
322 uint_t ssize;
323
324 (void) mutex_lock(&svc_door_mutex);
325
326 if (!make_tmp_dir()) {
327 (void) syslog(LOG_ERR, "svc_door_create: cannot open %s",
328 RPC_DOOR_DIR);
329 (void) mutex_unlock(&svc_door_mutex);
330 return (NULL);
331 }
332
333 if ((xprt = svc_xprt_alloc()) == NULL) {
334 (void) syslog(LOG_ERR, "svc_door_create: out of memory");
335 goto freedata;
336 }
337 /* LINTED pointer alignment */
338 svc_flags(xprt) |= SVC_DOOR;
339
340 (void) sprintf(rendezvous, RPC_DOOR_RENDEZVOUS, (int)prognum,
341 (int)versnum);
342 mask = umask(0);
343 fd = open(rendezvous, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0644);
344 (void) umask(mask);
345 if (fd < 0) {
346 if (errno == EEXIST) {
347 if (unlink(rendezvous) < 0) {
348 (void) syslog(LOG_ERR,
349 "svc_door_create: %s %s:%m", rendezvous,
350 "exists and could not be removed");
351 goto freedata;
352 }
353 mask = umask(0);
354 fd = open(rendezvous, O_WRONLY | O_CREAT | O_EXCL |
355 O_TRUNC, 0644);
356 (void) umask(mask);
357 if (fd < 0) {
358 (void) syslog(LOG_ERR,
359 "svc_door_create: %s %s:%m",
360 "could not create", rendezvous);
361 goto freedata;
362 }
363 } else {
364 (void) syslog(LOG_ERR,
365 "svc_door_create: could not create %s:%m",
366 rendezvous);
367 goto freedata;
368 }
369 }
370 (void) close(fd);
371 did = door_create(door_server, (void *)xprt, DOOR_REFUSE_DESC);
372 if (did < 0) {
373 (void) syslog(LOG_ERR,
374 "svc_door_create: door_create failed: %m");
375 goto freedata;
376 }
377
378 if (fattach(did, rendezvous) < 0) {
379 if (errno != EBUSY || fdetach(rendezvous) < 0 ||
380 fattach(did, rendezvous) < 0) {
381 (void) syslog(LOG_ERR,
382 "svc_door_create: fattach failed: %m");
383 goto freedata;
384 }
385 }
386
387 /*
388 * Determine send size
389 */
390 if (sendsize < __rpc_min_door_buf_size)
391 ssize = __rpc_default_door_buf_size;
392 else
393 ssize = RNDUP(sendsize);
394
395 su = malloc(sizeof (*su));
396 if (su == NULL) {
397 (void) syslog(LOG_ERR, "svc_door_create: out of memory");
398 goto freedata;
399 }
400 su->su_iosz = ssize;
401 su->call_info.prognum = prognum;
402 su->call_info.versnum = versnum;
403 su->call_info.dispatch = dispatch;
404
405 xprt->xp_p2 = (caddr_t)su;
406 xprt->xp_verf.oa_base = su->su_verfbody;
407 xprt->xp_ops = svc_door_ops();
408 xprt->xp_netid = strdup("door");
409 if (xprt->xp_netid == NULL) {
410 syslog(LOG_ERR, "svc_door_create: strdup failed");
411 goto freedata;
412 }
413 xprt->xp_tp = strdup(rendezvous);
414 if (xprt->xp_tp == NULL) {
415 syslog(LOG_ERR, "svc_door_create: strdup failed");
416 goto freedata;
417 }
418 xprt->xp_fd = did;
419
420 svc_ndoorfds++;
421 if (!__svc_add_to_xlist(&dxlist, xprt, NULL)) {
422
423 (void) syslog(LOG_ERR, "svc_door_create: out of memory");
424 goto freedata;
425 }
426 (void) mutex_unlock(&svc_door_mutex);
427 return (xprt);
428 freedata:
429 (void) fdetach(rendezvous);
430 (void) unlink(rendezvous);
431 if (did >= 0)
432 (void) door_revoke(did);
433 if (xprt)
434 svc_door_xprtfree(xprt);
435 (void) mutex_unlock(&svc_door_mutex);
436 return (NULL);
437 }
438
439
440 static SVCXPRT *
svc_door_xprtcopy(SVCXPRT * parent)441 svc_door_xprtcopy(SVCXPRT *parent)
442 {
443 SVCXPRT *xprt;
444 struct svc_door_data *su;
445
446 if ((xprt = svc_xprt_alloc()) == NULL)
447 return (NULL);
448
449 /* LINTED pointer alignment */
450 SVCEXT(xprt)->parent = parent;
451 /* LINTED pointer alignment */
452 SVCEXT(xprt)->flags = SVCEXT(parent)->flags;
453
454 xprt->xp_fd = parent->xp_fd;
455 xprt->xp_port = parent->xp_port;
456 xprt->xp_ops = svc_door_ops();
457 if (parent->xp_tp) {
458 xprt->xp_tp = (char *)strdup(parent->xp_tp);
459 if (xprt->xp_tp == NULL) {
460 syslog(LOG_ERR, "svc_door_xprtcopy: strdup failed");
461 svc_door_xprtfree(xprt);
462 return (NULL);
463 }
464 }
465 if (parent->xp_netid) {
466 xprt->xp_netid = (char *)strdup(parent->xp_netid);
467 if (xprt->xp_netid == NULL) {
468 syslog(LOG_ERR, "svc_door_xprtcopy: strdup failed");
469 if (parent->xp_tp)
470 free(parent->xp_tp);
471 svc_door_xprtfree(xprt);
472 return (NULL);
473 }
474 }
475 xprt->xp_type = parent->xp_type;
476
477 if ((su = malloc(sizeof (struct svc_door_data))) == NULL) {
478 svc_door_xprtfree(xprt);
479 return (NULL);
480 }
481 /* LINTED pointer alignment */
482 su->su_iosz = su_data(parent)->su_iosz;
483 /* LINTED pointer alignment */
484 su->call_info = su_data(parent)->call_info;
485
486 xprt->xp_p2 = (caddr_t)su; /* su_data(xprt) = su */
487 xprt->xp_verf.oa_base = su->su_verfbody;
488
489 return (xprt);
490 }
491
492
493 static SVCXPRT *
get_xprt_copy(SVCXPRT * parent,char * buf)494 get_xprt_copy(SVCXPRT *parent, char *buf)
495 {
496 /* LINTED pointer alignment */
497 SVCXPRT_LIST *xlist = SVCEXT(parent)->my_xlist;
498 SVCXPRT_LIST *xret;
499 SVCXPRT *xprt;
500 struct svc_door_data *su;
501
502 xret = xlist->next;
503 if (xret) {
504 xlist->next = xret->next;
505 xret->next = NULL;
506 xprt = xret->xprt;
507 /* LINTED pointer alignment */
508 svc_flags(xprt) = svc_flags(parent);
509 } else
510 xprt = svc_door_xprtcopy(parent);
511
512 if (xprt) {
513 /* LINTED pointer alignment */
514 SVCEXT(parent)->refcnt++;
515 /* LINTED pointer alignment */
516 su = su_data(xprt);
517 su->buf = buf;
518 su->len = 0;
519 }
520 return (xprt);
521 }
522
523 int
return_xprt_copy(SVCXPRT * xprt)524 return_xprt_copy(SVCXPRT *xprt)
525 {
526 SVCXPRT *parent;
527 SVCXPRT_LIST *xhead, *xlist;
528 /* LINTED pointer alignment */
529 int len = su_data(xprt)->len;
530
531 (void) mutex_lock(&svc_door_mutex);
532 /* LINTED pointer alignment */
533 if ((parent = SVCEXT(xprt)->parent) == NULL) {
534 (void) mutex_unlock(&svc_door_mutex);
535 return (0);
536 }
537 /* LINTED pointer alignment */
538 xhead = SVCEXT(parent)->my_xlist;
539 /* LINTED pointer alignment */
540 xlist = SVCEXT(xprt)->my_xlist;
541 xlist->next = xhead->next;
542 xhead->next = xlist;
543 /* LINTED pointer alignment */
544 SVCEXT(parent)->refcnt--;
545
546 /*
547 * Propagate any error flags. This is done in both directions to
548 * ensure that if one child gets an error, everyone will see it
549 * (even if there are multiple outstanding children) and the
550 * door will get closed.
551 */
552 /* LINTED pointer alignment */
553 svc_flags(xprt) |= svc_flags(parent);
554 /* LINTED pointer alignment */
555 if (svc_defunct(xprt)) {
556 /* LINTED pointer alignment */
557 svc_flags(parent) |= SVC_DEFUNCT;
558 /* LINTED pointer cast */
559 if (SVCEXT(parent)->refcnt == 0)
560 svc_door_destroy_pvt(xprt);
561 }
562 (void) mutex_unlock(&svc_door_mutex);
563 return (len);
564 }
565
566 /* ARGSUSED */
567 static enum xprt_stat
svc_door_stat(SVCXPRT * xprt)568 svc_door_stat(SVCXPRT *xprt)
569 {
570 return (XPRT_IDLE);
571 }
572
573 static bool_t
svc_door_recv(SVCXPRT * xprt,struct rpc_msg * msg)574 svc_door_recv(SVCXPRT *xprt, struct rpc_msg *msg)
575 {
576 /* LINTED pointer alignment */
577 struct svc_door_data *su = su_data(xprt);
578 XDR *xdrs = &(su->su_xdrs);
579
580 xdrmem_create(xdrs, su->argbuf, su->arglen, XDR_DECODE);
581 if (!xdr_callmsg(xdrs, msg))
582 return (FALSE);
583 su->su_xid = msg->rm_xid;
584 return (TRUE);
585 }
586
587 static bool_t
svc_door_reply(SVCXPRT * xprt,struct rpc_msg * msg)588 svc_door_reply(SVCXPRT *xprt, struct rpc_msg *msg)
589 {
590 /* LINTED pointer alignment */
591 struct svc_door_data *su = su_data(xprt);
592 XDR *xdrs = &(su->su_xdrs);
593
594 xdrmem_create(xdrs, su->buf, su->su_iosz, XDR_ENCODE);
595 msg->rm_xid = su->su_xid;
596 if (xdr_replymsg(xdrs, msg)) {
597 su->len = (int)XDR_GETPOS(xdrs);
598 return (TRUE);
599 }
600 return (FALSE);
601 }
602
603 static bool_t
svc_door_getargs(SVCXPRT * xprt,xdrproc_t xdr_args,caddr_t args_ptr)604 svc_door_getargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
605 {
606 /* LINTED pointer alignment */
607 return ((*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr));
608 }
609
610 static bool_t
svc_door_freeargs(SVCXPRT * xprt,xdrproc_t xdr_args,caddr_t args_ptr)611 svc_door_freeargs(SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
612 {
613 /* LINTED pointer alignment */
614 XDR *xdrs = &(su_data(xprt)->su_xdrs);
615
616 xdrs->x_op = XDR_FREE;
617 return ((*xdr_args)(xdrs, args_ptr));
618 }
619
620 static void
svc_door_destroy(SVCXPRT * xprt)621 svc_door_destroy(SVCXPRT *xprt)
622 {
623 (void) mutex_lock(&svc_door_mutex);
624 svc_door_destroy_pvt(xprt);
625 (void) mutex_unlock(&svc_door_mutex);
626 }
627
628 static void
svc_door_destroy_pvt(SVCXPRT * xprt)629 svc_door_destroy_pvt(SVCXPRT *xprt)
630 {
631 /* LINTED pointer alignment */
632 if (SVCEXT(xprt)->parent)
633 /* LINTED pointer alignment */
634 xprt = SVCEXT(xprt)->parent;
635 /* LINTED pointer alignment */
636 svc_flags(xprt) |= SVC_DEFUNCT;
637 /* LINTED pointer alignment */
638 if (SVCEXT(xprt)->refcnt > 0)
639 return;
640
641 __svc_rm_from_xlist(&dxlist, xprt, NULL);
642
643 if (xprt->xp_tp) {
644 (void) fdetach(xprt->xp_tp);
645 (void) unlink(xprt->xp_tp);
646 }
647 (void) door_revoke(xprt->xp_fd);
648
649 svc_xprt_destroy(xprt);
650 if (--svc_ndoorfds == 0)
651 /* wake up door dispatching */
652 (void) cond_signal(&svc_door_waitcv);
653 }
654
655 /* ARGSUSED */
656 static bool_t
svc_door_control(SVCXPRT * xprt,const uint_t rq,void * in)657 svc_door_control(SVCXPRT *xprt, const uint_t rq, void *in)
658 {
659 extern int __rpc_legal_connmaxrec(int);
660
661 size_t door_param;
662 int tmp;
663
664 switch (rq) {
665 case SVCSET_CONNMAXREC:
666 tmp = __rpc_legal_connmaxrec(*(int *)in);
667 if (tmp >= 0) {
668 door_param = (tmp == 0)? SIZE_MAX :
669 (size_t)(ssize_t)tmp;
670 if (door_setparam(xprt->xp_fd, DOOR_PARAM_DATA_MAX,
671 door_param) == 0)
672 return (TRUE);
673 return (FALSE);
674 }
675 return (FALSE);
676 case SVCGET_CONNMAXREC:
677 if (door_getparam(xprt->xp_fd, DOOR_PARAM_DATA_MAX,
678 &door_param) == 0) {
679 if (door_param == SIZE_MAX)
680 tmp = 0;
681 else if (door_param > INT_MAX)
682 tmp = INT_MAX;
683 else if (door_param > 0)
684 tmp = (int)door_param;
685 else
686 return (FALSE);
687
688 *(int *)in = tmp;
689 return (TRUE);
690 }
691 return (FALSE);
692 }
693 return (FALSE);
694 }
695
696 static struct xp_ops *
svc_door_ops(void)697 svc_door_ops(void)
698 {
699 static struct xp_ops ops;
700 extern mutex_t ops_lock;
701
702 (void) mutex_lock(&ops_lock);
703 if (ops.xp_recv == NULL) {
704 ops.xp_recv = svc_door_recv;
705 ops.xp_stat = svc_door_stat;
706 ops.xp_getargs = svc_door_getargs;
707 ops.xp_reply = svc_door_reply;
708 ops.xp_freeargs = svc_door_freeargs;
709 ops.xp_destroy = svc_door_destroy;
710 ops.xp_control = svc_door_control;
711 }
712 (void) mutex_unlock(&ops_lock);
713 return (&ops);
714 }
715
716 /*
717 * Return door credentials.
718 */
719 /* ARGSUSED */
720 bool_t
__svc_get_door_cred(SVCXPRT * xprt,svc_local_cred_t * lcred)721 __svc_get_door_cred(SVCXPRT *xprt, svc_local_cred_t *lcred)
722 {
723 door_cred_t dc;
724
725 if (door_cred(&dc) < 0)
726 return (FALSE);
727 lcred->euid = dc.dc_euid;
728 lcred->egid = dc.dc_egid;
729 lcred->ruid = dc.dc_ruid;
730 lcred->rgid = dc.dc_rgid;
731 lcred->pid = dc.dc_pid;
732 return (TRUE);
733 }
734
735 /* ARGSUSED */
736 bool_t
__svc_get_door_ucred(const SVCXPRT * xprt,ucred_t * ucp)737 __svc_get_door_ucred(const SVCXPRT *xprt, ucred_t *ucp)
738 {
739 return (door_ucred(&ucp) == 0);
740 }
741