• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src/router/samba-3.5.8/source4/libcli/raw/
1/*
2   Unix SMB/CIFS implementation.
3
4   RAW_QFS_* operations
5
6   Copyright (C) Andrew Tridgell 2003
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "includes.h"
23#include "libcli/raw/libcliraw.h"
24#include "libcli/raw/raw_proto.h"
25#include "librpc/gen_ndr/ndr_misc.h"
26
27/****************************************************************************
28 Query FS Info - SMBdskattr call (async send)
29****************************************************************************/
30static struct smbcli_request *smb_raw_dskattr_send(struct smbcli_tree *tree,
31						union smb_fsinfo *fsinfo)
32{
33	struct smbcli_request *req;
34
35	req = smbcli_request_setup(tree, SMBdskattr, 0, 0);
36
37	if (!smbcli_request_send(req)) {
38		smbcli_request_destroy(req);
39		return NULL;
40	}
41
42	return req;
43}
44
45/****************************************************************************
46 Query FS Info - SMBdskattr call (async recv)
47****************************************************************************/
48static NTSTATUS smb_raw_dskattr_recv(struct smbcli_request *req,
49				     union smb_fsinfo *fsinfo)
50{
51	if (!smbcli_request_receive(req) ||
52	    smbcli_request_is_error(req)) {
53		goto failed;
54	}
55
56	SMBCLI_CHECK_WCT(req, 5);
57	fsinfo->dskattr.out.units_total =     SVAL(req->in.vwv, VWV(0));
58	fsinfo->dskattr.out.blocks_per_unit = SVAL(req->in.vwv, VWV(1));
59	fsinfo->dskattr.out.block_size =      SVAL(req->in.vwv, VWV(2));
60	fsinfo->dskattr.out.units_free =      SVAL(req->in.vwv, VWV(3));
61
62failed:
63	return smbcli_request_destroy(req);
64}
65
66
67/****************************************************************************
68 RAW_QFS_ trans2 interface via blobs (async send)
69****************************************************************************/
70static struct smbcli_request *smb_raw_qfsinfo_send(struct smbcli_tree *tree,
71						TALLOC_CTX *mem_ctx,
72						uint16_t info_level)
73{
74	struct smb_trans2 tp;
75	uint16_t setup = TRANSACT2_QFSINFO;
76
77	tp.in.max_setup = 0;
78	tp.in.flags = 0;
79	tp.in.timeout = 0;
80	tp.in.setup_count = 1;
81	tp.in.max_param = 0;
82	tp.in.max_data = 0xFFFF;
83	tp.in.setup = &setup;
84	tp.in.data = data_blob(NULL, 0);
85	tp.in.timeout = 0;
86
87	tp.in.params = data_blob_talloc(mem_ctx, NULL, 2);
88	if (!tp.in.params.data) {
89		return NULL;
90	}
91	SSVAL(tp.in.params.data, 0, info_level);
92
93	return smb_raw_trans2_send(tree, &tp);
94}
95
96/****************************************************************************
97 RAW_QFS_ trans2 interface via blobs (async recv)
98****************************************************************************/
99static NTSTATUS smb_raw_qfsinfo_blob_recv(struct smbcli_request *req,
100					  TALLOC_CTX *mem_ctx,
101					  DATA_BLOB *blob)
102{
103	struct smb_trans2 tp;
104	NTSTATUS status;
105
106	status = smb_raw_trans2_recv(req, mem_ctx, &tp);
107
108	if (NT_STATUS_IS_OK(status)) {
109		(*blob) = tp.out.data;
110	}
111
112	return status;
113}
114
115
116/* local macros to make the code more readable */
117#define QFS_CHECK_MIN_SIZE(size) if (blob.length < (size)) { \
118      DEBUG(1,("Unexpected QFS reply size %d for level %u - expected min of %d\n", \
119	       (int)blob.length, fsinfo->generic.level, (size))); \
120      status = NT_STATUS_INFO_LENGTH_MISMATCH; \
121      goto failed; \
122}
123#define QFS_CHECK_SIZE(size) if (blob.length != (size)) { \
124      DEBUG(1,("Unexpected QFS reply size %d for level %u - expected %d\n", \
125	       (int)blob.length, fsinfo->generic.level, (size))); \
126      status = NT_STATUS_INFO_LENGTH_MISMATCH; \
127      goto failed; \
128}
129
130
131/****************************************************************************
132 Query FSInfo raw interface (async send)
133****************************************************************************/
134struct smbcli_request *smb_raw_fsinfo_send(struct smbcli_tree *tree,
135					TALLOC_CTX *mem_ctx,
136					union smb_fsinfo *fsinfo)
137{
138	uint16_t info_level;
139
140	/* handle the only non-trans2 call separately */
141	if (fsinfo->generic.level == RAW_QFS_DSKATTR) {
142		return smb_raw_dskattr_send(tree, fsinfo);
143	}
144	if (fsinfo->generic.level >= RAW_QFS_GENERIC) {
145		return NULL;
146	}
147
148	/* the headers map the trans2 levels direct to info levels */
149	info_level = (uint16_t)fsinfo->generic.level;
150
151	return smb_raw_qfsinfo_send(tree, mem_ctx, info_level);
152}
153
154/*
155  parse the fsinfo 'passthru' level replies
156*/
157NTSTATUS smb_raw_fsinfo_passthru_parse(DATA_BLOB blob, TALLOC_CTX *mem_ctx,
158				       enum smb_fsinfo_level level,
159				       union smb_fsinfo *fsinfo)
160{
161	NTSTATUS status = NT_STATUS_OK;
162	enum ndr_err_code ndr_err;
163	int i;
164
165	/* parse the results */
166	switch (level) {
167	case RAW_QFS_VOLUME_INFORMATION:
168		QFS_CHECK_MIN_SIZE(18);
169		fsinfo->volume_info.out.create_time   = smbcli_pull_nttime(blob.data, 0);
170		fsinfo->volume_info.out.serial_number = IVAL(blob.data, 8);
171		smbcli_blob_pull_string(NULL, mem_ctx, &blob,
172					&fsinfo->volume_info.out.volume_name,
173					12, 18, STR_UNICODE);
174		break;
175
176	case RAW_QFS_SIZE_INFORMATION:
177		QFS_CHECK_SIZE(24);
178		fsinfo->size_info.out.total_alloc_units = BVAL(blob.data,  0);
179		fsinfo->size_info.out.avail_alloc_units = BVAL(blob.data,  8);
180		fsinfo->size_info.out.sectors_per_unit =  IVAL(blob.data, 16);
181		fsinfo->size_info.out.bytes_per_sector =  IVAL(blob.data, 20);
182		break;
183
184	case RAW_QFS_DEVICE_INFORMATION:
185		QFS_CHECK_SIZE(8);
186		fsinfo->device_info.out.device_type     = IVAL(blob.data,  0);
187		fsinfo->device_info.out.characteristics = IVAL(blob.data,  4);
188		break;
189
190	case RAW_QFS_ATTRIBUTE_INFORMATION:
191		QFS_CHECK_MIN_SIZE(12);
192		fsinfo->attribute_info.out.fs_attr   =                 IVAL(blob.data, 0);
193		fsinfo->attribute_info.out.max_file_component_length = IVAL(blob.data, 4);
194		smbcli_blob_pull_string(NULL, mem_ctx, &blob,
195					&fsinfo->attribute_info.out.fs_type,
196					8, 12, STR_UNICODE);
197		break;
198
199	case RAW_QFS_QUOTA_INFORMATION:
200		QFS_CHECK_SIZE(48);
201		fsinfo->quota_information.out.unknown[0] =  BVAL(blob.data,  0);
202		fsinfo->quota_information.out.unknown[1] =  BVAL(blob.data,  8);
203		fsinfo->quota_information.out.unknown[2] =  BVAL(blob.data, 16);
204		fsinfo->quota_information.out.quota_soft =  BVAL(blob.data, 24);
205		fsinfo->quota_information.out.quota_hard =  BVAL(blob.data, 32);
206		fsinfo->quota_information.out.quota_flags = BVAL(blob.data, 40);
207		break;
208
209	case RAW_QFS_FULL_SIZE_INFORMATION:
210		QFS_CHECK_SIZE(32);
211		fsinfo->full_size_information.out.total_alloc_units =        BVAL(blob.data,  0);
212		fsinfo->full_size_information.out.call_avail_alloc_units =   BVAL(blob.data,  8);
213		fsinfo->full_size_information.out.actual_avail_alloc_units = BVAL(blob.data, 16);
214		fsinfo->full_size_information.out.sectors_per_unit =         IVAL(blob.data, 24);
215		fsinfo->full_size_information.out.bytes_per_sector =         IVAL(blob.data, 28);
216		break;
217
218	case RAW_QFS_OBJECTID_INFORMATION:
219		QFS_CHECK_SIZE(64);
220		ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &fsinfo->objectid_information.out.guid,
221					       (ndr_pull_flags_fn_t)ndr_pull_GUID);
222		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
223			status = ndr_map_error2ntstatus(ndr_err);
224		}
225		for (i=0;i<6;i++) {
226			fsinfo->objectid_information.out.unknown[i] = BVAL(blob.data, 16 + i*8);
227		}
228		break;
229
230	default:
231		status = NT_STATUS_INVALID_INFO_CLASS;
232	}
233
234failed:
235	return status;
236}
237
238
239/****************************************************************************
240 Query FSInfo raw interface (async recv)
241****************************************************************************/
242NTSTATUS smb_raw_fsinfo_recv(struct smbcli_request *req,
243			     TALLOC_CTX *mem_ctx,
244			     union smb_fsinfo *fsinfo)
245{
246	DATA_BLOB blob;
247	NTSTATUS status;
248	struct smbcli_session *session = req?req->session:NULL;
249
250	if (fsinfo->generic.level == RAW_QFS_DSKATTR) {
251		return smb_raw_dskattr_recv(req, fsinfo);
252	}
253
254	status = smb_raw_qfsinfo_blob_recv(req, mem_ctx, &blob);
255	if (!NT_STATUS_IS_OK(status)) {
256		return status;
257	}
258
259	/* parse the results */
260	switch (fsinfo->generic.level) {
261	case RAW_QFS_GENERIC:
262	case RAW_QFS_DSKATTR:
263		/* handled above */
264		break;
265
266	case RAW_QFS_ALLOCATION:
267		QFS_CHECK_SIZE(18);
268		fsinfo->allocation.out.fs_id =             IVAL(blob.data,  0);
269		fsinfo->allocation.out.sectors_per_unit =  IVAL(blob.data,  4);
270		fsinfo->allocation.out.total_alloc_units = IVAL(blob.data,  8);
271		fsinfo->allocation.out.avail_alloc_units = IVAL(blob.data, 12);
272		fsinfo->allocation.out.bytes_per_sector =  SVAL(blob.data, 16);
273		break;
274
275	case RAW_QFS_VOLUME:
276		QFS_CHECK_MIN_SIZE(5);
277		fsinfo->volume.out.serial_number = IVAL(blob.data, 0);
278		smbcli_blob_pull_string(session, mem_ctx, &blob,
279				     &fsinfo->volume.out.volume_name,
280				     4, 5, STR_LEN8BIT | STR_NOALIGN);
281		break;
282
283	case RAW_QFS_VOLUME_INFO:
284	case RAW_QFS_VOLUME_INFORMATION:
285		return smb_raw_fsinfo_passthru_parse(blob, mem_ctx,
286						     RAW_QFS_VOLUME_INFORMATION, fsinfo);
287
288	case RAW_QFS_SIZE_INFO:
289	case RAW_QFS_SIZE_INFORMATION:
290		return smb_raw_fsinfo_passthru_parse(blob, mem_ctx,
291						     RAW_QFS_SIZE_INFORMATION, fsinfo);
292
293	case RAW_QFS_DEVICE_INFO:
294	case RAW_QFS_DEVICE_INFORMATION:
295		return smb_raw_fsinfo_passthru_parse(blob, mem_ctx,
296						     RAW_QFS_DEVICE_INFORMATION, fsinfo);
297
298	case RAW_QFS_ATTRIBUTE_INFO:
299	case RAW_QFS_ATTRIBUTE_INFORMATION:
300		return smb_raw_fsinfo_passthru_parse(blob, mem_ctx,
301						     RAW_QFS_ATTRIBUTE_INFORMATION, fsinfo);
302
303	case RAW_QFS_UNIX_INFO:
304		QFS_CHECK_SIZE(12);
305		fsinfo->unix_info.out.major_version = SVAL(blob.data, 0);
306		fsinfo->unix_info.out.minor_version = SVAL(blob.data, 2);
307		fsinfo->unix_info.out.capability    = SVAL(blob.data, 4);
308		break;
309
310	case RAW_QFS_QUOTA_INFORMATION:
311		return smb_raw_fsinfo_passthru_parse(blob, mem_ctx,
312						     RAW_QFS_QUOTA_INFORMATION, fsinfo);
313
314	case RAW_QFS_FULL_SIZE_INFORMATION:
315		return smb_raw_fsinfo_passthru_parse(blob, mem_ctx,
316						     RAW_QFS_FULL_SIZE_INFORMATION, fsinfo);
317
318	case RAW_QFS_OBJECTID_INFORMATION:
319		return smb_raw_fsinfo_passthru_parse(blob, mem_ctx,
320						     RAW_QFS_OBJECTID_INFORMATION, fsinfo);
321	}
322
323failed:
324	return status;
325}
326
327/****************************************************************************
328 Query FSInfo raw interface (sync interface)
329****************************************************************************/
330_PUBLIC_ NTSTATUS smb_raw_fsinfo(struct smbcli_tree *tree,
331			TALLOC_CTX *mem_ctx,
332			union smb_fsinfo *fsinfo)
333{
334	struct smbcli_request *req = smb_raw_fsinfo_send(tree, mem_ctx, fsinfo);
335	return smb_raw_fsinfo_recv(req, mem_ctx, fsinfo);
336}
337