xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb2_query_info.c (revision c65ebfc7045424bd04a6c7719a27b0ad3399ad54)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
14  */
15 
16 /*
17  * Dispatch function for SMB2_QUERY_INFO
18  */
19 
20 #include <smbsrv/smb2_kproto.h>
21 #include <smbsrv/smb_fsops.h>
22 #include <smbsrv/ntifs.h>
23 
24 smb_sdrc_t
25 smb2_query_info(smb_request_t *sr)
26 {
27 	smb_queryinfo_t *qi;
28 	uint16_t StructSize;
29 	uint32_t oBufLength;
30 	uint16_t iBufOffset;
31 	uint32_t iBufLength;
32 	smb2fid_t smb2fid;
33 	uint16_t DataOff;
34 	uint32_t status;
35 	smb_sdrc_t sdrc = SDRC_SUCCESS;
36 	int rc = 0;
37 
38 	qi = kmem_zalloc(sizeof (*qi), KM_SLEEP);
39 
40 	/*
41 	 * SMB2 Query Info request
42 	 */
43 	rc = smb_mbc_decodef(
44 	    &sr->smb_data, "wbblw..lllqq",
45 	    &StructSize,		/* w */
46 	    &qi->qi_InfoType,		/* b */
47 	    &qi->qi_InfoClass,		/* b */
48 	    &oBufLength,		/* l */
49 	    &iBufOffset,		/* w */
50 	    /* reserved			  .. */
51 	    &iBufLength,		/* l */
52 	    &qi->qi_AddlInfo,		/* l */
53 	    &qi->qi_Flags,		/* l */
54 	    &smb2fid.persistent,	/* q */
55 	    &smb2fid.temporal);		/* q */
56 	if (rc || StructSize != 41) {
57 		sdrc = SDRC_ERROR;
58 		goto out;
59 	}
60 
61 	status = smb2sr_lookup_fid(sr, &smb2fid);
62 	if (status) {
63 		smb2sr_put_error(sr, status);
64 		goto out;
65 	}
66 
67 	if (oBufLength > smb2_max_trans)
68 		oBufLength = smb2_max_trans;
69 
70 	/*
71 	 * If there's an input buffer, setup a shadow.
72 	 */
73 	if (iBufLength) {
74 		rc = MBC_SHADOW_CHAIN(&qi->in_data, &sr->smb_data,
75 		    sr->smb2_cmd_hdr + iBufOffset, iBufLength);
76 		if (rc) {
77 			smb2sr_put_error(sr, NT_STATUS_INVALID_PARAMETER);
78 			goto out;
79 		}
80 	}
81 
82 	sr->raw_data.max_bytes = oBufLength;
83 
84 	switch (qi->qi_InfoType) {
85 	case SMB2_0_INFO_FILE:
86 		status = smb2_qinfo_file(sr, qi);
87 		break;
88 	case SMB2_0_INFO_FILESYSTEM:
89 		status = smb2_qinfo_fs(sr, qi);
90 		break;
91 	case SMB2_0_INFO_SECURITY:
92 		status = smb2_qinfo_sec(sr, qi);
93 		break;
94 	case SMB2_0_INFO_QUOTA:
95 		status = smb2_qinfo_quota(sr, qi);
96 		break;
97 	default:
98 		status = NT_STATUS_INVALID_PARAMETER;
99 		break;
100 	}
101 
102 	switch (status) {
103 
104 	case 0: /* success */
105 		break;
106 
107 	case NT_STATUS_BUFFER_OVERFLOW:
108 		/* Not really an error, per se.  Advisory. */
109 		sr->smb2_status = status;
110 		break;
111 
112 	case NT_STATUS_BUFFER_TOO_SMALL:
113 	case NT_STATUS_INFO_LENGTH_MISMATCH:
114 		/*
115 		 * These are special, per. [MS-SMB2] 3.2.5.17
116 		 * The error data is a 4-byte count of the size
117 		 * required to successfully query the data.
118 		 * That error data is built by the functions
119 		 * that returns one of these errors.
120 		 */
121 		smb2sr_put_error_data(sr, status, &sr->raw_data);
122 		goto out;
123 
124 	default:
125 		smb2sr_put_error(sr, status);
126 		goto out;
127 	}
128 
129 	/*
130 	 * SMB2 Query Info reply
131 	 */
132 	DataOff = SMB2_HDR_SIZE + 8;
133 	oBufLength = MBC_LENGTH(&sr->raw_data);
134 	rc = smb_mbc_encodef(
135 	    &sr->reply, "wwlC",
136 	    9,	/* StructSize */	/* w */
137 	    DataOff,			/* w */
138 	    oBufLength,			/* l */
139 	    &sr->raw_data);		/* C */
140 	if (rc)
141 		sdrc = SDRC_ERROR;
142 
143 out:
144 	kmem_free(qi, sizeof (*qi));
145 
146 	return (sdrc);
147 }
148