1da6c28aaSamw /* 2da6c28aaSamw * CDDL HEADER START 3da6c28aaSamw * 4da6c28aaSamw * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 7da6c28aaSamw * 8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10da6c28aaSamw * See the License for the specific language governing permissions 11da6c28aaSamw * and limitations under the License. 12da6c28aaSamw * 13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18da6c28aaSamw * 19da6c28aaSamw * CDDL HEADER END 20da6c28aaSamw */ 21148c5f43SAlan Wright 22da6c28aaSamw /* 23c5866007SKeyur Desai * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 2468b2bbf2SGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 25da6c28aaSamw */ 26da6c28aaSamw 27bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h> 28da6c28aaSamw #include <smbsrv/smb_fsops.h> 293db3f65cSamw #include <smbsrv/smb_share.h> 30bbf6f00cSJordan Brown #include <smbsrv/string.h> 31da6c28aaSamw #include <smbsrv/nmpipes.h> 32da6c28aaSamw #include <smbsrv/mailslot.h> 33da6c28aaSamw 34da6c28aaSamw /* 35da6c28aaSamw * count of bytes in server response packet 36da6c28aaSamw * except parameters and data. Note that setup 37da6c28aaSamw * word count is zero. 38da6c28aaSamw */ 39da6c28aaSamw #define RESP_HEADER_LEN 24 40da6c28aaSamw 41da6c28aaSamw /* 42b1352070SAlan Wright * We started by using common functions for transaction/transaction2 43da6c28aaSamw * and transaction_secondary/transaction2_secondary because they 44da6c28aaSamw * are respectively so similar. However, it turned out to be a bad 45da6c28aaSamw * idea because of quirky differences. Be sure if you modify one 46da6c28aaSamw * of these four functions to check and see if the modification should 47da6c28aaSamw * be applied to its peer. 48da6c28aaSamw */ 49da6c28aaSamw 509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static int smb_trans_ready(smb_xa_t *); 519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static smb_sdrc_t smb_trans_dispatch(smb_request_t *, smb_xa_t *); 529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static smb_sdrc_t smb_trans2_dispatch(smb_request_t *, smb_xa_t *); 53da6c28aaSamw 547b59d02dSjb150015 smb_sdrc_t 55faa1795aSjb150015 smb_pre_transaction(smb_request_t *sr) 56faa1795aSjb150015 { 57faa1795aSjb150015 DTRACE_SMB_1(op__Transaction__start, smb_request_t *, sr); 58faa1795aSjb150015 return (SDRC_SUCCESS); 59faa1795aSjb150015 } 60faa1795aSjb150015 61faa1795aSjb150015 void 62faa1795aSjb150015 smb_post_transaction(smb_request_t *sr) 63faa1795aSjb150015 { 64faa1795aSjb150015 DTRACE_SMB_1(op__Transaction__done, smb_request_t *, sr); 65faa1795aSjb150015 } 66faa1795aSjb150015 67faa1795aSjb150015 smb_sdrc_t 68faa1795aSjb150015 smb_com_transaction(smb_request_t *sr) 69da6c28aaSamw { 70da6c28aaSamw int rc; 71da6c28aaSamw unsigned char msrcnt, suwcnt; 72da6c28aaSamw uint16_t tpscnt, tdscnt, mprcnt, mdrcnt, flags; 73da6c28aaSamw uint16_t pscnt, psoff, dscnt, dsoff; 74da6c28aaSamw uint32_t timeo; 75da6c28aaSamw struct smb_xa *xa; 76da6c28aaSamw char *stn; 77da6c28aaSamw int ready; 78da6c28aaSamw 79da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, 80da6c28aaSamw &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &msrcnt, &flags, 81da6c28aaSamw &timeo, &pscnt, &psoff, &dscnt, &dsoff, &suwcnt); 82da6c28aaSamw 837b59d02dSjb150015 if (rc != 0) 84faa1795aSjb150015 return (SDRC_ERROR); 85da6c28aaSamw 86da6c28aaSamw xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, 87da6c28aaSamw msrcnt, suwcnt); 88da6c28aaSamw if (xa == NULL) { 89dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRnoroom); 90faa1795aSjb150015 return (SDRC_ERROR); 91da6c28aaSamw } 92da6c28aaSamw 93da6c28aaSamw /* Should be some alignment stuff here in SMB? */ 94da6c28aaSamw if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) { 95da6c28aaSamw rc = smbsr_decode_data(sr, "%.U", sr, &stn); 96da6c28aaSamw } else { 97da6c28aaSamw rc = smbsr_decode_data(sr, "%s", sr, &stn); 98da6c28aaSamw } 99da6c28aaSamw if (rc != 0) { 100da6c28aaSamw smb_xa_rele(sr->session, xa); 101faa1795aSjb150015 return (SDRC_ERROR); 102da6c28aaSamw } 103da6c28aaSamw 1049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States xa->xa_pipe_name = smb_mem_strdup(stn); 105da6c28aaSamw xa->smb_flags = flags; 106da6c28aaSamw xa->smb_timeout = timeo; 107da6c28aaSamw xa->req_disp_param = pscnt; 108da6c28aaSamw xa->req_disp_data = dscnt; 109da6c28aaSamw 1107f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv, 111da6c28aaSamw sr->smb_vwv.chain_offset, suwcnt * 2)) { 112da6c28aaSamw smb_xa_rele(sr->session, xa); 113dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 114faa1795aSjb150015 return (SDRC_ERROR); 115da6c28aaSamw } 1167f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 117da6c28aaSamw smb_xa_rele(sr->session, xa); 118dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 119faa1795aSjb150015 return (SDRC_ERROR); 120da6c28aaSamw } 1217f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 122da6c28aaSamw smb_xa_rele(sr->session, xa); 123dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 124faa1795aSjb150015 return (SDRC_ERROR); 125da6c28aaSamw } 126da6c28aaSamw 127da6c28aaSamw ready = smb_trans_ready(xa); 128da6c28aaSamw 129da6c28aaSamw if (smb_xa_open(xa)) { 130da6c28aaSamw smb_xa_rele(sr->session, xa); 131ccc71be5SGordon Ross smbsr_error(sr, 0, ERRSRV, ERRsrverror); 132faa1795aSjb150015 return (SDRC_ERROR); 133da6c28aaSamw } 134da6c28aaSamw sr->r_xa = xa; 135da6c28aaSamw 136da6c28aaSamw if (!ready) { 1377b59d02dSjb150015 rc = smbsr_encode_empty_result(sr); 138faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 139da6c28aaSamw } 140da6c28aaSamw 141da6c28aaSamw if (!smb_xa_complete(xa)) { 142da6c28aaSamw smb_xa_close(xa); 143dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 144faa1795aSjb150015 return (SDRC_ERROR); 145da6c28aaSamw } 146da6c28aaSamw 147da6c28aaSamw return (smb_trans_dispatch(sr, xa)); 148da6c28aaSamw } 149da6c28aaSamw 1507b59d02dSjb150015 smb_sdrc_t 151faa1795aSjb150015 smb_pre_transaction_secondary(smb_request_t *sr) 152faa1795aSjb150015 { 153faa1795aSjb150015 DTRACE_SMB_1(op__TransactionSecondary__start, smb_request_t *, sr); 154faa1795aSjb150015 return (SDRC_SUCCESS); 155faa1795aSjb150015 } 156faa1795aSjb150015 157faa1795aSjb150015 void 158faa1795aSjb150015 smb_post_transaction_secondary(smb_request_t *sr) 159faa1795aSjb150015 { 160faa1795aSjb150015 DTRACE_SMB_1(op__TransactionSecondary__done, smb_request_t *, sr); 161faa1795aSjb150015 } 162faa1795aSjb150015 163faa1795aSjb150015 smb_sdrc_t 164faa1795aSjb150015 smb_com_transaction_secondary(smb_request_t *sr) 165da6c28aaSamw { 166da6c28aaSamw uint16_t tpscnt, tdscnt, pscnt, psdisp; 167da6c28aaSamw uint16_t dscnt, dsoff, dsdisp, psoff; 168da6c28aaSamw smb_xa_t *xa; 169da6c28aaSamw int rc; 170da6c28aaSamw 171da6c28aaSamw if ((xa = smbsr_lookup_xa(sr)) == 0) { 172dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 173faa1795aSjb150015 return (SDRC_ERROR); 174da6c28aaSamw } 175da6c28aaSamw 176da6c28aaSamw if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 177da6c28aaSamw if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { 178dc20a302Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 179da6c28aaSamw ERRDOS, ERRnoaccess); 180faa1795aSjb150015 return (SDRC_ERROR); 181da6c28aaSamw } 182da6c28aaSamw } 183da6c28aaSamw 184da6c28aaSamw if (xa->smb_com != SMB_COM_TRANSACTION) { 185da6c28aaSamw return (SDRC_DROP_VC); 186da6c28aaSamw } 187da6c28aaSamw 188da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_TRANSSHDR_ED_FMT, &tpscnt, &tdscnt, 189da6c28aaSamw &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp); 190da6c28aaSamw 1917b59d02dSjb150015 if (rc != 0) 192faa1795aSjb150015 return (SDRC_ERROR); 193da6c28aaSamw 194da6c28aaSamw mutex_enter(&xa->xa_mutex); 1957f3ef643SGordon Ross if (xa->smb_tpscnt > tpscnt) 1967f3ef643SGordon Ross xa->smb_tpscnt = tpscnt; 1977f3ef643SGordon Ross if (xa->smb_tdscnt > tdscnt) 1987f3ef643SGordon Ross xa->smb_tdscnt = tdscnt; 199da6c28aaSamw xa->req_disp_param = psdisp + pscnt; 200da6c28aaSamw xa->req_disp_data = dsdisp + dscnt; 201da6c28aaSamw 2027f3ef643SGordon Ross /* 2037f3ef643SGordon Ross * The words psdisp, dsdisp, tell us what displacement 2047f3ef643SGordon Ross * into the entire trans parameter and data buffers 2057f3ef643SGordon Ross * where we should put the params & data that are 2067f3ef643SGordon Ross * delivered by this request. [MS-CIFS] says all the 2077f3ef643SGordon Ross * parameters and data SHOULD be sent sequentially, so 2087f3ef643SGordon Ross * so we can normally reassemble by simply appending. 2097f3ef643SGordon Ross * However, the components MAY come out of order, so 2107f3ef643SGordon Ross * check and set the current offset. This is rare, 2117f3ef643SGordon Ross * and we might like to know when this happens, so 2127f3ef643SGordon Ross * fire some static dtrace probes when it does. 2137f3ef643SGordon Ross */ 2147f3ef643SGordon Ross if (xa->req_param_mb.chain_offset != psdisp) { 2157f3ef643SGordon Ross DTRACE_PROBE2(trans_param_disp, 2167f3ef643SGordon Ross smb_xa_t *, xa, uint16_t, psdisp); 2177f3ef643SGordon Ross xa->req_param_mb.chain_offset = psdisp; 2187f3ef643SGordon Ross } 2197f3ef643SGordon Ross if (xa->req_data_mb.chain_offset != dsdisp) { 2207f3ef643SGordon Ross DTRACE_PROBE2(trans_data_disp, 2217f3ef643SGordon Ross smb_xa_t *, xa, uint16_t, dsdisp); 2227f3ef643SGordon Ross xa->req_data_mb.chain_offset = dsdisp; 2237f3ef643SGordon Ross } 2247f3ef643SGordon Ross 2257f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 226da6c28aaSamw mutex_exit(&xa->xa_mutex); 227da6c28aaSamw smb_xa_close(xa); 228dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 229faa1795aSjb150015 return (SDRC_ERROR); 230da6c28aaSamw } 2317f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 232da6c28aaSamw mutex_exit(&xa->xa_mutex); 233da6c28aaSamw smb_xa_close(xa); 234dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 235faa1795aSjb150015 return (SDRC_ERROR); 236da6c28aaSamw } 237da6c28aaSamw mutex_exit(&xa->xa_mutex); 238da6c28aaSamw 239da6c28aaSamw if (!smb_trans_ready(xa)) 240da6c28aaSamw return (SDRC_NO_REPLY); 241da6c28aaSamw 242da6c28aaSamw if (!smb_xa_complete(xa)) 243da6c28aaSamw return (SDRC_NO_REPLY); 244da6c28aaSamw 245da6c28aaSamw return (smb_trans_dispatch(sr, xa)); 246da6c28aaSamw } 247da6c28aaSamw 2487b59d02dSjb150015 smb_sdrc_t 249faa1795aSjb150015 smb_pre_ioctl(smb_request_t *sr) 250faa1795aSjb150015 { 251faa1795aSjb150015 DTRACE_SMB_1(op__Ioctl__start, smb_request_t *, sr); 252faa1795aSjb150015 return (SDRC_SUCCESS); 253faa1795aSjb150015 } 254faa1795aSjb150015 255faa1795aSjb150015 void 256faa1795aSjb150015 smb_post_ioctl(smb_request_t *sr) 257faa1795aSjb150015 { 258faa1795aSjb150015 DTRACE_SMB_1(op__Ioctl__done, smb_request_t *, sr); 259faa1795aSjb150015 } 260faa1795aSjb150015 261faa1795aSjb150015 smb_sdrc_t 262faa1795aSjb150015 smb_com_ioctl(smb_request_t *sr) 263da6c28aaSamw { 264da6c28aaSamw uint16_t fid, category, function, tpscnt, tdscnt, mprcnt; 265da6c28aaSamw uint16_t mdrcnt, pscnt, pdoff, dscnt, dsoff; 266da6c28aaSamw uint32_t timeout; 267da6c28aaSamw int rc; 268da6c28aaSamw 269da6c28aaSamw rc = smbsr_decode_vwv(sr, "wwwwwwwl2.wwww", &fid, &category, &function, 270da6c28aaSamw &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &timeout, &pscnt, 271da6c28aaSamw &pdoff, &dscnt, &dsoff); 272da6c28aaSamw 2737b59d02dSjb150015 if (rc != 0) 274faa1795aSjb150015 return (SDRC_ERROR); 275da6c28aaSamw 276faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED); 277da6c28aaSamw } 278da6c28aaSamw 279faa1795aSjb150015 smb_sdrc_t 280faa1795aSjb150015 smb_pre_transaction2(smb_request_t *sr) 281da6c28aaSamw { 282faa1795aSjb150015 DTRACE_SMB_1(op__Transaction2__start, smb_request_t *, sr); 283faa1795aSjb150015 return (SDRC_SUCCESS); 284faa1795aSjb150015 } 285faa1795aSjb150015 286faa1795aSjb150015 void 287faa1795aSjb150015 smb_post_transaction2(smb_request_t *sr) 288faa1795aSjb150015 { 289faa1795aSjb150015 DTRACE_SMB_1(op__Transaction2__done, smb_request_t *, sr); 290da6c28aaSamw } 291da6c28aaSamw 2927b59d02dSjb150015 smb_sdrc_t 293da6c28aaSamw smb_com_transaction2(struct smb_request *sr) 294da6c28aaSamw { 295da6c28aaSamw unsigned char msrcnt, suwcnt; 296da6c28aaSamw uint16_t tpscnt, tdscnt, mprcnt, mdrcnt, flags; 297da6c28aaSamw uint16_t pscnt, psoff, dscnt, dsoff; 298da6c28aaSamw uint32_t timeo; 299da6c28aaSamw smb_xa_t *xa; 300da6c28aaSamw int ready; 301da6c28aaSamw int rc; 302da6c28aaSamw 303da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, &tpscnt, &tdscnt, 304da6c28aaSamw &mprcnt, &mdrcnt, &msrcnt, &flags, &timeo, &pscnt, &psoff, &dscnt, 305da6c28aaSamw &dsoff, &suwcnt); 306da6c28aaSamw 3077b59d02dSjb150015 if (rc != 0) 308faa1795aSjb150015 return (SDRC_ERROR); 309da6c28aaSamw 310da6c28aaSamw xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, 311da6c28aaSamw msrcnt, suwcnt); 312da6c28aaSamw if (xa == 0) { 313dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRnoroom); 314faa1795aSjb150015 return (SDRC_ERROR); 315da6c28aaSamw } 316da6c28aaSamw 317da6c28aaSamw xa->smb_flags = flags; 318da6c28aaSamw xa->smb_timeout = timeo; 319da6c28aaSamw xa->req_disp_param = pscnt; 320da6c28aaSamw xa->req_disp_data = dscnt; 321da6c28aaSamw 3227f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv, 323da6c28aaSamw sr->smb_vwv.chain_offset, suwcnt*2)) { 324da6c28aaSamw smb_xa_rele(sr->session, xa); 325dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 326faa1795aSjb150015 return (SDRC_ERROR); 327da6c28aaSamw } 3287f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 329da6c28aaSamw smb_xa_rele(sr->session, xa); 330dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 331faa1795aSjb150015 return (SDRC_ERROR); 332da6c28aaSamw } 3337f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 334da6c28aaSamw smb_xa_rele(sr->session, xa); 335dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 336faa1795aSjb150015 return (SDRC_ERROR); 337da6c28aaSamw } 338da6c28aaSamw 339da6c28aaSamw ready = smb_trans_ready(xa); 340da6c28aaSamw 341da6c28aaSamw if (smb_xa_open(xa)) { 342da6c28aaSamw smb_xa_rele(sr->session, xa); 343ccc71be5SGordon Ross smbsr_error(sr, 0, ERRSRV, ERRsrverror); 344faa1795aSjb150015 return (SDRC_ERROR); 345da6c28aaSamw } 346da6c28aaSamw sr->r_xa = xa; 347da6c28aaSamw 348da6c28aaSamw if (!ready) { 3497b59d02dSjb150015 rc = smbsr_encode_empty_result(sr); 350faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 351da6c28aaSamw } 352da6c28aaSamw 353da6c28aaSamw if (!smb_xa_complete(xa)) { 354da6c28aaSamw smb_xa_close(xa); 355dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 356faa1795aSjb150015 return (SDRC_ERROR); 357da6c28aaSamw } 358da6c28aaSamw 359da6c28aaSamw return (smb_trans2_dispatch(sr, xa)); 360da6c28aaSamw } 361da6c28aaSamw 3627b59d02dSjb150015 smb_sdrc_t 363faa1795aSjb150015 smb_pre_transaction2_secondary(smb_request_t *sr) 364faa1795aSjb150015 { 365faa1795aSjb150015 DTRACE_SMB_1(op__Transaction2Secondary__start, smb_request_t *, sr); 366faa1795aSjb150015 return (SDRC_SUCCESS); 367faa1795aSjb150015 } 368faa1795aSjb150015 369faa1795aSjb150015 void 370faa1795aSjb150015 smb_post_transaction2_secondary(smb_request_t *sr) 371faa1795aSjb150015 { 372faa1795aSjb150015 DTRACE_SMB_1(op__Transaction2Secondary__done, smb_request_t *, sr); 373faa1795aSjb150015 } 374faa1795aSjb150015 375faa1795aSjb150015 smb_sdrc_t 376faa1795aSjb150015 smb_com_transaction2_secondary(smb_request_t *sr) 377da6c28aaSamw { 378da6c28aaSamw uint16_t tpscnt, tdscnt, fid; 379da6c28aaSamw uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp; 380da6c28aaSamw smb_xa_t *xa; 381da6c28aaSamw int rc; 382da6c28aaSamw 383da6c28aaSamw if ((xa = smbsr_lookup_xa(sr)) == 0) { 384dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 385faa1795aSjb150015 return (SDRC_ERROR); 386da6c28aaSamw } 387da6c28aaSamw 388da6c28aaSamw if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 389da6c28aaSamw if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { 390dc20a302Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 391da6c28aaSamw ERRDOS, ERRnoaccess); 392faa1795aSjb150015 return (SDRC_ERROR); 393da6c28aaSamw } 394da6c28aaSamw } 395da6c28aaSamw 396da6c28aaSamw if (xa->smb_com != SMB_COM_TRANSACTION2) { 397da6c28aaSamw return (SDRC_DROP_VC); 398da6c28aaSamw } 399da6c28aaSamw 400da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt, 401da6c28aaSamw &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid); 402da6c28aaSamw 4037b59d02dSjb150015 if (rc != 0) 404faa1795aSjb150015 return (SDRC_ERROR); 405da6c28aaSamw 406da6c28aaSamw mutex_enter(&xa->xa_mutex); 4077f3ef643SGordon Ross if (xa->smb_tpscnt > tpscnt) 4087f3ef643SGordon Ross xa->smb_tpscnt = tpscnt; 4097f3ef643SGordon Ross if (xa->smb_tdscnt > tdscnt) 4107f3ef643SGordon Ross xa->smb_tdscnt = tdscnt; 4117f3ef643SGordon Ross if (fid != 0xFFFF) 4127f3ef643SGordon Ross xa->xa_smb_fid = fid; 413da6c28aaSamw xa->req_disp_param = psdisp + pscnt; 414da6c28aaSamw xa->req_disp_data = dsdisp + dscnt; 415da6c28aaSamw 4167f3ef643SGordon Ross /* 4177f3ef643SGordon Ross * See comment in smb_com_transaction_secondary 4187f3ef643SGordon Ross */ 4197f3ef643SGordon Ross if (xa->req_param_mb.chain_offset != psdisp) { 4207f3ef643SGordon Ross DTRACE_PROBE2(trans_param_disp, 4217f3ef643SGordon Ross smb_xa_t *, xa, uint16_t, psdisp); 4227f3ef643SGordon Ross xa->req_param_mb.chain_offset = psdisp; 4237f3ef643SGordon Ross } 4247f3ef643SGordon Ross if (xa->req_data_mb.chain_offset != dsdisp) { 4257f3ef643SGordon Ross DTRACE_PROBE2(trans_data_disp, 4267f3ef643SGordon Ross smb_xa_t *, xa, uint16_t, dsdisp); 4277f3ef643SGordon Ross xa->req_data_mb.chain_offset = dsdisp; 4287f3ef643SGordon Ross } 4297f3ef643SGordon Ross 4307f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 431da6c28aaSamw mutex_exit(&xa->xa_mutex); 432da6c28aaSamw smb_xa_close(xa); 433dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 434faa1795aSjb150015 return (SDRC_ERROR); 435da6c28aaSamw } 4367f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 437da6c28aaSamw mutex_exit(&xa->xa_mutex); 438da6c28aaSamw smb_xa_close(xa); 439dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 440faa1795aSjb150015 return (SDRC_ERROR); 441da6c28aaSamw } 442da6c28aaSamw mutex_exit(&xa->xa_mutex); 443da6c28aaSamw 444da6c28aaSamw if (!smb_trans_ready(xa)) 445da6c28aaSamw return (SDRC_NO_REPLY); 446da6c28aaSamw 447da6c28aaSamw if (!smb_xa_complete(xa)) 448da6c28aaSamw return (SDRC_NO_REPLY); 449da6c28aaSamw 450da6c28aaSamw return (smb_trans2_dispatch(sr, xa)); 451da6c28aaSamw } 452da6c28aaSamw 4537b59d02dSjb150015 static smb_sdrc_t 454da6c28aaSamw smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) 455da6c28aaSamw { 456da6c28aaSamw int rc; 457da6c28aaSamw int total_bytes, n_setup, n_param, n_data; 458da6c28aaSamw int param_off, param_pad, data_off, data_pad; 459da6c28aaSamw 460da6c28aaSamw switch (xa->smb_func) { 461da6c28aaSamw case NT_TRANSACT_CREATE: 462faa1795aSjb150015 if ((rc = smb_pre_nt_transact_create(sr, xa)) == 0) 463da6c28aaSamw rc = smb_nt_transact_create(sr, xa); 464faa1795aSjb150015 smb_post_nt_transact_create(sr, xa); 465da6c28aaSamw break; 466da6c28aaSamw case NT_TRANSACT_NOTIFY_CHANGE: 467da6c28aaSamw rc = smb_nt_transact_notify_change(sr, xa); 468da6c28aaSamw break; 469da6c28aaSamw case NT_TRANSACT_QUERY_SECURITY_DESC: 470da6c28aaSamw rc = smb_nt_transact_query_security_info(sr, xa); 471da6c28aaSamw break; 472da6c28aaSamw case NT_TRANSACT_SET_SECURITY_DESC: 473da6c28aaSamw rc = smb_nt_transact_set_security_info(sr, xa); 474da6c28aaSamw break; 475da6c28aaSamw case NT_TRANSACT_IOCTL: 476da6c28aaSamw rc = smb_nt_transact_ioctl(sr, xa); 477da6c28aaSamw break; 478da6c28aaSamw case NT_TRANSACT_QUERY_QUOTA: 4799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_nt_transact_query_quota(sr, xa); 480b1352070SAlan Wright break; 481da6c28aaSamw case NT_TRANSACT_SET_QUOTA: 4829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_nt_transact_set_quota(sr, xa); 4839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break; 484bbf6f00cSJordan Brown case NT_TRANSACT_RENAME: 485bbf6f00cSJordan Brown rc = smb_nt_transact_rename(sr, xa); 486bbf6f00cSJordan Brown break; 487bbf6f00cSJordan Brown 488da6c28aaSamw default: 489dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); 490faa1795aSjb150015 return (SDRC_ERROR); 491da6c28aaSamw } 492da6c28aaSamw 493da6c28aaSamw switch (rc) { 494faa1795aSjb150015 case SDRC_SUCCESS: 495da6c28aaSamw break; 496da6c28aaSamw 497da6c28aaSamw case SDRC_DROP_VC: 498da6c28aaSamw case SDRC_NO_REPLY: 499faa1795aSjb150015 case SDRC_ERROR: 50059229f98Sjose borrego case SDRC_SR_KEPT: 501da6c28aaSamw return (rc); 502da6c28aaSamw 503faa1795aSjb150015 case SDRC_NOT_IMPLEMENTED: 504dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); 505faa1795aSjb150015 return (SDRC_ERROR); 506da6c28aaSamw 507da6c28aaSamw default: 508da6c28aaSamw break; 509da6c28aaSamw } 510da6c28aaSamw 511da6c28aaSamw n_setup = MBC_LENGTH(&xa->rep_setup_mb); 512da6c28aaSamw n_param = MBC_LENGTH(&xa->rep_param_mb); 513da6c28aaSamw n_data = MBC_LENGTH(&xa->rep_data_mb); 514da6c28aaSamw 515da6c28aaSamw if (xa->smb_msrcnt < n_setup || 516da6c28aaSamw xa->smb_mprcnt < n_param || 517da6c28aaSamw xa->smb_mdrcnt < n_data) { 518dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); 519faa1795aSjb150015 return (SDRC_ERROR); 520da6c28aaSamw } 521da6c28aaSamw 522da6c28aaSamw /* neato, blast it over there */ 523da6c28aaSamw 524da6c28aaSamw n_setup = (n_setup + 1) / 2; /* Conver to setup words */ 525da6c28aaSamw param_pad = 1; /* must be one */ 526da6c28aaSamw param_off = param_pad + 32 + 37 + (n_setup << 1) + 2; 527da6c28aaSamw data_pad = (4 - ((param_off + n_param) & 3)) % 4; /* Pad to 4 byte */ 528da6c28aaSamw data_off = param_off + n_param + data_pad; /* Param off from hdr */ 529da6c28aaSamw total_bytes = param_pad + n_param + data_pad + n_data; 530da6c28aaSamw 5317b59d02dSjb150015 rc = smbsr_encode_result(sr, 18+n_setup, total_bytes, 532da6c28aaSamw "b3.llllllllbCw#.C#.C", 533da6c28aaSamw 18 + n_setup, /* wct */ 534da6c28aaSamw n_param, /* Total Parameter Bytes */ 535da6c28aaSamw n_data, /* Total Data Bytes */ 536da6c28aaSamw n_param, /* Total Parameter Bytes this buffer */ 537da6c28aaSamw param_off, /* Param offset from header start */ 538da6c28aaSamw 0, /* Param displacement */ 539da6c28aaSamw n_data, /* Total Data Bytes this buffer */ 540da6c28aaSamw data_off, /* Data offset from header start */ 541da6c28aaSamw 0, /* Data displacement */ 542da6c28aaSamw n_setup, /* suwcnt */ 543da6c28aaSamw &xa->rep_setup_mb, /* setup[] */ 544da6c28aaSamw total_bytes, /* Total data bytes */ 545da6c28aaSamw param_pad, 546da6c28aaSamw &xa->rep_param_mb, 547da6c28aaSamw data_pad, 548da6c28aaSamw &xa->rep_data_mb); 549faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 550da6c28aaSamw } 551da6c28aaSamw 552faa1795aSjb150015 smb_sdrc_t 553faa1795aSjb150015 smb_pre_nt_transact(smb_request_t *sr) 554faa1795aSjb150015 { 555faa1795aSjb150015 DTRACE_SMB_1(op__NtTransact__start, smb_request_t *, sr); 556faa1795aSjb150015 return (SDRC_SUCCESS); 557faa1795aSjb150015 } 558faa1795aSjb150015 559faa1795aSjb150015 void 560faa1795aSjb150015 smb_post_nt_transact(smb_request_t *sr) 561faa1795aSjb150015 { 562faa1795aSjb150015 DTRACE_SMB_1(op__NtTransact__done, smb_request_t *, sr); 563faa1795aSjb150015 } 564da6c28aaSamw 5657b59d02dSjb150015 smb_sdrc_t 566da6c28aaSamw smb_com_nt_transact(struct smb_request *sr) 567da6c28aaSamw { 568da6c28aaSamw uint16_t Function; 569da6c28aaSamw unsigned char MaxSetupCount, SetupCount; 570da6c28aaSamw uint32_t TotalParameterCount, TotalDataCount; 571da6c28aaSamw uint32_t MaxParameterCount, MaxDataCount, pscnt; 572da6c28aaSamw uint32_t psoff, dscnt, dsoff; 573da6c28aaSamw smb_xa_t *xa; 574da6c28aaSamw int ready; 575da6c28aaSamw int rc; 576da6c28aaSamw 577da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_NT_TRANSHDR_ED_FMT, &MaxSetupCount, 578da6c28aaSamw &TotalParameterCount, &TotalDataCount, &MaxParameterCount, 579da6c28aaSamw &MaxDataCount, &pscnt, &psoff, &dscnt, 580da6c28aaSamw &dsoff, &SetupCount, &Function); 581da6c28aaSamw 5827b59d02dSjb150015 if (rc != 0) 583faa1795aSjb150015 return (SDRC_ERROR); 584da6c28aaSamw 585da6c28aaSamw xa = smb_xa_create(sr->session, sr, TotalParameterCount, TotalDataCount, 586da6c28aaSamw MaxParameterCount, MaxDataCount, MaxSetupCount, SetupCount); 587da6c28aaSamw if (xa == 0) { 588dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRnoroom); 589faa1795aSjb150015 return (SDRC_ERROR); 590da6c28aaSamw } 591da6c28aaSamw 592da6c28aaSamw xa->smb_flags = 0; 593da6c28aaSamw xa->smb_timeout = 0; 594da6c28aaSamw xa->smb_func = Function; 595da6c28aaSamw xa->req_disp_param = pscnt; 596da6c28aaSamw xa->req_disp_data = dscnt; 597da6c28aaSamw 5987f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv, 599da6c28aaSamw sr->smb_vwv.chain_offset, SetupCount * 2)) { 600da6c28aaSamw smb_xa_rele(sr->session, xa); 601dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 602faa1795aSjb150015 return (SDRC_ERROR); 603da6c28aaSamw } 6047f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 605da6c28aaSamw smb_xa_rele(sr->session, xa); 606dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 607faa1795aSjb150015 return (SDRC_ERROR); 608da6c28aaSamw } 6097f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 610da6c28aaSamw smb_xa_rele(sr->session, xa); 611dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 612faa1795aSjb150015 return (SDRC_ERROR); 613da6c28aaSamw } 614da6c28aaSamw 615da6c28aaSamw ready = smb_trans_ready(xa); 616da6c28aaSamw 617da6c28aaSamw if (smb_xa_open(xa)) { 618da6c28aaSamw smb_xa_rele(sr->session, xa); 619ccc71be5SGordon Ross smbsr_error(sr, 0, ERRSRV, ERRsrverror); 620faa1795aSjb150015 return (SDRC_ERROR); 621da6c28aaSamw } 622da6c28aaSamw sr->r_xa = xa; 623da6c28aaSamw 624da6c28aaSamw if (!ready) { 6257b59d02dSjb150015 rc = smbsr_encode_empty_result(sr); 626faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 627da6c28aaSamw } 628da6c28aaSamw 629da6c28aaSamw if (!smb_xa_complete(xa)) { 630da6c28aaSamw smb_xa_close(xa); 631dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 632faa1795aSjb150015 return (SDRC_ERROR); 633da6c28aaSamw } 634da6c28aaSamw 635da6c28aaSamw return (smb_nt_trans_dispatch(sr, xa)); 636da6c28aaSamw } 637da6c28aaSamw 638faa1795aSjb150015 smb_sdrc_t 639faa1795aSjb150015 smb_pre_nt_transact_secondary(smb_request_t *sr) 640faa1795aSjb150015 { 641faa1795aSjb150015 DTRACE_SMB_1(op__NtTransactSecondary__start, smb_request_t *, sr); 642faa1795aSjb150015 return (SDRC_SUCCESS); 643faa1795aSjb150015 } 644faa1795aSjb150015 645faa1795aSjb150015 void 646faa1795aSjb150015 smb_post_nt_transact_secondary(smb_request_t *sr) 647faa1795aSjb150015 { 648faa1795aSjb150015 DTRACE_SMB_1(op__NtTransactSecondary__done, smb_request_t *, sr); 649faa1795aSjb150015 } 650da6c28aaSamw 6517b59d02dSjb150015 smb_sdrc_t 652da6c28aaSamw smb_com_nt_transact_secondary(struct smb_request *sr) 653da6c28aaSamw { 654da6c28aaSamw uint16_t tpscnt, tdscnt, fid; 655da6c28aaSamw uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp; 656da6c28aaSamw smb_xa_t *xa; 657da6c28aaSamw int rc; 658da6c28aaSamw 659da6c28aaSamw if ((xa = smbsr_lookup_xa(sr)) == 0) { 660dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 661faa1795aSjb150015 return (SDRC_ERROR); 662da6c28aaSamw } 663da6c28aaSamw 664da6c28aaSamw if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 665da6c28aaSamw if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { 666dc20a302Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 667da6c28aaSamw ERRDOS, ERRnoaccess); 668faa1795aSjb150015 return (SDRC_ERROR); 669da6c28aaSamw } 670da6c28aaSamw } 671da6c28aaSamw 672da6c28aaSamw if (xa->smb_com != SMB_COM_TRANSACTION2) { 673da6c28aaSamw return (SDRC_DROP_VC); 674da6c28aaSamw } 675da6c28aaSamw 676da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt, 677da6c28aaSamw &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid); 678da6c28aaSamw 6797b59d02dSjb150015 if (rc != 0) 680faa1795aSjb150015 return (SDRC_ERROR); 681da6c28aaSamw 682da6c28aaSamw mutex_enter(&xa->xa_mutex); 6837f3ef643SGordon Ross if (xa->smb_tpscnt > tpscnt) 6847f3ef643SGordon Ross xa->smb_tpscnt = tpscnt; 6857f3ef643SGordon Ross if (xa->smb_tdscnt > tdscnt) 6867f3ef643SGordon Ross xa->smb_tdscnt = tdscnt; 6877f3ef643SGordon Ross if (fid != 0xFFFF) 6887f3ef643SGordon Ross xa->xa_smb_fid = fid; 689da6c28aaSamw xa->req_disp_param = psdisp + pscnt; 690da6c28aaSamw xa->req_disp_data = dsdisp + dscnt; 691da6c28aaSamw 6927f3ef643SGordon Ross /* 6937f3ef643SGordon Ross * See comment in smb_com_transaction_secondary 6947f3ef643SGordon Ross */ 6957f3ef643SGordon Ross if (xa->req_param_mb.chain_offset != psdisp) { 6967f3ef643SGordon Ross DTRACE_PROBE2(trans_param_disp, 6977f3ef643SGordon Ross smb_xa_t *, xa, uint16_t, psdisp); 6987f3ef643SGordon Ross xa->req_param_mb.chain_offset = psdisp; 6997f3ef643SGordon Ross } 7007f3ef643SGordon Ross if (xa->req_data_mb.chain_offset != dsdisp) { 7017f3ef643SGordon Ross DTRACE_PROBE2(trans_data_disp, 7027f3ef643SGordon Ross smb_xa_t *, xa, uint16_t, dsdisp); 7037f3ef643SGordon Ross xa->req_data_mb.chain_offset = dsdisp; 7047f3ef643SGordon Ross } 7057f3ef643SGordon Ross 7067f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 707da6c28aaSamw mutex_exit(&xa->xa_mutex); 708da6c28aaSamw smb_xa_close(xa); 709dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 710faa1795aSjb150015 return (SDRC_ERROR); 711da6c28aaSamw } 7127f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 713da6c28aaSamw mutex_exit(&xa->xa_mutex); 714da6c28aaSamw smb_xa_close(xa); 715dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 716faa1795aSjb150015 return (SDRC_ERROR); 717da6c28aaSamw } 718da6c28aaSamw mutex_exit(&xa->xa_mutex); 719da6c28aaSamw 720da6c28aaSamw if (!smb_trans_ready(xa)) 721da6c28aaSamw return (SDRC_NO_REPLY); 722da6c28aaSamw 723da6c28aaSamw if (!smb_xa_complete(xa)) 724da6c28aaSamw return (SDRC_NO_REPLY); 725da6c28aaSamw 726da6c28aaSamw return (smb_nt_trans_dispatch(sr, xa)); 727da6c28aaSamw } 728da6c28aaSamw 7297b59d02dSjb150015 static int 7309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_trans_ready(smb_xa_t *xa) 731da6c28aaSamw { 732da6c28aaSamw int rc; 733da6c28aaSamw 734da6c28aaSamw mutex_enter(&xa->xa_mutex); 735da6c28aaSamw rc = xa->req_disp_data >= xa->smb_tdscnt && 736da6c28aaSamw xa->req_disp_param >= xa->smb_tpscnt; 737da6c28aaSamw mutex_exit(&xa->xa_mutex); 738da6c28aaSamw 739da6c28aaSamw return (rc); 740da6c28aaSamw } 741da6c28aaSamw 7423ad684d6Sjb150015 static void 7433ad684d6Sjb150015 smb_encode_SHARE_INFO_1(struct mbuf_chain *output, struct mbuf_chain *text, 7443ad684d6Sjb150015 char *oem_name, uint16_t type, char *comment) 745da6c28aaSamw { 7463db3f65cSamw (void) smb_mbc_encodef(output, "13c.wl", oem_name, 7473ad684d6Sjb150015 type, MBC_LENGTH(text)); 748da6c28aaSamw 7493db3f65cSamw (void) smb_mbc_encodef(text, "s", comment ? comment : ""); 7506537f381Sas200622 } 751da6c28aaSamw 7523ad684d6Sjb150015 static void 7533ad684d6Sjb150015 smb_encode_SHARE_INFO_2(struct mbuf_chain *output, struct mbuf_chain *text, 7543ad684d6Sjb150015 smb_request_t *sr, char *oem_name, uint16_t type, 7553ad684d6Sjb150015 char *comment, uint16_t access, char *path, char *password) 756da6c28aaSamw { 757da6c28aaSamw unsigned char pword[9]; 758da6c28aaSamw 759da6c28aaSamw bzero(pword, sizeof (pword)); 760da6c28aaSamw (void) strncpy((char *)pword, password, sizeof (pword)); 7613ad684d6Sjb150015 smb_encode_SHARE_INFO_1(output, text, oem_name, type, comment); 7623db3f65cSamw (void) smb_mbc_encodef(output, "wwwl9c.", 763da6c28aaSamw access, 764faa1795aSjb150015 sr->sr_cfg->skc_maxconnections, 7658622ec45SGordon Ross smb_server_get_session_count(sr->sr_server), 766da6c28aaSamw MBC_LENGTH(text), 7673ad684d6Sjb150015 pword); 7683db3f65cSamw (void) smb_mbc_encodef(text, "s", path); 769da6c28aaSamw } 770da6c28aaSamw 771da6c28aaSamw int 772da6c28aaSamw smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa) 773da6c28aaSamw { 774da6c28aaSamw /* 775da6c28aaSamw * Number of data bytes that will 776da6c28aaSamw * be sent in the current response 777da6c28aaSamw */ 778da6c28aaSamw uint16_t data_scnt; 779da6c28aaSamw 780da6c28aaSamw /* 781da6c28aaSamw * Total number of data bytes that 782da6c28aaSamw * are sent till now. This is only 783da6c28aaSamw * used for calculating current data 784da6c28aaSamw * displacement 785da6c28aaSamw */ 786da6c28aaSamw uint16_t tot_data_scnt; 787da6c28aaSamw 788da6c28aaSamw /* 789da6c28aaSamw * Number of parameter bytes should 790da6c28aaSamw * be sent for the current response. 791da6c28aaSamw * It is 8 for the 1st response and 792da6c28aaSamw * 0 for others 793da6c28aaSamw */ 794da6c28aaSamw uint16_t param_scnt; 795da6c28aaSamw 796da6c28aaSamw /* number of setup and parameter bytes */ 797da6c28aaSamw uint16_t n_setup, n_param; 798da6c28aaSamw 799da6c28aaSamw /* data and parameter displacement */ 800da6c28aaSamw uint16_t data_disp, param_disp; 801da6c28aaSamw 802da6c28aaSamw /* parameter and data offset and pad */ 803da6c28aaSamw int param_off, param_pad, data_off, data_pad; 804da6c28aaSamw 805da6c28aaSamw /* 806da6c28aaSamw * total bytes of parameters and data 807da6c28aaSamw * in the packet, plus the pad bytes. 808da6c28aaSamw */ 809da6c28aaSamw int tot_packet_bytes; 810da6c28aaSamw 8113ad684d6Sjb150015 boolean_t first_resp; 812da6c28aaSamw 8133ad684d6Sjb150015 char fmt[16]; 8143ad684d6Sjb150015 struct mbuf_chain reply; 8153ad684d6Sjb150015 8163ad684d6Sjb150015 uint16_t level; 8173ad684d6Sjb150015 uint16_t pkt_bufsize; 8183ad684d6Sjb150015 smb_enumshare_info_t esi; 8193ad684d6Sjb150015 char *sent_buf; 8203ad684d6Sjb150015 8213ad684d6Sjb150015 ASSERT(sr->uid_user); 822da6c28aaSamw 8233db3f65cSamw if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level, 8243ad684d6Sjb150015 &esi.es_bufsize) != 0) 825faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED); 826da6c28aaSamw 827da6c28aaSamw if (level != 1) { 8283ad684d6Sjb150015 /* 8293ad684d6Sjb150015 * Only level 1 is valid for NetShareEnum 8303ad684d6Sjb150015 * None of the error codes in the spec are meaningful 8313ad684d6Sjb150015 * here. This error code is returned by Windows. 8323ad684d6Sjb150015 */ 8333db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 8343ad684d6Sjb150015 ERROR_INVALID_LEVEL, 0, 0, 0); 835faa1795aSjb150015 return (SDRC_SUCCESS); 836da6c28aaSamw } 837da6c28aaSamw 838148c5f43SAlan Wright esi.es_buf = smb_srm_zalloc(sr, esi.es_bufsize); 839c5866007SKeyur Desai esi.es_posix_uid = crgetuid(sr->uid_user->u_cred); 8408622ec45SGordon Ross smb_kshare_enum(sr->sr_server, &esi); 841da6c28aaSamw 8423ad684d6Sjb150015 /* client buffer size is not big enough to hold any shares */ 8433ad684d6Sjb150015 if (esi.es_nsent == 0) { 8443db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 8453ad684d6Sjb150015 ERROR_MORE_DATA, 0, esi.es_nsent, esi.es_ntotal); 846faa1795aSjb150015 return (SDRC_SUCCESS); 847da6c28aaSamw } 848da6c28aaSamw 849da6c28aaSamw /* 8507f3ef643SGordon Ross * Initialize the reply mbuf chain. Note that we re-initialize 8517f3ef643SGordon Ross * this on each pass through the loop below. 8527f3ef643SGordon Ross */ 8537f3ef643SGordon Ross MBC_SETUP(&reply, smb_maxbufsize); 8547f3ef643SGordon Ross 8557f3ef643SGordon Ross /* 856da6c28aaSamw * The rep_setup_mb is already initialized in smb_trans_dispatch(). 857da6c28aaSamw * Calling MBC_INIT() will initialized the structure and so the 858da6c28aaSamw * pointer to the mbuf chains will be lost. Therefore, we need 859da6c28aaSamw * to free the resources before calling MBC_INIT() again. 860da6c28aaSamw */ 8613ad684d6Sjb150015 n_setup = 0; /* Setup count for NetShareEnum SMB is 0 */ 8627f3ef643SGordon Ross MBC_FLUSH(&xa->rep_setup_mb); 863da6c28aaSamw 8643ad684d6Sjb150015 n_param = 8; 8653ad684d6Sjb150015 pkt_bufsize = sr->session->smb_msg_size - 8663ad684d6Sjb150015 (SMB_HEADER_ED_LEN + RESP_HEADER_LEN + n_param); 867da6c28aaSamw 8683ad684d6Sjb150015 tot_data_scnt = 0; 8693ad684d6Sjb150015 sent_buf = esi.es_buf; 8703ad684d6Sjb150015 first_resp = B_TRUE; 8713ad684d6Sjb150015 8723ad684d6Sjb150015 while (tot_data_scnt < esi.es_datasize) { 8733ad684d6Sjb150015 data_scnt = esi.es_datasize - tot_data_scnt; 8743ad684d6Sjb150015 if (data_scnt > pkt_bufsize) 8753ad684d6Sjb150015 data_scnt = pkt_bufsize; 8767f3ef643SGordon Ross MBC_FLUSH(&xa->rep_data_mb); 8773ad684d6Sjb150015 8783ad684d6Sjb150015 (void) sprintf(fmt, "%dc", data_scnt); 8793db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, fmt, sent_buf); 8803ad684d6Sjb150015 8813ad684d6Sjb150015 sent_buf += data_scnt; 882da6c28aaSamw tot_data_scnt += data_scnt; 883da6c28aaSamw 884da6c28aaSamw /* Only the 1st response packet contains parameters */ 885da6c28aaSamw param_scnt = (first_resp) ? n_param : 0; 886da6c28aaSamw param_pad = 1; /* always one */ 887da6c28aaSamw param_off = SMB_HEADER_ED_LEN + RESP_HEADER_LEN; 888da6c28aaSamw param_disp = (first_resp) ? 0 : n_param; 889da6c28aaSamw 8907f3ef643SGordon Ross MBC_FLUSH(&xa->rep_param_mb); 8913ad684d6Sjb150015 892da6c28aaSamw if (first_resp) { 8933ad684d6Sjb150015 first_resp = B_FALSE; 8943db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 8953ad684d6Sjb150015 (esi.es_ntotal > esi.es_nsent) 8963ad684d6Sjb150015 ? ERROR_MORE_DATA : 0, 8973ad684d6Sjb150015 0, esi.es_nsent, esi.es_ntotal); 898da6c28aaSamw } 899da6c28aaSamw 900da6c28aaSamw data_pad = (param_off + n_param) & 1; /* Pad to short */ 901da6c28aaSamw 902da6c28aaSamw /* data off from hdr start */ 903da6c28aaSamw data_off = param_off + param_scnt + data_pad; 904da6c28aaSamw data_disp = tot_data_scnt - data_scnt; 905da6c28aaSamw tot_packet_bytes = param_pad + param_scnt + data_pad + 906da6c28aaSamw data_scnt; 907da6c28aaSamw 9087f3ef643SGordon Ross MBC_FLUSH(&reply); 9093db3f65cSamw (void) smb_mbc_encodef(&reply, SMB_HEADER_ED_FMT, 910da6c28aaSamw sr->first_smb_com, 911da6c28aaSamw sr->smb_rcls, 912da6c28aaSamw sr->smb_reh, 913da6c28aaSamw sr->smb_err, 914da6c28aaSamw sr->smb_flg | SMB_FLAGS_REPLY, 915da6c28aaSamw sr->smb_flg2, 916da6c28aaSamw sr->smb_pid_high, 917da6c28aaSamw sr->smb_sig, 918da6c28aaSamw sr->smb_tid, 919da6c28aaSamw sr->smb_pid, 920da6c28aaSamw sr->smb_uid, 921da6c28aaSamw sr->smb_mid); 922da6c28aaSamw 9233db3f65cSamw (void) smb_mbc_encodef(&reply, 924da6c28aaSamw "bww2.wwwwwwb.Cw#.C#.C", 925da6c28aaSamw 10 + n_setup, /* wct */ 926da6c28aaSamw n_param, /* Total Parameter Bytes */ 9273ad684d6Sjb150015 esi.es_datasize, /* Total Data Bytes */ 928da6c28aaSamw param_scnt, /* Total Parameter Bytes this buffer */ 929da6c28aaSamw param_off, /* Param offset from header start */ 930da6c28aaSamw param_disp, /* Param displacement */ 931da6c28aaSamw data_scnt, /* Total Data Bytes this buffer */ 932da6c28aaSamw data_off, /* Data offset from header start */ 933da6c28aaSamw data_disp, /* Data displacement */ 934da6c28aaSamw n_setup, /* suwcnt */ 935da6c28aaSamw &xa->rep_setup_mb, /* setup[] */ 936da6c28aaSamw tot_packet_bytes, /* Total data bytes */ 937da6c28aaSamw param_pad, 938da6c28aaSamw &xa->rep_param_mb, 939da6c28aaSamw data_pad, 940da6c28aaSamw &xa->rep_data_mb); 941da6c28aaSamw 942da6c28aaSamw if (sr->session->signing.flags & SMB_SIGNING_ENABLED) 943b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_sign_reply(sr, &reply); 944da6c28aaSamw 945da6c28aaSamw (void) smb_session_send(sr->session, 0, &reply); 9467f3ef643SGordon Ross 947da6c28aaSamw } 948da6c28aaSamw 9497f3ef643SGordon Ross m_freem(reply.chain); 9507f3ef643SGordon Ross 951da6c28aaSamw return (SDRC_NO_REPLY); 952da6c28aaSamw } 953da6c28aaSamw 954da6c28aaSamw int 9553ad684d6Sjb150015 smb_trans_net_share_getinfo(smb_request_t *sr, struct smb_xa *xa) 956da6c28aaSamw { 9573ad684d6Sjb150015 uint16_t level, max_bytes, access; 958da6c28aaSamw struct mbuf_chain str_mb; 959da6c28aaSamw char *share; 960da6c28aaSamw char *password; 961148c5f43SAlan Wright smb_kshare_t *si; 962da6c28aaSamw 9633db3f65cSamw if (smb_mbc_decodef(&xa->req_param_mb, "%sww", sr, 9643ad684d6Sjb150015 &share, &level, &max_bytes) != 0) 965faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED); 966da6c28aaSamw 9678622ec45SGordon Ross si = smb_kshare_lookup(sr->sr_server, share); 968148c5f43SAlan Wright if ((si == NULL) || (si->shr_oemname == NULL)) { 9693db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 970da6c28aaSamw NERR_NetNameNotFound, 0, 0); 971148c5f43SAlan Wright if (si) 9728622ec45SGordon Ross smb_kshare_release(sr->sr_server, si); 973faa1795aSjb150015 return (SDRC_SUCCESS); 974da6c28aaSamw } 975da6c28aaSamw 9763ad684d6Sjb150015 access = SHARE_ACCESS_ALL; 977da6c28aaSamw password = ""; 978da6c28aaSamw 979da6c28aaSamw MBC_INIT(&str_mb, max_bytes); 980da6c28aaSamw 981da6c28aaSamw switch (level) { 982da6c28aaSamw case 0 : 983148c5f43SAlan Wright (void) smb_mbc_encodef(&xa->rep_data_mb, "13c", 984148c5f43SAlan Wright si->shr_oemname); 985da6c28aaSamw break; 986da6c28aaSamw 987da6c28aaSamw case 1 : 9883ad684d6Sjb150015 smb_encode_SHARE_INFO_1(&xa->rep_data_mb, &str_mb, 989148c5f43SAlan Wright si->shr_oemname, si->shr_type, si->shr_cmnt); 990da6c28aaSamw break; 991da6c28aaSamw 992da6c28aaSamw case 2 : 9933ad684d6Sjb150015 smb_encode_SHARE_INFO_2(&xa->rep_data_mb, &str_mb, sr, 994148c5f43SAlan Wright si->shr_oemname, si->shr_type, si->shr_cmnt, access, 995148c5f43SAlan Wright si->shr_path, password); 9963ad684d6Sjb150015 break; 9973ad684d6Sjb150015 998da6c28aaSamw default: 9998622ec45SGordon Ross smb_kshare_release(sr->sr_server, si); 10003db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 10013ad684d6Sjb150015 ERROR_INVALID_LEVEL, 0, 0); 1002da6c28aaSamw m_freem(str_mb.chain); 1003faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED); 1004da6c28aaSamw } 1005da6c28aaSamw 10068622ec45SGordon Ross smb_kshare_release(sr->sr_server, si); 10073db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www", NERR_Success, 1008da6c28aaSamw -MBC_LENGTH(&xa->rep_data_mb), 1009da6c28aaSamw MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb)); 10103db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb); 1011da6c28aaSamw m_freem(str_mb.chain); 1012faa1795aSjb150015 return (SDRC_SUCCESS); 1013da6c28aaSamw } 1014da6c28aaSamw 1015da6c28aaSamw int 10163ad684d6Sjb150015 smb_trans_net_workstation_getinfo(struct smb_request *sr, struct smb_xa *xa) 1017da6c28aaSamw { 10183ad684d6Sjb150015 uint16_t level, max_bytes; 1019da6c28aaSamw struct mbuf_chain str_mb; 1020da6c28aaSamw char *domain; 1021da6c28aaSamw char *hostname; 1022da6c28aaSamw 10233db3f65cSamw if ((smb_mbc_decodef(&xa->req_param_mb, "ww", 10243ad684d6Sjb150015 &level, &max_bytes) != 0) || 1025da6c28aaSamw (level != 10)) { 10263db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 1027da6c28aaSamw NERR_BadTransactConfig, 0, 0, 0); 1028faa1795aSjb150015 return (SDRC_SUCCESS); 1029da6c28aaSamw } 1030da6c28aaSamw 1031b89a8333Snatalie li - Sun Microsystems - Irvine United States domain = sr->sr_cfg->skc_nbdomain; 1032faa1795aSjb150015 hostname = sr->sr_cfg->skc_hostname; 1033da6c28aaSamw 1034da6c28aaSamw MBC_INIT(&str_mb, max_bytes); 1035da6c28aaSamw 10363db3f65cSamw (void) smb_mbc_encodef(&str_mb, "."); /* Prevent NULL pointers */ 1037da6c28aaSamw 10383db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 10393db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", hostname); 10403db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 10413db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", "nobody"); 10423db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 10433db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", domain); 10443db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "bbl", 1045fd9ee8b5Sjoyce mcintosh (uint8_t)sr->sr_cfg->skc_version.sv_major, 1046fd9ee8b5Sjoyce mcintosh (uint8_t)sr->sr_cfg->skc_version.sv_minor, 10479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States MBC_LENGTH(&str_mb)); 10483db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", domain); 10493db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 10503db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", domain); 1051da6c28aaSamw 10523db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 0, 1053da6c28aaSamw -MBC_LENGTH(&xa->rep_data_mb), 1054da6c28aaSamw MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb)); 10553db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb); 1056da6c28aaSamw m_freem(str_mb.chain); 1057faa1795aSjb150015 return (SDRC_SUCCESS); 1058da6c28aaSamw } 1059da6c28aaSamw 1060da6c28aaSamw int 10613ad684d6Sjb150015 smb_trans_net_user_getinfo(struct smb_request *sr, struct smb_xa *xa) 1062da6c28aaSamw { 10633ad684d6Sjb150015 uint16_t level, max_bytes; 1064da6c28aaSamw unsigned char *user; 1065da6c28aaSamw int rc; 1066da6c28aaSamw 10673db3f65cSamw rc = smb_mbc_decodef(&xa->req_param_mb, "%sww", sr, 1068da6c28aaSamw &user, 1069da6c28aaSamw &level, 1070da6c28aaSamw &max_bytes); 1071da6c28aaSamw 1072da6c28aaSamw if (rc != 0) 1073faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED); 1074da6c28aaSamw 10753db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 1076da6c28aaSamw NERR_UserNotFound, 0, 0); 1077faa1795aSjb150015 return (SDRC_SUCCESS); 1078da6c28aaSamw } 1079da6c28aaSamw 10807b59d02dSjb150015 smb_sdrc_t 10813ad684d6Sjb150015 smb_trans_net_server_getinfo(struct smb_request *sr, struct smb_xa *xa) 1082da6c28aaSamw { 10833ad684d6Sjb150015 uint16_t level, buf_size; 10843ad684d6Sjb150015 uint16_t avail_data, max_data; 1085da6c28aaSamw char server_name[16]; 1086da6c28aaSamw struct mbuf_chain str_mb; 1087da6c28aaSamw 10883db3f65cSamw if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level, &buf_size) != 0) 1089faa1795aSjb150015 return (SDRC_ERROR); 1090da6c28aaSamw 10913ad684d6Sjb150015 max_data = MBC_MAXBYTES(&xa->rep_data_mb); 1092da6c28aaSamw 1093da6c28aaSamw MBC_INIT(&str_mb, buf_size); 1094da6c28aaSamw 1095da6c28aaSamw bzero(server_name, sizeof (server_name)); 10963ad684d6Sjb150015 (void) strncpy(server_name, sr->sr_cfg->skc_hostname, 10973ad684d6Sjb150015 sizeof (server_name)); 1098da6c28aaSamw 10993ad684d6Sjb150015 /* valid levels are 0 and 1 */ 1100da6c28aaSamw switch (level) { 1101da6c28aaSamw case 0: 11023db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "16c", server_name); 1103da6c28aaSamw break; 11043ad684d6Sjb150015 1105da6c28aaSamw case 1: 11063db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", 11073ad684d6Sjb150015 sr->sr_cfg->skc_system_comment); 11083db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "16cbbll", server_name, 1109fd9ee8b5Sjoyce mcintosh (uint8_t)sr->sr_cfg->skc_version.sv_major, 1110fd9ee8b5Sjoyce mcintosh (uint8_t)sr->sr_cfg->skc_version.sv_minor, 11113ad684d6Sjb150015 MY_SERVER_TYPE, max_data - MBC_LENGTH(&str_mb)); 1112da6c28aaSamw break; 11133ad684d6Sjb150015 1114da6c28aaSamw default: 11153db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 11163ad684d6Sjb150015 ERROR_INVALID_LEVEL, 0, 0); 1117da6c28aaSamw m_freem(str_mb.chain); 11183ad684d6Sjb150015 return (SDRC_SUCCESS); 1119da6c28aaSamw } 1120da6c28aaSamw 11213ad684d6Sjb150015 avail_data = MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb); 11223db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 11233ad684d6Sjb150015 NERR_Success, max_data - avail_data, avail_data); 11243db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb); 1125da6c28aaSamw m_freem(str_mb.chain); 1126faa1795aSjb150015 return (SDRC_SUCCESS); 1127da6c28aaSamw } 1128da6c28aaSamw 1129da6c28aaSamw /* 1130da6c28aaSamw * 6.4 The NetServerEnum2 RAP Service 1131da6c28aaSamw * 1132da6c28aaSamw * The NetServerEnum2 RAP service lists all computers of the specified type 1133da6c28aaSamw * or types that are visible in the specified domains. It may also 1134da6c28aaSamw * enumerate domains. 1135da6c28aaSamw * 1136da6c28aaSamw * The following definition uses the notation and terminology defined in 1137da6c28aaSamw * the CIFS Remote Administration Protocol specification, which is required 1138da6c28aaSamw * in order to make it well-defined. The definition is: 1139da6c28aaSamw * 1140da6c28aaSamw * uint16_t NetServerEnum2 ( 1141da6c28aaSamw * uint16_t sLevel, 1142da6c28aaSamw * RCVBUF pbBuffer, 1143da6c28aaSamw * RCVBUFLEN cbBuffer, 1144da6c28aaSamw * ENTCOUNT pcEntriesRead, 1145da6c28aaSamw * uint16_t *pcTotalAvail, 1146da6c28aaSamw * uint32_t fServerType, 1147da6c28aaSamw * char *pszDomain, 1148da6c28aaSamw * ); 1149da6c28aaSamw * 1150da6c28aaSamw * where: 1151da6c28aaSamw * 1152da6c28aaSamw * sLevel specifies the level of detail (0 or 1) requested. 1153da6c28aaSamw * 1154da6c28aaSamw * pbBuffer points to the buffer to receive the returned data. If the 1155da6c28aaSamw * function is successful, the buffer contains a sequence of 1156da6c28aaSamw * server_info_x structures, where x is 0 or 1, depending on the 1157da6c28aaSamw * level of detail requested. 1158da6c28aaSamw * 1159da6c28aaSamw * cbBuffer specifies the size, in bytes, of the buffer pointed to by 1160da6c28aaSamw * the pbBuffer parameter. 1161da6c28aaSamw * 1162da6c28aaSamw * pcEntriesRead points to a 16 bit variable that receives a count of 1163da6c28aaSamw * the number of servers enumerated in the buffer. This count is 1164da6c28aaSamw * valid only if NetServerEnum2 returns the NERR_Success or 1165da6c28aaSamw * ERROR_MORE_DATA values. 1166da6c28aaSamw * 1167da6c28aaSamw * pcTotal Avail points to a 16 bit variable that receives a count of 1168da6c28aaSamw * the total number of available entries. This count is valid only if 1169da6c28aaSamw * NetServerEnum2 returns the NERR_Success or ERROR_MORE_DATA values. 1170da6c28aaSamw * 1171da6c28aaSamw * fServerType specifies the type or types of computers to enumerate. 1172da6c28aaSamw * Computers that match at least one of the specified types are 1173da6c28aaSamw * returned in the buffer. Possible values are defined in the request 1174da6c28aaSamw * parameters section. 1175da6c28aaSamw * 1176da6c28aaSamw * pszDomain points to a null-terminated string that contains the 1177da6c28aaSamw * name of the workgroup in which to enumerate computers of the 1178da6c28aaSamw * specified type or types. If the pszDomain parameter is a null 1179da6c28aaSamw * string or a null pointer, servers are enumerated for the current 1180da6c28aaSamw * domain of the computer. 1181da6c28aaSamw * 1182da6c28aaSamw * 6.4.1 Transaction Request Parameters section 1183da6c28aaSamw * 1184da6c28aaSamw * The Transaction request parameters section in this instance contains: 1185da6c28aaSamw * . The 16 bit function number for NetServerEnum2 which is 104. 1186da6c28aaSamw * . The parameter descriptor string which is "WrLehDz". 1187da6c28aaSamw * . The data descriptor string for the (returned) data which is "B16" for 1188da6c28aaSamw * level detail 0 or "B16BBDz" for level detail 1. 1189da6c28aaSamw * . The actual parameters as described by the parameter descriptor 1190da6c28aaSamw * string. 1191da6c28aaSamw * 1192da6c28aaSamw * The parameters are: 1193da6c28aaSamw * . A 16 bit integer with a value of 0 or 1 (corresponding to the "W" in 1194da6c28aaSamw * the parameter descriptor string. This represents the level of detail 1195da6c28aaSamw * the server is expected to return 1196da6c28aaSamw * . A 16 bit integer that contains the size of the receive buffer. 1197da6c28aaSamw * . A 32 bit integer that represents the type of servers the function 1198da6c28aaSamw * should enumerate. The possible values may be any of the following or 1199da6c28aaSamw * a combination of the following: 1200da6c28aaSamw * 1201da6c28aaSamw * SV_TYPE_WORKSTATION 0x00000001 All workstations 1202da6c28aaSamw * SV_TYPE_SERVER 0x00000002 All servers 1203da6c28aaSamw * SV_TYPE_SQLSERVER 0x00000004 Any server running with SQL 1204da6c28aaSamw * server 1205da6c28aaSamw * SV_TYPE_DOMAIN_CTRL 0x00000008 Primary domain controller 1206da6c28aaSamw * SV_TYPE_DOMAIN_BAKCTRL 0x00000010 Backup domain controller 1207da6c28aaSamw * SV_TYPE_TIME_SOURCE 0x00000020 Server running the timesource 1208da6c28aaSamw * service 1209da6c28aaSamw * SV_TYPE_AFP 0x00000040 Apple File Protocol servers 1210da6c28aaSamw * SV_TYPE_NOVELL 0x00000080 Novell servers 1211da6c28aaSamw * SV_TYPE_DOMAIN_MEMBER 0x00000100 Domain Member 1212da6c28aaSamw * SV_TYPE_PRINTQ_SERVER 0x00000200 Server sharing print queue 1213da6c28aaSamw * SV_TYPE_DIALIN_SERVER 0x00000400 Server running dialin service. 1214da6c28aaSamw * SV_TYPE_XENIX_SERVER 0x00000800 Xenix server 1215da6c28aaSamw * SV_TYPE_NT 0x00001000 NT server 1216da6c28aaSamw * SV_TYPE_WFW 0x00002000 Server running Windows for 1217da6c28aaSamw * Workgroups 1218da6c28aaSamw * SV_TYPE_SERVER_NT 0x00008000 Windows NT non DC server 1219da6c28aaSamw * SV_TYPE_POTENTIAL_BROWSER 0x00010000 Server that can run the browser 1220da6c28aaSamw * service 1221da6c28aaSamw * SV_TYPE_BACKUP_BROWSER 0x00020000 Backup browser server 1222da6c28aaSamw * SV_TYPE_MASTER_BROWSER 0x00040000 Master browser server 1223da6c28aaSamw * SV_TYPE_DOMAIN_MASTER 0x00080000 Domain Master Browser server 1224da6c28aaSamw * SV_TYPE_LOCAL_LIST_ONLY 0x40000000 Enumerate only entries marked 1225da6c28aaSamw * "local" 1226da6c28aaSamw * SV_TYPE_DOMAIN_ENUM 0x80000000 Enumerate Domains. The pszDomain 1227da6c28aaSamw * parameter must be NULL. 1228da6c28aaSamw * 1229da6c28aaSamw * . A null terminated ASCII string representing the pszDomain parameter 1230da6c28aaSamw * described above 1231da6c28aaSamw * 1232da6c28aaSamw * 6.4.2 Transaction Request Data section 1233da6c28aaSamw * 1234da6c28aaSamw * There is no data or auxiliary data to send as part of the request. 1235da6c28aaSamw * 1236da6c28aaSamw * 6.4.3 Transaction Response Parameters section 1237da6c28aaSamw * 1238da6c28aaSamw * The transaction response parameters section consists of: 1239da6c28aaSamw * . A 16 bit word indicating the return status. The possible values are: 1240da6c28aaSamw * 1241da6c28aaSamw * Code Value Description 1242da6c28aaSamw * NERR_Success 0 No errors encountered 1243da6c28aaSamw * ERROR_MORE_DATA 234 Additional data is available 1244da6c28aaSamw * NERR_ServerNotStarted 2114 The RAP service on the remote computer 1245da6c28aaSamw * is not running 1246da6c28aaSamw * NERR_BadTransactConfig 2141 The server is not configured for 1247da6c28aaSamw * transactions, IPC$ is not shared 1248da6c28aaSamw * 1249da6c28aaSamw * . A 16 bit "converter" word. 1250da6c28aaSamw * . A 16 bit number representing the number of entries returned. 1251da6c28aaSamw * . A 16 bit number representing the total number of available entries. 1252da6c28aaSamw * If the supplied buffer is large enough, this will equal the number of 1253da6c28aaSamw * entries returned. 1254da6c28aaSamw * 1255da6c28aaSamw * 6.4.4 Transaction Response Data section 1256da6c28aaSamw * 1257da6c28aaSamw * The return data section consists of a number of SERVER_INFO_1 structures. 1258da6c28aaSamw * The number of such structures present is determined by the third entry 1259da6c28aaSamw * (described above) in the return parameters section. 1260da6c28aaSamw * 1261da6c28aaSamw * At level detail 0, the Transaction response data section contains a 1262da6c28aaSamw * number of SERVER_INFO_0 data structure. The number of such structures is 1263da6c28aaSamw * equal to the 16 bit number returned by the server in the third parameter 1264da6c28aaSamw * in the Transaction response parameter section. The SERVER_INFO_0 data 1265da6c28aaSamw * structure is defined as: 1266da6c28aaSamw * 1267da6c28aaSamw * struct SERVER_INFO_0 { 1268da6c28aaSamw * char sv0_name[16]; 1269da6c28aaSamw * }; 1270da6c28aaSamw * 1271da6c28aaSamw * where: 1272da6c28aaSamw * 1273da6c28aaSamw * sv0_name is a null-terminated string that specifies the name of a 1274da6c28aaSamw * computer or domain . 1275da6c28aaSamw * 1276da6c28aaSamw * At level detail 1, the Transaction response data section contains a 1277da6c28aaSamw * number of SERVER_INFO_1 data structure. The number of such structures is 1278da6c28aaSamw * equal to the 16 bit number returned by the server in the third parameter 1279da6c28aaSamw * in the Transaction response parameter section. The SERVER_INFO_1 data 1280da6c28aaSamw * structure is defined as: 1281da6c28aaSamw * 1282da6c28aaSamw * struct SERVER_INFO_1 { 1283da6c28aaSamw * char sv1_name[16]; 1284da6c28aaSamw * char sv1_version_major; 1285da6c28aaSamw * char sv1_version_minor; 1286da6c28aaSamw * uint32_t sv1_type; 1287da6c28aaSamw * char *sv1_comment_or_master_browser; 1288da6c28aaSamw * }; 1289da6c28aaSamw * 1290da6c28aaSamw * sv1_name contains a null-terminated string that specifies the name 1291da6c28aaSamw * of a computer, or a domain name if SV_TYPE_DOMAIN_ENUM is set in 1292da6c28aaSamw * sv1_type. 1293da6c28aaSamw * 1294da6c28aaSamw * sv1_version_major whatever was specified in the HostAnnouncement 1295da6c28aaSamw * or DomainAnnouncement frame with which the entry was registered. 1296da6c28aaSamw * 1297da6c28aaSamw * sv1_version_minor whatever was specified in the HostAnnouncement 1298da6c28aaSamw * or DomainAnnouncement frame with which the entry was registered. 1299da6c28aaSamw * 1300da6c28aaSamw * sv1_type specifies the type of software the computer is running. 1301da6c28aaSamw * The member can be one or a combination of the values defined above 1302da6c28aaSamw * in the Transaction request parameters section for fServerType. 1303da6c28aaSamw * 1304da6c28aaSamw * 1305da6c28aaSamw * sv1_comment_or_master_browser points to a null-terminated string. If 1306da6c28aaSamw * the sv1_type indicates that the entry is for a domain, this 1307da6c28aaSamw * specifies the name of server running the domain master browser; 1308da6c28aaSamw * otherwise, it specifies a comment describing the server. The comment 1309da6c28aaSamw * can be a null string or the pointer may be a null pointer. 1310da6c28aaSamw * 1311da6c28aaSamw * In case there are multiple SERVER_INFO_1 data structures to 1312da6c28aaSamw * return, the server may put all these fixed length structures in 1313da6c28aaSamw * the return buffer, leave some space and then put all the variable 1314da6c28aaSamw * length data (the actual value of the sv1_comment strings) at the 1315da6c28aaSamw * end of the buffer. 1316da6c28aaSamw * 1317da6c28aaSamw * There is no auxiliary data to receive. 1318da6c28aaSamw */ 1319da6c28aaSamw 1320da6c28aaSamw int 1321da6c28aaSamw smb_trans_net_server_enum2(struct smb_request *sr, struct smb_xa *xa) 1322da6c28aaSamw { 1323da6c28aaSamw uint16_t opcode, level, max_bytes; 1324da6c28aaSamw uint32_t server_type; 1325da6c28aaSamw unsigned char *domain; 1326da6c28aaSamw struct mbuf_chain str_mb; 1327da6c28aaSamw char *hostname, *s; 1328da6c28aaSamw smb_kmod_cfg_t *si; 1329da6c28aaSamw 13303db3f65cSamw if (smb_mbc_decodef(&xa->req_param_mb, 13313db3f65cSamw "%wsswwls", sr, &opcode, &s, &s, 1332da6c28aaSamw &level, &max_bytes, &server_type, &domain) != 0) 1333faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED); 1334da6c28aaSamw 1335faa1795aSjb150015 si = sr->sr_cfg; 1336da6c28aaSamw 1337bbf6f00cSJordan Brown if (smb_strcasecmp(si->skc_nbdomain, (char *)domain, 0) != 0) { 13383db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0); 1339faa1795aSjb150015 return (SDRC_SUCCESS); 1340da6c28aaSamw } 1341da6c28aaSamw 1342da6c28aaSamw if ((server_type & MY_SERVER_TYPE) == 0) { 13433db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0); 1344faa1795aSjb150015 return (SDRC_SUCCESS); 1345da6c28aaSamw } 1346da6c28aaSamw 1347da6c28aaSamw MBC_INIT(&str_mb, max_bytes); 1348da6c28aaSamw 1349da6c28aaSamw hostname = si->skc_hostname; 1350da6c28aaSamw 13513db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "16c", hostname); 1352da6c28aaSamw if (level == 1) { 13533db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "bbll", 1354fd9ee8b5Sjoyce mcintosh (uint8_t)sr->sr_cfg->skc_version.sv_major, 1355fd9ee8b5Sjoyce mcintosh (uint8_t)sr->sr_cfg->skc_version.sv_minor, 1356da6c28aaSamw MY_SERVER_TYPE, MBC_LENGTH(&str_mb)); 13573db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", si->skc_system_comment); 1358da6c28aaSamw } 1359da6c28aaSamw 13603db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 1361da6c28aaSamw -MBC_LENGTH(&xa->rep_data_mb), 1, 1); 13623db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "m", str_mb.chain); 1363faa1795aSjb150015 return (SDRC_SUCCESS); 1364da6c28aaSamw } 1365da6c28aaSamw 1366bbf6f00cSJordan Brown static boolean_t 1367bbf6f00cSJordan Brown is_supported_mailslot(const char *mailslot) 1368da6c28aaSamw { 1369bbf6f00cSJordan Brown static char *mailslots[] = { 1370bbf6f00cSJordan Brown PIPE_LANMAN, 1371bbf6f00cSJordan Brown MAILSLOT_LANMAN, 1372bbf6f00cSJordan Brown MAILSLOT_BROWSE, 1373bbf6f00cSJordan Brown MAILSLOT_MSBROWSE 1374bbf6f00cSJordan Brown }; 1375da6c28aaSamw 1376bbf6f00cSJordan Brown int i; 1377bbf6f00cSJordan Brown 1378bbf6f00cSJordan Brown for (i = 0; i < sizeof (mailslots)/sizeof (mailslots[0]); ++i) 1379bbf6f00cSJordan Brown if (smb_strcasecmp(mailslot, mailslots[i], 0) == 0) 1380bbf6f00cSJordan Brown return (B_TRUE); 1381bbf6f00cSJordan Brown 1382bbf6f00cSJordan Brown return (B_FALSE); 1383bbf6f00cSJordan Brown } 1384bbf6f00cSJordan Brown 1385bbf6f00cSJordan Brown /* 138668b2bbf2SGordon Ross * smb_trans_nmpipe 138768b2bbf2SGordon Ross * 138868b2bbf2SGordon Ross * This is used for RPC bind and request transactions. 138968b2bbf2SGordon Ross * 139068b2bbf2SGordon Ross * If the data available from the pipe is larger than the maximum 139168b2bbf2SGordon Ross * data size requested by the client, return as much as requested. 139268b2bbf2SGordon Ross * The residual data remains in the pipe until the client comes back 139368b2bbf2SGordon Ross * with a read request or closes the pipe. 139468b2bbf2SGordon Ross * 139568b2bbf2SGordon Ross * When we read less than what's available, we MUST return the 139668b2bbf2SGordon Ross * status NT_STATUS_BUFFER_OVERFLOW (or ERRDOS/ERROR_MORE_DATA) 1397bbf6f00cSJordan Brown */ 139868b2bbf2SGordon Ross static smb_sdrc_t 139968b2bbf2SGordon Ross smb_trans_nmpipe(smb_request_t *sr, smb_xa_t *xa) 1400bbf6f00cSJordan Brown { 140168b2bbf2SGordon Ross smb_vdb_t vdb; 140268b2bbf2SGordon Ross struct mbuf *mb; 140368b2bbf2SGordon Ross int rc; 1404bbf6f00cSJordan Brown 140568b2bbf2SGordon Ross smbsr_lookup_file(sr); 140668b2bbf2SGordon Ross if (sr->fid_ofile == NULL) { 140768b2bbf2SGordon Ross smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 140868b2bbf2SGordon Ross ERRDOS, ERRbadfid); 140968b2bbf2SGordon Ross return (SDRC_ERROR); 141068b2bbf2SGordon Ross } 141168b2bbf2SGordon Ross 141268b2bbf2SGordon Ross rc = smb_mbc_decodef(&xa->req_data_mb, "#B", 141368b2bbf2SGordon Ross xa->smb_tdscnt, &vdb); 141468b2bbf2SGordon Ross if (rc != 0) { 141568b2bbf2SGordon Ross /* Not enough data sent. */ 141668b2bbf2SGordon Ross smbsr_error(sr, 0, ERRSRV, ERRerror); 141768b2bbf2SGordon Ross return (SDRC_ERROR); 141868b2bbf2SGordon Ross } 141968b2bbf2SGordon Ross 142068b2bbf2SGordon Ross rc = smb_opipe_write(sr, &vdb.vdb_uio); 142168b2bbf2SGordon Ross if (rc != 0) { 142268b2bbf2SGordon Ross smbsr_errno(sr, rc); 142368b2bbf2SGordon Ross return (SDRC_ERROR); 142468b2bbf2SGordon Ross } 142568b2bbf2SGordon Ross 142668b2bbf2SGordon Ross vdb.vdb_tag = 0; 142768b2bbf2SGordon Ross vdb.vdb_uio.uio_iov = &vdb.vdb_iovec[0]; 142868b2bbf2SGordon Ross vdb.vdb_uio.uio_iovcnt = MAX_IOVEC; 142968b2bbf2SGordon Ross vdb.vdb_uio.uio_segflg = UIO_SYSSPACE; 143068b2bbf2SGordon Ross vdb.vdb_uio.uio_extflg = UIO_COPY_DEFAULT; 143168b2bbf2SGordon Ross vdb.vdb_uio.uio_loffset = (offset_t)0; 143268b2bbf2SGordon Ross vdb.vdb_uio.uio_resid = xa->smb_mdrcnt; 143368b2bbf2SGordon Ross mb = smb_mbuf_allocate(&vdb.vdb_uio); 143468b2bbf2SGordon Ross 143568b2bbf2SGordon Ross rc = smb_opipe_read(sr, &vdb.vdb_uio); 143668b2bbf2SGordon Ross if (rc != 0) { 1437*bce01b59SGordon Ross m_freem(mb); 143868b2bbf2SGordon Ross smbsr_errno(sr, rc); 143968b2bbf2SGordon Ross return (SDRC_ERROR); 144068b2bbf2SGordon Ross } 144168b2bbf2SGordon Ross 144268b2bbf2SGordon Ross smb_mbuf_trim(mb, xa->smb_mdrcnt - vdb.vdb_uio.uio_resid); 144368b2bbf2SGordon Ross MBC_ATTACH_MBUF(&xa->rep_data_mb, mb); 144468b2bbf2SGordon Ross 1445*bce01b59SGordon Ross /* 1446*bce01b59SGordon Ross * If the output buffer holds a partial pipe message, 1447*bce01b59SGordon Ross * we're supposed to return NT_STATUS_BUFFER_OVERFLOW. 1448*bce01b59SGordon Ross * As we don't have message boundary markers, the best 1449*bce01b59SGordon Ross * we can do is return that status when we have ALL of: 1450*bce01b59SGordon Ross * Output buffer was < SMB_PIPE_MAX_MSGSIZE 1451*bce01b59SGordon Ross * We filled the output buffer (resid==0) 1452*bce01b59SGordon Ross * There's more data (ioctl FIONREAD) 1453*bce01b59SGordon Ross */ 1454*bce01b59SGordon Ross if (xa->smb_mdrcnt < SMB_PIPE_MAX_MSGSIZE && 1455*bce01b59SGordon Ross vdb.vdb_uio.uio_resid == 0) { 1456*bce01b59SGordon Ross int nread = 0; 1457*bce01b59SGordon Ross rc = smb_opipe_get_nread(sr, &nread); 1458*bce01b59SGordon Ross if (rc == 0 && nread != 0) { 1459*bce01b59SGordon Ross smbsr_status(sr, NT_STATUS_BUFFER_OVERFLOW, 1460*bce01b59SGordon Ross ERRDOS, ERROR_MORE_DATA); 1461*bce01b59SGordon Ross } 1462*bce01b59SGordon Ross } 1463*bce01b59SGordon Ross 146468b2bbf2SGordon Ross return (SDRC_SUCCESS); 1465da6c28aaSamw } 1466da6c28aaSamw 14677b59d02dSjb150015 static smb_sdrc_t 14689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_trans_dispatch(smb_request_t *sr, smb_xa_t *xa) 1469da6c28aaSamw { 1470da6c28aaSamw int rc, pos; 1471da6c28aaSamw int total_bytes, n_setup, n_param, n_data; 1472da6c28aaSamw int param_off, param_pad, data_off, data_pad; 1473da6c28aaSamw uint16_t opcode; 1474da6c28aaSamw uint16_t devstate; 1475da6c28aaSamw char *req_fmt; 1476da6c28aaSamw char *rep_fmt; 1477da6c28aaSamw 1478da6c28aaSamw if (xa->smb_suwcnt > 0 && STYPE_ISIPC(sr->tid_tree->t_res_type)) { 14793db3f65cSamw rc = smb_mbc_decodef(&xa->req_setup_mb, "ww", &opcode, 1480da6c28aaSamw &sr->smb_fid); 1481da6c28aaSamw if (rc != 0) 1482da6c28aaSamw goto trans_err_not_supported; 1483da6c28aaSamw switch (opcode) { 1484da6c28aaSamw case TRANS_SET_NMPIPE_STATE: 14853db3f65cSamw if ((rc = smb_mbc_decodef(&xa->req_param_mb, "w", 1486da6c28aaSamw &devstate)) != 0) 1487da6c28aaSamw goto trans_err_not_supported; 1488da6c28aaSamw 1489faa1795aSjb150015 rc = SDRC_SUCCESS; 1490da6c28aaSamw break; 1491da6c28aaSamw 1492da6c28aaSamw case TRANS_TRANSACT_NMPIPE: 149368b2bbf2SGordon Ross rc = smb_trans_nmpipe(sr, xa); 1494da6c28aaSamw break; 1495da6c28aaSamw 1496da6c28aaSamw case TRANS_WAIT_NMPIPE: 149768b2bbf2SGordon Ross delay(SEC_TO_TICK(1)); 1498faa1795aSjb150015 rc = SDRC_SUCCESS; 1499da6c28aaSamw break; 1500da6c28aaSamw 1501da6c28aaSamw default: 1502da6c28aaSamw goto trans_err_not_supported; 1503da6c28aaSamw } 1504da6c28aaSamw } else { 1505bbf6f00cSJordan Brown if (!is_supported_mailslot(xa->xa_pipe_name)) 1506da6c28aaSamw goto trans_err_not_supported; 1507da6c28aaSamw 15083db3f65cSamw if ((rc = smb_mbc_decodef(&xa->req_param_mb, "%wss", sr, 1509da6c28aaSamw &opcode, &req_fmt, &rep_fmt)) != 0) 1510da6c28aaSamw goto trans_err_not_supported; 1511da6c28aaSamw 1512da6c28aaSamw switch (opcode) { 1513da6c28aaSamw case API_WshareEnum: 1514da6c28aaSamw rc = smb_trans_net_share_enum(sr, xa); 1515da6c28aaSamw break; 1516da6c28aaSamw 1517da6c28aaSamw case API_WshareGetInfo: 15183ad684d6Sjb150015 rc = smb_trans_net_share_getinfo(sr, xa); 1519da6c28aaSamw break; 1520da6c28aaSamw 1521da6c28aaSamw case API_WserverGetInfo: 15223ad684d6Sjb150015 rc = smb_trans_net_server_getinfo(sr, xa); 1523da6c28aaSamw break; 1524da6c28aaSamw 1525da6c28aaSamw case API_WUserGetInfo: 15263ad684d6Sjb150015 rc = smb_trans_net_user_getinfo(sr, xa); 1527da6c28aaSamw break; 1528da6c28aaSamw 1529da6c28aaSamw case API_WWkstaGetInfo: 15303ad684d6Sjb150015 rc = smb_trans_net_workstation_getinfo(sr, xa); 1531da6c28aaSamw break; 1532da6c28aaSamw 1533da6c28aaSamw case API_NetServerEnum2: 1534da6c28aaSamw rc = smb_trans_net_server_enum2(sr, xa); 1535da6c28aaSamw break; 1536da6c28aaSamw 1537da6c28aaSamw default: 1538da6c28aaSamw goto trans_err_not_supported; 1539da6c28aaSamw } 1540da6c28aaSamw } 1541da6c28aaSamw 1542da6c28aaSamw switch (rc) { 1543faa1795aSjb150015 case SDRC_SUCCESS: 1544da6c28aaSamw break; 1545da6c28aaSamw 1546da6c28aaSamw case SDRC_DROP_VC: 1547da6c28aaSamw case SDRC_NO_REPLY: 1548faa1795aSjb150015 case SDRC_ERROR: 1549da6c28aaSamw return (rc); 1550da6c28aaSamw 1551faa1795aSjb150015 case SDRC_NOT_IMPLEMENTED: 1552da6c28aaSamw goto trans_err_not_supported; 1553da6c28aaSamw 1554da6c28aaSamw default: 1555da6c28aaSamw break; 1556da6c28aaSamw } 1557da6c28aaSamw 1558da6c28aaSamw n_setup = MBC_LENGTH(&xa->rep_setup_mb); 1559da6c28aaSamw n_param = MBC_LENGTH(&xa->rep_param_mb); 1560da6c28aaSamw n_data = MBC_LENGTH(&xa->rep_data_mb); 1561da6c28aaSamw 1562da6c28aaSamw if (xa->smb_msrcnt < n_setup || 1563da6c28aaSamw xa->smb_mprcnt < n_param || 1564da6c28aaSamw xa->smb_mdrcnt < n_data) { 1565da6c28aaSamw goto trans_err_too_small; 1566da6c28aaSamw } 1567da6c28aaSamw 1568da6c28aaSamw /* neato, blast it over there */ 1569da6c28aaSamw 1570da6c28aaSamw n_setup = (n_setup + 1) / 2; /* Convert to setup words */ 1571da6c28aaSamw param_pad = 1; /* always one */ 1572da6c28aaSamw param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 1573da6c28aaSamw data_pad = (param_off + n_param) & 1; /* Pad to short */ 1574da6c28aaSamw /* Param off from hdr start */ 1575da6c28aaSamw data_off = param_off + n_param + data_pad; 1576da6c28aaSamw total_bytes = param_pad + n_param + data_pad + n_data; 1577da6c28aaSamw 15787b59d02dSjb150015 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, 1579da6c28aaSamw "bww2.wwwwwwb.Cw#.C#.C", 1580da6c28aaSamw 10 + n_setup, /* wct */ 1581da6c28aaSamw n_param, /* Total Parameter Bytes */ 1582da6c28aaSamw n_data, /* Total Data Bytes */ 1583da6c28aaSamw n_param, /* Total Parameter Bytes this buffer */ 1584da6c28aaSamw param_off, /* Param offset from header start */ 1585da6c28aaSamw 0, /* Param displacement */ 1586da6c28aaSamw n_data, /* Total Data Bytes this buffer */ 1587da6c28aaSamw data_off, /* Data offset from header start */ 1588da6c28aaSamw 0, /* Data displacement */ 1589da6c28aaSamw n_setup, /* suwcnt */ 1590da6c28aaSamw &xa->rep_setup_mb, /* setup[] */ 1591da6c28aaSamw total_bytes, /* Total data bytes */ 1592da6c28aaSamw param_pad, 1593da6c28aaSamw &xa->rep_param_mb, 1594da6c28aaSamw data_pad, 1595da6c28aaSamw &xa->rep_data_mb); 1596faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1597da6c28aaSamw 1598da6c28aaSamw trans_err_too_small: 1599da6c28aaSamw rc = NERR_BufTooSmall; 1600da6c28aaSamw goto trans_err; 1601da6c28aaSamw 1602da6c28aaSamw trans_err_not_supported: 1603da6c28aaSamw rc = ERROR_NOT_SUPPORTED; 1604da6c28aaSamw goto trans_err; 1605da6c28aaSamw 1606da6c28aaSamw trans_err: 1607da6c28aaSamw pos = MBC_LENGTH(&sr->reply) + 23; 16087b59d02dSjb150015 rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www", 1609da6c28aaSamw 10, /* wct */ 1610da6c28aaSamw 4, 0, /* tpscnt tdscnt */ 1611da6c28aaSamw 4, pos, 0, /* pscnt psoff psdisp */ 1612da6c28aaSamw 0, 0, 0, /* dscnt dsoff dsdisp */ 1613da6c28aaSamw 0, /* suwcnt */ 1614da6c28aaSamw 4, /* bcc */ 1615da6c28aaSamw rc, 1616da6c28aaSamw 0); /* converter word? */ 1617faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1618da6c28aaSamw } 1619da6c28aaSamw 16207b59d02dSjb150015 static smb_sdrc_t 16219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_trans2_dispatch(smb_request_t *sr, smb_xa_t *xa) 1622da6c28aaSamw { 1623da6c28aaSamw int rc, pos; 1624da6c28aaSamw int total_bytes, n_setup, n_param, n_data; 1625b819cea2SGordon Ross int param_off, param_pad, data_off; 1626b819cea2SGordon Ross uint16_t data_pad; 1627da6c28aaSamw uint16_t opcode; 1628da6c28aaSamw uint16_t nt_unknown_secret = 0x0100; 1629da6c28aaSamw char *fmt; 1630da6c28aaSamw 16317f3ef643SGordon Ross n_data = xa->smb_mdrcnt; 1632da6c28aaSamw 16333db3f65cSamw if (smb_mbc_decodef(&xa->req_setup_mb, "w", &opcode) != 0) 1634da6c28aaSamw goto trans_err_not_supported; 1635da6c28aaSamw 1636da6c28aaSamw /* 1637da6c28aaSamw * Save this for /proc to read later. 1638da6c28aaSamw */ 1639da6c28aaSamw xa->smb_func = opcode; 1640da6c28aaSamw 1641da6c28aaSamw /* for now, only respond to the */ 1642da6c28aaSamw switch (opcode) { 16432c2961f8Sjose borrego case TRANS2_OPEN2: 16442c2961f8Sjose borrego rc = smb_com_trans2_open2(sr, xa); 16452c2961f8Sjose borrego break; 16462c2961f8Sjose borrego 1647da6c28aaSamw case TRANS2_CREATE_DIRECTORY: 1648da6c28aaSamw rc = smb_com_trans2_create_directory(sr, xa); 1649da6c28aaSamw break; 1650da6c28aaSamw 1651da6c28aaSamw case TRANS2_FIND_FIRST2: 1652da6c28aaSamw /* 1653da6c28aaSamw * Should have enough room to send the response 1654da6c28aaSamw * data back to client. 1655da6c28aaSamw */ 1656da6c28aaSamw if (n_data == 0) { 1657dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1658da6c28aaSamw ERRDOS, ERROR_BAD_LENGTH); 1659faa1795aSjb150015 return (SDRC_ERROR); 1660da6c28aaSamw } 1661da6c28aaSamw rc = smb_com_trans2_find_first2(sr, xa); 1662da6c28aaSamw break; 1663da6c28aaSamw 1664da6c28aaSamw case TRANS2_FIND_NEXT2: 1665da6c28aaSamw /* 1666da6c28aaSamw * Should have enough room to send the response 1667da6c28aaSamw * data back to client. 1668da6c28aaSamw */ 1669da6c28aaSamw if (n_data == 0) { 1670dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1671da6c28aaSamw ERRDOS, ERROR_BAD_LENGTH); 1672faa1795aSjb150015 return (SDRC_ERROR); 1673da6c28aaSamw } 1674da6c28aaSamw rc = smb_com_trans2_find_next2(sr, xa); 1675da6c28aaSamw break; 1676da6c28aaSamw 1677da6c28aaSamw case TRANS2_QUERY_FS_INFORMATION: 1678da6c28aaSamw /* 1679da6c28aaSamw * Should have enough room to send the response 1680da6c28aaSamw * data back to client. 1681da6c28aaSamw */ 1682da6c28aaSamw if (n_data == 0) { 1683dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1684da6c28aaSamw ERRDOS, ERROR_BAD_LENGTH); 1685faa1795aSjb150015 return (SDRC_ERROR); 1686da6c28aaSamw } 1687da6c28aaSamw rc = smb_com_trans2_query_fs_information(sr, xa); 1688da6c28aaSamw break; 1689da6c28aaSamw 16909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case TRANS2_SET_FS_INFORMATION: 16919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_com_trans2_set_fs_information(sr, xa); 16929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break; 16939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 1694da6c28aaSamw case TRANS2_QUERY_PATH_INFORMATION: 1695da6c28aaSamw /* 1696da6c28aaSamw * Should have enough room to send the response 1697da6c28aaSamw * data back to client. 1698da6c28aaSamw */ 1699da6c28aaSamw if (n_data == 0) { 1700dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1701da6c28aaSamw ERRDOS, ERROR_BAD_LENGTH); 1702faa1795aSjb150015 return (SDRC_ERROR); 1703da6c28aaSamw } 1704da6c28aaSamw rc = smb_com_trans2_query_path_information(sr, xa); 1705da6c28aaSamw break; 1706da6c28aaSamw 1707da6c28aaSamw case TRANS2_QUERY_FILE_INFORMATION: 1708da6c28aaSamw /* 1709da6c28aaSamw * Should have enough room to send the response 1710da6c28aaSamw * data back to client. 1711da6c28aaSamw */ 1712da6c28aaSamw if (n_data == 0) { 1713dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1714da6c28aaSamw ERRDOS, ERROR_BAD_LENGTH); 1715faa1795aSjb150015 return (SDRC_ERROR); 1716da6c28aaSamw } 1717da6c28aaSamw rc = smb_com_trans2_query_file_information(sr, xa); 1718da6c28aaSamw break; 1719da6c28aaSamw 1720da6c28aaSamw case TRANS2_SET_PATH_INFORMATION: 1721da6c28aaSamw rc = smb_com_trans2_set_path_information(sr, xa); 1722da6c28aaSamw break; 1723da6c28aaSamw 1724da6c28aaSamw case TRANS2_SET_FILE_INFORMATION: 1725da6c28aaSamw rc = smb_com_trans2_set_file_information(sr, xa); 1726da6c28aaSamw break; 17279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 17289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case TRANS2_GET_DFS_REFERRAL: 17299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_com_trans2_get_dfs_referral(sr, xa); 17309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break; 17319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 1732da6c28aaSamw default: 17332c2961f8Sjose borrego (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 1734da6c28aaSamw goto trans_err_not_supported; 1735da6c28aaSamw } 1736da6c28aaSamw 1737da6c28aaSamw switch (rc) { 1738faa1795aSjb150015 case SDRC_SUCCESS: 1739da6c28aaSamw break; 1740da6c28aaSamw 1741da6c28aaSamw case SDRC_DROP_VC: 1742da6c28aaSamw case SDRC_NO_REPLY: 1743faa1795aSjb150015 case SDRC_ERROR: 1744da6c28aaSamw return (rc); 1745da6c28aaSamw 1746faa1795aSjb150015 case SDRC_NOT_IMPLEMENTED: 1747da6c28aaSamw goto trans_err_not_supported; 1748da6c28aaSamw 1749da6c28aaSamw default: 1750da6c28aaSamw break; 1751da6c28aaSamw } 1752da6c28aaSamw 1753da6c28aaSamw n_setup = MBC_LENGTH(&xa->rep_setup_mb); 1754da6c28aaSamw n_param = MBC_LENGTH(&xa->rep_param_mb); 1755da6c28aaSamw n_data = MBC_LENGTH(&xa->rep_data_mb); 1756da6c28aaSamw 1757da6c28aaSamw if (xa->smb_msrcnt < n_setup || 1758da6c28aaSamw xa->smb_mprcnt < n_param || 1759da6c28aaSamw xa->smb_mdrcnt < n_data) { 1760da6c28aaSamw goto trans_err_too_small; 1761da6c28aaSamw } 1762da6c28aaSamw 1763da6c28aaSamw /* neato, blast it over there */ 1764da6c28aaSamw 1765da6c28aaSamw n_setup = (n_setup + 1) / 2; /* Conver to setup words */ 1766da6c28aaSamw param_pad = 1; /* must be one */ 1767da6c28aaSamw param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 1768da6c28aaSamw 1769da6c28aaSamw /* 1770da6c28aaSamw * Including the nt_unknown_secret value persuades netmon to 1771da6c28aaSamw * display the correct data format for QueryPathInfo and 1772da6c28aaSamw * QueryFileInfo. 1773da6c28aaSamw */ 1774da6c28aaSamw if (opcode == TRANS2_QUERY_FILE_INFORMATION || 1775da6c28aaSamw opcode == TRANS2_QUERY_PATH_INFORMATION) { 1776da6c28aaSamw data_pad = sizeof (uint16_t); 1777da6c28aaSamw data_off = param_off + n_param + data_pad; 1778da6c28aaSamw fmt = "bww2.wwwwwwb.Cw#.CwC"; 1779da6c28aaSamw nt_unknown_secret = 0x0100; 1780da6c28aaSamw } 1781da6c28aaSamw else 1782da6c28aaSamw { 1783da6c28aaSamw data_pad = (param_off + n_param) & 1; /* Pad to short */ 1784da6c28aaSamw /* Param off from hdr start */ 1785da6c28aaSamw data_off = param_off + n_param + data_pad; 1786da6c28aaSamw fmt = "bww2.wwwwwwb.Cw#.C#.C"; 1787da6c28aaSamw nt_unknown_secret = data_pad; 1788da6c28aaSamw } 1789da6c28aaSamw 1790da6c28aaSamw total_bytes = param_pad + n_param + data_pad + n_data; 1791da6c28aaSamw 17927b59d02dSjb150015 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, 1793da6c28aaSamw fmt, 1794da6c28aaSamw 10 + n_setup, /* wct */ 1795da6c28aaSamw n_param, /* Total Parameter Bytes */ 1796da6c28aaSamw n_data /* + data_pad */, /* Total Data Bytes */ 1797da6c28aaSamw n_param, /* Total Parameter Bytes this buffer */ 1798da6c28aaSamw param_off, /* Param offset from header start */ 1799da6c28aaSamw 0, /* Param displacement */ 1800da6c28aaSamw n_data /* + data_pad */, /* Total Data Bytes this buffer */ 1801da6c28aaSamw data_off, /* Data offset from header start */ 1802da6c28aaSamw 0, /* Data displacement */ 1803da6c28aaSamw n_setup, /* suwcnt */ 1804da6c28aaSamw &xa->rep_setup_mb, /* setup[] */ 1805da6c28aaSamw total_bytes, /* Total data bytes */ 1806da6c28aaSamw param_pad, 1807da6c28aaSamw &xa->rep_param_mb, 1808da6c28aaSamw nt_unknown_secret, 1809da6c28aaSamw &xa->rep_data_mb); 1810faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1811da6c28aaSamw 1812da6c28aaSamw trans_err_too_small: 1813da6c28aaSamw rc = NERR_BufTooSmall; 1814da6c28aaSamw goto trans_err; 1815da6c28aaSamw 1816da6c28aaSamw trans_err_not_supported: 1817da6c28aaSamw rc = ERROR_NOT_SUPPORTED; 1818da6c28aaSamw goto trans_err; 1819da6c28aaSamw 1820da6c28aaSamw trans_err: 1821da6c28aaSamw pos = MBC_LENGTH(&sr->reply) + 23; 18227b59d02dSjb150015 rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www", 1823da6c28aaSamw 10, /* wct */ 1824da6c28aaSamw 4, 0, /* tpscnt tdscnt */ 1825da6c28aaSamw 4, pos, 0, /* pscnt psoff psdisp */ 1826da6c28aaSamw 0, 0, 0, /* dscnt dsoff dsdisp */ 1827da6c28aaSamw 0, /* suwcnt */ 1828da6c28aaSamw 4, /* bcc */ 1829da6c28aaSamw rc, 1830da6c28aaSamw 0); /* converter word? */ 1831faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1832da6c28aaSamw } 1833da6c28aaSamw 18347f3ef643SGordon Ross static uint32_t smb_xa_max_setup_count = 200; 18357f3ef643SGordon Ross static uint32_t smb_xa_max_param_count = 32 * 1024; 18367f3ef643SGordon Ross static uint32_t smb_xa_max_data_count = 64 * 1024; 18377f3ef643SGordon Ross 1838da6c28aaSamw smb_xa_t * 1839da6c28aaSamw smb_xa_create( 1840da6c28aaSamw smb_session_t *session, 1841da6c28aaSamw smb_request_t *sr, 1842da6c28aaSamw uint32_t total_parameter_count, 1843da6c28aaSamw uint32_t total_data_count, 1844da6c28aaSamw uint32_t max_parameter_count, 1845da6c28aaSamw uint32_t max_data_count, 1846da6c28aaSamw uint32_t max_setup_count, 1847da6c28aaSamw uint32_t setup_word_count) 1848da6c28aaSamw { 1849da6c28aaSamw smb_xa_t *xa, *nxa; 1850da6c28aaSamw smb_llist_t *xlist; 1851da6c28aaSamw 18527f3ef643SGordon Ross /* 18537f3ef643SGordon Ross * Sanity check what the client says it will send. 18547f3ef643SGordon Ross * Caller handles NULL return as ERRnoroom. 18557f3ef643SGordon Ross */ 18567f3ef643SGordon Ross if (setup_word_count > smb_xa_max_setup_count) 18577f3ef643SGordon Ross return (NULL); 18587f3ef643SGordon Ross if (total_parameter_count > smb_xa_max_param_count) 18597f3ef643SGordon Ross return (NULL); 18607f3ef643SGordon Ross if (total_data_count > smb_xa_max_data_count) 18617f3ef643SGordon Ross return (NULL); 18627f3ef643SGordon Ross 18637f3ef643SGordon Ross /* 18647f3ef643SGordon Ross * Limit what the client asks us to allocate for 18657f3ef643SGordon Ross * returned setup, params, data. 18667f3ef643SGordon Ross */ 18677f3ef643SGordon Ross if (max_setup_count > smb_xa_max_setup_count) 18687f3ef643SGordon Ross max_setup_count = smb_xa_max_setup_count; 18697f3ef643SGordon Ross if (max_parameter_count > smb_xa_max_param_count) 18707f3ef643SGordon Ross max_parameter_count = smb_xa_max_param_count; 18717f3ef643SGordon Ross if (max_data_count > smb_xa_max_data_count) 18727f3ef643SGordon Ross max_data_count = smb_xa_max_data_count; 18737f3ef643SGordon Ross 1874bbf6f00cSJordan Brown xa = kmem_zalloc(sizeof (smb_xa_t), KM_SLEEP); 1875da6c28aaSamw xa->xa_refcnt = 1; 1876da6c28aaSamw xa->smb_com = sr->smb_com; 1877da6c28aaSamw xa->smb_flg = sr->smb_flg; 1878da6c28aaSamw xa->smb_flg2 = sr->smb_flg2; 1879da6c28aaSamw xa->smb_tid = sr->smb_tid; 1880da6c28aaSamw xa->smb_pid = sr->smb_pid; 1881da6c28aaSamw xa->smb_uid = sr->smb_uid; 1882da6c28aaSamw xa->xa_smb_mid = sr->smb_mid; 18837f3ef643SGordon Ross xa->xa_smb_fid = 0xFFFF; 1884da6c28aaSamw xa->reply_seqnum = sr->reply_seqnum; 1885da6c28aaSamw xa->smb_tpscnt = total_parameter_count; 1886da6c28aaSamw xa->smb_tdscnt = total_data_count; 1887da6c28aaSamw xa->smb_mprcnt = max_parameter_count; 1888da6c28aaSamw xa->smb_mdrcnt = max_data_count; 1889da6c28aaSamw xa->smb_msrcnt = max_setup_count; 1890da6c28aaSamw xa->smb_suwcnt = setup_word_count; 1891da6c28aaSamw xa->xa_session = session; 1892da6c28aaSamw xa->xa_magic = SMB_XA_MAGIC; 1893da6c28aaSamw 18947f3ef643SGordon Ross /* request parts */ 18957f3ef643SGordon Ross xa->req_setup_mb.max_bytes = setup_word_count * 2; 18967f3ef643SGordon Ross xa->req_param_mb.max_bytes = total_parameter_count; 18977f3ef643SGordon Ross xa->req_data_mb.max_bytes = total_data_count; 18987f3ef643SGordon Ross 18997f3ef643SGordon Ross /* reply parts */ 19007f3ef643SGordon Ross xa->rep_setup_mb.max_bytes = max_setup_count * 2; 19017f3ef643SGordon Ross xa->rep_param_mb.max_bytes = max_parameter_count; 19027f3ef643SGordon Ross xa->rep_data_mb.max_bytes = max_data_count; 19037f3ef643SGordon Ross 1904da6c28aaSamw /* 1905da6c28aaSamw * The new xa structure is checked against the current list to see 1906da6c28aaSamw * if it exists already. 1907da6c28aaSamw */ 1908da6c28aaSamw xlist = &session->s_xa_list; 1909da6c28aaSamw smb_llist_enter(xlist, RW_WRITER); 1910da6c28aaSamw nxa = smb_llist_head(xlist); 1911da6c28aaSamw while (nxa) { 1912da6c28aaSamw ASSERT(nxa->xa_magic == SMB_XA_MAGIC); 1913da6c28aaSamw if (nxa->xa_smb_mid == xa->xa_smb_mid && 1914da6c28aaSamw nxa->smb_pid == xa->smb_pid && 1915da6c28aaSamw !SMB_XA_CLOSED(nxa) && 1916da6c28aaSamw !(nxa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 1917da6c28aaSamw smb_llist_exit(xlist); 1918bbf6f00cSJordan Brown kmem_free(xa, sizeof (smb_xa_t)); 1919da6c28aaSamw return (NULL); 1920da6c28aaSamw } 1921da6c28aaSamw nxa = smb_llist_next(xlist, nxa); 1922da6c28aaSamw } 1923da6c28aaSamw smb_llist_insert_tail(xlist, xa); 1924da6c28aaSamw smb_llist_exit(xlist); 1925da6c28aaSamw return (xa); 1926da6c28aaSamw } 1927da6c28aaSamw 1928da6c28aaSamw void 1929da6c28aaSamw smb_xa_delete(smb_xa_t *xa) 1930da6c28aaSamw { 1931da6c28aaSamw ASSERT(xa->xa_refcnt == 0); 1932da6c28aaSamw ASSERT(SMB_XA_CLOSED(xa)); 1933da6c28aaSamw 1934bbf6f00cSJordan Brown if (xa->xa_pipe_name) 19359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_mem_free(xa->xa_pipe_name); 1936da6c28aaSamw 19377f3ef643SGordon Ross /* request parts */ 19387f3ef643SGordon Ross if (xa->req_setup_mb.chain != NULL) 19397f3ef643SGordon Ross m_freem(xa->req_setup_mb.chain); 19407f3ef643SGordon Ross if (xa->req_param_mb.chain != NULL) 19417f3ef643SGordon Ross m_freem(xa->req_param_mb.chain); 19427f3ef643SGordon Ross if (xa->req_data_mb.chain != NULL) 19437f3ef643SGordon Ross m_freem(xa->req_data_mb.chain); 19447f3ef643SGordon Ross 19457f3ef643SGordon Ross /* reply parts */ 1946da6c28aaSamw if (xa->rep_setup_mb.chain != NULL) 1947da6c28aaSamw m_freem(xa->rep_setup_mb.chain); 1948da6c28aaSamw if (xa->rep_param_mb.chain != NULL) 1949da6c28aaSamw m_freem(xa->rep_param_mb.chain); 1950da6c28aaSamw if (xa->rep_data_mb.chain != NULL) 1951da6c28aaSamw m_freem(xa->rep_data_mb.chain); 1952da6c28aaSamw 1953da6c28aaSamw xa->xa_magic = (uint32_t)~SMB_XA_MAGIC; 1954bbf6f00cSJordan Brown kmem_free(xa, sizeof (smb_xa_t)); 1955da6c28aaSamw } 1956da6c28aaSamw 1957da6c28aaSamw smb_xa_t * 1958da6c28aaSamw smb_xa_hold(smb_xa_t *xa) 1959da6c28aaSamw { 1960da6c28aaSamw mutex_enter(&xa->xa_mutex); 1961da6c28aaSamw xa->xa_refcnt++; 1962da6c28aaSamw ASSERT(xa->xa_refcnt); 1963da6c28aaSamw mutex_exit(&xa->xa_mutex); 1964da6c28aaSamw return (xa); 1965da6c28aaSamw } 1966da6c28aaSamw 1967da6c28aaSamw void 1968da6c28aaSamw smb_xa_rele(smb_session_t *session, smb_xa_t *xa) 1969da6c28aaSamw { 1970da6c28aaSamw mutex_enter(&xa->xa_mutex); 1971da6c28aaSamw ASSERT(xa->xa_refcnt); 1972da6c28aaSamw xa->xa_refcnt--; 1973da6c28aaSamw if (SMB_XA_CLOSED(xa) && (xa->xa_refcnt == 0)) { 1974da6c28aaSamw mutex_exit(&xa->xa_mutex); 1975da6c28aaSamw smb_llist_enter(&session->s_xa_list, RW_WRITER); 1976da6c28aaSamw smb_llist_remove(&session->s_xa_list, xa); 1977da6c28aaSamw smb_llist_exit(&session->s_xa_list); 1978da6c28aaSamw smb_xa_delete(xa); 1979da6c28aaSamw return; 1980da6c28aaSamw } 1981da6c28aaSamw mutex_exit(&xa->xa_mutex); 1982da6c28aaSamw } 1983da6c28aaSamw 1984da6c28aaSamw int 1985da6c28aaSamw smb_xa_open(smb_xa_t *xa) 1986da6c28aaSamw { 1987da6c28aaSamw int rc; 1988da6c28aaSamw 1989da6c28aaSamw mutex_enter(&xa->xa_mutex); 1990da6c28aaSamw 1991da6c28aaSamw ASSERT((xa->xa_flags & SMB_XA_FLAG_OPEN) == 0); 1992da6c28aaSamw 1993da6c28aaSamw if ((xa->xa_flags & SMB_XA_FLAG_CLOSE) == 0) { 1994da6c28aaSamw xa->xa_flags |= SMB_XA_FLAG_OPEN; 1995da6c28aaSamw rc = 0; 1996da6c28aaSamw } else { 1997da6c28aaSamw rc = ERROR_INVALID_HANDLE; 1998da6c28aaSamw } 1999da6c28aaSamw 2000da6c28aaSamw mutex_exit(&xa->xa_mutex); 2001da6c28aaSamw 2002da6c28aaSamw return (rc); 2003da6c28aaSamw } 2004da6c28aaSamw 2005da6c28aaSamw void 2006da6c28aaSamw smb_xa_close(smb_xa_t *xa) 2007da6c28aaSamw { 2008da6c28aaSamw mutex_enter(&xa->xa_mutex); 2009da6c28aaSamw xa->xa_flags |= SMB_XA_FLAG_CLOSE; 2010da6c28aaSamw xa->xa_flags &= ~SMB_XA_FLAG_OPEN; 2011da6c28aaSamw 2012da6c28aaSamw if (xa->xa_refcnt == 0) { 2013da6c28aaSamw mutex_exit(&xa->xa_mutex); 2014da6c28aaSamw smb_llist_enter(&xa->xa_session->s_xa_list, RW_WRITER); 2015da6c28aaSamw smb_llist_remove(&xa->xa_session->s_xa_list, xa); 2016da6c28aaSamw smb_llist_exit(&xa->xa_session->s_xa_list); 2017da6c28aaSamw smb_xa_delete(xa); 2018da6c28aaSamw return; 2019da6c28aaSamw } 2020da6c28aaSamw 2021da6c28aaSamw mutex_exit(&xa->xa_mutex); 2022da6c28aaSamw } 2023da6c28aaSamw 2024da6c28aaSamw int 2025da6c28aaSamw smb_xa_complete(smb_xa_t *xa) 2026da6c28aaSamw { 2027da6c28aaSamw int rc; 2028da6c28aaSamw 2029da6c28aaSamw mutex_enter(&xa->xa_mutex); 2030da6c28aaSamw if (xa->xa_flags & (SMB_XA_FLAG_COMPLETE | SMB_XA_FLAG_CLOSE)) { 20317f3ef643SGordon Ross rc = 0; /* error ("not complete") */ 2032da6c28aaSamw } else { 20337f3ef643SGordon Ross rc = 1; /* Yes, "complete" */ 2034da6c28aaSamw xa->xa_flags |= SMB_XA_FLAG_COMPLETE; 20357f3ef643SGordon Ross 20367f3ef643SGordon Ross /* 20377f3ef643SGordon Ross * During trans & trans-secondary processing, 20387f3ef643SGordon Ross * we copied the request data into these. 20397f3ef643SGordon Ross * Now we want to parse them, so we need to 20407f3ef643SGordon Ross * move the "finger" back to the beginning. 20417f3ef643SGordon Ross */ 20427f3ef643SGordon Ross xa->req_setup_mb.chain_offset = 0; 20437f3ef643SGordon Ross xa->req_param_mb.chain_offset = 0; 20447f3ef643SGordon Ross xa->req_data_mb.chain_offset = 0; 2045da6c28aaSamw } 20467f3ef643SGordon Ross 2047da6c28aaSamw mutex_exit(&xa->xa_mutex); 2048da6c28aaSamw return (rc); 2049da6c28aaSamw } 2050da6c28aaSamw 2051da6c28aaSamw smb_xa_t * 2052da6c28aaSamw smb_xa_find( 2053da6c28aaSamw smb_session_t *session, 2054da6c28aaSamw uint16_t pid, 2055da6c28aaSamw uint16_t mid) 2056da6c28aaSamw { 2057da6c28aaSamw smb_xa_t *xa; 2058da6c28aaSamw smb_llist_t *xlist; 2059da6c28aaSamw 2060da6c28aaSamw xlist = &session->s_xa_list; 2061da6c28aaSamw smb_llist_enter(xlist, RW_READER); 2062da6c28aaSamw xa = smb_llist_head(xlist); 2063da6c28aaSamw while (xa) { 2064da6c28aaSamw mutex_enter(&xa->xa_mutex); 2065da6c28aaSamw if (xa->xa_smb_mid == mid && 2066da6c28aaSamw xa->smb_pid == pid && 2067da6c28aaSamw !SMB_XA_CLOSED(xa) && 2068da6c28aaSamw !(xa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 2069da6c28aaSamw xa->xa_refcnt++; 2070da6c28aaSamw ASSERT(xa->xa_refcnt); 2071da6c28aaSamw mutex_exit(&xa->xa_mutex); 2072da6c28aaSamw break; 2073da6c28aaSamw } 2074da6c28aaSamw mutex_exit(&xa->xa_mutex); 2075da6c28aaSamw xa = smb_llist_next(xlist, xa); 2076da6c28aaSamw } 2077da6c28aaSamw smb_llist_exit(xlist); 2078da6c28aaSamw return (xa); 2079da6c28aaSamw } 2080