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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <smbsrv/smb_incl.h> 27 #include <smbsrv/smb_fsops.h> 28 #include <smbsrv/smb_share.h> 29 #include <smbsrv/oem.h> 30 #include <smbsrv/nmpipes.h> 31 #include <smbsrv/mailslot.h> 32 #include <smbsrv/lmerr.h> 33 #include <smbsrv/nterror.h> 34 35 /* 36 * count of bytes in server response packet 37 * except parameters and data. Note that setup 38 * word count is zero. 39 */ 40 #define RESP_HEADER_LEN 24 41 42 /* 43 * NB. I started by using common functions for transaction/transaction2 44 * and transaction_secondary/transaction2_secondary because they 45 * are respectively so similar. However, it turned out to be a bad 46 * idea because of quirky differences. Be sure if you modify one 47 * of these four functions to check and see if the modification should 48 * be applied to its peer. 49 */ 50 51 static int smb_trans_ready(struct smb_xa *); 52 static smb_sdrc_t smb_trans_dispatch(struct smb_request *, struct smb_xa *); 53 static smb_sdrc_t smb_trans2_dispatch(struct smb_request *, struct smb_xa *); 54 static smb_sdrc_t smb_nt_transact_query_quota(struct smb_request *, 55 struct smb_xa *); 56 57 smb_sdrc_t 58 smb_pre_transaction(smb_request_t *sr) 59 { 60 DTRACE_SMB_1(op__Transaction__start, smb_request_t *, sr); 61 return (SDRC_SUCCESS); 62 } 63 64 void 65 smb_post_transaction(smb_request_t *sr) 66 { 67 DTRACE_SMB_1(op__Transaction__done, smb_request_t *, sr); 68 } 69 70 smb_sdrc_t 71 smb_com_transaction(smb_request_t *sr) 72 { 73 int rc; 74 unsigned char msrcnt, suwcnt; 75 uint16_t tpscnt, tdscnt, mprcnt, mdrcnt, flags; 76 uint16_t pscnt, psoff, dscnt, dsoff; 77 uint32_t timeo; 78 struct smb_xa *xa; 79 char *stn; 80 int ready; 81 82 rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, 83 &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &msrcnt, &flags, 84 &timeo, &pscnt, &psoff, &dscnt, &dsoff, &suwcnt); 85 86 if (rc != 0) 87 return (SDRC_ERROR); 88 89 xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, 90 msrcnt, suwcnt); 91 if (xa == NULL) { 92 smbsr_error(sr, 0, ERRSRV, ERRnoroom); 93 return (SDRC_ERROR); 94 } 95 96 /* Should be some alignment stuff here in SMB? */ 97 if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) { 98 rc = smbsr_decode_data(sr, "%.U", sr, &stn); 99 } else { 100 rc = smbsr_decode_data(sr, "%s", sr, &stn); 101 } 102 if (rc != 0) { 103 smb_xa_rele(sr->session, xa); 104 return (SDRC_ERROR); 105 } 106 xa->xa_smb_trans_name = MEM_STRDUP("smb", stn); 107 108 xa->smb_flags = flags; 109 xa->smb_timeout = timeo; 110 xa->req_disp_param = pscnt; 111 xa->req_disp_data = dscnt; 112 113 if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv, 114 sr->smb_vwv.chain_offset, suwcnt * 2)) { 115 smb_xa_rele(sr->session, xa); 116 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 117 return (SDRC_ERROR); 118 } 119 if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 120 smb_xa_rele(sr->session, xa); 121 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 122 return (SDRC_ERROR); 123 } 124 if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 125 smb_xa_rele(sr->session, xa); 126 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 127 return (SDRC_ERROR); 128 } 129 130 ready = smb_trans_ready(xa); 131 132 if (smb_xa_open(xa)) { 133 smb_xa_rele(sr->session, xa); 134 smbsr_error(sr, 0, ERRDOS, ERRsrverror); 135 return (SDRC_ERROR); 136 } 137 sr->r_xa = xa; 138 139 if (!ready) { 140 rc = smbsr_encode_empty_result(sr); 141 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 142 } 143 144 if (!smb_xa_complete(xa)) { 145 smb_xa_close(xa); 146 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 147 return (SDRC_ERROR); 148 } 149 150 return (smb_trans_dispatch(sr, xa)); 151 } 152 153 smb_sdrc_t 154 smb_pre_transaction_secondary(smb_request_t *sr) 155 { 156 DTRACE_SMB_1(op__TransactionSecondary__start, smb_request_t *, sr); 157 return (SDRC_SUCCESS); 158 } 159 160 void 161 smb_post_transaction_secondary(smb_request_t *sr) 162 { 163 DTRACE_SMB_1(op__TransactionSecondary__done, smb_request_t *, sr); 164 } 165 166 smb_sdrc_t 167 smb_com_transaction_secondary(smb_request_t *sr) 168 { 169 uint16_t tpscnt, tdscnt, pscnt, psdisp; 170 uint16_t dscnt, dsoff, dsdisp, psoff; 171 smb_xa_t *xa; 172 int rc; 173 174 if ((xa = smbsr_lookup_xa(sr)) == 0) { 175 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 176 return (SDRC_ERROR); 177 } 178 179 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 180 if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { 181 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 182 ERRDOS, ERRnoaccess); 183 return (SDRC_ERROR); 184 } 185 } 186 187 if (xa->smb_com != SMB_COM_TRANSACTION) { 188 return (SDRC_DROP_VC); 189 } 190 191 rc = smbsr_decode_vwv(sr, SMB_TRANSSHDR_ED_FMT, &tpscnt, &tdscnt, 192 &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp); 193 194 if (rc != 0) 195 return (SDRC_ERROR); 196 197 mutex_enter(&xa->xa_mutex); 198 xa->smb_tpscnt = tpscnt; /* might have shrunk */ 199 xa->smb_tdscnt = tdscnt; /* might have shrunk */ 200 xa->req_disp_param = psdisp+pscnt; 201 xa->req_disp_data = dsdisp+dscnt; 202 203 if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 204 mutex_exit(&xa->xa_mutex); 205 smb_xa_close(xa); 206 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 207 return (SDRC_ERROR); 208 } 209 if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 210 mutex_exit(&xa->xa_mutex); 211 smb_xa_close(xa); 212 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 213 return (SDRC_ERROR); 214 } 215 mutex_exit(&xa->xa_mutex); 216 217 if (!smb_trans_ready(xa)) 218 return (SDRC_NO_REPLY); 219 220 if (!smb_xa_complete(xa)) 221 return (SDRC_NO_REPLY); 222 223 return (smb_trans_dispatch(sr, xa)); 224 } 225 226 smb_sdrc_t 227 smb_pre_ioctl(smb_request_t *sr) 228 { 229 DTRACE_SMB_1(op__Ioctl__start, smb_request_t *, sr); 230 return (SDRC_SUCCESS); 231 } 232 233 void 234 smb_post_ioctl(smb_request_t *sr) 235 { 236 DTRACE_SMB_1(op__Ioctl__done, smb_request_t *, sr); 237 } 238 239 smb_sdrc_t 240 smb_com_ioctl(smb_request_t *sr) 241 { 242 uint16_t fid, category, function, tpscnt, tdscnt, mprcnt; 243 uint16_t mdrcnt, pscnt, pdoff, dscnt, dsoff; 244 uint32_t timeout; 245 int rc; 246 247 rc = smbsr_decode_vwv(sr, "wwwwwwwl2.wwww", &fid, &category, &function, 248 &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &timeout, &pscnt, 249 &pdoff, &dscnt, &dsoff); 250 251 if (rc != 0) 252 return (SDRC_ERROR); 253 254 return (SDRC_NOT_IMPLEMENTED); 255 } 256 257 smb_sdrc_t 258 smb_pre_transaction2(smb_request_t *sr) 259 { 260 DTRACE_SMB_1(op__Transaction2__start, smb_request_t *, sr); 261 return (SDRC_SUCCESS); 262 } 263 264 void 265 smb_post_transaction2(smb_request_t *sr) 266 { 267 DTRACE_SMB_1(op__Transaction2__done, smb_request_t *, sr); 268 } 269 270 smb_sdrc_t 271 smb_com_transaction2(struct smb_request *sr) 272 { 273 unsigned char msrcnt, suwcnt; 274 uint16_t tpscnt, tdscnt, mprcnt, mdrcnt, flags; 275 uint16_t pscnt, psoff, dscnt, dsoff; 276 uint32_t timeo; 277 smb_xa_t *xa; 278 int ready; 279 int rc; 280 281 rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, &tpscnt, &tdscnt, 282 &mprcnt, &mdrcnt, &msrcnt, &flags, &timeo, &pscnt, &psoff, &dscnt, 283 &dsoff, &suwcnt); 284 285 if (rc != 0) 286 return (SDRC_ERROR); 287 288 xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, 289 msrcnt, suwcnt); 290 if (xa == 0) { 291 smbsr_error(sr, 0, ERRSRV, ERRnoroom); 292 return (SDRC_ERROR); 293 } 294 295 xa->smb_flags = flags; 296 xa->smb_timeout = timeo; 297 xa->req_disp_param = pscnt; 298 xa->req_disp_data = dscnt; 299 300 if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv, 301 sr->smb_vwv.chain_offset, suwcnt*2)) { 302 smb_xa_rele(sr->session, xa); 303 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 304 return (SDRC_ERROR); 305 } 306 if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 307 smb_xa_rele(sr->session, xa); 308 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 309 return (SDRC_ERROR); 310 } 311 if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 312 smb_xa_rele(sr->session, xa); 313 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 314 return (SDRC_ERROR); 315 } 316 317 ready = smb_trans_ready(xa); 318 319 if (smb_xa_open(xa)) { 320 smb_xa_rele(sr->session, xa); 321 smbsr_error(sr, 0, ERRDOS, ERRsrverror); 322 return (SDRC_ERROR); 323 } 324 sr->r_xa = xa; 325 326 if (!ready) { 327 rc = smbsr_encode_empty_result(sr); 328 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 329 } 330 331 if (!smb_xa_complete(xa)) { 332 smb_xa_close(xa); 333 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 334 return (SDRC_ERROR); 335 } 336 337 return (smb_trans2_dispatch(sr, xa)); 338 } 339 340 smb_sdrc_t 341 smb_pre_transaction2_secondary(smb_request_t *sr) 342 { 343 DTRACE_SMB_1(op__Transaction2Secondary__start, smb_request_t *, sr); 344 return (SDRC_SUCCESS); 345 } 346 347 void 348 smb_post_transaction2_secondary(smb_request_t *sr) 349 { 350 DTRACE_SMB_1(op__Transaction2Secondary__done, smb_request_t *, sr); 351 } 352 353 smb_sdrc_t 354 smb_com_transaction2_secondary(smb_request_t *sr) 355 { 356 uint16_t tpscnt, tdscnt, fid; 357 uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp; 358 smb_xa_t *xa; 359 int rc; 360 361 if ((xa = smbsr_lookup_xa(sr)) == 0) { 362 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 363 return (SDRC_ERROR); 364 } 365 366 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 367 if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { 368 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 369 ERRDOS, ERRnoaccess); 370 return (SDRC_ERROR); 371 } 372 } 373 374 if (xa->smb_com != SMB_COM_TRANSACTION2) { 375 return (SDRC_DROP_VC); 376 } 377 378 rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt, 379 &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid); 380 381 if (rc != 0) 382 return (SDRC_ERROR); 383 384 mutex_enter(&xa->xa_mutex); 385 xa->smb_tpscnt = tpscnt; /* might have shrunk */ 386 xa->smb_tdscnt = tdscnt; /* might have shrunk */ 387 xa->xa_smb_fid = fid; /* overwrite rules? */ 388 xa->req_disp_param = psdisp + pscnt; 389 xa->req_disp_data = dsdisp + dscnt; 390 391 if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 392 mutex_exit(&xa->xa_mutex); 393 smb_xa_close(xa); 394 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 395 return (SDRC_ERROR); 396 } 397 if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 398 mutex_exit(&xa->xa_mutex); 399 smb_xa_close(xa); 400 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 401 return (SDRC_ERROR); 402 } 403 mutex_exit(&xa->xa_mutex); 404 405 if (!smb_trans_ready(xa)) 406 return (SDRC_NO_REPLY); 407 408 if (!smb_xa_complete(xa)) 409 return (SDRC_NO_REPLY); 410 411 return (smb_trans2_dispatch(sr, xa)); 412 } 413 414 static smb_sdrc_t 415 smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) 416 { 417 int rc; 418 int total_bytes, n_setup, n_param, n_data; 419 int param_off, param_pad, data_off, data_pad; 420 421 n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200; 422 n_setup++; 423 n_setup = n_setup & ~0x0001; 424 n_param = (xa->smb_mprcnt < smb_maxbufsize) 425 ? xa->smb_mprcnt : smb_maxbufsize; 426 n_param++; 427 n_param = n_param & ~0x0001; 428 rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param); 429 n_data = (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc; 430 MBC_INIT(&xa->rep_setup_mb, n_setup * 2); 431 MBC_INIT(&xa->rep_param_mb, n_param); 432 MBC_INIT(&xa->rep_data_mb, n_data); 433 434 switch (xa->smb_func) { 435 case NT_TRANSACT_CREATE: 436 if ((rc = smb_pre_nt_transact_create(sr, xa)) == 0) 437 rc = smb_nt_transact_create(sr, xa); 438 smb_post_nt_transact_create(sr, xa); 439 break; 440 case NT_TRANSACT_NOTIFY_CHANGE: 441 rc = smb_nt_transact_notify_change(sr, xa); 442 break; 443 case NT_TRANSACT_QUERY_SECURITY_DESC: 444 rc = smb_nt_transact_query_security_info(sr, xa); 445 break; 446 case NT_TRANSACT_SET_SECURITY_DESC: 447 rc = smb_nt_transact_set_security_info(sr, xa); 448 break; 449 case NT_TRANSACT_IOCTL: 450 rc = smb_nt_transact_ioctl(sr, xa); 451 break; 452 453 case NT_TRANSACT_QUERY_QUOTA: 454 (void) smb_nt_transact_query_quota(sr, xa); 455 smbsr_error(sr, 0, ERRSRV, ERRaccess); 456 return (SDRC_ERROR); 457 458 case NT_TRANSACT_SET_QUOTA: 459 smbsr_error(sr, 0, ERRSRV, ERRaccess); 460 return (SDRC_ERROR); 461 462 default: 463 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); 464 return (SDRC_ERROR); 465 } 466 467 switch (rc) { 468 case SDRC_SUCCESS: 469 break; 470 471 case SDRC_DROP_VC: 472 case SDRC_NO_REPLY: 473 case SDRC_ERROR: 474 case SDRC_SR_KEPT: 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 smb_vdb_t 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 smbsr_lookup_file(sr); 1406 if (sr->fid_ofile == NULL) { 1407 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 1408 ERRDOS, ERRbadfid); 1409 return (SDRC_ERROR); 1410 } 1411 1412 rc = smb_mbc_decodef(&xa->req_data_mb, "#B", 1413 xa->smb_tdscnt, &vdb); 1414 if (rc != 0) 1415 goto trans_err_not_supported; 1416 1417 rc = smb_opipe_transact(sr, &vdb.vdb_uio); 1418 break; 1419 1420 case TRANS_WAIT_NMPIPE: 1421 if (is_supported_pipe(xa->xa_smb_trans_name) == 0) { 1422 smbsr_error(sr, 0, ERRDOS, ERRbadfile); 1423 return (SDRC_ERROR); 1424 } 1425 rc = SDRC_SUCCESS; 1426 break; 1427 1428 default: 1429 goto trans_err_not_supported; 1430 } 1431 } else { 1432 if ((utf8_strcasecmp(xa->xa_smb_trans_name, 1433 PIPE_LANMAN) != 0) && 1434 (utf8_strcasecmp( 1435 xa->xa_smb_trans_name, MAILSLOT_LANMAN) != 0) && 1436 (utf8_strcasecmp( 1437 xa->xa_smb_trans_name, MAILSLOT_BROWSE) != 0) && 1438 (utf8_strcasecmp( 1439 xa->xa_smb_trans_name, MAILSLOT_MSBROWSE) != 0)) 1440 goto trans_err_not_supported; 1441 1442 if ((rc = smb_mbc_decodef(&xa->req_param_mb, "%wss", sr, 1443 &opcode, &req_fmt, &rep_fmt)) != 0) 1444 goto trans_err_not_supported; 1445 1446 switch (opcode) { 1447 case API_WshareEnum: 1448 rc = smb_trans_net_share_enum(sr, xa); 1449 break; 1450 1451 case API_WshareGetInfo: 1452 rc = smb_trans_net_share_getinfo(sr, xa); 1453 break; 1454 1455 case API_WserverGetInfo: 1456 rc = smb_trans_net_server_getinfo(sr, xa); 1457 break; 1458 1459 case API_WUserGetInfo: 1460 rc = smb_trans_net_user_getinfo(sr, xa); 1461 break; 1462 1463 case API_WWkstaGetInfo: 1464 rc = smb_trans_net_workstation_getinfo(sr, xa); 1465 break; 1466 1467 case API_NetServerEnum2: 1468 rc = smb_trans_net_server_enum2(sr, xa); 1469 break; 1470 1471 default: 1472 goto trans_err_not_supported; 1473 } 1474 } 1475 1476 switch (rc) { 1477 case SDRC_SUCCESS: 1478 break; 1479 1480 case SDRC_DROP_VC: 1481 case SDRC_NO_REPLY: 1482 case SDRC_ERROR: 1483 return (rc); 1484 1485 case SDRC_NOT_IMPLEMENTED: 1486 goto trans_err_not_supported; 1487 1488 default: 1489 break; 1490 } 1491 1492 n_setup = MBC_LENGTH(&xa->rep_setup_mb); 1493 n_param = MBC_LENGTH(&xa->rep_param_mb); 1494 n_data = MBC_LENGTH(&xa->rep_data_mb); 1495 1496 if (xa->smb_msrcnt < n_setup || 1497 xa->smb_mprcnt < n_param || 1498 xa->smb_mdrcnt < n_data) { 1499 goto trans_err_too_small; 1500 } 1501 1502 /* neato, blast it over there */ 1503 1504 n_setup = (n_setup + 1) / 2; /* Convert to setup words */ 1505 param_pad = 1; /* always one */ 1506 param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 1507 data_pad = (param_off + n_param) & 1; /* Pad to short */ 1508 /* Param off from hdr start */ 1509 data_off = param_off + n_param + data_pad; 1510 total_bytes = param_pad + n_param + data_pad + n_data; 1511 1512 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, 1513 "bww2.wwwwwwb.Cw#.C#.C", 1514 10 + n_setup, /* wct */ 1515 n_param, /* Total Parameter Bytes */ 1516 n_data, /* Total Data Bytes */ 1517 n_param, /* Total Parameter Bytes this buffer */ 1518 param_off, /* Param offset from header start */ 1519 0, /* Param displacement */ 1520 n_data, /* Total Data Bytes this buffer */ 1521 data_off, /* Data offset from header start */ 1522 0, /* Data displacement */ 1523 n_setup, /* suwcnt */ 1524 &xa->rep_setup_mb, /* setup[] */ 1525 total_bytes, /* Total data bytes */ 1526 param_pad, 1527 &xa->rep_param_mb, 1528 data_pad, 1529 &xa->rep_data_mb); 1530 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1531 1532 trans_err_too_small: 1533 rc = NERR_BufTooSmall; 1534 goto trans_err; 1535 1536 trans_err_not_supported: 1537 rc = ERROR_NOT_SUPPORTED; 1538 goto trans_err; 1539 1540 trans_err: 1541 pos = MBC_LENGTH(&sr->reply) + 23; 1542 rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www", 1543 10, /* wct */ 1544 4, 0, /* tpscnt tdscnt */ 1545 4, pos, 0, /* pscnt psoff psdisp */ 1546 0, 0, 0, /* dscnt dsoff dsdisp */ 1547 0, /* suwcnt */ 1548 4, /* bcc */ 1549 rc, 1550 0); /* converter word? */ 1551 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1552 } 1553 1554 static smb_sdrc_t 1555 smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) 1556 { 1557 int rc, pos; 1558 int total_bytes, n_setup, n_param, n_data; 1559 int param_off, param_pad, data_off, data_pad; 1560 uint16_t opcode; 1561 uint16_t nt_unknown_secret = 0x0100; 1562 char *fmt; 1563 1564 n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200; 1565 n_setup++; 1566 n_setup = n_setup & ~0x0001; 1567 n_param = (xa->smb_mprcnt < smb_maxbufsize) 1568 ? xa->smb_mprcnt : smb_maxbufsize; 1569 n_param++; 1570 n_param = n_param & ~0x0001; 1571 rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param); 1572 n_data = (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc; 1573 MBC_INIT(&xa->rep_setup_mb, n_setup * 2); 1574 MBC_INIT(&xa->rep_param_mb, n_param); 1575 MBC_INIT(&xa->rep_data_mb, n_data); 1576 1577 if (smb_mbc_decodef(&xa->req_setup_mb, "w", &opcode) != 0) 1578 goto trans_err_not_supported; 1579 1580 /* 1581 * Save this for /proc to read later. 1582 */ 1583 xa->smb_func = opcode; 1584 1585 /* for now, only respond to the */ 1586 switch (opcode) { 1587 case TRANS2_OPEN2: 1588 rc = smb_com_trans2_open2(sr, xa); 1589 break; 1590 1591 case TRANS2_CREATE_DIRECTORY: 1592 rc = smb_com_trans2_create_directory(sr, xa); 1593 break; 1594 1595 case TRANS2_FIND_FIRST2: 1596 /* 1597 * Should have enough room to send the response 1598 * data back to client. 1599 */ 1600 if (n_data == 0) { 1601 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1602 ERRDOS, ERROR_BAD_LENGTH); 1603 return (SDRC_ERROR); 1604 } 1605 rc = smb_com_trans2_find_first2(sr, xa); 1606 break; 1607 1608 case TRANS2_FIND_NEXT2: 1609 /* 1610 * Should have enough room to send the response 1611 * data back to client. 1612 */ 1613 if (n_data == 0) { 1614 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1615 ERRDOS, ERROR_BAD_LENGTH); 1616 return (SDRC_ERROR); 1617 } 1618 rc = smb_com_trans2_find_next2(sr, xa); 1619 break; 1620 1621 case TRANS2_QUERY_FS_INFORMATION: 1622 /* 1623 * Should have enough room to send the response 1624 * data back to client. 1625 */ 1626 if (n_data == 0) { 1627 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1628 ERRDOS, ERROR_BAD_LENGTH); 1629 return (SDRC_ERROR); 1630 } 1631 rc = smb_com_trans2_query_fs_information(sr, xa); 1632 break; 1633 1634 case TRANS2_QUERY_PATH_INFORMATION: 1635 /* 1636 * Should have enough room to send the response 1637 * data back to client. 1638 */ 1639 if (n_data == 0) { 1640 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1641 ERRDOS, ERROR_BAD_LENGTH); 1642 return (SDRC_ERROR); 1643 } 1644 rc = smb_com_trans2_query_path_information(sr, xa); 1645 break; 1646 1647 case TRANS2_QUERY_FILE_INFORMATION: 1648 /* 1649 * Should have enough room to send the response 1650 * data back to client. 1651 */ 1652 if (n_data == 0) { 1653 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 1654 ERRDOS, ERROR_BAD_LENGTH); 1655 return (SDRC_ERROR); 1656 } 1657 rc = smb_com_trans2_query_file_information(sr, xa); 1658 break; 1659 1660 case TRANS2_SET_PATH_INFORMATION: 1661 rc = smb_com_trans2_set_path_information(sr, xa); 1662 break; 1663 1664 case TRANS2_SET_FILE_INFORMATION: 1665 rc = smb_com_trans2_set_file_information(sr, xa); 1666 break; 1667 default: 1668 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0); 1669 goto trans_err_not_supported; 1670 } 1671 1672 switch (rc) { 1673 case SDRC_SUCCESS: 1674 break; 1675 1676 case SDRC_DROP_VC: 1677 case SDRC_NO_REPLY: 1678 case SDRC_ERROR: 1679 return (rc); 1680 1681 case SDRC_NOT_IMPLEMENTED: 1682 goto trans_err_not_supported; 1683 1684 default: 1685 break; 1686 } 1687 1688 n_setup = MBC_LENGTH(&xa->rep_setup_mb); 1689 n_param = MBC_LENGTH(&xa->rep_param_mb); 1690 n_data = MBC_LENGTH(&xa->rep_data_mb); 1691 1692 if (xa->smb_msrcnt < n_setup || 1693 xa->smb_mprcnt < n_param || 1694 xa->smb_mdrcnt < n_data) { 1695 goto trans_err_too_small; 1696 } 1697 1698 /* neato, blast it over there */ 1699 1700 n_setup = (n_setup + 1) / 2; /* Conver to setup words */ 1701 param_pad = 1; /* must be one */ 1702 param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 1703 1704 /* 1705 * Including the nt_unknown_secret value persuades netmon to 1706 * display the correct data format for QueryPathInfo and 1707 * QueryFileInfo. 1708 */ 1709 if (opcode == TRANS2_QUERY_FILE_INFORMATION || 1710 opcode == TRANS2_QUERY_PATH_INFORMATION) { 1711 data_pad = sizeof (uint16_t); 1712 data_off = param_off + n_param + data_pad; 1713 fmt = "bww2.wwwwwwb.Cw#.CwC"; 1714 nt_unknown_secret = 0x0100; 1715 } 1716 else 1717 { 1718 data_pad = (param_off + n_param) & 1; /* Pad to short */ 1719 /* Param off from hdr start */ 1720 data_off = param_off + n_param + data_pad; 1721 fmt = "bww2.wwwwwwb.Cw#.C#.C"; 1722 /*LINTED E_ASSIGN_NARROW_CONV*/ 1723 nt_unknown_secret = data_pad; 1724 } 1725 1726 total_bytes = param_pad + n_param + data_pad + n_data; 1727 1728 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, 1729 fmt, 1730 10 + n_setup, /* wct */ 1731 n_param, /* Total Parameter Bytes */ 1732 n_data /* + data_pad */, /* Total Data Bytes */ 1733 n_param, /* Total Parameter Bytes this buffer */ 1734 param_off, /* Param offset from header start */ 1735 0, /* Param displacement */ 1736 n_data /* + data_pad */, /* Total Data Bytes this buffer */ 1737 data_off, /* Data offset from header start */ 1738 0, /* Data displacement */ 1739 n_setup, /* suwcnt */ 1740 &xa->rep_setup_mb, /* setup[] */ 1741 total_bytes, /* Total data bytes */ 1742 param_pad, 1743 &xa->rep_param_mb, 1744 nt_unknown_secret, 1745 &xa->rep_data_mb); 1746 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1747 1748 trans_err_too_small: 1749 rc = NERR_BufTooSmall; 1750 goto trans_err; 1751 1752 trans_err_not_supported: 1753 rc = ERROR_NOT_SUPPORTED; 1754 goto trans_err; 1755 1756 trans_err: 1757 pos = MBC_LENGTH(&sr->reply) + 23; 1758 rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www", 1759 10, /* wct */ 1760 4, 0, /* tpscnt tdscnt */ 1761 4, pos, 0, /* pscnt psoff psdisp */ 1762 0, 0, 0, /* dscnt dsoff dsdisp */ 1763 0, /* suwcnt */ 1764 4, /* bcc */ 1765 rc, 1766 0); /* converter word? */ 1767 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 1768 } 1769 1770 smb_xa_t * 1771 smb_xa_create( 1772 smb_session_t *session, 1773 smb_request_t *sr, 1774 uint32_t total_parameter_count, 1775 uint32_t total_data_count, 1776 uint32_t max_parameter_count, 1777 uint32_t max_data_count, 1778 uint32_t max_setup_count, 1779 uint32_t setup_word_count) 1780 { 1781 smb_xa_t *xa, *nxa; 1782 smb_llist_t *xlist; 1783 1784 xa = MEM_ZALLOC("xa", sizeof (smb_xa_t)); 1785 xa->xa_refcnt = 1; 1786 xa->smb_com = sr->smb_com; 1787 xa->smb_flg = sr->smb_flg; 1788 xa->smb_flg2 = sr->smb_flg2; 1789 xa->smb_tid = sr->smb_tid; 1790 xa->smb_pid = sr->smb_pid; 1791 xa->smb_uid = sr->smb_uid; 1792 xa->xa_smb_mid = sr->smb_mid; 1793 xa->reply_seqnum = sr->reply_seqnum; 1794 xa->smb_tpscnt = total_parameter_count; 1795 xa->smb_tdscnt = total_data_count; 1796 xa->smb_mprcnt = max_parameter_count; 1797 xa->smb_mdrcnt = max_data_count; 1798 xa->smb_msrcnt = max_setup_count; 1799 xa->smb_suwcnt = setup_word_count; 1800 xa->xa_session = session; 1801 xa->xa_magic = SMB_XA_MAGIC; 1802 1803 /* 1804 * The new xa structure is checked against the current list to see 1805 * if it exists already. 1806 */ 1807 xlist = &session->s_xa_list; 1808 smb_llist_enter(xlist, RW_WRITER); 1809 nxa = smb_llist_head(xlist); 1810 while (nxa) { 1811 ASSERT(nxa->xa_magic == SMB_XA_MAGIC); 1812 if (nxa->xa_smb_mid == xa->xa_smb_mid && 1813 nxa->smb_pid == xa->smb_pid && 1814 !SMB_XA_CLOSED(nxa) && 1815 !(nxa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 1816 smb_llist_exit(xlist); 1817 MEM_FREE("xa", xa); 1818 return (NULL); 1819 } 1820 nxa = smb_llist_next(xlist, nxa); 1821 } 1822 smb_llist_insert_tail(xlist, xa); 1823 smb_llist_exit(xlist); 1824 return (xa); 1825 } 1826 1827 void 1828 smb_xa_delete(smb_xa_t *xa) 1829 { 1830 ASSERT(xa->xa_refcnt == 0); 1831 ASSERT(SMB_XA_CLOSED(xa)); 1832 1833 if (xa->xa_smb_trans_name) 1834 MEM_FREE("smb", xa->xa_smb_trans_name); 1835 1836 if (xa->rep_setup_mb.chain != NULL) 1837 m_freem(xa->rep_setup_mb.chain); 1838 if (xa->rep_param_mb.chain != NULL) 1839 m_freem(xa->rep_param_mb.chain); 1840 if (xa->rep_data_mb.chain != NULL) 1841 m_freem(xa->rep_data_mb.chain); 1842 1843 xa->xa_magic = (uint32_t)~SMB_XA_MAGIC; 1844 MEM_FREE("xa", xa); 1845 } 1846 1847 smb_xa_t * 1848 smb_xa_hold(smb_xa_t *xa) 1849 { 1850 mutex_enter(&xa->xa_mutex); 1851 xa->xa_refcnt++; 1852 ASSERT(xa->xa_refcnt); 1853 mutex_exit(&xa->xa_mutex); 1854 return (xa); 1855 } 1856 1857 void 1858 smb_xa_rele(smb_session_t *session, smb_xa_t *xa) 1859 { 1860 mutex_enter(&xa->xa_mutex); 1861 ASSERT(xa->xa_refcnt); 1862 xa->xa_refcnt--; 1863 if (SMB_XA_CLOSED(xa) && (xa->xa_refcnt == 0)) { 1864 mutex_exit(&xa->xa_mutex); 1865 smb_llist_enter(&session->s_xa_list, RW_WRITER); 1866 smb_llist_remove(&session->s_xa_list, xa); 1867 smb_llist_exit(&session->s_xa_list); 1868 smb_xa_delete(xa); 1869 return; 1870 } 1871 mutex_exit(&xa->xa_mutex); 1872 } 1873 1874 int 1875 smb_xa_open(smb_xa_t *xa) 1876 { 1877 int rc; 1878 1879 mutex_enter(&xa->xa_mutex); 1880 1881 ASSERT((xa->xa_flags & SMB_XA_FLAG_OPEN) == 0); 1882 1883 if ((xa->xa_flags & SMB_XA_FLAG_CLOSE) == 0) { 1884 xa->xa_flags |= SMB_XA_FLAG_OPEN; 1885 rc = 0; 1886 } else { 1887 rc = ERROR_INVALID_HANDLE; 1888 } 1889 1890 mutex_exit(&xa->xa_mutex); 1891 1892 return (rc); 1893 } 1894 1895 void 1896 smb_xa_close(smb_xa_t *xa) 1897 { 1898 mutex_enter(&xa->xa_mutex); 1899 xa->xa_flags |= SMB_XA_FLAG_CLOSE; 1900 xa->xa_flags &= ~SMB_XA_FLAG_OPEN; 1901 1902 if (xa->xa_refcnt == 0) { 1903 mutex_exit(&xa->xa_mutex); 1904 smb_llist_enter(&xa->xa_session->s_xa_list, RW_WRITER); 1905 smb_llist_remove(&xa->xa_session->s_xa_list, xa); 1906 smb_llist_exit(&xa->xa_session->s_xa_list); 1907 smb_xa_delete(xa); 1908 return; 1909 } 1910 1911 mutex_exit(&xa->xa_mutex); 1912 } 1913 1914 int 1915 smb_xa_complete(smb_xa_t *xa) 1916 { 1917 int rc; 1918 1919 mutex_enter(&xa->xa_mutex); 1920 if (xa->xa_flags & (SMB_XA_FLAG_COMPLETE | SMB_XA_FLAG_CLOSE)) { 1921 rc = 0; 1922 } else { 1923 rc = 1; 1924 xa->xa_flags |= SMB_XA_FLAG_COMPLETE; 1925 } 1926 mutex_exit(&xa->xa_mutex); 1927 return (rc); 1928 } 1929 1930 smb_xa_t * 1931 smb_xa_find( 1932 smb_session_t *session, 1933 uint16_t pid, 1934 uint16_t mid) 1935 { 1936 smb_xa_t *xa; 1937 smb_llist_t *xlist; 1938 1939 xlist = &session->s_xa_list; 1940 smb_llist_enter(xlist, RW_READER); 1941 xa = smb_llist_head(xlist); 1942 while (xa) { 1943 mutex_enter(&xa->xa_mutex); 1944 if (xa->xa_smb_mid == mid && 1945 xa->smb_pid == pid && 1946 !SMB_XA_CLOSED(xa) && 1947 !(xa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 1948 xa->xa_refcnt++; 1949 ASSERT(xa->xa_refcnt); 1950 mutex_exit(&xa->xa_mutex); 1951 break; 1952 } 1953 mutex_exit(&xa->xa_mutex); 1954 xa = smb_llist_next(xlist, xa); 1955 } 1956 smb_llist_exit(xlist); 1957 return (xa); 1958 } 1959