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