Home | History | Annotate | Download | only in smbsrv
      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  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27 
     28 #include <sys/ddi.h>
     29 #include <sys/sunddi.h>
     30 #include <sys/cmn_err.h>
     31 #include <smbsrv/smb_common_door.h>
     32 #include <smbsrv/smb_door_svc.h>
     33 #include <smbsrv/smb_xdr.h>
     34 
     35 
     36 /*
     37  * smb_kdr_decode_common
     38  *
     39  * This function can be used for decoding both door request and result buffer.
     40  * pre-condition: data is non-null pointer, and is bzero'd.
     41  */
     42 int
     43 smb_kdr_decode_common(char *buf, size_t len, xdrproc_t proc, void *data)
     44 {
     45 	XDR xdrs;
     46 	int rc = 0;
     47 
     48 	if (!data) {
     49 		cmn_err(CE_WARN, "smb_kdr_decode_common: invalid param");
     50 		return (-1);
     51 	}
     52 
     53 	xdrmem_create(&xdrs, buf, len, XDR_DECODE);
     54 	if (!proc(&xdrs, data))
     55 		rc = -1;
     56 
     57 	xdr_destroy(&xdrs);
     58 	return (rc);
     59 }
     60 
     61 /*
     62  * smb_kdr_encode_common
     63  *
     64  * This function is used for encoding both request/result door buffer.
     65  * This function will first encode integer value 'reserved' (opcode/status),
     66  * followed by the data (which will be encoded via the specified XDR routine.
     67  *
     68  * Returns encoded buffer upon success. Otherwise, returns NULL.
     69  */
     70 char *
     71 smb_kdr_encode_common(uint_t reserved, void *data, xdrproc_t proc, size_t *len)
     72 {
     73 	XDR xdrs;
     74 	char *buf;
     75 
     76 	if (proc && !data) {
     77 		cmn_err(CE_WARN, "smb_kdr_encode_common: invalid param");
     78 		*len = 0;
     79 		return (NULL);
     80 	}
     81 
     82 	*len = xdr_sizeof(xdr_uint32_t, &reserved);
     83 	if (proc)
     84 		*len += xdr_sizeof(proc, data);
     85 	buf = kmem_alloc(*len, KM_SLEEP);
     86 	xdrmem_create(&xdrs, buf, *len, XDR_ENCODE);
     87 	if (!xdr_uint32_t(&xdrs, &reserved)) {
     88 		cmn_err(CE_WARN, "smb_kdr_encode_common: encode error 1");
     89 		kmem_free(buf, *len);
     90 		*len = 0;
     91 		xdr_destroy(&xdrs);
     92 		return (NULL);
     93 	}
     94 
     95 	if (proc && !proc(&xdrs, data)) {
     96 		cmn_err(CE_WARN, "smb_kdr_encode_common: encode error 2");
     97 		kmem_free(buf, *len);
     98 		buf = NULL;
     99 		*len = 0;
    100 	}
    101 
    102 	xdr_destroy(&xdrs);
    103 	return (buf);
    104 }
    105 
    106 /*
    107  * Get the opcode of the door argument buffer.
    108  */
    109 int
    110 smb_dr_get_opcode(char *argp, size_t arg_size)
    111 {
    112 	int opcode;
    113 
    114 	if (smb_kdr_decode_common(argp, arg_size, xdr_uint32_t, &opcode) != 0)
    115 		opcode = -1;
    116 	return (opcode);
    117 }
    118 
    119 /*
    120  * Set the opcode of the door argument buffer.
    121  */
    122 char *
    123 smb_dr_set_opcode(uint32_t opcode, size_t *len)
    124 {
    125 	char *buf;
    126 
    127 	buf = smb_kdr_encode_common(opcode, NULL, NULL, len);
    128 	return (buf);
    129 }
    130 
    131 /*
    132  * Get the status of the door result buffer.
    133  */
    134 int
    135 smb_dr_get_res_stat(char *rbufp, size_t rbuf_size)
    136 {
    137 	int stat;
    138 	if (smb_kdr_decode_common(rbufp, rbuf_size, xdr_uint32_t, &stat) != 0)
    139 		stat = -1;
    140 	return (stat);
    141 }
    142 
    143 /*
    144  * Set the status of the door result buffer.
    145  */
    146 char *
    147 smb_dr_set_res_stat(uint32_t stat, size_t *len)
    148 {
    149 	char *buf;
    150 
    151 	buf = smb_kdr_encode_common(stat, NULL, NULL, len);
    152 	return (buf);
    153 }
    154 
    155 char *
    156 smb_dr_encode_arg_get_token(netr_client_t *clnt_info, size_t *len)
    157 {
    158 
    159 	char *buf;
    160 	smb_dr_bytes_t arg;
    161 	uint_t opcode = SMB_DR_USER_AUTH_LOGON;
    162 
    163 	arg.bytes_val = netr_client_mkselfrel(clnt_info,
    164 	    &arg.bytes_len);
    165 
    166 	buf = smb_kdr_encode_common(opcode, &arg, xdr_smb_dr_bytes_t, len);
    167 	kmem_free(arg.bytes_val, arg.bytes_len);
    168 	return (buf);
    169 }
    170 
    171 smb_token_t *
    172 smb_dr_decode_res_token(char *buf, size_t len)
    173 {
    174 	smb_dr_bytes_t res;
    175 	smb_token_t *token;
    176 
    177 	bzero(&res, sizeof (smb_dr_bytes_t));
    178 	if (smb_kdr_decode_common(buf, len, xdr_smb_dr_bytes_t, &res) !=
    179 	    0) {
    180 		cmn_err(CE_WARN, "smb_dr_decode_res_token: failed");
    181 		xdr_free(xdr_smb_dr_bytes_t, (char *)&res);
    182 		return (NULL);
    183 	}
    184 	token = smb_token_mkabsolute(res.bytes_val, res.bytes_len);
    185 	xdr_free(xdr_smb_dr_bytes_t, (char *)&res);
    186 
    187 	return (token);
    188 }
    189 
    190 char *
    191 smb_dr_encode_string(uint32_t reserved, char *str, size_t *len)
    192 {
    193 	char *buf = NULL;
    194 	smb_dr_string_t res;
    195 
    196 	if (!str) {
    197 		*len = 0;
    198 		return (buf);
    199 	}
    200 
    201 	res.buf = str;
    202 	if ((buf = smb_kdr_encode_common(reserved, &res,
    203 	    xdr_smb_dr_string_t, len)) == 0)
    204 		cmn_err(CE_WARN, "smb_dr_encode_string: failed");
    205 	return (buf);
    206 }
    207 
    208 /*
    209  * smb_dr_decode_kshare()
    210  *
    211  * The kshare information arrives encoded in a flat buffer, so retrieve
    212  * the flat buffer and convert it to an smb_dr_kshare structure.
    213  */
    214 
    215 smb_dr_kshare_t *
    216 smb_dr_decode_kshare(char *buf, size_t len)
    217 {
    218 	smb_dr_bytes_t res;
    219 	smb_dr_kshare_t *kshare;
    220 
    221 	bzero(&res, sizeof (smb_dr_bytes_t));
    222 	if (smb_kdr_decode_common(buf, len, xdr_smb_dr_bytes_t, &res) !=
    223 	    0) {
    224 		cmn_err(CE_WARN, "smb_dr_decode_kshare: failed");
    225 		xdr_free(xdr_smb_dr_bytes_t, (char *)&res);
    226 		return (NULL);
    227 	}
    228 	kshare = smb_share_mkabsolute(res.bytes_val, res.bytes_len);
    229 	xdr_free(xdr_smb_dr_bytes_t, (char *)&res);
    230 
    231 	return (kshare);
    232 }
    233 
    234 /*
    235  * smb_share_mkabsolute
    236  *
    237  * decode: flat buffer -> structure
    238  */
    239 
    240 smb_dr_kshare_t *
    241 smb_share_mkabsolute(uint8_t *buf, uint32_t len)
    242 {
    243 	smb_dr_kshare_t *obj;
    244 	XDR xdrs;
    245 
    246 	xdrmem_create(&xdrs, (const caddr_t)buf, len, XDR_DECODE);
    247 	obj = kmem_zalloc(sizeof (smb_dr_kshare_t), KM_SLEEP);
    248 
    249 	if (!xdr_smb_dr_kshare_t(&xdrs, obj)) {
    250 		kmem_free(obj, sizeof (smb_dr_kshare_t));
    251 		obj = NULL;
    252 	}
    253 
    254 	xdr_destroy(&xdrs);
    255 	return (obj);
    256 }
    257 
    258 void
    259 smb_dr_kshare_free(smb_dr_kshare_t *kshare)
    260 {
    261 	if (!kshare)
    262 		return;
    263 
    264 	xdr_free(xdr_smb_dr_kshare_t, (char *)kshare);
    265 	kmem_free(kshare, sizeof (smb_dr_kshare_t));
    266 }
    267