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