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