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