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