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 */ 21da6c28aaSamw /* 222c2961f8Sjose borrego * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24da6c28aaSamw */ 25da6c28aaSamw 26*bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h> 27da6c28aaSamw #include <smbsrv/smb_fsops.h> 283db3f65cSamw #include <smbsrv/smb_share.h> 29*bbf6f00cSJordan Brown #include <smbsrv/string.h> 30da6c28aaSamw #include <smbsrv/nmpipes.h> 31da6c28aaSamw #include <smbsrv/mailslot.h> 32da6c28aaSamw #include <smbsrv/lmerr.h> 33da6c28aaSamw 34b1352070SAlan Wright #define SMB_QUOTA_UNLIMITED 0xFFFFFFFFFFFFFFFF; 35b1352070SAlan Wright 36da6c28aaSamw /* 37da6c28aaSamw * count of bytes in server response packet 38da6c28aaSamw * except parameters and data. Note that setup 39da6c28aaSamw * word count is zero. 40da6c28aaSamw */ 41da6c28aaSamw #define RESP_HEADER_LEN 24 42da6c28aaSamw 43da6c28aaSamw /* 44b1352070SAlan Wright * We started by using common functions for transaction/transaction2 45da6c28aaSamw * and transaction_secondary/transaction2_secondary because they 46da6c28aaSamw * are respectively so similar. However, it turned out to be a bad 47da6c28aaSamw * idea because of quirky differences. Be sure if you modify one 48da6c28aaSamw * of these four functions to check and see if the modification should 49da6c28aaSamw * be applied to its peer. 50da6c28aaSamw */ 51da6c28aaSamw 527b59d02dSjb150015 static int smb_trans_ready(struct smb_xa *); 537b59d02dSjb150015 static smb_sdrc_t smb_trans_dispatch(struct smb_request *, struct smb_xa *); 547b59d02dSjb150015 static smb_sdrc_t smb_trans2_dispatch(struct smb_request *, struct smb_xa *); 557b59d02dSjb150015 static smb_sdrc_t smb_nt_transact_query_quota(struct smb_request *, 567b59d02dSjb150015 struct smb_xa *); 57da6c28aaSamw 587b59d02dSjb150015 smb_sdrc_t 59faa1795aSjb150015 smb_pre_transaction(smb_request_t *sr) 60faa1795aSjb150015 { 61faa1795aSjb150015 DTRACE_SMB_1(op__Transaction__start, smb_request_t *, sr); 62faa1795aSjb150015 return (SDRC_SUCCESS); 63faa1795aSjb150015 } 64faa1795aSjb150015 65faa1795aSjb150015 void 66faa1795aSjb150015 smb_post_transaction(smb_request_t *sr) 67faa1795aSjb150015 { 68faa1795aSjb150015 DTRACE_SMB_1(op__Transaction__done, smb_request_t *, sr); 69faa1795aSjb150015 } 70faa1795aSjb150015 71faa1795aSjb150015 smb_sdrc_t 72faa1795aSjb150015 smb_com_transaction(smb_request_t *sr) 73da6c28aaSamw { 74da6c28aaSamw int rc; 75da6c28aaSamw unsigned char msrcnt, suwcnt; 76da6c28aaSamw uint16_t tpscnt, tdscnt, mprcnt, mdrcnt, flags; 77da6c28aaSamw uint16_t pscnt, psoff, dscnt, dsoff; 78da6c28aaSamw uint32_t timeo; 79da6c28aaSamw struct smb_xa *xa; 80da6c28aaSamw char *stn; 81da6c28aaSamw int ready; 82da6c28aaSamw 83da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, 84da6c28aaSamw &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &msrcnt, &flags, 85da6c28aaSamw &timeo, &pscnt, &psoff, &dscnt, &dsoff, &suwcnt); 86da6c28aaSamw 877b59d02dSjb150015 if (rc != 0) 88faa1795aSjb150015 return (SDRC_ERROR); 89da6c28aaSamw 90da6c28aaSamw xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, 91da6c28aaSamw msrcnt, suwcnt); 92da6c28aaSamw if (xa == NULL) { 93dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRnoroom); 94faa1795aSjb150015 return (SDRC_ERROR); 95da6c28aaSamw } 96da6c28aaSamw 97da6c28aaSamw /* Should be some alignment stuff here in SMB? */ 98da6c28aaSamw if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) { 99da6c28aaSamw rc = smbsr_decode_data(sr, "%.U", sr, &stn); 100da6c28aaSamw } else { 101da6c28aaSamw rc = smbsr_decode_data(sr, "%s", sr, &stn); 102da6c28aaSamw } 103da6c28aaSamw if (rc != 0) { 104da6c28aaSamw smb_xa_rele(sr->session, xa); 105faa1795aSjb150015 return (SDRC_ERROR); 106da6c28aaSamw } 107da6c28aaSamw 108*bbf6f00cSJordan Brown xa->xa_pipe_name = smb_strdup(stn); 109da6c28aaSamw xa->smb_flags = flags; 110da6c28aaSamw xa->smb_timeout = timeo; 111da6c28aaSamw xa->req_disp_param = pscnt; 112da6c28aaSamw xa->req_disp_data = dscnt; 113da6c28aaSamw 114da6c28aaSamw if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv, 115da6c28aaSamw sr->smb_vwv.chain_offset, suwcnt * 2)) { 116da6c28aaSamw smb_xa_rele(sr->session, xa); 117dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 118faa1795aSjb150015 return (SDRC_ERROR); 119da6c28aaSamw } 120da6c28aaSamw if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 121da6c28aaSamw smb_xa_rele(sr->session, xa); 122dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 123faa1795aSjb150015 return (SDRC_ERROR); 124da6c28aaSamw } 125da6c28aaSamw if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 126da6c28aaSamw smb_xa_rele(sr->session, xa); 127dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 128faa1795aSjb150015 return (SDRC_ERROR); 129da6c28aaSamw } 130da6c28aaSamw 131da6c28aaSamw ready = smb_trans_ready(xa); 132da6c28aaSamw 133da6c28aaSamw if (smb_xa_open(xa)) { 134da6c28aaSamw smb_xa_rele(sr->session, xa); 135dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRsrverror); 136faa1795aSjb150015 return (SDRC_ERROR); 137da6c28aaSamw } 138da6c28aaSamw sr->r_xa = xa; 139da6c28aaSamw 140da6c28aaSamw if (!ready) { 1417b59d02dSjb150015 rc = smbsr_encode_empty_result(sr); 142faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 143da6c28aaSamw } 144da6c28aaSamw 145da6c28aaSamw if (!smb_xa_complete(xa)) { 146da6c28aaSamw smb_xa_close(xa); 147dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 148faa1795aSjb150015 return (SDRC_ERROR); 149da6c28aaSamw } 150da6c28aaSamw 151da6c28aaSamw return (smb_trans_dispatch(sr, xa)); 152da6c28aaSamw } 153da6c28aaSamw 1547b59d02dSjb150015 smb_sdrc_t 155faa1795aSjb150015 smb_pre_transaction_secondary(smb_request_t *sr) 156faa1795aSjb150015 { 157faa1795aSjb150015 DTRACE_SMB_1(op__TransactionSecondary__start, smb_request_t *, sr); 158faa1795aSjb150015 return (SDRC_SUCCESS); 159faa1795aSjb150015 } 160faa1795aSjb150015 161faa1795aSjb150015 void 162faa1795aSjb150015 smb_post_transaction_secondary(smb_request_t *sr) 163faa1795aSjb150015 { 164faa1795aSjb150015 DTRACE_SMB_1(op__TransactionSecondary__done, smb_request_t *, sr); 165faa1795aSjb150015 } 166faa1795aSjb150015 167faa1795aSjb150015 smb_sdrc_t 168faa1795aSjb150015 smb_com_transaction_secondary(smb_request_t *sr) 169da6c28aaSamw { 170da6c28aaSamw uint16_t tpscnt, tdscnt, pscnt, psdisp; 171da6c28aaSamw uint16_t dscnt, dsoff, dsdisp, psoff; 172da6c28aaSamw smb_xa_t *xa; 173da6c28aaSamw int rc; 174da6c28aaSamw 175da6c28aaSamw if ((xa = smbsr_lookup_xa(sr)) == 0) { 176dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 177faa1795aSjb150015 return (SDRC_ERROR); 178da6c28aaSamw } 179da6c28aaSamw 180da6c28aaSamw if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 181da6c28aaSamw if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { 182dc20a302Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 183da6c28aaSamw ERRDOS, ERRnoaccess); 184faa1795aSjb150015 return (SDRC_ERROR); 185da6c28aaSamw } 186da6c28aaSamw } 187da6c28aaSamw 188da6c28aaSamw if (xa->smb_com != SMB_COM_TRANSACTION) { 189da6c28aaSamw return (SDRC_DROP_VC); 190da6c28aaSamw } 191da6c28aaSamw 192da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_TRANSSHDR_ED_FMT, &tpscnt, &tdscnt, 193da6c28aaSamw &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp); 194da6c28aaSamw 1957b59d02dSjb150015 if (rc != 0) 196faa1795aSjb150015 return (SDRC_ERROR); 197da6c28aaSamw 198da6c28aaSamw mutex_enter(&xa->xa_mutex); 199da6c28aaSamw xa->smb_tpscnt = tpscnt; /* might have shrunk */ 200da6c28aaSamw xa->smb_tdscnt = tdscnt; /* might have shrunk */ 201da6c28aaSamw xa->req_disp_param = psdisp+pscnt; 202da6c28aaSamw xa->req_disp_data = dsdisp+dscnt; 203da6c28aaSamw 204da6c28aaSamw if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 205da6c28aaSamw mutex_exit(&xa->xa_mutex); 206da6c28aaSamw smb_xa_close(xa); 207dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 208faa1795aSjb150015 return (SDRC_ERROR); 209da6c28aaSamw } 210da6c28aaSamw if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 211da6c28aaSamw mutex_exit(&xa->xa_mutex); 212da6c28aaSamw smb_xa_close(xa); 213dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 214faa1795aSjb150015 return (SDRC_ERROR); 215da6c28aaSamw } 216da6c28aaSamw mutex_exit(&xa->xa_mutex); 217da6c28aaSamw 218da6c28aaSamw if (!smb_trans_ready(xa)) 219da6c28aaSamw return (SDRC_NO_REPLY); 220da6c28aaSamw 221da6c28aaSamw if (!smb_xa_complete(xa)) 222da6c28aaSamw return (SDRC_NO_REPLY); 223da6c28aaSamw 224da6c28aaSamw return (smb_trans_dispatch(sr, xa)); 225da6c28aaSamw } 226da6c28aaSamw 2277b59d02dSjb150015 smb_sdrc_t 228faa1795aSjb150015 smb_pre_ioctl(smb_request_t *sr) 229faa1795aSjb150015 { 230faa1795aSjb150015 DTRACE_SMB_1(op__Ioctl__start, smb_request_t *, sr); 231faa1795aSjb150015 return (SDRC_SUCCESS); 232faa1795aSjb150015 } 233faa1795aSjb150015 234faa1795aSjb150015 void 235faa1795aSjb150015 smb_post_ioctl(smb_request_t *sr) 236faa1795aSjb150015 { 237faa1795aSjb150015 DTRACE_SMB_1(op__Ioctl__done, smb_request_t *, sr); 238faa1795aSjb150015 } 239faa1795aSjb150015 240faa1795aSjb150015 smb_sdrc_t 241faa1795aSjb150015 smb_com_ioctl(smb_request_t *sr) 242da6c28aaSamw { 243da6c28aaSamw uint16_t fid, category, function, tpscnt, tdscnt, mprcnt; 244da6c28aaSamw uint16_t mdrcnt, pscnt, pdoff, dscnt, dsoff; 245da6c28aaSamw uint32_t timeout; 246da6c28aaSamw int rc; 247da6c28aaSamw 248da6c28aaSamw rc = smbsr_decode_vwv(sr, "wwwwwwwl2.wwww", &fid, &category, &function, 249da6c28aaSamw &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &timeout, &pscnt, 250da6c28aaSamw &pdoff, &dscnt, &dsoff); 251da6c28aaSamw 2527b59d02dSjb150015 if (rc != 0) 253faa1795aSjb150015 return (SDRC_ERROR); 254da6c28aaSamw 255faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED); 256da6c28aaSamw } 257da6c28aaSamw 258faa1795aSjb150015 smb_sdrc_t 259faa1795aSjb150015 smb_pre_transaction2(smb_request_t *sr) 260da6c28aaSamw { 261faa1795aSjb150015 DTRACE_SMB_1(op__Transaction2__start, smb_request_t *, sr); 262faa1795aSjb150015 return (SDRC_SUCCESS); 263faa1795aSjb150015 } 264faa1795aSjb150015 265faa1795aSjb150015 void 266faa1795aSjb150015 smb_post_transaction2(smb_request_t *sr) 267faa1795aSjb150015 { 268faa1795aSjb150015 DTRACE_SMB_1(op__Transaction2__done, smb_request_t *, sr); 269da6c28aaSamw } 270da6c28aaSamw 2717b59d02dSjb150015 smb_sdrc_t 272da6c28aaSamw smb_com_transaction2(struct smb_request *sr) 273da6c28aaSamw { 274da6c28aaSamw unsigned char msrcnt, suwcnt; 275da6c28aaSamw uint16_t tpscnt, tdscnt, mprcnt, mdrcnt, flags; 276da6c28aaSamw uint16_t pscnt, psoff, dscnt, dsoff; 277da6c28aaSamw uint32_t timeo; 278da6c28aaSamw smb_xa_t *xa; 279da6c28aaSamw int ready; 280da6c28aaSamw int rc; 281da6c28aaSamw 282da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, &tpscnt, &tdscnt, 283da6c28aaSamw &mprcnt, &mdrcnt, &msrcnt, &flags, &timeo, &pscnt, &psoff, &dscnt, 284da6c28aaSamw &dsoff, &suwcnt); 285da6c28aaSamw 2867b59d02dSjb150015 if (rc != 0) 287faa1795aSjb150015 return (SDRC_ERROR); 288da6c28aaSamw 289da6c28aaSamw xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, 290da6c28aaSamw msrcnt, suwcnt); 291da6c28aaSamw if (xa == 0) { 292dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRnoroom); 293faa1795aSjb150015 return (SDRC_ERROR); 294da6c28aaSamw } 295da6c28aaSamw 296da6c28aaSamw xa->smb_flags = flags; 297da6c28aaSamw xa->smb_timeout = timeo; 298da6c28aaSamw xa->req_disp_param = pscnt; 299da6c28aaSamw xa->req_disp_data = dscnt; 300da6c28aaSamw 301da6c28aaSamw if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv, 302da6c28aaSamw sr->smb_vwv.chain_offset, suwcnt*2)) { 303da6c28aaSamw smb_xa_rele(sr->session, xa); 304dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 305faa1795aSjb150015 return (SDRC_ERROR); 306da6c28aaSamw } 307da6c28aaSamw if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 308da6c28aaSamw smb_xa_rele(sr->session, xa); 309dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 310faa1795aSjb150015 return (SDRC_ERROR); 311da6c28aaSamw } 312da6c28aaSamw if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 313da6c28aaSamw smb_xa_rele(sr->session, xa); 314dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 315faa1795aSjb150015 return (SDRC_ERROR); 316da6c28aaSamw } 317da6c28aaSamw 318da6c28aaSamw ready = smb_trans_ready(xa); 319da6c28aaSamw 320da6c28aaSamw if (smb_xa_open(xa)) { 321da6c28aaSamw smb_xa_rele(sr->session, xa); 322dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRsrverror); 323faa1795aSjb150015 return (SDRC_ERROR); 324da6c28aaSamw } 325da6c28aaSamw sr->r_xa = xa; 326da6c28aaSamw 327da6c28aaSamw if (!ready) { 3287b59d02dSjb150015 rc = smbsr_encode_empty_result(sr); 329faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 330da6c28aaSamw } 331da6c28aaSamw 332da6c28aaSamw if (!smb_xa_complete(xa)) { 333da6c28aaSamw smb_xa_close(xa); 334dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 335faa1795aSjb150015 return (SDRC_ERROR); 336da6c28aaSamw } 337da6c28aaSamw 338da6c28aaSamw return (smb_trans2_dispatch(sr, xa)); 339da6c28aaSamw } 340da6c28aaSamw 3417b59d02dSjb150015 smb_sdrc_t 342faa1795aSjb150015 smb_pre_transaction2_secondary(smb_request_t *sr) 343faa1795aSjb150015 { 344faa1795aSjb150015 DTRACE_SMB_1(op__Transaction2Secondary__start, smb_request_t *, sr); 345faa1795aSjb150015 return (SDRC_SUCCESS); 346faa1795aSjb150015 } 347faa1795aSjb150015 348faa1795aSjb150015 void 349faa1795aSjb150015 smb_post_transaction2_secondary(smb_request_t *sr) 350faa1795aSjb150015 { 351faa1795aSjb150015 DTRACE_SMB_1(op__Transaction2Secondary__done, smb_request_t *, sr); 352faa1795aSjb150015 } 353faa1795aSjb150015 354faa1795aSjb150015 smb_sdrc_t 355faa1795aSjb150015 smb_com_transaction2_secondary(smb_request_t *sr) 356da6c28aaSamw { 357da6c28aaSamw uint16_t tpscnt, tdscnt, fid; 358da6c28aaSamw uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp; 359da6c28aaSamw smb_xa_t *xa; 360da6c28aaSamw int rc; 361da6c28aaSamw 362da6c28aaSamw if ((xa = smbsr_lookup_xa(sr)) == 0) { 363dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 364faa1795aSjb150015 return (SDRC_ERROR); 365da6c28aaSamw } 366da6c28aaSamw 367da6c28aaSamw if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 368da6c28aaSamw if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { 369dc20a302Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 370da6c28aaSamw ERRDOS, ERRnoaccess); 371faa1795aSjb150015 return (SDRC_ERROR); 372da6c28aaSamw } 373da6c28aaSamw } 374da6c28aaSamw 375da6c28aaSamw if (xa->smb_com != SMB_COM_TRANSACTION2) { 376da6c28aaSamw return (SDRC_DROP_VC); 377da6c28aaSamw } 378da6c28aaSamw 379da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt, 380da6c28aaSamw &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid); 381da6c28aaSamw 3827b59d02dSjb150015 if (rc != 0) 383faa1795aSjb150015 return (SDRC_ERROR); 384da6c28aaSamw 385da6c28aaSamw mutex_enter(&xa->xa_mutex); 386da6c28aaSamw xa->smb_tpscnt = tpscnt; /* might have shrunk */ 387da6c28aaSamw xa->smb_tdscnt = tdscnt; /* might have shrunk */ 388da6c28aaSamw xa->xa_smb_fid = fid; /* overwrite rules? */ 389da6c28aaSamw xa->req_disp_param = psdisp + pscnt; 390da6c28aaSamw xa->req_disp_data = dsdisp + dscnt; 391da6c28aaSamw 392da6c28aaSamw if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 393da6c28aaSamw mutex_exit(&xa->xa_mutex); 394da6c28aaSamw smb_xa_close(xa); 395dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 396faa1795aSjb150015 return (SDRC_ERROR); 397da6c28aaSamw } 398da6c28aaSamw if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 399da6c28aaSamw mutex_exit(&xa->xa_mutex); 400da6c28aaSamw smb_xa_close(xa); 401dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 402faa1795aSjb150015 return (SDRC_ERROR); 403da6c28aaSamw } 404da6c28aaSamw mutex_exit(&xa->xa_mutex); 405da6c28aaSamw 406da6c28aaSamw if (!smb_trans_ready(xa)) 407da6c28aaSamw return (SDRC_NO_REPLY); 408da6c28aaSamw 409da6c28aaSamw if (!smb_xa_complete(xa)) 410da6c28aaSamw return (SDRC_NO_REPLY); 411da6c28aaSamw 412da6c28aaSamw return (smb_trans2_dispatch(sr, xa)); 413da6c28aaSamw } 414da6c28aaSamw 4157b59d02dSjb150015 static smb_sdrc_t 416da6c28aaSamw smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) 417da6c28aaSamw { 418da6c28aaSamw int rc; 419da6c28aaSamw int total_bytes, n_setup, n_param, n_data; 420da6c28aaSamw int param_off, param_pad, data_off, data_pad; 421da6c28aaSamw 422da6c28aaSamw n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200; 423da6c28aaSamw n_setup++; 424da6c28aaSamw n_setup = n_setup & ~0x0001; 425da6c28aaSamw n_param = (xa->smb_mprcnt < smb_maxbufsize) 426da6c28aaSamw ? xa->smb_mprcnt : smb_maxbufsize; 427da6c28aaSamw n_param++; 428da6c28aaSamw n_param = n_param & ~0x0001; 429da6c28aaSamw rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param); 430da6c28aaSamw n_data = (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc; 431da6c28aaSamw MBC_INIT(&xa->rep_setup_mb, n_setup * 2); 432da6c28aaSamw MBC_INIT(&xa->rep_param_mb, n_param); 433da6c28aaSamw MBC_INIT(&xa->rep_data_mb, n_data); 434da6c28aaSamw 435da6c28aaSamw switch (xa->smb_func) { 436da6c28aaSamw case NT_TRANSACT_CREATE: 437faa1795aSjb150015 if ((rc = smb_pre_nt_transact_create(sr, xa)) == 0) 438da6c28aaSamw rc = smb_nt_transact_create(sr, xa); 439faa1795aSjb150015 smb_post_nt_transact_create(sr, xa); 440da6c28aaSamw break; 441da6c28aaSamw case NT_TRANSACT_NOTIFY_CHANGE: 442da6c28aaSamw rc = smb_nt_transact_notify_change(sr, xa); 443da6c28aaSamw break; 444da6c28aaSamw case NT_TRANSACT_QUERY_SECURITY_DESC: 445da6c28aaSamw rc = smb_nt_transact_query_security_info(sr, xa); 446da6c28aaSamw break; 447da6c28aaSamw case NT_TRANSACT_SET_SECURITY_DESC: 448da6c28aaSamw rc = smb_nt_transact_set_security_info(sr, xa); 449da6c28aaSamw break; 450da6c28aaSamw case NT_TRANSACT_IOCTL: 451da6c28aaSamw rc = smb_nt_transact_ioctl(sr, xa); 452da6c28aaSamw break; 453da6c28aaSamw 454da6c28aaSamw case NT_TRANSACT_QUERY_QUOTA: 455da6c28aaSamw (void) smb_nt_transact_query_quota(sr, xa); 456b1352070SAlan Wright break; 457da6c28aaSamw 458da6c28aaSamw case NT_TRANSACT_SET_QUOTA: 459dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRaccess); 460faa1795aSjb150015 return (SDRC_ERROR); 461da6c28aaSamw 462*bbf6f00cSJordan Brown case NT_TRANSACT_RENAME: 463*bbf6f00cSJordan Brown rc = smb_nt_transact_rename(sr, xa); 464*bbf6f00cSJordan Brown break; 465*bbf6f00cSJordan Brown 466da6c28aaSamw default: 467dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); 468faa1795aSjb150015 return (SDRC_ERROR); 469da6c28aaSamw } 470da6c28aaSamw 471da6c28aaSamw switch (rc) { 472faa1795aSjb150015 case SDRC_SUCCESS: 473da6c28aaSamw break; 474da6c28aaSamw 475da6c28aaSamw case SDRC_DROP_VC: 476da6c28aaSamw case SDRC_NO_REPLY: 477faa1795aSjb150015 case SDRC_ERROR: 47859229f98Sjose borrego case SDRC_SR_KEPT: 479da6c28aaSamw return (rc); 480da6c28aaSamw 481faa1795aSjb150015 case SDRC_NOT_IMPLEMENTED: 482dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); 483faa1795aSjb150015 return (SDRC_ERROR); 484da6c28aaSamw 485da6c28aaSamw default: 486da6c28aaSamw break; 487da6c28aaSamw } 488da6c28aaSamw 489da6c28aaSamw n_setup = MBC_LENGTH(&xa->rep_setup_mb); 490da6c28aaSamw n_param = MBC_LENGTH(&xa->rep_param_mb); 491da6c28aaSamw n_data = MBC_LENGTH(&xa->rep_data_mb); 492da6c28aaSamw 493da6c28aaSamw if (xa->smb_msrcnt < n_setup || 494da6c28aaSamw xa->smb_mprcnt < n_param || 495da6c28aaSamw xa->smb_mdrcnt < n_data) { 496dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); 497faa1795aSjb150015 return (SDRC_ERROR); 498da6c28aaSamw } 499da6c28aaSamw 500da6c28aaSamw /* neato, blast it over there */ 501da6c28aaSamw 502da6c28aaSamw n_setup = (n_setup + 1) / 2; /* Conver to setup words */ 503da6c28aaSamw param_pad = 1; /* must be one */ 504da6c28aaSamw param_off = param_pad + 32 + 37 + (n_setup << 1) + 2; 505da6c28aaSamw data_pad = (4 - ((param_off + n_param) & 3)) % 4; /* Pad to 4 byte */ 506da6c28aaSamw data_off = param_off + n_param + data_pad; /* Param off from hdr */ 507da6c28aaSamw total_bytes = param_pad + n_param + data_pad + n_data; 508da6c28aaSamw 5097b59d02dSjb150015 rc = smbsr_encode_result(sr, 18+n_setup, total_bytes, 510da6c28aaSamw "b3.llllllllbCw#.C#.C", 511da6c28aaSamw 18 + n_setup, /* wct */ 512da6c28aaSamw n_param, /* Total Parameter Bytes */ 513da6c28aaSamw n_data, /* Total Data Bytes */ 514da6c28aaSamw n_param, /* Total Parameter Bytes this buffer */ 515da6c28aaSamw param_off, /* Param offset from header start */ 516da6c28aaSamw 0, /* Param displacement */ 517da6c28aaSamw n_data, /* Total Data Bytes this buffer */ 518da6c28aaSamw data_off, /* Data offset from header start */ 519da6c28aaSamw 0, /* Data displacement */ 520da6c28aaSamw n_setup, /* suwcnt */ 521da6c28aaSamw &xa->rep_setup_mb, /* setup[] */ 522da6c28aaSamw total_bytes, /* Total data bytes */ 523da6c28aaSamw param_pad, 524da6c28aaSamw &xa->rep_param_mb, 525da6c28aaSamw data_pad, 526da6c28aaSamw &xa->rep_data_mb); 527faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 528da6c28aaSamw } 529da6c28aaSamw 530da6c28aaSamw /* 531da6c28aaSamw * smb_nt_transact_query_quota 532da6c28aaSamw * 533b1352070SAlan Wright * Request Description 534b1352070SAlan Wright * ========================== ================================== 535b1352070SAlan Wright * WORD fid 536b1352070SAlan Wright * BYTE ReturnSingleEntry A boolean indicating whether to return 537b1352070SAlan Wright * a single entry or multiple entries. 538b1352070SAlan Wright * BYTE RestartScan A boolean indicating whether to continue from 539b1352070SAlan Wright * the previous request or restart a new sequence. 540b1352070SAlan Wright * DWORD SidListLength The length in bytes of the SidList or 0 if 541b1352070SAlan Wright * there is no SidList. 542b1352070SAlan Wright * DWORD StartSidLength The length in bytes of the StartSid or 0 if 543b1352070SAlan Wright * there is no StartSid. The server must ignore 544b1352070SAlan Wright * StartSidLength if SidListLength is non-zero. 545b1352070SAlan Wright * DWORD StartSidOffset The offset, in bytes, to the StartSid in the 546b1352070SAlan Wright * parameter block. 547b1352070SAlan Wright * 548b1352070SAlan Wright * If SidListLength is non-zero, the request contains a list of SIDs 549b1352070SAlan Wright * for which information is requested. If StartSidLength is nonzero, 550b1352070SAlan Wright * the request contains the SID at which the enumeration should start. 551b1352070SAlan Wright * 552b1352070SAlan Wright * One of SidListLength and StartSidLength must be 0. If both are 0, 553b1352070SAlan Wright * all SIDs are to be enumerated by the server as if they were passed 554b1352070SAlan Wright * the SidList. 555da6c28aaSamw */ 5567b59d02dSjb150015 static smb_sdrc_t 557da6c28aaSamw smb_nt_transact_query_quota(struct smb_request *sr, struct smb_xa *xa) 558da6c28aaSamw { 559b1352070SAlan Wright smb_sid_t *sid; 560b1352070SAlan Wright uint8_t single, restart; 561da6c28aaSamw uint16_t fid; 562b1352070SAlan Wright uint32_t sidlen, listlen, startlen, startoff; 563b1352070SAlan Wright uint64_t limit, used, mtime; 564da6c28aaSamw 565b1352070SAlan Wright if (smb_mbc_decodef(&xa->req_param_mb, "%wbblll", sr, 566b1352070SAlan Wright &fid, &single, &restart, &listlen, &startlen, &startoff)) 567faa1795aSjb150015 return (SDRC_ERROR); 568da6c28aaSamw 569b1352070SAlan Wright if (restart == 0) { 570b1352070SAlan Wright (void) smb_mbc_encodef(&xa->rep_param_mb, "l", 0); 571b1352070SAlan Wright return (SDRC_SUCCESS); 572b1352070SAlan Wright } 573b1352070SAlan Wright 574b1352070SAlan Wright /* 575b1352070SAlan Wright * BUILTIN\Administrators 576b1352070SAlan Wright */ 577b1352070SAlan Wright if ((sid = smb_sid_fromstr("S-1-5-32-544")) == NULL) { 578b1352070SAlan Wright smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 0, 0); 579b1352070SAlan Wright return (SDRC_ERROR); 580b1352070SAlan Wright } 581b1352070SAlan Wright 582b1352070SAlan Wright sidlen = smb_sid_len(sid); 583b1352070SAlan Wright used = 0; 584b1352070SAlan Wright mtime = 0xBA7ADAAC0436C601; /* canned dummy timestamp */ 585b1352070SAlan Wright limit = SMB_QUOTA_UNLIMITED; 586b1352070SAlan Wright 587b1352070SAlan Wright /* 588b1352070SAlan Wright * The encoded length of "llqqqq" is 40 bytes. 589b1352070SAlan Wright */ 590b1352070SAlan Wright (void) smb_mbc_encodef(&xa->rep_param_mb, "l", 40 + sidlen); 591b1352070SAlan Wright 592b1352070SAlan Wright (void) smb_mbc_encodef(&xa->rep_data_mb, "llqqqq", 593b1352070SAlan Wright 0, /* next offset */ 594b1352070SAlan Wright sidlen, /* sid length */ 595b1352070SAlan Wright mtime, /* change time */ 596b1352070SAlan Wright used, /* quota used */ 597b1352070SAlan Wright limit, /* soft limit */ 598b1352070SAlan Wright limit); /* hard limit */ 599b1352070SAlan Wright 600b1352070SAlan Wright smb_encode_sid(xa, sid); 601b1352070SAlan Wright smb_sid_free(sid); 602faa1795aSjb150015 return (SDRC_SUCCESS); 603da6c28aaSamw } 604da6c28aaSamw 605faa1795aSjb150015 smb_sdrc_t 606faa1795aSjb150015 smb_pre_nt_transact(smb_request_t *sr) 607faa1795aSjb150015 { 608faa1795aSjb150015 DTRACE_SMB_1(op__NtTransact__start, smb_request_t *, sr); 609faa1795aSjb150015 return (SDRC_SUCCESS); 610faa1795aSjb150015 } 611faa1795aSjb150015 612faa1795aSjb150015 void 613faa1795aSjb150015 smb_post_nt_transact(smb_request_t *sr) 614faa1795aSjb150015 { 615faa1795aSjb150015 DTRACE_SMB_1(op__NtTransact__done, smb_request_t *, sr); 616faa1795aSjb150015 } 617da6c28aaSamw 6187b59d02dSjb150015 smb_sdrc_t 619da6c28aaSamw smb_com_nt_transact(struct smb_request *sr) 620da6c28aaSamw { 621da6c28aaSamw uint16_t Function; 622da6c28aaSamw unsigned char MaxSetupCount, SetupCount; 623da6c28aaSamw uint32_t TotalParameterCount, TotalDataCount; 624da6c28aaSamw uint32_t MaxParameterCount, MaxDataCount, pscnt; 625da6c28aaSamw uint32_t psoff, dscnt, dsoff; 626da6c28aaSamw smb_xa_t *xa; 627da6c28aaSamw int ready; 628da6c28aaSamw int rc; 629da6c28aaSamw 630da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_NT_TRANSHDR_ED_FMT, &MaxSetupCount, 631da6c28aaSamw &TotalParameterCount, &TotalDataCount, &MaxParameterCount, 632da6c28aaSamw &MaxDataCount, &pscnt, &psoff, &dscnt, 633da6c28aaSamw &dsoff, &SetupCount, &Function); 634da6c28aaSamw 6357b59d02dSjb150015 if (rc != 0) 636faa1795aSjb150015 return (SDRC_ERROR); 637da6c28aaSamw 638da6c28aaSamw xa = smb_xa_create(sr->session, sr, TotalParameterCount, TotalDataCount, 639da6c28aaSamw MaxParameterCount, MaxDataCount, MaxSetupCount, SetupCount); 640da6c28aaSamw if (xa == 0) { 641dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRnoroom); 642faa1795aSjb150015 return (SDRC_ERROR); 643da6c28aaSamw } 644da6c28aaSamw 645da6c28aaSamw xa->smb_flags = 0; 646da6c28aaSamw xa->smb_timeout = 0; 647da6c28aaSamw xa->smb_func = Function; 648da6c28aaSamw xa->req_disp_param = pscnt; 649da6c28aaSamw xa->req_disp_data = dscnt; 650da6c28aaSamw 651da6c28aaSamw if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv, 652da6c28aaSamw sr->smb_vwv.chain_offset, SetupCount * 2)) { 653da6c28aaSamw smb_xa_rele(sr->session, xa); 654dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 655faa1795aSjb150015 return (SDRC_ERROR); 656da6c28aaSamw } 657da6c28aaSamw if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 658da6c28aaSamw smb_xa_rele(sr->session, xa); 659dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 660faa1795aSjb150015 return (SDRC_ERROR); 661da6c28aaSamw } 662da6c28aaSamw if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 663da6c28aaSamw smb_xa_rele(sr->session, xa); 664dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 665faa1795aSjb150015 return (SDRC_ERROR); 666da6c28aaSamw } 667da6c28aaSamw 668da6c28aaSamw ready = smb_trans_ready(xa); 669da6c28aaSamw 670da6c28aaSamw if (smb_xa_open(xa)) { 671da6c28aaSamw smb_xa_rele(sr->session, xa); 672dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRsrverror); 673faa1795aSjb150015 return (SDRC_ERROR); 674da6c28aaSamw } 675da6c28aaSamw sr->r_xa = xa; 676da6c28aaSamw 677da6c28aaSamw if (!ready) { 6787b59d02dSjb150015 rc = smbsr_encode_empty_result(sr); 679faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 680da6c28aaSamw } 681da6c28aaSamw 682da6c28aaSamw if (!smb_xa_complete(xa)) { 683da6c28aaSamw smb_xa_close(xa); 684dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 685faa1795aSjb150015 return (SDRC_ERROR); 686da6c28aaSamw } 687da6c28aaSamw 688da6c28aaSamw return (smb_nt_trans_dispatch(sr, xa)); 689da6c28aaSamw } 690da6c28aaSamw 691faa1795aSjb150015 smb_sdrc_t 692faa1795aSjb150015 smb_pre_nt_transact_secondary(smb_request_t *sr) 693faa1795aSjb150015 { 694faa1795aSjb150015 DTRACE_SMB_1(op__NtTransactSecondary__start, smb_request_t *, sr); 695faa1795aSjb150015 return (SDRC_SUCCESS); 696faa1795aSjb150015 } 697faa1795aSjb150015 698faa1795aSjb150015 void 699faa1795aSjb150015 smb_post_nt_transact_secondary(smb_request_t *sr) 700faa1795aSjb150015 { 701faa1795aSjb150015 DTRACE_SMB_1(op__NtTransactSecondary__done, smb_request_t *, sr); 702faa1795aSjb150015 } 703da6c28aaSamw 7047b59d02dSjb150015 smb_sdrc_t 705da6c28aaSamw smb_com_nt_transact_secondary(struct smb_request *sr) 706da6c28aaSamw { 707da6c28aaSamw uint16_t tpscnt, tdscnt, fid; 708da6c28aaSamw uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp; 709da6c28aaSamw smb_xa_t *xa; 710da6c28aaSamw int rc; 711da6c28aaSamw 712da6c28aaSamw if ((xa = smbsr_lookup_xa(sr)) == 0) { 713dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 714faa1795aSjb150015 return (SDRC_ERROR); 715da6c28aaSamw } 716da6c28aaSamw 717da6c28aaSamw if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 718da6c28aaSamw if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { 719dc20a302Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 720da6c28aaSamw ERRDOS, ERRnoaccess); 721faa1795aSjb150015 return (SDRC_ERROR); 722da6c28aaSamw } 723da6c28aaSamw } 724da6c28aaSamw 725da6c28aaSamw if (xa->smb_com != SMB_COM_TRANSACTION2) { 726da6c28aaSamw return (SDRC_DROP_VC); 727da6c28aaSamw } 728da6c28aaSamw 729da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt, 730da6c28aaSamw &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid); 731da6c28aaSamw 7327b59d02dSjb150015 if (rc != 0) 733faa1795aSjb150015 return (SDRC_ERROR); 734da6c28aaSamw 735da6c28aaSamw mutex_enter(&xa->xa_mutex); 736da6c28aaSamw xa->smb_tpscnt = tpscnt; /* might have shrunk */ 737da6c28aaSamw xa->smb_tdscnt = tdscnt; /* might have shrunk */ 738da6c28aaSamw xa->xa_smb_fid = fid; /* overwrite rules? */ 739da6c28aaSamw xa->req_disp_param = psdisp+pscnt; 740da6c28aaSamw xa->req_disp_data = dsdisp+dscnt; 741da6c28aaSamw 742da6c28aaSamw if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 743da6c28aaSamw mutex_exit(&xa->xa_mutex); 744da6c28aaSamw smb_xa_close(xa); 745dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 746faa1795aSjb150015 return (SDRC_ERROR); 747da6c28aaSamw } 748da6c28aaSamw if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 749da6c28aaSamw mutex_exit(&xa->xa_mutex); 750da6c28aaSamw smb_xa_close(xa); 751dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 752faa1795aSjb150015 return (SDRC_ERROR); 753da6c28aaSamw } 754da6c28aaSamw mutex_exit(&xa->xa_mutex); 755da6c28aaSamw 756da6c28aaSamw if (!smb_trans_ready(xa)) 757da6c28aaSamw return (SDRC_NO_REPLY); 758da6c28aaSamw 759da6c28aaSamw if (!smb_xa_complete(xa)) 760da6c28aaSamw return (SDRC_NO_REPLY); 761da6c28aaSamw 762da6c28aaSamw return (smb_nt_trans_dispatch(sr, xa)); 763da6c28aaSamw } 764da6c28aaSamw 7657b59d02dSjb150015 static int 766da6c28aaSamw smb_trans_ready(struct smb_xa *xa) 767da6c28aaSamw { 768da6c28aaSamw int rc; 769da6c28aaSamw 770da6c28aaSamw mutex_enter(&xa->xa_mutex); 771da6c28aaSamw rc = xa->req_disp_data >= xa->smb_tdscnt && 772da6c28aaSamw xa->req_disp_param >= xa->smb_tpscnt; 773da6c28aaSamw mutex_exit(&xa->xa_mutex); 774da6c28aaSamw 775da6c28aaSamw return (rc); 776da6c28aaSamw } 777da6c28aaSamw 7783ad684d6Sjb150015 static void 7793ad684d6Sjb150015 smb_encode_SHARE_INFO_1(struct mbuf_chain *output, struct mbuf_chain *text, 7803ad684d6Sjb150015 char *oem_name, uint16_t type, char *comment) 781da6c28aaSamw { 7823db3f65cSamw (void) smb_mbc_encodef(output, "13c.wl", oem_name, 7833ad684d6Sjb150015 type, MBC_LENGTH(text)); 784da6c28aaSamw 7853db3f65cSamw (void) smb_mbc_encodef(text, "s", comment ? comment : ""); 7866537f381Sas200622 } 787da6c28aaSamw 7883ad684d6Sjb150015 static void 7893ad684d6Sjb150015 smb_encode_SHARE_INFO_2(struct mbuf_chain *output, struct mbuf_chain *text, 7903ad684d6Sjb150015 smb_request_t *sr, char *oem_name, uint16_t type, 7913ad684d6Sjb150015 char *comment, uint16_t access, char *path, char *password) 792da6c28aaSamw { 793da6c28aaSamw unsigned char pword[9]; 794da6c28aaSamw 795da6c28aaSamw bzero(pword, sizeof (pword)); 796da6c28aaSamw (void) strncpy((char *)pword, password, sizeof (pword)); 7973ad684d6Sjb150015 smb_encode_SHARE_INFO_1(output, text, oem_name, type, comment); 7983db3f65cSamw (void) smb_mbc_encodef(output, "wwwl9c.", 799da6c28aaSamw access, 800faa1795aSjb150015 sr->sr_cfg->skc_maxconnections, 801faa1795aSjb150015 smb_server_get_session_count(), 802da6c28aaSamw MBC_LENGTH(text), 8033ad684d6Sjb150015 pword); 8043db3f65cSamw (void) smb_mbc_encodef(text, "s", path); 805da6c28aaSamw } 806da6c28aaSamw 807da6c28aaSamw int 808da6c28aaSamw smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa) 809da6c28aaSamw { 810faa1795aSjb150015 door_handle_t dhdl = sr->sr_server->sv_lmshrd; 811da6c28aaSamw 812da6c28aaSamw /* 813da6c28aaSamw * Number of data bytes that will 814da6c28aaSamw * be sent in the current response 815da6c28aaSamw */ 816da6c28aaSamw uint16_t data_scnt; 817da6c28aaSamw 818da6c28aaSamw /* 819da6c28aaSamw * Total number of data bytes that 820da6c28aaSamw * are sent till now. This is only 821da6c28aaSamw * used for calculating current data 822da6c28aaSamw * displacement 823da6c28aaSamw */ 824da6c28aaSamw uint16_t tot_data_scnt; 825da6c28aaSamw 826da6c28aaSamw /* 827da6c28aaSamw * Number of parameter bytes should 828da6c28aaSamw * be sent for the current response. 829da6c28aaSamw * It is 8 for the 1st response and 830da6c28aaSamw * 0 for others 831da6c28aaSamw */ 832da6c28aaSamw uint16_t param_scnt; 833da6c28aaSamw 834da6c28aaSamw /* number of setup and parameter bytes */ 835da6c28aaSamw uint16_t n_setup, n_param; 836da6c28aaSamw 837da6c28aaSamw /* data and parameter displacement */ 838da6c28aaSamw uint16_t data_disp, param_disp; 839da6c28aaSamw 840da6c28aaSamw /* parameter and data offset and pad */ 841da6c28aaSamw int param_off, param_pad, data_off, data_pad; 842da6c28aaSamw 843da6c28aaSamw /* 844da6c28aaSamw * total bytes of parameters and data 845da6c28aaSamw * in the packet, plus the pad bytes. 846da6c28aaSamw */ 847da6c28aaSamw int tot_packet_bytes; 848da6c28aaSamw 8493ad684d6Sjb150015 boolean_t first_resp; 850da6c28aaSamw 8513ad684d6Sjb150015 char fmt[16]; 8523ad684d6Sjb150015 struct mbuf_chain reply; 8533ad684d6Sjb150015 8543ad684d6Sjb150015 uint16_t level; 8553ad684d6Sjb150015 uint16_t pkt_bufsize; 8563ad684d6Sjb150015 smb_enumshare_info_t esi; 8573ad684d6Sjb150015 char *sent_buf; 8583ad684d6Sjb150015 8593ad684d6Sjb150015 ASSERT(sr->uid_user); 860da6c28aaSamw 861da6c28aaSamw /* 862da6c28aaSamw * Initialize the mbuf chain of reply to zero. If it is not 863da6c28aaSamw * zero, code inside the while loop will try to free the chain. 864da6c28aaSamw */ 865da6c28aaSamw bzero(&reply, sizeof (struct mbuf_chain)); 866da6c28aaSamw 8673db3f65cSamw if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level, 8683ad684d6Sjb150015 &esi.es_bufsize) != 0) 869faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED); 870da6c28aaSamw 871da6c28aaSamw if (level != 1) { 8723ad684d6Sjb150015 /* 8733ad684d6Sjb150015 * Only level 1 is valid for NetShareEnum 8743ad684d6Sjb150015 * None of the error codes in the spec are meaningful 8753ad684d6Sjb150015 * here. This error code is returned by Windows. 8763ad684d6Sjb150015 */ 8773db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 8783ad684d6Sjb150015 ERROR_INVALID_LEVEL, 0, 0, 0); 879faa1795aSjb150015 return (SDRC_SUCCESS); 880da6c28aaSamw } 881da6c28aaSamw 8823ad684d6Sjb150015 esi.es_buf = kmem_zalloc(esi.es_bufsize, KM_SLEEP); 8833ad684d6Sjb150015 esi.es_username = sr->uid_user->u_name; 8843ad684d6Sjb150015 (void) smb_kshare_enum(dhdl, &esi); 885da6c28aaSamw 8863ad684d6Sjb150015 /* client buffer size is not big enough to hold any shares */ 8873ad684d6Sjb150015 if (esi.es_nsent == 0) { 8883db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 8893ad684d6Sjb150015 ERROR_MORE_DATA, 0, esi.es_nsent, esi.es_ntotal); 8903ad684d6Sjb150015 kmem_free(esi.es_buf, esi.es_bufsize); 891faa1795aSjb150015 return (SDRC_SUCCESS); 892da6c28aaSamw } 893da6c28aaSamw 894da6c28aaSamw /* 895da6c28aaSamw * The rep_setup_mb is already initialized in smb_trans_dispatch(). 896da6c28aaSamw * Calling MBC_INIT() will initialized the structure and so the 897da6c28aaSamw * pointer to the mbuf chains will be lost. Therefore, we need 898da6c28aaSamw * to free the resources before calling MBC_INIT() again. 899da6c28aaSamw */ 9003ad684d6Sjb150015 n_setup = 0; /* Setup count for NetShareEnum SMB is 0 */ 901da6c28aaSamw m_freem(xa->rep_setup_mb.chain); 902da6c28aaSamw MBC_INIT(&xa->rep_setup_mb, n_setup * 2); 903da6c28aaSamw 9043ad684d6Sjb150015 n_param = 8; 9053ad684d6Sjb150015 pkt_bufsize = sr->session->smb_msg_size - 9063ad684d6Sjb150015 (SMB_HEADER_ED_LEN + RESP_HEADER_LEN + n_param); 907da6c28aaSamw 9083ad684d6Sjb150015 tot_data_scnt = 0; 9093ad684d6Sjb150015 sent_buf = esi.es_buf; 9103ad684d6Sjb150015 first_resp = B_TRUE; 9113ad684d6Sjb150015 9123ad684d6Sjb150015 while (tot_data_scnt < esi.es_datasize) { 9133ad684d6Sjb150015 data_scnt = esi.es_datasize - tot_data_scnt; 9143ad684d6Sjb150015 if (data_scnt > pkt_bufsize) 9153ad684d6Sjb150015 data_scnt = pkt_bufsize; 916da6c28aaSamw m_freem(xa->rep_data_mb.chain); 9173ad684d6Sjb150015 MBC_INIT(&xa->rep_data_mb, data_scnt); 9183ad684d6Sjb150015 9193ad684d6Sjb150015 (void) sprintf(fmt, "%dc", data_scnt); 9203db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, fmt, sent_buf); 9213ad684d6Sjb150015 9223ad684d6Sjb150015 sent_buf += data_scnt; 923da6c28aaSamw tot_data_scnt += data_scnt; 924da6c28aaSamw 925da6c28aaSamw /* Only the 1st response packet contains parameters */ 926da6c28aaSamw param_scnt = (first_resp) ? n_param : 0; 927da6c28aaSamw param_pad = 1; /* always one */ 928da6c28aaSamw param_off = SMB_HEADER_ED_LEN + RESP_HEADER_LEN; 929da6c28aaSamw param_disp = (first_resp) ? 0 : n_param; 930da6c28aaSamw 931da6c28aaSamw m_freem(xa->rep_param_mb.chain); 932da6c28aaSamw MBC_INIT(&xa->rep_param_mb, param_scnt); 9333ad684d6Sjb150015 934da6c28aaSamw if (first_resp) { 9353ad684d6Sjb150015 first_resp = B_FALSE; 9363db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 9373ad684d6Sjb150015 (esi.es_ntotal > esi.es_nsent) 9383ad684d6Sjb150015 ? ERROR_MORE_DATA : 0, 9393ad684d6Sjb150015 0, esi.es_nsent, esi.es_ntotal); 940da6c28aaSamw } 941da6c28aaSamw 942da6c28aaSamw data_pad = (param_off + n_param) & 1; /* Pad to short */ 943da6c28aaSamw 944da6c28aaSamw /* data off from hdr start */ 945da6c28aaSamw data_off = param_off + param_scnt + data_pad; 946da6c28aaSamw data_disp = tot_data_scnt - data_scnt; 947da6c28aaSamw tot_packet_bytes = param_pad + param_scnt + data_pad + 948da6c28aaSamw data_scnt; 949da6c28aaSamw 950da6c28aaSamw /* 951da6c28aaSamw * Calling MBC_INIT() will initialized the structure and so the 952da6c28aaSamw * pointer to the mbuf chains will be lost. Therefore, we need 953da6c28aaSamw * to free the resources if any before calling MBC_INIT(). 954da6c28aaSamw */ 955da6c28aaSamw m_freem(reply.chain); 956da6c28aaSamw MBC_INIT(&reply, SMB_HEADER_ED_LEN 9573ad684d6Sjb150015 + sizeof (uint8_t) /* word parameters count */ 9583ad684d6Sjb150015 + 10*sizeof (uint16_t) /* word parameters */ 9593ad684d6Sjb150015 + n_setup*sizeof (uint16_t) /* setup parameters */ 9603ad684d6Sjb150015 + sizeof (uint16_t) /* total data byte count */ 961da6c28aaSamw + tot_packet_bytes); 962da6c28aaSamw 9633db3f65cSamw (void) smb_mbc_encodef(&reply, SMB_HEADER_ED_FMT, 964da6c28aaSamw sr->first_smb_com, 965da6c28aaSamw sr->smb_rcls, 966da6c28aaSamw sr->smb_reh, 967da6c28aaSamw sr->smb_err, 968da6c28aaSamw sr->smb_flg | SMB_FLAGS_REPLY, 969da6c28aaSamw sr->smb_flg2, 970da6c28aaSamw sr->smb_pid_high, 971da6c28aaSamw sr->smb_sig, 972da6c28aaSamw sr->smb_tid, 973da6c28aaSamw sr->smb_pid, 974da6c28aaSamw sr->smb_uid, 975da6c28aaSamw sr->smb_mid); 976da6c28aaSamw 9773db3f65cSamw (void) smb_mbc_encodef(&reply, 978da6c28aaSamw "bww2.wwwwwwb.Cw#.C#.C", 979da6c28aaSamw 10 + n_setup, /* wct */ 980da6c28aaSamw n_param, /* Total Parameter Bytes */ 9813ad684d6Sjb150015 esi.es_datasize, /* Total Data Bytes */ 982da6c28aaSamw param_scnt, /* Total Parameter Bytes this buffer */ 983da6c28aaSamw param_off, /* Param offset from header start */ 984da6c28aaSamw param_disp, /* Param displacement */ 985da6c28aaSamw data_scnt, /* Total Data Bytes this buffer */ 986da6c28aaSamw data_off, /* Data offset from header start */ 987da6c28aaSamw data_disp, /* Data displacement */ 988da6c28aaSamw n_setup, /* suwcnt */ 989da6c28aaSamw &xa->rep_setup_mb, /* setup[] */ 990da6c28aaSamw tot_packet_bytes, /* Total data bytes */ 991da6c28aaSamw param_pad, 992da6c28aaSamw &xa->rep_param_mb, 993da6c28aaSamw data_pad, 994da6c28aaSamw &xa->rep_data_mb); 995da6c28aaSamw 996da6c28aaSamw if (sr->session->signing.flags & SMB_SIGNING_ENABLED) 997b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_sign_reply(sr, &reply); 998da6c28aaSamw 999da6c28aaSamw (void) smb_session_send(sr->session, 0, &reply); 1000da6c28aaSamw } 1001da6c28aaSamw 10023ad684d6Sjb150015 kmem_free(esi.es_buf, esi.es_bufsize); 1003da6c28aaSamw return (SDRC_NO_REPLY); 1004da6c28aaSamw } 1005da6c28aaSamw 1006da6c28aaSamw int 10073ad684d6Sjb150015 smb_trans_net_share_getinfo(smb_request_t *sr, struct smb_xa *xa) 1008da6c28aaSamw { 10093ad684d6Sjb150015 uint16_t level, max_bytes, access; 1010da6c28aaSamw struct mbuf_chain str_mb; 1011da6c28aaSamw char *share; 1012da6c28aaSamw char *password; 10133db3f65cSamw smb_share_t si; 10143ad684d6Sjb150015 int rc; 1015da6c28aaSamw 10163db3f65cSamw if (smb_mbc_decodef(&xa->req_param_mb, "%sww", sr, 10173ad684d6Sjb150015 &share, &level, &max_bytes) != 0) 1018faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED); 1019da6c28aaSamw 1020*bbf6f00cSJordan Brown (void) smb_strlwr(share); 1021b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = smb_kshare_getinfo(sr->sr_server->sv_lmshrd, share, &si, NULL); 10223db3f65cSamw if ((rc != NERR_Success) || (si.shr_flags & SMB_SHRF_LONGNAME)) { 10233db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 1024da6c28aaSamw NERR_NetNameNotFound, 0, 0); 1025faa1795aSjb150015 return (SDRC_SUCCESS); 1026da6c28aaSamw } 1027da6c28aaSamw 10283ad684d6Sjb150015 access = SHARE_ACCESS_ALL; 1029da6c28aaSamw password = ""; 1030da6c28aaSamw 1031da6c28aaSamw MBC_INIT(&str_mb, max_bytes); 1032da6c28aaSamw 1033da6c28aaSamw switch (level) { 1034da6c28aaSamw case 0 : 10353db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "13c", si.shr_oemname); 1036da6c28aaSamw break; 1037da6c28aaSamw 1038da6c28aaSamw case 1 : 10393ad684d6Sjb150015 smb_encode_SHARE_INFO_1(&xa->rep_data_mb, &str_mb, 10403db3f65cSamw si.shr_oemname, si.shr_type, si.shr_cmnt); 1041da6c28aaSamw break; 1042da6c28aaSamw 1043da6c28aaSamw case 2 : 10443ad684d6Sjb150015 smb_encode_SHARE_INFO_2(&xa->rep_data_mb, &str_mb, sr, 10453db3f65cSamw si.shr_oemname, si.shr_type, si.shr_cmnt, access, 10463db3f65cSamw si.shr_path, password); 10473ad684d6Sjb150015 break; 10483ad684d6Sjb150015 1049da6c28aaSamw default: 10503db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 10513ad684d6Sjb150015 ERROR_INVALID_LEVEL, 0, 0); 1052da6c28aaSamw m_freem(str_mb.chain); 1053faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED); 1054da6c28aaSamw } 1055da6c28aaSamw 10563db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www", NERR_Success, 1057da6c28aaSamw -MBC_LENGTH(&xa->rep_data_mb), 1058da6c28aaSamw MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb)); 10593db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb); 1060da6c28aaSamw m_freem(str_mb.chain); 1061faa1795aSjb150015 return (SDRC_SUCCESS); 1062da6c28aaSamw } 1063da6c28aaSamw 1064da6c28aaSamw int 10653ad684d6Sjb150015 smb_trans_net_workstation_getinfo(struct smb_request *sr, struct smb_xa *xa) 1066da6c28aaSamw { 10673ad684d6Sjb150015 uint16_t level, max_bytes; 1068da6c28aaSamw struct mbuf_chain str_mb; 1069da6c28aaSamw char *domain; 1070da6c28aaSamw char *hostname; 1071da6c28aaSamw 10723db3f65cSamw if ((smb_mbc_decodef(&xa->req_param_mb, "ww", 10733ad684d6Sjb150015 &level, &max_bytes) != 0) || 1074da6c28aaSamw (level != 10)) { 10753db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 1076da6c28aaSamw NERR_BadTransactConfig, 0, 0, 0); 1077faa1795aSjb150015 return (SDRC_SUCCESS); 1078da6c28aaSamw } 1079da6c28aaSamw 1080b89a8333Snatalie li - Sun Microsystems - Irvine United States domain = sr->sr_cfg->skc_nbdomain; 1081faa1795aSjb150015 hostname = sr->sr_cfg->skc_hostname; 1082da6c28aaSamw 1083da6c28aaSamw MBC_INIT(&str_mb, max_bytes); 1084da6c28aaSamw 10853db3f65cSamw (void) smb_mbc_encodef(&str_mb, "."); /* Prevent NULL pointers */ 1086da6c28aaSamw 10873db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 10883db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", hostname); 10893db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 10903db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", "nobody"); 10913db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 10923db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", domain); 10933db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "bbl", 1094da6c28aaSamw SMB_VERSION_MAJOR, SMB_VERSION_MINOR, MBC_LENGTH(&str_mb)); 10953db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", domain); 10963db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 10973db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", domain); 1098da6c28aaSamw 10993db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 0, 1100da6c28aaSamw -MBC_LENGTH(&xa->rep_data_mb), 1101da6c28aaSamw MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb)); 11023db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb); 1103da6c28aaSamw m_freem(str_mb.chain); 1104faa1795aSjb150015 return (SDRC_SUCCESS); 1105da6c28aaSamw } 1106da6c28aaSamw 1107da6c28aaSamw int 11083ad684d6Sjb150015 smb_trans_net_user_getinfo(struct smb_request *sr, struct smb_xa *xa) 1109da6c28aaSamw { 11103ad684d6Sjb150015 uint16_t level, max_bytes; 1111da6c28aaSamw unsigned char *user; 1112da6c28aaSamw int rc; 1113da6c28aaSamw 11143db3f65cSamw rc = smb_mbc_decodef(&xa->req_param_mb, "%sww", sr, 1115da6c28aaSamw &user, 1116da6c28aaSamw &level, 1117da6c28aaSamw &max_bytes); 1118da6c28aaSamw 1119da6c28aaSamw if (rc != 0) 1120faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED); 1121da6c28aaSamw 11223db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 1123da6c28aaSamw NERR_UserNotFound, 0, 0); 1124faa1795aSjb150015 return (SDRC_SUCCESS); 1125da6c28aaSamw } 1126da6c28aaSamw 11277b59d02dSjb150015 smb_sdrc_t 11283ad684d6Sjb150015 smb_trans_net_server_getinfo(struct smb_request *sr, struct smb_xa *xa) 1129da6c28aaSamw { 11303ad684d6Sjb150015 uint16_t level, buf_size; 11313ad684d6Sjb150015 uint16_t avail_data, max_data; 1132da6c28aaSamw char server_name[16]; 1133da6c28aaSamw struct mbuf_chain str_mb; 1134da6c28aaSamw 11353db3f65cSamw if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level, &buf_size) != 0) 1136faa1795aSjb150015 return (SDRC_ERROR); 1137da6c28aaSamw 11383ad684d6Sjb150015 max_data = MBC_MAXBYTES(&xa->rep_data_mb); 1139da6c28aaSamw 1140da6c28aaSamw MBC_INIT(&str_mb, buf_size); 1141da6c28aaSamw 1142da6c28aaSamw bzero(server_name, sizeof (server_name)); 11433ad684d6Sjb150015 (void) strncpy(server_name, sr->sr_cfg->skc_hostname, 11443ad684d6Sjb150015 sizeof (server_name)); 1145da6c28aaSamw 11463ad684d6Sjb150015 /* valid levels are 0 and 1 */ 1147da6c28aaSamw switch (level) { 1148da6c28aaSamw case 0: 11493db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "16c", server_name); 1150da6c28aaSamw break; 11513ad684d6Sjb150015 1152da6c28aaSamw case 1: 11533db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", 11543ad684d6Sjb150015 sr->sr_cfg->skc_system_comment); 11553db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "16cbbll", server_name, 1156da6c28aaSamw SMB_VERSION_MAJOR, SMB_VERSION_MINOR, 11573ad684d6Sjb150015 MY_SERVER_TYPE, max_data - MBC_LENGTH(&str_mb)); 1158da6c28aaSamw break; 11593ad684d6Sjb150015 1160da6c28aaSamw default: 11613db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 11623ad684d6Sjb150015 ERROR_INVALID_LEVEL, 0, 0); 1163da6c28aaSamw m_freem(str_mb.chain); 11643ad684d6Sjb150015 return (SDRC_SUCCESS); 1165da6c28aaSamw } 1166da6c28aaSamw 11673ad684d6Sjb150015 avail_data = MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb); 11683db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 11693ad684d6Sjb150015 NERR_Success, max_data - avail_data, avail_data); 11703db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb); 1171da6c28aaSamw m_freem(str_mb.chain); 1172faa1795aSjb150015 return (SDRC_SUCCESS); 1173da6c28aaSamw } 1174da6c28aaSamw 1175da6c28aaSamw /* 1176da6c28aaSamw * 6.4 The NetServerEnum2 RAP Service 1177da6c28aaSamw * 1178da6c28aaSamw * The NetServerEnum2 RAP service lists all computers of the specified type 1179da6c28aaSamw * or types that are visible in the specified domains. It may also 1180da6c28aaSamw * enumerate domains. 1181da6c28aaSamw * 1182da6c28aaSamw * The following definition uses the notation and terminology defined in 1183da6c28aaSamw * the CIFS Remote Administration Protocol specification, which is required 1184da6c28aaSamw * in order to make it well-defined. The definition is: 1185da6c28aaSamw * 1186da6c28aaSamw * uint16_t NetServerEnum2 ( 1187da6c28aaSamw * uint16_t sLevel, 1188da6c28aaSamw * RCVBUF pbBuffer, 1189da6c28aaSamw * RCVBUFLEN cbBuffer, 1190da6c28aaSamw * ENTCOUNT pcEntriesRead, 1191da6c28aaSamw * uint16_t *pcTotalAvail, 1192da6c28aaSamw * uint32_t fServerType, 1193da6c28aaSamw * char *pszDomain, 1194da6c28aaSamw * ); 1195da6c28aaSamw * 1196da6c28aaSamw * where: 1197da6c28aaSamw * 1198da6c28aaSamw * sLevel specifies the level of detail (0 or 1) requested. 1199da6c28aaSamw * 1200da6c28aaSamw * pbBuffer points to the buffer to receive the returned data. If the 1201da6c28aaSamw * function is successful, the buffer contains a sequence of 1202da6c28aaSamw * server_info_x structures, where x is 0 or 1, depending on the 1203da6c28aaSamw * level of detail requested. 1204da6c28aaSamw * 1205da6c28aaSamw * cbBuffer specifies the size, in bytes, of the buffer pointed to by 1206da6c28aaSamw * the pbBuffer parameter. 1207da6c28aaSamw * 1208da6c28aaSamw * pcEntriesRead points to a 16 bit variable that receives a count of 1209da6c28aaSamw * the number of servers enumerated in the buffer. This count is 1210da6c28aaSamw * valid only if NetServerEnum2 returns the NERR_Success or 1211da6c28aaSamw * ERROR_MORE_DATA values. 1212da6c28aaSamw * 1213da6c28aaSamw * pcTotal Avail points to a 16 bit variable that receives a count of 1214da6c28aaSamw * the total number of available entries. This count is valid only if 1215da6c28aaSamw * NetServerEnum2 returns the NERR_Success or ERROR_MORE_DATA values. 1216da6c28aaSamw * 1217da6c28aaSamw * fServerType specifies the type or types of computers to enumerate. 1218da6c28aaSamw * Computers that match at least one of the specified types are 1219da6c28aaSamw * returned in the buffer. Possible values are defined in the request 1220da6c28aaSamw * parameters section. 1221da6c28aaSamw * 1222da6c28aaSamw * pszDomain points to a null-terminated string that contains the 1223da6c28aaSamw * name of the workgroup in which to enumerate computers of the 1224da6c28aaSamw * specified type or types. If the pszDomain parameter is a null 1225da6c28aaSamw * string or a null pointer, servers are enumerated for the current 1226da6c28aaSamw * domain of the computer. 1227da6c28aaSamw * 1228da6c28aaSamw * 6.4.1 Transaction Request Parameters section 1229da6c28aaSamw * 1230da6c28aaSamw * The Transaction request parameters section in this instance contains: 1231da6c28aaSamw * . The 16 bit function number for NetServerEnum2 which is 104. 1232da6c28aaSamw * . The parameter descriptor string which is "WrLehDz". 1233da6c28aaSamw * . The data descriptor string for the (returned) data which is "B16" for 1234da6c28aaSamw * level detail 0 or "B16BBDz" for level detail 1. 1235da6c28aaSamw * . The actual parameters as described by the parameter descriptor 1236da6c28aaSamw * string. 1237da6c28aaSamw * 1238da6c28aaSamw * The parameters are: 1239da6c28aaSamw * . A 16 bit integer with a value of 0 or 1 (corresponding to the "W" in 1240da6c28aaSamw * the parameter descriptor string. This represents the level of detail 1241da6c28aaSamw * the server is expected to return 1242da6c28aaSamw * . A 16 bit integer that contains the size of the receive buffer. 1243da6c28aaSamw * . A 32 bit integer that represents the type of servers the function 1244da6c28aaSamw * should enumerate. The possible values may be any of the following or 1245da6c28aaSamw * a combination of the following: 1246da6c28aaSamw * 1247da6c28aaSamw * SV_TYPE_WORKSTATION 0x00000001 All workstations 1248da6c28aaSamw * SV_TYPE_SERVER 0x00000002 All servers 1249da6c28aaSamw * SV_TYPE_SQLSERVER 0x00000004 Any server running with SQL 1250da6c28aaSamw * server 1251da6c28aaSamw * SV_TYPE_DOMAIN_CTRL 0x00000008 Primary domain controller 1252da6c28aaSamw * SV_TYPE_DOMAIN_BAKCTRL 0x00000010 Backup domain controller 1253da6c28aaSamw * SV_TYPE_TIME_SOURCE 0x00000020 Server running the timesource 1254da6c28aaSamw * service 1255da6c28aaSamw * SV_TYPE_AFP 0x00000040 Apple File Protocol servers 1256da6c28aaSamw * SV_TYPE_NOVELL 0x00000080 Novell servers 1257da6c28aaSamw * SV_TYPE_DOMAIN_MEMBER 0x00000100 Domain Member 1258da6c28aaSamw * SV_TYPE_PRINTQ_SERVER 0x00000200 Server sharing print queue 1259da6c28aaSamw * SV_TYPE_DIALIN_SERVER 0x00000400 Server running dialin service. 1260da6c28aaSamw * SV_TYPE_XENIX_SERVER 0x00000800 Xenix server 1261da6c28aaSamw * SV_TYPE_NT 0x00001000 NT server 1262da6c28aaSamw * SV_TYPE_WFW 0x00002000 Server running Windows for 1263da6c28aaSamw * Workgroups 1264da6c28aaSamw * SV_TYPE_SERVER_NT 0x00008000 Windows NT non DC server 1265da6c28aaSamw * SV_TYPE_POTENTIAL_BROWSER 0x00010000 Server that can run the browser 1266da6c28aaSamw * service 1267da6c28aaSamw * SV_TYPE_BACKUP_BROWSER 0x00020000 Backup browser server 1268da6c28aaSamw * SV_TYPE_MASTER_BROWSER 0x00040000 Master browser server 1269da6c28aaSamw * SV_TYPE_DOMAIN_MASTER 0x00080000 Domain Master Browser server 1270da6c28aaSamw * SV_TYPE_LOCAL_LIST_ONLY 0x40000000 Enumerate only entries marked 1271da6c28aaSamw * "local" 1272da6c28aaSamw * SV_TYPE_DOMAIN_ENUM 0x80000000 Enumerate Domains. The pszDomain 1273da6c28aaSamw * parameter must be NULL. 1274da6c28aaSamw * 1275da6c28aaSamw * . A null terminated ASCII string representing the pszDomain parameter 1276da6c28aaSamw * described above 1277da6c28aaSamw * 1278da6c28aaSamw * 6.4.2 Transaction Request Data section 1279da6c28aaSamw * 1280da6c28aaSamw * There is no data or auxiliary data to send as part of the request. 1281da6c28aaSamw * 1282da6c28aaSamw * 6.4.3 Transaction Response Parameters section 1283da6c28aaSamw * 1284da6c28aaSamw * The transaction response parameters section consists of: 1285da6c28aaSamw * . A 16 bit word indicating the return status. The possible values are: 1286da6c28aaSamw * 1287da6c28aaSamw * Code Value Description 1288da6c28aaSamw * NERR_Success 0 No errors encountered 1289da6c28aaSamw * ERROR_MORE_DATA 234 Additional data is available 1290da6c28aaSamw * NERR_ServerNotStarted 2114 The RAP service on the remote computer 1291da6c28aaSamw * is not running 1292da6c28aaSamw * NERR_BadTransactConfig 2141 The server is not configured for 1293da6c28aaSamw * transactions, IPC$ is not shared 1294da6c28aaSamw * 1295da6c28aaSamw * . A 16 bit "converter" word. 1296da6c28aaSamw * . A 16 bit number representing the number of entries returned. 1297da6c28aaSamw * . A 16 bit number representing the total number of available entries. 1298da6c28aaSamw * If the supplied buffer is large enough, this will equal the number of 1299da6c28aaSamw * entries returned. 1300da6c28aaSamw * 1301da6c28aaSamw * 6.4.4 Transaction Response Data section 1302da6c28aaSamw * 1303da6c28aaSamw * The return data section consists of a number of SERVER_INFO_1 structures. 1304da6c28aaSamw * The number of such structures present is determined by the third entry 1305da6c28aaSamw * (described above) in the return parameters section. 1306da6c28aaSamw * 1307da6c28aaSamw * At level detail 0, the Transaction response data section contains a 1308da6c28aaSamw * number of SERVER_INFO_0 data structure. The number of such structures is 1309da6c28aaSamw * equal to the 16 bit number returned by the server in the third parameter 1310da6c28aaSamw * in the Transaction response parameter section. The SERVER_INFO_0 data 1311da6c28aaSamw * structure is defined as: 1312da6c28aaSamw * 1313da6c28aaSamw * struct SERVER_INFO_0 { 1314da6c28aaSamw * char sv0_name[16]; 1315da6c28aaSamw * }; 1316da6c28aaSamw * 1317da6c28aaSamw * where: 1318da6c28aaSamw * 1319da6c28aaSamw * sv0_name is a null-terminated string that specifies the name of a 1320da6c28aaSamw * computer or domain . 1321da6c28aaSamw * 1322da6c28aaSamw * At level detail 1, the Transaction response data section contains a 1323da6c28aaSamw * number of SERVER_INFO_1 data structure. The number of such structures is 1324da6c28aaSamw * equal to the 16 bit number returned by the server in the third parameter 1325da6c28aaSamw * in the Transaction response parameter section. The SERVER_INFO_1 data 1326da6c28aaSamw * structure is defined as: 1327da6c28aaSamw * 1328da6c28aaSamw * struct SERVER_INFO_1 { 1329da6c28aaSamw * char sv1_name[16]; 1330da6c28aaSamw * char sv1_version_major; 1331da6c28aaSamw * char sv1_version_minor; 1332da6c28aaSamw * uint32_t sv1_type; 1333da6c28aaSamw * char *sv1_comment_or_master_browser; 1334da6c28aaSamw * }; 1335da6c28aaSamw * 1336da6c28aaSamw * sv1_name contains a null-terminated string that specifies the name 1337da6c28aaSamw * of a computer, or a domain name if SV_TYPE_DOMAIN_ENUM is set in 1338da6c28aaSamw * sv1_type. 1339da6c28aaSamw * 1340da6c28aaSamw * sv1_version_major whatever was specified in the HostAnnouncement 1341da6c28aaSamw * or DomainAnnouncement frame with which the entry was registered. 1342da6c28aaSamw * 1343da6c28aaSamw * sv1_version_minor whatever was specified in the HostAnnouncement 1344da6c28aaSamw * or DomainAnnouncement frame with which the entry was registered. 1345da6c28aaSamw * 1346da6c28aaSamw * sv1_type specifies the type of software the computer is running. 1347da6c28aaSamw * The member can be one or a combination of the values defined above 1348da6c28aaSamw * in the Transaction request parameters section for fServerType. 1349da6c28aaSamw * 1350da6c28aaSamw * 1351da6c28aaSamw * sv1_comment_or_master_browser points to a null-terminated string. If 1352da6c28aaSamw * the sv1_type indicates that the entry is for a domain, this 1353da6c28aaSamw * specifies the name of server running the domain master browser; 1354da6c28aaSamw * otherwise, it specifies a comment describing the server. The comment 1355da6c28aaSamw * can be a null string or the pointer may be a null pointer. 1356da6c28aaSamw * 1357da6c28aaSamw * In case there are multiple SERVER_INFO_1 data structures to 1358da6c28aaSamw * return, the server may put all these fixed length structures in 1359da6c28aaSamw * the return buffer, leave some space and then put all the variable 1360da6c28aaSamw * length data (the actual value of the sv1_comment strings) at the 1361da6c28aaSamw * end of the buffer. 1362da6c28aaSamw * 1363da6c28aaSamw * There is no auxiliary data to receive. 1364da6c28aaSamw */ 1365da6c28aaSamw 1366da6c28aaSamw int 1367da6c28aaSamw smb_trans_net_server_enum2(struct smb_request *sr, struct smb_xa *xa) 1368da6c28aaSamw { 1369da6c28aaSamw uint16_t opcode, level, max_bytes; 1370da6c28aaSamw uint32_t server_type; 1371da6c28aaSamw unsigned char *domain; 1372da6c28aaSamw struct mbuf_chain str_mb; 1373da6c28aaSamw char *hostname, *s; 1374da6c28aaSamw smb_kmod_cfg_t *si; 1375da6c28aaSamw 13763db3f65cSamw if (smb_mbc_decodef(&xa->req_param_mb, 13773db3f65cSamw "%wsswwls", sr, &opcode, &s, &s, 1378da6c28aaSamw &level, &max_bytes, &server_type, &domain) != 0) 1379faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED); 1380da6c28aaSamw 1381faa1795aSjb150015 si = sr->sr_cfg; 1382da6c28aaSamw 1383*bbf6f00cSJordan Brown if (smb_strcasecmp(si->skc_nbdomain, (char *)domain, 0) != 0) { 13843db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0); 1385faa1795aSjb150015 return (SDRC_SUCCESS); 1386da6c28aaSamw } 1387da6c28aaSamw 1388da6c28aaSamw if ((server_type & MY_SERVER_TYPE) == 0) { 13893db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0); 1390faa1795aSjb150015 return (SDRC_SUCCESS); 1391da6c28aaSamw } 1392da6c28aaSamw 1393da6c28aaSamw MBC_INIT(&str_mb, max_bytes); 1394da6c28aaSamw 1395da6c28aaSamw hostname = si->skc_hostname; 1396da6c28aaSamw 13973db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "16c", hostname); 1398da6c28aaSamw if (level == 1) { 13993db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "bbll", 1400da6c28aaSamw SMB_VERSION_MAJOR, SMB_VERSION_MINOR, 1401da6c28aaSamw MY_SERVER_TYPE, MBC_LENGTH(&str_mb)); 14023db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", si->skc_system_comment); 1403da6c28aaSamw } 1404da6c28aaSamw 14053db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 1406da6c28aaSamw -MBC_LENGTH(&xa->rep_data_mb), 1, 1); 14073db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "m", str_mb.chain); 1408faa1795aSjb150015 return (SDRC_SUCCESS); 1409da6c28aaSamw } 1410da6c28aaSamw 1411*bbf6f00cSJordan Brown static boolean_t 1412*bbf6f00cSJordan Brown is_supported_mailslot(const char *mailslot) 1413da6c28aaSamw { 1414*bbf6f00cSJordan Brown static char *mailslots[] = { 1415*bbf6f00cSJordan Brown PIPE_LANMAN, 1416*bbf6f00cSJordan Brown MAILSLOT_LANMAN, 1417*bbf6f00cSJordan Brown MAILSLOT_BROWSE, 1418*bbf6f00cSJordan Brown MAILSLOT_MSBROWSE 1419*bbf6f00cSJordan Brown }; 1420da6c28aaSamw 1421*bbf6f00cSJordan Brown int i; 1422*bbf6f00cSJordan Brown 1423*bbf6f00cSJordan Brown for (i = 0; i < sizeof (mailslots)/sizeof (mailslots[0]); ++i) 1424*bbf6f00cSJordan Brown if (smb_strcasecmp(mailslot, mailslots[i], 0) == 0) 1425*bbf6f00cSJordan Brown return (B_TRUE); 1426*bbf6f00cSJordan Brown 1427*bbf6f00cSJordan Brown return (B_FALSE); 1428*bbf6f00cSJordan Brown } 1429*bbf6f00cSJordan Brown 1430*bbf6f00cSJordan Brown /* 1431*bbf6f00cSJordan Brown * Currently, just return false if the pipe is \\PIPE\repl. 1432*bbf6f00cSJordan Brown * Otherwise, return true. 1433*bbf6f00cSJordan Brown */ 1434*bbf6f00cSJordan Brown static boolean_t 1435*bbf6f00cSJordan Brown is_supported_pipe(const char *pname) 1436*bbf6f00cSJordan Brown { 1437*bbf6f00cSJordan Brown if (smb_strcasecmp(pname, PIPE_REPL, 0) == 0) 1438*bbf6f00cSJordan Brown return (B_FALSE); 1439*bbf6f00cSJordan Brown 1440*bbf6f00cSJordan Brown return (B_TRUE); 1441da6c28aaSamw } 1442da6c28aaSamw 14437b59d02dSjb150015 static smb_sdrc_t 1444da6c28aaSamw smb_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) 1445da6c28aaSamw { 1446da6c28aaSamw int rc, pos; 1447da6c28aaSamw int total_bytes, n_setup, n_param, n_data; 1448da6c28aaSamw int param_off, param_pad, data_off, data_pad; 1449da6c28aaSamw uint16_t opcode; 1450da6c28aaSamw uint16_t devstate; 1451da6c28aaSamw char *req_fmt; 1452da6c28aaSamw char *rep_fmt; 14532c2961f8Sjose borrego smb_vdb_t vdb; 1454da6c28aaSamw 1455da6c28aaSamw n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200; 1456da6c28aaSamw n_setup++; 1457da6c28aaSamw n_setup = n_setup & ~0x0001; 1458da6c28aaSamw n_param = (xa->smb_mprcnt < smb_maxbufsize) 1459da6c28aaSamw ? xa->smb_mprcnt : smb_maxbufsize; 1460da6c28aaSamw n_param++; 1461da6c28aaSamw n_param = n_param & ~0x0001; 1462da6c28aaSamw rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param); 1463da6c28aaSamw n_data = (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc; 1464da6c28aaSamw MBC_INIT(&xa->rep_setup_mb, n_setup * 2); 1465da6c28aaSamw MBC_INIT(&xa->rep_param_mb, n_param); 1466da6c28aaSamw MBC_INIT(&xa->rep_data_mb, n_data); 1467da6c28aaSamw 1468da6c28aaSamw if (xa->smb_suwcnt > 0 && STYPE_ISIPC(sr->tid_tree->t_res_type)) { 14693db3f65cSamw rc = smb_mbc_decodef(&xa->req_setup_mb, "ww", &opcode, 1470da6c28aaSamw &sr->smb_fid); 1471da6c28aaSamw if (rc != 0) 1472da6c28aaSamw goto trans_err_not_supported; 1473da6c28aaSamw switch (opcode) { 1474da6c28aaSamw case TRANS_SET_NMPIPE_STATE: 14753db3f65cSamw if ((rc = smb_mbc_decodef(&xa->req_param_mb, "w", 1476da6c28aaSamw &devstate)) != 0) 1477da6c28aaSamw goto trans_err_not_supported; 1478da6c28aaSamw 1479faa1795aSjb150015 rc = SDRC_SUCCESS; 1480da6c28aaSamw break; 1481da6c28aaSamw 1482da6c28aaSamw case TRANS_TRANSACT_NMPIPE: 14832c2961f8Sjose borrego smbsr_lookup_file(sr); 1484da6c28aaSamw if (sr->fid_ofile == NULL) { 1485dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 1486da6c28aaSamw ERRDOS, ERRbadfid); 1487faa1795aSjb150015 return (SDRC_ERROR); 1488da6c28aaSamw } 1489da6c28aaSamw 14903db3f65cSamw rc = smb_mbc_decodef(&xa->req_data_mb, "#B", 1491da6c28aaSamw xa->smb_tdscnt, &vdb); 1492da6c28aaSamw if (rc != 0) 1493da6c28aaSamw goto trans_err_not_supported; 1494da6c28aaSamw 14952c2961f8Sjose borrego rc = smb_opipe_transact(sr, &vdb.vdb_uio); 1496da6c28aaSamw break; 1497da6c28aaSamw 1498da6c28aaSamw case TRANS_WAIT_NMPIPE: 1499*bbf6f00cSJordan Brown if (!is_supported_pipe(xa->xa_pipe_name)) { 1500dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadfile); 1501faa1795aSjb150015 return (SDRC_ERROR); 1502da6c28aaSamw } 1503faa1795aSjb150015 rc = SDRC_SUCCESS; 1504da6c28aaSamw break; 1505da6c28aaSamw 1506da6c28aaSamw default: 1507da6c28aaSamw goto trans_err_not_supported; 1508da6c28aaSamw } 1509da6c28aaSamw } else { 1510*bbf6f00cSJordan Brown if (!is_supported_mailslot(xa->xa_pipe_name)) 1511da6c28aaSamw goto trans_err_not_supported; 1512da6c28aaSamw 15133db3f65cSamw if ((rc = smb_mbc_decodef(&xa->req_param_mb, "%wss", sr, 1514da6c28aaSamw &opcode, &req_fmt, &rep_fmt)) != 0) 1515da6c28aaSamw goto trans_err_not_supported; 1516da6c28aaSamw 1517da6c28aaSamw switch (opcode) { 1518da6c28aaSamw case API_WshareEnum: 1519da6c28aaSamw rc = smb_trans_net_share_enum(sr, xa); 1520da6c28aaSamw break; 1521da6c28aaSamw 1522da6c28aaSamw case API_WshareGetInfo: 15233ad684d6Sjb150015 rc = smb_trans_net_share_getinfo(sr, xa); 1524da6c28aaSamw break; 1525da6c28aaSamw 1526da6c28aaSamw case API_WserverGetInfo: 15273ad684d6Sjb150015 rc = smb_trans_net_server_getinfo(sr, xa); 1528da6c28aaSamw break; 1529da6c28aaSamw 1530da6c28aaSamw case API_WUserGetInfo: 15313ad684d6Sjb150015 rc = smb_trans_net_user_getinfo(sr, xa); 1532da6c28aaSamw break; 1533da6c28aaSamw 1534da6c28aaSamw case API_WWkstaGetInfo: 15353ad684d6Sjb150015 rc = smb_trans_net_workstation_getinfo(sr, xa); 1536da6c28aaSamw break; 1537da6c28aaSamw 1538da6c28aaSamw case API_NetServerEnum2: 1539da6c28aaSamw rc = smb_trans_net_server_enum2(sr, xa); 1540da6c28aaSamw break; 1541da6c28aaSamw 1542da6c28aaSamw default: 1543da6c28aaSamw goto trans_err_not_supported; 1544da6c28aaSamw } 1545da6c28aaSamw } 1546da6c28aaSamw 1547da6c28aaSamw switch (rc) { 1548faa1795aSjb150015 case SDRC_SUCCESS: 1549da6c28aaSamw break; 1550da6c28aaSamw 1551da6c28aaSamw case SDRC_DROP_VC: 1552da6c28aaSamw case SDRC_NO_REPLY: 1553faa1795aSjb150015 case SDRC_ERROR: 1554da6c28aaSamw return (rc); 1555da6c28aaSamw 1556faa1795aSjb150015 case SDRC_NOT_IMPLEMENTED: 1557da6c28aaSamw goto trans_err_not_supported; 1558da6c28aaSamw 1559da6c28aaSamw default: 1560da6c28aaSamw break; 1561da6c28aaSamw } 1562da6c28aaSamw 1563da6c28aaSamw n_setup = MBC_LENGTH(&xa->rep_setup_mb); 1564da6c28aaSamw n_param = MBC_LENGTH(&xa->rep_param_mb); 1565da6c28aaSamw n_data = MBC_LENGTH(&xa->rep_data_mb); 1566da6c28aaSamw 1567da6c28aaSamw if (xa->smb_msrcnt < n_setup || 1568da6c28aaSamw xa->smb_mprcnt < n_param || 1569da6c28aaSamw xa->smb_mdrcnt < n_data) { 1570da6c28aaSamw goto trans_err_too_small; 1571da6c28aaSamw } 1572da6c28aaSamw 1573da6c28aaSamw /* neato, blast it over there */ 1574da6c28aaSamw 1575da6c28aaSamw n_setup = (n_setup + 1) / 2; /* Convert to setup words */ 1576da6c28aaSamw param_pad = 1; /* always one */ 1577da6c28aaSamw param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 1578da6c28aaSamw data_pad = (param_off + n_param) & 1; /* Pad to short */ 1579da6c28aaSamw /* Param off from hdr start */ 1580da6c28aaSamw data_off = param_off + n_param + data_pad; 1581da6c28aaSamw total_bytes = param_pad + n_param + data_pad + n_data; 1582da6c28aaSamw 15837b59d02dSjb150015 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, 1584da6c28aaSamw "bww2.wwwwwwb.Cw#.C#.C", 1585da6c28aaSamw 10 + n_setup, /* wct */ 1586da6c28aaSamw n_param, /* Total Parameter Bytes */ 1587da6c28aaSamw n_data, /* Total Data Bytes */ 1588da6c28aaSamw n_param, /* Total Parameter Bytes this buffer */ 1589da6c28aaSamw param_off, /* Param offset from header start */ 1590da6c28aaSamw 0, /* Param displacement */ 1591da6c28aaSamw n_data, /* Total Data Bytes this buffer */ 1592da6c28aaSamw data_off, /* Data offset from header start */ 1593da6c28aaSamw 0, /* Data displacement */ 1594da6c28aaSamw n_setup, /* suwcnt */ 1595da6c28aaSamw &xa->rep_setup_mb, /* setup[] */ 1596da6c28aaSamw total_bytes, /* Total data bytes */ 1597da6c28aaSamw param_pad, 1598da6c28aaSamw &xa->rep_param_mb, 1599da6c28aaSamw data_pad, 1600da6c28aaSamw &xa->rep_data_mb); 1601faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1602da6c28aaSamw 1603da6c28aaSamw trans_err_too_small: 1604da6c28aaSamw rc = NERR_BufTooSmall; 1605da6c28aaSamw goto trans_err; 1606da6c28aaSamw 1607da6c28aaSamw trans_err_not_supported: 1608da6c28aaSamw rc = ERROR_NOT_SUPPORTED; 1609da6c28aaSamw goto trans_err; 1610da6c28aaSamw 1611da6c28aaSamw trans_err: 1612da6c28aaSamw pos = MBC_LENGTH(&sr->reply) + 23; 16137b59d02dSjb150015 rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www", 1614da6c28aaSamw 10, /* wct */ 1615da6c28aaSamw 4, 0, /* tpscnt tdscnt */ 1616da6c28aaSamw 4, pos, 0, /* pscnt psoff psdisp */ 1617da6c28aaSamw 0, 0, 0, /* dscnt dsoff dsdisp */ 1618da6c28aaSamw 0, /* suwcnt */ 1619da6c28aaSamw 4, /* bcc */ 1620da6c28aaSamw rc, 1621da6c28aaSamw 0); /* converter word? */ 1622faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1623da6c28aaSamw } 1624da6c28aaSamw 16257b59d02dSjb150015 static smb_sdrc_t 1626da6c28aaSamw smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) 1627da6c28aaSamw { 1628da6c28aaSamw int rc, pos; 1629da6c28aaSamw int total_bytes, n_setup, n_param, n_data; 1630da6c28aaSamw int param_off, param_pad, data_off, data_pad; 1631da6c28aaSamw uint16_t opcode; 1632da6c28aaSamw uint16_t nt_unknown_secret = 0x0100; 1633da6c28aaSamw char *fmt; 1634da6c28aaSamw 1635da6c28aaSamw n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200; 1636da6c28aaSamw n_setup++; 1637da6c28aaSamw n_setup = n_setup & ~0x0001; 1638da6c28aaSamw n_param = (xa->smb_mprcnt < smb_maxbufsize) 1639da6c28aaSamw ? xa->smb_mprcnt : smb_maxbufsize; 1640da6c28aaSamw n_param++; 1641da6c28aaSamw n_param = n_param & ~0x0001; 1642da6c28aaSamw rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param); 1643da6c28aaSamw n_data = (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc; 1644da6c28aaSamw MBC_INIT(&xa->rep_setup_mb, n_setup * 2); 1645da6c28aaSamw MBC_INIT(&xa->rep_param_mb, n_param); 1646da6c28aaSamw MBC_INIT(&xa->rep_data_mb, n_data); 1647da6c28aaSamw 16483db3f65cSamw if (smb_mbc_decodef(&xa->req_setup_mb, "w", &opcode) != 0) 1649da6c28aaSamw goto trans_err_not_supported; 1650da6c28aaSamw 1651da6c28aaSamw /* 1652da6c28aaSamw * Save this for /proc to read later. 1653da6c28aaSamw */ 1654da6c28aaSamw xa->smb_func = opcode; 1655da6c28aaSamw 1656da6c28aaSamw /* for now, only respond to the */ 1657da6c28aaSamw switch (opcode) { 16582c2961f8Sjose borrego case TRANS2_OPEN2: 16592c2961f8Sjose borrego rc = smb_com_trans2_open2(sr, xa); 16602c2961f8Sjose borrego break; 16612c2961f8Sjose borrego 1662da6c28aaSamw case TRANS2_CREATE_DIRECTORY: 1663da6c28aaSamw rc = smb_com_trans2_create_directory(sr, xa); 1664da6c28aaSamw break; 1665da6c28aaSamw 1666da6c28aaSamw case TRANS2_FIND_FIRST2: 1667da6c28aaSamw /* 1668da6c28aaSamw * Should have enough room to send the response 1669da6c28aaSamw * data back to client. 1670da6c28aaSamw */ 1671da6c28aaSamw if (n_data == 0) { 1672dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1673da6c28aaSamw ERRDOS, ERROR_BAD_LENGTH); 1674faa1795aSjb150015 return (SDRC_ERROR); 1675da6c28aaSamw } 1676da6c28aaSamw rc = smb_com_trans2_find_first2(sr, xa); 1677da6c28aaSamw break; 1678da6c28aaSamw 1679da6c28aaSamw case TRANS2_FIND_NEXT2: 1680da6c28aaSamw /* 1681da6c28aaSamw * Should have enough room to send the response 1682da6c28aaSamw * data back to client. 1683da6c28aaSamw */ 1684da6c28aaSamw if (n_data == 0) { 1685dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1686da6c28aaSamw ERRDOS, ERROR_BAD_LENGTH); 1687faa1795aSjb150015 return (SDRC_ERROR); 1688da6c28aaSamw } 1689da6c28aaSamw rc = smb_com_trans2_find_next2(sr, xa); 1690da6c28aaSamw break; 1691da6c28aaSamw 1692da6c28aaSamw case TRANS2_QUERY_FS_INFORMATION: 1693da6c28aaSamw /* 1694da6c28aaSamw * Should have enough room to send the response 1695da6c28aaSamw * data back to client. 1696da6c28aaSamw */ 1697da6c28aaSamw if (n_data == 0) { 1698dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1699da6c28aaSamw ERRDOS, ERROR_BAD_LENGTH); 1700faa1795aSjb150015 return (SDRC_ERROR); 1701da6c28aaSamw } 1702da6c28aaSamw rc = smb_com_trans2_query_fs_information(sr, xa); 1703da6c28aaSamw break; 1704da6c28aaSamw 1705da6c28aaSamw case TRANS2_QUERY_PATH_INFORMATION: 1706da6c28aaSamw /* 1707da6c28aaSamw * Should have enough room to send the response 1708da6c28aaSamw * data back to client. 1709da6c28aaSamw */ 1710da6c28aaSamw if (n_data == 0) { 1711dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1712da6c28aaSamw ERRDOS, ERROR_BAD_LENGTH); 1713faa1795aSjb150015 return (SDRC_ERROR); 1714da6c28aaSamw } 1715da6c28aaSamw rc = smb_com_trans2_query_path_information(sr, xa); 1716da6c28aaSamw break; 1717da6c28aaSamw 1718da6c28aaSamw case TRANS2_QUERY_FILE_INFORMATION: 1719da6c28aaSamw /* 1720da6c28aaSamw * Should have enough room to send the response 1721da6c28aaSamw * data back to client. 1722da6c28aaSamw */ 1723da6c28aaSamw if (n_data == 0) { 1724dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1725da6c28aaSamw ERRDOS, ERROR_BAD_LENGTH); 1726faa1795aSjb150015 return (SDRC_ERROR); 1727da6c28aaSamw } 1728da6c28aaSamw rc = smb_com_trans2_query_file_information(sr, xa); 1729da6c28aaSamw break; 1730da6c28aaSamw 1731da6c28aaSamw case TRANS2_SET_PATH_INFORMATION: 1732da6c28aaSamw rc = smb_com_trans2_set_path_information(sr, xa); 1733da6c28aaSamw break; 1734da6c28aaSamw 1735da6c28aaSamw case TRANS2_SET_FILE_INFORMATION: 1736da6c28aaSamw rc = smb_com_trans2_set_file_information(sr, xa); 1737da6c28aaSamw break; 1738da6c28aaSamw default: 17392c2961f8Sjose borrego (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 1740da6c28aaSamw goto trans_err_not_supported; 1741da6c28aaSamw } 1742da6c28aaSamw 1743da6c28aaSamw switch (rc) { 1744faa1795aSjb150015 case SDRC_SUCCESS: 1745da6c28aaSamw break; 1746da6c28aaSamw 1747da6c28aaSamw case SDRC_DROP_VC: 1748da6c28aaSamw case SDRC_NO_REPLY: 1749faa1795aSjb150015 case SDRC_ERROR: 1750da6c28aaSamw return (rc); 1751da6c28aaSamw 1752faa1795aSjb150015 case SDRC_NOT_IMPLEMENTED: 1753da6c28aaSamw goto trans_err_not_supported; 1754da6c28aaSamw 1755da6c28aaSamw default: 1756da6c28aaSamw break; 1757da6c28aaSamw } 1758da6c28aaSamw 1759da6c28aaSamw n_setup = MBC_LENGTH(&xa->rep_setup_mb); 1760da6c28aaSamw n_param = MBC_LENGTH(&xa->rep_param_mb); 1761da6c28aaSamw n_data = MBC_LENGTH(&xa->rep_data_mb); 1762da6c28aaSamw 1763da6c28aaSamw if (xa->smb_msrcnt < n_setup || 1764da6c28aaSamw xa->smb_mprcnt < n_param || 1765da6c28aaSamw xa->smb_mdrcnt < n_data) { 1766da6c28aaSamw goto trans_err_too_small; 1767da6c28aaSamw } 1768da6c28aaSamw 1769da6c28aaSamw /* neato, blast it over there */ 1770da6c28aaSamw 1771da6c28aaSamw n_setup = (n_setup + 1) / 2; /* Conver to setup words */ 1772da6c28aaSamw param_pad = 1; /* must be one */ 1773da6c28aaSamw param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 1774da6c28aaSamw 1775da6c28aaSamw /* 1776da6c28aaSamw * Including the nt_unknown_secret value persuades netmon to 1777da6c28aaSamw * display the correct data format for QueryPathInfo and 1778da6c28aaSamw * QueryFileInfo. 1779da6c28aaSamw */ 1780da6c28aaSamw if (opcode == TRANS2_QUERY_FILE_INFORMATION || 1781da6c28aaSamw opcode == TRANS2_QUERY_PATH_INFORMATION) { 1782da6c28aaSamw data_pad = sizeof (uint16_t); 1783da6c28aaSamw data_off = param_off + n_param + data_pad; 1784da6c28aaSamw fmt = "bww2.wwwwwwb.Cw#.CwC"; 1785da6c28aaSamw nt_unknown_secret = 0x0100; 1786da6c28aaSamw } 1787da6c28aaSamw else 1788da6c28aaSamw { 1789da6c28aaSamw data_pad = (param_off + n_param) & 1; /* Pad to short */ 1790da6c28aaSamw /* Param off from hdr start */ 1791da6c28aaSamw data_off = param_off + n_param + data_pad; 1792da6c28aaSamw fmt = "bww2.wwwwwwb.Cw#.C#.C"; 1793da6c28aaSamw /*LINTED E_ASSIGN_NARROW_CONV*/ 1794da6c28aaSamw nt_unknown_secret = data_pad; 1795da6c28aaSamw } 1796da6c28aaSamw 1797da6c28aaSamw total_bytes = param_pad + n_param + data_pad + n_data; 1798da6c28aaSamw 17997b59d02dSjb150015 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, 1800da6c28aaSamw fmt, 1801da6c28aaSamw 10 + n_setup, /* wct */ 1802da6c28aaSamw n_param, /* Total Parameter Bytes */ 1803da6c28aaSamw n_data /* + data_pad */, /* Total Data Bytes */ 1804da6c28aaSamw n_param, /* Total Parameter Bytes this buffer */ 1805da6c28aaSamw param_off, /* Param offset from header start */ 1806da6c28aaSamw 0, /* Param displacement */ 1807da6c28aaSamw n_data /* + data_pad */, /* Total Data Bytes this buffer */ 1808da6c28aaSamw data_off, /* Data offset from header start */ 1809da6c28aaSamw 0, /* Data displacement */ 1810da6c28aaSamw n_setup, /* suwcnt */ 1811da6c28aaSamw &xa->rep_setup_mb, /* setup[] */ 1812da6c28aaSamw total_bytes, /* Total data bytes */ 1813da6c28aaSamw param_pad, 1814da6c28aaSamw &xa->rep_param_mb, 1815da6c28aaSamw nt_unknown_secret, 1816da6c28aaSamw &xa->rep_data_mb); 1817faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1818da6c28aaSamw 1819da6c28aaSamw trans_err_too_small: 1820da6c28aaSamw rc = NERR_BufTooSmall; 1821da6c28aaSamw goto trans_err; 1822da6c28aaSamw 1823da6c28aaSamw trans_err_not_supported: 1824da6c28aaSamw rc = ERROR_NOT_SUPPORTED; 1825da6c28aaSamw goto trans_err; 1826da6c28aaSamw 1827da6c28aaSamw trans_err: 1828da6c28aaSamw pos = MBC_LENGTH(&sr->reply) + 23; 18297b59d02dSjb150015 rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www", 1830da6c28aaSamw 10, /* wct */ 1831da6c28aaSamw 4, 0, /* tpscnt tdscnt */ 1832da6c28aaSamw 4, pos, 0, /* pscnt psoff psdisp */ 1833da6c28aaSamw 0, 0, 0, /* dscnt dsoff dsdisp */ 1834da6c28aaSamw 0, /* suwcnt */ 1835da6c28aaSamw 4, /* bcc */ 1836da6c28aaSamw rc, 1837da6c28aaSamw 0); /* converter word? */ 1838faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1839da6c28aaSamw } 1840da6c28aaSamw 1841da6c28aaSamw smb_xa_t * 1842da6c28aaSamw smb_xa_create( 1843da6c28aaSamw smb_session_t *session, 1844da6c28aaSamw smb_request_t *sr, 1845da6c28aaSamw uint32_t total_parameter_count, 1846da6c28aaSamw uint32_t total_data_count, 1847da6c28aaSamw uint32_t max_parameter_count, 1848da6c28aaSamw uint32_t max_data_count, 1849da6c28aaSamw uint32_t max_setup_count, 1850da6c28aaSamw uint32_t setup_word_count) 1851da6c28aaSamw { 1852da6c28aaSamw smb_xa_t *xa, *nxa; 1853da6c28aaSamw smb_llist_t *xlist; 1854da6c28aaSamw 1855*bbf6f00cSJordan Brown xa = kmem_zalloc(sizeof (smb_xa_t), KM_SLEEP); 1856da6c28aaSamw xa->xa_refcnt = 1; 1857da6c28aaSamw xa->smb_com = sr->smb_com; 1858da6c28aaSamw xa->smb_flg = sr->smb_flg; 1859da6c28aaSamw xa->smb_flg2 = sr->smb_flg2; 1860da6c28aaSamw xa->smb_tid = sr->smb_tid; 1861da6c28aaSamw xa->smb_pid = sr->smb_pid; 1862da6c28aaSamw xa->smb_uid = sr->smb_uid; 1863da6c28aaSamw xa->xa_smb_mid = sr->smb_mid; 1864da6c28aaSamw xa->reply_seqnum = sr->reply_seqnum; 1865da6c28aaSamw xa->smb_tpscnt = total_parameter_count; 1866da6c28aaSamw xa->smb_tdscnt = total_data_count; 1867da6c28aaSamw xa->smb_mprcnt = max_parameter_count; 1868da6c28aaSamw xa->smb_mdrcnt = max_data_count; 1869da6c28aaSamw xa->smb_msrcnt = max_setup_count; 1870da6c28aaSamw xa->smb_suwcnt = setup_word_count; 1871da6c28aaSamw xa->xa_session = session; 1872da6c28aaSamw xa->xa_magic = SMB_XA_MAGIC; 1873da6c28aaSamw 1874da6c28aaSamw /* 1875da6c28aaSamw * The new xa structure is checked against the current list to see 1876da6c28aaSamw * if it exists already. 1877da6c28aaSamw */ 1878da6c28aaSamw xlist = &session->s_xa_list; 1879da6c28aaSamw smb_llist_enter(xlist, RW_WRITER); 1880da6c28aaSamw nxa = smb_llist_head(xlist); 1881da6c28aaSamw while (nxa) { 1882da6c28aaSamw ASSERT(nxa->xa_magic == SMB_XA_MAGIC); 1883da6c28aaSamw if (nxa->xa_smb_mid == xa->xa_smb_mid && 1884da6c28aaSamw nxa->smb_pid == xa->smb_pid && 1885da6c28aaSamw !SMB_XA_CLOSED(nxa) && 1886da6c28aaSamw !(nxa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 1887da6c28aaSamw smb_llist_exit(xlist); 1888*bbf6f00cSJordan Brown kmem_free(xa, sizeof (smb_xa_t)); 1889da6c28aaSamw return (NULL); 1890da6c28aaSamw } 1891da6c28aaSamw nxa = smb_llist_next(xlist, nxa); 1892da6c28aaSamw } 1893da6c28aaSamw smb_llist_insert_tail(xlist, xa); 1894da6c28aaSamw smb_llist_exit(xlist); 1895da6c28aaSamw return (xa); 1896da6c28aaSamw } 1897da6c28aaSamw 1898da6c28aaSamw void 1899da6c28aaSamw smb_xa_delete(smb_xa_t *xa) 1900da6c28aaSamw { 1901da6c28aaSamw ASSERT(xa->xa_refcnt == 0); 1902da6c28aaSamw ASSERT(SMB_XA_CLOSED(xa)); 1903da6c28aaSamw 1904*bbf6f00cSJordan Brown if (xa->xa_pipe_name) 1905*bbf6f00cSJordan Brown smb_mfree(xa->xa_pipe_name); 1906da6c28aaSamw 1907da6c28aaSamw if (xa->rep_setup_mb.chain != NULL) 1908da6c28aaSamw m_freem(xa->rep_setup_mb.chain); 1909da6c28aaSamw if (xa->rep_param_mb.chain != NULL) 1910da6c28aaSamw m_freem(xa->rep_param_mb.chain); 1911da6c28aaSamw if (xa->rep_data_mb.chain != NULL) 1912da6c28aaSamw m_freem(xa->rep_data_mb.chain); 1913da6c28aaSamw 1914da6c28aaSamw xa->xa_magic = (uint32_t)~SMB_XA_MAGIC; 1915*bbf6f00cSJordan Brown kmem_free(xa, sizeof (smb_xa_t)); 1916da6c28aaSamw } 1917da6c28aaSamw 1918da6c28aaSamw smb_xa_t * 1919da6c28aaSamw smb_xa_hold(smb_xa_t *xa) 1920da6c28aaSamw { 1921da6c28aaSamw mutex_enter(&xa->xa_mutex); 1922da6c28aaSamw xa->xa_refcnt++; 1923da6c28aaSamw ASSERT(xa->xa_refcnt); 1924da6c28aaSamw mutex_exit(&xa->xa_mutex); 1925da6c28aaSamw return (xa); 1926da6c28aaSamw } 1927da6c28aaSamw 1928da6c28aaSamw void 1929da6c28aaSamw smb_xa_rele(smb_session_t *session, smb_xa_t *xa) 1930da6c28aaSamw { 1931da6c28aaSamw mutex_enter(&xa->xa_mutex); 1932da6c28aaSamw ASSERT(xa->xa_refcnt); 1933da6c28aaSamw xa->xa_refcnt--; 1934da6c28aaSamw if (SMB_XA_CLOSED(xa) && (xa->xa_refcnt == 0)) { 1935da6c28aaSamw mutex_exit(&xa->xa_mutex); 1936da6c28aaSamw smb_llist_enter(&session->s_xa_list, RW_WRITER); 1937da6c28aaSamw smb_llist_remove(&session->s_xa_list, xa); 1938da6c28aaSamw smb_llist_exit(&session->s_xa_list); 1939da6c28aaSamw smb_xa_delete(xa); 1940da6c28aaSamw return; 1941da6c28aaSamw } 1942da6c28aaSamw mutex_exit(&xa->xa_mutex); 1943da6c28aaSamw } 1944da6c28aaSamw 1945da6c28aaSamw int 1946da6c28aaSamw smb_xa_open(smb_xa_t *xa) 1947da6c28aaSamw { 1948da6c28aaSamw int rc; 1949da6c28aaSamw 1950da6c28aaSamw mutex_enter(&xa->xa_mutex); 1951da6c28aaSamw 1952da6c28aaSamw ASSERT((xa->xa_flags & SMB_XA_FLAG_OPEN) == 0); 1953da6c28aaSamw 1954da6c28aaSamw if ((xa->xa_flags & SMB_XA_FLAG_CLOSE) == 0) { 1955da6c28aaSamw xa->xa_flags |= SMB_XA_FLAG_OPEN; 1956da6c28aaSamw rc = 0; 1957da6c28aaSamw } else { 1958da6c28aaSamw rc = ERROR_INVALID_HANDLE; 1959da6c28aaSamw } 1960da6c28aaSamw 1961da6c28aaSamw mutex_exit(&xa->xa_mutex); 1962da6c28aaSamw 1963da6c28aaSamw return (rc); 1964da6c28aaSamw } 1965da6c28aaSamw 1966da6c28aaSamw void 1967da6c28aaSamw smb_xa_close(smb_xa_t *xa) 1968da6c28aaSamw { 1969da6c28aaSamw mutex_enter(&xa->xa_mutex); 1970da6c28aaSamw xa->xa_flags |= SMB_XA_FLAG_CLOSE; 1971da6c28aaSamw xa->xa_flags &= ~SMB_XA_FLAG_OPEN; 1972da6c28aaSamw 1973da6c28aaSamw if (xa->xa_refcnt == 0) { 1974da6c28aaSamw mutex_exit(&xa->xa_mutex); 1975da6c28aaSamw smb_llist_enter(&xa->xa_session->s_xa_list, RW_WRITER); 1976da6c28aaSamw smb_llist_remove(&xa->xa_session->s_xa_list, xa); 1977da6c28aaSamw smb_llist_exit(&xa->xa_session->s_xa_list); 1978da6c28aaSamw smb_xa_delete(xa); 1979da6c28aaSamw return; 1980da6c28aaSamw } 1981da6c28aaSamw 1982da6c28aaSamw mutex_exit(&xa->xa_mutex); 1983da6c28aaSamw } 1984da6c28aaSamw 1985da6c28aaSamw int 1986da6c28aaSamw smb_xa_complete(smb_xa_t *xa) 1987da6c28aaSamw { 1988da6c28aaSamw int rc; 1989da6c28aaSamw 1990da6c28aaSamw mutex_enter(&xa->xa_mutex); 1991da6c28aaSamw if (xa->xa_flags & (SMB_XA_FLAG_COMPLETE | SMB_XA_FLAG_CLOSE)) { 1992da6c28aaSamw rc = 0; 1993da6c28aaSamw } else { 1994da6c28aaSamw rc = 1; 1995da6c28aaSamw xa->xa_flags |= SMB_XA_FLAG_COMPLETE; 1996da6c28aaSamw } 1997da6c28aaSamw mutex_exit(&xa->xa_mutex); 1998da6c28aaSamw return (rc); 1999da6c28aaSamw } 2000da6c28aaSamw 2001da6c28aaSamw smb_xa_t * 2002da6c28aaSamw smb_xa_find( 2003da6c28aaSamw smb_session_t *session, 2004da6c28aaSamw uint16_t pid, 2005da6c28aaSamw uint16_t mid) 2006da6c28aaSamw { 2007da6c28aaSamw smb_xa_t *xa; 2008da6c28aaSamw smb_llist_t *xlist; 2009da6c28aaSamw 2010da6c28aaSamw xlist = &session->s_xa_list; 2011da6c28aaSamw smb_llist_enter(xlist, RW_READER); 2012da6c28aaSamw xa = smb_llist_head(xlist); 2013da6c28aaSamw while (xa) { 2014da6c28aaSamw mutex_enter(&xa->xa_mutex); 2015da6c28aaSamw if (xa->xa_smb_mid == mid && 2016da6c28aaSamw xa->smb_pid == pid && 2017da6c28aaSamw !SMB_XA_CLOSED(xa) && 2018da6c28aaSamw !(xa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 2019da6c28aaSamw xa->xa_refcnt++; 2020da6c28aaSamw ASSERT(xa->xa_refcnt); 2021da6c28aaSamw mutex_exit(&xa->xa_mutex); 2022da6c28aaSamw break; 2023da6c28aaSamw } 2024da6c28aaSamw mutex_exit(&xa->xa_mutex); 2025da6c28aaSamw xa = smb_llist_next(xlist, xa); 2026da6c28aaSamw } 2027da6c28aaSamw smb_llist_exit(xlist); 2028da6c28aaSamw return (xa); 2029da6c28aaSamw } 2030