xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_common_transact.c (revision 13082:81ec56bf6147)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
2112508Samw@Sun.COM 
225331Samw /*
2312065SKeyur.Desai@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
245331Samw  */
255331Samw 
2610966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h>
275331Samw #include <smbsrv/smb_fsops.h>
287052Samw #include <smbsrv/smb_share.h>
2910966SJordan.Brown@Sun.COM #include <smbsrv/string.h>
305331Samw #include <smbsrv/nmpipes.h>
315331Samw #include <smbsrv/mailslot.h>
325331Samw 
335331Samw /*
345331Samw  * count of bytes in server response packet
355331Samw  * except parameters and data. Note that setup
365331Samw  * word count is zero.
375331Samw  */
385331Samw #define	RESP_HEADER_LEN		24
395331Samw 
405331Samw /*
419914Samw@Sun.COM  * We started by using common functions for transaction/transaction2
425331Samw  * and transaction_secondary/transaction2_secondary because they
435331Samw  * are respectively so similar. However, it turned out to be a bad
445331Samw  * idea because of quirky differences. Be sure if you modify one
455331Samw  * of these four functions to check and see if the modification should
465331Samw  * be applied to its peer.
475331Samw  */
485331Samw 
4911963SAfshin.Ardakani@Sun.COM static int smb_trans_ready(smb_xa_t *);
5011963SAfshin.Ardakani@Sun.COM static smb_sdrc_t smb_trans_dispatch(smb_request_t *, smb_xa_t *);
5111963SAfshin.Ardakani@Sun.COM static smb_sdrc_t smb_trans2_dispatch(smb_request_t *, smb_xa_t *);
525331Samw 
536030Sjb150015 smb_sdrc_t
smb_pre_transaction(smb_request_t * sr)546139Sjb150015 smb_pre_transaction(smb_request_t *sr)
556139Sjb150015 {
566139Sjb150015 	DTRACE_SMB_1(op__Transaction__start, smb_request_t *, sr);
576139Sjb150015 	return (SDRC_SUCCESS);
586139Sjb150015 }
596139Sjb150015 
606139Sjb150015 void
smb_post_transaction(smb_request_t * sr)616139Sjb150015 smb_post_transaction(smb_request_t *sr)
626139Sjb150015 {
636139Sjb150015 	DTRACE_SMB_1(op__Transaction__done, smb_request_t *, sr);
646139Sjb150015 }
656139Sjb150015 
666139Sjb150015 smb_sdrc_t
smb_com_transaction(smb_request_t * sr)676139Sjb150015 smb_com_transaction(smb_request_t *sr)
685331Samw {
695331Samw 	int		rc;
705331Samw 	unsigned char	msrcnt, suwcnt;
715331Samw 	uint16_t	tpscnt, tdscnt, mprcnt, mdrcnt, flags;
725331Samw 	uint16_t	pscnt, psoff, dscnt, dsoff;
735331Samw 	uint32_t	timeo;
745331Samw 	struct smb_xa *xa;
755331Samw 	char *stn;
765331Samw 	int ready;
775331Samw 
785331Samw 	rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT,
795331Samw 	    &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &msrcnt, &flags,
805331Samw 	    &timeo, &pscnt, &psoff, &dscnt, &dsoff, &suwcnt);
815331Samw 
826030Sjb150015 	if (rc != 0)
836139Sjb150015 		return (SDRC_ERROR);
845331Samw 
855331Samw 	xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt,
865331Samw 	    msrcnt, suwcnt);
875331Samw 	if (xa == NULL) {
885772Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRnoroom);
896139Sjb150015 		return (SDRC_ERROR);
905331Samw 	}
915331Samw 
925331Samw 	/* Should be some alignment stuff here in SMB? */
935331Samw 	if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) {
945331Samw 		rc = smbsr_decode_data(sr, "%.U", sr, &stn);
955331Samw 	} else {
965331Samw 		rc = smbsr_decode_data(sr, "%s", sr,  &stn);
975331Samw 	}
985331Samw 	if (rc != 0) {
995331Samw 		smb_xa_rele(sr->session, xa);
1006139Sjb150015 		return (SDRC_ERROR);
1015331Samw 	}
1025331Samw 
10311963SAfshin.Ardakani@Sun.COM 	xa->xa_pipe_name = smb_mem_strdup(stn);
1045331Samw 	xa->smb_flags  = flags;
1055331Samw 	xa->smb_timeout = timeo;
1065331Samw 	xa->req_disp_param = pscnt;
1075331Samw 	xa->req_disp_data  = dscnt;
1085331Samw 
1095331Samw 	if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv,
1105331Samw 	    sr->smb_vwv.chain_offset, suwcnt * 2)) {
1115331Samw 		smb_xa_rele(sr->session, xa);
1125772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
1136139Sjb150015 		return (SDRC_ERROR);
1145331Samw 	}
1155331Samw 	if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
1165331Samw 		smb_xa_rele(sr->session, xa);
1175772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
1186139Sjb150015 		return (SDRC_ERROR);
1195331Samw 	}
1205331Samw 	if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
1215331Samw 		smb_xa_rele(sr->session, xa);
1225772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
1236139Sjb150015 		return (SDRC_ERROR);
1245331Samw 	}
1255331Samw 
1265331Samw 	ready = smb_trans_ready(xa);
1275331Samw 
1285331Samw 	if (smb_xa_open(xa)) {
1295331Samw 		smb_xa_rele(sr->session, xa);
1305772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRsrverror);
1316139Sjb150015 		return (SDRC_ERROR);
1325331Samw 	}
1335331Samw 	sr->r_xa = xa;
1345331Samw 
1355331Samw 	if (!ready) {
1366030Sjb150015 		rc = smbsr_encode_empty_result(sr);
1376139Sjb150015 		return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1385331Samw 	}
1395331Samw 
1405331Samw 	if (!smb_xa_complete(xa)) {
1415331Samw 		smb_xa_close(xa);
1425772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
1436139Sjb150015 		return (SDRC_ERROR);
1445331Samw 	}
1455331Samw 
1465331Samw 	return (smb_trans_dispatch(sr, xa));
1475331Samw }
1485331Samw 
1496030Sjb150015 smb_sdrc_t
smb_pre_transaction_secondary(smb_request_t * sr)1506139Sjb150015 smb_pre_transaction_secondary(smb_request_t *sr)
1516139Sjb150015 {
1526139Sjb150015 	DTRACE_SMB_1(op__TransactionSecondary__start, smb_request_t *, sr);
1536139Sjb150015 	return (SDRC_SUCCESS);
1546139Sjb150015 }
1556139Sjb150015 
1566139Sjb150015 void
smb_post_transaction_secondary(smb_request_t * sr)1576139Sjb150015 smb_post_transaction_secondary(smb_request_t *sr)
1586139Sjb150015 {
1596139Sjb150015 	DTRACE_SMB_1(op__TransactionSecondary__done, smb_request_t *, sr);
1606139Sjb150015 }
1616139Sjb150015 
1626139Sjb150015 smb_sdrc_t
smb_com_transaction_secondary(smb_request_t * sr)1636139Sjb150015 smb_com_transaction_secondary(smb_request_t *sr)
1645331Samw {
1655331Samw 	uint16_t tpscnt, tdscnt, pscnt, psdisp;
1665331Samw 	uint16_t dscnt, dsoff, dsdisp, psoff;
1675331Samw 	smb_xa_t *xa;
1685331Samw 	int rc;
1695331Samw 
1705331Samw 	if ((xa = smbsr_lookup_xa(sr)) == 0) {
1715772Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
1726139Sjb150015 		return (SDRC_ERROR);
1735331Samw 	}
1745331Samw 
1755331Samw 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
1765331Samw 		if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
1775772Sas200622 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
1785331Samw 			    ERRDOS, ERRnoaccess);
1796139Sjb150015 			return (SDRC_ERROR);
1805331Samw 		}
1815331Samw 	}
1825331Samw 
1835331Samw 	if (xa->smb_com != SMB_COM_TRANSACTION) {
1845331Samw 		return (SDRC_DROP_VC);
1855331Samw 	}
1865331Samw 
1875331Samw 	rc = smbsr_decode_vwv(sr, SMB_TRANSSHDR_ED_FMT, &tpscnt, &tdscnt,
1885331Samw 	    &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp);
1895331Samw 
1906030Sjb150015 	if (rc != 0)
1916139Sjb150015 		return (SDRC_ERROR);
1925331Samw 
1935331Samw 	mutex_enter(&xa->xa_mutex);
1945331Samw 	xa->smb_tpscnt = tpscnt;	/* might have shrunk */
1955331Samw 	xa->smb_tdscnt = tdscnt;	/* might have shrunk */
1965331Samw 	xa->req_disp_param = psdisp+pscnt;
1975331Samw 	xa->req_disp_data  = dsdisp+dscnt;
1985331Samw 
1995331Samw 	if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
2005331Samw 		mutex_exit(&xa->xa_mutex);
2015331Samw 		smb_xa_close(xa);
2025772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
2036139Sjb150015 		return (SDRC_ERROR);
2045331Samw 	}
2055331Samw 	if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
2065331Samw 		mutex_exit(&xa->xa_mutex);
2075331Samw 		smb_xa_close(xa);
2085772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
2096139Sjb150015 		return (SDRC_ERROR);
2105331Samw 	}
2115331Samw 	mutex_exit(&xa->xa_mutex);
2125331Samw 
2135331Samw 	if (!smb_trans_ready(xa))
2145331Samw 		return (SDRC_NO_REPLY);
2155331Samw 
2165331Samw 	if (!smb_xa_complete(xa))
2175331Samw 		return (SDRC_NO_REPLY);
2185331Samw 
2195331Samw 	return (smb_trans_dispatch(sr, xa));
2205331Samw }
2215331Samw 
2226030Sjb150015 smb_sdrc_t
smb_pre_ioctl(smb_request_t * sr)2236139Sjb150015 smb_pre_ioctl(smb_request_t *sr)
2246139Sjb150015 {
2256139Sjb150015 	DTRACE_SMB_1(op__Ioctl__start, smb_request_t *, sr);
2266139Sjb150015 	return (SDRC_SUCCESS);
2276139Sjb150015 }
2286139Sjb150015 
2296139Sjb150015 void
smb_post_ioctl(smb_request_t * sr)2306139Sjb150015 smb_post_ioctl(smb_request_t *sr)
2316139Sjb150015 {
2326139Sjb150015 	DTRACE_SMB_1(op__Ioctl__done, smb_request_t *, sr);
2336139Sjb150015 }
2346139Sjb150015 
2356139Sjb150015 smb_sdrc_t
smb_com_ioctl(smb_request_t * sr)2366139Sjb150015 smb_com_ioctl(smb_request_t *sr)
2375331Samw {
2385331Samw 	uint16_t fid, category, function, tpscnt, tdscnt, mprcnt;
2395331Samw 	uint16_t mdrcnt, pscnt, pdoff, dscnt, dsoff;
2405331Samw 	uint32_t timeout;
2415331Samw 	int rc;
2425331Samw 
2435331Samw 	rc = smbsr_decode_vwv(sr, "wwwwwwwl2.wwww", &fid, &category, &function,
2445331Samw 	    &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &timeout, &pscnt,
2455331Samw 	    &pdoff, &dscnt, &dsoff);
2465331Samw 
2476030Sjb150015 	if (rc != 0)
2486139Sjb150015 		return (SDRC_ERROR);
2495331Samw 
2506139Sjb150015 	return (SDRC_NOT_IMPLEMENTED);
2515331Samw }
2525331Samw 
2536139Sjb150015 smb_sdrc_t
smb_pre_transaction2(smb_request_t * sr)2546139Sjb150015 smb_pre_transaction2(smb_request_t *sr)
2555331Samw {
2566139Sjb150015 	DTRACE_SMB_1(op__Transaction2__start, smb_request_t *, sr);
2576139Sjb150015 	return (SDRC_SUCCESS);
2586139Sjb150015 }
2596139Sjb150015 
2606139Sjb150015 void
smb_post_transaction2(smb_request_t * sr)2616139Sjb150015 smb_post_transaction2(smb_request_t *sr)
2626139Sjb150015 {
2636139Sjb150015 	DTRACE_SMB_1(op__Transaction2__done, smb_request_t *, sr);
2645331Samw }
2655331Samw 
2666030Sjb150015 smb_sdrc_t
smb_com_transaction2(struct smb_request * sr)2675331Samw smb_com_transaction2(struct smb_request *sr)
2685331Samw {
2695331Samw 	unsigned char	msrcnt, suwcnt;
2705331Samw 	uint16_t	tpscnt, tdscnt, mprcnt, mdrcnt, flags;
2715331Samw 	uint16_t	pscnt, psoff, dscnt, dsoff;
2725331Samw 	uint32_t	timeo;
2735331Samw 	smb_xa_t *xa;
2745331Samw 	int ready;
2755331Samw 	int rc;
2765331Samw 
2775331Samw 	rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, &tpscnt, &tdscnt,
2785331Samw 	    &mprcnt, &mdrcnt, &msrcnt, &flags, &timeo, &pscnt, &psoff, &dscnt,
2795331Samw 	    &dsoff, &suwcnt);
2805331Samw 
2816030Sjb150015 	if (rc != 0)
2826139Sjb150015 		return (SDRC_ERROR);
2835331Samw 
2845331Samw 	xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt,
2855331Samw 	    msrcnt, suwcnt);
2865331Samw 	if (xa == 0) {
2875772Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRnoroom);
2886139Sjb150015 		return (SDRC_ERROR);
2895331Samw 	}
2905331Samw 
2915331Samw 	xa->smb_flags  = flags;
2925331Samw 	xa->smb_timeout = timeo;
2935331Samw 	xa->req_disp_param = pscnt;
2945331Samw 	xa->req_disp_data  = dscnt;
2955331Samw 
2965331Samw 	if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv,
2975331Samw 	    sr->smb_vwv.chain_offset, suwcnt*2)) {
2985331Samw 		smb_xa_rele(sr->session, xa);
2995772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
3006139Sjb150015 		return (SDRC_ERROR);
3015331Samw 	}
3025331Samw 	if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
3035331Samw 		smb_xa_rele(sr->session, xa);
3045772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
3056139Sjb150015 		return (SDRC_ERROR);
3065331Samw 	}
3075331Samw 	if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
3085331Samw 		smb_xa_rele(sr->session, xa);
3095772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
3106139Sjb150015 		return (SDRC_ERROR);
3115331Samw 	}
3125331Samw 
3135331Samw 	ready = smb_trans_ready(xa);
3145331Samw 
3155331Samw 	if (smb_xa_open(xa)) {
3165331Samw 		smb_xa_rele(sr->session, xa);
3175772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRsrverror);
3186139Sjb150015 		return (SDRC_ERROR);
3195331Samw 	}
3205331Samw 	sr->r_xa = xa;
3215331Samw 
3225331Samw 	if (!ready) {
3236030Sjb150015 		rc = smbsr_encode_empty_result(sr);
3246139Sjb150015 		return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
3255331Samw 	}
3265331Samw 
3275331Samw 	if (!smb_xa_complete(xa)) {
3285331Samw 		smb_xa_close(xa);
3295772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
3306139Sjb150015 		return (SDRC_ERROR);
3315331Samw 	}
3325331Samw 
3335331Samw 	return (smb_trans2_dispatch(sr, xa));
3345331Samw }
3355331Samw 
3366030Sjb150015 smb_sdrc_t
smb_pre_transaction2_secondary(smb_request_t * sr)3376139Sjb150015 smb_pre_transaction2_secondary(smb_request_t *sr)
3386139Sjb150015 {
3396139Sjb150015 	DTRACE_SMB_1(op__Transaction2Secondary__start, smb_request_t *, sr);
3406139Sjb150015 	return (SDRC_SUCCESS);
3416139Sjb150015 }
3426139Sjb150015 
3436139Sjb150015 void
smb_post_transaction2_secondary(smb_request_t * sr)3446139Sjb150015 smb_post_transaction2_secondary(smb_request_t *sr)
3456139Sjb150015 {
3466139Sjb150015 	DTRACE_SMB_1(op__Transaction2Secondary__done, smb_request_t *, sr);
3476139Sjb150015 }
3486139Sjb150015 
3496139Sjb150015 smb_sdrc_t
smb_com_transaction2_secondary(smb_request_t * sr)3506139Sjb150015 smb_com_transaction2_secondary(smb_request_t *sr)
3515331Samw {
3525331Samw 	uint16_t tpscnt, tdscnt, fid;
3535331Samw 	uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp;
3545331Samw 	smb_xa_t *xa;
3555331Samw 	int rc;
3565331Samw 
3575331Samw 	if ((xa = smbsr_lookup_xa(sr)) == 0) {
3585772Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
3596139Sjb150015 		return (SDRC_ERROR);
3605331Samw 	}
3615331Samw 
3625331Samw 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
3635331Samw 		if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
3645772Sas200622 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
3655331Samw 			    ERRDOS, ERRnoaccess);
3666139Sjb150015 			return (SDRC_ERROR);
3675331Samw 		}
3685331Samw 	}
3695331Samw 
3705331Samw 	if (xa->smb_com != SMB_COM_TRANSACTION2) {
3715331Samw 		return (SDRC_DROP_VC);
3725331Samw 	}
3735331Samw 
3745331Samw 	rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt,
3755331Samw 	    &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid);
3765331Samw 
3776030Sjb150015 	if (rc != 0)
3786139Sjb150015 		return (SDRC_ERROR);
3795331Samw 
3805331Samw 	mutex_enter(&xa->xa_mutex);
3815331Samw 	xa->smb_tpscnt = tpscnt;	/* might have shrunk */
3825331Samw 	xa->smb_tdscnt = tdscnt;	/* might have shrunk */
3835331Samw 	xa->xa_smb_fid = fid;		/* overwrite rules? */
3845331Samw 	xa->req_disp_param = psdisp + pscnt;
3855331Samw 	xa->req_disp_data  = dsdisp + dscnt;
3865331Samw 
3875331Samw 	if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
3885331Samw 		mutex_exit(&xa->xa_mutex);
3895331Samw 		smb_xa_close(xa);
3905772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
3916139Sjb150015 		return (SDRC_ERROR);
3925331Samw 	}
3935331Samw 	if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
3945331Samw 		mutex_exit(&xa->xa_mutex);
3955331Samw 		smb_xa_close(xa);
3965772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
3976139Sjb150015 		return (SDRC_ERROR);
3985331Samw 	}
3995331Samw 	mutex_exit(&xa->xa_mutex);
4005331Samw 
4015331Samw 	if (!smb_trans_ready(xa))
4025331Samw 		return (SDRC_NO_REPLY);
4035331Samw 
4045331Samw 	if (!smb_xa_complete(xa))
4055331Samw 		return (SDRC_NO_REPLY);
4065331Samw 
4075331Samw 	return (smb_trans2_dispatch(sr, xa));
4085331Samw }
4095331Samw 
4106030Sjb150015 static smb_sdrc_t
smb_nt_trans_dispatch(struct smb_request * sr,struct smb_xa * xa)4115331Samw smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa)
4125331Samw {
4135331Samw 	int rc;
4145331Samw 	int total_bytes, n_setup, n_param, n_data;
4155331Samw 	int param_off, param_pad, data_off, data_pad;
4165331Samw 
4175331Samw 	n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200;
4185331Samw 	n_setup++;
4195331Samw 	n_setup = n_setup & ~0x0001;
4205331Samw 	n_param = (xa->smb_mprcnt < smb_maxbufsize)
4215331Samw 	    ? xa->smb_mprcnt : smb_maxbufsize;
4225331Samw 	n_param++;
4235331Samw 	n_param = n_param & ~0x0001;
4245331Samw 	rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param);
4255331Samw 	n_data = (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc;
4265331Samw 	MBC_INIT(&xa->rep_setup_mb, n_setup * 2);
4275331Samw 	MBC_INIT(&xa->rep_param_mb, n_param);
4285331Samw 	MBC_INIT(&xa->rep_data_mb, n_data);
4295331Samw 
4305331Samw 	switch (xa->smb_func) {
4315331Samw 	case NT_TRANSACT_CREATE:
4326139Sjb150015 		if ((rc = smb_pre_nt_transact_create(sr, xa)) == 0)
4336139Sjb150015 			rc = smb_nt_transact_create(sr, xa);
4346139Sjb150015 		smb_post_nt_transact_create(sr, xa);
4355331Samw 		break;
4365331Samw 	case NT_TRANSACT_NOTIFY_CHANGE:
4375331Samw 		rc = smb_nt_transact_notify_change(sr, xa);
4385331Samw 		break;
4395331Samw 	case NT_TRANSACT_QUERY_SECURITY_DESC:
4405331Samw 		rc = smb_nt_transact_query_security_info(sr, xa);
4415331Samw 		break;
4425331Samw 	case NT_TRANSACT_SET_SECURITY_DESC:
4435331Samw 		rc = smb_nt_transact_set_security_info(sr, xa);
4445331Samw 		break;
4455331Samw 	case NT_TRANSACT_IOCTL:
4465331Samw 		rc = smb_nt_transact_ioctl(sr, xa);
4475331Samw 		break;
4485331Samw 	case NT_TRANSACT_QUERY_QUOTA:
44911963SAfshin.Ardakani@Sun.COM 		rc = smb_nt_transact_query_quota(sr, xa);
4509914Samw@Sun.COM 		break;
4515331Samw 	case NT_TRANSACT_SET_QUOTA:
45211963SAfshin.Ardakani@Sun.COM 		rc = smb_nt_transact_set_quota(sr, xa);
45311963SAfshin.Ardakani@Sun.COM 		break;
45410966SJordan.Brown@Sun.COM 	case NT_TRANSACT_RENAME:
45510966SJordan.Brown@Sun.COM 		rc = smb_nt_transact_rename(sr, xa);
45610966SJordan.Brown@Sun.COM 		break;
45710966SJordan.Brown@Sun.COM 
4585331Samw 	default:
4595772Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
4606139Sjb150015 		return (SDRC_ERROR);
4615331Samw 	}
4625331Samw 
4635331Samw 	switch (rc) {
4646139Sjb150015 	case SDRC_SUCCESS:
4655331Samw 		break;
4665331Samw 
4675331Samw 	case SDRC_DROP_VC:
4685331Samw 	case SDRC_NO_REPLY:
4696139Sjb150015 	case SDRC_ERROR:
4708262SJose.Borrego@Sun.COM 	case SDRC_SR_KEPT:
4715331Samw 		return (rc);
4725331Samw 
4736139Sjb150015 	case SDRC_NOT_IMPLEMENTED:
4745772Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
4756139Sjb150015 		return (SDRC_ERROR);
4765331Samw 
4775331Samw 	default:
4785331Samw 		break;
4795331Samw 	}
4805331Samw 
4815331Samw 	n_setup = MBC_LENGTH(&xa->rep_setup_mb);
4825331Samw 	n_param = MBC_LENGTH(&xa->rep_param_mb);
4835331Samw 	n_data  = MBC_LENGTH(&xa->rep_data_mb);
4845331Samw 
4855331Samw 	if (xa->smb_msrcnt < n_setup ||
4865331Samw 	    xa->smb_mprcnt < n_param ||
4875331Samw 	    xa->smb_mdrcnt < n_data) {
4885772Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
4896139Sjb150015 		return (SDRC_ERROR);
4905331Samw 	}
4915331Samw 
4925331Samw 	/* neato, blast it over there */
4935331Samw 
4945331Samw 	n_setup = (n_setup + 1) / 2;		/* Conver to setup words */
4955331Samw 	param_pad = 1;				/* must be one */
4965331Samw 	param_off = param_pad + 32 + 37 + (n_setup << 1) + 2;
4975331Samw 	data_pad = (4 - ((param_off + n_param) & 3)) % 4; /* Pad to 4 byte */
4985331Samw 	data_off = param_off + n_param + data_pad; /* Param off from hdr */
4995331Samw 	total_bytes = param_pad + n_param + data_pad + n_data;
5005331Samw 
5016030Sjb150015 	rc = smbsr_encode_result(sr, 18+n_setup, total_bytes,
5027052Samw 	    "b3.llllllllbCw#.C#.C",
5035331Samw 	    18 + n_setup,		/* wct */
5045331Samw 	    n_param,			/* Total Parameter Bytes */
5055331Samw 	    n_data,			/* Total Data Bytes */
5065331Samw 	    n_param,			/* Total Parameter Bytes this buffer */
5075331Samw 	    param_off,			/* Param offset from header start */
5085331Samw 	    0,				/* Param displacement */
5095331Samw 	    n_data,			/* Total Data Bytes this buffer */
5105331Samw 	    data_off,			/* Data offset from header start */
5115331Samw 	    0,				/* Data displacement */
5125331Samw 	    n_setup,			/* suwcnt */
5135331Samw 	    &xa->rep_setup_mb,		/* setup[] */
5145331Samw 	    total_bytes,		/* Total data bytes */
5155331Samw 	    param_pad,
5165331Samw 	    &xa->rep_param_mb,
5175331Samw 	    data_pad,
5185331Samw 	    &xa->rep_data_mb);
5196139Sjb150015 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
5205331Samw }
5215331Samw 
5226139Sjb150015 smb_sdrc_t
smb_pre_nt_transact(smb_request_t * sr)5236139Sjb150015 smb_pre_nt_transact(smb_request_t *sr)
5246139Sjb150015 {
5256139Sjb150015 	DTRACE_SMB_1(op__NtTransact__start, smb_request_t *, sr);
5266139Sjb150015 	return (SDRC_SUCCESS);
5276139Sjb150015 }
5286139Sjb150015 
5296139Sjb150015 void
smb_post_nt_transact(smb_request_t * sr)5306139Sjb150015 smb_post_nt_transact(smb_request_t *sr)
5316139Sjb150015 {
5326139Sjb150015 	DTRACE_SMB_1(op__NtTransact__done, smb_request_t *, sr);
5336139Sjb150015 }
5345331Samw 
5356030Sjb150015 smb_sdrc_t
smb_com_nt_transact(struct smb_request * sr)5365331Samw smb_com_nt_transact(struct smb_request *sr)
5375331Samw {
5385331Samw 	uint16_t	Function;
5395331Samw 	unsigned char	MaxSetupCount, SetupCount;
5405331Samw 	uint32_t	TotalParameterCount, TotalDataCount;
5415331Samw 	uint32_t	MaxParameterCount, MaxDataCount, pscnt;
5425331Samw 	uint32_t	psoff, dscnt, dsoff;
5435331Samw 	smb_xa_t *xa;
5445331Samw 	int ready;
5455331Samw 	int rc;
5465331Samw 
5475331Samw 	rc = smbsr_decode_vwv(sr, SMB_NT_TRANSHDR_ED_FMT, &MaxSetupCount,
5485331Samw 	    &TotalParameterCount, &TotalDataCount, &MaxParameterCount,
5495331Samw 	    &MaxDataCount, &pscnt, &psoff, &dscnt,
5505331Samw 	    &dsoff, &SetupCount, &Function);
5515331Samw 
5526030Sjb150015 	if (rc != 0)
5536139Sjb150015 		return (SDRC_ERROR);
5545331Samw 
5555331Samw 	xa = smb_xa_create(sr->session, sr, TotalParameterCount, TotalDataCount,
5565331Samw 	    MaxParameterCount, MaxDataCount, MaxSetupCount, SetupCount);
5575331Samw 	if (xa == 0) {
5585772Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRnoroom);
5596139Sjb150015 		return (SDRC_ERROR);
5605331Samw 	}
5615331Samw 
5625331Samw 	xa->smb_flags  = 0;
5635331Samw 	xa->smb_timeout = 0;
5645331Samw 	xa->smb_func = Function;
5655331Samw 	xa->req_disp_param = pscnt;
5665331Samw 	xa->req_disp_data  = dscnt;
5675331Samw 
5685331Samw 	if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv,
5695331Samw 	    sr->smb_vwv.chain_offset, SetupCount * 2)) {
5705331Samw 		smb_xa_rele(sr->session, xa);
5715772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
5726139Sjb150015 		return (SDRC_ERROR);
5735331Samw 	}
5745331Samw 	if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
5755331Samw 		smb_xa_rele(sr->session, xa);
5765772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
5776139Sjb150015 		return (SDRC_ERROR);
5785331Samw 	}
5795331Samw 	if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
5805331Samw 		smb_xa_rele(sr->session, xa);
5815772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
5826139Sjb150015 		return (SDRC_ERROR);
5835331Samw 	}
5845331Samw 
5855331Samw 	ready = smb_trans_ready(xa);
5865331Samw 
5875331Samw 	if (smb_xa_open(xa)) {
5885331Samw 		smb_xa_rele(sr->session, xa);
5895772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRsrverror);
5906139Sjb150015 		return (SDRC_ERROR);
5915331Samw 	}
5925331Samw 	sr->r_xa = xa;
5935331Samw 
5945331Samw 	if (!ready) {
5956030Sjb150015 		rc = smbsr_encode_empty_result(sr);
5966139Sjb150015 		return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
5975331Samw 	}
5985331Samw 
5995331Samw 	if (!smb_xa_complete(xa)) {
6005331Samw 		smb_xa_close(xa);
6015772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
6026139Sjb150015 		return (SDRC_ERROR);
6035331Samw 	}
6045331Samw 
6055331Samw 	return (smb_nt_trans_dispatch(sr, xa));
6065331Samw }
6075331Samw 
6086139Sjb150015 smb_sdrc_t
smb_pre_nt_transact_secondary(smb_request_t * sr)6096139Sjb150015 smb_pre_nt_transact_secondary(smb_request_t *sr)
6106139Sjb150015 {
6116139Sjb150015 	DTRACE_SMB_1(op__NtTransactSecondary__start, smb_request_t *, sr);
6126139Sjb150015 	return (SDRC_SUCCESS);
6136139Sjb150015 }
6146139Sjb150015 
6156139Sjb150015 void
smb_post_nt_transact_secondary(smb_request_t * sr)6166139Sjb150015 smb_post_nt_transact_secondary(smb_request_t *sr)
6176139Sjb150015 {
6186139Sjb150015 	DTRACE_SMB_1(op__NtTransactSecondary__done, smb_request_t *, sr);
6196139Sjb150015 }
6205331Samw 
6216030Sjb150015 smb_sdrc_t
smb_com_nt_transact_secondary(struct smb_request * sr)6225331Samw smb_com_nt_transact_secondary(struct smb_request *sr)
6235331Samw {
6245331Samw 	uint16_t tpscnt, tdscnt, fid;
6255331Samw 	uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp;
6265331Samw 	smb_xa_t *xa;
6275331Samw 	int rc;
6285331Samw 
6295331Samw 	if ((xa = smbsr_lookup_xa(sr)) == 0) {
6305772Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
6316139Sjb150015 		return (SDRC_ERROR);
6325331Samw 	}
6335331Samw 
6345331Samw 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
6355331Samw 		if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
6365772Sas200622 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
6375331Samw 			    ERRDOS, ERRnoaccess);
6386139Sjb150015 			return (SDRC_ERROR);
6395331Samw 		}
6405331Samw 	}
6415331Samw 
6425331Samw 	if (xa->smb_com != SMB_COM_TRANSACTION2) {
6435331Samw 		return (SDRC_DROP_VC);
6445331Samw 	}
6455331Samw 
6465331Samw 	rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt,
6475331Samw 	    &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid);
6485331Samw 
6496030Sjb150015 	if (rc != 0)
6506139Sjb150015 		return (SDRC_ERROR);
6515331Samw 
6525331Samw 	mutex_enter(&xa->xa_mutex);
6535331Samw 	xa->smb_tpscnt = tpscnt;	/* might have shrunk */
6545331Samw 	xa->smb_tdscnt = tdscnt;	/* might have shrunk */
6555331Samw 	xa->xa_smb_fid = fid;		/* overwrite rules? */
6565331Samw 	xa->req_disp_param = psdisp+pscnt;
6575331Samw 	xa->req_disp_data  = dsdisp+dscnt;
6585331Samw 
6595331Samw 	if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
6605331Samw 		mutex_exit(&xa->xa_mutex);
6615331Samw 		smb_xa_close(xa);
6625772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
6636139Sjb150015 		return (SDRC_ERROR);
6645331Samw 	}
6655331Samw 	if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
6665331Samw 		mutex_exit(&xa->xa_mutex);
6675331Samw 		smb_xa_close(xa);
6685772Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
6696139Sjb150015 		return (SDRC_ERROR);
6705331Samw 	}
6715331Samw 	mutex_exit(&xa->xa_mutex);
6725331Samw 
6735331Samw 	if (!smb_trans_ready(xa))
6745331Samw 		return (SDRC_NO_REPLY);
6755331Samw 
6765331Samw 	if (!smb_xa_complete(xa))
6775331Samw 		return (SDRC_NO_REPLY);
6785331Samw 
6795331Samw 	return (smb_nt_trans_dispatch(sr, xa));
6805331Samw }
6815331Samw 
6826030Sjb150015 static int
smb_trans_ready(smb_xa_t * xa)68311963SAfshin.Ardakani@Sun.COM smb_trans_ready(smb_xa_t *xa)
6845331Samw {
6855331Samw 	int rc;
6865331Samw 
6875331Samw 	mutex_enter(&xa->xa_mutex);
6885331Samw 	rc = xa->req_disp_data >= xa->smb_tdscnt &&
6895331Samw 	    xa->req_disp_param >= xa->smb_tpscnt;
6905331Samw 	mutex_exit(&xa->xa_mutex);
6915331Samw 
6925331Samw 	return (rc);
6935331Samw }
6945331Samw 
6956771Sjb150015 static void
smb_encode_SHARE_INFO_1(struct mbuf_chain * output,struct mbuf_chain * text,char * oem_name,uint16_t type,char * comment)6966771Sjb150015 smb_encode_SHARE_INFO_1(struct mbuf_chain *output, struct mbuf_chain *text,
6976771Sjb150015     char *oem_name, uint16_t type, char *comment)
6985331Samw {
6997052Samw 	(void) smb_mbc_encodef(output, "13c.wl", oem_name,
7006771Sjb150015 	    type, MBC_LENGTH(text));
7015331Samw 
7027052Samw 	(void) smb_mbc_encodef(text, "s", comment ? comment : "");
7035331Samw }
7045331Samw 
7056771Sjb150015 static void
smb_encode_SHARE_INFO_2(struct mbuf_chain * output,struct mbuf_chain * text,smb_request_t * sr,char * oem_name,uint16_t type,char * comment,uint16_t access,char * path,char * password)7066771Sjb150015 smb_encode_SHARE_INFO_2(struct mbuf_chain *output, struct mbuf_chain *text,
7076771Sjb150015 	smb_request_t *sr, char *oem_name, uint16_t type,
7086771Sjb150015 	char *comment, uint16_t access, char *path, char *password)
7095331Samw {
7106771Sjb150015 	unsigned char pword[9];
7115331Samw 
7125331Samw 	bzero(pword, sizeof (pword));
7135331Samw 	(void) strncpy((char *)pword, password, sizeof (pword));
7146771Sjb150015 	smb_encode_SHARE_INFO_1(output, text, oem_name, type, comment);
7157052Samw 	(void) smb_mbc_encodef(output, "wwwl9c.",
7165331Samw 	    access,
7176139Sjb150015 	    sr->sr_cfg->skc_maxconnections,
7186139Sjb150015 	    smb_server_get_session_count(),
7195331Samw 	    MBC_LENGTH(text),
7206771Sjb150015 	    pword);
7217052Samw 	(void) smb_mbc_encodef(text, "s", path);
7225331Samw }
7235331Samw 
7245331Samw int
smb_trans_net_share_enum(struct smb_request * sr,struct smb_xa * xa)7255331Samw smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa)
7265331Samw {
7275331Samw 	/*
7285331Samw 	 * Number of data bytes that will
7295331Samw 	 * be sent in the current response
7305331Samw 	 */
7315331Samw 	uint16_t data_scnt;
7325331Samw 
7335331Samw 	/*
7345331Samw 	 * Total number of data bytes that
7355331Samw 	 * are sent till now. This is only
7365331Samw 	 * used for calculating current data
7375331Samw 	 * displacement
7385331Samw 	 */
7395331Samw 	uint16_t tot_data_scnt;
7405331Samw 
7415331Samw 	/*
7425331Samw 	 * Number of parameter bytes should
7435331Samw 	 * be sent for the current response.
7445331Samw 	 * It is 8 for the 1st response and
7455331Samw 	 * 0 for others
7465331Samw 	 */
7475331Samw 	uint16_t param_scnt;
7485331Samw 
7495331Samw 	/* number of setup and parameter bytes */
7505331Samw 	uint16_t n_setup, n_param;
7515331Samw 
7525331Samw 	/* data and parameter displacement */
7535331Samw 	uint16_t data_disp, param_disp;
7545331Samw 
7555331Samw 	/* parameter and data offset and pad */
7565331Samw 	int param_off, param_pad, data_off, data_pad;
7575331Samw 
7585331Samw 	/*
7595331Samw 	 * total bytes of parameters and data
7605331Samw 	 * in the packet, plus the pad bytes.
7615331Samw 	 */
7625331Samw 	int tot_packet_bytes;
7635331Samw 
7646771Sjb150015 	boolean_t first_resp;
7656771Sjb150015 
7666771Sjb150015 	char fmt[16];
7675331Samw 	struct mbuf_chain reply;
7685331Samw 
7696771Sjb150015 	uint16_t level;
7706771Sjb150015 	uint16_t pkt_bufsize;
7716771Sjb150015 	smb_enumshare_info_t esi;
7726771Sjb150015 	char *sent_buf;
7736771Sjb150015 
7746771Sjb150015 	ASSERT(sr->uid_user);
7755331Samw 
7765331Samw 	/*
7775331Samw 	 * Initialize the mbuf chain of reply to zero. If it is not
7785331Samw 	 * zero, code inside the while loop will try to free the chain.
7795331Samw 	 */
7805331Samw 	bzero(&reply, sizeof (struct mbuf_chain));
7815331Samw 
7827052Samw 	if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level,
7836771Sjb150015 	    &esi.es_bufsize) != 0)
7846139Sjb150015 		return (SDRC_NOT_IMPLEMENTED);
7855331Samw 
7865331Samw 	if (level != 1) {
7876771Sjb150015 		/*
7886771Sjb150015 		 * Only level 1 is valid for NetShareEnum
7896771Sjb150015 		 * None of the error codes in the spec are meaningful
7906771Sjb150015 		 * here. This error code is returned by Windows.
7916771Sjb150015 		 */
7927052Samw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
7936771Sjb150015 		    ERROR_INVALID_LEVEL, 0, 0, 0);
7946139Sjb150015 		return (SDRC_SUCCESS);
7955331Samw 	}
7965331Samw 
79712508Samw@Sun.COM 	esi.es_buf = smb_srm_zalloc(sr, esi.es_bufsize);
79812065SKeyur.Desai@Sun.COM 	esi.es_posix_uid = crgetuid(sr->uid_user->u_cred);
79912508Samw@Sun.COM 	smb_kshare_enum(&esi);
8005331Samw 
8016771Sjb150015 	/* client buffer size is not big enough to hold any shares */
8026771Sjb150015 	if (esi.es_nsent == 0) {
8037052Samw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
8046771Sjb150015 		    ERROR_MORE_DATA, 0, esi.es_nsent, esi.es_ntotal);
8056771Sjb150015 		return (SDRC_SUCCESS);
8065331Samw 	}
8075331Samw 
8085331Samw 	/*
8095331Samw 	 * The rep_setup_mb is already initialized in smb_trans_dispatch().
8105331Samw 	 * Calling MBC_INIT() will initialized the structure and so the
8115331Samw 	 * pointer to the mbuf chains will be lost. Therefore, we need
8125331Samw 	 * to free the resources before calling MBC_INIT() again.
8135331Samw 	 */
8146771Sjb150015 	n_setup = 0;	/* Setup count for NetShareEnum SMB is 0 */
8155331Samw 	m_freem(xa->rep_setup_mb.chain);
8165331Samw 	MBC_INIT(&xa->rep_setup_mb, n_setup * 2);
8175331Samw 
8186771Sjb150015 	n_param = 8;
8196771Sjb150015 	pkt_bufsize = sr->session->smb_msg_size -
8206771Sjb150015 	    (SMB_HEADER_ED_LEN + RESP_HEADER_LEN + n_param);
8215331Samw 
8226771Sjb150015 	tot_data_scnt = 0;
8236771Sjb150015 	sent_buf = esi.es_buf;
8246771Sjb150015 	first_resp = B_TRUE;
8256771Sjb150015 
8266771Sjb150015 	while (tot_data_scnt < esi.es_datasize) {
8276771Sjb150015 		data_scnt = esi.es_datasize - tot_data_scnt;
8286771Sjb150015 		if (data_scnt > pkt_bufsize)
8296771Sjb150015 			data_scnt = pkt_bufsize;
8305331Samw 		m_freem(xa->rep_data_mb.chain);
8316771Sjb150015 		MBC_INIT(&xa->rep_data_mb, data_scnt);
8326771Sjb150015 
8336771Sjb150015 		(void) sprintf(fmt, "%dc", data_scnt);
8347052Samw 		(void) smb_mbc_encodef(&xa->rep_data_mb, fmt, sent_buf);
8356771Sjb150015 
8366771Sjb150015 		sent_buf += data_scnt;
8375331Samw 		tot_data_scnt += data_scnt;
8385331Samw 
8395331Samw 		/* Only the 1st response packet contains parameters */
8405331Samw 		param_scnt = (first_resp) ? n_param : 0;
8415331Samw 		param_pad = 1;				/* always one */
8425331Samw 		param_off = SMB_HEADER_ED_LEN + RESP_HEADER_LEN;
8435331Samw 		param_disp = (first_resp) ? 0 : n_param;
8445331Samw 
8455331Samw 		m_freem(xa->rep_param_mb.chain);
8465331Samw 		MBC_INIT(&xa->rep_param_mb, param_scnt);
8476771Sjb150015 
8485331Samw 		if (first_resp) {
8496771Sjb150015 			first_resp = B_FALSE;
8507052Samw 			(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
8516771Sjb150015 			    (esi.es_ntotal > esi.es_nsent)
8526771Sjb150015 			    ? ERROR_MORE_DATA : 0,
8536771Sjb150015 			    0, esi.es_nsent, esi.es_ntotal);
8545331Samw 		}
8555331Samw 
8565331Samw 		data_pad = (param_off + n_param) & 1;	/* Pad to short */
8575331Samw 
8585331Samw 		/* data off from hdr start */
8595331Samw 		data_off = param_off + param_scnt + data_pad;
8605331Samw 		data_disp = tot_data_scnt - data_scnt;
8615331Samw 		tot_packet_bytes = param_pad + param_scnt + data_pad +
8625331Samw 		    data_scnt;
8635331Samw 
8645331Samw 		/*
8655331Samw 		 * Calling MBC_INIT() will initialized the structure and so the
8665331Samw 		 * pointer to the mbuf chains will be lost. Therefore, we need
8675331Samw 		 * to free the resources if any before calling MBC_INIT().
8685331Samw 		 */
8695331Samw 		m_freem(reply.chain);
8705331Samw 		MBC_INIT(&reply, SMB_HEADER_ED_LEN
8716771Sjb150015 		    + sizeof (uint8_t)		/* word parameters count */
8726771Sjb150015 		    + 10*sizeof (uint16_t)	/* word parameters */
8736771Sjb150015 		    + n_setup*sizeof (uint16_t)	/* setup parameters */
8746771Sjb150015 		    + sizeof (uint16_t)		/* total data byte count */
8755331Samw 		    + tot_packet_bytes);
8765331Samw 
8777052Samw 		(void) smb_mbc_encodef(&reply, SMB_HEADER_ED_FMT,
8785331Samw 		    sr->first_smb_com,
8795331Samw 		    sr->smb_rcls,
8805331Samw 		    sr->smb_reh,
8815331Samw 		    sr->smb_err,
8825331Samw 		    sr->smb_flg | SMB_FLAGS_REPLY,
8835331Samw 		    sr->smb_flg2,
8845331Samw 		    sr->smb_pid_high,
8855331Samw 		    sr->smb_sig,
8865331Samw 		    sr->smb_tid,
8875331Samw 		    sr->smb_pid,
8885331Samw 		    sr->smb_uid,
8895331Samw 		    sr->smb_mid);
8905331Samw 
8917052Samw 		(void) smb_mbc_encodef(&reply,
8927052Samw 		    "bww2.wwwwwwb.Cw#.C#.C",
8935331Samw 		    10 + n_setup,	/* wct */
8945331Samw 		    n_param,		/* Total Parameter Bytes */
8956771Sjb150015 		    esi.es_datasize,	/* Total Data Bytes */
8965331Samw 		    param_scnt,		/* Total Parameter Bytes this buffer */
8975331Samw 		    param_off,		/* Param offset from header start */
8985331Samw 		    param_disp,		/* Param displacement */
8995331Samw 		    data_scnt,		/* Total Data Bytes this buffer */
9005331Samw 		    data_off,		/* Data offset from header start */
9015331Samw 		    data_disp,		/* Data displacement */
9025331Samw 		    n_setup,		/* suwcnt */
9035331Samw 		    &xa->rep_setup_mb, 	/* setup[] */
9045331Samw 		    tot_packet_bytes,	/* Total data bytes */
9055331Samw 		    param_pad,
9065331Samw 		    &xa->rep_param_mb,
9075331Samw 		    data_pad,
9085331Samw 		    &xa->rep_data_mb);
9095331Samw 
9105331Samw 		if (sr->session->signing.flags & SMB_SIGNING_ENABLED)
9117961SNatalie.Li@Sun.COM 			smb_sign_reply(sr, &reply);
9125331Samw 
9135331Samw 		(void) smb_session_send(sr->session, 0, &reply);
9145331Samw 	}
9155331Samw 
9165331Samw 	return (SDRC_NO_REPLY);
9175331Samw }
9185331Samw 
9195331Samw int
smb_trans_net_share_getinfo(smb_request_t * sr,struct smb_xa * xa)9206771Sjb150015 smb_trans_net_share_getinfo(smb_request_t *sr, struct smb_xa *xa)
9215331Samw {
9226771Sjb150015 	uint16_t		level, max_bytes, access;
9235331Samw 	struct mbuf_chain	str_mb;
9245331Samw 	char			*share;
9255331Samw 	char			*password;
92612508Samw@Sun.COM 	smb_kshare_t		*si;
9275331Samw 
9287052Samw 	if (smb_mbc_decodef(&xa->req_param_mb, "%sww", sr,
9296771Sjb150015 	    &share, &level, &max_bytes) != 0)
9306139Sjb150015 		return (SDRC_NOT_IMPLEMENTED);
9315331Samw 
93212508Samw@Sun.COM 	si = smb_kshare_lookup(share);
93312508Samw@Sun.COM 	if ((si == NULL) || (si->shr_oemname == NULL)) {
9347052Samw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "www",
9355331Samw 		    NERR_NetNameNotFound, 0, 0);
93612508Samw@Sun.COM 		if (si)
93712508Samw@Sun.COM 			smb_kshare_release(si);
9386139Sjb150015 		return (SDRC_SUCCESS);
9395331Samw 	}
9405331Samw 
9416771Sjb150015 	access = SHARE_ACCESS_ALL;
9425331Samw 	password = "";
9435331Samw 
9445331Samw 	MBC_INIT(&str_mb, max_bytes);
9455331Samw 
9465331Samw 	switch (level) {
9475331Samw 	case 0 :
94812508Samw@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "13c",
94912508Samw@Sun.COM 		    si->shr_oemname);
9505331Samw 		break;
9515331Samw 
9525331Samw 	case 1 :
9536771Sjb150015 		smb_encode_SHARE_INFO_1(&xa->rep_data_mb, &str_mb,
95412508Samw@Sun.COM 		    si->shr_oemname, si->shr_type, si->shr_cmnt);
9555331Samw 		break;
9565331Samw 
9575331Samw 	case 2 :
9586771Sjb150015 		smb_encode_SHARE_INFO_2(&xa->rep_data_mb, &str_mb, sr,
95912508Samw@Sun.COM 		    si->shr_oemname, si->shr_type, si->shr_cmnt, access,
96012508Samw@Sun.COM 		    si->shr_path, password);
9616771Sjb150015 		break;
9626771Sjb150015 
9635331Samw 	default:
96412508Samw@Sun.COM 		smb_kshare_release(si);
9657052Samw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "www",
9666771Sjb150015 		    ERROR_INVALID_LEVEL, 0, 0);
9675331Samw 		m_freem(str_mb.chain);
9686139Sjb150015 		return (SDRC_NOT_IMPLEMENTED);
9695331Samw 	}
9705331Samw 
97112508Samw@Sun.COM 	smb_kshare_release(si);
9727052Samw 	(void) smb_mbc_encodef(&xa->rep_param_mb, "www", NERR_Success,
9735331Samw 	    -MBC_LENGTH(&xa->rep_data_mb),
9745331Samw 	    MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb));
9757052Samw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
9765331Samw 	m_freem(str_mb.chain);
9776139Sjb150015 	return (SDRC_SUCCESS);
9785331Samw }
9795331Samw 
9805331Samw int
smb_trans_net_workstation_getinfo(struct smb_request * sr,struct smb_xa * xa)9816771Sjb150015 smb_trans_net_workstation_getinfo(struct smb_request *sr, struct smb_xa *xa)
9825331Samw {
9836771Sjb150015 	uint16_t		level, max_bytes;
9845331Samw 	struct mbuf_chain	str_mb;
9855331Samw 	char *domain;
9865331Samw 	char *hostname;
9875331Samw 
9887052Samw 	if ((smb_mbc_decodef(&xa->req_param_mb, "ww",
9896771Sjb150015 	    &level, &max_bytes) != 0) ||
9905331Samw 	    (level != 10)) {
9917052Samw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
9925331Samw 		    NERR_BadTransactConfig, 0, 0, 0);
9936139Sjb150015 		return (SDRC_SUCCESS);
9945331Samw 	}
9955331Samw 
9967961SNatalie.Li@Sun.COM 	domain = sr->sr_cfg->skc_nbdomain;
9976139Sjb150015 	hostname = sr->sr_cfg->skc_hostname;
9985331Samw 
9995331Samw 	MBC_INIT(&str_mb, max_bytes);
10005331Samw 
10017052Samw 	(void) smb_mbc_encodef(&str_mb, "."); /* Prevent NULL pointers */
10025331Samw 
10037052Samw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
10047052Samw 	(void) smb_mbc_encodef(&str_mb, "s", hostname);
10057052Samw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
10067052Samw 	(void) smb_mbc_encodef(&str_mb, "s", "nobody");
10077052Samw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
10087052Samw 	(void) smb_mbc_encodef(&str_mb, "s", domain);
10097052Samw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "bbl",
1010*13082SJoyce.McIntosh@Sun.COM 	    (uint8_t)sr->sr_cfg->skc_version.sv_major,
1011*13082SJoyce.McIntosh@Sun.COM 	    (uint8_t)sr->sr_cfg->skc_version.sv_minor,
101211963SAfshin.Ardakani@Sun.COM 	    MBC_LENGTH(&str_mb));
10137052Samw 	(void) smb_mbc_encodef(&str_mb, "s", domain);
10147052Samw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
10157052Samw 	(void) smb_mbc_encodef(&str_mb, "s", domain);
10165331Samw 
10177052Samw 	(void) smb_mbc_encodef(&xa->rep_param_mb, "www", 0,
10185331Samw 	    -MBC_LENGTH(&xa->rep_data_mb),
10195331Samw 	    MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb));
10207052Samw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
10215331Samw 	m_freem(str_mb.chain);
10226139Sjb150015 	return (SDRC_SUCCESS);
10235331Samw }
10245331Samw 
10255331Samw int
smb_trans_net_user_getinfo(struct smb_request * sr,struct smb_xa * xa)10266771Sjb150015 smb_trans_net_user_getinfo(struct smb_request *sr, struct smb_xa *xa)
10275331Samw {
10286771Sjb150015 	uint16_t		level, max_bytes;
10295331Samw 	unsigned char		*user;
10305331Samw 	int rc;
10315331Samw 
10327052Samw 	rc = smb_mbc_decodef(&xa->req_param_mb, "%sww", sr,
10335331Samw 	    &user,
10345331Samw 	    &level,
10355331Samw 	    &max_bytes);
10365331Samw 
10375331Samw 	if (rc != 0)
10386139Sjb150015 		return (SDRC_NOT_IMPLEMENTED);
10395331Samw 
10407052Samw 	(void) smb_mbc_encodef(&xa->rep_param_mb, "www",
10415331Samw 	    NERR_UserNotFound, 0, 0);
10426139Sjb150015 	return (SDRC_SUCCESS);
10435331Samw }
10445331Samw 
10456030Sjb150015 smb_sdrc_t
smb_trans_net_server_getinfo(struct smb_request * sr,struct smb_xa * xa)10466771Sjb150015 smb_trans_net_server_getinfo(struct smb_request *sr, struct smb_xa *xa)
10475331Samw {
10486771Sjb150015 	uint16_t		level, buf_size;
10496771Sjb150015 	uint16_t		avail_data, max_data;
10505331Samw 	char			server_name[16];
10515331Samw 	struct mbuf_chain	str_mb;
10525331Samw 
10537052Samw 	if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level, &buf_size) != 0)
10546139Sjb150015 		return (SDRC_ERROR);
10555331Samw 
10566771Sjb150015 	max_data = MBC_MAXBYTES(&xa->rep_data_mb);
10575331Samw 
10585331Samw 	MBC_INIT(&str_mb, buf_size);
10595331Samw 
10605331Samw 	bzero(server_name, sizeof (server_name));
10616771Sjb150015 	(void) strncpy(server_name, sr->sr_cfg->skc_hostname,
10626771Sjb150015 	    sizeof (server_name));
10635331Samw 
10646771Sjb150015 	/* valid levels are 0 and 1 */
10655331Samw 	switch (level) {
10665331Samw 	case 0:
10677052Samw 		(void) smb_mbc_encodef(&xa->rep_data_mb, "16c", server_name);
10685331Samw 		break;
10696771Sjb150015 
10705331Samw 	case 1:
10717052Samw 		(void) smb_mbc_encodef(&str_mb, "s",
10726771Sjb150015 		    sr->sr_cfg->skc_system_comment);
10737052Samw 		(void) smb_mbc_encodef(&xa->rep_data_mb, "16cbbll", server_name,
1074*13082SJoyce.McIntosh@Sun.COM 		    (uint8_t)sr->sr_cfg->skc_version.sv_major,
1075*13082SJoyce.McIntosh@Sun.COM 		    (uint8_t)sr->sr_cfg->skc_version.sv_minor,
10766771Sjb150015 		    MY_SERVER_TYPE, max_data - MBC_LENGTH(&str_mb));
10775331Samw 		break;
10786771Sjb150015 
10795331Samw 	default:
10807052Samw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "www",
10816771Sjb150015 		    ERROR_INVALID_LEVEL, 0, 0);
10825331Samw 		m_freem(str_mb.chain);
10836771Sjb150015 		return (SDRC_SUCCESS);
10845331Samw 	}
10855331Samw 
10866771Sjb150015 	avail_data = MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb);
10877052Samw 	(void) smb_mbc_encodef(&xa->rep_param_mb, "www",
10886771Sjb150015 	    NERR_Success, max_data - avail_data, avail_data);
10897052Samw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
10905331Samw 	m_freem(str_mb.chain);
10916139Sjb150015 	return (SDRC_SUCCESS);
10925331Samw }
10935331Samw 
10945331Samw /*
10955331Samw  * 6.4 The NetServerEnum2 RAP Service
10965331Samw  *
10975331Samw  * The NetServerEnum2 RAP service lists all computers of the specified type
10985331Samw  * or types that are visible in the specified domains. It may also
10995331Samw  * enumerate domains.
11005331Samw  *
11015331Samw  * The following definition uses the notation and terminology defined in
11025331Samw  * the CIFS Remote Administration Protocol specification, which is required
11035331Samw  * in order to make it well-defined. The definition is:
11045331Samw  *
11055331Samw  *     uint16_t NetServerEnum2 (
11065331Samw  *         uint16_t  sLevel,
11075331Samw  *         RCVBUF          pbBuffer,
11085331Samw  *         RCVBUFLEN       cbBuffer,
11095331Samw  *         ENTCOUNT        pcEntriesRead,
11105331Samw  *         uint16_t  *pcTotalAvail,
11115331Samw  *         uint32_t   fServerType,
11125331Samw  *         char            *pszDomain,
11135331Samw  *     );
11145331Samw  *
11155331Samw  * where:
11165331Samw  *
11175331Samw  *    sLevel specifies the level of detail (0 or 1) requested.
11185331Samw  *
11195331Samw  *    pbBuffer points to the buffer to receive the returned data. If the
11205331Samw  *    function is successful, the buffer contains a sequence of
11215331Samw  *    server_info_x structures, where x is 0 or 1, depending on the
11225331Samw  *    level of detail requested.
11235331Samw  *
11245331Samw  *    cbBuffer specifies the size, in bytes, of the buffer pointed to by
11255331Samw  *    the pbBuffer parameter.
11265331Samw  *
11275331Samw  *    pcEntriesRead points to a 16 bit variable that receives a count of
11285331Samw  *    the number of servers enumerated in the buffer. This count is
11295331Samw  *    valid only if NetServerEnum2 returns the NERR_Success or
11305331Samw  *    ERROR_MORE_DATA values.
11315331Samw  *
11325331Samw  *    pcTotal Avail points to a 16 bit variable that receives a count of
11335331Samw  *    the total number of available entries. This count is valid only if
11345331Samw  *    NetServerEnum2 returns the NERR_Success or ERROR_MORE_DATA values.
11355331Samw  *
11365331Samw  *     fServerType specifies the type or types of computers to enumerate.
11375331Samw  *     Computers that match at least one of the specified types are
11385331Samw  *     returned in the buffer. Possible values are defined in the request
11395331Samw  *     parameters section.
11405331Samw  *
11415331Samw  *    pszDomain points to a null-terminated string that contains the
11425331Samw  *    name of the workgroup in which to enumerate computers of the
11435331Samw  *    specified type or types. If the pszDomain parameter is a null
11445331Samw  *    string or a null pointer, servers are enumerated for the current
11455331Samw  *    domain of the computer.
11465331Samw  *
11475331Samw  * 6.4.1 Transaction Request Parameters section
11485331Samw  *
11495331Samw  * The Transaction request parameters section in this instance contains:
11505331Samw  * . The 16 bit function number for NetServerEnum2 which is 104.
11515331Samw  * . The parameter descriptor string which is "WrLehDz".
11525331Samw  * . The data descriptor string for the (returned) data which is "B16" for
11535331Samw  *   level detail 0 or "B16BBDz" for level detail 1.
11545331Samw  * . The actual parameters as described by the parameter descriptor
11555331Samw  *   string.
11565331Samw  *
11575331Samw  * The parameters are:
11585331Samw  * . A 16 bit integer with a value of 0 or 1 (corresponding to the "W" in
11595331Samw  *   the parameter descriptor string. This represents the level of detail
11605331Samw  *   the server is expected to return
11615331Samw  * . A 16 bit integer that contains the size of the receive buffer.
11625331Samw  * . A 32 bit integer that represents the type of servers the function
11635331Samw  *   should enumerate. The possible values may be any of the following or
11645331Samw  *   a combination of the following:
11655331Samw  *
11665331Samw  * SV_TYPE_WORKSTATION        0x00000001 All workstations
11675331Samw  * SV_TYPE_SERVER             0x00000002 All servers
11685331Samw  * SV_TYPE_SQLSERVER          0x00000004 Any server running with SQL
11695331Samw  *                                       server
11705331Samw  * SV_TYPE_DOMAIN_CTRL        0x00000008 Primary domain controller
11715331Samw  * SV_TYPE_DOMAIN_BAKCTRL     0x00000010 Backup domain controller
11725331Samw  * SV_TYPE_TIME_SOURCE        0x00000020 Server running the timesource
11735331Samw  *                                       service
11745331Samw  * SV_TYPE_AFP                0x00000040 Apple File Protocol servers
11755331Samw  * SV_TYPE_NOVELL             0x00000080 Novell servers
11765331Samw  * SV_TYPE_DOMAIN_MEMBER      0x00000100 Domain Member
11775331Samw  * SV_TYPE_PRINTQ_SERVER      0x00000200 Server sharing print queue
11785331Samw  * SV_TYPE_DIALIN_SERVER      0x00000400 Server running dialin service.
11795331Samw  * SV_TYPE_XENIX_SERVER       0x00000800 Xenix server
11805331Samw  * SV_TYPE_NT                 0x00001000 NT server
11815331Samw  * SV_TYPE_WFW                0x00002000 Server running Windows for
11825331Samw  *                                       Workgroups
11835331Samw  * SV_TYPE_SERVER_NT          0x00008000 Windows NT non DC server
11845331Samw  * SV_TYPE_POTENTIAL_BROWSER  0x00010000 Server that can run the browser
11855331Samw  *                                       service
11865331Samw  * SV_TYPE_BACKUP_BROWSER     0x00020000 Backup browser server
11875331Samw  * SV_TYPE_MASTER_BROWSER     0x00040000 Master browser server
11885331Samw  * SV_TYPE_DOMAIN_MASTER      0x00080000 Domain Master Browser server
11895331Samw  * SV_TYPE_LOCAL_LIST_ONLY    0x40000000 Enumerate only entries marked
11905331Samw  *                                       "local"
11915331Samw  * SV_TYPE_DOMAIN_ENUM        0x80000000 Enumerate Domains. The pszDomain
11925331Samw  *                                       parameter must be NULL.
11935331Samw  *
11945331Samw  * . A null terminated ASCII string representing the pszDomain parameter
11955331Samw  *   described above
11965331Samw  *
11975331Samw  * 6.4.2 Transaction Request Data section
11985331Samw  *
11995331Samw  * There is no data or auxiliary data to send as part of the request.
12005331Samw  *
12015331Samw  * 6.4.3 Transaction Response Parameters section
12025331Samw  *
12035331Samw  * The transaction response parameters section consists of:
12045331Samw  * . A 16 bit word indicating the return status. The possible values are:
12055331Samw  *
12065331Samw  * Code                   Value  Description
12075331Samw  * NERR_Success           0      No errors encountered
12085331Samw  * ERROR_MORE_DATA        234    Additional data is available
12095331Samw  * NERR_ServerNotStarted  2114   The RAP service on the remote computer
12105331Samw  *                               is not running
12115331Samw  * NERR_BadTransactConfig 2141   The server is not configured for
12125331Samw  *                               transactions, IPC$ is not shared
12135331Samw  *
12145331Samw  * . A 16 bit "converter" word.
12155331Samw  * . A 16 bit number representing the number of entries returned.
12165331Samw  * . A 16 bit number representing the total number of available entries.
12175331Samw  *   If the supplied buffer is large enough, this will equal the number of
12185331Samw  *   entries returned.
12195331Samw  *
12205331Samw  * 6.4.4 Transaction Response Data section
12215331Samw  *
12225331Samw  * The return data section consists of a number of SERVER_INFO_1 structures.
12235331Samw  * The number of such structures present is determined by the third entry
12245331Samw  * (described above) in the return parameters section.
12255331Samw  *
12265331Samw  * At level detail 0, the Transaction response data section contains a
12275331Samw  * number of SERVER_INFO_0 data structure. The number of such structures is
12285331Samw  * equal to the 16 bit number returned by the server in the third parameter
12295331Samw  * in the Transaction response parameter section. The SERVER_INFO_0 data
12305331Samw  * structure is defined as:
12315331Samw  *
12325331Samw  *     struct SERVER_INFO_0 {
12335331Samw  *         char        sv0_name[16];
12345331Samw  *     };
12355331Samw  *
12365331Samw  *  where:
12375331Samw  *
12385331Samw  *    sv0_name is a null-terminated string that specifies the name of a
12395331Samw  *    computer or domain .
12405331Samw  *
12415331Samw  * At level detail 1, the Transaction response data section contains a
12425331Samw  * number of SERVER_INFO_1 data structure. The number of such structures is
12435331Samw  * equal to the 16 bit number returned by the server in the third parameter
12445331Samw  * in the Transaction response parameter section. The SERVER_INFO_1 data
12455331Samw  * structure is defined as:
12465331Samw  *
12475331Samw  *     struct SERVER_INFO_1 {
12485331Samw  *         char            sv1_name[16];
12495331Samw  *         char            sv1_version_major;
12505331Samw  *         char            sv1_version_minor;
12515331Samw  *         uint32_t   sv1_type;
12525331Samw  *         char        *sv1_comment_or_master_browser;
12535331Samw  *     };
12545331Samw  *
12555331Samw  *    sv1_name contains a null-terminated string that specifies the name
12565331Samw  *    of a computer, or a domain name if SV_TYPE_DOMAIN_ENUM is set in
12575331Samw  *    sv1_type.
12585331Samw  *
12595331Samw  *    sv1_version_major whatever was specified in the HostAnnouncement
12605331Samw  *    or DomainAnnouncement frame with which the entry was registered.
12615331Samw  *
12625331Samw  *    sv1_version_minor whatever was specified in the HostAnnouncement
12635331Samw  *    or DomainAnnouncement frame with which the entry was registered.
12645331Samw  *
12655331Samw  *    sv1_type specifies the type of software the computer is running.
12665331Samw  *    The member can be one or a combination of the values defined above
12675331Samw  *    in the Transaction request parameters section for fServerType.
12685331Samw  *
12695331Samw  *
12705331Samw  *    sv1_comment_or_master_browser points to a null-terminated string. If
12715331Samw  *    the sv1_type indicates that the entry is for a domain, this
12725331Samw  *    specifies the name of server running the domain master browser;
12735331Samw  *    otherwise, it specifies a comment describing the server. The comment
12745331Samw  *    can be a null string or the pointer may be a null pointer.
12755331Samw  *
12765331Samw  *    In case there are multiple SERVER_INFO_1 data structures to
12775331Samw  *    return, the server may put all these fixed length structures in
12785331Samw  *    the return buffer, leave some space and then put all the variable
12795331Samw  *    length data (the actual value of the sv1_comment strings) at the
12805331Samw  *    end of the buffer.
12815331Samw  *
12825331Samw  * There is no auxiliary data to receive.
12835331Samw  */
12845331Samw 
12855331Samw int
smb_trans_net_server_enum2(struct smb_request * sr,struct smb_xa * xa)12865331Samw smb_trans_net_server_enum2(struct smb_request *sr, struct smb_xa *xa)
12875331Samw {
12885331Samw 	uint16_t opcode, level, max_bytes;
12895331Samw 	uint32_t server_type;
12905331Samw 	unsigned char *domain;
12915331Samw 	struct mbuf_chain str_mb;
12925331Samw 	char *hostname, *s;
12935331Samw 	smb_kmod_cfg_t *si;
12945331Samw 
12957052Samw 	if (smb_mbc_decodef(&xa->req_param_mb,
12967052Samw 	    "%wsswwls", sr, &opcode, &s, &s,
12975331Samw 	    &level, &max_bytes, &server_type, &domain) != 0)
12986139Sjb150015 		return (SDRC_NOT_IMPLEMENTED);
12995331Samw 
13006139Sjb150015 	si = sr->sr_cfg;
13015331Samw 
130210966SJordan.Brown@Sun.COM 	if (smb_strcasecmp(si->skc_nbdomain, (char *)domain, 0) != 0) {
13037052Samw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0);
13046139Sjb150015 		return (SDRC_SUCCESS);
13055331Samw 	}
13065331Samw 
13075331Samw 	if ((server_type & MY_SERVER_TYPE) == 0) {
13087052Samw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0);
13096139Sjb150015 		return (SDRC_SUCCESS);
13105331Samw 	}
13115331Samw 
13125331Samw 	MBC_INIT(&str_mb, max_bytes);
13135331Samw 
13145331Samw 	hostname = si->skc_hostname;
13155331Samw 
13167052Samw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "16c", hostname);
13175331Samw 	if (level == 1) {
13187052Samw 		(void) smb_mbc_encodef(&xa->rep_data_mb, "bbll",
1319*13082SJoyce.McIntosh@Sun.COM 		    (uint8_t)sr->sr_cfg->skc_version.sv_major,
1320*13082SJoyce.McIntosh@Sun.COM 		    (uint8_t)sr->sr_cfg->skc_version.sv_minor,
13215331Samw 		    MY_SERVER_TYPE, MBC_LENGTH(&str_mb));
13227052Samw 		(void) smb_mbc_encodef(&str_mb, "s", si->skc_system_comment);
13235331Samw 	}
13245331Samw 
13257052Samw 	(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0,
13265331Samw 	    -MBC_LENGTH(&xa->rep_data_mb), 1, 1);
13277052Samw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "m", str_mb.chain);
13286139Sjb150015 	return (SDRC_SUCCESS);
13295331Samw }
13305331Samw 
133110966SJordan.Brown@Sun.COM static boolean_t
is_supported_mailslot(const char * mailslot)133210966SJordan.Brown@Sun.COM is_supported_mailslot(const char *mailslot)
133310966SJordan.Brown@Sun.COM {
133410966SJordan.Brown@Sun.COM 	static char *mailslots[] = {
133510966SJordan.Brown@Sun.COM 		PIPE_LANMAN,
133610966SJordan.Brown@Sun.COM 		MAILSLOT_LANMAN,
133710966SJordan.Brown@Sun.COM 		MAILSLOT_BROWSE,
133810966SJordan.Brown@Sun.COM 		MAILSLOT_MSBROWSE
133910966SJordan.Brown@Sun.COM 	};
134010966SJordan.Brown@Sun.COM 
134110966SJordan.Brown@Sun.COM 	int i;
134210966SJordan.Brown@Sun.COM 
134310966SJordan.Brown@Sun.COM 	for (i = 0; i < sizeof (mailslots)/sizeof (mailslots[0]); ++i)
134410966SJordan.Brown@Sun.COM 		if (smb_strcasecmp(mailslot, mailslots[i], 0) == 0)
134510966SJordan.Brown@Sun.COM 			return (B_TRUE);
134610966SJordan.Brown@Sun.COM 
134710966SJordan.Brown@Sun.COM 	return (B_FALSE);
134810966SJordan.Brown@Sun.COM }
134910966SJordan.Brown@Sun.COM 
13505331Samw /*
135110966SJordan.Brown@Sun.COM  * Currently, just return false if the pipe is \\PIPE\repl.
135210966SJordan.Brown@Sun.COM  * Otherwise, return true.
13535331Samw  */
135410966SJordan.Brown@Sun.COM static boolean_t
is_supported_pipe(const char * pname)135510966SJordan.Brown@Sun.COM is_supported_pipe(const char *pname)
13565331Samw {
135710966SJordan.Brown@Sun.COM 	if (smb_strcasecmp(pname, PIPE_REPL, 0) == 0)
135810966SJordan.Brown@Sun.COM 		return (B_FALSE);
13595331Samw 
136010966SJordan.Brown@Sun.COM 	return (B_TRUE);
13615331Samw }
13625331Samw 
13636030Sjb150015 static smb_sdrc_t
smb_trans_dispatch(smb_request_t * sr,smb_xa_t * xa)136411963SAfshin.Ardakani@Sun.COM smb_trans_dispatch(smb_request_t *sr, smb_xa_t *xa)
13655331Samw {
13665331Samw 	int		rc, pos;
13675331Samw 	int		total_bytes, n_setup, n_param, n_data;
13685331Samw 	int		param_off, param_pad, data_off, data_pad;
13695331Samw 	uint16_t	opcode;
13705331Samw 	uint16_t	devstate;
13715331Samw 	char		*req_fmt;
13725331Samw 	char		*rep_fmt;
13738934SJose.Borrego@Sun.COM 	smb_vdb_t	vdb;
13745331Samw 
13755331Samw 	n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200;
13765331Samw 	n_setup++;
13775331Samw 	n_setup = n_setup & ~0x0001;
13785331Samw 	n_param = (xa->smb_mprcnt < smb_maxbufsize)
13795331Samw 	    ? xa->smb_mprcnt : smb_maxbufsize;
13805331Samw 	n_param++;
13815331Samw 	n_param = n_param & ~0x0001;
13825331Samw 	rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param);
13835331Samw 	n_data =  (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc;
13845331Samw 	MBC_INIT(&xa->rep_setup_mb, n_setup * 2);
13855331Samw 	MBC_INIT(&xa->rep_param_mb, n_param);
13865331Samw 	MBC_INIT(&xa->rep_data_mb, n_data);
13875331Samw 
13885331Samw 	if (xa->smb_suwcnt > 0 && STYPE_ISIPC(sr->tid_tree->t_res_type)) {
13897052Samw 		rc = smb_mbc_decodef(&xa->req_setup_mb, "ww", &opcode,
13905331Samw 		    &sr->smb_fid);
13915331Samw 		if (rc != 0)
13925331Samw 			goto trans_err_not_supported;
13935331Samw 		switch (opcode) {
13945331Samw 		case TRANS_SET_NMPIPE_STATE:
13957052Samw 			if ((rc = smb_mbc_decodef(&xa->req_param_mb, "w",
13965331Samw 			    &devstate)) != 0)
13975331Samw 				goto trans_err_not_supported;
13985331Samw 
13996139Sjb150015 			rc = SDRC_SUCCESS;
14005331Samw 			break;
14015331Samw 
14025331Samw 		case TRANS_TRANSACT_NMPIPE:
14038934SJose.Borrego@Sun.COM 			smbsr_lookup_file(sr);
14045331Samw 			if (sr->fid_ofile == NULL) {
14055772Sas200622 				smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
14065331Samw 				    ERRDOS, ERRbadfid);
14076139Sjb150015 				return (SDRC_ERROR);
14085331Samw 			}
14095331Samw 
14107052Samw 			rc = smb_mbc_decodef(&xa->req_data_mb, "#B",
14115331Samw 			    xa->smb_tdscnt, &vdb);
14125331Samw 			if (rc != 0)
14135331Samw 				goto trans_err_not_supported;
14145331Samw 
14158934SJose.Borrego@Sun.COM 			rc = smb_opipe_transact(sr, &vdb.vdb_uio);
14165331Samw 			break;
14175331Samw 
14185331Samw 		case TRANS_WAIT_NMPIPE:
141910966SJordan.Brown@Sun.COM 			if (!is_supported_pipe(xa->xa_pipe_name)) {
14205772Sas200622 				smbsr_error(sr, 0, ERRDOS, ERRbadfile);
14216139Sjb150015 				return (SDRC_ERROR);
14225331Samw 			}
14236139Sjb150015 			rc = SDRC_SUCCESS;
14245331Samw 			break;
14255331Samw 
14265331Samw 		default:
14275331Samw 			goto trans_err_not_supported;
14285331Samw 		}
14295331Samw 	} else {
143010966SJordan.Brown@Sun.COM 		if (!is_supported_mailslot(xa->xa_pipe_name))
14315331Samw 			goto trans_err_not_supported;
14325331Samw 
14337052Samw 		if ((rc = smb_mbc_decodef(&xa->req_param_mb, "%wss", sr,
14345331Samw 		    &opcode, &req_fmt, &rep_fmt)) != 0)
14355331Samw 			goto trans_err_not_supported;
14365331Samw 
14375331Samw 		switch (opcode) {
14385331Samw 		case API_WshareEnum:
14395331Samw 			rc = smb_trans_net_share_enum(sr, xa);
14405331Samw 			break;
14415331Samw 
14425331Samw 		case API_WshareGetInfo:
14436771Sjb150015 			rc = smb_trans_net_share_getinfo(sr, xa);
14445331Samw 			break;
14455331Samw 
14465331Samw 		case API_WserverGetInfo:
14476771Sjb150015 			rc = smb_trans_net_server_getinfo(sr, xa);
14485331Samw 			break;
14495331Samw 
14505331Samw 		case API_WUserGetInfo:
14516771Sjb150015 			rc = smb_trans_net_user_getinfo(sr, xa);
14525331Samw 			break;
14535331Samw 
14545331Samw 		case API_WWkstaGetInfo:
14556771Sjb150015 			rc = smb_trans_net_workstation_getinfo(sr, xa);
14565331Samw 			break;
14575331Samw 
14585331Samw 		case API_NetServerEnum2:
14595331Samw 			rc = smb_trans_net_server_enum2(sr, xa);
14605331Samw 			break;
14615331Samw 
14625331Samw 		default:
14635331Samw 			goto trans_err_not_supported;
14645331Samw 		}
14655331Samw 	}
14665331Samw 
14675331Samw 	switch (rc) {
14686139Sjb150015 	case SDRC_SUCCESS:
14695331Samw 		break;
14705331Samw 
14715331Samw 	case SDRC_DROP_VC:
14725331Samw 	case SDRC_NO_REPLY:
14736139Sjb150015 	case SDRC_ERROR:
14745331Samw 		return (rc);
14755331Samw 
14766139Sjb150015 	case SDRC_NOT_IMPLEMENTED:
14775331Samw 		goto trans_err_not_supported;
14785331Samw 
14795331Samw 	default:
14805331Samw 		break;
14815331Samw 	}
14825331Samw 
14835331Samw 	n_setup = MBC_LENGTH(&xa->rep_setup_mb);
14845331Samw 	n_param = MBC_LENGTH(&xa->rep_param_mb);
14855331Samw 	n_data  = MBC_LENGTH(&xa->rep_data_mb);
14865331Samw 
14875331Samw 	if (xa->smb_msrcnt < n_setup ||
14885331Samw 	    xa->smb_mprcnt < n_param ||
14895331Samw 	    xa->smb_mdrcnt < n_data) {
14905331Samw 		goto trans_err_too_small;
14915331Samw 	}
14925331Samw 
14935331Samw 	/* neato, blast it over there */
14945331Samw 
14955331Samw 	n_setup = (n_setup + 1) / 2;		/* Convert to setup words */
14965331Samw 	param_pad = 1;				/* always one */
14975331Samw 	param_off = param_pad + 32 + 21 + (n_setup << 1) + 2;
14985331Samw 	data_pad = (param_off + n_param) & 1;	/* Pad to short */
14995331Samw 	/* Param off from hdr start */
15005331Samw 	data_off = param_off + n_param + data_pad;
15015331Samw 	total_bytes = param_pad + n_param + data_pad + n_data;
15025331Samw 
15036030Sjb150015 	rc = smbsr_encode_result(sr, 10+n_setup, total_bytes,
15047052Samw 	    "bww2.wwwwwwb.Cw#.C#.C",
15055331Samw 	    10 + n_setup,		/* wct */
15065331Samw 	    n_param,			/* Total Parameter Bytes */
15075331Samw 	    n_data,			/* Total Data Bytes */
15085331Samw 	    n_param,			/* Total Parameter Bytes this buffer */
15095331Samw 	    param_off,			/* Param offset from header start */
15105331Samw 	    0,				/* Param displacement */
15115331Samw 	    n_data,			/* Total Data Bytes this buffer */
15125331Samw 	    data_off,			/* Data offset from header start */
15135331Samw 	    0,				/* Data displacement */
15145331Samw 	    n_setup,			/* suwcnt */
15155331Samw 	    &xa->rep_setup_mb, /* setup[] */
15165331Samw 	    total_bytes,		/* Total data bytes */
15175331Samw 	    param_pad,
15185331Samw 	    &xa->rep_param_mb,
15195331Samw 	    data_pad,
15205331Samw 	    &xa->rep_data_mb);
15216139Sjb150015 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
15225331Samw 
15235331Samw trans_err_too_small:
15245331Samw 	rc = NERR_BufTooSmall;
15255331Samw 	goto trans_err;
15265331Samw 
15275331Samw trans_err_not_supported:
15285331Samw 	rc = ERROR_NOT_SUPPORTED;
15295331Samw 	goto trans_err;
15305331Samw 
15315331Samw trans_err:
15325331Samw 	pos = MBC_LENGTH(&sr->reply) + 23;
15337052Samw 	rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www",
15345331Samw 	    10,		/* wct */
15355331Samw 	    4, 0,	/* tpscnt tdscnt */
15365331Samw 	    4, pos, 0,	/* pscnt psoff psdisp */
15375331Samw 	    0, 0, 0,	/* dscnt dsoff dsdisp */
15385331Samw 	    0,		/* suwcnt */
15395331Samw 	    4,		/* bcc */
15405331Samw 	    rc,
15415331Samw 	    0);		/* converter word? */
15426139Sjb150015 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
15435331Samw }
15445331Samw 
15456030Sjb150015 static smb_sdrc_t
smb_trans2_dispatch(smb_request_t * sr,smb_xa_t * xa)154611963SAfshin.Ardakani@Sun.COM smb_trans2_dispatch(smb_request_t *sr, smb_xa_t *xa)
15475331Samw {
15485331Samw 	int		rc, pos;
15495331Samw 	int		total_bytes, n_setup, n_param, n_data;
15505331Samw 	int		param_off, param_pad, data_off, data_pad;
15515331Samw 	uint16_t	opcode;
15525331Samw 	uint16_t  nt_unknown_secret = 0x0100;
15535331Samw 	char *fmt;
15545331Samw 
15555331Samw 	n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200;
15565331Samw 	n_setup++;
15575331Samw 	n_setup = n_setup & ~0x0001;
15585331Samw 	n_param = (xa->smb_mprcnt < smb_maxbufsize)
15595331Samw 	    ? xa->smb_mprcnt : smb_maxbufsize;
15605331Samw 	n_param++;
15615331Samw 	n_param = n_param & ~0x0001;
15625331Samw 	rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param);
15635331Samw 	n_data =  (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc;
15645331Samw 	MBC_INIT(&xa->rep_setup_mb, n_setup * 2);
15655331Samw 	MBC_INIT(&xa->rep_param_mb, n_param);
15665331Samw 	MBC_INIT(&xa->rep_data_mb, n_data);
15675331Samw 
15687052Samw 	if (smb_mbc_decodef(&xa->req_setup_mb, "w", &opcode) != 0)
15695331Samw 		goto trans_err_not_supported;
15705331Samw 
15715331Samw 	/*
15725331Samw 	 * Save this for /proc to read later.
15735331Samw 	 */
15745331Samw 	xa->smb_func = opcode;
15755331Samw 
15765331Samw 	/* for now, only respond to the */
15775331Samw 	switch (opcode) {
15788934SJose.Borrego@Sun.COM 	case TRANS2_OPEN2:
15798934SJose.Borrego@Sun.COM 		rc = smb_com_trans2_open2(sr, xa);
15808934SJose.Borrego@Sun.COM 		break;
15818934SJose.Borrego@Sun.COM 
15825331Samw 	case TRANS2_CREATE_DIRECTORY:
15835331Samw 		rc = smb_com_trans2_create_directory(sr, xa);
15845331Samw 		break;
15855331Samw 
15865331Samw 	case TRANS2_FIND_FIRST2:
15875331Samw 		/*
15885331Samw 		 * Should have enough room to send the response
15895331Samw 		 * data back to client.
15905331Samw 		 */
15915331Samw 		if (n_data == 0) {
15925772Sas200622 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
15935331Samw 			    ERRDOS, ERROR_BAD_LENGTH);
15946139Sjb150015 			return (SDRC_ERROR);
15955331Samw 		}
15965331Samw 		rc = smb_com_trans2_find_first2(sr, xa);
15975331Samw 		break;
15985331Samw 
15995331Samw 	case TRANS2_FIND_NEXT2:
16005331Samw 		/*
16015331Samw 		 * Should have enough room to send the response
16025331Samw 		 * data back to client.
16035331Samw 		 */
16045331Samw 		if (n_data == 0) {
16055772Sas200622 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
16065331Samw 			    ERRDOS, ERROR_BAD_LENGTH);
16076139Sjb150015 			return (SDRC_ERROR);
16085331Samw 		}
16095331Samw 		rc = smb_com_trans2_find_next2(sr, xa);
16105331Samw 		break;
16115331Samw 
16125331Samw 	case TRANS2_QUERY_FS_INFORMATION:
16135331Samw 		/*
16145331Samw 		 * Should have enough room to send the response
16155331Samw 		 * data back to client.
16165331Samw 		 */
16175331Samw 		if (n_data == 0) {
16185772Sas200622 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
16195331Samw 			    ERRDOS, ERROR_BAD_LENGTH);
16206139Sjb150015 			return (SDRC_ERROR);
16215331Samw 		}
16225331Samw 		rc = smb_com_trans2_query_fs_information(sr, xa);
16235331Samw 		break;
16245331Samw 
162511963SAfshin.Ardakani@Sun.COM 	case TRANS2_SET_FS_INFORMATION:
162611963SAfshin.Ardakani@Sun.COM 		rc = smb_com_trans2_set_fs_information(sr, xa);
162711963SAfshin.Ardakani@Sun.COM 		break;
162811963SAfshin.Ardakani@Sun.COM 
16295331Samw 	case TRANS2_QUERY_PATH_INFORMATION:
16305331Samw 		/*
16315331Samw 		 * Should have enough room to send the response
16325331Samw 		 * data back to client.
16335331Samw 		 */
16345331Samw 		if (n_data == 0) {
16355772Sas200622 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
16365331Samw 			    ERRDOS, ERROR_BAD_LENGTH);
16376139Sjb150015 			return (SDRC_ERROR);
16385331Samw 		}
16395331Samw 		rc = smb_com_trans2_query_path_information(sr, xa);
16405331Samw 		break;
16415331Samw 
16425331Samw 	case TRANS2_QUERY_FILE_INFORMATION:
16435331Samw 		/*
16445331Samw 		 * Should have enough room to send the response
16455331Samw 		 * data back to client.
16465331Samw 		 */
16475331Samw 		if (n_data == 0) {
16485772Sas200622 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
16495331Samw 			    ERRDOS, ERROR_BAD_LENGTH);
16506139Sjb150015 			return (SDRC_ERROR);
16515331Samw 		}
16525331Samw 		rc = smb_com_trans2_query_file_information(sr, xa);
16535331Samw 		break;
16545331Samw 
16555331Samw 	case TRANS2_SET_PATH_INFORMATION:
16565331Samw 		rc = smb_com_trans2_set_path_information(sr, xa);
16575331Samw 		break;
16585331Samw 
16595331Samw 	case TRANS2_SET_FILE_INFORMATION:
16605331Samw 		rc = smb_com_trans2_set_file_information(sr, xa);
16615331Samw 		break;
166211963SAfshin.Ardakani@Sun.COM 
166311963SAfshin.Ardakani@Sun.COM 	case TRANS2_GET_DFS_REFERRAL:
166411963SAfshin.Ardakani@Sun.COM 		rc = smb_com_trans2_get_dfs_referral(sr, xa);
166511963SAfshin.Ardakani@Sun.COM 		break;
166611963SAfshin.Ardakani@Sun.COM 
16675331Samw 	default:
16688934SJose.Borrego@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
16695331Samw 		goto trans_err_not_supported;
16705331Samw 	}
16715331Samw 
16725331Samw 	switch (rc) {
16736139Sjb150015 	case SDRC_SUCCESS:
16745331Samw 		break;
16755331Samw 
16765331Samw 	case SDRC_DROP_VC:
16775331Samw 	case SDRC_NO_REPLY:
16786139Sjb150015 	case SDRC_ERROR:
16795331Samw 		return (rc);
16805331Samw 
16816139Sjb150015 	case SDRC_NOT_IMPLEMENTED:
16825331Samw 		goto trans_err_not_supported;
16835331Samw 
16845331Samw 	default:
16855331Samw 		break;
16865331Samw 	}
16875331Samw 
16885331Samw 	n_setup = MBC_LENGTH(&xa->rep_setup_mb);
16895331Samw 	n_param = MBC_LENGTH(&xa->rep_param_mb);
16905331Samw 	n_data  = MBC_LENGTH(&xa->rep_data_mb);
16915331Samw 
16925331Samw 	if (xa->smb_msrcnt < n_setup ||
16935331Samw 	    xa->smb_mprcnt < n_param ||
16945331Samw 	    xa->smb_mdrcnt < n_data) {
16955331Samw 		goto trans_err_too_small;
16965331Samw 	}
16975331Samw 
16985331Samw 	/* neato, blast it over there */
16995331Samw 
17005331Samw 	n_setup = (n_setup + 1) / 2;		/* Conver to setup words */
17015331Samw 	param_pad = 1;				/* must be one */
17025331Samw 	param_off = param_pad + 32 + 21 + (n_setup << 1) + 2;
17035331Samw 
17045331Samw 	/*
17055331Samw 	 * Including the nt_unknown_secret value persuades netmon to
17065331Samw 	 * display the correct data format for QueryPathInfo and
17075331Samw 	 * QueryFileInfo.
17085331Samw 	 */
17095331Samw 	if (opcode == TRANS2_QUERY_FILE_INFORMATION ||
17105331Samw 	    opcode == TRANS2_QUERY_PATH_INFORMATION) {
17115331Samw 		data_pad = sizeof (uint16_t);
17125331Samw 		data_off = param_off + n_param + data_pad;
17137052Samw 		fmt = "bww2.wwwwwwb.Cw#.CwC";
17145331Samw 		nt_unknown_secret = 0x0100;
17155331Samw 	}
17165331Samw 	else
17175331Samw 	{
17185331Samw 		data_pad = (param_off + n_param) & 1; /* Pad to short */
17195331Samw 		/* Param off from hdr start */
17205331Samw 		data_off = param_off + n_param + data_pad;
17217052Samw 		fmt = "bww2.wwwwwwb.Cw#.C#.C";
17225331Samw 		/*LINTED E_ASSIGN_NARROW_CONV*/
17235331Samw 		nt_unknown_secret = data_pad;
17245331Samw 	}
17255331Samw 
17265331Samw 	total_bytes = param_pad + n_param + data_pad + n_data;
17275331Samw 
17286030Sjb150015 	rc = smbsr_encode_result(sr, 10+n_setup, total_bytes,
17295331Samw 	    fmt,
17305331Samw 	    10 + n_setup,		/* wct */
17315331Samw 	    n_param,			/* Total Parameter Bytes */
17325331Samw 	    n_data /* + data_pad */,	/* Total Data Bytes */
17335331Samw 	    n_param,			/* Total Parameter Bytes this buffer */
17345331Samw 	    param_off,			/* Param offset from header start */
17355331Samw 	    0,				/* Param displacement */
17365331Samw 	    n_data /* + data_pad */,	/* Total Data Bytes this buffer */
17375331Samw 	    data_off,			/* Data offset from header start */
17385331Samw 	    0,				/* Data displacement */
17395331Samw 	    n_setup,			/* suwcnt */
17405331Samw 	    &xa->rep_setup_mb,		/* setup[] */
17415331Samw 	    total_bytes,		/* Total data bytes */
17425331Samw 	    param_pad,
17435331Samw 	    &xa->rep_param_mb,
17445331Samw 	    nt_unknown_secret,
17455331Samw 	    &xa->rep_data_mb);
17466139Sjb150015 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
17475331Samw 
17485331Samw trans_err_too_small:
17495331Samw 	rc = NERR_BufTooSmall;
17505331Samw 	goto trans_err;
17515331Samw 
17525331Samw trans_err_not_supported:
17535331Samw 	rc = ERROR_NOT_SUPPORTED;
17545331Samw 	goto trans_err;
17555331Samw 
17565331Samw trans_err:
17575331Samw 	pos = MBC_LENGTH(&sr->reply) + 23;
17587052Samw 	rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www",
17595331Samw 	    10,		/* wct */
17605331Samw 	    4, 0,	/* tpscnt tdscnt */
17615331Samw 	    4, pos, 0,	/* pscnt psoff psdisp */
17625331Samw 	    0, 0, 0,	/* dscnt dsoff dsdisp */
17635331Samw 	    0,		/* suwcnt */
17645331Samw 	    4,		/* bcc */
17655331Samw 	    rc,
17665331Samw 	    0);		/* converter word? */
17676139Sjb150015 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
17685331Samw }
17695331Samw 
17705331Samw smb_xa_t *
smb_xa_create(smb_session_t * session,smb_request_t * sr,uint32_t total_parameter_count,uint32_t total_data_count,uint32_t max_parameter_count,uint32_t max_data_count,uint32_t max_setup_count,uint32_t setup_word_count)17715331Samw smb_xa_create(
17725331Samw     smb_session_t	*session,
17735331Samw     smb_request_t	*sr,
17745331Samw     uint32_t		total_parameter_count,
17755331Samw     uint32_t		total_data_count,
17765331Samw     uint32_t		max_parameter_count,
17775331Samw     uint32_t		max_data_count,
17785331Samw     uint32_t		max_setup_count,
17795331Samw     uint32_t		setup_word_count)
17805331Samw {
17815331Samw 	smb_xa_t	*xa, *nxa;
17825331Samw 	smb_llist_t	*xlist;
17835331Samw 
178410966SJordan.Brown@Sun.COM 	xa = kmem_zalloc(sizeof (smb_xa_t), KM_SLEEP);
17855331Samw 	xa->xa_refcnt = 1;
17865331Samw 	xa->smb_com = sr->smb_com;
17875331Samw 	xa->smb_flg = sr->smb_flg;
17885331Samw 	xa->smb_flg2 = sr->smb_flg2;
17895331Samw 	xa->smb_tid = sr->smb_tid;
17905331Samw 	xa->smb_pid = sr->smb_pid;
17915331Samw 	xa->smb_uid = sr->smb_uid;
17925331Samw 	xa->xa_smb_mid = sr->smb_mid;
17935331Samw 	xa->reply_seqnum = sr->reply_seqnum;
17945331Samw 	xa->smb_tpscnt = total_parameter_count;
17955331Samw 	xa->smb_tdscnt = total_data_count;
17965331Samw 	xa->smb_mprcnt = max_parameter_count;
17975331Samw 	xa->smb_mdrcnt = max_data_count;
17985331Samw 	xa->smb_msrcnt = max_setup_count;
17995331Samw 	xa->smb_suwcnt = setup_word_count;
18005331Samw 	xa->xa_session = session;
18015331Samw 	xa->xa_magic = SMB_XA_MAGIC;
18025331Samw 
18035331Samw 	/*
18045331Samw 	 * The new xa structure is checked against the current list to see
18055331Samw 	 * if it exists already.
18065331Samw 	 */
18075331Samw 	xlist = &session->s_xa_list;
18085331Samw 	smb_llist_enter(xlist, RW_WRITER);
18095331Samw 	nxa = smb_llist_head(xlist);
18105331Samw 	while (nxa) {
18115331Samw 		ASSERT(nxa->xa_magic == SMB_XA_MAGIC);
18125331Samw 		if (nxa->xa_smb_mid == xa->xa_smb_mid &&
18135331Samw 		    nxa->smb_pid == xa->smb_pid &&
18145331Samw 		    !SMB_XA_CLOSED(nxa) &&
18155331Samw 		    !(nxa->xa_flags & SMB_XA_FLAG_COMPLETE)) {
18165331Samw 			smb_llist_exit(xlist);
181710966SJordan.Brown@Sun.COM 			kmem_free(xa, sizeof (smb_xa_t));
18185331Samw 			return (NULL);
18195331Samw 		}
18205331Samw 		nxa = smb_llist_next(xlist, nxa);
18215331Samw 	}
18225331Samw 	smb_llist_insert_tail(xlist, xa);
18235331Samw 	smb_llist_exit(xlist);
18245331Samw 	return (xa);
18255331Samw }
18265331Samw 
18275331Samw void
smb_xa_delete(smb_xa_t * xa)18285331Samw smb_xa_delete(smb_xa_t *xa)
18295331Samw {
18305331Samw 	ASSERT(xa->xa_refcnt == 0);
18315331Samw 	ASSERT(SMB_XA_CLOSED(xa));
18325331Samw 
183310966SJordan.Brown@Sun.COM 	if (xa->xa_pipe_name)
183411963SAfshin.Ardakani@Sun.COM 		smb_mem_free(xa->xa_pipe_name);
18355331Samw 
18365331Samw 	if (xa->rep_setup_mb.chain != NULL)
18375331Samw 		m_freem(xa->rep_setup_mb.chain);
18385331Samw 	if (xa->rep_param_mb.chain != NULL)
18395331Samw 		m_freem(xa->rep_param_mb.chain);
18405331Samw 	if (xa->rep_data_mb.chain != NULL)
18415331Samw 		m_freem(xa->rep_data_mb.chain);
18425331Samw 
18435331Samw 	xa->xa_magic = (uint32_t)~SMB_XA_MAGIC;
184410966SJordan.Brown@Sun.COM 	kmem_free(xa, sizeof (smb_xa_t));
18455331Samw }
18465331Samw 
18475331Samw smb_xa_t *
smb_xa_hold(smb_xa_t * xa)18485331Samw smb_xa_hold(smb_xa_t *xa)
18495331Samw {
18505331Samw 	mutex_enter(&xa->xa_mutex);
18515331Samw 	xa->xa_refcnt++;
18525331Samw 	ASSERT(xa->xa_refcnt);
18535331Samw 	mutex_exit(&xa->xa_mutex);
18545331Samw 	return (xa);
18555331Samw }
18565331Samw 
18575331Samw void
smb_xa_rele(smb_session_t * session,smb_xa_t * xa)18585331Samw smb_xa_rele(smb_session_t *session, smb_xa_t *xa)
18595331Samw {
18605331Samw 	mutex_enter(&xa->xa_mutex);
18615331Samw 	ASSERT(xa->xa_refcnt);
18625331Samw 	xa->xa_refcnt--;
18635331Samw 	if (SMB_XA_CLOSED(xa) && (xa->xa_refcnt == 0)) {
18645331Samw 		mutex_exit(&xa->xa_mutex);
18655331Samw 		smb_llist_enter(&session->s_xa_list, RW_WRITER);
18665331Samw 		smb_llist_remove(&session->s_xa_list, xa);
18675331Samw 		smb_llist_exit(&session->s_xa_list);
18685331Samw 		smb_xa_delete(xa);
18695331Samw 		return;
18705331Samw 	}
18715331Samw 	mutex_exit(&xa->xa_mutex);
18725331Samw }
18735331Samw 
18745331Samw int
smb_xa_open(smb_xa_t * xa)18755331Samw smb_xa_open(smb_xa_t *xa)
18765331Samw {
18775331Samw 	int rc;
18785331Samw 
18795331Samw 	mutex_enter(&xa->xa_mutex);
18805331Samw 
18815331Samw 	ASSERT((xa->xa_flags & SMB_XA_FLAG_OPEN) == 0);
18825331Samw 
18835331Samw 	if ((xa->xa_flags & SMB_XA_FLAG_CLOSE) == 0) {
18845331Samw 		xa->xa_flags |= SMB_XA_FLAG_OPEN;
18855331Samw 		rc = 0;
18865331Samw 	} else {
18875331Samw 		rc = ERROR_INVALID_HANDLE;
18885331Samw 	}
18895331Samw 
18905331Samw 	mutex_exit(&xa->xa_mutex);
18915331Samw 
18925331Samw 	return (rc);
18935331Samw }
18945331Samw 
18955331Samw void
smb_xa_close(smb_xa_t * xa)18965331Samw smb_xa_close(smb_xa_t *xa)
18975331Samw {
18985331Samw 	mutex_enter(&xa->xa_mutex);
18995331Samw 	xa->xa_flags |= SMB_XA_FLAG_CLOSE;
19005331Samw 	xa->xa_flags &= ~SMB_XA_FLAG_OPEN;
19015331Samw 
19025331Samw 	if (xa->xa_refcnt == 0) {
19035331Samw 		mutex_exit(&xa->xa_mutex);
19045331Samw 		smb_llist_enter(&xa->xa_session->s_xa_list, RW_WRITER);
19055331Samw 		smb_llist_remove(&xa->xa_session->s_xa_list, xa);
19065331Samw 		smb_llist_exit(&xa->xa_session->s_xa_list);
19075331Samw 		smb_xa_delete(xa);
19085331Samw 		return;
19095331Samw 	}
19105331Samw 
19115331Samw 	mutex_exit(&xa->xa_mutex);
19125331Samw }
19135331Samw 
19145331Samw int
smb_xa_complete(smb_xa_t * xa)19155331Samw smb_xa_complete(smb_xa_t *xa)
19165331Samw {
19175331Samw 	int rc;
19185331Samw 
19195331Samw 	mutex_enter(&xa->xa_mutex);
19205331Samw 	if (xa->xa_flags & (SMB_XA_FLAG_COMPLETE | SMB_XA_FLAG_CLOSE)) {
19215331Samw 		rc = 0;
19225331Samw 	} else {
19235331Samw 		rc = 1;
19245331Samw 		xa->xa_flags |= SMB_XA_FLAG_COMPLETE;
19255331Samw 	}
19265331Samw 	mutex_exit(&xa->xa_mutex);
19275331Samw 	return (rc);
19285331Samw }
19295331Samw 
19305331Samw smb_xa_t *
smb_xa_find(smb_session_t * session,uint16_t pid,uint16_t mid)19315331Samw smb_xa_find(
19325331Samw     smb_session_t	*session,
19335331Samw     uint16_t		pid,
19345331Samw     uint16_t		mid)
19355331Samw {
19365331Samw 	smb_xa_t	*xa;
19375331Samw 	smb_llist_t	*xlist;
19385331Samw 
19395331Samw 	xlist = &session->s_xa_list;
19405331Samw 	smb_llist_enter(xlist, RW_READER);
19415331Samw 	xa = smb_llist_head(xlist);
19425331Samw 	while (xa) {
19435331Samw 		mutex_enter(&xa->xa_mutex);
19445331Samw 		if (xa->xa_smb_mid == mid &&
19455331Samw 		    xa->smb_pid == pid &&
19465331Samw 		    !SMB_XA_CLOSED(xa) &&
19475331Samw 		    !(xa->xa_flags & SMB_XA_FLAG_COMPLETE)) {
19485331Samw 			xa->xa_refcnt++;
19495331Samw 			ASSERT(xa->xa_refcnt);
19505331Samw 			mutex_exit(&xa->xa_mutex);
19515331Samw 			break;
19525331Samw 		}
19535331Samw 		mutex_exit(&xa->xa_mutex);
19545331Samw 		xa = smb_llist_next(xlist, xa);
19555331Samw 	}
19565331Samw 	smb_llist_exit(xlist);
19575331Samw 	return (xa);
19585331Samw }
1959