17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*afa82f98SNicolas Williams * Common Development and Distribution License (the "License"). 6*afa82f98SNicolas Williams * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 2161961e0fSrobinson 227c478bd9Sstevel@tonic-gate /* 23*afa82f98SNicolas Williams * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * clnt_doors.c, Client side for doors IPC based RPC. 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include "mt.h" 327c478bd9Sstevel@tonic-gate #include "rpc_mt.h" 337c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 347c478bd9Sstevel@tonic-gate #include <errno.h> 357c478bd9Sstevel@tonic-gate #include <sys/poll.h> 367c478bd9Sstevel@tonic-gate #include <syslog.h> 377c478bd9Sstevel@tonic-gate #include <sys/types.h> 387c478bd9Sstevel@tonic-gate #include <sys/kstat.h> 397c478bd9Sstevel@tonic-gate #include <sys/time.h> 407c478bd9Sstevel@tonic-gate #include <door.h> 417c478bd9Sstevel@tonic-gate #include <stdlib.h> 427c478bd9Sstevel@tonic-gate #include <unistd.h> 437c478bd9Sstevel@tonic-gate #include <string.h> 447c478bd9Sstevel@tonic-gate #include <alloca.h> 457c478bd9Sstevel@tonic-gate #include <rpc/svc_mt.h> 4661961e0fSrobinson #include <sys/mman.h> 47*afa82f98SNicolas Williams #include <atomic.h> 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate 5061961e0fSrobinson extern bool_t xdr_opaque_auth(XDR *, struct opaque_auth *); 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate static struct clnt_ops *clnt_door_ops(); 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate extern int __rpc_default_door_buf_size; 557c478bd9Sstevel@tonic-gate extern int __rpc_min_door_buf_size; 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate /* 587c478bd9Sstevel@tonic-gate * Private data kept per client handle 597c478bd9Sstevel@tonic-gate */ 607c478bd9Sstevel@tonic-gate struct cu_data { 617c478bd9Sstevel@tonic-gate int cu_fd; /* door fd */ 627c478bd9Sstevel@tonic-gate bool_t cu_closeit; /* close it on destroy */ 637c478bd9Sstevel@tonic-gate struct rpc_err cu_error; 647c478bd9Sstevel@tonic-gate uint_t cu_xdrpos; 657c478bd9Sstevel@tonic-gate uint_t cu_sendsz; /* send size */ 667c478bd9Sstevel@tonic-gate char cu_header[32]; /* precreated header */ 677c478bd9Sstevel@tonic-gate }; 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate /* 707c478bd9Sstevel@tonic-gate * Door IPC based client creation routine. 717c478bd9Sstevel@tonic-gate * 727c478bd9Sstevel@tonic-gate * NB: The rpch->cl_auth is initialized to null authentication. 737c478bd9Sstevel@tonic-gate * Caller may wish to set this something more useful. 747c478bd9Sstevel@tonic-gate * 757c478bd9Sstevel@tonic-gate * sendsz is the maximum allowable packet size that can be sent. 767c478bd9Sstevel@tonic-gate * 0 will cause default to be used. 777c478bd9Sstevel@tonic-gate */ 787c478bd9Sstevel@tonic-gate CLIENT * 7961961e0fSrobinson clnt_door_create(const rpcprog_t program, const rpcvers_t version, 8061961e0fSrobinson const uint_t sendsz) 817c478bd9Sstevel@tonic-gate { 827c478bd9Sstevel@tonic-gate CLIENT *cl = NULL; /* client handle */ 837c478bd9Sstevel@tonic-gate struct cu_data *cu = NULL; /* private data */ 847c478bd9Sstevel@tonic-gate struct rpc_msg call_msg; 857c478bd9Sstevel@tonic-gate char rendezvous[64]; 867c478bd9Sstevel@tonic-gate int did; 877c478bd9Sstevel@tonic-gate struct door_info info; 887c478bd9Sstevel@tonic-gate XDR xdrs; 897c478bd9Sstevel@tonic-gate struct timeval now; 9061961e0fSrobinson uint_t ssz; 917c478bd9Sstevel@tonic-gate 9261961e0fSrobinson (void) sprintf(rendezvous, RPC_DOOR_RENDEZVOUS, (int)program, 9361961e0fSrobinson (int)version); 947c478bd9Sstevel@tonic-gate if ((did = open(rendezvous, O_RDONLY, 0)) < 0) { 957c478bd9Sstevel@tonic-gate rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 967c478bd9Sstevel@tonic-gate rpc_createerr.cf_error.re_errno = errno; 977c478bd9Sstevel@tonic-gate rpc_createerr.cf_error.re_terrno = 0; 987c478bd9Sstevel@tonic-gate return (NULL); 997c478bd9Sstevel@tonic-gate } 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate if (door_info(did, &info) < 0 || (info.di_attributes & DOOR_REVOKED)) { 10261961e0fSrobinson (void) close(did); 1037c478bd9Sstevel@tonic-gate rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 1047c478bd9Sstevel@tonic-gate rpc_createerr.cf_error.re_errno = errno; 1057c478bd9Sstevel@tonic-gate rpc_createerr.cf_error.re_terrno = 0; 1067c478bd9Sstevel@tonic-gate return (NULL); 1077c478bd9Sstevel@tonic-gate } 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate /* 1107c478bd9Sstevel@tonic-gate * Determine send size 1117c478bd9Sstevel@tonic-gate */ 1127c478bd9Sstevel@tonic-gate if (sendsz < __rpc_min_door_buf_size) 11361961e0fSrobinson ssz = __rpc_default_door_buf_size; 1147c478bd9Sstevel@tonic-gate else 11561961e0fSrobinson ssz = RNDUP(sendsz); 1167c478bd9Sstevel@tonic-gate 11761961e0fSrobinson if ((cl = malloc(sizeof (CLIENT))) == NULL || 11861961e0fSrobinson (cu = malloc(sizeof (*cu))) == NULL) { 1197c478bd9Sstevel@tonic-gate rpc_createerr.cf_stat = RPC_SYSTEMERROR; 1207c478bd9Sstevel@tonic-gate rpc_createerr.cf_error.re_errno = errno; 1217c478bd9Sstevel@tonic-gate goto err; 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate /* 1257c478bd9Sstevel@tonic-gate * Precreate RPC header for performance reasons. 1267c478bd9Sstevel@tonic-gate */ 12761961e0fSrobinson (void) gettimeofday(&now, NULL); 1287c478bd9Sstevel@tonic-gate call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec; 1297c478bd9Sstevel@tonic-gate call_msg.rm_call.cb_prog = program; 1307c478bd9Sstevel@tonic-gate call_msg.rm_call.cb_vers = version; 1317c478bd9Sstevel@tonic-gate xdrmem_create(&xdrs, cu->cu_header, sizeof (cu->cu_header), XDR_ENCODE); 1327c478bd9Sstevel@tonic-gate if (!xdr_callhdr(&xdrs, &call_msg)) { 1337c478bd9Sstevel@tonic-gate rpc_createerr.cf_stat = RPC_CANTENCODEARGS; 1347c478bd9Sstevel@tonic-gate rpc_createerr.cf_error.re_errno = 0; 1357c478bd9Sstevel@tonic-gate goto err; 1367c478bd9Sstevel@tonic-gate } 1377c478bd9Sstevel@tonic-gate cu->cu_xdrpos = XDR_GETPOS(&xdrs); 1387c478bd9Sstevel@tonic-gate 13961961e0fSrobinson cu->cu_sendsz = ssz; 1407c478bd9Sstevel@tonic-gate cu->cu_fd = did; 1417c478bd9Sstevel@tonic-gate cu->cu_closeit = TRUE; 1427c478bd9Sstevel@tonic-gate cl->cl_ops = clnt_door_ops(); 1437c478bd9Sstevel@tonic-gate cl->cl_private = (caddr_t)cu; 1447c478bd9Sstevel@tonic-gate cl->cl_auth = authnone_create(); 1457c478bd9Sstevel@tonic-gate cl->cl_tp = strdup(rendezvous); 1467c478bd9Sstevel@tonic-gate if (cl->cl_tp == NULL) { 1477c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "clnt_door_create: strdup failed"); 1487c478bd9Sstevel@tonic-gate rpc_createerr.cf_stat = RPC_SYSTEMERROR; 1497c478bd9Sstevel@tonic-gate rpc_createerr.cf_error.re_errno = errno; 1507c478bd9Sstevel@tonic-gate goto err; 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate cl->cl_netid = strdup("door"); 1537c478bd9Sstevel@tonic-gate if (cl->cl_netid == NULL) { 1547c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "clnt_door_create: strdup failed"); 1557c478bd9Sstevel@tonic-gate if (cl->cl_tp) 1567c478bd9Sstevel@tonic-gate free(cl->cl_tp); 1577c478bd9Sstevel@tonic-gate rpc_createerr.cf_stat = RPC_SYSTEMERROR; 1587c478bd9Sstevel@tonic-gate rpc_createerr.cf_error.re_errno = errno; 1597c478bd9Sstevel@tonic-gate goto err; 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate return (cl); 1627c478bd9Sstevel@tonic-gate err: 1637c478bd9Sstevel@tonic-gate rpc_createerr.cf_error.re_terrno = 0; 1647c478bd9Sstevel@tonic-gate if (cl) { 16561961e0fSrobinson free(cl); 1667c478bd9Sstevel@tonic-gate if (cu) 16761961e0fSrobinson free(cu); 1687c478bd9Sstevel@tonic-gate } 16961961e0fSrobinson (void) close(did); 17061961e0fSrobinson return (NULL); 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1747c478bd9Sstevel@tonic-gate static enum clnt_stat 17561961e0fSrobinson clnt_door_call(CLIENT *cl, rpcproc_t proc, xdrproc_t xargs, caddr_t argsp, 17661961e0fSrobinson xdrproc_t xresults, caddr_t resultsp, struct timeval utimeout) 1777c478bd9Sstevel@tonic-gate { 1787c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 1797c478bd9Sstevel@tonic-gate struct cu_data *cu = (struct cu_data *)cl->cl_private; 1807c478bd9Sstevel@tonic-gate XDR xdrs; 1817c478bd9Sstevel@tonic-gate door_arg_t params; 1827c478bd9Sstevel@tonic-gate char *outbuf_ref; 1837c478bd9Sstevel@tonic-gate struct rpc_msg reply_msg; 1847c478bd9Sstevel@tonic-gate bool_t need_to_unmap; 185*afa82f98SNicolas Williams uint32_t xid; 1867c478bd9Sstevel@tonic-gate int nrefreshes = 2; /* number of times to refresh cred */ 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate rpc_callerr.re_errno = 0; 1897c478bd9Sstevel@tonic-gate rpc_callerr.re_terrno = 0; 1907c478bd9Sstevel@tonic-gate 19161961e0fSrobinson if ((params.rbuf = alloca(cu->cu_sendsz)) == NULL) { 1927c478bd9Sstevel@tonic-gate rpc_callerr.re_terrno = 0; 1937c478bd9Sstevel@tonic-gate rpc_callerr.re_errno = errno; 1947c478bd9Sstevel@tonic-gate return (rpc_callerr.re_status = RPC_SYSTEMERROR); 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate outbuf_ref = params.rbuf; 1977c478bd9Sstevel@tonic-gate params.rsize = cu->cu_sendsz; 19861961e0fSrobinson if ((params.data_ptr = alloca(cu->cu_sendsz)) == NULL) { 1997c478bd9Sstevel@tonic-gate rpc_callerr.re_terrno = 0; 2007c478bd9Sstevel@tonic-gate rpc_callerr.re_errno = errno; 2017c478bd9Sstevel@tonic-gate return (rpc_callerr.re_status = RPC_SYSTEMERROR); 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate call_again: 2057c478bd9Sstevel@tonic-gate xdrmem_create(&xdrs, params.data_ptr, cu->cu_sendsz, XDR_ENCODE); 206*afa82f98SNicolas Williams /* Increment XID (not really needed for RPC over doors...) */ 2077c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 208*afa82f98SNicolas Williams xid = atomic_inc_uint_nv((uint32_t *)cu->cu_header); 20961961e0fSrobinson (void) memcpy(params.data_ptr, cu->cu_header, cu->cu_xdrpos); 210*afa82f98SNicolas Williams /* LINTED pointer alignment */ 211*afa82f98SNicolas Williams *(uint32_t *)params.data_ptr = xid; 2127c478bd9Sstevel@tonic-gate XDR_SETPOS(&xdrs, cu->cu_xdrpos); 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate if ((!XDR_PUTINT32(&xdrs, (int32_t *)&proc)) || 2157c478bd9Sstevel@tonic-gate (!AUTH_MARSHALL(cl->cl_auth, &xdrs)) || 2167c478bd9Sstevel@tonic-gate (!(*xargs)(&xdrs, argsp))) { 2177c478bd9Sstevel@tonic-gate return (rpc_callerr.re_status = RPC_CANTENCODEARGS); 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate params.data_size = (int)XDR_GETPOS(&xdrs); 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate params.desc_ptr = NULL; 2227c478bd9Sstevel@tonic-gate params.desc_num = 0; 2237c478bd9Sstevel@tonic-gate if (door_call(cu->cu_fd, ¶ms) < 0) { 2247c478bd9Sstevel@tonic-gate rpc_callerr.re_errno = errno; 2257c478bd9Sstevel@tonic-gate return (rpc_callerr.re_status = RPC_CANTSEND); 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate if (params.rbuf == NULL || params.rsize == 0) { 2297c478bd9Sstevel@tonic-gate return (rpc_callerr.re_status = RPC_FAILED); 2307c478bd9Sstevel@tonic-gate } 2317c478bd9Sstevel@tonic-gate need_to_unmap = (params.rbuf != outbuf_ref); 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 234*afa82f98SNicolas Williams if (*(uint32_t *)params.rbuf != xid) { 2357c478bd9Sstevel@tonic-gate rpc_callerr.re_status = RPC_CANTDECODERES; 2367c478bd9Sstevel@tonic-gate goto done; 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate xdrmem_create(&xdrs, params.rbuf, params.rsize, XDR_DECODE); 2407c478bd9Sstevel@tonic-gate reply_msg.acpted_rply.ar_verf = _null_auth; 2417c478bd9Sstevel@tonic-gate reply_msg.acpted_rply.ar_results.where = resultsp; 2427c478bd9Sstevel@tonic-gate reply_msg.acpted_rply.ar_results.proc = xresults; 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate if (xdr_replymsg(&xdrs, &reply_msg)) { 2457c478bd9Sstevel@tonic-gate if (reply_msg.rm_reply.rp_stat == MSG_ACCEPTED && 2467c478bd9Sstevel@tonic-gate reply_msg.acpted_rply.ar_stat == SUCCESS) 2477c478bd9Sstevel@tonic-gate rpc_callerr.re_status = RPC_SUCCESS; 2487c478bd9Sstevel@tonic-gate else 2497c478bd9Sstevel@tonic-gate __seterr_reply(&reply_msg, &rpc_callerr); 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate if (rpc_callerr.re_status == RPC_SUCCESS) { 2527c478bd9Sstevel@tonic-gate if (!AUTH_VALIDATE(cl->cl_auth, 2537c478bd9Sstevel@tonic-gate &reply_msg.acpted_rply.ar_verf)) { 2547c478bd9Sstevel@tonic-gate rpc_callerr.re_status = RPC_AUTHERROR; 2557c478bd9Sstevel@tonic-gate rpc_callerr.re_why = AUTH_INVALIDRESP; 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) { 2587c478bd9Sstevel@tonic-gate xdrs.x_op = XDR_FREE; 2597c478bd9Sstevel@tonic-gate (void) xdr_opaque_auth(&xdrs, 2607c478bd9Sstevel@tonic-gate &(reply_msg.acpted_rply.ar_verf)); 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate /* 2647c478bd9Sstevel@tonic-gate * If unsuccesful AND error is an authentication error 2657c478bd9Sstevel@tonic-gate * then refresh credentials and try again, else break 2667c478bd9Sstevel@tonic-gate */ 2677c478bd9Sstevel@tonic-gate else if (rpc_callerr.re_status == RPC_AUTHERROR) { 2687c478bd9Sstevel@tonic-gate /* 2697c478bd9Sstevel@tonic-gate * maybe our credentials need to be refreshed ... 2707c478bd9Sstevel@tonic-gate */ 2717c478bd9Sstevel@tonic-gate if (nrefreshes-- && 2727c478bd9Sstevel@tonic-gate AUTH_REFRESH(cl->cl_auth, &reply_msg)) { 2737c478bd9Sstevel@tonic-gate if (need_to_unmap) 27461961e0fSrobinson (void) munmap(params.rbuf, 27561961e0fSrobinson params.rsize); 2767c478bd9Sstevel@tonic-gate goto call_again; 2777c478bd9Sstevel@tonic-gate } else 2787c478bd9Sstevel@tonic-gate /* 2797c478bd9Sstevel@tonic-gate * We are setting rpc_callerr here given that 2807c478bd9Sstevel@tonic-gate * libnsl is not reentrant thereby 2817c478bd9Sstevel@tonic-gate * reinitializing the TSD. If not set here then 2827c478bd9Sstevel@tonic-gate * success could be returned even though refresh 2837c478bd9Sstevel@tonic-gate * failed. 2847c478bd9Sstevel@tonic-gate */ 2857c478bd9Sstevel@tonic-gate rpc_callerr.re_status = RPC_AUTHERROR; 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate } else 2887c478bd9Sstevel@tonic-gate rpc_callerr.re_status = RPC_CANTDECODERES; 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate done: 2917c478bd9Sstevel@tonic-gate if (need_to_unmap) 29261961e0fSrobinson (void) munmap(params.rbuf, params.rsize); 2937c478bd9Sstevel@tonic-gate return (rpc_callerr.re_status); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2977c478bd9Sstevel@tonic-gate static enum clnt_stat 29861961e0fSrobinson clnt_door_send(CLIENT *cl, rpcproc_t proc, xdrproc_t xargs, caddr_t argsp) 2997c478bd9Sstevel@tonic-gate { 3007c478bd9Sstevel@tonic-gate /* send() call not supported on doors */ 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate rpc_callerr.re_errno = ENOTSUP; 3037c478bd9Sstevel@tonic-gate rpc_callerr.re_terrno = 0; 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate return (rpc_callerr.re_status = RPC_FAILED); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate static void 30961961e0fSrobinson clnt_door_geterr(CLIENT *cl, struct rpc_err *errp) 3107c478bd9Sstevel@tonic-gate { 3117c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 3127c478bd9Sstevel@tonic-gate struct cu_data *cu = (struct cu_data *)cl->cl_private; 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate *errp = rpc_callerr; 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3187c478bd9Sstevel@tonic-gate static bool_t 31961961e0fSrobinson clnt_door_freeres(CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr) 3207c478bd9Sstevel@tonic-gate { 3217c478bd9Sstevel@tonic-gate XDR xdrs; 3227c478bd9Sstevel@tonic-gate 32361961e0fSrobinson (void) memset(&xdrs, 0, sizeof (xdrs)); 3247c478bd9Sstevel@tonic-gate xdrs.x_op = XDR_FREE; 3257c478bd9Sstevel@tonic-gate return ((*xdr_res)(&xdrs, res_ptr)); 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate static void 32961961e0fSrobinson clnt_door_abort(CLIENT *cl) 3307c478bd9Sstevel@tonic-gate { 3317c478bd9Sstevel@tonic-gate cl = cl; 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate static bool_t 33561961e0fSrobinson clnt_door_control(CLIENT *cl, int request, char *info) 3367c478bd9Sstevel@tonic-gate { 3377c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 3387c478bd9Sstevel@tonic-gate struct cu_data *cu = (struct cu_data *)cl->cl_private; 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate switch (request) { 3417c478bd9Sstevel@tonic-gate case CLSET_FD_CLOSE: 3427c478bd9Sstevel@tonic-gate cu->cu_closeit = TRUE; 3437c478bd9Sstevel@tonic-gate return (TRUE); 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate case CLSET_FD_NCLOSE: 3467c478bd9Sstevel@tonic-gate cu->cu_closeit = FALSE; 3477c478bd9Sstevel@tonic-gate return (TRUE); 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate /* for other requests which use info */ 3517c478bd9Sstevel@tonic-gate if (info == NULL) 3527c478bd9Sstevel@tonic-gate return (FALSE); 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate switch (request) { 3557c478bd9Sstevel@tonic-gate case CLGET_FD: 3567c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 3577c478bd9Sstevel@tonic-gate *(int *)info = cu->cu_fd; 3587c478bd9Sstevel@tonic-gate break; 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate case CLGET_XID: 3617c478bd9Sstevel@tonic-gate /* 3627c478bd9Sstevel@tonic-gate * use the knowledge that xid is the 3637c478bd9Sstevel@tonic-gate * first element in the call structure *. 3647c478bd9Sstevel@tonic-gate * This will get the xid of the PREVIOUS call 3657c478bd9Sstevel@tonic-gate */ 3667c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 3677c478bd9Sstevel@tonic-gate *(uint32_t *)info = ntohl(*(uint32_t *)cu->cu_header); 3687c478bd9Sstevel@tonic-gate break; 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate case CLSET_XID: 3717c478bd9Sstevel@tonic-gate /* This will set the xid of the NEXT call */ 3727c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 3737c478bd9Sstevel@tonic-gate *(uint32_t *)cu->cu_header = htonl(*(uint32_t *)info - 1); 3747c478bd9Sstevel@tonic-gate /* decrement by 1 as clnt_door_call() increments once */ 3757c478bd9Sstevel@tonic-gate break; 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate case CLGET_VERS: 3787c478bd9Sstevel@tonic-gate /* 3797c478bd9Sstevel@tonic-gate * This RELIES on the information that, in the call body, 3807c478bd9Sstevel@tonic-gate * the version number field is the fifth field from the 3817c478bd9Sstevel@tonic-gate * begining of the RPC header. MUST be changed if the 3827c478bd9Sstevel@tonic-gate * call_struct is changed 3837c478bd9Sstevel@tonic-gate */ 3847c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 3857c478bd9Sstevel@tonic-gate *(uint32_t *)info = ntohl(*(uint32_t *)(cu->cu_header + 3867c478bd9Sstevel@tonic-gate 4 * BYTES_PER_XDR_UNIT)); 3877c478bd9Sstevel@tonic-gate break; 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate case CLSET_VERS: 3907c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 3917c478bd9Sstevel@tonic-gate *(uint32_t *)(cu->cu_header + 4 * BYTES_PER_XDR_UNIT) = 3927c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 3937c478bd9Sstevel@tonic-gate htonl(*(uint32_t *)info); 3947c478bd9Sstevel@tonic-gate break; 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate case CLGET_PROG: 3977c478bd9Sstevel@tonic-gate /* 3987c478bd9Sstevel@tonic-gate * This RELIES on the information that, in the call body, 3997c478bd9Sstevel@tonic-gate * the program number field is the fourth field from the 4007c478bd9Sstevel@tonic-gate * begining of the RPC header. MUST be changed if the 4017c478bd9Sstevel@tonic-gate * call_struct is changed 4027c478bd9Sstevel@tonic-gate */ 4037c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 4047c478bd9Sstevel@tonic-gate *(uint32_t *)info = ntohl(*(uint32_t *)(cu->cu_header + 4057c478bd9Sstevel@tonic-gate 3 * BYTES_PER_XDR_UNIT)); 4067c478bd9Sstevel@tonic-gate break; 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate case CLSET_PROG: 4097c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 4107c478bd9Sstevel@tonic-gate *(uint32_t *)(cu->cu_header + 3 * BYTES_PER_XDR_UNIT) = 4117c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 4127c478bd9Sstevel@tonic-gate htonl(*(uint32_t *)info); 4137c478bd9Sstevel@tonic-gate break; 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate default: 4167c478bd9Sstevel@tonic-gate return (FALSE); 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate return (TRUE); 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate static void 42261961e0fSrobinson clnt_door_destroy(CLIENT *cl) 4237c478bd9Sstevel@tonic-gate { 4247c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 4257c478bd9Sstevel@tonic-gate struct cu_data *cu = (struct cu_data *)cl->cl_private; 4267c478bd9Sstevel@tonic-gate int cu_fd = cu->cu_fd; 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate if (cu->cu_closeit) 42961961e0fSrobinson (void) close(cu_fd); 43061961e0fSrobinson free(cu); 4317c478bd9Sstevel@tonic-gate if (cl->cl_netid && cl->cl_netid[0]) 43261961e0fSrobinson free(cl->cl_netid); 4337c478bd9Sstevel@tonic-gate if (cl->cl_tp && cl->cl_tp[0]) 43461961e0fSrobinson free(cl->cl_tp); 43561961e0fSrobinson free(cl); 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate static struct clnt_ops * 43961961e0fSrobinson clnt_door_ops(void) 4407c478bd9Sstevel@tonic-gate { 4417c478bd9Sstevel@tonic-gate static struct clnt_ops ops; 4427c478bd9Sstevel@tonic-gate extern mutex_t ops_lock; 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate sig_mutex_lock(&ops_lock); 4457c478bd9Sstevel@tonic-gate if (ops.cl_call == NULL) { 4467c478bd9Sstevel@tonic-gate ops.cl_call = clnt_door_call; 4477c478bd9Sstevel@tonic-gate ops.cl_send = clnt_door_send; 4487c478bd9Sstevel@tonic-gate ops.cl_abort = clnt_door_abort; 4497c478bd9Sstevel@tonic-gate ops.cl_geterr = clnt_door_geterr; 4507c478bd9Sstevel@tonic-gate ops.cl_freeres = clnt_door_freeres; 4517c478bd9Sstevel@tonic-gate ops.cl_destroy = clnt_door_destroy; 4527c478bd9Sstevel@tonic-gate ops.cl_control = clnt_door_control; 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate sig_mutex_unlock(&ops_lock); 4557c478bd9Sstevel@tonic-gate return (&ops); 4567c478bd9Sstevel@tonic-gate } 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate int 45961961e0fSrobinson _update_did(CLIENT *cl, int vers) 4607c478bd9Sstevel@tonic-gate { 4617c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 4627c478bd9Sstevel@tonic-gate struct cu_data *cu = (struct cu_data *)cl->cl_private; 4637c478bd9Sstevel@tonic-gate rpcprog_t prog; 4647c478bd9Sstevel@tonic-gate char rendezvous[64]; 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate if (cu->cu_fd >= 0) 46761961e0fSrobinson (void) close(cu->cu_fd); 4687c478bd9Sstevel@tonic-gate /* Make sure that the right door id is used in door_call. */ 4697c478bd9Sstevel@tonic-gate clnt_control(cl, CLGET_PROG, (void *)&prog); 47061961e0fSrobinson (void) sprintf(rendezvous, RPC_DOOR_RENDEZVOUS, (int)prog, vers); 4717c478bd9Sstevel@tonic-gate if ((cu->cu_fd = open(rendezvous, O_RDONLY, 0)) < 0) { 4727c478bd9Sstevel@tonic-gate rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; 4737c478bd9Sstevel@tonic-gate rpc_createerr.cf_error.re_errno = errno; 4747c478bd9Sstevel@tonic-gate rpc_createerr.cf_error.re_terrno = 0; 4757c478bd9Sstevel@tonic-gate return (0); 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate free(cl->cl_tp); 4787c478bd9Sstevel@tonic-gate cl->cl_tp = strdup(rendezvous); 4797c478bd9Sstevel@tonic-gate if (cl->cl_tp == NULL) { 4807c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "_update_did: strdup failed"); 4817c478bd9Sstevel@tonic-gate rpc_createerr.cf_stat = RPC_SYSTEMERROR; 4827c478bd9Sstevel@tonic-gate rpc_createerr.cf_error.re_errno = errno; 4837c478bd9Sstevel@tonic-gate rpc_createerr.cf_error.re_terrno = 0; 4847c478bd9Sstevel@tonic-gate return (0); 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate return (1); 4877c478bd9Sstevel@tonic-gate } 488