111963SAfshin.Ardakani@Sun.COM /*
211963SAfshin.Ardakani@Sun.COM * CDDL HEADER START
311963SAfshin.Ardakani@Sun.COM *
411963SAfshin.Ardakani@Sun.COM * The contents of this file are subject to the terms of the
511963SAfshin.Ardakani@Sun.COM * Common Development and Distribution License (the "License").
611963SAfshin.Ardakani@Sun.COM * You may not use this file except in compliance with the License.
711963SAfshin.Ardakani@Sun.COM *
811963SAfshin.Ardakani@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911963SAfshin.Ardakani@Sun.COM * or http://www.opensolaris.org/os/licensing.
1011963SAfshin.Ardakani@Sun.COM * See the License for the specific language governing permissions
1111963SAfshin.Ardakani@Sun.COM * and limitations under the License.
1211963SAfshin.Ardakani@Sun.COM *
1311963SAfshin.Ardakani@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1411963SAfshin.Ardakani@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1511963SAfshin.Ardakani@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1611963SAfshin.Ardakani@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1711963SAfshin.Ardakani@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1811963SAfshin.Ardakani@Sun.COM *
1911963SAfshin.Ardakani@Sun.COM * CDDL HEADER END
2011963SAfshin.Ardakani@Sun.COM */
2111963SAfshin.Ardakani@Sun.COM /*
22*12890SJoyce.McIntosh@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
2311963SAfshin.Ardakani@Sun.COM */
2411963SAfshin.Ardakani@Sun.COM
2511963SAfshin.Ardakani@Sun.COM #include <sys/types.h>
2611963SAfshin.Ardakani@Sun.COM #include <sys/kmem.h>
2711963SAfshin.Ardakani@Sun.COM #include <sys/ddi.h>
2811963SAfshin.Ardakani@Sun.COM #include <sys/sunddi.h>
2911963SAfshin.Ardakani@Sun.COM #include <sys/cmn_err.h>
3011963SAfshin.Ardakani@Sun.COM #include <sys/door.h>
3111963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_kproto.h>
3211963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_door.h>
3311963SAfshin.Ardakani@Sun.COM
3411963SAfshin.Ardakani@Sun.COM static int smb_kdoor_send(smb_doorarg_t *);
3511963SAfshin.Ardakani@Sun.COM static int smb_kdoor_receive(smb_doorarg_t *);
3611963SAfshin.Ardakani@Sun.COM static int smb_kdoor_upcall_private(smb_doorarg_t *);
3711963SAfshin.Ardakani@Sun.COM static int smb_kdoor_encode(smb_doorarg_t *);
3811963SAfshin.Ardakani@Sun.COM static int smb_kdoor_decode(smb_doorarg_t *);
3911963SAfshin.Ardakani@Sun.COM static void smb_kdoor_sethdr(smb_doorarg_t *, uint32_t);
4011963SAfshin.Ardakani@Sun.COM static boolean_t smb_kdoor_chkhdr(smb_doorarg_t *, smb_doorhdr_t *);
4111963SAfshin.Ardakani@Sun.COM static void smb_kdoor_free(door_arg_t *);
4211963SAfshin.Ardakani@Sun.COM
4311963SAfshin.Ardakani@Sun.COM door_handle_t smb_kdoor_hd = NULL;
4411963SAfshin.Ardakani@Sun.COM static int smb_kdoor_id = -1;
4511963SAfshin.Ardakani@Sun.COM static uint64_t smb_kdoor_ncall = 0;
4611963SAfshin.Ardakani@Sun.COM static kmutex_t smb_kdoor_mutex;
4711963SAfshin.Ardakani@Sun.COM static kcondvar_t smb_kdoor_cv;
4811963SAfshin.Ardakani@Sun.COM
4911963SAfshin.Ardakani@Sun.COM void
smb_kdoor_init(void)5011963SAfshin.Ardakani@Sun.COM smb_kdoor_init(void)
5111963SAfshin.Ardakani@Sun.COM {
5211963SAfshin.Ardakani@Sun.COM mutex_init(&smb_kdoor_mutex, NULL, MUTEX_DEFAULT, NULL);
5311963SAfshin.Ardakani@Sun.COM cv_init(&smb_kdoor_cv, NULL, CV_DEFAULT, NULL);
5411963SAfshin.Ardakani@Sun.COM }
5511963SAfshin.Ardakani@Sun.COM
5611963SAfshin.Ardakani@Sun.COM void
smb_kdoor_fini(void)5711963SAfshin.Ardakani@Sun.COM smb_kdoor_fini(void)
5811963SAfshin.Ardakani@Sun.COM {
5911963SAfshin.Ardakani@Sun.COM smb_kdoor_close();
6011963SAfshin.Ardakani@Sun.COM cv_destroy(&smb_kdoor_cv);
6111963SAfshin.Ardakani@Sun.COM mutex_destroy(&smb_kdoor_mutex);
6211963SAfshin.Ardakani@Sun.COM }
6311963SAfshin.Ardakani@Sun.COM
6411963SAfshin.Ardakani@Sun.COM /*
6511963SAfshin.Ardakani@Sun.COM * Open the door. If the door is already open, close it first
6611963SAfshin.Ardakani@Sun.COM * because the door-id has probably changed.
6711963SAfshin.Ardakani@Sun.COM */
6811963SAfshin.Ardakani@Sun.COM int
smb_kdoor_open(int door_id)6911963SAfshin.Ardakani@Sun.COM smb_kdoor_open(int door_id)
7011963SAfshin.Ardakani@Sun.COM {
7111963SAfshin.Ardakani@Sun.COM int rc;
7211963SAfshin.Ardakani@Sun.COM
7311963SAfshin.Ardakani@Sun.COM smb_kdoor_close();
7411963SAfshin.Ardakani@Sun.COM
7511963SAfshin.Ardakani@Sun.COM mutex_enter(&smb_kdoor_mutex);
7611963SAfshin.Ardakani@Sun.COM smb_kdoor_ncall = 0;
7711963SAfshin.Ardakani@Sun.COM
7811963SAfshin.Ardakani@Sun.COM if (smb_kdoor_hd == NULL) {
7911963SAfshin.Ardakani@Sun.COM smb_kdoor_id = door_id;
8011963SAfshin.Ardakani@Sun.COM smb_kdoor_hd = door_ki_lookup(door_id);
8111963SAfshin.Ardakani@Sun.COM }
8211963SAfshin.Ardakani@Sun.COM
8311963SAfshin.Ardakani@Sun.COM rc = (smb_kdoor_hd == NULL) ? -1 : 0;
8411963SAfshin.Ardakani@Sun.COM mutex_exit(&smb_kdoor_mutex);
8511963SAfshin.Ardakani@Sun.COM return (rc);
8611963SAfshin.Ardakani@Sun.COM }
8711963SAfshin.Ardakani@Sun.COM
8811963SAfshin.Ardakani@Sun.COM /*
8911963SAfshin.Ardakani@Sun.COM * Close the door.
9011963SAfshin.Ardakani@Sun.COM */
9111963SAfshin.Ardakani@Sun.COM void
smb_kdoor_close(void)9211963SAfshin.Ardakani@Sun.COM smb_kdoor_close(void)
9311963SAfshin.Ardakani@Sun.COM {
9411963SAfshin.Ardakani@Sun.COM mutex_enter(&smb_kdoor_mutex);
9511963SAfshin.Ardakani@Sun.COM
9611963SAfshin.Ardakani@Sun.COM if (smb_kdoor_hd != NULL) {
9711963SAfshin.Ardakani@Sun.COM while (smb_kdoor_ncall > 0)
9811963SAfshin.Ardakani@Sun.COM cv_wait(&smb_kdoor_cv, &smb_kdoor_mutex);
9911963SAfshin.Ardakani@Sun.COM
10011963SAfshin.Ardakani@Sun.COM door_ki_rele(smb_kdoor_hd);
10111963SAfshin.Ardakani@Sun.COM smb_kdoor_hd = NULL;
10211963SAfshin.Ardakani@Sun.COM }
10311963SAfshin.Ardakani@Sun.COM
10411963SAfshin.Ardakani@Sun.COM mutex_exit(&smb_kdoor_mutex);
10511963SAfshin.Ardakani@Sun.COM }
10611963SAfshin.Ardakani@Sun.COM
10711963SAfshin.Ardakani@Sun.COM /*
10811963SAfshin.Ardakani@Sun.COM * Wrapper to handle door call reference counting.
10911963SAfshin.Ardakani@Sun.COM */
11011963SAfshin.Ardakani@Sun.COM int
smb_kdoor_upcall(uint32_t cmd,void * req_data,xdrproc_t req_xdr,void * rsp_data,xdrproc_t rsp_xdr)11111963SAfshin.Ardakani@Sun.COM smb_kdoor_upcall(uint32_t cmd, void *req_data, xdrproc_t req_xdr,
11211963SAfshin.Ardakani@Sun.COM void *rsp_data, xdrproc_t rsp_xdr)
11311963SAfshin.Ardakani@Sun.COM {
11411963SAfshin.Ardakani@Sun.COM smb_doorarg_t da;
11511963SAfshin.Ardakani@Sun.COM int rc;
11611963SAfshin.Ardakani@Sun.COM
11711963SAfshin.Ardakani@Sun.COM bzero(&da, sizeof (smb_doorarg_t));
11811963SAfshin.Ardakani@Sun.COM da.da_opcode = cmd;
11911963SAfshin.Ardakani@Sun.COM da.da_opname = smb_doorhdr_opname(cmd);
12011963SAfshin.Ardakani@Sun.COM da.da_req_xdr = req_xdr;
12111963SAfshin.Ardakani@Sun.COM da.da_rsp_xdr = rsp_xdr;
12211963SAfshin.Ardakani@Sun.COM da.da_req_data = req_data;
12311963SAfshin.Ardakani@Sun.COM da.da_rsp_data = rsp_data;
12411963SAfshin.Ardakani@Sun.COM
12511963SAfshin.Ardakani@Sun.COM if ((req_data == NULL && req_xdr != NULL) ||
12611963SAfshin.Ardakani@Sun.COM (rsp_data == NULL && rsp_xdr != NULL)) {
12711963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "smb_kdoor_upcall[%s]: invalid param",
12811963SAfshin.Ardakani@Sun.COM da.da_opname);
12911963SAfshin.Ardakani@Sun.COM return (-1);
13011963SAfshin.Ardakani@Sun.COM }
13111963SAfshin.Ardakani@Sun.COM
13211963SAfshin.Ardakani@Sun.COM if (rsp_data != NULL && rsp_xdr != NULL)
13311963SAfshin.Ardakani@Sun.COM da.da_flags = SMB_DF_ASYNC;
13411963SAfshin.Ardakani@Sun.COM
135*12890SJoyce.McIntosh@Sun.COM if ((da.da_event = smb_event_create(SMB_EVENT_TIMEOUT)) == NULL)
13611963SAfshin.Ardakani@Sun.COM return (-1);
13711963SAfshin.Ardakani@Sun.COM
13811963SAfshin.Ardakani@Sun.COM mutex_enter(&smb_kdoor_mutex);
13911963SAfshin.Ardakani@Sun.COM
14011963SAfshin.Ardakani@Sun.COM if (smb_kdoor_hd == NULL) {
14111963SAfshin.Ardakani@Sun.COM mutex_exit(&smb_kdoor_mutex);
14211963SAfshin.Ardakani@Sun.COM
14311963SAfshin.Ardakani@Sun.COM if (smb_kdoor_open(smb_kdoor_id) != 0) {
14411963SAfshin.Ardakani@Sun.COM smb_event_destroy(da.da_event);
14511963SAfshin.Ardakani@Sun.COM return (-1);
14611963SAfshin.Ardakani@Sun.COM }
14711963SAfshin.Ardakani@Sun.COM
14811963SAfshin.Ardakani@Sun.COM mutex_enter(&smb_kdoor_mutex);
14911963SAfshin.Ardakani@Sun.COM }
15011963SAfshin.Ardakani@Sun.COM
15111963SAfshin.Ardakani@Sun.COM ++smb_kdoor_ncall;
15211963SAfshin.Ardakani@Sun.COM mutex_exit(&smb_kdoor_mutex);
15311963SAfshin.Ardakani@Sun.COM
15411963SAfshin.Ardakani@Sun.COM if (da.da_flags & SMB_DF_ASYNC) {
15511963SAfshin.Ardakani@Sun.COM if ((rc = smb_kdoor_send(&da)) == 0) {
15611963SAfshin.Ardakani@Sun.COM if (smb_event_wait(da.da_event) != 0)
15711963SAfshin.Ardakani@Sun.COM rc = -1;
15811963SAfshin.Ardakani@Sun.COM else
15911963SAfshin.Ardakani@Sun.COM rc = smb_kdoor_receive(&da);
16011963SAfshin.Ardakani@Sun.COM }
16111963SAfshin.Ardakani@Sun.COM } else {
16211963SAfshin.Ardakani@Sun.COM if ((rc = smb_kdoor_encode(&da)) == 0) {
16311963SAfshin.Ardakani@Sun.COM if ((rc = smb_kdoor_upcall_private(&da)) == 0)
16411963SAfshin.Ardakani@Sun.COM rc = smb_kdoor_decode(&da);
16511963SAfshin.Ardakani@Sun.COM }
16611963SAfshin.Ardakani@Sun.COM smb_kdoor_free(&da.da_arg);
16711963SAfshin.Ardakani@Sun.COM }
16811963SAfshin.Ardakani@Sun.COM
16911963SAfshin.Ardakani@Sun.COM smb_event_destroy(da.da_event);
17011963SAfshin.Ardakani@Sun.COM
17111963SAfshin.Ardakani@Sun.COM mutex_enter(&smb_kdoor_mutex);
17211963SAfshin.Ardakani@Sun.COM if ((--smb_kdoor_ncall) == 0)
17311963SAfshin.Ardakani@Sun.COM cv_signal(&smb_kdoor_cv);
17411963SAfshin.Ardakani@Sun.COM mutex_exit(&smb_kdoor_mutex);
17511963SAfshin.Ardakani@Sun.COM return (rc);
17611963SAfshin.Ardakani@Sun.COM }
17711963SAfshin.Ardakani@Sun.COM
17811963SAfshin.Ardakani@Sun.COM /*
17911963SAfshin.Ardakani@Sun.COM * Send the request half of the consumer's door call.
18011963SAfshin.Ardakani@Sun.COM */
18111963SAfshin.Ardakani@Sun.COM static int
smb_kdoor_send(smb_doorarg_t * outer_da)18211963SAfshin.Ardakani@Sun.COM smb_kdoor_send(smb_doorarg_t *outer_da)
18311963SAfshin.Ardakani@Sun.COM {
18411963SAfshin.Ardakani@Sun.COM smb_doorarg_t da;
18511963SAfshin.Ardakani@Sun.COM int rc;
18611963SAfshin.Ardakani@Sun.COM
18711963SAfshin.Ardakani@Sun.COM bcopy(outer_da, &da, sizeof (smb_doorarg_t));
18811963SAfshin.Ardakani@Sun.COM da.da_rsp_xdr = NULL;
18911963SAfshin.Ardakani@Sun.COM da.da_rsp_data = NULL;
19011963SAfshin.Ardakani@Sun.COM
19111963SAfshin.Ardakani@Sun.COM if (smb_kdoor_encode(&da) != 0)
19211963SAfshin.Ardakani@Sun.COM return (-1);
19311963SAfshin.Ardakani@Sun.COM
19411963SAfshin.Ardakani@Sun.COM if ((rc = smb_kdoor_upcall_private(&da)) == 0)
19511963SAfshin.Ardakani@Sun.COM rc = smb_kdoor_decode(&da);
19611963SAfshin.Ardakani@Sun.COM
19711963SAfshin.Ardakani@Sun.COM smb_kdoor_free(&da.da_arg);
19811963SAfshin.Ardakani@Sun.COM return (rc);
19911963SAfshin.Ardakani@Sun.COM }
20011963SAfshin.Ardakani@Sun.COM
20111963SAfshin.Ardakani@Sun.COM /*
20211963SAfshin.Ardakani@Sun.COM * Get the response half for the consumer's door call.
20311963SAfshin.Ardakani@Sun.COM */
20411963SAfshin.Ardakani@Sun.COM static int
smb_kdoor_receive(smb_doorarg_t * outer_da)20511963SAfshin.Ardakani@Sun.COM smb_kdoor_receive(smb_doorarg_t *outer_da)
20611963SAfshin.Ardakani@Sun.COM {
20711963SAfshin.Ardakani@Sun.COM smb_doorarg_t da;
20811963SAfshin.Ardakani@Sun.COM int rc;
20911963SAfshin.Ardakani@Sun.COM
21011963SAfshin.Ardakani@Sun.COM bcopy(outer_da, &da, sizeof (smb_doorarg_t));
21111963SAfshin.Ardakani@Sun.COM da.da_opcode = SMB_DR_ASYNC_RESPONSE;
21211963SAfshin.Ardakani@Sun.COM da.da_opname = smb_doorhdr_opname(da.da_opcode);
21311963SAfshin.Ardakani@Sun.COM da.da_flags &= ~SMB_DF_ASYNC;
21411963SAfshin.Ardakani@Sun.COM da.da_req_xdr = NULL;
21511963SAfshin.Ardakani@Sun.COM da.da_req_data = NULL;
21611963SAfshin.Ardakani@Sun.COM
21711963SAfshin.Ardakani@Sun.COM if (smb_kdoor_encode(&da) != 0)
21811963SAfshin.Ardakani@Sun.COM return (-1);
21911963SAfshin.Ardakani@Sun.COM
22011963SAfshin.Ardakani@Sun.COM if ((rc = smb_kdoor_upcall_private(&da)) == 0)
22111963SAfshin.Ardakani@Sun.COM rc = smb_kdoor_decode(&da);
22211963SAfshin.Ardakani@Sun.COM
22311963SAfshin.Ardakani@Sun.COM smb_kdoor_free(&da.da_arg);
22411963SAfshin.Ardakani@Sun.COM return (rc);
22511963SAfshin.Ardakani@Sun.COM }
22611963SAfshin.Ardakani@Sun.COM
22711963SAfshin.Ardakani@Sun.COM /*
22811963SAfshin.Ardakani@Sun.COM * We use a copy of the door arg because doorfs may change data_ptr
22911963SAfshin.Ardakani@Sun.COM * and we want to detect that when freeing the door buffers. After
23011963SAfshin.Ardakani@Sun.COM * this call, response data must be referenced via rbuf and rsize.
23111963SAfshin.Ardakani@Sun.COM */
23211963SAfshin.Ardakani@Sun.COM static int
smb_kdoor_upcall_private(smb_doorarg_t * da)23311963SAfshin.Ardakani@Sun.COM smb_kdoor_upcall_private(smb_doorarg_t *da)
23411963SAfshin.Ardakani@Sun.COM {
23511963SAfshin.Ardakani@Sun.COM door_arg_t door_arg;
23611963SAfshin.Ardakani@Sun.COM int i;
23711963SAfshin.Ardakani@Sun.COM int rc;
23811963SAfshin.Ardakani@Sun.COM
23911963SAfshin.Ardakani@Sun.COM bcopy(&da->da_arg, &door_arg, sizeof (door_arg_t));
24011963SAfshin.Ardakani@Sun.COM
24111963SAfshin.Ardakani@Sun.COM for (i = 0; i < SMB_DOOR_CALL_RETRIES; ++i) {
24211963SAfshin.Ardakani@Sun.COM if (smb_server_is_stopping())
24311963SAfshin.Ardakani@Sun.COM return (-1);
24411963SAfshin.Ardakani@Sun.COM
24511963SAfshin.Ardakani@Sun.COM if ((rc = door_ki_upcall_limited(smb_kdoor_hd, &door_arg,
24611963SAfshin.Ardakani@Sun.COM NULL, SIZE_MAX, 0)) == 0)
24711963SAfshin.Ardakani@Sun.COM break;
24811963SAfshin.Ardakani@Sun.COM
24911963SAfshin.Ardakani@Sun.COM if (rc != EAGAIN && rc != EINTR)
25011963SAfshin.Ardakani@Sun.COM return (-1);
25111963SAfshin.Ardakani@Sun.COM }
25211963SAfshin.Ardakani@Sun.COM
25311963SAfshin.Ardakani@Sun.COM if (rc != 0 || door_arg.data_size == 0 || door_arg.rsize == 0)
25411963SAfshin.Ardakani@Sun.COM return (-1);
25511963SAfshin.Ardakani@Sun.COM
25611963SAfshin.Ardakani@Sun.COM da->da_arg.rbuf = door_arg.data_ptr;
25711963SAfshin.Ardakani@Sun.COM da->da_arg.rsize = door_arg.rsize;
25811963SAfshin.Ardakani@Sun.COM return (0);
25911963SAfshin.Ardakani@Sun.COM }
26011963SAfshin.Ardakani@Sun.COM
26111963SAfshin.Ardakani@Sun.COM static int
smb_kdoor_encode(smb_doorarg_t * da)26211963SAfshin.Ardakani@Sun.COM smb_kdoor_encode(smb_doorarg_t *da)
26311963SAfshin.Ardakani@Sun.COM {
26411963SAfshin.Ardakani@Sun.COM XDR xdrs;
26511963SAfshin.Ardakani@Sun.COM char *buf;
26611963SAfshin.Ardakani@Sun.COM uint32_t len;
26711963SAfshin.Ardakani@Sun.COM
26811963SAfshin.Ardakani@Sun.COM len = xdr_sizeof(smb_doorhdr_xdr, &da->da_hdr);
26911963SAfshin.Ardakani@Sun.COM if (da->da_req_xdr != NULL)
27011963SAfshin.Ardakani@Sun.COM len += xdr_sizeof(da->da_req_xdr, da->da_req_data);
27111963SAfshin.Ardakani@Sun.COM
27211963SAfshin.Ardakani@Sun.COM smb_kdoor_sethdr(da, len);
27311963SAfshin.Ardakani@Sun.COM
27411963SAfshin.Ardakani@Sun.COM buf = kmem_zalloc(len, KM_SLEEP);
27511963SAfshin.Ardakani@Sun.COM xdrmem_create(&xdrs, buf, len, XDR_ENCODE);
27611963SAfshin.Ardakani@Sun.COM
27711963SAfshin.Ardakani@Sun.COM if (!smb_doorhdr_xdr(&xdrs, &da->da_hdr)) {
27811963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "smb_kdoor_encode[%s]: header encode failed",
27911963SAfshin.Ardakani@Sun.COM da->da_opname);
28011963SAfshin.Ardakani@Sun.COM kmem_free(buf, len);
28111963SAfshin.Ardakani@Sun.COM xdr_destroy(&xdrs);
28211963SAfshin.Ardakani@Sun.COM return (-1);
28311963SAfshin.Ardakani@Sun.COM }
28411963SAfshin.Ardakani@Sun.COM
28511963SAfshin.Ardakani@Sun.COM if (da->da_req_xdr != NULL) {
28611963SAfshin.Ardakani@Sun.COM if (!da->da_req_xdr(&xdrs, da->da_req_data)) {
28711963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "smb_kdoor_encode[%s]: encode failed",
28811963SAfshin.Ardakani@Sun.COM da->da_opname);
28911963SAfshin.Ardakani@Sun.COM kmem_free(buf, len);
29011963SAfshin.Ardakani@Sun.COM xdr_destroy(&xdrs);
29111963SAfshin.Ardakani@Sun.COM return (-1);
29211963SAfshin.Ardakani@Sun.COM }
29311963SAfshin.Ardakani@Sun.COM }
29411963SAfshin.Ardakani@Sun.COM
29511963SAfshin.Ardakani@Sun.COM da->da_arg.data_ptr = buf;
29611963SAfshin.Ardakani@Sun.COM da->da_arg.data_size = len;
29711963SAfshin.Ardakani@Sun.COM da->da_arg.desc_ptr = NULL;
29811963SAfshin.Ardakani@Sun.COM da->da_arg.desc_num = 0;
29911963SAfshin.Ardakani@Sun.COM da->da_arg.rbuf = buf;
30011963SAfshin.Ardakani@Sun.COM da->da_arg.rsize = len;
30111963SAfshin.Ardakani@Sun.COM
30211963SAfshin.Ardakani@Sun.COM xdr_destroy(&xdrs);
30311963SAfshin.Ardakani@Sun.COM return (0);
30411963SAfshin.Ardakani@Sun.COM }
30511963SAfshin.Ardakani@Sun.COM
30611963SAfshin.Ardakani@Sun.COM /*
30711963SAfshin.Ardakani@Sun.COM * Decode the response in rbuf and rsize.
30811963SAfshin.Ardakani@Sun.COM */
30911963SAfshin.Ardakani@Sun.COM static int
smb_kdoor_decode(smb_doorarg_t * da)31011963SAfshin.Ardakani@Sun.COM smb_kdoor_decode(smb_doorarg_t *da)
31111963SAfshin.Ardakani@Sun.COM {
31211963SAfshin.Ardakani@Sun.COM XDR xdrs;
31311963SAfshin.Ardakani@Sun.COM smb_doorhdr_t hdr;
31411963SAfshin.Ardakani@Sun.COM char *rbuf = da->da_arg.rbuf;
31511963SAfshin.Ardakani@Sun.COM uint32_t rsize = da->da_arg.rsize;
31611963SAfshin.Ardakani@Sun.COM
31711963SAfshin.Ardakani@Sun.COM if (rbuf == NULL || rsize == 0) {
31811963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "smb_kdoor_decode[%s]: invalid param",
31911963SAfshin.Ardakani@Sun.COM da->da_opname);
32011963SAfshin.Ardakani@Sun.COM return (-1);
32111963SAfshin.Ardakani@Sun.COM }
32211963SAfshin.Ardakani@Sun.COM
32311963SAfshin.Ardakani@Sun.COM xdrmem_create(&xdrs, rbuf, rsize, XDR_DECODE);
32411963SAfshin.Ardakani@Sun.COM
32511963SAfshin.Ardakani@Sun.COM if (!smb_doorhdr_xdr(&xdrs, &hdr)) {
32611963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "smb_kdoor_decode[%s]: header decode failed",
32711963SAfshin.Ardakani@Sun.COM da->da_opname);
32811963SAfshin.Ardakani@Sun.COM xdr_destroy(&xdrs);
32911963SAfshin.Ardakani@Sun.COM return (-1);
33011963SAfshin.Ardakani@Sun.COM }
33111963SAfshin.Ardakani@Sun.COM
33211963SAfshin.Ardakani@Sun.COM if (!smb_kdoor_chkhdr(da, &hdr)) {
33311963SAfshin.Ardakani@Sun.COM xdr_destroy(&xdrs);
33411963SAfshin.Ardakani@Sun.COM return (-1);
33511963SAfshin.Ardakani@Sun.COM }
33611963SAfshin.Ardakani@Sun.COM
33711963SAfshin.Ardakani@Sun.COM if (hdr.dh_datalen != 0 && da->da_rsp_xdr != NULL) {
33811963SAfshin.Ardakani@Sun.COM if (!da->da_rsp_xdr(&xdrs, da->da_rsp_data)) {
33911963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "smb_kdoor_decode[%s]: decode failed",
34011963SAfshin.Ardakani@Sun.COM da->da_opname);
34111963SAfshin.Ardakani@Sun.COM xdr_destroy(&xdrs);
34211963SAfshin.Ardakani@Sun.COM return (-1);
34311963SAfshin.Ardakani@Sun.COM }
34411963SAfshin.Ardakani@Sun.COM }
34511963SAfshin.Ardakani@Sun.COM
34611963SAfshin.Ardakani@Sun.COM xdr_destroy(&xdrs);
34711963SAfshin.Ardakani@Sun.COM return (0);
34811963SAfshin.Ardakani@Sun.COM }
34911963SAfshin.Ardakani@Sun.COM
35011963SAfshin.Ardakani@Sun.COM static void
smb_kdoor_sethdr(smb_doorarg_t * da,uint32_t datalen)35111963SAfshin.Ardakani@Sun.COM smb_kdoor_sethdr(smb_doorarg_t *da, uint32_t datalen)
35211963SAfshin.Ardakani@Sun.COM {
35311963SAfshin.Ardakani@Sun.COM smb_doorhdr_t *hdr = &da->da_hdr;
35411963SAfshin.Ardakani@Sun.COM
35511963SAfshin.Ardakani@Sun.COM bzero(hdr, sizeof (smb_doorhdr_t));
35611963SAfshin.Ardakani@Sun.COM hdr->dh_magic = SMB_DOOR_HDR_MAGIC;
35711963SAfshin.Ardakani@Sun.COM hdr->dh_flags = da->da_flags | SMB_DF_SYSSPACE;
35811963SAfshin.Ardakani@Sun.COM hdr->dh_op = da->da_opcode;
35911963SAfshin.Ardakani@Sun.COM hdr->dh_txid = smb_event_txid(da->da_event);
36011963SAfshin.Ardakani@Sun.COM hdr->dh_datalen = datalen;
36111963SAfshin.Ardakani@Sun.COM hdr->dh_door_rc = SMB_DOP_NOT_CALLED;
36211963SAfshin.Ardakani@Sun.COM }
36311963SAfshin.Ardakani@Sun.COM
36411963SAfshin.Ardakani@Sun.COM static boolean_t
smb_kdoor_chkhdr(smb_doorarg_t * da,smb_doorhdr_t * hdr)36511963SAfshin.Ardakani@Sun.COM smb_kdoor_chkhdr(smb_doorarg_t *da, smb_doorhdr_t *hdr)
36611963SAfshin.Ardakani@Sun.COM {
36711963SAfshin.Ardakani@Sun.COM if ((hdr->dh_magic != SMB_DOOR_HDR_MAGIC) ||
36811963SAfshin.Ardakani@Sun.COM (hdr->dh_op != da->da_hdr.dh_op) ||
36911963SAfshin.Ardakani@Sun.COM (hdr->dh_txid != da->da_hdr.dh_txid)) {
37011963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "smb_kdoor_chkhdr[%s]: invalid header",
37111963SAfshin.Ardakani@Sun.COM da->da_opname);
37211963SAfshin.Ardakani@Sun.COM return (B_FALSE);
37311963SAfshin.Ardakani@Sun.COM }
37411963SAfshin.Ardakani@Sun.COM
37511963SAfshin.Ardakani@Sun.COM if (hdr->dh_door_rc != SMB_DOP_SUCCESS) {
37611963SAfshin.Ardakani@Sun.COM cmn_err(CE_WARN, "smb_kdoor_chkhdr[%s]: call failed: %u",
37711963SAfshin.Ardakani@Sun.COM da->da_opname, hdr->dh_door_rc);
37811963SAfshin.Ardakani@Sun.COM return (B_FALSE);
37911963SAfshin.Ardakani@Sun.COM }
38011963SAfshin.Ardakani@Sun.COM
38111963SAfshin.Ardakani@Sun.COM return (B_TRUE);
38211963SAfshin.Ardakani@Sun.COM }
38311963SAfshin.Ardakani@Sun.COM
38411963SAfshin.Ardakani@Sun.COM /*
38511963SAfshin.Ardakani@Sun.COM * Free both the argument and result door buffers regardless of the status
38611963SAfshin.Ardakani@Sun.COM * of the up-call. The doorfs allocates a new buffer if the result buffer
38711963SAfshin.Ardakani@Sun.COM * passed by the client is too small.
38811963SAfshin.Ardakani@Sun.COM */
38911963SAfshin.Ardakani@Sun.COM static void
smb_kdoor_free(door_arg_t * arg)39011963SAfshin.Ardakani@Sun.COM smb_kdoor_free(door_arg_t *arg)
39111963SAfshin.Ardakani@Sun.COM {
39211963SAfshin.Ardakani@Sun.COM if (arg->rbuf != NULL && arg->rbuf != arg->data_ptr)
39311963SAfshin.Ardakani@Sun.COM kmem_free(arg->rbuf, arg->rsize);
39411963SAfshin.Ardakani@Sun.COM
39511963SAfshin.Ardakani@Sun.COM if (arg->data_ptr != NULL)
39611963SAfshin.Ardakani@Sun.COM kmem_free(arg->data_ptr, arg->data_size);
39711963SAfshin.Ardakani@Sun.COM }
398