xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c (revision 12890:16985853e3aa)
110504SKeyur.Desai@Sun.COM /*
210504SKeyur.Desai@Sun.COM  * CDDL HEADER START
310504SKeyur.Desai@Sun.COM  *
410504SKeyur.Desai@Sun.COM  * The contents of this file are subject to the terms of the
510504SKeyur.Desai@Sun.COM  * Common Development and Distribution License (the "License").
610504SKeyur.Desai@Sun.COM  * You may not use this file except in compliance with the License.
710504SKeyur.Desai@Sun.COM  *
810504SKeyur.Desai@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910504SKeyur.Desai@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1010504SKeyur.Desai@Sun.COM  * See the License for the specific language governing permissions
1110504SKeyur.Desai@Sun.COM  * and limitations under the License.
1210504SKeyur.Desai@Sun.COM  *
1310504SKeyur.Desai@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1410504SKeyur.Desai@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510504SKeyur.Desai@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1610504SKeyur.Desai@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1710504SKeyur.Desai@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1810504SKeyur.Desai@Sun.COM  *
1910504SKeyur.Desai@Sun.COM  * CDDL HEADER END
2010504SKeyur.Desai@Sun.COM  */
2112508Samw@Sun.COM 
2210504SKeyur.Desai@Sun.COM /*
2312065SKeyur.Desai@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
2410504SKeyur.Desai@Sun.COM  */
2510504SKeyur.Desai@Sun.COM 
2610966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h>
2710504SKeyur.Desai@Sun.COM #include <smbsrv/smb_vops.h>
2810504SKeyur.Desai@Sun.COM #include <smbsrv/smb_fsops.h>
2910504SKeyur.Desai@Sun.COM 
3010504SKeyur.Desai@Sun.COM /*
3110504SKeyur.Desai@Sun.COM  * Trans2 Query File/Path Information Levels:
3210504SKeyur.Desai@Sun.COM  *
3310504SKeyur.Desai@Sun.COM  * SMB_INFO_STANDARD
3410504SKeyur.Desai@Sun.COM  * SMB_INFO_QUERY_EA_SIZE
3510504SKeyur.Desai@Sun.COM  * SMB_INFO_QUERY_EAS_FROM_LIST
3610504SKeyur.Desai@Sun.COM  * SMB_INFO_QUERY_ALL_EAS - not valid for pipes
3710504SKeyur.Desai@Sun.COM  * SMB_INFO_IS_NAME_VALID - only valid when query is by path
3810504SKeyur.Desai@Sun.COM  *
3910504SKeyur.Desai@Sun.COM  * SMB_QUERY_FILE_BASIC_INFO
4010504SKeyur.Desai@Sun.COM  * SMB_QUERY_FILE_STANDARD_INFO
4110504SKeyur.Desai@Sun.COM  * SMB_QUERY_FILE_EA_INFO
4210504SKeyur.Desai@Sun.COM  * SMB_QUERY_FILE_NAME_INFO
4310504SKeyur.Desai@Sun.COM  * SMB_QUERY_FILE_ALL_INFO
4410504SKeyur.Desai@Sun.COM  * SMB_QUERY_FILE_ALT_NAME_INFO - not valid for pipes
4510504SKeyur.Desai@Sun.COM  * SMB_QUERY_FILE_STREAM_INFO - not valid for pipes
4610504SKeyur.Desai@Sun.COM  * SMB_QUERY_FILE_COMPRESSION_INFO - not valid for pipes
4710504SKeyur.Desai@Sun.COM  *
4810504SKeyur.Desai@Sun.COM  * Supported Passthrough levels:
4910504SKeyur.Desai@Sun.COM  * SMB_FILE_BASIC_INFORMATION
5010504SKeyur.Desai@Sun.COM  * SMB_FILE_STANDARD_INFORMATION
5110504SKeyur.Desai@Sun.COM  * SMB_FILE_INTERNAL_INFORMATION
5210504SKeyur.Desai@Sun.COM  * SMB_FILE_EA_INFORMATION
53*12890SJoyce.McIntosh@Sun.COM  * SMB_FILE_ACCESS_INFORMATION - not yet supported when query by path
5410504SKeyur.Desai@Sun.COM  * SMB_FILE_NAME_INFORMATION
5510504SKeyur.Desai@Sun.COM  * SMB_FILE_ALL_INFORMATION
5610504SKeyur.Desai@Sun.COM  * SMB_FILE_ALT_NAME_INFORMATION - not valid for pipes
5710504SKeyur.Desai@Sun.COM  * SMB_FILE_STREAM_INFORMATION - not valid for pipes
5810504SKeyur.Desai@Sun.COM  * SMB_FILE_COMPRESSION_INFORMATION - not valid for pipes
5911963SAfshin.Ardakani@Sun.COM  * SMB_FILE_NETWORK_OPEN_INFORMATION - not valid for pipes
6010504SKeyur.Desai@Sun.COM  * SMB_FILE_ATTR_TAG_INFORMATION - not valid for pipes
6110504SKeyur.Desai@Sun.COM  *
6210504SKeyur.Desai@Sun.COM  * Internal levels representing non trans2 requests
6310504SKeyur.Desai@Sun.COM  * SMB_QUERY_INFORMATION
6410504SKeyur.Desai@Sun.COM  * SMB_QUERY_INFORMATION2
6510504SKeyur.Desai@Sun.COM  */
6610504SKeyur.Desai@Sun.COM 
67*12890SJoyce.McIntosh@Sun.COM /*
68*12890SJoyce.McIntosh@Sun.COM  * SMB_STREAM_ENCODE_FIXED_SIZE:
69*12890SJoyce.McIntosh@Sun.COM  * 2 dwords + 2 quadwords => 4 + 4 + 8 + 8 => 24
70*12890SJoyce.McIntosh@Sun.COM  */
71*12890SJoyce.McIntosh@Sun.COM #define	SMB_STREAM_ENCODE_FIXED_SZ	24
72*12890SJoyce.McIntosh@Sun.COM 
7310504SKeyur.Desai@Sun.COM typedef struct smb_queryinfo {
7410504SKeyur.Desai@Sun.COM 	smb_node_t	*qi_node;	/* NULL for pipes */
7510504SKeyur.Desai@Sun.COM 	smb_attr_t	qi_attr;
7610504SKeyur.Desai@Sun.COM 	boolean_t	qi_delete_on_close;
7710504SKeyur.Desai@Sun.COM 	uint32_t	qi_namelen;
7810504SKeyur.Desai@Sun.COM 	char		qi_shortname[SMB_SHORTNAMELEN];
7910504SKeyur.Desai@Sun.COM 	char		qi_name[MAXPATHLEN];
8010504SKeyur.Desai@Sun.COM } smb_queryinfo_t;
8110504SKeyur.Desai@Sun.COM #define	qi_mtime	qi_attr.sa_vattr.va_mtime
8210504SKeyur.Desai@Sun.COM #define	qi_ctime	qi_attr.sa_vattr.va_ctime
8310504SKeyur.Desai@Sun.COM #define	qi_atime	qi_attr.sa_vattr.va_atime
8410504SKeyur.Desai@Sun.COM #define	qi_crtime	qi_attr.sa_crtime
8510504SKeyur.Desai@Sun.COM 
8610504SKeyur.Desai@Sun.COM static int smb_query_by_fid(smb_request_t *, smb_xa_t *, uint16_t);
8711963SAfshin.Ardakani@Sun.COM static int smb_query_by_path(smb_request_t *, smb_xa_t *, uint16_t);
8810504SKeyur.Desai@Sun.COM 
8910504SKeyur.Desai@Sun.COM static int smb_query_fileinfo(smb_request_t *, smb_node_t *,
9010504SKeyur.Desai@Sun.COM     uint16_t, smb_queryinfo_t *);
9110504SKeyur.Desai@Sun.COM static int smb_query_pipeinfo(smb_request_t *, smb_opipe_t *,
9210504SKeyur.Desai@Sun.COM     uint16_t, smb_queryinfo_t *);
9310504SKeyur.Desai@Sun.COM static boolean_t smb_query_pipe_valid_infolev(smb_request_t *, uint16_t);
9410504SKeyur.Desai@Sun.COM 
9510504SKeyur.Desai@Sun.COM static int smb_query_encode_response(smb_request_t *, smb_xa_t *,
9610504SKeyur.Desai@Sun.COM     uint16_t, smb_queryinfo_t *);
9710504SKeyur.Desai@Sun.COM static void smb_encode_stream_info(smb_request_t *, smb_xa_t *,
9810504SKeyur.Desai@Sun.COM     smb_queryinfo_t *);
99*12890SJoyce.McIntosh@Sun.COM static boolean_t smb_stream_fits(smb_request_t *, smb_xa_t *, char *, uint32_t);
10012508Samw@Sun.COM static int smb_query_pathname(smb_request_t *, smb_node_t *, boolean_t,
10112508Samw@Sun.COM     smb_queryinfo_t *);
10212508Samw@Sun.COM static void smb_query_shortname(smb_node_t *, smb_queryinfo_t *);
10310504SKeyur.Desai@Sun.COM 
10411963SAfshin.Ardakani@Sun.COM int smb_query_passthru;
10510504SKeyur.Desai@Sun.COM 
10610504SKeyur.Desai@Sun.COM /*
10710504SKeyur.Desai@Sun.COM  * smb_com_trans2_query_file_information
10810504SKeyur.Desai@Sun.COM  */
10910504SKeyur.Desai@Sun.COM smb_sdrc_t
smb_com_trans2_query_file_information(struct smb_request * sr,struct smb_xa * xa)11010504SKeyur.Desai@Sun.COM smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa)
11110504SKeyur.Desai@Sun.COM {
11210504SKeyur.Desai@Sun.COM 	uint16_t infolev;
11310504SKeyur.Desai@Sun.COM 
11410504SKeyur.Desai@Sun.COM 	if (smb_mbc_decodef(&xa->req_param_mb, "ww",
11510504SKeyur.Desai@Sun.COM 	    &sr->smb_fid, &infolev) != 0)
11610504SKeyur.Desai@Sun.COM 		return (SDRC_ERROR);
11710504SKeyur.Desai@Sun.COM 
11810504SKeyur.Desai@Sun.COM 	if (smb_query_by_fid(sr, xa, infolev) != 0)
11910504SKeyur.Desai@Sun.COM 		return (SDRC_ERROR);
12010504SKeyur.Desai@Sun.COM 
12110504SKeyur.Desai@Sun.COM 	return (SDRC_SUCCESS);
12210504SKeyur.Desai@Sun.COM }
12310504SKeyur.Desai@Sun.COM 
12410504SKeyur.Desai@Sun.COM /*
12510504SKeyur.Desai@Sun.COM  * smb_com_trans2_query_path_information
12610504SKeyur.Desai@Sun.COM  */
12710504SKeyur.Desai@Sun.COM smb_sdrc_t
smb_com_trans2_query_path_information(smb_request_t * sr,smb_xa_t * xa)12810504SKeyur.Desai@Sun.COM smb_com_trans2_query_path_information(smb_request_t *sr, smb_xa_t *xa)
12910504SKeyur.Desai@Sun.COM {
13011963SAfshin.Ardakani@Sun.COM 	uint16_t	infolev;
13111963SAfshin.Ardakani@Sun.COM 	smb_fqi_t	*fqi = &sr->arg.dirop.fqi;
13210504SKeyur.Desai@Sun.COM 
13311447Samw@Sun.COM 	if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
13410504SKeyur.Desai@Sun.COM 		smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
13510504SKeyur.Desai@Sun.COM 		    ERRDOS, ERROR_INVALID_FUNCTION);
13610504SKeyur.Desai@Sun.COM 		return (SDRC_ERROR);
13710504SKeyur.Desai@Sun.COM 	}
13810504SKeyur.Desai@Sun.COM 
13910504SKeyur.Desai@Sun.COM 	if (smb_mbc_decodef(&xa->req_param_mb, "%w4.u",
14011963SAfshin.Ardakani@Sun.COM 	    sr, &infolev, &fqi->fq_path.pn_path) != 0)
14110504SKeyur.Desai@Sun.COM 		return (SDRC_ERROR);
14210504SKeyur.Desai@Sun.COM 
14311963SAfshin.Ardakani@Sun.COM 	if (smb_query_by_path(sr, xa, infolev) != 0)
14410504SKeyur.Desai@Sun.COM 		return (SDRC_ERROR);
14510504SKeyur.Desai@Sun.COM 
14610504SKeyur.Desai@Sun.COM 	return (SDRC_SUCCESS);
14710504SKeyur.Desai@Sun.COM }
14810504SKeyur.Desai@Sun.COM 
14910504SKeyur.Desai@Sun.COM /*
15010504SKeyur.Desai@Sun.COM  * smb_com_query_information (aka getattr)
15110504SKeyur.Desai@Sun.COM  */
15210504SKeyur.Desai@Sun.COM smb_sdrc_t
smb_pre_query_information(smb_request_t * sr)15310504SKeyur.Desai@Sun.COM smb_pre_query_information(smb_request_t *sr)
15410504SKeyur.Desai@Sun.COM {
15510504SKeyur.Desai@Sun.COM 	int rc;
15610504SKeyur.Desai@Sun.COM 	smb_fqi_t *fqi = &sr->arg.dirop.fqi;
15710504SKeyur.Desai@Sun.COM 
15810504SKeyur.Desai@Sun.COM 	rc = smbsr_decode_data(sr, "%S", sr, &fqi->fq_path.pn_path);
15910504SKeyur.Desai@Sun.COM 
16010504SKeyur.Desai@Sun.COM 	DTRACE_SMB_2(op__QueryInformation__start, smb_request_t *, sr,
16110504SKeyur.Desai@Sun.COM 	    smb_fqi_t *, fqi);
16210504SKeyur.Desai@Sun.COM 
16310504SKeyur.Desai@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
16410504SKeyur.Desai@Sun.COM }
16510504SKeyur.Desai@Sun.COM 
16610504SKeyur.Desai@Sun.COM void
smb_post_query_information(smb_request_t * sr)16710504SKeyur.Desai@Sun.COM smb_post_query_information(smb_request_t *sr)
16810504SKeyur.Desai@Sun.COM {
16910504SKeyur.Desai@Sun.COM 	DTRACE_SMB_1(op__QueryInformation__done, smb_request_t *, sr);
17010504SKeyur.Desai@Sun.COM }
17110504SKeyur.Desai@Sun.COM 
17210504SKeyur.Desai@Sun.COM smb_sdrc_t
smb_com_query_information(smb_request_t * sr)17310504SKeyur.Desai@Sun.COM smb_com_query_information(smb_request_t *sr)
17410504SKeyur.Desai@Sun.COM {
17510504SKeyur.Desai@Sun.COM 	uint16_t infolev = SMB_QUERY_INFORMATION;
17610504SKeyur.Desai@Sun.COM 
17711447Samw@Sun.COM 	if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
17810504SKeyur.Desai@Sun.COM 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
17910504SKeyur.Desai@Sun.COM 		    ERRDOS, ERROR_ACCESS_DENIED);
18010504SKeyur.Desai@Sun.COM 		return (SDRC_ERROR);
18110504SKeyur.Desai@Sun.COM 	}
18210504SKeyur.Desai@Sun.COM 
18311963SAfshin.Ardakani@Sun.COM 	if (smb_query_by_path(sr, NULL, infolev) != 0)
18410504SKeyur.Desai@Sun.COM 		return (SDRC_ERROR);
18510504SKeyur.Desai@Sun.COM 
18610504SKeyur.Desai@Sun.COM 	return (SDRC_SUCCESS);
18710504SKeyur.Desai@Sun.COM }
18810504SKeyur.Desai@Sun.COM 
18910504SKeyur.Desai@Sun.COM /*
19010504SKeyur.Desai@Sun.COM  * smb_com_query_information2 (aka getattre)
19110504SKeyur.Desai@Sun.COM  */
19210504SKeyur.Desai@Sun.COM smb_sdrc_t
smb_pre_query_information2(smb_request_t * sr)19310504SKeyur.Desai@Sun.COM smb_pre_query_information2(smb_request_t *sr)
19410504SKeyur.Desai@Sun.COM {
19510504SKeyur.Desai@Sun.COM 	int rc;
19610504SKeyur.Desai@Sun.COM 	rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid);
19710504SKeyur.Desai@Sun.COM 
19810504SKeyur.Desai@Sun.COM 	DTRACE_SMB_1(op__QueryInformation2__start, smb_request_t *, sr);
19910504SKeyur.Desai@Sun.COM 
20010504SKeyur.Desai@Sun.COM 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
20110504SKeyur.Desai@Sun.COM }
20210504SKeyur.Desai@Sun.COM 
20310504SKeyur.Desai@Sun.COM void
smb_post_query_information2(smb_request_t * sr)20410504SKeyur.Desai@Sun.COM smb_post_query_information2(smb_request_t *sr)
20510504SKeyur.Desai@Sun.COM {
20610504SKeyur.Desai@Sun.COM 	DTRACE_SMB_1(op__QueryInformation2__done, smb_request_t *, sr);
20710504SKeyur.Desai@Sun.COM }
20810504SKeyur.Desai@Sun.COM 
20910504SKeyur.Desai@Sun.COM smb_sdrc_t
smb_com_query_information2(smb_request_t * sr)21010504SKeyur.Desai@Sun.COM smb_com_query_information2(smb_request_t *sr)
21110504SKeyur.Desai@Sun.COM {
21210504SKeyur.Desai@Sun.COM 	uint16_t infolev = SMB_QUERY_INFORMATION2;
21310504SKeyur.Desai@Sun.COM 
21410504SKeyur.Desai@Sun.COM 	if (smb_query_by_fid(sr, NULL, infolev) != 0)
21510504SKeyur.Desai@Sun.COM 		return (SDRC_ERROR);
21610504SKeyur.Desai@Sun.COM 
21710504SKeyur.Desai@Sun.COM 	return (SDRC_SUCCESS);
21810504SKeyur.Desai@Sun.COM }
21910504SKeyur.Desai@Sun.COM 
22010504SKeyur.Desai@Sun.COM /*
22110504SKeyur.Desai@Sun.COM  * smb_query_by_fid
22210504SKeyur.Desai@Sun.COM  *
22310504SKeyur.Desai@Sun.COM  * Common code for querying file information by open file (or pipe) id.
22410504SKeyur.Desai@Sun.COM  * Use the id to identify the node / pipe object and request the
22510504SKeyur.Desai@Sun.COM  * smb_queryinfo_t data for that object.
22610504SKeyur.Desai@Sun.COM  */
22710504SKeyur.Desai@Sun.COM static int
smb_query_by_fid(smb_request_t * sr,smb_xa_t * xa,uint16_t infolev)22810504SKeyur.Desai@Sun.COM smb_query_by_fid(smb_request_t *sr, smb_xa_t *xa, uint16_t infolev)
22910504SKeyur.Desai@Sun.COM {
23010504SKeyur.Desai@Sun.COM 	int		rc;
23110504SKeyur.Desai@Sun.COM 	smb_queryinfo_t	*qinfo;
23210504SKeyur.Desai@Sun.COM 	smb_node_t	*node;
23310504SKeyur.Desai@Sun.COM 	smb_opipe_t	*opipe;
23410504SKeyur.Desai@Sun.COM 
23510504SKeyur.Desai@Sun.COM 	smbsr_lookup_file(sr);
23610504SKeyur.Desai@Sun.COM 
23710504SKeyur.Desai@Sun.COM 	if (sr->fid_ofile == NULL) {
23810504SKeyur.Desai@Sun.COM 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
23910504SKeyur.Desai@Sun.COM 		return (-1);
24010504SKeyur.Desai@Sun.COM 	}
24110504SKeyur.Desai@Sun.COM 
24210504SKeyur.Desai@Sun.COM 	if (infolev == SMB_INFO_IS_NAME_VALID) {
24312508Samw@Sun.COM 		smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_LEVEL);
24410504SKeyur.Desai@Sun.COM 		smbsr_release_file(sr);
24510504SKeyur.Desai@Sun.COM 		return (-1);
24610504SKeyur.Desai@Sun.COM 	}
24710504SKeyur.Desai@Sun.COM 
24810504SKeyur.Desai@Sun.COM 	if ((sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE) &&
24910504SKeyur.Desai@Sun.COM 	    (!smb_query_pipe_valid_infolev(sr, infolev))) {
25010504SKeyur.Desai@Sun.COM 		smbsr_release_file(sr);
25110504SKeyur.Desai@Sun.COM 		return (-1);
25210504SKeyur.Desai@Sun.COM 	}
25310504SKeyur.Desai@Sun.COM 
25410504SKeyur.Desai@Sun.COM 	qinfo = kmem_alloc(sizeof (smb_queryinfo_t), KM_SLEEP);
25510504SKeyur.Desai@Sun.COM 
25610504SKeyur.Desai@Sun.COM 	switch (sr->fid_ofile->f_ftype) {
25710504SKeyur.Desai@Sun.COM 	case SMB_FTYPE_DISK:
25810504SKeyur.Desai@Sun.COM 		node = sr->fid_ofile->f_node;
25910504SKeyur.Desai@Sun.COM 		rc = smb_query_fileinfo(sr, node, infolev, qinfo);
26010504SKeyur.Desai@Sun.COM 		break;
26110504SKeyur.Desai@Sun.COM 	case SMB_FTYPE_MESG_PIPE:
26210504SKeyur.Desai@Sun.COM 		opipe = sr->fid_ofile->f_pipe;
26310504SKeyur.Desai@Sun.COM 		rc = smb_query_pipeinfo(sr, opipe, infolev, qinfo);
26410504SKeyur.Desai@Sun.COM 		break;
26510504SKeyur.Desai@Sun.COM 	default:
26610504SKeyur.Desai@Sun.COM 		smbsr_error(sr, 0, ERRDOS, ERRbadfile);
26710504SKeyur.Desai@Sun.COM 		rc = -1;
26810504SKeyur.Desai@Sun.COM 		break;
26910504SKeyur.Desai@Sun.COM 	}
27010504SKeyur.Desai@Sun.COM 
27110504SKeyur.Desai@Sun.COM 	if (rc == 0)
27210504SKeyur.Desai@Sun.COM 		rc = smb_query_encode_response(sr, xa, infolev, qinfo);
27310504SKeyur.Desai@Sun.COM 
27410504SKeyur.Desai@Sun.COM 	kmem_free(qinfo, sizeof (smb_queryinfo_t));
27510504SKeyur.Desai@Sun.COM 	smbsr_release_file(sr);
27610504SKeyur.Desai@Sun.COM 	return (rc);
27710504SKeyur.Desai@Sun.COM }
27810504SKeyur.Desai@Sun.COM 
27910504SKeyur.Desai@Sun.COM /*
28010504SKeyur.Desai@Sun.COM  * smb_query_by_path
28110504SKeyur.Desai@Sun.COM  *
28210504SKeyur.Desai@Sun.COM  * Common code for querying file information by file name.
28310504SKeyur.Desai@Sun.COM  * Use the file name to identify the node object and request the
28410504SKeyur.Desai@Sun.COM  * smb_queryinfo_t data for that node.
28510504SKeyur.Desai@Sun.COM  *
28611963SAfshin.Ardakani@Sun.COM  * Path should be set in sr->arg.dirop.fqi.fq_path prior to
28711963SAfshin.Ardakani@Sun.COM  * calling smb_query_by_path.
28811963SAfshin.Ardakani@Sun.COM  *
28910504SKeyur.Desai@Sun.COM  * Querying attributes on a named pipe by name is an error and
29010504SKeyur.Desai@Sun.COM  * is handled in the calling functions so that they can return
29110504SKeyur.Desai@Sun.COM  * the appropriate error status code (which differs by caller).
29210504SKeyur.Desai@Sun.COM  */
29310504SKeyur.Desai@Sun.COM static int
smb_query_by_path(smb_request_t * sr,smb_xa_t * xa,uint16_t infolev)29411963SAfshin.Ardakani@Sun.COM smb_query_by_path(smb_request_t *sr, smb_xa_t *xa, uint16_t infolev)
29510504SKeyur.Desai@Sun.COM {
29610504SKeyur.Desai@Sun.COM 	smb_queryinfo_t	*qinfo;
29710504SKeyur.Desai@Sun.COM 	smb_node_t	*node, *dnode;
29811963SAfshin.Ardakani@Sun.COM 	smb_pathname_t	*pn;
29910504SKeyur.Desai@Sun.COM 	int		rc;
30010504SKeyur.Desai@Sun.COM 
30110504SKeyur.Desai@Sun.COM 	/* VALID, but not yet supported */
30210504SKeyur.Desai@Sun.COM 	if (infolev == SMB_FILE_ACCESS_INFORMATION) {
30312508Samw@Sun.COM 		smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_LEVEL);
30410504SKeyur.Desai@Sun.COM 		return (-1);
30510504SKeyur.Desai@Sun.COM 	}
30610504SKeyur.Desai@Sun.COM 
30711963SAfshin.Ardakani@Sun.COM 	pn = &sr->arg.dirop.fqi.fq_path;
30811963SAfshin.Ardakani@Sun.COM 	smb_pathname_init(sr, pn, pn->pn_path);
30911963SAfshin.Ardakani@Sun.COM 	if (!smb_pathname_validate(sr, pn))
31011963SAfshin.Ardakani@Sun.COM 		return (-1);
31110504SKeyur.Desai@Sun.COM 
31210504SKeyur.Desai@Sun.COM 	qinfo = kmem_alloc(sizeof (smb_queryinfo_t), KM_SLEEP);
31310504SKeyur.Desai@Sun.COM 
31411963SAfshin.Ardakani@Sun.COM 	rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path,
31511963SAfshin.Ardakani@Sun.COM 	    sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dnode,
31611963SAfshin.Ardakani@Sun.COM 	    qinfo->qi_name);
31711963SAfshin.Ardakani@Sun.COM 
31810504SKeyur.Desai@Sun.COM 	if (rc == 0) {
31910504SKeyur.Desai@Sun.COM 		rc = smb_fsop_lookup_name(sr, sr->user_cr, SMB_FOLLOW_LINKS,
32010504SKeyur.Desai@Sun.COM 		    sr->tid_tree->t_snode, dnode, qinfo->qi_name, &node);
32110504SKeyur.Desai@Sun.COM 		smb_node_release(dnode);
32210504SKeyur.Desai@Sun.COM 	}
32310504SKeyur.Desai@Sun.COM 
32410504SKeyur.Desai@Sun.COM 	if (rc != 0) {
32510504SKeyur.Desai@Sun.COM 		if (rc == ENOENT)
32610504SKeyur.Desai@Sun.COM 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
32710504SKeyur.Desai@Sun.COM 			    ERRDOS, ERROR_FILE_NOT_FOUND);
32810504SKeyur.Desai@Sun.COM 		else
32910504SKeyur.Desai@Sun.COM 			smbsr_errno(sr, rc);
33010504SKeyur.Desai@Sun.COM 
33110504SKeyur.Desai@Sun.COM 		kmem_free(qinfo, sizeof (smb_queryinfo_t));
33210504SKeyur.Desai@Sun.COM 		return (-1);
33310504SKeyur.Desai@Sun.COM 	}
33410504SKeyur.Desai@Sun.COM 
33511963SAfshin.Ardakani@Sun.COM 	if ((sr->smb_flg2 & SMB_FLAGS2_DFS) && smb_node_is_dfslink(node)) {
33611963SAfshin.Ardakani@Sun.COM 		smbsr_error(sr, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
33711963SAfshin.Ardakani@Sun.COM 		kmem_free(qinfo, sizeof (smb_queryinfo_t));
33811963SAfshin.Ardakani@Sun.COM 		smb_node_release(node);
33911963SAfshin.Ardakani@Sun.COM 		return (-1);
34011963SAfshin.Ardakani@Sun.COM 	}
34111963SAfshin.Ardakani@Sun.COM 
34210504SKeyur.Desai@Sun.COM 	rc = smb_query_fileinfo(sr, node, infolev, qinfo);
34310504SKeyur.Desai@Sun.COM 	if (rc != 0) {
34410504SKeyur.Desai@Sun.COM 		kmem_free(qinfo, sizeof (smb_queryinfo_t));
34510504SKeyur.Desai@Sun.COM 		smb_node_release(node);
34610504SKeyur.Desai@Sun.COM 		return (rc);
34710504SKeyur.Desai@Sun.COM 	}
34810504SKeyur.Desai@Sun.COM 
34910504SKeyur.Desai@Sun.COM 	/* If delete_on_close - NT_STATUS_DELETE_PENDING */
35010504SKeyur.Desai@Sun.COM 	if (qinfo->qi_delete_on_close) {
35110504SKeyur.Desai@Sun.COM 		smbsr_error(sr, NT_STATUS_DELETE_PENDING,
35210504SKeyur.Desai@Sun.COM 		    ERRDOS, ERROR_ACCESS_DENIED);
35310504SKeyur.Desai@Sun.COM 		kmem_free(qinfo, sizeof (smb_queryinfo_t));
35410504SKeyur.Desai@Sun.COM 		smb_node_release(node);
35510504SKeyur.Desai@Sun.COM 		return (-1);
35610504SKeyur.Desai@Sun.COM 	}
35710504SKeyur.Desai@Sun.COM 
35810504SKeyur.Desai@Sun.COM 	rc = smb_query_encode_response(sr, xa, infolev, qinfo);
35910504SKeyur.Desai@Sun.COM 	kmem_free(qinfo, sizeof (smb_queryinfo_t));
36010504SKeyur.Desai@Sun.COM 	smb_node_release(node);
36110504SKeyur.Desai@Sun.COM 	return (rc);
36210504SKeyur.Desai@Sun.COM }
36310504SKeyur.Desai@Sun.COM 
36410504SKeyur.Desai@Sun.COM /*
36510504SKeyur.Desai@Sun.COM  * smb_size32
36610504SKeyur.Desai@Sun.COM  * Some responses only support 32 bit file sizes. If the file size
36710504SKeyur.Desai@Sun.COM  * exceeds UINT_MAX (32 bit) we return UINT_MAX in the response.
36810504SKeyur.Desai@Sun.COM  */
36910504SKeyur.Desai@Sun.COM static uint32_t
smb_size32(u_offset_t size)37010504SKeyur.Desai@Sun.COM smb_size32(u_offset_t size)
37110504SKeyur.Desai@Sun.COM {
37210504SKeyur.Desai@Sun.COM 	return ((size > UINT_MAX) ? UINT_MAX : (uint32_t)size);
37310504SKeyur.Desai@Sun.COM }
37410504SKeyur.Desai@Sun.COM 
37510504SKeyur.Desai@Sun.COM /*
37610504SKeyur.Desai@Sun.COM  * smb_query_encode_response
37710504SKeyur.Desai@Sun.COM  *
37810504SKeyur.Desai@Sun.COM  * Encode the data from smb_queryinfo_t into client response
37910504SKeyur.Desai@Sun.COM  */
38010504SKeyur.Desai@Sun.COM int
smb_query_encode_response(smb_request_t * sr,smb_xa_t * xa,uint16_t infolev,smb_queryinfo_t * qinfo)38110504SKeyur.Desai@Sun.COM smb_query_encode_response(smb_request_t *sr, smb_xa_t *xa,
38210504SKeyur.Desai@Sun.COM     uint16_t infolev, smb_queryinfo_t *qinfo)
38310504SKeyur.Desai@Sun.COM {
38410504SKeyur.Desai@Sun.COM 	uint16_t dattr;
38510504SKeyur.Desai@Sun.COM 	u_offset_t datasz, allocsz;
38611963SAfshin.Ardakani@Sun.COM 	uint32_t isdir;
38710504SKeyur.Desai@Sun.COM 
38810504SKeyur.Desai@Sun.COM 	dattr = qinfo->qi_attr.sa_dosattr & FILE_ATTRIBUTE_MASK;
38910504SKeyur.Desai@Sun.COM 	datasz = qinfo->qi_attr.sa_vattr.va_size;
39010504SKeyur.Desai@Sun.COM 	allocsz = qinfo->qi_attr.sa_allocsz;
39111963SAfshin.Ardakani@Sun.COM 	isdir = ((dattr & FILE_ATTRIBUTE_DIRECTORY) != 0);
39210504SKeyur.Desai@Sun.COM 
39310504SKeyur.Desai@Sun.COM 	switch (infolev) {
39410504SKeyur.Desai@Sun.COM 	case SMB_QUERY_INFORMATION:
39510504SKeyur.Desai@Sun.COM 		(void) smbsr_encode_result(sr, 10, 0, "bwll10.w",
39610504SKeyur.Desai@Sun.COM 		    10,
39710504SKeyur.Desai@Sun.COM 		    dattr,
39810504SKeyur.Desai@Sun.COM 		    smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec),
39910504SKeyur.Desai@Sun.COM 		    smb_size32(datasz),
40010504SKeyur.Desai@Sun.COM 		    0);
40110504SKeyur.Desai@Sun.COM 		break;
40210504SKeyur.Desai@Sun.COM 
40310504SKeyur.Desai@Sun.COM 	case SMB_QUERY_INFORMATION2:
40410504SKeyur.Desai@Sun.COM 		(void) smbsr_encode_result(sr, 11, 0, "byyyllww",
40510504SKeyur.Desai@Sun.COM 		    11,
40610504SKeyur.Desai@Sun.COM 		    smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec),
40710504SKeyur.Desai@Sun.COM 		    smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec),
40810504SKeyur.Desai@Sun.COM 		    smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec),
40910504SKeyur.Desai@Sun.COM 		    smb_size32(datasz), smb_size32(allocsz), dattr, 0);
41010504SKeyur.Desai@Sun.COM 	break;
41110504SKeyur.Desai@Sun.COM 
41210504SKeyur.Desai@Sun.COM 	case SMB_FILE_ACCESS_INFORMATION:
41310504SKeyur.Desai@Sun.COM 		ASSERT(sr->fid_ofile);
41410504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "l",
41510504SKeyur.Desai@Sun.COM 		    sr->fid_ofile->f_granted_access);
41610504SKeyur.Desai@Sun.COM 		break;
41710504SKeyur.Desai@Sun.COM 
41810504SKeyur.Desai@Sun.COM 	case SMB_INFO_STANDARD:
41910504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
42010504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb,
42110504SKeyur.Desai@Sun.COM 		    ((sr->session->native_os == NATIVE_OS_WIN95) ?
42210504SKeyur.Desai@Sun.COM 		    "YYYllw" : "yyyllw"),
42310504SKeyur.Desai@Sun.COM 		    smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec),
42410504SKeyur.Desai@Sun.COM 		    smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec),
42510504SKeyur.Desai@Sun.COM 		    smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec),
42610504SKeyur.Desai@Sun.COM 		    smb_size32(datasz), smb_size32(allocsz), dattr);
42710504SKeyur.Desai@Sun.COM 		break;
42810504SKeyur.Desai@Sun.COM 
42910504SKeyur.Desai@Sun.COM 	case SMB_INFO_QUERY_EA_SIZE:
43010504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
43110504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb,
43210504SKeyur.Desai@Sun.COM 		    ((sr->session->native_os == NATIVE_OS_WIN95) ?
43310504SKeyur.Desai@Sun.COM 		    "YYYllwl" : "yyyllwl"),
43410504SKeyur.Desai@Sun.COM 		    smb_time_gmt_to_local(sr, qinfo->qi_crtime.tv_sec),
43510504SKeyur.Desai@Sun.COM 		    smb_time_gmt_to_local(sr, qinfo->qi_atime.tv_sec),
43610504SKeyur.Desai@Sun.COM 		    smb_time_gmt_to_local(sr, qinfo->qi_mtime.tv_sec),
43710504SKeyur.Desai@Sun.COM 		    smb_size32(datasz), smb_size32(allocsz), dattr, 0);
43810504SKeyur.Desai@Sun.COM 		break;
43910504SKeyur.Desai@Sun.COM 
44010504SKeyur.Desai@Sun.COM 	case SMB_INFO_QUERY_ALL_EAS:
44110504SKeyur.Desai@Sun.COM 	case SMB_INFO_QUERY_EAS_FROM_LIST:
44210504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
44310504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0);
44410504SKeyur.Desai@Sun.COM 		break;
44510504SKeyur.Desai@Sun.COM 
44610504SKeyur.Desai@Sun.COM 	case SMB_INFO_IS_NAME_VALID:
44710504SKeyur.Desai@Sun.COM 		break;
44810504SKeyur.Desai@Sun.COM 
44910504SKeyur.Desai@Sun.COM 	case SMB_QUERY_FILE_BASIC_INFO:
45010504SKeyur.Desai@Sun.COM 	case SMB_FILE_BASIC_INFORMATION:
45110504SKeyur.Desai@Sun.COM 		/*
45210504SKeyur.Desai@Sun.COM 		 * NT includes 6 bytes (spec says 4) at the end of this
45310504SKeyur.Desai@Sun.COM 		 * response, which are required by NetBench 5.01.
45410504SKeyur.Desai@Sun.COM 		 */
45510504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
45610504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTw6.",
45710504SKeyur.Desai@Sun.COM 		    &qinfo->qi_crtime,
45810504SKeyur.Desai@Sun.COM 		    &qinfo->qi_atime,
45910504SKeyur.Desai@Sun.COM 		    &qinfo->qi_mtime,
46010504SKeyur.Desai@Sun.COM 		    &qinfo->qi_ctime,
46110504SKeyur.Desai@Sun.COM 		    dattr);
46210504SKeyur.Desai@Sun.COM 		break;
46310504SKeyur.Desai@Sun.COM 
46410504SKeyur.Desai@Sun.COM 	case SMB_QUERY_FILE_STANDARD_INFO:
46510504SKeyur.Desai@Sun.COM 	case SMB_FILE_STANDARD_INFORMATION:
46610504SKeyur.Desai@Sun.COM 		/* 2-byte pad at end */
46710504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
46810504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "qqlbb2.",
46910504SKeyur.Desai@Sun.COM 		    (uint64_t)allocsz,
47010504SKeyur.Desai@Sun.COM 		    (uint64_t)datasz,
47110504SKeyur.Desai@Sun.COM 		    qinfo->qi_attr.sa_vattr.va_nlink,
47210504SKeyur.Desai@Sun.COM 		    qinfo->qi_delete_on_close,
47311963SAfshin.Ardakani@Sun.COM 		    (uint8_t)isdir);
47410504SKeyur.Desai@Sun.COM 		break;
47510504SKeyur.Desai@Sun.COM 
47610504SKeyur.Desai@Sun.COM 	case SMB_QUERY_FILE_EA_INFO:
47710504SKeyur.Desai@Sun.COM 	case SMB_FILE_EA_INFORMATION:
47810504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
47910504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0);
48010504SKeyur.Desai@Sun.COM 		break;
48110504SKeyur.Desai@Sun.COM 
48210504SKeyur.Desai@Sun.COM 	case SMB_QUERY_FILE_NAME_INFO:
48310504SKeyur.Desai@Sun.COM 	case SMB_FILE_NAME_INFORMATION:
48410504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
48510504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "%lu", sr,
48610504SKeyur.Desai@Sun.COM 		    qinfo->qi_namelen, qinfo->qi_name);
48710504SKeyur.Desai@Sun.COM 		break;
48810504SKeyur.Desai@Sun.COM 
48910504SKeyur.Desai@Sun.COM 	case SMB_QUERY_FILE_ALL_INFO:
49010504SKeyur.Desai@Sun.COM 	case SMB_FILE_ALL_INFORMATION:
49110504SKeyur.Desai@Sun.COM 		/*
49210504SKeyur.Desai@Sun.COM 		 * There is a 6-byte pad between Attributes and AllocationSize,
49310504SKeyur.Desai@Sun.COM 		 * and a 2-byte pad after the Directory field.
49410504SKeyur.Desai@Sun.COM 		 */
49510504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
49610504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTw6.qqlbb2.l",
49710504SKeyur.Desai@Sun.COM 		    &qinfo->qi_crtime,
49810504SKeyur.Desai@Sun.COM 		    &qinfo->qi_atime,
49910504SKeyur.Desai@Sun.COM 		    &qinfo->qi_mtime,
50010504SKeyur.Desai@Sun.COM 		    &qinfo->qi_ctime,
50110504SKeyur.Desai@Sun.COM 		    dattr,
50210504SKeyur.Desai@Sun.COM 		    (uint64_t)allocsz,
50310504SKeyur.Desai@Sun.COM 		    (uint64_t)datasz,
50410504SKeyur.Desai@Sun.COM 		    qinfo->qi_attr.sa_vattr.va_nlink,
50510504SKeyur.Desai@Sun.COM 		    qinfo->qi_delete_on_close,
50611963SAfshin.Ardakani@Sun.COM 		    isdir,
50710504SKeyur.Desai@Sun.COM 		    0);
50810504SKeyur.Desai@Sun.COM 
50910504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "%lu",
51010504SKeyur.Desai@Sun.COM 		    sr, qinfo->qi_namelen, qinfo->qi_name);
51110504SKeyur.Desai@Sun.COM 		break;
51210504SKeyur.Desai@Sun.COM 
51310504SKeyur.Desai@Sun.COM 	case SMB_QUERY_FILE_ALT_NAME_INFO:
51410504SKeyur.Desai@Sun.COM 	case SMB_FILE_ALT_NAME_INFORMATION:
51510504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
51610504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "%lU", sr,
51710966SJordan.Brown@Sun.COM 		    smb_wcequiv_strlen(qinfo->qi_shortname),
51810504SKeyur.Desai@Sun.COM 		    qinfo->qi_shortname);
51910504SKeyur.Desai@Sun.COM 		break;
52010504SKeyur.Desai@Sun.COM 
52110504SKeyur.Desai@Sun.COM 	case SMB_QUERY_FILE_STREAM_INFO:
52210504SKeyur.Desai@Sun.COM 	case SMB_FILE_STREAM_INFORMATION:
52310504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
52410504SKeyur.Desai@Sun.COM 		smb_encode_stream_info(sr, xa, qinfo);
52510504SKeyur.Desai@Sun.COM 		break;
52610504SKeyur.Desai@Sun.COM 
52710504SKeyur.Desai@Sun.COM 	case SMB_QUERY_FILE_COMPRESSION_INFO:
52810504SKeyur.Desai@Sun.COM 	case SMB_FILE_COMPRESSION_INFORMATION:
52910504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
53010504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "qwbbb3.",
53110504SKeyur.Desai@Sun.COM 		    datasz, 0, 0, 0, 0);
53210504SKeyur.Desai@Sun.COM 		break;
53310504SKeyur.Desai@Sun.COM 
53410504SKeyur.Desai@Sun.COM 	case SMB_FILE_INTERNAL_INFORMATION:
53510504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
53610504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "q",
53710504SKeyur.Desai@Sun.COM 		    qinfo->qi_attr.sa_vattr.va_nodeid);
53810504SKeyur.Desai@Sun.COM 		break;
53910504SKeyur.Desai@Sun.COM 
54011963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_NETWORK_OPEN_INFORMATION:
54111963SAfshin.Ardakani@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
54211963SAfshin.Ardakani@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "TTTTqql4.",
54311963SAfshin.Ardakani@Sun.COM 		    &qinfo->qi_crtime,
54411963SAfshin.Ardakani@Sun.COM 		    &qinfo->qi_atime,
54511963SAfshin.Ardakani@Sun.COM 		    &qinfo->qi_mtime,
54611963SAfshin.Ardakani@Sun.COM 		    &qinfo->qi_ctime,
54711963SAfshin.Ardakani@Sun.COM 		    (uint64_t)allocsz,
54811963SAfshin.Ardakani@Sun.COM 		    (uint64_t)datasz,
54911963SAfshin.Ardakani@Sun.COM 		    (uint32_t)dattr);
55011963SAfshin.Ardakani@Sun.COM 		break;
55111963SAfshin.Ardakani@Sun.COM 
55210504SKeyur.Desai@Sun.COM 	case SMB_FILE_ATTR_TAG_INFORMATION:
55310504SKeyur.Desai@Sun.COM 		/*
55410504SKeyur.Desai@Sun.COM 		 * If dattr includes FILE_ATTRIBUTE_REPARSE_POINT, the
55510504SKeyur.Desai@Sun.COM 		 * second dword should be the reparse tag.  Otherwise
55610504SKeyur.Desai@Sun.COM 		 * the tag value should be set to zero.
55710504SKeyur.Desai@Sun.COM 		 * We don't support reparse points, so we set the tag
55810504SKeyur.Desai@Sun.COM 		 * to zero.
55910504SKeyur.Desai@Sun.COM 		 */
56010504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
56110504SKeyur.Desai@Sun.COM 		(void) smb_mbc_encodef(&xa->rep_data_mb, "ll",
56210504SKeyur.Desai@Sun.COM 		    (uint32_t)dattr, 0);
56310504SKeyur.Desai@Sun.COM 		break;
56410504SKeyur.Desai@Sun.COM 
56510504SKeyur.Desai@Sun.COM 	default:
56611963SAfshin.Ardakani@Sun.COM 		if ((infolev > 1000) && smb_query_passthru)
56711963SAfshin.Ardakani@Sun.COM 			smbsr_error(sr, NT_STATUS_NOT_SUPPORTED,
56811963SAfshin.Ardakani@Sun.COM 			    ERRDOS, ERROR_NOT_SUPPORTED);
56911963SAfshin.Ardakani@Sun.COM 		else
57012508Samw@Sun.COM 			smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_LEVEL);
57110504SKeyur.Desai@Sun.COM 		return (-1);
57210504SKeyur.Desai@Sun.COM 	}
57310504SKeyur.Desai@Sun.COM 
57410504SKeyur.Desai@Sun.COM 	return (0);
57510504SKeyur.Desai@Sun.COM }
57610504SKeyur.Desai@Sun.COM 
57710504SKeyur.Desai@Sun.COM /*
57810504SKeyur.Desai@Sun.COM  * smb_encode_stream_info
57910504SKeyur.Desai@Sun.COM  *
58010504SKeyur.Desai@Sun.COM  * This function encodes the streams information.
58110504SKeyur.Desai@Sun.COM  * The following rules about how have been derived from observed NT
58210504SKeyur.Desai@Sun.COM  * behaviour.
58310504SKeyur.Desai@Sun.COM  *
58410504SKeyur.Desai@Sun.COM  * If the target is a file:
58510504SKeyur.Desai@Sun.COM  * 1. If there are no named streams, the response should still contain
58610504SKeyur.Desai@Sun.COM  *    an entry for the unnamed stream.
58710504SKeyur.Desai@Sun.COM  * 2. If there are named streams, the response should contain an entry
58810504SKeyur.Desai@Sun.COM  *    for the unnamed stream followed by the entries for the named
58910504SKeyur.Desai@Sun.COM  *    streams.
59010504SKeyur.Desai@Sun.COM  *
59110504SKeyur.Desai@Sun.COM  * If the target is a directory:
59210504SKeyur.Desai@Sun.COM  * 1. If there are no streams, the response is complete. Directories
59310504SKeyur.Desai@Sun.COM  *    do not report the unnamed stream.
59410504SKeyur.Desai@Sun.COM  * 2. If there are streams, the response should contain entries for
59510504SKeyur.Desai@Sun.COM  *    those streams but there should not be an entry for the unnamed
59610504SKeyur.Desai@Sun.COM  *    stream.
59710504SKeyur.Desai@Sun.COM  *
59810504SKeyur.Desai@Sun.COM  * Note that the stream name lengths exclude the null terminator but
59910504SKeyur.Desai@Sun.COM  * the field lengths (i.e. next offset calculations) need to include
60010504SKeyur.Desai@Sun.COM  * the null terminator and be padded to a multiple of 8 bytes. The
60110504SKeyur.Desai@Sun.COM  * last entry does not seem to need any padding.
60210504SKeyur.Desai@Sun.COM  *
60310504SKeyur.Desai@Sun.COM  * If an error is encountered when trying to read the stream entries
60410504SKeyur.Desai@Sun.COM  * (smb_odir_read_streaminfo) it is treated as if there are no [more]
60510504SKeyur.Desai@Sun.COM  * entries. The entries that have been read so far are returned and
60610504SKeyur.Desai@Sun.COM  * no error is reported.
60710504SKeyur.Desai@Sun.COM  *
608*12890SJoyce.McIntosh@Sun.COM  * If the response buffer is not large enough to return all of the
609*12890SJoyce.McIntosh@Sun.COM  * named stream entries, the entries that do fit are returned and
610*12890SJoyce.McIntosh@Sun.COM  * a warning code is set (NT_STATUS_BUFFER_OVERFLOW). The next_offset
611*12890SJoyce.McIntosh@Sun.COM  * value in the last returned entry must be 0.
61210504SKeyur.Desai@Sun.COM  */
61310504SKeyur.Desai@Sun.COM static void
smb_encode_stream_info(smb_request_t * sr,smb_xa_t * xa,smb_queryinfo_t * qinfo)61410504SKeyur.Desai@Sun.COM smb_encode_stream_info(smb_request_t *sr, smb_xa_t *xa, smb_queryinfo_t *qinfo)
61510504SKeyur.Desai@Sun.COM {
61610504SKeyur.Desai@Sun.COM 	char *stream_name;
61710504SKeyur.Desai@Sun.COM 	uint32_t next_offset;
61810504SKeyur.Desai@Sun.COM 	uint32_t stream_nlen;
61910504SKeyur.Desai@Sun.COM 	uint32_t pad;
62010504SKeyur.Desai@Sun.COM 	u_offset_t datasz, allocsz;
62110504SKeyur.Desai@Sun.COM 	boolean_t is_dir;
62210504SKeyur.Desai@Sun.COM 	smb_streaminfo_t *sinfo, *sinfo_next;
62310504SKeyur.Desai@Sun.COM 	int rc = 0;
62410504SKeyur.Desai@Sun.COM 	boolean_t done = B_FALSE;
62510504SKeyur.Desai@Sun.COM 	boolean_t eos = B_FALSE;
62610504SKeyur.Desai@Sun.COM 	uint16_t odid;
62710504SKeyur.Desai@Sun.COM 	smb_odir_t *od = NULL;
62810504SKeyur.Desai@Sun.COM 
62910504SKeyur.Desai@Sun.COM 	smb_node_t *fnode = qinfo->qi_node;
63010504SKeyur.Desai@Sun.COM 	smb_attr_t *attr = &qinfo->qi_attr;
63110504SKeyur.Desai@Sun.COM 
63210504SKeyur.Desai@Sun.COM 	ASSERT(fnode);
63310504SKeyur.Desai@Sun.COM 	if (SMB_IS_STREAM(fnode)) {
63410504SKeyur.Desai@Sun.COM 		fnode = fnode->n_unode;
63510504SKeyur.Desai@Sun.COM 		ASSERT(fnode);
63610504SKeyur.Desai@Sun.COM 	}
63710504SKeyur.Desai@Sun.COM 	ASSERT(fnode->n_magic == SMB_NODE_MAGIC);
63810504SKeyur.Desai@Sun.COM 	ASSERT(fnode->n_state != SMB_NODE_STATE_DESTROYING);
63910504SKeyur.Desai@Sun.COM 
64010504SKeyur.Desai@Sun.COM 	sinfo = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP);
64110504SKeyur.Desai@Sun.COM 	sinfo_next = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP);
64211963SAfshin.Ardakani@Sun.COM 	is_dir = ((attr->sa_dosattr & FILE_ATTRIBUTE_DIRECTORY) != 0);
64310504SKeyur.Desai@Sun.COM 	datasz = attr->sa_vattr.va_size;
64410504SKeyur.Desai@Sun.COM 	allocsz = attr->sa_allocsz;
64510504SKeyur.Desai@Sun.COM 
64610504SKeyur.Desai@Sun.COM 	odid = smb_odir_openat(sr, fnode);
64710504SKeyur.Desai@Sun.COM 	if (odid != 0)
64810504SKeyur.Desai@Sun.COM 		od = smb_tree_lookup_odir(sr->tid_tree, odid);
64910504SKeyur.Desai@Sun.COM 	if (od != NULL)
65010504SKeyur.Desai@Sun.COM 		rc = smb_odir_read_streaminfo(sr, od, sinfo, &eos);
65110504SKeyur.Desai@Sun.COM 
65210504SKeyur.Desai@Sun.COM 	if ((od == NULL) || (rc != 0) || (eos))
65310504SKeyur.Desai@Sun.COM 		done = B_TRUE;
65410504SKeyur.Desai@Sun.COM 
65510504SKeyur.Desai@Sun.COM 	/* If not a directory, encode an entry for the unnamed stream. */
65610504SKeyur.Desai@Sun.COM 	if (!is_dir) {
65710504SKeyur.Desai@Sun.COM 		stream_name = "::$DATA";
65810504SKeyur.Desai@Sun.COM 		stream_nlen = smb_ascii_or_unicode_strlen(sr, stream_name);
659*12890SJoyce.McIntosh@Sun.COM 		next_offset = SMB_STREAM_ENCODE_FIXED_SZ + stream_nlen +
660*12890SJoyce.McIntosh@Sun.COM 		    smb_ascii_or_unicode_null_len(sr);
66110504SKeyur.Desai@Sun.COM 
662*12890SJoyce.McIntosh@Sun.COM 		/* Can unnamed stream fit in response buffer? */
663*12890SJoyce.McIntosh@Sun.COM 		if (MBC_ROOM_FOR(&xa->rep_data_mb, next_offset) == 0) {
664*12890SJoyce.McIntosh@Sun.COM 			done = B_TRUE;
665*12890SJoyce.McIntosh@Sun.COM 			smbsr_warn(sr, NT_STATUS_BUFFER_OVERFLOW,
666*12890SJoyce.McIntosh@Sun.COM 			    ERRDOS, ERROR_MORE_DATA);
667*12890SJoyce.McIntosh@Sun.COM 		} else {
668*12890SJoyce.McIntosh@Sun.COM 			/* Can first named stream fit in rsp buffer? */
669*12890SJoyce.McIntosh@Sun.COM 			if (!done && !smb_stream_fits(sr, xa, sinfo->si_name,
670*12890SJoyce.McIntosh@Sun.COM 			    next_offset)) {
671*12890SJoyce.McIntosh@Sun.COM 				done = B_TRUE;
672*12890SJoyce.McIntosh@Sun.COM 				smbsr_warn(sr, NT_STATUS_BUFFER_OVERFLOW,
673*12890SJoyce.McIntosh@Sun.COM 				    ERRDOS, ERROR_MORE_DATA);
674*12890SJoyce.McIntosh@Sun.COM 			}
67510504SKeyur.Desai@Sun.COM 
676*12890SJoyce.McIntosh@Sun.COM 			if (done)
677*12890SJoyce.McIntosh@Sun.COM 				next_offset = 0;
678*12890SJoyce.McIntosh@Sun.COM 
679*12890SJoyce.McIntosh@Sun.COM 			(void) smb_mbc_encodef(&xa->rep_data_mb, "%llqqu", sr,
680*12890SJoyce.McIntosh@Sun.COM 			    next_offset, stream_nlen, datasz, allocsz,
681*12890SJoyce.McIntosh@Sun.COM 			    stream_name);
682*12890SJoyce.McIntosh@Sun.COM 		}
68310504SKeyur.Desai@Sun.COM 	}
68410504SKeyur.Desai@Sun.COM 
68510504SKeyur.Desai@Sun.COM 	/*
686*12890SJoyce.McIntosh@Sun.COM 	 * If there is no next entry, or there is not enough space in
687*12890SJoyce.McIntosh@Sun.COM 	 * the response buffer for the next entry, the next_offset and
688*12890SJoyce.McIntosh@Sun.COM 	 * padding are 0.
68910504SKeyur.Desai@Sun.COM 	 */
69010504SKeyur.Desai@Sun.COM 	while (!done) {
69110504SKeyur.Desai@Sun.COM 		stream_nlen = smb_ascii_or_unicode_strlen(sr, sinfo->si_name);
69210504SKeyur.Desai@Sun.COM 		sinfo_next->si_name[0] = 0;
69310504SKeyur.Desai@Sun.COM 
69410504SKeyur.Desai@Sun.COM 		rc = smb_odir_read_streaminfo(sr, od, sinfo_next, &eos);
69510504SKeyur.Desai@Sun.COM 		if ((rc != 0) || (eos)) {
69610504SKeyur.Desai@Sun.COM 			done = B_TRUE;
69710504SKeyur.Desai@Sun.COM 		} else {
698*12890SJoyce.McIntosh@Sun.COM 			next_offset = SMB_STREAM_ENCODE_FIXED_SZ +
699*12890SJoyce.McIntosh@Sun.COM 			    stream_nlen +
70010504SKeyur.Desai@Sun.COM 			    smb_ascii_or_unicode_null_len(sr);
70110504SKeyur.Desai@Sun.COM 			pad = smb_pad_align(next_offset, 8);
70210504SKeyur.Desai@Sun.COM 			next_offset += pad;
703*12890SJoyce.McIntosh@Sun.COM 
704*12890SJoyce.McIntosh@Sun.COM 			/* Can next named stream fit in response buffer? */
705*12890SJoyce.McIntosh@Sun.COM 			if (!smb_stream_fits(sr, xa, sinfo_next->si_name,
706*12890SJoyce.McIntosh@Sun.COM 			    next_offset)) {
707*12890SJoyce.McIntosh@Sun.COM 				done = B_TRUE;
708*12890SJoyce.McIntosh@Sun.COM 				smbsr_warn(sr, NT_STATUS_BUFFER_OVERFLOW,
709*12890SJoyce.McIntosh@Sun.COM 				    ERRDOS, ERROR_MORE_DATA);
710*12890SJoyce.McIntosh@Sun.COM 			}
71110504SKeyur.Desai@Sun.COM 		}
712*12890SJoyce.McIntosh@Sun.COM 
713*12890SJoyce.McIntosh@Sun.COM 		if (done) {
714*12890SJoyce.McIntosh@Sun.COM 			next_offset = 0;
715*12890SJoyce.McIntosh@Sun.COM 			pad = 0;
716*12890SJoyce.McIntosh@Sun.COM 		}
717*12890SJoyce.McIntosh@Sun.COM 
718*12890SJoyce.McIntosh@Sun.COM 		rc = smb_mbc_encodef(&xa->rep_data_mb, "%llqqu#.",
71910504SKeyur.Desai@Sun.COM 		    sr, next_offset, stream_nlen,
72010504SKeyur.Desai@Sun.COM 		    sinfo->si_size, sinfo->si_alloc_size,
72110504SKeyur.Desai@Sun.COM 		    sinfo->si_name, pad);
72210504SKeyur.Desai@Sun.COM 
72310504SKeyur.Desai@Sun.COM 		(void) memcpy(sinfo, sinfo_next, sizeof (smb_streaminfo_t));
72410504SKeyur.Desai@Sun.COM 	}
72510504SKeyur.Desai@Sun.COM 
72610504SKeyur.Desai@Sun.COM 	kmem_free(sinfo, sizeof (smb_streaminfo_t));
72710504SKeyur.Desai@Sun.COM 	kmem_free(sinfo_next, sizeof (smb_streaminfo_t));
72810504SKeyur.Desai@Sun.COM 	if (od) {
72910504SKeyur.Desai@Sun.COM 		smb_odir_close(od);
73010504SKeyur.Desai@Sun.COM 		smb_odir_release(od);
73110504SKeyur.Desai@Sun.COM 	}
73210504SKeyur.Desai@Sun.COM }
73310504SKeyur.Desai@Sun.COM 
73410504SKeyur.Desai@Sun.COM /*
735*12890SJoyce.McIntosh@Sun.COM  * smb_stream_fits
736*12890SJoyce.McIntosh@Sun.COM  *
737*12890SJoyce.McIntosh@Sun.COM  * Check if the named stream entry can fit in the response buffer.
738*12890SJoyce.McIntosh@Sun.COM  *
739*12890SJoyce.McIntosh@Sun.COM  * Required space =
740*12890SJoyce.McIntosh@Sun.COM  *	offset (size of current entry)
741*12890SJoyce.McIntosh@Sun.COM  *	+ SMB_STREAM_ENCODE_FIXED_SIZE
742*12890SJoyce.McIntosh@Sun.COM  *      + length of encoded stream name
743*12890SJoyce.McIntosh@Sun.COM  *	+ length of null terminator
744*12890SJoyce.McIntosh@Sun.COM  *	+ alignment padding
745*12890SJoyce.McIntosh@Sun.COM  */
746*12890SJoyce.McIntosh@Sun.COM static boolean_t
smb_stream_fits(smb_request_t * sr,smb_xa_t * xa,char * name,uint32_t offset)747*12890SJoyce.McIntosh@Sun.COM smb_stream_fits(smb_request_t *sr, smb_xa_t *xa, char *name, uint32_t offset)
748*12890SJoyce.McIntosh@Sun.COM {
749*12890SJoyce.McIntosh@Sun.COM 	uint32_t len, pad;
750*12890SJoyce.McIntosh@Sun.COM 
751*12890SJoyce.McIntosh@Sun.COM 	len = SMB_STREAM_ENCODE_FIXED_SZ +
752*12890SJoyce.McIntosh@Sun.COM 	    smb_ascii_or_unicode_strlen(sr, name) +
753*12890SJoyce.McIntosh@Sun.COM 	    smb_ascii_or_unicode_null_len(sr);
754*12890SJoyce.McIntosh@Sun.COM 	pad = smb_pad_align(len, 8);
755*12890SJoyce.McIntosh@Sun.COM 	len += pad;
756*12890SJoyce.McIntosh@Sun.COM 
757*12890SJoyce.McIntosh@Sun.COM 	return (MBC_ROOM_FOR(&xa->rep_data_mb, offset + len) != 0);
758*12890SJoyce.McIntosh@Sun.COM }
759*12890SJoyce.McIntosh@Sun.COM 
760*12890SJoyce.McIntosh@Sun.COM /*
76110504SKeyur.Desai@Sun.COM  * smb_query_fileinfo
76210504SKeyur.Desai@Sun.COM  *
76310504SKeyur.Desai@Sun.COM  * Populate smb_queryinfo_t structure for SMB_FTYPE_DISK
76410504SKeyur.Desai@Sun.COM  * (This should become an smb_ofile / smb_node function.)
76510504SKeyur.Desai@Sun.COM  */
76610504SKeyur.Desai@Sun.COM int
smb_query_fileinfo(smb_request_t * sr,smb_node_t * node,uint16_t infolev,smb_queryinfo_t * qinfo)76710504SKeyur.Desai@Sun.COM smb_query_fileinfo(smb_request_t *sr, smb_node_t *node, uint16_t infolev,
76810504SKeyur.Desai@Sun.COM     smb_queryinfo_t *qinfo)
76910504SKeyur.Desai@Sun.COM {
77012508Samw@Sun.COM 	int rc = 0;
77110504SKeyur.Desai@Sun.COM 
772*12890SJoyce.McIntosh@Sun.COM 	/* If shortname required but not supported -> OBJECT_NAME_NOT_FOUND */
773*12890SJoyce.McIntosh@Sun.COM 	if ((infolev == SMB_QUERY_FILE_ALT_NAME_INFO) ||
774*12890SJoyce.McIntosh@Sun.COM 	    (infolev == SMB_FILE_ALT_NAME_INFORMATION)) {
775*12890SJoyce.McIntosh@Sun.COM 		if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_SHORTNAMES)) {
776*12890SJoyce.McIntosh@Sun.COM 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
777*12890SJoyce.McIntosh@Sun.COM 			    ERRDOS, ERROR_FILE_NOT_FOUND);
778*12890SJoyce.McIntosh@Sun.COM 			return (-1);
779*12890SJoyce.McIntosh@Sun.COM 		}
780*12890SJoyce.McIntosh@Sun.COM 	}
781*12890SJoyce.McIntosh@Sun.COM 
78210504SKeyur.Desai@Sun.COM 	(void) bzero(qinfo, sizeof (smb_queryinfo_t));
78310504SKeyur.Desai@Sun.COM 
78410504SKeyur.Desai@Sun.COM 	if (smb_node_getattr(sr, node, &qinfo->qi_attr) != 0) {
78510504SKeyur.Desai@Sun.COM 		smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
78610504SKeyur.Desai@Sun.COM 		    ERRDOS, ERROR_INTERNAL_ERROR);
78710504SKeyur.Desai@Sun.COM 		return (-1);
78810504SKeyur.Desai@Sun.COM 	}
78910504SKeyur.Desai@Sun.COM 
79010504SKeyur.Desai@Sun.COM 	qinfo->qi_node = node;
79110504SKeyur.Desai@Sun.COM 	qinfo->qi_delete_on_close =
79210504SKeyur.Desai@Sun.COM 	    (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) != 0;
79310504SKeyur.Desai@Sun.COM 
79410504SKeyur.Desai@Sun.COM 	/*
79510504SKeyur.Desai@Sun.COM 	 * The number of links reported should be the number of
79610504SKeyur.Desai@Sun.COM 	 * non-deleted links. Thus if delete_on_close is set,
79710504SKeyur.Desai@Sun.COM 	 * decrement the link count.
79810504SKeyur.Desai@Sun.COM 	 */
79910504SKeyur.Desai@Sun.COM 	if (qinfo->qi_delete_on_close &&
80010504SKeyur.Desai@Sun.COM 	    qinfo->qi_attr.sa_vattr.va_nlink > 0) {
80110504SKeyur.Desai@Sun.COM 		--(qinfo->qi_attr.sa_vattr.va_nlink);
80210504SKeyur.Desai@Sun.COM 	}
80310504SKeyur.Desai@Sun.COM 
80412508Samw@Sun.COM 	/*
80512508Samw@Sun.COM 	 * populate name, namelen and shortname ONLY for the information
80612508Samw@Sun.COM 	 * levels that require these fields
80712508Samw@Sun.COM 	 */
80812508Samw@Sun.COM 	switch (infolev) {
80912508Samw@Sun.COM 	case SMB_QUERY_FILE_ALL_INFO:
81012508Samw@Sun.COM 	case SMB_FILE_ALL_INFORMATION:
81112508Samw@Sun.COM 		rc = smb_query_pathname(sr, node, B_TRUE, qinfo);
81212508Samw@Sun.COM 		break;
81312508Samw@Sun.COM 	case SMB_QUERY_FILE_NAME_INFO:
81412508Samw@Sun.COM 	case SMB_FILE_NAME_INFORMATION:
81512508Samw@Sun.COM 		rc = smb_query_pathname(sr, node, B_FALSE, qinfo);
81612508Samw@Sun.COM 		break;
81712508Samw@Sun.COM 	case SMB_QUERY_FILE_ALT_NAME_INFO:
81812508Samw@Sun.COM 	case SMB_FILE_ALT_NAME_INFORMATION:
81912508Samw@Sun.COM 		smb_query_shortname(node, qinfo);
82012508Samw@Sun.COM 		break;
82112508Samw@Sun.COM 	default:
82212508Samw@Sun.COM 		break;
82310504SKeyur.Desai@Sun.COM 	}
82410504SKeyur.Desai@Sun.COM 
82510966SJordan.Brown@Sun.COM 	if (rc != 0) {
82610966SJordan.Brown@Sun.COM 		smbsr_errno(sr, rc);
82710966SJordan.Brown@Sun.COM 		return (-1);
82810966SJordan.Brown@Sun.COM 	}
82912508Samw@Sun.COM 	return (0);
83012508Samw@Sun.COM }
83110504SKeyur.Desai@Sun.COM 
83212508Samw@Sun.COM /*
83312508Samw@Sun.COM  * smb_query_pathname
83412508Samw@Sun.COM  *
83512508Samw@Sun.COM  * Determine the absolute pathname of 'node' within the share.
83612508Samw@Sun.COM  * For some levels (e.g. ALL_INFO) the pathname should include the
83712508Samw@Sun.COM  * sharename for others (e.g. NAME_INFO) the pathname should be
83812508Samw@Sun.COM  * relative to the share.
83912508Samw@Sun.COM  * For example if the node represents file "test1.txt" in directory
84012508Samw@Sun.COM  * "dir1" on share "share1"
84112508Samw@Sun.COM  * - if include_share is TRUE the pathname would be: \share1\dir1\test1.txt
84212508Samw@Sun.COM  * - if include_share is FALSE the pathname would be: \dir1\test1.txt
84312508Samw@Sun.COM  *
84412508Samw@Sun.COM  * For some reason NT will not show the security tab in the root
84512508Samw@Sun.COM  * directory of a mapped drive unless the filename length is greater
84612508Samw@Sun.COM  * than one. So if the length is 1 we set it to 2 to persuade NT to
84712508Samw@Sun.COM  * show the tab. It should be safe because of the null terminator.
84812508Samw@Sun.COM  */
84912508Samw@Sun.COM static int
smb_query_pathname(smb_request_t * sr,smb_node_t * node,boolean_t include_share,smb_queryinfo_t * qinfo)85012508Samw@Sun.COM smb_query_pathname(smb_request_t *sr, smb_node_t *node, boolean_t include_share,
85112508Samw@Sun.COM     smb_queryinfo_t *qinfo)
85212508Samw@Sun.COM {
85312508Samw@Sun.COM 	smb_tree_t *tree = sr->tid_tree;
85412508Samw@Sun.COM 	char *buf = qinfo->qi_name;
85512508Samw@Sun.COM 	size_t buflen = MAXPATHLEN;
85612508Samw@Sun.COM 	size_t len;
85712508Samw@Sun.COM 	int rc;
85812508Samw@Sun.COM 
85912508Samw@Sun.COM 	if (include_share) {
86012508Samw@Sun.COM 		len = snprintf(buf, buflen, "\\%s", tree->t_sharename);
86112508Samw@Sun.COM 		if (len == (buflen - 1))
86212508Samw@Sun.COM 			return (ENAMETOOLONG);
86310504SKeyur.Desai@Sun.COM 
86412508Samw@Sun.COM 		buf += len;
86512508Samw@Sun.COM 		buflen -= len;
86612508Samw@Sun.COM 	}
86712508Samw@Sun.COM 
86812508Samw@Sun.COM 	if (node == tree->t_snode) {
86912508Samw@Sun.COM 		if (!include_share)
87012508Samw@Sun.COM 			(void) strlcpy(buf, "\\", buflen);
87112508Samw@Sun.COM 		return (0);
87212508Samw@Sun.COM 	}
87310504SKeyur.Desai@Sun.COM 
87412508Samw@Sun.COM 	rc =  smb_node_getshrpath(node, tree, buf, buflen);
87512508Samw@Sun.COM 	if (rc == 0) {
87612508Samw@Sun.COM 		qinfo->qi_namelen =
87712508Samw@Sun.COM 		    smb_ascii_or_unicode_strlen(sr, qinfo->qi_name);
87812508Samw@Sun.COM 		if (qinfo->qi_namelen == 1)
87912508Samw@Sun.COM 			qinfo->qi_namelen = 2;
88012508Samw@Sun.COM 	}
88112508Samw@Sun.COM 	return (rc);
88212508Samw@Sun.COM }
88312508Samw@Sun.COM 
88412508Samw@Sun.COM /*
88512508Samw@Sun.COM  * smb_query_shortname
88612508Samw@Sun.COM  *
88712508Samw@Sun.COM  * If the node is a named stream, use its associated
88812508Samw@Sun.COM  * unnamed stream name to determine the shortname.
88912508Samw@Sun.COM  * If a shortname is required (smb_needs_mangle()), generate it
89012508Samw@Sun.COM  * using smb_mangle(), otherwise, convert the original name to
89112508Samw@Sun.COM  * upper-case and return it as the alternative name.
89212508Samw@Sun.COM  */
89312508Samw@Sun.COM static void
smb_query_shortname(smb_node_t * node,smb_queryinfo_t * qinfo)89412508Samw@Sun.COM smb_query_shortname(smb_node_t *node, smb_queryinfo_t *qinfo)
89512508Samw@Sun.COM {
89612508Samw@Sun.COM 	char *namep;
89712508Samw@Sun.COM 
89811963SAfshin.Ardakani@Sun.COM 	if (SMB_IS_STREAM(node))
89911963SAfshin.Ardakani@Sun.COM 		namep = node->n_unode->od_name;
90011963SAfshin.Ardakani@Sun.COM 	else
90111963SAfshin.Ardakani@Sun.COM 		namep = node->od_name;
90211963SAfshin.Ardakani@Sun.COM 
90312508Samw@Sun.COM 	if (smb_needs_mangled(namep)) {
90412508Samw@Sun.COM 		smb_mangle(namep, qinfo->qi_attr.sa_vattr.va_nodeid,
90512508Samw@Sun.COM 		    qinfo->qi_shortname, SMB_SHORTNAMELEN);
90612508Samw@Sun.COM 	} else {
907*12890SJoyce.McIntosh@Sun.COM 		(void) strlcpy(qinfo->qi_shortname, namep, SMB_SHORTNAMELEN);
90810966SJordan.Brown@Sun.COM 		(void) smb_strupr(qinfo->qi_shortname);
90910504SKeyur.Desai@Sun.COM 	}
91010504SKeyur.Desai@Sun.COM }
91110504SKeyur.Desai@Sun.COM 
91210504SKeyur.Desai@Sun.COM /*
91310504SKeyur.Desai@Sun.COM  * smb_query_pipeinfo
91410504SKeyur.Desai@Sun.COM  *
91510504SKeyur.Desai@Sun.COM  * Populate smb_queryinfo_t structure for SMB_FTYPE_MESG_PIPE
91610504SKeyur.Desai@Sun.COM  * (This should become an smb_opipe function.)
91710504SKeyur.Desai@Sun.COM  */
91810504SKeyur.Desai@Sun.COM static int
smb_query_pipeinfo(smb_request_t * sr,smb_opipe_t * opipe,uint16_t infolev,smb_queryinfo_t * qinfo)91910504SKeyur.Desai@Sun.COM smb_query_pipeinfo(smb_request_t *sr, smb_opipe_t *opipe, uint16_t infolev,
92010504SKeyur.Desai@Sun.COM     smb_queryinfo_t *qinfo)
92110504SKeyur.Desai@Sun.COM {
92210504SKeyur.Desai@Sun.COM 	char *namep = opipe->p_name;
92310504SKeyur.Desai@Sun.COM 
92410504SKeyur.Desai@Sun.COM 	(void) bzero(qinfo, sizeof (smb_queryinfo_t));
92510504SKeyur.Desai@Sun.COM 	qinfo->qi_node = NULL;
92610504SKeyur.Desai@Sun.COM 	qinfo->qi_attr.sa_vattr.va_nlink = 1;
92710504SKeyur.Desai@Sun.COM 	qinfo->qi_delete_on_close = 1;
92810504SKeyur.Desai@Sun.COM 
92910504SKeyur.Desai@Sun.COM 	if ((infolev == SMB_INFO_STANDARD) ||
93010504SKeyur.Desai@Sun.COM 	    (infolev == SMB_INFO_QUERY_EA_SIZE) ||
93110504SKeyur.Desai@Sun.COM 	    (infolev == SMB_QUERY_INFORMATION2)) {
93210504SKeyur.Desai@Sun.COM 		qinfo->qi_attr.sa_dosattr = 0;
93310504SKeyur.Desai@Sun.COM 	} else {
93410504SKeyur.Desai@Sun.COM 		qinfo->qi_attr.sa_dosattr = FILE_ATTRIBUTE_NORMAL;
93510504SKeyur.Desai@Sun.COM 	}
93610504SKeyur.Desai@Sun.COM 
93710504SKeyur.Desai@Sun.COM 	/* If the leading \ is missing from the pipe name, add it. */
93810504SKeyur.Desai@Sun.COM 	if (*namep != '\\')
93910504SKeyur.Desai@Sun.COM 		(void) snprintf(qinfo->qi_name, MAXNAMELEN, "\\%s", namep);
94010504SKeyur.Desai@Sun.COM 	else
94110504SKeyur.Desai@Sun.COM 		(void) strlcpy(qinfo->qi_name, namep, MAXNAMELEN);
94210504SKeyur.Desai@Sun.COM 
94310504SKeyur.Desai@Sun.COM 	qinfo->qi_namelen=
94410504SKeyur.Desai@Sun.COM 	    smb_ascii_or_unicode_strlen(sr, qinfo->qi_name);
94510504SKeyur.Desai@Sun.COM 
94610504SKeyur.Desai@Sun.COM 	return (0);
94710504SKeyur.Desai@Sun.COM }
94810504SKeyur.Desai@Sun.COM 
94910504SKeyur.Desai@Sun.COM /*
95010504SKeyur.Desai@Sun.COM  * smb_query_pipe_valid_infolev
95110504SKeyur.Desai@Sun.COM  *
95210504SKeyur.Desai@Sun.COM  * If the infolev is not valid for a message pipe, the error
95310504SKeyur.Desai@Sun.COM  * information is set in sr and B_FALSE is returned.
95410504SKeyur.Desai@Sun.COM  * Otherwise, returns B_TRUE.
95510504SKeyur.Desai@Sun.COM  */
95610504SKeyur.Desai@Sun.COM static boolean_t
smb_query_pipe_valid_infolev(smb_request_t * sr,uint16_t infolev)95710504SKeyur.Desai@Sun.COM smb_query_pipe_valid_infolev(smb_request_t *sr, uint16_t infolev)
95810504SKeyur.Desai@Sun.COM {
95910504SKeyur.Desai@Sun.COM 	switch (infolev) {
96010504SKeyur.Desai@Sun.COM 	case SMB_INFO_QUERY_ALL_EAS:
96110504SKeyur.Desai@Sun.COM 		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
96210504SKeyur.Desai@Sun.COM 		    ERRDOS, ERROR_ACCESS_DENIED);
96310504SKeyur.Desai@Sun.COM 		return (B_FALSE);
96410504SKeyur.Desai@Sun.COM 
96510504SKeyur.Desai@Sun.COM 	case SMB_QUERY_FILE_ALT_NAME_INFO:
96610504SKeyur.Desai@Sun.COM 	case SMB_FILE_ALT_NAME_INFORMATION:
96710504SKeyur.Desai@Sun.COM 	case SMB_QUERY_FILE_STREAM_INFO:
96810504SKeyur.Desai@Sun.COM 	case SMB_FILE_STREAM_INFORMATION:
96910504SKeyur.Desai@Sun.COM 	case SMB_QUERY_FILE_COMPRESSION_INFO:
97010504SKeyur.Desai@Sun.COM 	case SMB_FILE_COMPRESSION_INFORMATION:
97111963SAfshin.Ardakani@Sun.COM 	case SMB_FILE_NETWORK_OPEN_INFORMATION:
97210504SKeyur.Desai@Sun.COM 	case SMB_FILE_ATTR_TAG_INFORMATION:
97310504SKeyur.Desai@Sun.COM 		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
97410504SKeyur.Desai@Sun.COM 		    ERRDOS, ERROR_INVALID_PARAMETER);
97510504SKeyur.Desai@Sun.COM 		return (B_FALSE);
97610504SKeyur.Desai@Sun.COM 	}
97710504SKeyur.Desai@Sun.COM 
97810504SKeyur.Desai@Sun.COM 	return (B_TRUE);
97910504SKeyur.Desai@Sun.COM }
980