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