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/oem.h> 32 #include <smbsrv/nmpipes.h> 33 #include <smbsrv/mailslot.h> 34 #include <smbsrv/lmerr.h> 35 #include <smbsrv/nterror.h> 36 37 #define MAX_SHARE_NAME_LEN 13 38 #define SHARE_INFO_1_SIZE (MAX_SHARE_NAME_LEN + sizeof (char) + \ 39 sizeof (short) + sizeof (uint32_t)) 40 41 /* 42 * count of bytes in server response packet 43 * except parameters and data. Note that setup 44 * word count is zero. 45 */ 46 #define RESP_HEADER_LEN 24 47 48 /* 49 * NB. I started by using common functions for transaction/transaction2 50 * and transaction_secondary/transaction2_secondary because they 51 * are respectively so similar. However, it turned out to be a bad 52 * idea because of quirky differences. Be sure if you modify one 53 * of these four functions to check and see if the modification should 54 * be applied to its peer. 55 */ 56 57 static int smb_trans_ready(struct smb_xa *); 58 static smb_sdrc_t smb_trans_dispatch(struct smb_request *, struct smb_xa *); 59 static smb_sdrc_t smb_trans2_dispatch(struct smb_request *, struct smb_xa *); 60 static smb_sdrc_t smb_nt_transact_query_quota(struct smb_request *, 61 struct smb_xa *); 62 63 smb_sdrc_t 64 smb_pre_transaction(smb_request_t *sr) 65 { 66 DTRACE_SMB_1(op__Transaction__start, smb_request_t *, sr); 67 return (SDRC_SUCCESS); 68 } 69 70 void 71 smb_post_transaction(smb_request_t *sr) 72 { 73 DTRACE_SMB_1(op__Transaction__done, smb_request_t *, sr); 74 } 75 76 smb_sdrc_t 77 smb_com_transaction(smb_request_t *sr) 78 { 79 int rc; 80 unsigned char msrcnt, suwcnt; 81 uint16_t tpscnt, tdscnt, mprcnt, mdrcnt, flags; 82 uint16_t pscnt, psoff, dscnt, dsoff; 83 uint32_t timeo; 84 struct smb_xa *xa; 85 char *stn; 86 int ready; 87 88 rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, 89 &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &msrcnt, &flags, 90 &timeo, &pscnt, &psoff, &dscnt, &dsoff, &suwcnt); 91 92 if (rc != 0) 93 return (SDRC_ERROR); 94 95 xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, 96 msrcnt, suwcnt); 97 if (xa == NULL) { 98 smbsr_error(sr, 0, ERRSRV, ERRnoroom); 99 return (SDRC_ERROR); 100 } 101 102 /* Should be some alignment stuff here in SMB? */ 103 if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) { 104 rc = smbsr_decode_data(sr, "%.U", sr, &stn); 105 } else { 106 rc = smbsr_decode_data(sr, "%s", sr, &stn); 107 } 108 if (rc != 0) { 109 smb_xa_rele(sr->session, xa); 110 return (SDRC_ERROR); 111 } 112 xa->xa_smb_trans_name = MEM_STRDUP("smb", stn); 113 114 xa->smb_flags = flags; 115 xa->smb_timeout = timeo; 116 xa->req_disp_param = pscnt; 117 xa->req_disp_data = dscnt; 118 119 if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv, 120 sr->smb_vwv.chain_offset, suwcnt * 2)) { 121 smb_xa_rele(sr->session, xa); 122 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 123 return (SDRC_ERROR); 124 } 125 if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 126 smb_xa_rele(sr->session, xa); 127 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 128 return (SDRC_ERROR); 129 } 130 if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 131 smb_xa_rele(sr->session, xa); 132 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 133 return (SDRC_ERROR); 134 } 135 136 ready = smb_trans_ready(xa); 137 138 if (smb_xa_open(xa)) { 139 smb_xa_rele(sr->session, xa); 140 smbsr_error(sr, 0, ERRDOS, ERRsrverror); 141 return (SDRC_ERROR); 142 } 143 sr->r_xa = xa; 144 145 if (!ready) { 146 rc = smbsr_encode_empty_result(sr); 147 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 148 } 149 150 if (!smb_xa_complete(xa)) { 151 smb_xa_close(xa); 152 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 153 return (SDRC_ERROR); 154 } 155 156 return (smb_trans_dispatch(sr, xa)); 157 } 158 159 smb_sdrc_t 160 smb_pre_transaction_secondary(smb_request_t *sr) 161 { 162 DTRACE_SMB_1(op__TransactionSecondary__start, smb_request_t *, sr); 163 return (SDRC_SUCCESS); 164 } 165 166 void 167 smb_post_transaction_secondary(smb_request_t *sr) 168 { 169 DTRACE_SMB_1(op__TransactionSecondary__done, smb_request_t *, sr); 170 } 171 172 smb_sdrc_t 173 smb_com_transaction_secondary(smb_request_t *sr) 174 { 175 uint16_t tpscnt, tdscnt, pscnt, psdisp; 176 uint16_t dscnt, dsoff, dsdisp, psoff; 177 smb_xa_t *xa; 178 int rc; 179 180 if ((xa = smbsr_lookup_xa(sr)) == 0) { 181 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 182 return (SDRC_ERROR); 183 } 184 185 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 186 if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { 187 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 188 ERRDOS, ERRnoaccess); 189 return (SDRC_ERROR); 190 } 191 } 192 193 if (xa->smb_com != SMB_COM_TRANSACTION) { 194 return (SDRC_DROP_VC); 195 } 196 197 rc = smbsr_decode_vwv(sr, SMB_TRANSSHDR_ED_FMT, &tpscnt, &tdscnt, 198 &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp); 199 200 if (rc != 0) 201 return (SDRC_ERROR); 202 203 mutex_enter(&xa->xa_mutex); 204 xa->smb_tpscnt = tpscnt; /* might have shrunk */ 205 xa->smb_tdscnt = tdscnt; /* might have shrunk */ 206 xa->req_disp_param = psdisp+pscnt; 207 xa->req_disp_data = dsdisp+dscnt; 208 209 if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 210 mutex_exit(&xa->xa_mutex); 211 smb_xa_close(xa); 212 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 213 return (SDRC_ERROR); 214 } 215 if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 216 mutex_exit(&xa->xa_mutex); 217 smb_xa_close(xa); 218 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 219 return (SDRC_ERROR); 220 } 221 mutex_exit(&xa->xa_mutex); 222 223 if (!smb_trans_ready(xa)) 224 return (SDRC_NO_REPLY); 225 226 if (!smb_xa_complete(xa)) 227 return (SDRC_NO_REPLY); 228 229 return (smb_trans_dispatch(sr, xa)); 230 } 231 232 smb_sdrc_t 233 smb_pre_ioctl(smb_request_t *sr) 234 { 235 DTRACE_SMB_1(op__Ioctl__start, smb_request_t *, sr); 236 return (SDRC_SUCCESS); 237 } 238 239 void 240 smb_post_ioctl(smb_request_t *sr) 241 { 242 DTRACE_SMB_1(op__Ioctl__done, smb_request_t *, sr); 243 } 244 245 smb_sdrc_t 246 smb_com_ioctl(smb_request_t *sr) 247 { 248 uint16_t fid, category, function, tpscnt, tdscnt, mprcnt; 249 uint16_t mdrcnt, pscnt, pdoff, dscnt, dsoff; 250 uint32_t timeout; 251 int rc; 252 253 rc = smbsr_decode_vwv(sr, "wwwwwwwl2.wwww", &fid, &category, &function, 254 &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &timeout, &pscnt, 255 &pdoff, &dscnt, &dsoff); 256 257 if (rc != 0) 258 return (SDRC_ERROR); 259 260 return (SDRC_NOT_IMPLEMENTED); 261 } 262 263 smb_sdrc_t 264 smb_pre_transaction2(smb_request_t *sr) 265 { 266 DTRACE_SMB_1(op__Transaction2__start, smb_request_t *, sr); 267 return (SDRC_SUCCESS); 268 } 269 270 void 271 smb_post_transaction2(smb_request_t *sr) 272 { 273 DTRACE_SMB_1(op__Transaction2__done, smb_request_t *, sr); 274 } 275 276 smb_sdrc_t 277 smb_com_transaction2(struct smb_request *sr) 278 { 279 unsigned char msrcnt, suwcnt; 280 uint16_t tpscnt, tdscnt, mprcnt, mdrcnt, flags; 281 uint16_t pscnt, psoff, dscnt, dsoff; 282 uint32_t timeo; 283 smb_xa_t *xa; 284 int ready; 285 int rc; 286 287 rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, &tpscnt, &tdscnt, 288 &mprcnt, &mdrcnt, &msrcnt, &flags, &timeo, &pscnt, &psoff, &dscnt, 289 &dsoff, &suwcnt); 290 291 if (rc != 0) 292 return (SDRC_ERROR); 293 294 xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, 295 msrcnt, suwcnt); 296 if (xa == 0) { 297 smbsr_error(sr, 0, ERRSRV, ERRnoroom); 298 return (SDRC_ERROR); 299 } 300 301 xa->smb_flags = flags; 302 xa->smb_timeout = timeo; 303 xa->req_disp_param = pscnt; 304 xa->req_disp_data = dscnt; 305 306 if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv, 307 sr->smb_vwv.chain_offset, suwcnt*2)) { 308 smb_xa_rele(sr->session, xa); 309 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 310 return (SDRC_ERROR); 311 } 312 if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 313 smb_xa_rele(sr->session, xa); 314 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 315 return (SDRC_ERROR); 316 } 317 if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 318 smb_xa_rele(sr->session, xa); 319 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 320 return (SDRC_ERROR); 321 } 322 323 ready = smb_trans_ready(xa); 324 325 if (smb_xa_open(xa)) { 326 smb_xa_rele(sr->session, xa); 327 smbsr_error(sr, 0, ERRDOS, ERRsrverror); 328 return (SDRC_ERROR); 329 } 330 sr->r_xa = xa; 331 332 if (!ready) { 333 rc = smbsr_encode_empty_result(sr); 334 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 335 } 336 337 if (!smb_xa_complete(xa)) { 338 smb_xa_close(xa); 339 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 340 return (SDRC_ERROR); 341 } 342 343 return (smb_trans2_dispatch(sr, xa)); 344 } 345 346 smb_sdrc_t 347 smb_pre_transaction2_secondary(smb_request_t *sr) 348 { 349 DTRACE_SMB_1(op__Transaction2Secondary__start, smb_request_t *, sr); 350 return (SDRC_SUCCESS); 351 } 352 353 void 354 smb_post_transaction2_secondary(smb_request_t *sr) 355 { 356 DTRACE_SMB_1(op__Transaction2Secondary__done, smb_request_t *, sr); 357 } 358 359 smb_sdrc_t 360 smb_com_transaction2_secondary(smb_request_t *sr) 361 { 362 uint16_t tpscnt, tdscnt, fid; 363 uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp; 364 smb_xa_t *xa; 365 int rc; 366 367 if ((xa = smbsr_lookup_xa(sr)) == 0) { 368 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 369 return (SDRC_ERROR); 370 } 371 372 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 373 if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { 374 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 375 ERRDOS, ERRnoaccess); 376 return (SDRC_ERROR); 377 } 378 } 379 380 if (xa->smb_com != SMB_COM_TRANSACTION2) { 381 return (SDRC_DROP_VC); 382 } 383 384 rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt, 385 &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid); 386 387 if (rc != 0) 388 return (SDRC_ERROR); 389 390 mutex_enter(&xa->xa_mutex); 391 xa->smb_tpscnt = tpscnt; /* might have shrunk */ 392 xa->smb_tdscnt = tdscnt; /* might have shrunk */ 393 xa->xa_smb_fid = fid; /* overwrite rules? */ 394 xa->req_disp_param = psdisp + pscnt; 395 xa->req_disp_data = dsdisp + dscnt; 396 397 if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 398 mutex_exit(&xa->xa_mutex); 399 smb_xa_close(xa); 400 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 401 return (SDRC_ERROR); 402 } 403 if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 404 mutex_exit(&xa->xa_mutex); 405 smb_xa_close(xa); 406 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 407 return (SDRC_ERROR); 408 } 409 mutex_exit(&xa->xa_mutex); 410 411 if (!smb_trans_ready(xa)) 412 return (SDRC_NO_REPLY); 413 414 if (!smb_xa_complete(xa)) 415 return (SDRC_NO_REPLY); 416 417 return (smb_trans2_dispatch(sr, xa)); 418 } 419 420 static smb_sdrc_t 421 smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) 422 { 423 int rc; 424 int total_bytes, n_setup, n_param, n_data; 425 int param_off, param_pad, data_off, data_pad; 426 427 n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200; 428 n_setup++; 429 n_setup = n_setup & ~0x0001; 430 n_param = (xa->smb_mprcnt < smb_maxbufsize) 431 ? xa->smb_mprcnt : smb_maxbufsize; 432 n_param++; 433 n_param = n_param & ~0x0001; 434 rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param); 435 n_data = (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc; 436 MBC_INIT(&xa->rep_setup_mb, n_setup * 2); 437 MBC_INIT(&xa->rep_param_mb, n_param); 438 MBC_INIT(&xa->rep_data_mb, n_data); 439 440 switch (xa->smb_func) { 441 case NT_TRANSACT_CREATE: 442 if ((rc = smb_pre_nt_transact_create(sr, xa)) == 0) 443 rc = smb_nt_transact_create(sr, xa); 444 smb_post_nt_transact_create(sr, xa); 445 break; 446 case NT_TRANSACT_NOTIFY_CHANGE: 447 rc = smb_nt_transact_notify_change(sr, xa); 448 break; 449 case NT_TRANSACT_QUERY_SECURITY_DESC: 450 rc = smb_nt_transact_query_security_info(sr, xa); 451 break; 452 case NT_TRANSACT_SET_SECURITY_DESC: 453 rc = smb_nt_transact_set_security_info(sr, xa); 454 break; 455 case NT_TRANSACT_IOCTL: 456 rc = smb_nt_transact_ioctl(sr, xa); 457 break; 458 459 case NT_TRANSACT_QUERY_QUOTA: 460 (void) smb_nt_transact_query_quota(sr, xa); 461 smbsr_error(sr, 0, ERRSRV, ERRaccess); 462 return (SDRC_ERROR); 463 464 case NT_TRANSACT_SET_QUOTA: 465 smbsr_error(sr, 0, ERRSRV, ERRaccess); 466 return (SDRC_ERROR); 467 468 default: 469 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); 470 return (SDRC_ERROR); 471 } 472 473 switch (rc) { 474 case SDRC_SUCCESS: 475 break; 476 477 case SDRC_DROP_VC: 478 case SDRC_NO_REPLY: 479 case SDRC_ERROR: 480 return (rc); 481 482 case SDRC_NOT_IMPLEMENTED: 483 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); 484 return (SDRC_ERROR); 485 486 default: 487 break; 488 } 489 490 n_setup = MBC_LENGTH(&xa->rep_setup_mb); 491 n_param = MBC_LENGTH(&xa->rep_param_mb); 492 n_data = MBC_LENGTH(&xa->rep_data_mb); 493 494 if (xa->smb_msrcnt < n_setup || 495 xa->smb_mprcnt < n_param || 496 xa->smb_mdrcnt < n_data) { 497 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); 498 return (SDRC_ERROR); 499 } 500 501 /* neato, blast it over there */ 502 503 n_setup = (n_setup + 1) / 2; /* Conver to setup words */ 504 param_pad = 1; /* must be one */ 505 param_off = param_pad + 32 + 37 + (n_setup << 1) + 2; 506 data_pad = (4 - ((param_off + n_param) & 3)) % 4; /* Pad to 4 byte */ 507 data_off = param_off + n_param + data_pad; /* Param off from hdr */ 508 total_bytes = param_pad + n_param + data_pad + n_data; 509 510 rc = smbsr_encode_result(sr, 18+n_setup, total_bytes, 511 "b 3. llllllllb C w #. C #. C", 512 18 + n_setup, /* wct */ 513 n_param, /* Total Parameter Bytes */ 514 n_data, /* Total Data Bytes */ 515 n_param, /* Total Parameter Bytes this buffer */ 516 param_off, /* Param offset from header start */ 517 0, /* Param displacement */ 518 n_data, /* Total Data Bytes this buffer */ 519 data_off, /* Data offset from header start */ 520 0, /* Data displacement */ 521 n_setup, /* suwcnt */ 522 &xa->rep_setup_mb, /* setup[] */ 523 total_bytes, /* Total data bytes */ 524 param_pad, 525 &xa->rep_param_mb, 526 data_pad, 527 &xa->rep_data_mb); 528 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 529 } 530 531 532 /* 533 * smb_nt_transact_query_quota 534 * 535 * There are 16 parameter bytes: fid, flags and 12 zero bytes. 536 */ 537 static smb_sdrc_t 538 smb_nt_transact_query_quota(struct smb_request *sr, struct smb_xa *xa) 539 { 540 uint16_t fid; 541 uint16_t flags; 542 543 if (smb_decode_mbc(&xa->req_param_mb, "%ww", sr, &fid, &flags)) 544 return (SDRC_ERROR); 545 546 return (SDRC_SUCCESS); 547 } 548 549 smb_sdrc_t 550 smb_pre_nt_transact(smb_request_t *sr) 551 { 552 DTRACE_SMB_1(op__NtTransact__start, smb_request_t *, sr); 553 return (SDRC_SUCCESS); 554 } 555 556 void 557 smb_post_nt_transact(smb_request_t *sr) 558 { 559 DTRACE_SMB_1(op__NtTransact__done, smb_request_t *, sr); 560 } 561 562 smb_sdrc_t 563 smb_com_nt_transact(struct smb_request *sr) 564 { 565 uint16_t Function; 566 unsigned char MaxSetupCount, SetupCount; 567 uint32_t TotalParameterCount, TotalDataCount; 568 uint32_t MaxParameterCount, MaxDataCount, pscnt; 569 uint32_t psoff, dscnt, dsoff; 570 smb_xa_t *xa; 571 int ready; 572 int rc; 573 574 rc = smbsr_decode_vwv(sr, SMB_NT_TRANSHDR_ED_FMT, &MaxSetupCount, 575 &TotalParameterCount, &TotalDataCount, &MaxParameterCount, 576 &MaxDataCount, &pscnt, &psoff, &dscnt, 577 &dsoff, &SetupCount, &Function); 578 579 if (rc != 0) 580 return (SDRC_ERROR); 581 582 xa = smb_xa_create(sr->session, sr, TotalParameterCount, TotalDataCount, 583 MaxParameterCount, MaxDataCount, MaxSetupCount, SetupCount); 584 if (xa == 0) { 585 smbsr_error(sr, 0, ERRSRV, ERRnoroom); 586 return (SDRC_ERROR); 587 } 588 589 xa->smb_flags = 0; 590 xa->smb_timeout = 0; 591 xa->smb_func = Function; 592 xa->req_disp_param = pscnt; 593 xa->req_disp_data = dscnt; 594 595 if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv, 596 sr->smb_vwv.chain_offset, SetupCount * 2)) { 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_param_mb, &sr->command, psoff, pscnt)) { 602 smb_xa_rele(sr->session, xa); 603 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 604 return (SDRC_ERROR); 605 } 606 if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 607 smb_xa_rele(sr->session, xa); 608 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 609 return (SDRC_ERROR); 610 } 611 612 ready = smb_trans_ready(xa); 613 614 if (smb_xa_open(xa)) { 615 smb_xa_rele(sr->session, xa); 616 smbsr_error(sr, 0, ERRDOS, ERRsrverror); 617 return (SDRC_ERROR); 618 } 619 sr->r_xa = xa; 620 621 if (!ready) { 622 rc = smbsr_encode_empty_result(sr); 623 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 624 } 625 626 if (!smb_xa_complete(xa)) { 627 smb_xa_close(xa); 628 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 629 return (SDRC_ERROR); 630 } 631 632 return (smb_nt_trans_dispatch(sr, xa)); 633 } 634 635 smb_sdrc_t 636 smb_pre_nt_transact_secondary(smb_request_t *sr) 637 { 638 DTRACE_SMB_1(op__NtTransactSecondary__start, smb_request_t *, sr); 639 return (SDRC_SUCCESS); 640 } 641 642 void 643 smb_post_nt_transact_secondary(smb_request_t *sr) 644 { 645 DTRACE_SMB_1(op__NtTransactSecondary__done, smb_request_t *, sr); 646 } 647 648 smb_sdrc_t 649 smb_com_nt_transact_secondary(struct smb_request *sr) 650 { 651 uint16_t tpscnt, tdscnt, fid; 652 uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp; 653 smb_xa_t *xa; 654 int rc; 655 656 if ((xa = smbsr_lookup_xa(sr)) == 0) { 657 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 658 return (SDRC_ERROR); 659 } 660 661 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { 662 if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { 663 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 664 ERRDOS, ERRnoaccess); 665 return (SDRC_ERROR); 666 } 667 } 668 669 if (xa->smb_com != SMB_COM_TRANSACTION2) { 670 return (SDRC_DROP_VC); 671 } 672 673 rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt, 674 &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid); 675 676 if (rc != 0) 677 return (SDRC_ERROR); 678 679 mutex_enter(&xa->xa_mutex); 680 xa->smb_tpscnt = tpscnt; /* might have shrunk */ 681 xa->smb_tdscnt = tdscnt; /* might have shrunk */ 682 xa->xa_smb_fid = fid; /* overwrite rules? */ 683 xa->req_disp_param = psdisp+pscnt; 684 xa->req_disp_data = dsdisp+dscnt; 685 686 if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { 687 mutex_exit(&xa->xa_mutex); 688 smb_xa_close(xa); 689 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 690 return (SDRC_ERROR); 691 } 692 if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { 693 mutex_exit(&xa->xa_mutex); 694 smb_xa_close(xa); 695 smbsr_error(sr, 0, ERRDOS, ERRbadformat); 696 return (SDRC_ERROR); 697 } 698 mutex_exit(&xa->xa_mutex); 699 700 if (!smb_trans_ready(xa)) 701 return (SDRC_NO_REPLY); 702 703 if (!smb_xa_complete(xa)) 704 return (SDRC_NO_REPLY); 705 706 return (smb_nt_trans_dispatch(sr, xa)); 707 } 708 709 static int 710 smb_trans_ready(struct smb_xa *xa) 711 { 712 int rc; 713 714 mutex_enter(&xa->xa_mutex); 715 rc = xa->req_disp_data >= xa->smb_tdscnt && 716 xa->req_disp_param >= xa->smb_tpscnt; 717 mutex_exit(&xa->xa_mutex); 718 719 return (rc); 720 } 721 722 723 /* 724 * smb_emit_SHARE_INFO_0 725 * 726 * This function will convert unicode chars to oem chars before 727 * and store the result in a fixed length, MAX_SHARE_NAME_LEN, buffer. If the 728 * length after conversion is longer than 12, -1 will be reported 729 * to indicate an error. The fixed length is a limitation of the 730 * smb protocol. 731 */ 732 static int 733 smb_emit_SHARE_INFO_0(struct mbuf_chain *output, unsigned char *name) 734 { 735 mts_wchar_t *unibuf; 736 char *tmpbuf; 737 unsigned int cpid = oem_get_smb_cpid(); 738 unsigned int length; 739 char name_buf[MAX_SHARE_NAME_LEN]; 740 741 if (name == 0) 742 tmpbuf = ""; 743 else 744 tmpbuf = (char *)name; 745 746 length = strlen(tmpbuf) + 1; 747 unibuf = MEM_MALLOC("smb", length * sizeof (mts_wchar_t)); 748 749 (void) mts_mbstowcs(unibuf, tmpbuf, length); 750 tmpbuf = MEM_MALLOC("smb", length); 751 if (unicodestooems(tmpbuf, unibuf, length, cpid) == 0) 752 (void) strcpy(tmpbuf, (char *)name); 753 754 if (strlen(tmpbuf) + 1 > MAX_SHARE_NAME_LEN) { 755 MEM_FREE("smb", unibuf); 756 MEM_FREE("smb", tmpbuf); 757 return (-1); 758 } 759 760 bzero(name_buf, sizeof (name_buf)); 761 (void) strcpy(name_buf, tmpbuf); 762 (void) smb_encode_mbc(output, "13c", name_buf); 763 764 MEM_FREE("smb", unibuf); 765 MEM_FREE("smb", tmpbuf); 766 767 return (0); 768 } 769 770 static int 771 smb_emit_SHARE_INFO_1(struct mbuf_chain *output, struct mbuf_chain *text, 772 unsigned char *name, uint16_t type, 773 unsigned char *comment) 774 { 775 if (smb_emit_SHARE_INFO_0(output, name) < 0) 776 return (-1); 777 778 (void) smb_encode_mbc(output, ".wl", type, MBC_LENGTH(text)); 779 (void) smb_encode_mbc(text, "s", 780 (comment ? comment : (unsigned char *)"No comment")); 781 return (0); 782 } 783 784 static void /*ARGSUSED*/ 785 smb_emit_SHARE_INFO_2(struct mbuf_chain *output, struct mbuf_chain *text, 786 struct smb_request *sr, unsigned char *name, uint16_t type, 787 unsigned char *comment, uint16_t access, char *path, char *password) 788 { 789 unsigned char pword[9]; 790 791 /* 792 * XXX PGD. Is there a bug here? We zero pword, copy password 793 * into pword then ignore it and use password for smb_encode_mbc? 794 */ 795 bzero(pword, sizeof (pword)); 796 (void) strncpy((char *)pword, password, sizeof (pword)); 797 (void) smb_emit_SHARE_INFO_1(output, text, name, type, comment); 798 (void) smb_encode_mbc(output, "wwwl9c.", 799 access, 800 sr->sr_cfg->skc_maxconnections, 801 smb_server_get_session_count(), 802 MBC_LENGTH(text), 803 password); 804 (void) smb_encode_mbc(text, "s", path); 805 } 806 807 /* 808 * is_long_sharename 809 * 810 * This function is extracted from smb_emit_SHARE_INFO_0 only for 811 * finding shares that their names are longer than MAX_SHARE_NAME_LEN. 812 * 813 * The function returns 1 for long share names and 0 when the length 814 * is Ok. 815 */ 816 static int 817 is_long_sharename(unsigned char *name) 818 { 819 mts_wchar_t *unibuf; 820 char *tmpbuf; 821 unsigned int cpid = oem_get_smb_cpid(); 822 unsigned int length; 823 824 if (name == 0) 825 tmpbuf = ""; 826 else 827 tmpbuf = (char *)name; 828 829 length = strlen(tmpbuf) + 1; 830 unibuf = MEM_MALLOC("smb", length * sizeof (mts_wchar_t)); 831 (void) mts_mbstowcs(unibuf, tmpbuf, length); 832 tmpbuf = MEM_MALLOC("smb", length); 833 if (unicodestooems(tmpbuf, unibuf, length, cpid) == 0) 834 (void) strcpy(tmpbuf, (char *)name); 835 836 if (strlen(tmpbuf) + 1 > MAX_SHARE_NAME_LEN) { 837 MEM_FREE("smb", unibuf); 838 MEM_FREE("smb", tmpbuf); 839 return (1); 840 } 841 842 MEM_FREE("smb", unibuf); 843 MEM_FREE("smb", tmpbuf); 844 845 return (0); 846 } 847 848 /* 849 * This structure holds information about shares which will 850 * fit in the specified client buffer size. 851 * 852 * sei_bufsize: Client specified buffer size 853 * sei_count: Maximum number of shares that can be 854 * sent in the buffer. 855 * 856 * The return data section consists of a number of SHARE_INFO_1 structures. 857 * In case there are multiple SHARE_INFO_1 data structures to return this 858 * function put all fixed length part of these structures in the return buffer 859 * and then put all the variable length data (shares' comment) at the end of 860 * buffer. 861 * 862 * sei_info_len: Size of fixed length part of SHARE_INFO_1 863 * structures for sei_count shares 864 * sei_cmnt_len: Size of comments for sei_count shares 865 */ 866 typedef struct { 867 uint16_t sei_bufsize; 868 short sei_count; 869 int sei_infolen; 870 int sei_cmntlen; 871 } smb_share_enum_t; 872 873 /* 874 * smb_share_update_info 875 * 876 * Check to see if the given buffer has enough 877 * room to fit the information of the given share. 878 * If there is enough room update the passed max_??? 879 * information. 880 * 881 * Return 1 if buffer is not full yet, 0 if it's full. 882 */ 883 static int 884 smb_share_update_info(door_handle_t dhdl, lmshare_info_t *si, 885 smb_share_enum_t *shr_enum_info) 886 { 887 int cmnt_len; 888 int new_info_len = shr_enum_info->sei_infolen; 889 int new_cmnt_len = shr_enum_info->sei_cmntlen; 890 891 if (lmshrd_is_special(dhdl, si->share_name)) 892 cmnt_len = 1; 893 else 894 cmnt_len = (strlen(si->comment) + 1); 895 896 new_info_len += SHARE_INFO_1_SIZE; 897 new_cmnt_len += cmnt_len; 898 899 if ((new_info_len + new_cmnt_len) < shr_enum_info->sei_bufsize) { 900 shr_enum_info->sei_count++; 901 shr_enum_info->sei_infolen = new_info_len; 902 shr_enum_info->sei_cmntlen = new_cmnt_len; 903 return (1); 904 } 905 906 return (0); 907 } 908 909 /* 910 * smb_share_skip_share 911 * 912 * Determines whether the given share should be enumerated 913 * or not. The share will not be enumerated if its name is 914 * long or it's autohome share. 915 * 916 * Return 1 if the share should be skipped; otherwise returns 917 * 0 918 */ 919 static int 920 smb_share_skip_share(lmshare_info_t *si) 921 { 922 if (is_long_sharename((unsigned char *)si->share_name)) { 923 return (1); 924 } 925 926 /* Skip autohome share if autohome filter is enabled */ 927 if (si->mode == LMSHRM_TRANS) { 928 return (1); 929 } 930 931 return (0); 932 } 933 934 /* 935 * smb_share_add_autohome 936 * 937 * Determines if an autohome share should be added to shares' list 938 * for the given user. 939 * Autohome will be add when all the following conditions are true: 940 * 941 * 1. Autohome feature is enabled 942 * 2. A share with the same name as the given user exists 943 * 3. The share is not a permanent share 944 * 4. Share name is not longer than maximum allowed 945 */ 946 static int 947 smb_share_add_autohome(door_handle_t dhdl, char *username, lmshare_info_t *si) 948 { 949 int do_add = 0; 950 951 do_add = (lmshrd_getinfo(dhdl, username, si) == NERR_Success) && 952 (si->mode & LMSHRM_TRANS) && 953 (is_long_sharename((unsigned char *)(si->share_name)) == 0); 954 955 return (do_add); 956 } 957 958 /* 959 * smb_share_total_info 960 * 961 * This function calculates following informations 962 * - Maximum number of shares that can be sent for clients 963 * according to its buffer size (cli_bufsize) 964 * - length of fixed information about above shares 965 * - length of comments of above shares 966 * - total number of shares that their names are no longer 967 * than MAX_SHARE_NAME_LEN. 968 * 969 * Added SMB user object to the parameter list to filter out other 970 * user autohome shares. 971 */ 972 static void 973 smb_share_total_info(door_handle_t dhdl, smb_share_enum_t *shr_enum_info, 974 short *tot_shares_num, smb_user_t *user) 975 { 976 uint64_t iterator; 977 lmshare_info_t *si; 978 struct lmshare_info *auto_si; 979 int more_room = 1; 980 981 si = kmem_zalloc(sizeof (lmshare_info_t), KM_SLEEP); 982 auto_si = kmem_zalloc(sizeof (struct lmshare_info), KM_SLEEP); 983 984 *tot_shares_num = 0; 985 shr_enum_info->sei_count = 0; 986 shr_enum_info->sei_infolen = 0; 987 shr_enum_info->sei_cmntlen = 0; 988 989 if (smb_share_add_autohome(dhdl, user->u_name, auto_si)) { 990 (*tot_shares_num)++; 991 more_room = smb_share_update_info(dhdl, auto_si, shr_enum_info); 992 } 993 994 iterator = lmshrd_open_iterator(dhdl, LMSHRM_ALL); 995 if (iterator == 0) { 996 kmem_free(si, sizeof (lmshare_info_t)); 997 kmem_free(auto_si, sizeof (struct lmshare_info)); 998 return; 999 } 1000 1001 /* check for door errors */ 1002 if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) { 1003 (void) lmshrd_close_iterator(dhdl, iterator); 1004 kmem_free(si, sizeof (lmshare_info_t)); 1005 kmem_free(auto_si, sizeof (struct lmshare_info)); 1006 return; 1007 } 1008 1009 while (*si->share_name != 0) { 1010 if (smb_share_skip_share(si)) { 1011 /* check for door errors */ 1012 if (lmshrd_iterate(dhdl, iterator, si) != 1013 NERR_Success) { 1014 (void) lmshrd_close_iterator(dhdl, iterator); 1015 kmem_free(si, sizeof (lmshare_info_t)); 1016 kmem_free(auto_si, 1017 sizeof (struct lmshare_info)); 1018 return; 1019 } 1020 continue; 1021 } 1022 1023 (*tot_shares_num)++; 1024 1025 if (more_room) { 1026 more_room = smb_share_update_info(dhdl, si, 1027 shr_enum_info); 1028 } 1029 1030 /* check for door errors */ 1031 if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) { 1032 (void) lmshrd_close_iterator(dhdl, iterator); 1033 kmem_free(si, sizeof (lmshare_info_t)); 1034 kmem_free(auto_si, sizeof (struct lmshare_info)); 1035 return; 1036 } 1037 } 1038 1039 (void) lmshrd_close_iterator(dhdl, iterator); 1040 kmem_free(si, sizeof (lmshare_info_t)); 1041 kmem_free(auto_si, sizeof (struct lmshare_info)); 1042 } 1043 1044 /* 1045 * smb_encode_SHARE_INFO_1 1046 * 1047 * This function is extracted from smb_emit_SHARE_INFO_1 and only 1048 * encodes fixed part of SHARE_INFO_1 structure. 1049 * 1050 * The function returns -1 if encoding fails and 0 on success. 1051 */ 1052 static int 1053 smb_encode_SHARE_INFO_1(struct mbuf_chain *output, unsigned char *name, 1054 uint16_t type, int cmnt_len) 1055 { 1056 if (smb_emit_SHARE_INFO_0(output, name) < 0) 1057 return (-1); 1058 (void) smb_encode_mbc(output, ".wl", type, cmnt_len); 1059 return (0); 1060 } 1061 1062 /* 1063 * collect_shares_info 1064 * 1065 * This function encodes information of shares_num of shares 1066 * into data_mb and cmnt_str. 1067 * 1068 * Added SMB user object to the parameter list to filter out other 1069 * user autohome shares. 1070 * 1071 */ 1072 static void 1073 collect_shares_info(door_handle_t dhdl, uint64_t iterator, int shares_num, 1074 struct mbuf_chain *data_mb, char *cmnt_str, int *cmnt_len, smb_user_t *user, 1075 int first_resp) 1076 { 1077 int i = 0; 1078 lmshare_info_t *si; 1079 struct lmshare_info *tsi; 1080 int is_special; 1081 1082 si = kmem_zalloc(sizeof (lmshare_info_t), KM_SLEEP); 1083 tsi = kmem_zalloc(sizeof (struct lmshare_info), KM_SLEEP); 1084 1085 if (first_resp && smb_share_add_autohome(dhdl, user->u_name, tsi)) { 1086 if (smb_encode_SHARE_INFO_1(data_mb, 1087 (unsigned char *)tsi->share_name, 1088 tsi->stype, *cmnt_len) == 0) { 1089 (void) memcpy(cmnt_str+(*cmnt_len), 1090 tsi->comment, strlen(tsi->comment)+1); 1091 (*cmnt_len) += (strlen(tsi->comment) + 1); 1092 i++; 1093 } 1094 } 1095 1096 /* check for door errors */ 1097 if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) { 1098 kmem_free(si, sizeof (lmshare_info_t)); 1099 kmem_free(tsi, sizeof (struct lmshare_info)); 1100 return; 1101 } 1102 1103 while ((i < shares_num) && (*si->share_name != 0)) { 1104 if (smb_share_skip_share(si)) { 1105 goto next; 1106 } 1107 1108 1109 is_special = lmshrd_is_special(dhdl, si->share_name); 1110 /* check for door errors */ 1111 if (is_special == NERR_InternalError) { 1112 kmem_free(si, sizeof (lmshare_info_t)); 1113 kmem_free(tsi, sizeof (struct lmshare_info)); 1114 return; 1115 } 1116 1117 if (is_special) { 1118 si->stype |= STYPE_HIDDEN; 1119 if (smb_encode_SHARE_INFO_1(data_mb, 1120 (unsigned char *)si->share_name, 1121 si->stype, *cmnt_len) < 0) { 1122 goto next; 1123 } 1124 cmnt_str[*cmnt_len] = '\0'; 1125 (*cmnt_len)++; 1126 } else { 1127 if (smb_encode_SHARE_INFO_1(data_mb, 1128 (unsigned char *)si->share_name, si->stype, 1129 *cmnt_len) < 0) { 1130 goto next; 1131 } 1132 (void) memcpy(cmnt_str+(*cmnt_len), si->comment, 1133 strlen(si->comment)+1); 1134 (*cmnt_len) += (strlen(si->comment) + 1); 1135 } 1136 1137 next: 1138 /* check for door errors */ 1139 if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) { 1140 kmem_free(si, sizeof (lmshare_info_t)); 1141 kmem_free(tsi, sizeof (struct lmshare_info)); 1142 return; 1143 } 1144 } 1145 kmem_free(si, sizeof (lmshare_info_t)); 1146 kmem_free(tsi, sizeof (struct lmshare_info)); 1147 } 1148 1149 int 1150 smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa) 1151 { 1152 door_handle_t dhdl = sr->sr_server->sv_lmshrd; 1153 smb_share_enum_t shr_enum_info; 1154 short left_shares_cnt; /* Number of shares not sent yet */ 1155 1156 /* 1157 * Number of shares that should be sent 1158 * in the current response packet. 1159 * It can be a number between 0 and 1160 * max_share_scnt. 1161 */ 1162 short shares_scnt; 1163 1164 /* 1165 * Maximum number of shares that can be 1166 * sent in one response packet regarding 1167 * the maximum negotiated buffer size 1168 * for SMB messages. 1169 */ 1170 short max_shares_per_packet; 1171 1172 /* 1173 * Total number of shares on the server 1174 * that their name is not greater than 1175 * MAX_SHARE_NAME_LEN 1176 */ 1177 short shares_tot_num; 1178 1179 /* 1180 * Size of total data (info + cmnt) 1181 * that should be sent for client 1182 */ 1183 int shares_tot_byte; 1184 1185 /* 1186 * Maximum size of data that can be 1187 * sent in one SMB transaction response 1188 * according to the maximum negotiated 1189 * buffer size for SMB packets 1190 */ 1191 int data_buf_limit; 1192 1193 /* 1194 * Number of comment bytes that will 1195 * be sent in the current response 1196 */ 1197 uint16_t cmnt_scnt; 1198 1199 /* 1200 * Number of data bytes that will 1201 * be sent in the current response 1202 */ 1203 uint16_t data_scnt; 1204 1205 /* 1206 * Total number of data bytes that 1207 * are sent till now. This is only 1208 * used for calculating current data 1209 * displacement 1210 */ 1211 uint16_t tot_data_scnt; 1212 1213 /* 1214 * Number of parameter bytes should 1215 * be sent for the current response. 1216 * It is 8 for the 1st response and 1217 * 0 for others 1218 */ 1219 uint16_t param_scnt; 1220 1221 /* number of setup and parameter bytes */ 1222 uint16_t n_setup, n_param; 1223 1224 /* data and parameter displacement */ 1225 uint16_t data_disp, param_disp; 1226 1227 /* return status by the 1st reply */ 1228 uint16_t ret_stat; 1229 1230 /* parameter and data offset and pad */ 1231 int param_off, param_pad, data_off, data_pad; 1232 1233 /* 1234 * total bytes of parameters and data 1235 * in the packet, plus the pad bytes. 1236 */ 1237 int tot_packet_bytes; 1238 1239 char first_resp; 1240 uint16_t opcode, level, cli_bufsize; 1241 unsigned char *r_fmt; 1242 char fmt[10]; 1243 uint64_t iterator; 1244 char *cmnt_str, *cmnt_start; 1245 int cmnt_len; 1246 struct mbuf_chain reply; 1247 smb_user_t *user; 1248 1249 user = sr->uid_user; 1250 ASSERT(user); 1251 1252 /* 1253 * Initialize the mbuf chain of reply to zero. If it is not 1254 * zero, code inside the while loop will try to free the chain. 1255 */ 1256 bzero(&reply, sizeof (struct mbuf_chain)); 1257 1258 if (smb_decode_mbc(&xa->req_param_mb, "%wss(lev)w(size)w", sr, 1259 &opcode, &r_fmt, &r_fmt, &level, &cli_bufsize) != 0) 1260 return (SDRC_NOT_IMPLEMENTED); 1261 1262 if (level != 1) { 1263 (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 1264 NERR_BadTransactConfig, 0, 0, 0); 1265 return (SDRC_SUCCESS); 1266 } 1267 1268 n_setup = 0; /* Setup count for NetShareEnum SMB is 0 */ 1269 n_param = 8; 1270 data_buf_limit = sr->session->smb_msg_size - 1271 (SMB_HEADER_ED_LEN + RESP_HEADER_LEN + n_param); 1272 1273 shr_enum_info.sei_bufsize = cli_bufsize; 1274 smb_share_total_info(dhdl, &shr_enum_info, &shares_tot_num, user); 1275 1276 shares_tot_byte = shr_enum_info.sei_infolen + shr_enum_info.sei_cmntlen; 1277 1278 /* Check buffer to have enough space */ 1279 if (shares_tot_byte == 0) { 1280 (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 1281 ERROR_NOT_ENOUGH_MEMORY, 0, 0, 0); 1282 return (SDRC_SUCCESS); 1283 } 1284 1285 max_shares_per_packet = data_buf_limit / SHARE_INFO_1_SIZE; 1286 1287 shares_scnt = (shr_enum_info.sei_count > max_shares_per_packet) 1288 ? max_shares_per_packet : shr_enum_info.sei_count; 1289 1290 cmnt_str = MEM_MALLOC("smb", shr_enum_info.sei_cmntlen * sizeof (char)); 1291 cmnt_len = 0; 1292 /* save start of buffer to free it at the end of function */ 1293 cmnt_start = cmnt_str; 1294 1295 iterator = lmshrd_open_iterator(dhdl, LMSHRM_ALL); 1296 1297 if (iterator == NULL) { 1298 MEM_FREE("smb", cmnt_str); 1299 return (SDRC_DROP_VC); 1300 } 1301 1302 /* 1303 * The rep_setup_mb is already initialized in smb_trans_dispatch(). 1304 * Calling MBC_INIT() will initialized the structure and so the 1305 * pointer to the mbuf chains will be lost. Therefore, we need 1306 * to free the resources before calling MBC_INIT() again. 1307 */ 1308 m_freem(xa->rep_setup_mb.chain); 1309 MBC_INIT(&xa->rep_setup_mb, n_setup * 2); 1310 1311 left_shares_cnt = shr_enum_info.sei_count; 1312 tot_data_scnt = 0; 1313 cmnt_scnt = 0; 1314 1315 first_resp = 1; 1316 while (tot_data_scnt < shares_tot_byte) { 1317 /* 1318 * Calling MBC_INIT() will initialized the structure and so the 1319 * pointer to the mbuf chains will be lost. Therefore, we need 1320 * to free the resources if any before calling MBC_INIT(). 1321 */ 1322 m_freem(xa->rep_data_mb.chain); 1323 MBC_INIT(&xa->rep_data_mb, data_buf_limit); 1324 collect_shares_info(dhdl, iterator, 1325 shares_scnt, &xa->rep_data_mb, cmnt_str, &cmnt_len, user, 1326 first_resp); 1327 data_scnt = shares_scnt * SHARE_INFO_1_SIZE; 1328 left_shares_cnt -= shares_scnt; 1329 if (left_shares_cnt < max_shares_per_packet) 1330 shares_scnt = left_shares_cnt; 1331 if (left_shares_cnt == 0) { 1332 /* 1333 * Now send comments. 1334 * Append comments to the end of share_info_1 1335 * structures. 1336 */ 1337 cmnt_scnt = data_buf_limit - 1338 MBC_LENGTH(&xa->rep_data_mb); 1339 if (cmnt_scnt > shr_enum_info.sei_cmntlen) { 1340 /*LINTED E_ASSIGN_NARROW_CONV*/ 1341 cmnt_scnt = shr_enum_info.sei_cmntlen; 1342 } 1343 (void) sprintf(fmt, "%dc", cmnt_scnt); 1344 (void) smb_encode_mbc(&xa->rep_data_mb, fmt, cmnt_str); 1345 cmnt_str += cmnt_scnt; 1346 shr_enum_info.sei_cmntlen -= cmnt_scnt; 1347 } 1348 data_scnt += cmnt_scnt; 1349 tot_data_scnt += data_scnt; 1350 1351 /* Only the 1st response packet contains parameters */ 1352 param_scnt = (first_resp) ? n_param : 0; 1353 param_pad = 1; /* always one */ 1354 param_off = SMB_HEADER_ED_LEN + RESP_HEADER_LEN; 1355 param_disp = (first_resp) ? 0 : n_param; 1356 1357 /* 1358 * Calling MBC_INIT() will initialized the structure and so the 1359 * pointer to the mbuf chains will be lost. Therefore, we need 1360 * to free the resources if any before calling MBC_INIT(). 1361 */ 1362 m_freem(xa->rep_param_mb.chain); 1363 MBC_INIT(&xa->rep_param_mb, param_scnt); 1364 if (first_resp) { 1365 first_resp = 0; 1366 /* Prepare parameters for the 1st response packet */ 1367 ret_stat = (shares_tot_num > shr_enum_info.sei_count) 1368 ? ERROR_MORE_DATA : 0; 1369 (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 1370 ret_stat, -shr_enum_info.sei_infolen, 1371 shr_enum_info.sei_count, 1372 shares_tot_num); 1373 } 1374 1375 data_pad = (param_off + n_param) & 1; /* Pad to short */ 1376 1377 /* data off from hdr start */ 1378 data_off = param_off + param_scnt + data_pad; 1379 data_disp = tot_data_scnt - data_scnt; 1380 tot_packet_bytes = param_pad + param_scnt + data_pad + 1381 data_scnt; 1382 1383 /* 1384 * Calling MBC_INIT() will initialized the structure and so the 1385 * pointer to the mbuf chains will be lost. Therefore, we need 1386 * to free the resources if any before calling MBC_INIT(). 1387 */ 1388 m_freem(reply.chain); 1389 MBC_INIT(&reply, SMB_HEADER_ED_LEN 1390 + sizeof (uchar_t) /* word parameters count */ 1391 + 10*sizeof (ushort_t) /* word parameters */ 1392 + n_setup*sizeof (ushort_t) /* setup parameters */ 1393 + sizeof (ushort_t) /* total data byte count */ 1394 + tot_packet_bytes); 1395 1396 (void) smb_encode_mbc(&reply, SMB_HEADER_ED_FMT, 1397 sr->first_smb_com, 1398 sr->smb_rcls, 1399 sr->smb_reh, 1400 sr->smb_err, 1401 sr->smb_flg | SMB_FLAGS_REPLY, 1402 sr->smb_flg2, 1403 sr->smb_pid_high, 1404 sr->smb_sig, 1405 sr->smb_tid, 1406 sr->smb_pid, 1407 sr->smb_uid, 1408 sr->smb_mid); 1409 1410 (void) smb_encode_mbc(&reply, 1411 "b ww 2. www www b . C w #. C #. C", 1412 10 + n_setup, /* wct */ 1413 n_param, /* Total Parameter Bytes */ 1414 shares_tot_byte, /* Total Data Bytes */ 1415 param_scnt, /* Total Parameter Bytes this buffer */ 1416 param_off, /* Param offset from header start */ 1417 param_disp, /* Param displacement */ 1418 data_scnt, /* Total Data Bytes this buffer */ 1419 data_off, /* Data offset from header start */ 1420 data_disp, /* Data displacement */ 1421 n_setup, /* suwcnt */ 1422 &xa->rep_setup_mb, /* setup[] */ 1423 tot_packet_bytes, /* Total data bytes */ 1424 param_pad, 1425 &xa->rep_param_mb, 1426 data_pad, 1427 &xa->rep_data_mb); 1428 1429 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) 1430 smb_sign_reply(sr, NULL); 1431 1432 (void) smb_session_send(sr->session, 0, &reply); 1433 } 1434 1435 (void) lmshrd_close_iterator(dhdl, iterator); 1436 MEM_FREE("smb", cmnt_start); 1437 return (SDRC_NO_REPLY); 1438 } 1439 1440 int 1441 smb_trans_net_share_get_info(smb_request_t *sr, struct smb_xa *xa) 1442 { 1443 uint16_t opcode, level, max_bytes, access; 1444 uint32_t type; 1445 unsigned char *req_fmt; 1446 unsigned char *rep_fmt; 1447 struct mbuf_chain str_mb; 1448 char *share; 1449 char *path; 1450 char *password; 1451 char *comment; 1452 lmshare_info_t si; 1453 int shr_found; 1454 1455 if (smb_decode_mbc(&xa->req_param_mb, "%wsss(lev)w(size)w", sr, 1456 &opcode, &req_fmt, &rep_fmt, &share, &level, &max_bytes) != 0) 1457 return (SDRC_NOT_IMPLEMENTED); 1458 1459 (void) utf8_strlwr(share); 1460 shr_found = lmshrd_getinfo(sr->sr_server->sv_lmshrd, share, &si); 1461 if (strcmp(share, "ipc$") == 0) { 1462 type = STYPE_IPC; 1463 path = ""; 1464 password = ""; 1465 access = SHARE_ACCESS_ALL; 1466 } else if (shr_found) { 1467 path = si.directory; 1468 type = STYPE_DISKTREE; 1469 if (path[strlen(path)] == '$') 1470 type |= STYPE_HIDDEN; 1471 password = ""; 1472 access = SHARE_ACCESS_ALL; 1473 } else { 1474 /* We have no idea what this share is... */ 1475 (void) smb_encode_mbc(&xa->rep_param_mb, "www", 1476 NERR_NetNameNotFound, 0, 0); 1477 return (SDRC_SUCCESS); 1478 } 1479 1480 if (shr_found) 1481 comment = si.comment; 1482 else 1483 comment = ""; 1484 1485 password = ""; 1486 1487 MBC_INIT(&str_mb, max_bytes); 1488 1489 switch (level) { 1490 case 0 : 1491 (void) smb_emit_SHARE_INFO_0(&xa->rep_data_mb, 1492 (unsigned char *)share); 1493 break; 1494 1495 case 1 : 1496 (void) smb_emit_SHARE_INFO_1(&xa->rep_data_mb, &str_mb, 1497 (unsigned char *)share, type, 1498 (unsigned char *)comment); 1499 break; 1500 1501 case 2 : 1502 smb_emit_SHARE_INFO_2(&xa->rep_data_mb, &str_mb, sr, 1503 (unsigned char *)share, type, (unsigned char *)comment, 1504 access, path, password); 1505 default: 1506 m_freem(str_mb.chain); 1507 return (SDRC_NOT_IMPLEMENTED); 1508 } 1509 1510 (void) smb_encode_mbc(&xa->rep_param_mb, "www", 0, 1511 -MBC_LENGTH(&xa->rep_data_mb), 1512 MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb)); 1513 (void) smb_encode_mbc(&xa->rep_data_mb, "C", &str_mb); 1514 m_freem(str_mb.chain); 1515 return (SDRC_SUCCESS); 1516 } 1517 1518 int 1519 smb_trans_net_workstation_get_info(struct smb_request *sr, struct smb_xa *xa) 1520 { 1521 uint16_t opcode, level, max_bytes; 1522 unsigned char *req_fmt; 1523 unsigned char *rep_fmt; 1524 struct mbuf_chain str_mb; 1525 char *domain; 1526 char *hostname; 1527 1528 if ((smb_decode_mbc(&xa->req_param_mb, "%wss(lev)w(size)w", sr, 1529 &opcode, &req_fmt, &rep_fmt, &level, &max_bytes) != 0) || 1530 (level != 10)) { 1531 (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 1532 NERR_BadTransactConfig, 0, 0, 0); 1533 return (SDRC_SUCCESS); 1534 } 1535 1536 domain = sr->sr_cfg->skc_resource_domain; 1537 hostname = sr->sr_cfg->skc_hostname; 1538 1539 MBC_INIT(&str_mb, max_bytes); 1540 1541 (void) smb_encode_mbc(&str_mb, "."); /* Prevent NULL pointers */ 1542 1543 (void) smb_encode_mbc(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 1544 (void) smb_encode_mbc(&str_mb, "s", hostname); 1545 (void) smb_encode_mbc(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 1546 (void) smb_encode_mbc(&str_mb, "s", "nobody"); 1547 (void) smb_encode_mbc(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 1548 (void) smb_encode_mbc(&str_mb, "s", domain); 1549 (void) smb_encode_mbc(&xa->rep_data_mb, "bbl", 1550 SMB_VERSION_MAJOR, SMB_VERSION_MINOR, MBC_LENGTH(&str_mb)); 1551 (void) smb_encode_mbc(&str_mb, "s", domain); 1552 (void) smb_encode_mbc(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb)); 1553 (void) smb_encode_mbc(&str_mb, "s", domain); 1554 1555 (void) smb_encode_mbc(&xa->rep_param_mb, "www", 0, 1556 -MBC_LENGTH(&xa->rep_data_mb), 1557 MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb)); 1558 (void) smb_encode_mbc(&xa->rep_data_mb, "C", &str_mb); 1559 m_freem(str_mb.chain); 1560 return (SDRC_SUCCESS); 1561 } 1562 1563 int 1564 smb_trans_net_user_get_info(struct smb_request *sr, struct smb_xa *xa) 1565 { 1566 uint16_t opcode, level, max_bytes; 1567 unsigned char *req_fmt; 1568 unsigned char *rep_fmt; 1569 unsigned char *user; 1570 int rc; 1571 1572 rc = smb_decode_mbc(&xa->req_param_mb, "%wssww", sr, 1573 &opcode, 1574 &req_fmt, 1575 &rep_fmt, 1576 &user, 1577 &level, 1578 &max_bytes); 1579 1580 if (rc != 0) 1581 return (SDRC_NOT_IMPLEMENTED); 1582 1583 (void) smb_encode_mbc(&xa->rep_param_mb, "www", 1584 NERR_UserNotFound, 0, 0); 1585 return (SDRC_SUCCESS); 1586 } 1587 1588 smb_sdrc_t 1589 smb_trans_server_get_info(struct smb_request *sr, struct smb_xa *xa) 1590 { 1591 uint16_t opcode, level, buf_size; 1592 char *req_fmt; 1593 char *rep_fmt; 1594 char server_name[16]; 1595 struct mbuf_chain str_mb; 1596 char *hostname; 1597 char *comment; 1598 1599 if (smb_decode_mbc(&xa->req_param_mb, "%wssww", sr, 1600 &opcode, &req_fmt, &rep_fmt, &level, &buf_size) != 0) { 1601 return (SDRC_ERROR); 1602 } 1603 1604 comment = sr->sr_cfg->skc_system_comment; 1605 hostname = sr->sr_cfg->skc_hostname; 1606 1607 MBC_INIT(&str_mb, buf_size); 1608 1609 bzero(server_name, sizeof (server_name)); 1610 (void) strncpy(server_name, hostname, sizeof (server_name)); 1611 1612 switch (level) { 1613 case 0: 1614 (void) smb_encode_mbc(&xa->rep_data_mb, "16c", server_name); 1615 break; 1616 case 1: 1617 (void) smb_encode_mbc(&str_mb, "."); /* Prevent NULL pointers */ 1618 (void) smb_encode_mbc(&xa->rep_data_mb, "16cbbll", server_name, 1619 SMB_VERSION_MAJOR, SMB_VERSION_MINOR, 1620 MY_SERVER_TYPE, MBC_LENGTH(&str_mb)); 1621 (void) smb_encode_mbc(&str_mb, "s", comment); 1622 break; 1623 case 2: 1624 /* B16BBDzDDDWWzWWWWWWWB21BzWWWWWWWWWWWWWWWWWWWWWWz */ 1625 (void) smb_encode_mbc(&str_mb, "."); /* Prevent NULL pointers */ 1626 /* B16BBDz */ 1627 (void) smb_encode_mbc(&xa->rep_data_mb, "16cbbll", server_name, 1628 SMB_VERSION_MAJOR, 1629 SMB_VERSION_MINOR, MY_SERVER_TYPE, MBC_LENGTH(&str_mb)); 1630 (void) smb_encode_mbc(&str_mb, "s", comment); 1631 (void) smb_encode_mbc(&xa->rep_data_mb, "lllwwl", 1632 (uint32_t)1, 1633 (uint32_t)2, 1634 (uint32_t)3, 1635 (uint16_t)4, 1636 (uint16_t)5, 1637 MBC_LENGTH(&str_mb)); 1638 (void) smb_encode_mbc(&str_mb, "s", "str1"); 1639 (void) smb_encode_mbc(&xa->rep_data_mb, "wwwwwww21cbl", 1640 (uint16_t)6, 1641 (uint16_t)7, 1642 (uint16_t)8, 1643 (uint16_t)9, 1644 (uint16_t)10, 1645 (uint16_t)11, 1646 (uint16_t)12, 1647 "21 byte comment ", 1648 (unsigned char)13, 1649 MBC_LENGTH(&str_mb)); 1650 (void) smb_encode_mbc(&str_mb, "s", "str2"); 1651 (void) smb_encode_mbc(&xa->rep_data_mb, 1652 "wwwwwwwwwwwwwwwwwwwwwwl", 1653 (uint16_t)14, 1654 (uint16_t)15, 1655 (uint16_t)16, 1656 (uint16_t)17, 1657 (uint16_t)18, 1658 (uint16_t)19, 1659 (uint16_t)20, 1660 (uint16_t)21, 1661 (uint16_t)22, 1662 (uint16_t)23, 1663 (uint16_t)24, 1664 (uint16_t)25, 1665 (uint16_t)26, 1666 (uint16_t)27, 1667 (uint16_t)28, 1668 (uint16_t)29, 1669 (uint16_t)20, 1670 (uint16_t)31, 1671 (uint16_t)32, 1672 (uint16_t)33, 1673 (uint16_t)34, 1674 (uint16_t)35, 1675 MBC_LENGTH(&str_mb)); 1676 (void) smb_encode_mbc(&str_mb, "s", "str3"); 1677 break; 1678 default: 1679 m_freem(str_mb.chain); 1680 return (SDRC_NOT_IMPLEMENTED); 1681 } 1682 1683 (void) smb_encode_mbc(&xa->rep_param_mb, "www", 0, 1684 -MBC_LENGTH(&xa->rep_data_mb), 1685 (MBC_LENGTH(&xa->rep_data_mb)) + 1686 (MBC_LENGTH(&str_mb))); 1687 (void) smb_encode_mbc(&xa->rep_data_mb, "C", &str_mb); 1688 m_freem(str_mb.chain); 1689 return (SDRC_SUCCESS); 1690 } 1691 1692 /* 1693 * 6.4 The NetServerEnum2 RAP Service 1694 * 1695 * The NetServerEnum2 RAP service lists all computers of the specified type 1696 * or types that are visible in the specified domains. It may also 1697 * enumerate domains. 1698 * 1699 * The following definition uses the notation and terminology defined in 1700 * the CIFS Remote Administration Protocol specification, which is required 1701 * in order to make it well-defined. The definition is: 1702 * 1703 * uint16_t NetServerEnum2 ( 1704 * uint16_t sLevel, 1705 * RCVBUF pbBuffer, 1706 * RCVBUFLEN cbBuffer, 1707 * ENTCOUNT pcEntriesRead, 1708 * uint16_t *pcTotalAvail, 1709 * uint32_t fServerType, 1710 * char *pszDomain, 1711 * ); 1712 * 1713 * where: 1714 * 1715 * sLevel specifies the level of detail (0 or 1) requested. 1716 * 1717 * pbBuffer points to the buffer to receive the returned data. If the 1718 * function is successful, the buffer contains a sequence of 1719 * server_info_x structures, where x is 0 or 1, depending on the 1720 * level of detail requested. 1721 * 1722 * cbBuffer specifies the size, in bytes, of the buffer pointed to by 1723 * the pbBuffer parameter. 1724 * 1725 * pcEntriesRead points to a 16 bit variable that receives a count of 1726 * the number of servers enumerated in the buffer. This count is 1727 * valid only if NetServerEnum2 returns the NERR_Success or 1728 * ERROR_MORE_DATA values. 1729 * 1730 * pcTotal Avail points to a 16 bit variable that receives a count of 1731 * the total number of available entries. This count is valid only if 1732 * NetServerEnum2 returns the NERR_Success or ERROR_MORE_DATA values. 1733 * 1734 * fServerType specifies the type or types of computers to enumerate. 1735 * Computers that match at least one of the specified types are 1736 * returned in the buffer. Possible values are defined in the request 1737 * parameters section. 1738 * 1739 * pszDomain points to a null-terminated string that contains the 1740 * name of the workgroup in which to enumerate computers of the 1741 * specified type or types. If the pszDomain parameter is a null 1742 * string or a null pointer, servers are enumerated for the current 1743 * domain of the computer. 1744 * 1745 * 6.4.1 Transaction Request Parameters section 1746 * 1747 * The Transaction request parameters section in this instance contains: 1748 * . The 16 bit function number for NetServerEnum2 which is 104. 1749 * . The parameter descriptor string which is "WrLehDz". 1750 * . The data descriptor string for the (returned) data which is "B16" for 1751 * level detail 0 or "B16BBDz" for level detail 1. 1752 * . The actual parameters as described by the parameter descriptor 1753 * string. 1754 * 1755 * The parameters are: 1756 * . A 16 bit integer with a value of 0 or 1 (corresponding to the "W" in 1757 * the parameter descriptor string. This represents the level of detail 1758 * the server is expected to return 1759 * . A 16 bit integer that contains the size of the receive buffer. 1760 * . A 32 bit integer that represents the type of servers the function 1761 * should enumerate. The possible values may be any of the following or 1762 * a combination of the following: 1763 * 1764 * SV_TYPE_WORKSTATION 0x00000001 All workstations 1765 * SV_TYPE_SERVER 0x00000002 All servers 1766 * SV_TYPE_SQLSERVER 0x00000004 Any server running with SQL 1767 * server 1768 * SV_TYPE_DOMAIN_CTRL 0x00000008 Primary domain controller 1769 * SV_TYPE_DOMAIN_BAKCTRL 0x00000010 Backup domain controller 1770 * SV_TYPE_TIME_SOURCE 0x00000020 Server running the timesource 1771 * service 1772 * SV_TYPE_AFP 0x00000040 Apple File Protocol servers 1773 * SV_TYPE_NOVELL 0x00000080 Novell servers 1774 * SV_TYPE_DOMAIN_MEMBER 0x00000100 Domain Member 1775 * SV_TYPE_PRINTQ_SERVER 0x00000200 Server sharing print queue 1776 * SV_TYPE_DIALIN_SERVER 0x00000400 Server running dialin service. 1777 * SV_TYPE_XENIX_SERVER 0x00000800 Xenix server 1778 * SV_TYPE_NT 0x00001000 NT server 1779 * SV_TYPE_WFW 0x00002000 Server running Windows for 1780 * Workgroups 1781 * SV_TYPE_SERVER_NT 0x00008000 Windows NT non DC server 1782 * SV_TYPE_POTENTIAL_BROWSER 0x00010000 Server that can run the browser 1783 * service 1784 * SV_TYPE_BACKUP_BROWSER 0x00020000 Backup browser server 1785 * SV_TYPE_MASTER_BROWSER 0x00040000 Master browser server 1786 * SV_TYPE_DOMAIN_MASTER 0x00080000 Domain Master Browser server 1787 * SV_TYPE_LOCAL_LIST_ONLY 0x40000000 Enumerate only entries marked 1788 * "local" 1789 * SV_TYPE_DOMAIN_ENUM 0x80000000 Enumerate Domains. The pszDomain 1790 * parameter must be NULL. 1791 * 1792 * . A null terminated ASCII string representing the pszDomain parameter 1793 * described above 1794 * 1795 * 6.4.2 Transaction Request Data section 1796 * 1797 * There is no data or auxiliary data to send as part of the request. 1798 * 1799 * 6.4.3 Transaction Response Parameters section 1800 * 1801 * The transaction response parameters section consists of: 1802 * . A 16 bit word indicating the return status. The possible values are: 1803 * 1804 * Code Value Description 1805 * NERR_Success 0 No errors encountered 1806 * ERROR_MORE_DATA 234 Additional data is available 1807 * NERR_ServerNotStarted 2114 The RAP service on the remote computer 1808 * is not running 1809 * NERR_BadTransactConfig 2141 The server is not configured for 1810 * transactions, IPC$ is not shared 1811 * 1812 * . A 16 bit "converter" word. 1813 * . A 16 bit number representing the number of entries returned. 1814 * . A 16 bit number representing the total number of available entries. 1815 * If the supplied buffer is large enough, this will equal the number of 1816 * entries returned. 1817 * 1818 * 6.4.4 Transaction Response Data section 1819 * 1820 * The return data section consists of a number of SERVER_INFO_1 structures. 1821 * The number of such structures present is determined by the third entry 1822 * (described above) in the return parameters section. 1823 * 1824 * At level detail 0, the Transaction response data section contains a 1825 * number of SERVER_INFO_0 data structure. The number of such structures is 1826 * equal to the 16 bit number returned by the server in the third parameter 1827 * in the Transaction response parameter section. The SERVER_INFO_0 data 1828 * structure is defined as: 1829 * 1830 * struct SERVER_INFO_0 { 1831 * char sv0_name[16]; 1832 * }; 1833 * 1834 * where: 1835 * 1836 * sv0_name is a null-terminated string that specifies the name of a 1837 * computer or domain . 1838 * 1839 * At level detail 1, the Transaction response data section contains a 1840 * number of SERVER_INFO_1 data structure. The number of such structures is 1841 * equal to the 16 bit number returned by the server in the third parameter 1842 * in the Transaction response parameter section. The SERVER_INFO_1 data 1843 * structure is defined as: 1844 * 1845 * struct SERVER_INFO_1 { 1846 * char sv1_name[16]; 1847 * char sv1_version_major; 1848 * char sv1_version_minor; 1849 * uint32_t sv1_type; 1850 * char *sv1_comment_or_master_browser; 1851 * }; 1852 * 1853 * sv1_name contains a null-terminated string that specifies the name 1854 * of a computer, or a domain name if SV_TYPE_DOMAIN_ENUM is set in 1855 * sv1_type. 1856 * 1857 * sv1_version_major whatever was specified in the HostAnnouncement 1858 * or DomainAnnouncement frame with which the entry was registered. 1859 * 1860 * sv1_version_minor whatever was specified in the HostAnnouncement 1861 * or DomainAnnouncement frame with which the entry was registered. 1862 * 1863 * sv1_type specifies the type of software the computer is running. 1864 * The member can be one or a combination of the values defined above 1865 * in the Transaction request parameters section for fServerType. 1866 * 1867 * 1868 * sv1_comment_or_master_browser points to a null-terminated string. If 1869 * the sv1_type indicates that the entry is for a domain, this 1870 * specifies the name of server running the domain master browser; 1871 * otherwise, it specifies a comment describing the server. The comment 1872 * can be a null string or the pointer may be a null pointer. 1873 * 1874 * In case there are multiple SERVER_INFO_1 data structures to 1875 * return, the server may put all these fixed length structures in 1876 * the return buffer, leave some space and then put all the variable 1877 * length data (the actual value of the sv1_comment strings) at the 1878 * end of the buffer. 1879 * 1880 * There is no auxiliary data to receive. 1881 */ 1882 1883 int 1884 smb_trans_net_server_enum2(struct smb_request *sr, struct smb_xa *xa) 1885 { 1886 uint16_t opcode, level, max_bytes; 1887 uint32_t server_type; 1888 unsigned char *domain; 1889 struct mbuf_chain str_mb; 1890 char *hostname, *s; 1891 smb_kmod_cfg_t *si; 1892 1893 if (smb_decode_mbc(&xa->req_param_mb, 1894 "%w s(request format) s(reply format) wwls", sr, &opcode, &s, &s, 1895 &level, &max_bytes, &server_type, &domain) != 0) 1896 return (SDRC_NOT_IMPLEMENTED); 1897 1898 si = sr->sr_cfg; 1899 1900 if (utf8_strcasecmp(si->skc_resource_domain, (char *)domain) != 0) { 1901 (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 0, 0, 0, 0); 1902 return (SDRC_SUCCESS); 1903 } 1904 1905 if ((server_type & MY_SERVER_TYPE) == 0) { 1906 (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 0, 0, 0, 0); 1907 return (SDRC_SUCCESS); 1908 } 1909 1910 MBC_INIT(&str_mb, max_bytes); 1911 1912 hostname = si->skc_hostname; 1913 1914 (void) smb_encode_mbc(&xa->rep_data_mb, "16c", hostname); 1915 if (level == 1) { 1916 (void) smb_encode_mbc(&xa->rep_data_mb, "bbll", 1917 SMB_VERSION_MAJOR, SMB_VERSION_MINOR, 1918 MY_SERVER_TYPE, MBC_LENGTH(&str_mb)); 1919 (void) smb_encode_mbc(&str_mb, "s", si->skc_system_comment); 1920 } 1921 1922 (void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 0, 1923 -MBC_LENGTH(&xa->rep_data_mb), 1, 1); 1924 (void) smb_encode_mbc(&xa->rep_data_mb, "m", str_mb.chain); 1925 return (SDRC_SUCCESS); 1926 } 1927 1928 /* 1929 * is_supported_pipe 1930 * 1931 * Currently, just return 0 if the pipe is \\PIPE\repl otherwise 1932 * return 1. 1933 */ 1934 int 1935 is_supported_pipe(char *pname) 1936 { 1937 if (utf8_strcasecmp(pname, PIPE_REPL) == 0) 1938 return (0); 1939 1940 return (1); 1941 } 1942 1943 static smb_sdrc_t 1944 smb_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) 1945 { 1946 int rc, pos; 1947 int total_bytes, n_setup, n_param, n_data; 1948 int param_off, param_pad, data_off, data_pad; 1949 uint16_t opcode; 1950 uint16_t devstate; 1951 char *req_fmt; 1952 char *rep_fmt; 1953 struct vardata_block vdb; 1954 1955 n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200; 1956 n_setup++; 1957 n_setup = n_setup & ~0x0001; 1958 n_param = (xa->smb_mprcnt < smb_maxbufsize) 1959 ? xa->smb_mprcnt : smb_maxbufsize; 1960 n_param++; 1961 n_param = n_param & ~0x0001; 1962 rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param); 1963 n_data = (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc; 1964 MBC_INIT(&xa->rep_setup_mb, n_setup * 2); 1965 MBC_INIT(&xa->rep_param_mb, n_param); 1966 MBC_INIT(&xa->rep_data_mb, n_data); 1967 1968 if (xa->smb_suwcnt > 0 && STYPE_ISIPC(sr->tid_tree->t_res_type)) { 1969 rc = smb_decode_mbc(&xa->req_setup_mb, "ww", &opcode, 1970 &sr->smb_fid); 1971 if (rc != 0) 1972 goto trans_err_not_supported; 1973 switch (opcode) { 1974 case TRANS_SET_NMPIPE_STATE: 1975 if ((rc = smb_decode_mbc(&xa->req_param_mb, "w", 1976 &devstate)) != 0) 1977 goto trans_err_not_supported; 1978 1979 rc = SDRC_SUCCESS; 1980 break; 1981 1982 case TRANS_TRANSACT_NMPIPE: 1983 sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, 1984 sr->smb_fid); 1985 if (sr->fid_ofile == NULL) { 1986 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 1987 ERRDOS, ERRbadfid); 1988 return (SDRC_ERROR); 1989 } 1990 1991 rc = smb_decode_mbc(&xa->req_data_mb, "#B", 1992 xa->smb_tdscnt, &vdb); 1993 if (rc != 0) 1994 goto trans_err_not_supported; 1995 1996 rc = smb_rpc_transact(sr, &vdb.uio); 1997 break; 1998 1999 case TRANS_WAIT_NMPIPE: 2000 if (is_supported_pipe(xa->xa_smb_trans_name) == 0) { 2001 smbsr_error(sr, 0, ERRDOS, ERRbadfile); 2002 return (SDRC_ERROR); 2003 } 2004 rc = SDRC_SUCCESS; 2005 break; 2006 2007 default: 2008 goto trans_err_not_supported; 2009 } 2010 } else { 2011 if ((utf8_strcasecmp(xa->xa_smb_trans_name, 2012 PIPE_LANMAN) != 0) && 2013 (utf8_strcasecmp( 2014 xa->xa_smb_trans_name, MAILSLOT_LANMAN) != 0) && 2015 (utf8_strcasecmp( 2016 xa->xa_smb_trans_name, MAILSLOT_BROWSE) != 0) && 2017 (utf8_strcasecmp( 2018 xa->xa_smb_trans_name, MAILSLOT_MSBROWSE) != 0)) 2019 goto trans_err_not_supported; 2020 2021 if ((rc = smb_decode_mbc(&xa->req_param_mb, "%wss\b", sr, 2022 &opcode, &req_fmt, &rep_fmt)) != 0) 2023 goto trans_err_not_supported; 2024 2025 /* for now, only respond to the */ 2026 switch (opcode) { 2027 case API_WshareEnum: 2028 rc = smb_trans_net_share_enum(sr, xa); 2029 break; 2030 2031 case API_WshareGetInfo: 2032 rc = smb_trans_net_share_get_info(sr, xa); 2033 break; 2034 2035 case API_WserverGetInfo: 2036 rc = smb_trans_server_get_info(sr, xa); 2037 break; 2038 2039 case API_WUserGetInfo: 2040 rc = smb_trans_net_user_get_info(sr, xa); 2041 break; 2042 2043 case API_WWkstaGetInfo: 2044 rc = smb_trans_net_workstation_get_info(sr, xa); 2045 break; 2046 2047 case API_NetServerEnum2: 2048 rc = smb_trans_net_server_enum2(sr, xa); 2049 break; 2050 2051 default: 2052 goto trans_err_not_supported; 2053 } 2054 } 2055 2056 switch (rc) { 2057 case SDRC_SUCCESS: 2058 break; 2059 2060 case SDRC_DROP_VC: 2061 case SDRC_NO_REPLY: 2062 case SDRC_ERROR: 2063 return (rc); 2064 2065 case SDRC_NOT_IMPLEMENTED: 2066 goto trans_err_not_supported; 2067 2068 default: 2069 break; 2070 } 2071 2072 n_setup = MBC_LENGTH(&xa->rep_setup_mb); 2073 n_param = MBC_LENGTH(&xa->rep_param_mb); 2074 n_data = MBC_LENGTH(&xa->rep_data_mb); 2075 2076 if (xa->smb_msrcnt < n_setup || 2077 xa->smb_mprcnt < n_param || 2078 xa->smb_mdrcnt < n_data) { 2079 goto trans_err_too_small; 2080 } 2081 2082 /* neato, blast it over there */ 2083 2084 n_setup = (n_setup + 1) / 2; /* Convert to setup words */ 2085 param_pad = 1; /* always one */ 2086 param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 2087 data_pad = (param_off + n_param) & 1; /* Pad to short */ 2088 /* Param off from hdr start */ 2089 data_off = param_off + n_param + data_pad; 2090 total_bytes = param_pad + n_param + data_pad + n_data; 2091 2092 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, 2093 "b ww 2. www www b . C w #. C #. C", 2094 10 + n_setup, /* wct */ 2095 n_param, /* Total Parameter Bytes */ 2096 n_data, /* Total Data Bytes */ 2097 n_param, /* Total Parameter Bytes this buffer */ 2098 param_off, /* Param offset from header start */ 2099 0, /* Param displacement */ 2100 n_data, /* Total Data Bytes this buffer */ 2101 data_off, /* Data offset from header start */ 2102 0, /* Data displacement */ 2103 n_setup, /* suwcnt */ 2104 &xa->rep_setup_mb, /* setup[] */ 2105 total_bytes, /* Total data bytes */ 2106 param_pad, 2107 &xa->rep_param_mb, 2108 data_pad, 2109 &xa->rep_data_mb); 2110 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 2111 2112 trans_err_too_small: 2113 rc = NERR_BufTooSmall; 2114 goto trans_err; 2115 2116 trans_err_not_supported: 2117 rc = ERROR_NOT_SUPPORTED; 2118 goto trans_err; 2119 2120 trans_err: 2121 pos = MBC_LENGTH(&sr->reply) + 23; 2122 rc = smbsr_encode_result(sr, 10, 4, "b ww 2. www www b . w ww", 2123 10, /* wct */ 2124 4, 0, /* tpscnt tdscnt */ 2125 4, pos, 0, /* pscnt psoff psdisp */ 2126 0, 0, 0, /* dscnt dsoff dsdisp */ 2127 0, /* suwcnt */ 2128 4, /* bcc */ 2129 rc, 2130 0); /* converter word? */ 2131 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 2132 } 2133 2134 static smb_sdrc_t 2135 smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) 2136 { 2137 int rc, pos; 2138 int total_bytes, n_setup, n_param, n_data; 2139 int param_off, param_pad, data_off, data_pad; 2140 uint16_t opcode; 2141 uint16_t nt_unknown_secret = 0x0100; 2142 char *fmt; 2143 2144 n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200; 2145 n_setup++; 2146 n_setup = n_setup & ~0x0001; 2147 n_param = (xa->smb_mprcnt < smb_maxbufsize) 2148 ? xa->smb_mprcnt : smb_maxbufsize; 2149 n_param++; 2150 n_param = n_param & ~0x0001; 2151 rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param); 2152 n_data = (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc; 2153 MBC_INIT(&xa->rep_setup_mb, n_setup * 2); 2154 MBC_INIT(&xa->rep_param_mb, n_param); 2155 MBC_INIT(&xa->rep_data_mb, n_data); 2156 2157 if (smb_decode_mbc(&xa->req_setup_mb, "w", &opcode) != 0) 2158 goto trans_err_not_supported; 2159 2160 /* 2161 * Save this for /proc to read later. 2162 */ 2163 xa->smb_func = opcode; 2164 2165 /* for now, only respond to the */ 2166 switch (opcode) { 2167 case TRANS2_CREATE_DIRECTORY: 2168 rc = smb_com_trans2_create_directory(sr, xa); 2169 break; 2170 2171 case TRANS2_FIND_FIRST2: 2172 /* 2173 * Should have enough room to send the response 2174 * data back to client. 2175 */ 2176 if (n_data == 0) { 2177 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 2178 ERRDOS, ERROR_BAD_LENGTH); 2179 return (SDRC_ERROR); 2180 } 2181 rc = smb_com_trans2_find_first2(sr, xa); 2182 break; 2183 2184 case TRANS2_FIND_NEXT2: 2185 /* 2186 * Should have enough room to send the response 2187 * data back to client. 2188 */ 2189 if (n_data == 0) { 2190 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 2191 ERRDOS, ERROR_BAD_LENGTH); 2192 return (SDRC_ERROR); 2193 } 2194 rc = smb_com_trans2_find_next2(sr, xa); 2195 break; 2196 2197 case TRANS2_QUERY_FS_INFORMATION: 2198 /* 2199 * Should have enough room to send the response 2200 * data back to client. 2201 */ 2202 if (n_data == 0) { 2203 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 2204 ERRDOS, ERROR_BAD_LENGTH); 2205 return (SDRC_ERROR); 2206 } 2207 rc = smb_com_trans2_query_fs_information(sr, xa); 2208 break; 2209 2210 case TRANS2_QUERY_PATH_INFORMATION: 2211 /* 2212 * Should have enough room to send the response 2213 * data back to client. 2214 */ 2215 if (n_data == 0) { 2216 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 2217 ERRDOS, ERROR_BAD_LENGTH); 2218 return (SDRC_ERROR); 2219 } 2220 rc = smb_com_trans2_query_path_information(sr, xa); 2221 break; 2222 2223 case TRANS2_QUERY_FILE_INFORMATION: 2224 /* 2225 * Should have enough room to send the response 2226 * data back to client. 2227 */ 2228 if (n_data == 0) { 2229 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, 2230 ERRDOS, ERROR_BAD_LENGTH); 2231 return (SDRC_ERROR); 2232 } 2233 rc = smb_com_trans2_query_file_information(sr, xa); 2234 break; 2235 2236 case TRANS2_SET_PATH_INFORMATION: 2237 rc = smb_com_trans2_set_path_information(sr, xa); 2238 break; 2239 2240 case TRANS2_SET_FILE_INFORMATION: 2241 rc = smb_com_trans2_set_file_information(sr, xa); 2242 break; 2243 default: 2244 goto trans_err_not_supported; 2245 } 2246 2247 switch (rc) { 2248 case SDRC_SUCCESS: 2249 break; 2250 2251 case SDRC_DROP_VC: 2252 case SDRC_NO_REPLY: 2253 case SDRC_ERROR: 2254 return (rc); 2255 2256 case SDRC_NOT_IMPLEMENTED: 2257 goto trans_err_not_supported; 2258 2259 default: 2260 break; 2261 } 2262 2263 n_setup = MBC_LENGTH(&xa->rep_setup_mb); 2264 n_param = MBC_LENGTH(&xa->rep_param_mb); 2265 n_data = MBC_LENGTH(&xa->rep_data_mb); 2266 2267 if (xa->smb_msrcnt < n_setup || 2268 xa->smb_mprcnt < n_param || 2269 xa->smb_mdrcnt < n_data) { 2270 goto trans_err_too_small; 2271 } 2272 2273 /* neato, blast it over there */ 2274 2275 n_setup = (n_setup + 1) / 2; /* Conver to setup words */ 2276 param_pad = 1; /* must be one */ 2277 param_off = param_pad + 32 + 21 + (n_setup << 1) + 2; 2278 2279 /* 2280 * Including the nt_unknown_secret value persuades netmon to 2281 * display the correct data format for QueryPathInfo and 2282 * QueryFileInfo. 2283 */ 2284 if (opcode == TRANS2_QUERY_FILE_INFORMATION || 2285 opcode == TRANS2_QUERY_PATH_INFORMATION) { 2286 data_pad = sizeof (uint16_t); 2287 data_off = param_off + n_param + data_pad; 2288 fmt = "b ww 2. www www b . C w #. C w C"; 2289 nt_unknown_secret = 0x0100; 2290 } 2291 else 2292 { 2293 data_pad = (param_off + n_param) & 1; /* Pad to short */ 2294 /* Param off from hdr start */ 2295 data_off = param_off + n_param + data_pad; 2296 fmt = "b ww 2. www www b . C w #. C #. C"; 2297 /*LINTED E_ASSIGN_NARROW_CONV*/ 2298 nt_unknown_secret = data_pad; 2299 } 2300 2301 total_bytes = param_pad + n_param + data_pad + n_data; 2302 2303 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes, 2304 fmt, 2305 10 + n_setup, /* wct */ 2306 n_param, /* Total Parameter Bytes */ 2307 n_data /* + data_pad */, /* Total Data Bytes */ 2308 n_param, /* Total Parameter Bytes this buffer */ 2309 param_off, /* Param offset from header start */ 2310 0, /* Param displacement */ 2311 n_data /* + data_pad */, /* Total Data Bytes this buffer */ 2312 data_off, /* Data offset from header start */ 2313 0, /* Data displacement */ 2314 n_setup, /* suwcnt */ 2315 &xa->rep_setup_mb, /* setup[] */ 2316 total_bytes, /* Total data bytes */ 2317 param_pad, 2318 &xa->rep_param_mb, 2319 nt_unknown_secret, 2320 &xa->rep_data_mb); 2321 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 2322 2323 trans_err_too_small: 2324 rc = NERR_BufTooSmall; 2325 goto trans_err; 2326 2327 trans_err_not_supported: 2328 rc = ERROR_NOT_SUPPORTED; 2329 goto trans_err; 2330 2331 trans_err: 2332 pos = MBC_LENGTH(&sr->reply) + 23; 2333 rc = smbsr_encode_result(sr, 10, 4, "b ww 2. www www b . w ww", 2334 10, /* wct */ 2335 4, 0, /* tpscnt tdscnt */ 2336 4, pos, 0, /* pscnt psoff psdisp */ 2337 0, 0, 0, /* dscnt dsoff dsdisp */ 2338 0, /* suwcnt */ 2339 4, /* bcc */ 2340 rc, 2341 0); /* converter word? */ 2342 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 2343 } 2344 2345 smb_xa_t * 2346 smb_xa_create( 2347 smb_session_t *session, 2348 smb_request_t *sr, 2349 uint32_t total_parameter_count, 2350 uint32_t total_data_count, 2351 uint32_t max_parameter_count, 2352 uint32_t max_data_count, 2353 uint32_t max_setup_count, 2354 uint32_t setup_word_count) 2355 { 2356 smb_xa_t *xa, *nxa; 2357 smb_llist_t *xlist; 2358 2359 xa = MEM_ZALLOC("xa", sizeof (smb_xa_t)); 2360 xa->xa_refcnt = 1; 2361 xa->smb_com = sr->smb_com; 2362 xa->smb_flg = sr->smb_flg; 2363 xa->smb_flg2 = sr->smb_flg2; 2364 xa->smb_tid = sr->smb_tid; 2365 xa->smb_pid = sr->smb_pid; 2366 xa->smb_uid = sr->smb_uid; 2367 xa->xa_smb_mid = sr->smb_mid; 2368 xa->reply_seqnum = sr->reply_seqnum; 2369 xa->smb_tpscnt = total_parameter_count; 2370 xa->smb_tdscnt = total_data_count; 2371 xa->smb_mprcnt = max_parameter_count; 2372 xa->smb_mdrcnt = max_data_count; 2373 xa->smb_msrcnt = max_setup_count; 2374 xa->smb_suwcnt = setup_word_count; 2375 xa->xa_session = session; 2376 xa->xa_magic = SMB_XA_MAGIC; 2377 2378 /* 2379 * The new xa structure is checked against the current list to see 2380 * if it exists already. 2381 */ 2382 xlist = &session->s_xa_list; 2383 smb_llist_enter(xlist, RW_WRITER); 2384 nxa = smb_llist_head(xlist); 2385 while (nxa) { 2386 ASSERT(nxa->xa_magic == SMB_XA_MAGIC); 2387 if (nxa->xa_smb_mid == xa->xa_smb_mid && 2388 nxa->smb_pid == xa->smb_pid && 2389 !SMB_XA_CLOSED(nxa) && 2390 !(nxa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 2391 smb_llist_exit(xlist); 2392 MEM_FREE("xa", xa); 2393 return (NULL); 2394 } 2395 nxa = smb_llist_next(xlist, nxa); 2396 } 2397 smb_llist_insert_tail(xlist, xa); 2398 smb_llist_exit(xlist); 2399 return (xa); 2400 } 2401 2402 void 2403 smb_xa_delete(smb_xa_t *xa) 2404 { 2405 ASSERT(xa->xa_refcnt == 0); 2406 ASSERT(SMB_XA_CLOSED(xa)); 2407 2408 if (xa->xa_smb_trans_name) 2409 MEM_FREE("smb", xa->xa_smb_trans_name); 2410 2411 if (xa->rep_setup_mb.chain != NULL) 2412 m_freem(xa->rep_setup_mb.chain); 2413 if (xa->rep_param_mb.chain != NULL) 2414 m_freem(xa->rep_param_mb.chain); 2415 if (xa->rep_data_mb.chain != NULL) 2416 m_freem(xa->rep_data_mb.chain); 2417 2418 xa->xa_magic = (uint32_t)~SMB_XA_MAGIC; 2419 MEM_FREE("xa", xa); 2420 } 2421 2422 smb_xa_t * 2423 smb_xa_hold(smb_xa_t *xa) 2424 { 2425 mutex_enter(&xa->xa_mutex); 2426 xa->xa_refcnt++; 2427 ASSERT(xa->xa_refcnt); 2428 mutex_exit(&xa->xa_mutex); 2429 return (xa); 2430 } 2431 2432 void 2433 smb_xa_rele(smb_session_t *session, smb_xa_t *xa) 2434 { 2435 mutex_enter(&xa->xa_mutex); 2436 ASSERT(xa->xa_refcnt); 2437 xa->xa_refcnt--; 2438 if (SMB_XA_CLOSED(xa) && (xa->xa_refcnt == 0)) { 2439 mutex_exit(&xa->xa_mutex); 2440 smb_llist_enter(&session->s_xa_list, RW_WRITER); 2441 smb_llist_remove(&session->s_xa_list, xa); 2442 smb_llist_exit(&session->s_xa_list); 2443 smb_xa_delete(xa); 2444 return; 2445 } 2446 mutex_exit(&xa->xa_mutex); 2447 } 2448 2449 int 2450 smb_xa_open(smb_xa_t *xa) 2451 { 2452 int rc; 2453 2454 mutex_enter(&xa->xa_mutex); 2455 2456 ASSERT((xa->xa_flags & SMB_XA_FLAG_OPEN) == 0); 2457 2458 if ((xa->xa_flags & SMB_XA_FLAG_CLOSE) == 0) { 2459 xa->xa_flags |= SMB_XA_FLAG_OPEN; 2460 rc = 0; 2461 } else { 2462 rc = ERROR_INVALID_HANDLE; 2463 } 2464 2465 mutex_exit(&xa->xa_mutex); 2466 2467 return (rc); 2468 } 2469 2470 void 2471 smb_xa_close(smb_xa_t *xa) 2472 { 2473 mutex_enter(&xa->xa_mutex); 2474 xa->xa_flags |= SMB_XA_FLAG_CLOSE; 2475 xa->xa_flags &= ~SMB_XA_FLAG_OPEN; 2476 2477 if (xa->xa_refcnt == 0) { 2478 mutex_exit(&xa->xa_mutex); 2479 smb_llist_enter(&xa->xa_session->s_xa_list, RW_WRITER); 2480 smb_llist_remove(&xa->xa_session->s_xa_list, xa); 2481 smb_llist_exit(&xa->xa_session->s_xa_list); 2482 smb_xa_delete(xa); 2483 return; 2484 } 2485 2486 mutex_exit(&xa->xa_mutex); 2487 } 2488 2489 int 2490 smb_xa_complete(smb_xa_t *xa) 2491 { 2492 int rc; 2493 2494 mutex_enter(&xa->xa_mutex); 2495 if (xa->xa_flags & (SMB_XA_FLAG_COMPLETE | SMB_XA_FLAG_CLOSE)) { 2496 rc = 0; 2497 } else { 2498 rc = 1; 2499 xa->xa_flags |= SMB_XA_FLAG_COMPLETE; 2500 } 2501 mutex_exit(&xa->xa_mutex); 2502 return (rc); 2503 } 2504 2505 smb_xa_t * 2506 smb_xa_find( 2507 smb_session_t *session, 2508 uint16_t pid, 2509 uint16_t mid) 2510 { 2511 smb_xa_t *xa; 2512 smb_llist_t *xlist; 2513 2514 xlist = &session->s_xa_list; 2515 smb_llist_enter(xlist, RW_READER); 2516 xa = smb_llist_head(xlist); 2517 while (xa) { 2518 mutex_enter(&xa->xa_mutex); 2519 if (xa->xa_smb_mid == mid && 2520 xa->smb_pid == pid && 2521 !SMB_XA_CLOSED(xa) && 2522 !(xa->xa_flags & SMB_XA_FLAG_COMPLETE)) { 2523 xa->xa_refcnt++; 2524 ASSERT(xa->xa_refcnt); 2525 mutex_exit(&xa->xa_mutex); 2526 break; 2527 } 2528 mutex_exit(&xa->xa_mutex); 2529 xa = smb_llist_next(xlist, xa); 2530 } 2531 smb_llist_exit(xlist); 2532 return (xa); 2533 } 2534