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