r23792: convert Samba4 to GPLv3
[ira/wip.git] / source / libcli / raw / rawfsinfo.c
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 "librpc/gen_ndr/ndr_misc.h"
25
26 /****************************************************************************
27  Query FS Info - SMBdskattr call (async send)
28 ****************************************************************************/
29 static struct smbcli_request *smb_raw_dskattr_send(struct smbcli_tree *tree, 
30                                                 union smb_fsinfo *fsinfo)
31 {
32         struct smbcli_request *req; 
33
34         req = smbcli_request_setup(tree, SMBdskattr, 0, 0);
35
36         if (!smbcli_request_send(req)) {
37                 smbcli_request_destroy(req);
38                 return NULL;
39         }
40
41         return req;
42 }
43
44 /****************************************************************************
45  Query FS Info - SMBdskattr call (async recv)
46 ****************************************************************************/
47 static NTSTATUS smb_raw_dskattr_recv(struct smbcli_request *req,
48                                      union smb_fsinfo *fsinfo)
49 {
50         if (!smbcli_request_receive(req) ||
51             smbcli_request_is_error(req)) {
52                 goto failed;
53         }
54
55         SMBCLI_CHECK_WCT(req, 5);
56         fsinfo->dskattr.out.units_total =     SVAL(req->in.vwv, VWV(0));
57         fsinfo->dskattr.out.blocks_per_unit = SVAL(req->in.vwv, VWV(1));
58         fsinfo->dskattr.out.block_size =      SVAL(req->in.vwv, VWV(2));
59         fsinfo->dskattr.out.units_free =      SVAL(req->in.vwv, VWV(3));
60
61 failed:
62         return smbcli_request_destroy(req);
63 }
64
65
66 /****************************************************************************
67  RAW_QFS_ trans2 interface via blobs (async send)
68 ****************************************************************************/
69 static struct smbcli_request *smb_raw_qfsinfo_send(struct smbcli_tree *tree,
70                                                 TALLOC_CTX *mem_ctx,
71                                                 uint16_t info_level)
72 {
73         struct smb_trans2 tp;
74         uint16_t setup = TRANSACT2_QFSINFO;
75         
76         tp.in.max_setup = 0;
77         tp.in.flags = 0; 
78         tp.in.timeout = 0;
79         tp.in.setup_count = 1;
80         tp.in.max_param = 0;
81         tp.in.max_data = 0xFFFF;
82         tp.in.setup = &setup;
83         tp.in.data = data_blob(NULL, 0);
84         tp.in.timeout = 0;
85
86         tp.in.params = data_blob_talloc(mem_ctx, NULL, 2);
87         if (!tp.in.params.data) {
88                 return NULL;
89         }
90         SSVAL(tp.in.params.data, 0, info_level);
91
92         return smb_raw_trans2_send(tree, &tp);
93 }
94
95 /****************************************************************************
96  RAW_QFS_ trans2 interface via blobs (async recv)
97 ****************************************************************************/
98 static NTSTATUS smb_raw_qfsinfo_blob_recv(struct smbcli_request *req,
99                                           TALLOC_CTX *mem_ctx,
100                                           DATA_BLOB *blob)
101 {
102         struct smb_trans2 tp;
103         NTSTATUS status;
104         
105         status = smb_raw_trans2_recv(req, mem_ctx, &tp);
106         
107         if (NT_STATUS_IS_OK(status)) {
108                 (*blob) = tp.out.data;
109         }
110
111         return status;
112 }
113
114
115 /* local macros to make the code more readable */
116 #define QFS_CHECK_MIN_SIZE(size) if (blob.length < (size)) { \
117       DEBUG(1,("Unexpected QFS reply size %d for level %u - expected min of %d\n", \
118                (int)blob.length, fsinfo->generic.level, (size))); \
119       status = NT_STATUS_INFO_LENGTH_MISMATCH; \
120       goto failed; \
121 }
122 #define QFS_CHECK_SIZE(size) if (blob.length != (size)) { \
123       DEBUG(1,("Unexpected QFS reply size %d for level %u - expected %d\n", \
124                (int)blob.length, fsinfo->generic.level, (size))); \
125       status = NT_STATUS_INFO_LENGTH_MISMATCH; \
126       goto failed; \
127 }
128
129
130 /****************************************************************************
131  Query FSInfo raw interface (async send)
132 ****************************************************************************/
133 struct smbcli_request *smb_raw_fsinfo_send(struct smbcli_tree *tree, 
134                                         TALLOC_CTX *mem_ctx, 
135                                         union smb_fsinfo *fsinfo)
136 {
137         uint16_t info_level;
138
139         /* handle the only non-trans2 call separately */
140         if (fsinfo->generic.level == RAW_QFS_DSKATTR) {
141                 return smb_raw_dskattr_send(tree, fsinfo);
142         }
143         if (fsinfo->generic.level >= RAW_QFS_GENERIC) {
144                 return NULL;
145         }
146
147         /* the headers map the trans2 levels direct to info levels */
148         info_level = (uint16_t)fsinfo->generic.level;
149
150         return smb_raw_qfsinfo_send(tree, mem_ctx, info_level);
151 }
152
153 /*
154   parse the fsinfo 'passthru' level replies
155 */
156 NTSTATUS smb_raw_fsinfo_passthru_parse(DATA_BLOB blob, TALLOC_CTX *mem_ctx, 
157                                        enum smb_fsinfo_level level,
158                                        union smb_fsinfo *fsinfo)
159 {
160         NTSTATUS status = NT_STATUS_OK;
161         int i;
162
163         /* parse the results */
164         switch (level) {
165         case RAW_QFS_VOLUME_INFORMATION:
166                 QFS_CHECK_MIN_SIZE(18);
167                 fsinfo->volume_info.out.create_time   = smbcli_pull_nttime(blob.data, 0);
168                 fsinfo->volume_info.out.serial_number = IVAL(blob.data, 8);
169                 smbcli_blob_pull_string(NULL, mem_ctx, &blob, 
170                                         &fsinfo->volume_info.out.volume_name,
171                                         12, 18, STR_UNICODE);
172                 break;          
173
174         case RAW_QFS_SIZE_INFORMATION:
175                 QFS_CHECK_SIZE(24);
176                 fsinfo->size_info.out.total_alloc_units = BVAL(blob.data,  0);
177                 fsinfo->size_info.out.avail_alloc_units = BVAL(blob.data,  8);
178                 fsinfo->size_info.out.sectors_per_unit =  IVAL(blob.data, 16);
179                 fsinfo->size_info.out.bytes_per_sector =  IVAL(blob.data, 20); 
180                 break;          
181
182         case RAW_QFS_DEVICE_INFORMATION:
183                 QFS_CHECK_SIZE(8);
184                 fsinfo->device_info.out.device_type     = IVAL(blob.data,  0);
185                 fsinfo->device_info.out.characteristics = IVAL(blob.data,  4);
186                 break;          
187
188         case RAW_QFS_ATTRIBUTE_INFORMATION:
189                 QFS_CHECK_MIN_SIZE(12);
190                 fsinfo->attribute_info.out.fs_attr   =                 IVAL(blob.data, 0);
191                 fsinfo->attribute_info.out.max_file_component_length = IVAL(blob.data, 4);
192                 smbcli_blob_pull_string(NULL, mem_ctx, &blob, 
193                                         &fsinfo->attribute_info.out.fs_type,
194                                         8, 12, STR_UNICODE);
195                 break;          
196
197         case RAW_QFS_QUOTA_INFORMATION:
198                 QFS_CHECK_SIZE(48);
199                 fsinfo->quota_information.out.unknown[0] =  BVAL(blob.data,  0);
200                 fsinfo->quota_information.out.unknown[1] =  BVAL(blob.data,  8);
201                 fsinfo->quota_information.out.unknown[2] =  BVAL(blob.data, 16);
202                 fsinfo->quota_information.out.quota_soft =  BVAL(blob.data, 24);
203                 fsinfo->quota_information.out.quota_hard =  BVAL(blob.data, 32);
204                 fsinfo->quota_information.out.quota_flags = BVAL(blob.data, 40);
205                 break;          
206
207         case RAW_QFS_FULL_SIZE_INFORMATION:
208                 QFS_CHECK_SIZE(32);
209                 fsinfo->full_size_information.out.total_alloc_units =        BVAL(blob.data,  0);
210                 fsinfo->full_size_information.out.call_avail_alloc_units =   BVAL(blob.data,  8);
211                 fsinfo->full_size_information.out.actual_avail_alloc_units = BVAL(blob.data, 16);
212                 fsinfo->full_size_information.out.sectors_per_unit =         IVAL(blob.data, 24);
213                 fsinfo->full_size_information.out.bytes_per_sector =         IVAL(blob.data, 28);
214                 break;          
215
216         case RAW_QFS_OBJECTID_INFORMATION:
217                 QFS_CHECK_SIZE(64);
218                 status = ndr_pull_struct_blob(&blob, mem_ctx, &fsinfo->objectid_information.out.guid,
219                                               (ndr_pull_flags_fn_t)ndr_pull_GUID);
220                 for (i=0;i<6;i++) {
221                         fsinfo->objectid_information.out.unknown[i] = BVAL(blob.data, 16 + i*8);
222                 }
223                 break;
224                 
225         default:
226                 status = NT_STATUS_INVALID_INFO_CLASS;
227         }
228
229 failed:
230         return status;
231 }
232
233
234 /****************************************************************************
235  Query FSInfo raw interface (async recv)
236 ****************************************************************************/
237 NTSTATUS smb_raw_fsinfo_recv(struct smbcli_request *req, 
238                              TALLOC_CTX *mem_ctx, 
239                              union smb_fsinfo *fsinfo)
240 {
241         DATA_BLOB blob;
242         NTSTATUS status;
243         struct smbcli_session *session = req?req->session:NULL;
244
245         if (fsinfo->generic.level == RAW_QFS_DSKATTR) {
246                 return smb_raw_dskattr_recv(req, fsinfo);
247         }
248
249         status = smb_raw_qfsinfo_blob_recv(req, mem_ctx, &blob);
250         if (!NT_STATUS_IS_OK(status)) {
251                 return status;
252         }
253
254         /* parse the results */
255         switch (fsinfo->generic.level) {
256         case RAW_QFS_GENERIC:
257         case RAW_QFS_DSKATTR:
258                 /* handled above */
259                 break;
260
261         case RAW_QFS_ALLOCATION:
262                 QFS_CHECK_SIZE(18);
263                 fsinfo->allocation.out.fs_id =             IVAL(blob.data,  0);
264                 fsinfo->allocation.out.sectors_per_unit =  IVAL(blob.data,  4);
265                 fsinfo->allocation.out.total_alloc_units = IVAL(blob.data,  8);
266                 fsinfo->allocation.out.avail_alloc_units = IVAL(blob.data, 12);
267                 fsinfo->allocation.out.bytes_per_sector =  SVAL(blob.data, 16); 
268                 break;          
269
270         case RAW_QFS_VOLUME:
271                 QFS_CHECK_MIN_SIZE(5);
272                 fsinfo->volume.out.serial_number = IVAL(blob.data, 0);
273                 smbcli_blob_pull_string(session, mem_ctx, &blob, 
274                                      &fsinfo->volume.out.volume_name,
275                                      4, 5, STR_LEN8BIT | STR_NOALIGN);
276                 break;          
277
278         case RAW_QFS_VOLUME_INFO:
279         case RAW_QFS_VOLUME_INFORMATION:
280                 return smb_raw_fsinfo_passthru_parse(blob, mem_ctx, 
281                                                      RAW_QFS_VOLUME_INFORMATION, fsinfo);
282
283         case RAW_QFS_SIZE_INFO:
284         case RAW_QFS_SIZE_INFORMATION:
285                 return smb_raw_fsinfo_passthru_parse(blob, mem_ctx, 
286                                                      RAW_QFS_SIZE_INFORMATION, fsinfo);
287
288         case RAW_QFS_DEVICE_INFO:
289         case RAW_QFS_DEVICE_INFORMATION:
290                 return smb_raw_fsinfo_passthru_parse(blob, mem_ctx, 
291                                                      RAW_QFS_DEVICE_INFORMATION, fsinfo);
292
293         case RAW_QFS_ATTRIBUTE_INFO:
294         case RAW_QFS_ATTRIBUTE_INFORMATION:
295                 return smb_raw_fsinfo_passthru_parse(blob, mem_ctx, 
296                                                      RAW_QFS_ATTRIBUTE_INFORMATION, fsinfo);
297
298         case RAW_QFS_UNIX_INFO:
299                 QFS_CHECK_SIZE(12);
300                 fsinfo->unix_info.out.major_version = SVAL(blob.data, 0);
301                 fsinfo->unix_info.out.minor_version = SVAL(blob.data, 2);
302                 fsinfo->unix_info.out.capability    = SVAL(blob.data, 4);
303                 break;
304
305         case RAW_QFS_QUOTA_INFORMATION:
306                 return smb_raw_fsinfo_passthru_parse(blob, mem_ctx, 
307                                                      RAW_QFS_QUOTA_INFORMATION, fsinfo);
308
309         case RAW_QFS_FULL_SIZE_INFORMATION:
310                 return smb_raw_fsinfo_passthru_parse(blob, mem_ctx, 
311                                                      RAW_QFS_FULL_SIZE_INFORMATION, fsinfo);
312
313         case RAW_QFS_OBJECTID_INFORMATION:
314                 return smb_raw_fsinfo_passthru_parse(blob, mem_ctx, 
315                                                      RAW_QFS_OBJECTID_INFORMATION, fsinfo);
316         }
317
318 failed:
319         return status;
320 }
321
322 /****************************************************************************
323  Query FSInfo raw interface (sync interface)
324 ****************************************************************************/
325 NTSTATUS smb_raw_fsinfo(struct smbcli_tree *tree, 
326                         TALLOC_CTX *mem_ctx, 
327                         union smb_fsinfo *fsinfo)
328 {
329         struct smbcli_request *req = smb_raw_fsinfo_send(tree, mem_ctx, fsinfo);
330         return smb_raw_fsinfo_recv(req, mem_ctx, fsinfo);
331 }