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