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.
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.
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]
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
27 * "Upcall" glue for the fake (user-mode) smbsrv module.
30 #include <sys/types.h>
33 #include <sys/sunddi.h>
34 #include <sys/cmn_err.h>
36 #include <smbsrv/smb_kproto.h>
37 #include <smbsrv/smb_door.h>
39 static int smb_kdoor_encode(smb_doorarg_t
*);
40 static int smb_kdoor_decode(smb_doorarg_t
*);
41 static void smb_kdoor_sethdr(smb_doorarg_t
*, uint32_t);
42 static boolean_t
smb_kdoor_chkhdr(smb_doorarg_t
*, smb_doorhdr_t
*);
43 static void smb_kdoor_free(door_arg_t
*);
46 smb_kdoor_init(smb_server_t
*sv
)
49 mutex_init(&sv
->sv_kdoor_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
50 cv_init(&sv
->sv_kdoor_cv
, NULL
, CV_DEFAULT
, NULL
);
54 smb_kdoor_fini(smb_server_t
*sv
)
57 cv_destroy(&sv
->sv_kdoor_cv
);
58 mutex_destroy(&sv
->sv_kdoor_mutex
);
62 * In the "fake kernen", our "upcalls" don't use the
63 * real door, but just call via a function pointer.
64 * This is where we setup that pointer, which is
65 * fksmbd_door_dispatch()
68 fksmb_kdoor_open(smb_server_t
*sv
, void *varg
)
70 sv
->sv_kdoor_hd
= varg
;
74 smb_kdoor_close(smb_server_t
*sv
)
76 sv
->sv_kdoor_hd
= NULL
;
82 smb_kdoor_upcall(smb_server_t
*sv
, uint32_t cmd
,
83 void *req_data
, xdrproc_t req_xdr
,
84 void *rsp_data
, xdrproc_t rsp_xdr
)
87 fksmb_kdoor_disp_func_t
*func
;
90 bzero(&da
, sizeof (smb_doorarg_t
));
92 da
.da_opname
= smb_doorhdr_opname(cmd
);
93 da
.da_req_xdr
= req_xdr
;
94 da
.da_rsp_xdr
= rsp_xdr
;
95 da
.da_req_data
= req_data
;
96 da
.da_rsp_data
= rsp_data
;
98 if ((req_data
== NULL
&& req_xdr
!= NULL
) ||
99 (rsp_data
== NULL
&& rsp_xdr
!= NULL
)) {
100 cmn_err(CE_WARN
, "smb_kdoor_upcall[%s]: invalid param",
105 /* NB: no ASYNC, nor event stuff */
107 func
= (fksmb_kdoor_disp_func_t
*)(sv
->sv_kdoor_hd
);
111 if ((rc
= smb_kdoor_encode(&da
)) != 0)
115 * The "upcall" (just call via function pointer)
116 * i.e. see: fksmbd_door_dispatch()
118 if ((rc
= (*func
)(&da
)) != 0)
121 rc
= smb_kdoor_decode(&da
);
123 smb_kdoor_free(&da
.da_arg
);
128 /* no smb_kdoor_send, smb_kdoor_receive */
129 /* no smb_kdoor_upcall_private */
132 smb_kdoor_encode(smb_doorarg_t
*da
)
138 len
= xdr_sizeof(smb_doorhdr_xdr
, &da
->da_hdr
);
139 if (da
->da_req_xdr
!= NULL
)
140 len
+= xdr_sizeof(da
->da_req_xdr
, da
->da_req_data
);
142 smb_kdoor_sethdr(da
, len
);
144 buf
= kmem_zalloc(len
, KM_SLEEP
);
145 xdrmem_create(&xdrs
, buf
, len
, XDR_ENCODE
);
147 if (!smb_doorhdr_xdr(&xdrs
, &da
->da_hdr
)) {
148 cmn_err(CE_WARN
, "smb_kdoor_encode[%s]: header encode failed",
155 if (da
->da_req_xdr
!= NULL
) {
156 if (!da
->da_req_xdr(&xdrs
, da
->da_req_data
)) {
157 cmn_err(CE_WARN
, "smb_kdoor_encode[%s]: encode failed",
165 da
->da_arg
.data_ptr
= buf
;
166 da
->da_arg
.data_size
= len
;
167 da
->da_arg
.desc_ptr
= NULL
;
168 da
->da_arg
.desc_num
= 0;
169 da
->da_arg
.rbuf
= buf
;
170 da
->da_arg
.rsize
= len
;
177 * Decode the response in rbuf and rsize.
180 smb_kdoor_decode(smb_doorarg_t
*da
)
184 char *rbuf
= da
->da_arg
.rbuf
;
185 uint32_t rsize
= da
->da_arg
.rsize
;
187 if (rbuf
== NULL
|| rsize
== 0) {
188 cmn_err(CE_WARN
, "smb_kdoor_decode[%s]: invalid param",
193 xdrmem_create(&xdrs
, rbuf
, rsize
, XDR_DECODE
);
195 if (!smb_doorhdr_xdr(&xdrs
, &hdr
)) {
196 cmn_err(CE_WARN
, "smb_kdoor_decode[%s]: header decode failed",
202 if (!smb_kdoor_chkhdr(da
, &hdr
)) {
207 if (hdr
.dh_datalen
!= 0 && da
->da_rsp_xdr
!= NULL
) {
208 if (!da
->da_rsp_xdr(&xdrs
, da
->da_rsp_data
)) {
209 cmn_err(CE_WARN
, "smb_kdoor_decode[%s]: decode failed",
221 smb_kdoor_sethdr(smb_doorarg_t
*da
, uint32_t datalen
)
223 smb_doorhdr_t
*hdr
= &da
->da_hdr
;
225 bzero(hdr
, sizeof (smb_doorhdr_t
));
226 hdr
->dh_magic
= SMB_DOOR_HDR_MAGIC
;
227 hdr
->dh_flags
= da
->da_flags
| SMB_DF_FAKE_KERNEL
;
228 hdr
->dh_op
= da
->da_opcode
;
229 /* hdr->dh_txid = 0 (not used) */
230 hdr
->dh_datalen
= datalen
;
231 hdr
->dh_door_rc
= SMB_DOP_NOT_CALLED
;
235 smb_kdoor_chkhdr(smb_doorarg_t
*da
, smb_doorhdr_t
*hdr
)
237 if ((hdr
->dh_magic
!= SMB_DOOR_HDR_MAGIC
) ||
238 (hdr
->dh_op
!= da
->da_hdr
.dh_op
) ||
239 (hdr
->dh_txid
!= da
->da_hdr
.dh_txid
)) {
240 cmn_err(CE_WARN
, "smb_kdoor_chkhdr[%s]: invalid header",
245 switch (hdr
->dh_door_rc
) {
246 case SMB_DOP_SUCCESS
:
249 /* SMB_DOP_EMPTYBUF is a "normal" error (silent). */
250 case SMB_DOP_EMPTYBUF
:
254 cmn_err(CE_WARN
, "smb_kdoor_chkhdr[%s]: call failed: %u",
255 da
->da_opname
, hdr
->dh_door_rc
);
263 * Free both the argument and result door buffers regardless of the status
264 * of the up-call. The doorfs allocates a new buffer if the result buffer
265 * passed by the client is too small.
268 smb_kdoor_free(door_arg_t
*arg
)
270 if (arg
->rbuf
!= NULL
&& arg
->rbuf
!= arg
->data_ptr
)
271 kmem_free(arg
->rbuf
, arg
->rsize
);
273 if (arg
->data_ptr
!= NULL
)
274 kmem_free(arg
->data_ptr
, arg
->data_size
);