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