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 sr->sr_cfg->skc_version.sv_major, sr->sr_cfg->skc_version.sv_minor, 1011 MBC_LENGTH(&str_mb)); 1012 (void) smb_mbc_encodef(&str_mb, "s", domain); 1013 (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 1014 (void) smb_mbc_encodef(&str_mb, "s", domain); 1015 1016 (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 0, 1017 -MBC_LENGTH(&xa->rep_data_mb), 1018 MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb)); 1019 (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb); 1020 m_freem(str_mb.chain); 1021 return (SDRC_SUCCESS); 1022 } 1023 1024 int 1025 smb_trans_net_user_getinfo(struct smb_request *sr, struct smb_xa *xa) 1026 { 1027 uint16_t level, max_bytes; 1028 unsigned char *user; 1029 int rc; 1030 1031 rc = smb_mbc_decodef(&xa->req_param_mb, "%sww", sr, 1032 &user, 1033 &level, 1034 &max_bytes); 1035 1036 if (rc != 0) 1037 return (SDRC_NOT_IMPLEMENTED); 1038 1039 (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 1040 NERR_UserNotFound, 0, 0); 1041 return (SDRC_SUCCESS); 1042 } 1043 1044 smb_sdrc_t 1045 smb_trans_net_server_getinfo(struct smb_request *sr, struct smb_xa *xa) 1046 { 1047 uint16_t level, buf_size; 1048 uint16_t avail_data, max_data; 1049 char server_name[16]; 1050 struct mbuf_chain str_mb; 1051 1052 if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level, &buf_size) != 0) 1053 return (SDRC_ERROR); 1054 1055 max_data = MBC_MAXBYTES(&xa->rep_data_mb); 1056 1057 MBC_INIT(&str_mb, buf_size); 1058 1059 bzero(server_name, sizeof (server_name)); 1060 (void) strncpy(server_name, sr->sr_cfg->skc_hostname, 1061 sizeof (server_name)); 1062 1063 /* valid levels are 0 and 1 */ 1064 switch (level) { 1065 case 0: 1066 (void) smb_mbc_encodef(&xa->rep_data_mb, "16c", server_name); 1067 break; 1068 1069 case 1: 1070 (void) smb_mbc_encodef(&str_mb, "s", 1071 sr->sr_cfg->skc_system_comment); 1072 (void) smb_mbc_encodef(&xa->rep_data_mb, "16cbbll", server_name, 1073 sr->sr_cfg->skc_version.sv_major, 1074 sr->sr_cfg->skc_version.sv_minor, 1075 MY_SERVER_TYPE, max_data - MBC_LENGTH(&str_mb)); 1076 break; 1077 1078 default: 1079 (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 1080 ERROR_INVALID_LEVEL, 0, 0); 1081 m_freem(str_mb.chain); 1082 return (SDRC_SUCCESS); 1083 } 1084 1085 avail_data = MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb); 1086 (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 1087 NERR_Success, max_data - avail_data, avail_data); 1088 (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb); 1089 m_freem(str_mb.chain); 1090 return (SDRC_SUCCESS); 1091 } 1092 1093 /* 1094 * 6.4 The NetServerEnum2 RAP Service 1095 * 1096 * The NetServerEnum2 RAP service lists all computers of the specified type 1097 * or types that are visible in the specified domains. It may also 1098 * enumerate domains. 1099 * 1100 * The following definition uses the notation and terminology defined in 1101 * the CIFS Remote Administration Protocol specification, which is required 1102 * in order to make it well-defined. The definition is: 1103 * 1104 * uint16_t NetServerEnum2 ( 1105 * uint16_t sLevel, 1106 * RCVBUF pbBuffer, 1107 * RCVBUFLEN cbBuffer, 1108 * ENTCOUNT pcEntriesRead, 1109 * uint16_t *pcTotalAvail, 1110 * uint32_t fServerType, 1111 * char *pszDomain, 1112 * ); 1113 * 1114 * where: 1115 * 1116 * sLevel specifies the level of detail (0 or 1) requested. 1117 * 1118 * pbBuffer points to the buffer to receive the returned data. If the 1119 * function is successful, the buffer contains a sequence of 1120 * server_info_x structures, where x is 0 or 1, depending on the 1121 * level of detail requested. 1122 * 1123 * cbBuffer specifies the size, in bytes, of the buffer pointed to by 1124 * the pbBuffer parameter. 1125 * 1126 * pcEntriesRead points to a 16 bit variable that receives a count of 1127 * the number of servers enumerated in the buffer. This count is 1128 * valid only if NetServerEnum2 returns the NERR_Success or 1129 * ERROR_MORE_DATA values. 1130 * 1131 * pcTotal Avail points to a 16 bit variable that receives a count of 1132 * the total number of available entries. This count is valid only if 1133 * NetServerEnum2 returns the NERR_Success or ERROR_MORE_DATA values. 1134 * 1135 * fServerType specifies the type or types of computers to enumerate. 1136 * Computers that match at least one of the specified types are 1137 * returned in the buffer. Possible values are defined in the request 1138 * parameters section. 1139 * 1140 * pszDomain points to a null-terminated string that contains the 1141 * name of the workgroup in which to enumerate computers of the 1142 * specified type or types. If the pszDomain parameter is a null 1143 * string or a null pointer, servers are enumerated for the current 1144 * domain of the computer. 1145 * 1146 * 6.4.1 Transaction Request Parameters section 1147 * 1148 * The Transaction request parameters section in this instance contains: 1149 * . The 16 bit function number for NetServerEnum2 which is 104. 1150 * . The parameter descriptor string which is "WrLehDz". 1151 * . The data descriptor string for the (returned) data which is "B16" for 1152 * level detail 0 or "B16BBDz" for level detail 1. 1153 * . The actual parameters as described by the parameter descriptor 1154 * string. 1155 * 1156 * The parameters are: 1157 * . A 16 bit integer with a value of 0 or 1 (corresponding to the "W" in 1158 * the parameter descriptor string. This represents the level of detail 1159 * the server is expected to return 1160 * . A 16 bit integer that contains the size of the receive buffer. 1161 * . A 32 bit integer that represents the type of servers the function 1162 * should enumerate. The possible values may be any of the following or 1163 * a combination of the following: 1164 * 1165 * SV_TYPE_WORKSTATION 0x00000001 All workstations 1166 * SV_TYPE_SERVER 0x00000002 All servers 1167 * SV_TYPE_SQLSERVER 0x00000004 Any server running with SQL 1168 * server 1169 * SV_TYPE_DOMAIN_CTRL 0x00000008 Primary domain controller 1170 * SV_TYPE_DOMAIN_BAKCTRL 0x00000010 Backup domain controller 1171 * SV_TYPE_TIME_SOURCE 0x00000020 Server running the timesource 1172 * service 1173 * SV_TYPE_AFP 0x00000040 Apple File Protocol servers 1174 * SV_TYPE_NOVELL 0x00000080 Novell servers 1175 * SV_TYPE_DOMAIN_MEMBER 0x00000100 Domain Member 1176 * SV_TYPE_PRINTQ_SERVER 0x00000200 Server sharing print queue 1177 * SV_TYPE_DIALIN_SERVER 0x00000400 Server running dialin service. 1178 * SV_TYPE_XENIX_SERVER 0x00000800 Xenix server 1179 * SV_TYPE_NT 0x00001000 NT server 1180 * SV_TYPE_WFW 0x00002000 Server running Windows for 1181 * Workgroups 1182 * SV_TYPE_SERVER_NT 0x00008000 Windows NT non DC server 1183 * SV_TYPE_POTENTIAL_BROWSER 0x00010000 Server that can run the browser 1184 * service 1185 * SV_TYPE_BACKUP_BROWSER 0x00020000 Backup browser server 1186 * SV_TYPE_MASTER_BROWSER 0x00040000 Master browser server 1187 * SV_TYPE_DOMAIN_MASTER 0x00080000 Domain Master Browser server 1188 * SV_TYPE_LOCAL_LIST_ONLY 0x40000000 Enumerate only entries marked 1189 * "local" 1190 * SV_TYPE_DOMAIN_ENUM 0x80000000 Enumerate Domains. The pszDomain 1191 * parameter must be NULL. 1192 * 1193 * . A null terminated ASCII string representing the pszDomain parameter 1194 * described above 1195 * 1196 * 6.4.2 Transaction Request Data section 1197 * 1198 * There is no data or auxiliary data to send as part of the request. 1199 * 1200 * 6.4.3 Transaction Response Parameters section 1201 * 1202 * The transaction response parameters section consists of: 1203 * . A 16 bit word indicating the return status. The possible values are: 1204 * 1205 * Code Value Description 1206 * NERR_Success 0 No errors encountered 1207 * ERROR_MORE_DATA 234 Additional data is available 1208 * NERR_ServerNotStarted 2114 The RAP service on the remote computer 1209 * is not running 1210 * NERR_BadTransactConfig 2141 The server is not configured for 1211 * transactions, IPC$ is not shared 1212 * 1213 * . A 16 bit "converter" word. 1214 * . A 16 bit number representing the number of entries returned. 1215 * . A 16 bit number representing the total number of available entries. 1216 * If the supplied buffer is large enough, this will equal the number of 1217 * entries returned. 1218 * 1219 * 6.4.4 Transaction Response Data section 1220 * 1221 * The return data section consists of a number of SERVER_INFO_1 structures. 1222 * The number of such structures present is determined by the third entry 1223 * (described above) in the return parameters section. 1224 * 1225 * At level detail 0, the Transaction response data section contains a 1226 * number of SERVER_INFO_0 data structure. The number of such structures is 1227 * equal to the 16 bit number returned by the server in the third parameter 1228 * in the Transaction response parameter section. The SERVER_INFO_0 data 1229 * structure is defined as: 1230 * 1231 * struct SERVER_INFO_0 { 1232 * char sv0_name[16]; 1233 * }; 1234 * 1235 * where: 1236 * 1237 * sv0_name is a null-terminated string that specifies the name of a 1238 * computer or domain . 1239 * 1240 * At level detail 1, the Transaction response data section contains a 1241 * number of SERVER_INFO_1 data structure. The number of such structures is 1242 * equal to the 16 bit number returned by the server in the third parameter 1243 * in the Transaction response parameter section. The SERVER_INFO_1 data 1244 * structure is defined as: 1245 * 1246 * struct SERVER_INFO_1 { 1247 * char sv1_name[16]; 1248 * char sv1_version_major; 1249 * char sv1_version_minor; 1250 * uint32_t sv1_type; 1251 * char *sv1_comment_or_master_browser; 1252 * }; 1253 * 1254 * sv1_name contains a null-terminated string that specifies the name 1255 * of a computer, or a domain name if SV_TYPE_DOMAIN_ENUM is set in 1256 * sv1_type. 1257 * 1258 * sv1_version_major whatever was specified in the HostAnnouncement 1259 * or DomainAnnouncement frame with which the entry was registered. 1260 * 1261 * sv1_version_minor whatever was specified in the HostAnnouncement 1262 * or DomainAnnouncement frame with which the entry was registered. 1263 * 1264 * sv1_type specifies the type of software the computer is running. 1265 * The member can be one or a combination of the values defined above 1266 * in the Transaction request parameters section for fServerType. 1267 * 1268 * 1269 * sv1_comment_or_master_browser points to a null-terminated string. If 1270 * the sv1_type indicates that the entry is for a domain, this 1271 * specifies the name of server running the domain master browser; 1272 * otherwise, it specifies a comment describing the server. The comment 1273 * can be a null string or the pointer may be a null pointer. 1274 * 1275 * In case there are multiple SERVER_INFO_1 data structures to 1276 * return, the server may put all these fixed length structures in 1277 * the return buffer, leave some space and then put all the variable 1278 * length data (the actual value of the sv1_comment strings) at the 1279 * end of the buffer. 1280 * 1281 * There is no auxiliary data to receive. 1282 */ 1283 1284 int 1285 smb_trans_net_server_enum2(struct smb_request *sr, struct smb_xa *xa) 1286 { 1287 uint16_t opcode, level, max_bytes; 1288 uint32_t server_type; 1289 unsigned char *domain; 1290 struct mbuf_chain str_mb; 1291 char *hostname, *s; 1292 smb_kmod_cfg_t *si; 1293 1294 if (smb_mbc_decodef(&xa->req_param_mb, 1295 "%wsswwls", sr, &opcode, &s, &s, 1296 &level, &max_bytes, &server_type, &domain) != 0) 1297 return (SDRC_NOT_IMPLEMENTED); 1298 1299 si = sr->sr_cfg; 1300 1301 if (smb_strcasecmp(si->skc_nbdomain, (char *)domain, 0) != 0) { 1302 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0); 1303 return (SDRC_SUCCESS); 1304 } 1305 1306 if ((server_type & MY_SERVER_TYPE) == 0) { 1307 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0); 1308 return (SDRC_SUCCESS); 1309 } 1310 1311 MBC_INIT(&str_mb, max_bytes); 1312 1313 hostname = si->skc_hostname; 1314 1315 (void) smb_mbc_encodef(&xa->rep_data_mb, "16c", hostname); 1316 if (level == 1) { 1317 (void) smb_mbc_encodef(&xa->rep_data_mb, "bbll", 1318 sr->sr_cfg->skc_version.sv_major, 1319 sr->sr_cfg->skc_version.sv_minor, 1320 MY_SERVER_TYPE, MBC_LENGTH(&str_mb)); 1321 (void) smb_mbc_encodef(&str_mb, "s", si->skc_system_comment); 1322 } 1323 1324 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 1325 -MBC_LENGTH(&xa->rep_data_mb), 1, 1); 1326 (void) smb_mbc_encodef(&xa->rep_data_mb, "m", str_mb.chain); 1327 return (SDRC_SUCCESS); 1328 } 1329 1330 static boolean_t 1331 is_supported_mailslot(const char *mailslot) 1332 { 1333 static char *mailslots[] = { 1334 PIPE_LANMAN, 1335 MAILSLOT_LANMAN, 1336 MAILSLOT_BROWSE, 1337 MAILSLOT_MSBROWSE 1338 }; 1339 1340 int i; 1341 1342 for (i = 0; i < sizeof (mailslots)/sizeof (mailslots[0]); ++i) 1343 if (smb_strcasecmp(mailslot, mailslots[i], 0) == 0) 1344 return (B_TRUE); 1345 1346 return (B_FALSE); 1347 } 1348 1349 /* 1350 * Currently, just return false if the pipe is \\PIPE\repl. 1351 * Otherwise, return true. 1352 */ 1353 static boolean_t 1354 is_supported_pipe(const char *pname) 1355 { 1356 if (smb_strcasecmp(pname, PIPE_REPL, 0) == 0) 1357 return (B_FALSE); 1358 1359 return (B_TRUE); 1360 } 1361 1362 static smb_sdrc_t 1363 smb_trans_dispatch(smb_request_t *sr, smb_xa_t *xa) 1364 { 1365 int rc, pos; 1366 int total_bytes, n_setup, n_param, n_data; 1367 int param_off, param_pad, data_off, data_pad; 1368 uint16_t opcode; 1369 uint16_t devstate; 1370 char *req_fmt; 1371 char *rep_fmt; 1372 smb_vdb_t vdb; 1373 1374 n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200; 1375 n_setup++; 1376 n_setup = n_setup & ~0x0001; 1377 n_param = (xa->smb_mprcnt < smb_maxbufsize) 1378 ? xa->smb_mprcnt : smb_maxbufsize; 1379 n_param++; 1380 n_param = n_param & ~0x0001; 1381 rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param); 1382 n_data = (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc; 1383 MBC_INIT(&xa->rep_setup_mb, n_setup * 2); 1384 MBC_INIT(&xa->rep_param_mb, n_param); 1385 MBC_INIT(&xa->rep_data_mb, n_data); 1386 1387 if (xa->smb_suwcnt > 0 && STYPE_ISIPC(sr->tid_tree->t_res_type)) { 1388 rc = smb_mbc_decodef(&xa->req_setup_mb, "ww", &opcode, 1389 &sr->smb_fid); 1390 if (rc != 0) 1391 goto trans_err_not_supported; 1392 switch (opcode) { 1393 case TRANS_SET_NMPIPE_STATE: 1394 if ((rc = smb_mbc_decodef(&xa->req_param_mb, "w", 1395 &devstate)) != 0) 1396 goto trans_err_not_supported; 1397 1398 rc = SDRC_SUCCESS; 1399 break; 1400 1401 case TRANS_TRANSACT_NMPIPE: 1402 smbsr_lookup_file(sr); 1403 if (sr->fid_ofile == NULL) { 1404 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 1405 ERRDOS, ERRbadfid); 1406 return (SDRC_ERROR); 1407 } 1408 1409 rc = smb_mbc_decodef(&xa->req_data_mb, "#B", 1410 xa->smb_tdscnt, &vdb); 1411 if (rc != 0) 1412 goto trans_err_not_supported; 1413 1414 rc = smb_opipe_transact(sr, &vdb.vdb_uio); 1415 break; 1416 1417 case TRANS_WAIT_NMPIPE: 1418 if (!is_supported_pipe(xa->xa_pipe_name)) { 1419 smbsr_error(sr, 0, ERRDOS, ERRbadfile); 1420 return (SDRC_ERROR); 1421 } 1422 rc = SDRC_SUCCESS; 1423 break; 1424 1425 default: 1426 goto trans_err_not_supported; 1427 } 1428 } else { 1429 if (!is_supported_mailslot(xa->xa_pipe_name)) 1430 goto trans_err_not_supported; 1431 1432 if ((rc = smb_mbc_decodef(&xa->req_param_mb, "%wss", sr, 1433 &opcode, &req_fmt, &rep_fmt)) != 0) 1434 goto trans_err_not_supported; 1435 1436 switch (opcode) { 1437 case API_WshareEnum: 1438 rc = smb_trans_net_share_enum(sr, xa); 1439 break; 1440 1441 case API_WshareGetInfo: 1442 rc = smb_trans_net_share_getinfo(sr, xa); 1443 break; 1444 1445 case API_WserverGetInfo: 1446 rc = smb_trans_net_server_getinfo(sr, xa); 1447 break; 1448 1449 case API_WUserGetInfo: 1450 rc = smb_trans_net_user_getinfo(sr, xa); 1451 break; 1452 1453 case API_WWkstaGetInfo: 1454 rc = smb_trans_net_workstation_getinfo(sr, xa); 1455 break; 1456 1457 case API_NetServerEnum2: 1458 rc = smb_trans_net_server_enum2(sr, xa); 1459 break; 1460 1461 default: 1462 goto trans_err_not_supported; 1463 } 1464 } 1465 1466 switch (rc) { 1467 case SDRC_SUCCESS: 1468 break; 1469 1470 case SDRC_DROP_VC: 1471 case SDRC_NO_REPLY: 1472 case SDRC_ERROR: 1473 return (rc); 1474 1475 case SDRC_NOT_IMPLEMENTED: 1476 goto trans_err_not_supported; 1477 1478 default: 1479 break; 1480 } 1481 1482 n_setup = MBC_LENGTH(&xa->rep_setup_mb); 1483 n_param = MBC_LENGTH(&xa->rep_param_mb); 1484 n_data = MBC_LENGTH(&xa->rep_data_mb); 1485 1486 if (xa->smb_msrcnt < n_setup || 1487 xa->smb_mprcnt < n_param || 1488 xa->smb_mdrcnt < n_data) { 1489 goto trans_err_too_small; 1490 } 1491 1492 /* neato, blast it over there */ 1493 1494 n_setup = (n_setup + 1) / 2; /* Convert to setup words */ 1495 param_pad = 1; /* always one */ 1496 param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 1497 data_pad = (param_off + n_param) & 1; /* Pad to short */ 1498 /* Param off from hdr start */ 1499 data_off = param_off + n_param + data_pad; 1500 total_bytes = param_pad + n_param + data_pad + n_data; 1501 1502 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, 1503 "bww2.wwwwwwb.Cw#.C#.C", 1504 10 + n_setup, /* wct */ 1505 n_param, /* Total Parameter Bytes */ 1506 n_data, /* Total Data Bytes */ 1507 n_param, /* Total Parameter Bytes this buffer */ 1508 param_off, /* Param offset from header start */ 1509 0, /* Param displacement */ 1510 n_data, /* Total Data Bytes this buffer */ 1511 data_off, /* Data offset from header start */ 1512 0, /* Data displacement */ 1513 n_setup, /* suwcnt */ 1514 &xa->rep_setup_mb, /* setup[] */ 1515 total_bytes, /* Total data bytes */ 1516 param_pad, 1517 &xa->rep_param_mb, 1518 data_pad, 1519 &xa->rep_data_mb); 1520 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1521 1522 trans_err_too_small: 1523 rc = NERR_BufTooSmall; 1524 goto trans_err; 1525 1526 trans_err_not_supported: 1527 rc = ERROR_NOT_SUPPORTED; 1528 goto trans_err; 1529 1530 trans_err: 1531 pos = MBC_LENGTH(&sr->reply) + 23; 1532 rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www", 1533 10, /* wct */ 1534 4, 0, /* tpscnt tdscnt */ 1535 4, pos, 0, /* pscnt psoff psdisp */ 1536 0, 0, 0, /* dscnt dsoff dsdisp */ 1537 0, /* suwcnt */ 1538 4, /* bcc */ 1539 rc, 1540 0); /* converter word? */ 1541 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1542 } 1543 1544 static smb_sdrc_t 1545 smb_trans2_dispatch(smb_request_t *sr, smb_xa_t *xa) 1546 { 1547 int rc, pos; 1548 int total_bytes, n_setup, n_param, n_data; 1549 int param_off, param_pad, data_off, data_pad; 1550 uint16_t opcode; 1551 uint16_t nt_unknown_secret = 0x0100; 1552 char *fmt; 1553 1554 n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200; 1555 n_setup++; 1556 n_setup = n_setup & ~0x0001; 1557 n_param = (xa->smb_mprcnt < smb_maxbufsize) 1558 ? xa->smb_mprcnt : smb_maxbufsize; 1559 n_param++; 1560 n_param = n_param & ~0x0001; 1561 rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param); 1562 n_data = (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc; 1563 MBC_INIT(&xa->rep_setup_mb, n_setup * 2); 1564 MBC_INIT(&xa->rep_param_mb, n_param); 1565 MBC_INIT(&xa->rep_data_mb, n_data); 1566 1567 if (smb_mbc_decodef(&xa->req_setup_mb, "w", &opcode) != 0) 1568 goto trans_err_not_supported; 1569 1570 /* 1571 * Save this for /proc to read later. 1572 */ 1573 xa->smb_func = opcode; 1574 1575 /* for now, only respond to the */ 1576 switch (opcode) { 1577 case TRANS2_OPEN2: 1578 rc = smb_com_trans2_open2(sr, xa); 1579 break; 1580 1581 case TRANS2_CREATE_DIRECTORY: 1582 rc = smb_com_trans2_create_directory(sr, xa); 1583 break; 1584 1585 case TRANS2_FIND_FIRST2: 1586 /* 1587 * Should have enough room to send the response 1588 * data back to client. 1589 */ 1590 if (n_data == 0) { 1591 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1592 ERRDOS, ERROR_BAD_LENGTH); 1593 return (SDRC_ERROR); 1594 } 1595 rc = smb_com_trans2_find_first2(sr, xa); 1596 break; 1597 1598 case TRANS2_FIND_NEXT2: 1599 /* 1600 * Should have enough room to send the response 1601 * data back to client. 1602 */ 1603 if (n_data == 0) { 1604 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1605 ERRDOS, ERROR_BAD_LENGTH); 1606 return (SDRC_ERROR); 1607 } 1608 rc = smb_com_trans2_find_next2(sr, xa); 1609 break; 1610 1611 case TRANS2_QUERY_FS_INFORMATION: 1612 /* 1613 * Should have enough room to send the response 1614 * data back to client. 1615 */ 1616 if (n_data == 0) { 1617 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1618 ERRDOS, ERROR_BAD_LENGTH); 1619 return (SDRC_ERROR); 1620 } 1621 rc = smb_com_trans2_query_fs_information(sr, xa); 1622 break; 1623 1624 case TRANS2_SET_FS_INFORMATION: 1625 rc = smb_com_trans2_set_fs_information(sr, xa); 1626 break; 1627 1628 case TRANS2_QUERY_PATH_INFORMATION: 1629 /* 1630 * Should have enough room to send the response 1631 * data back to client. 1632 */ 1633 if (n_data == 0) { 1634 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1635 ERRDOS, ERROR_BAD_LENGTH); 1636 return (SDRC_ERROR); 1637 } 1638 rc = smb_com_trans2_query_path_information(sr, xa); 1639 break; 1640 1641 case TRANS2_QUERY_FILE_INFORMATION: 1642 /* 1643 * Should have enough room to send the response 1644 * data back to client. 1645 */ 1646 if (n_data == 0) { 1647 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1648 ERRDOS, ERROR_BAD_LENGTH); 1649 return (SDRC_ERROR); 1650 } 1651 rc = smb_com_trans2_query_file_information(sr, xa); 1652 break; 1653 1654 case TRANS2_SET_PATH_INFORMATION: 1655 rc = smb_com_trans2_set_path_information(sr, xa); 1656 break; 1657 1658 case TRANS2_SET_FILE_INFORMATION: 1659 rc = smb_com_trans2_set_file_information(sr, xa); 1660 break; 1661 1662 case TRANS2_GET_DFS_REFERRAL: 1663 rc = smb_com_trans2_get_dfs_referral(sr, xa); 1664 break; 1665 1666 default: 1667 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 1668 goto trans_err_not_supported; 1669 } 1670 1671 switch (rc) { 1672 case SDRC_SUCCESS: 1673 break; 1674 1675 case SDRC_DROP_VC: 1676 case SDRC_NO_REPLY: 1677 case SDRC_ERROR: 1678 return (rc); 1679 1680 case SDRC_NOT_IMPLEMENTED: 1681 goto trans_err_not_supported; 1682 1683 default: 1684 break; 1685 } 1686 1687 n_setup = MBC_LENGTH(&xa->rep_setup_mb); 1688 n_param = MBC_LENGTH(&xa->rep_param_mb); 1689 n_data = MBC_LENGTH(&xa->rep_data_mb); 1690 1691 if (xa->smb_msrcnt < n_setup || 1692 xa->smb_mprcnt < n_param || 1693 xa->smb_mdrcnt < n_data) { 1694 goto trans_err_too_small; 1695 } 1696 1697 /* neato, blast it over there */ 1698 1699 n_setup = (n_setup + 1) / 2; /* Conver to setup words */ 1700 param_pad = 1; /* must be one */ 1701 param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 1702 1703 /* 1704 * Including the nt_unknown_secret value persuades netmon to 1705 * display the correct data format for QueryPathInfo and 1706 * QueryFileInfo. 1707 */ 1708 if (opcode == TRANS2_QUERY_FILE_INFORMATION || 1709 opcode == TRANS2_QUERY_PATH_INFORMATION) { 1710 data_pad = sizeof (uint16_t); 1711 data_off = param_off + n_param + data_pad; 1712 fmt = "bww2.wwwwwwb.Cw#.CwC"; 1713 nt_unknown_secret = 0x0100; 1714 } 1715 else 1716 { 1717 data_pad = (param_off + n_param) & 1; /* Pad to short */ 1718 /* Param off from hdr start */ 1719 data_off = param_off + n_param + data_pad; 1720 fmt = "bww2.wwwwwwb.Cw#.C#.C"; 1721 /*LINTED E_ASSIGN_NARROW_CONV*/ 1722 nt_unknown_secret = data_pad; 1723 } 1724 1725 total_bytes = param_pad + n_param + data_pad + n_data; 1726 1727 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, 1728 fmt, 1729 10 + n_setup, /* wct */ 1730 n_param, /* Total Parameter Bytes */ 1731 n_data /* + data_pad */, /* Total Data Bytes */ 1732 n_param, /* Total Parameter Bytes this buffer */ 1733 param_off, /* Param offset from header start */ 1734 0, /* Param displacement */ 1735 n_data /* + data_pad */, /* Total Data Bytes this buffer */ 1736 data_off, /* Data offset from header start */ 1737 0, /* Data displacement */ 1738 n_setup, /* suwcnt */ 1739 &xa->rep_setup_mb, /* setup[] */ 1740 total_bytes, /* Total data bytes */ 1741 param_pad, 1742 &xa->rep_param_mb, 1743 nt_unknown_secret, 1744 &xa->rep_data_mb); 1745 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1746 1747 trans_err_too_small: 1748 rc = NERR_BufTooSmall; 1749 goto trans_err; 1750 1751 trans_err_not_supported: 1752 rc = ERROR_NOT_SUPPORTED; 1753 goto trans_err; 1754 1755 trans_err: 1756 pos = MBC_LENGTH(&sr->reply) + 23; 1757 rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www", 1758 10, /* wct */ 1759 4, 0, /* tpscnt tdscnt */ 1760 4, pos, 0, /* pscnt psoff psdisp */ 1761 0, 0, 0, /* dscnt dsoff dsdisp */ 1762 0, /* suwcnt */ 1763 4, /* bcc */ 1764 rc, 1765 0); /* converter word? */ 1766 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1767 } 1768 1769 smb_xa_t * 1770 smb_xa_create( 1771 smb_session_t *session, 1772 smb_request_t *sr, 1773 uint32_t total_parameter_count, 1774 uint32_t total_data_count, 1775 uint32_t max_parameter_count, 1776 uint32_t max_data_count, 1777 uint32_t max_setup_count, 1778 uint32_t setup_word_count) 1779 { 1780 smb_xa_t *xa, *nxa; 1781 smb_llist_t *xlist; 1782 1783 xa = kmem_zalloc(sizeof (smb_xa_t), KM_SLEEP); 1784 xa->xa_refcnt = 1; 1785 xa->smb_com = sr->smb_com; 1786 xa->smb_flg = sr->smb_flg; 1787 xa->smb_flg2 = sr->smb_flg2; 1788 xa->smb_tid = sr->smb_tid; 1789 xa->smb_pid = sr->smb_pid; 1790 xa->smb_uid = sr->smb_uid; 1791 xa->xa_smb_mid = sr->smb_mid; 1792 xa->reply_seqnum = sr->reply_seqnum; 1793 xa->smb_tpscnt = total_parameter_count; 1794 xa->smb_tdscnt = total_data_count; 1795 xa->smb_mprcnt = max_parameter_count; 1796 xa->smb_mdrcnt = max_data_count; 1797 xa->smb_msrcnt = max_setup_count; 1798 xa->smb_suwcnt = setup_word_count; 1799 xa->xa_session = session; 1800 xa->xa_magic = SMB_XA_MAGIC; 1801 1802 /* 1803 * The new xa structure is checked against the current list to see 1804 * if it exists already. 1805 */ 1806 xlist = &session->s_xa_list; 1807 smb_llist_enter(xlist, RW_WRITER); 1808 nxa = smb_llist_head(xlist); 1809 while (nxa) { 1810 ASSERT(nxa->xa_magic == SMB_XA_MAGIC); 1811 if (nxa->xa_smb_mid == xa->xa_smb_mid && 1812 nxa->smb_pid == xa->smb_pid && 1813 !SMB_XA_CLOSED(nxa) && 1814 !(nxa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 1815 smb_llist_exit(xlist); 1816 kmem_free(xa, sizeof (smb_xa_t)); 1817 return (NULL); 1818 } 1819 nxa = smb_llist_next(xlist, nxa); 1820 } 1821 smb_llist_insert_tail(xlist, xa); 1822 smb_llist_exit(xlist); 1823 return (xa); 1824 } 1825 1826 void 1827 smb_xa_delete(smb_xa_t *xa) 1828 { 1829 ASSERT(xa->xa_refcnt == 0); 1830 ASSERT(SMB_XA_CLOSED(xa)); 1831 1832 if (xa->xa_pipe_name) 1833 smb_mem_free(xa->xa_pipe_name); 1834 1835 if (xa->rep_setup_mb.chain != NULL) 1836 m_freem(xa->rep_setup_mb.chain); 1837 if (xa->rep_param_mb.chain != NULL) 1838 m_freem(xa->rep_param_mb.chain); 1839 if (xa->rep_data_mb.chain != NULL) 1840 m_freem(xa->rep_data_mb.chain); 1841 1842 xa->xa_magic = (uint32_t)~SMB_XA_MAGIC; 1843 kmem_free(xa, sizeof (smb_xa_t)); 1844 } 1845 1846 smb_xa_t * 1847 smb_xa_hold(smb_xa_t *xa) 1848 { 1849 mutex_enter(&xa->xa_mutex); 1850 xa->xa_refcnt++; 1851 ASSERT(xa->xa_refcnt); 1852 mutex_exit(&xa->xa_mutex); 1853 return (xa); 1854 } 1855 1856 void 1857 smb_xa_rele(smb_session_t *session, smb_xa_t *xa) 1858 { 1859 mutex_enter(&xa->xa_mutex); 1860 ASSERT(xa->xa_refcnt); 1861 xa->xa_refcnt--; 1862 if (SMB_XA_CLOSED(xa) && (xa->xa_refcnt == 0)) { 1863 mutex_exit(&xa->xa_mutex); 1864 smb_llist_enter(&session->s_xa_list, RW_WRITER); 1865 smb_llist_remove(&session->s_xa_list, xa); 1866 smb_llist_exit(&session->s_xa_list); 1867 smb_xa_delete(xa); 1868 return; 1869 } 1870 mutex_exit(&xa->xa_mutex); 1871 } 1872 1873 int 1874 smb_xa_open(smb_xa_t *xa) 1875 { 1876 int rc; 1877 1878 mutex_enter(&xa->xa_mutex); 1879 1880 ASSERT((xa->xa_flags & SMB_XA_FLAG_OPEN) == 0); 1881 1882 if ((xa->xa_flags & SMB_XA_FLAG_CLOSE) == 0) { 1883 xa->xa_flags |= SMB_XA_FLAG_OPEN; 1884 rc = 0; 1885 } else { 1886 rc = ERROR_INVALID_HANDLE; 1887 } 1888 1889 mutex_exit(&xa->xa_mutex); 1890 1891 return (rc); 1892 } 1893 1894 void 1895 smb_xa_close(smb_xa_t *xa) 1896 { 1897 mutex_enter(&xa->xa_mutex); 1898 xa->xa_flags |= SMB_XA_FLAG_CLOSE; 1899 xa->xa_flags &= ~SMB_XA_FLAG_OPEN; 1900 1901 if (xa->xa_refcnt == 0) { 1902 mutex_exit(&xa->xa_mutex); 1903 smb_llist_enter(&xa->xa_session->s_xa_list, RW_WRITER); 1904 smb_llist_remove(&xa->xa_session->s_xa_list, xa); 1905 smb_llist_exit(&xa->xa_session->s_xa_list); 1906 smb_xa_delete(xa); 1907 return; 1908 } 1909 1910 mutex_exit(&xa->xa_mutex); 1911 } 1912 1913 int 1914 smb_xa_complete(smb_xa_t *xa) 1915 { 1916 int rc; 1917 1918 mutex_enter(&xa->xa_mutex); 1919 if (xa->xa_flags & (SMB_XA_FLAG_COMPLETE | SMB_XA_FLAG_CLOSE)) { 1920 rc = 0; 1921 } else { 1922 rc = 1; 1923 xa->xa_flags |= SMB_XA_FLAG_COMPLETE; 1924 } 1925 mutex_exit(&xa->xa_mutex); 1926 return (rc); 1927 } 1928 1929 smb_xa_t * 1930 smb_xa_find( 1931 smb_session_t *session, 1932 uint16_t pid, 1933 uint16_t mid) 1934 { 1935 smb_xa_t *xa; 1936 smb_llist_t *xlist; 1937 1938 xlist = &session->s_xa_list; 1939 smb_llist_enter(xlist, RW_READER); 1940 xa = smb_llist_head(xlist); 1941 while (xa) { 1942 mutex_enter(&xa->xa_mutex); 1943 if (xa->xa_smb_mid == mid && 1944 xa->smb_pid == pid && 1945 !SMB_XA_CLOSED(xa) && 1946 !(xa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 1947 xa->xa_refcnt++; 1948 ASSERT(xa->xa_refcnt); 1949 mutex_exit(&xa->xa_mutex); 1950 break; 1951 } 1952 mutex_exit(&xa->xa_mutex); 1953 xa = smb_llist_next(xlist, xa); 1954 } 1955 smb_llist_exit(xlist); 1956 return (xa); 1957 } 1958