1/*
2 *  Unix SMB/CIFS implementation.
3 *  MSDfs RPC Pipe client / server routines
4 *  Copyright (C) Andrew Tridgell              1992-2000,
5 *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 *  Copyright (C) Shirish Kalele               2000.
7 *  Copyright (C) Jeremy Allison				2001.
8 *
9 *  This program is free software; you can redistribute it and/or modify
10 *  it under the terms of the GNU General Public License as published by
11 *  the Free Software Foundation; either version 2 of the License, or
12 *  (at your option) any later version.
13 *
14 *  This program is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this program; if not, write to the Free Software
21 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include "includes.h"
25#include "nterr.h"
26#include "rpc_parse.h"
27
28#undef DBGC_CLASS
29#define DBGC_CLASS DBGC_RPC_PARSE
30
31/*******************************************************************
32Make a DFS_Q_DFS_QUERY structure
33*******************************************************************/
34
35void init_dfs_q_dfs_exist(DFS_Q_DFS_EXIST *q_d)
36{
37	q_d->dummy = 0;
38}
39
40/*************************************************************
41 Read/write a DFS_Q_DFS_EXIST structure - dummy...
42 ************************************************************/
43
44BOOL dfs_io_q_dfs_exist(const char *desc, DFS_Q_DFS_EXIST *q_d, prs_struct *ps, int depth)
45{
46	if(q_d == NULL)
47		return False;
48
49	prs_debug(ps, depth, desc, "dfs_io_q_dfs_exist");
50
51	return True;
52}
53
54/*************************************************************
55 Read/write a DFS_R_DFS_EXIST structure
56 ************************************************************/
57
58BOOL dfs_io_r_dfs_exist(const char *desc, DFS_R_DFS_EXIST *q_d, prs_struct *ps, int depth)
59{
60	if(q_d == NULL)
61		return False;
62
63	prs_debug(ps, depth, desc, "dfs_io_r_dfs_exist");
64	depth++;
65
66	if(!prs_align(ps))
67		return False;
68
69	if(!prs_uint32("exist flag", ps, 0, &q_d->status))
70		return False;
71
72	return True;
73}
74
75/*******************************************************************
76Make a DFS_Q_DFS_REMOVE structure
77*******************************************************************/
78
79BOOL init_dfs_q_dfs_remove(DFS_Q_DFS_REMOVE *q_d, const char *entrypath,
80			   const char *servername, const char *sharename)
81{
82	DEBUG(5,("init_dfs_q_dfs_remove\n"));
83	init_unistr2(&q_d->DfsEntryPath, entrypath, UNI_STR_TERMINATE);
84	init_unistr2(&q_d->ServerName, servername, UNI_STR_TERMINATE);
85	init_unistr2(&q_d->ShareName, sharename, UNI_STR_TERMINATE);
86	q_d->ptr_ServerName = q_d->ptr_ShareName = 1;
87	return True;
88}
89
90/*******************************************************************
91Read/write a DFS_Q_DFS_REMOVE structure
92*******************************************************************/
93
94BOOL dfs_io_q_dfs_remove(const char *desc, DFS_Q_DFS_REMOVE *q_d, prs_struct *ps, int depth)
95{
96	if(q_d == NULL)
97		return False;
98
99	prs_debug(ps, depth, desc, "dfs_io_q_dfs_remove");
100	depth++;
101
102	if(!prs_align(ps))
103		return False;
104
105	if(!smb_io_unistr2("DfsEntryPath",&q_d->DfsEntryPath, 1, ps, depth))
106		return False;
107
108	if(!prs_align(ps))
109		return False;
110
111	if(!prs_uint32("ptr_ServerName", ps, depth, &q_d->ptr_ServerName))
112		return False;
113	if(q_d->ptr_ServerName)
114		if (!smb_io_unistr2("ServerName",&q_d->ServerName, q_d->ptr_ServerName, ps, depth))
115			return False;
116	if(!prs_align(ps))
117		return False;
118
119	if(!prs_uint32("ptr_ShareName", ps, depth, &q_d->ptr_ShareName))
120		return False;
121	if(q_d->ptr_ShareName)
122		if (!smb_io_unistr2("ShareName",&q_d->ShareName,  q_d->ptr_ShareName, ps, depth))
123			return False;
124	if(!prs_align(ps))
125		return False;
126
127	return True;
128}
129
130/*******************************************************************
131Read/write a DFS_R_DFS_REMOVE structure
132*******************************************************************/
133
134BOOL dfs_io_r_dfs_remove(const char *desc, DFS_R_DFS_REMOVE *r_d, prs_struct *ps, int depth)
135{
136	if(r_d == NULL)
137		return False;
138
139	prs_debug(ps, depth, desc, "dfs_io_r_dfs_remove");
140	depth++;
141
142	if(!prs_werror("status", ps, depth, &r_d->status))
143		return False;
144
145	return True;
146}
147
148/*******************************************************************
149Make a DFS_Q_DFS_ADD structure
150*******************************************************************/
151
152BOOL init_dfs_q_dfs_add(DFS_Q_DFS_ADD *q_d, const char *entrypath,
153			const char *servername, const char *sharename,
154			const char *comment, uint32 flags)
155{
156	DEBUG(5,("init_dfs_q_dfs_add\n"));
157	q_d->ptr_DfsEntryPath = q_d->ptr_ServerName = q_d->ptr_ShareName = 1;
158	init_unistr2(&q_d->DfsEntryPath, entrypath, UNI_STR_TERMINATE);
159	init_unistr2(&q_d->ServerName, servername, UNI_STR_TERMINATE);
160	init_unistr2(&q_d->ShareName, sharename, UNI_STR_TERMINATE);
161	if(comment != NULL) {
162		init_unistr2(&q_d->Comment, comment,UNI_STR_TERMINATE);
163		q_d->ptr_Comment = 1;
164	} else {
165		q_d->ptr_Comment = 0;
166	}
167
168	q_d->Flags = flags;
169	return True;
170}
171
172/************************************************************
173 Read/write a DFS_Q_DFS_ADD structure
174 ************************************************************/
175
176BOOL dfs_io_q_dfs_add(const char *desc, DFS_Q_DFS_ADD *q_d, prs_struct *ps, int depth)
177{
178	if(q_d == NULL)
179		return False;
180
181	prs_debug(ps, depth, desc, "dfs_io_q_dfs_add");
182	depth++;
183
184	if(!prs_align(ps))
185		return False;
186
187	if(!smb_io_unistr2("DfsEntryPath",&q_d->DfsEntryPath, 1, ps, depth))
188		return False;
189	if(!prs_align(ps))
190		return False;
191
192	if(!smb_io_unistr2("ServerName",&q_d->ServerName, 1, ps, depth))
193		return False;
194	if(!prs_align(ps))
195		return False;
196
197	if(!prs_uint32("ptr_ShareName", ps, depth, &q_d->ptr_ShareName))
198		return False;
199	if(!smb_io_unistr2("ShareName",&q_d->ShareName,  1, ps, depth))
200		return False;
201	if(!prs_align(ps))
202		return False;
203
204	if(!prs_uint32("ptr_Comment", ps, depth, &q_d->ptr_Comment))
205		return False;
206	if(!smb_io_unistr2("",&q_d->Comment, q_d->ptr_Comment , ps, depth))
207		return False;
208	if(!prs_align(ps))
209		return False;
210
211	if(!prs_uint32("Flags", ps, depth, &q_d->Flags))
212		return True;
213
214	return True;
215}
216
217/************************************************************
218 Read/write a DFS_R_DFS_ADD structure
219 ************************************************************/
220
221BOOL dfs_io_r_dfs_add(const char *desc, DFS_R_DFS_ADD *r_d, prs_struct *ps, int depth)
222{
223	if(r_d == NULL)
224		return False;
225
226	prs_debug(ps, depth, desc, "dfs_io_r_dfs_add");
227	depth++;
228
229	if(!prs_werror("status", ps, depth, &r_d->status))
230		return False;
231
232	return True;
233}
234
235BOOL init_dfs_q_dfs_get_info(DFS_Q_DFS_GET_INFO *q_d, const char *entrypath,
236			     const char *servername, const char *sharename,
237			     uint32 info_level)
238{
239	DEBUG(5,("init_dfs_q2_get_info\n"));
240	init_unistr2(&q_d->uni_path, entrypath, UNI_STR_TERMINATE);
241	init_unistr2(&q_d->uni_server, servername, UNI_STR_TERMINATE);
242	init_unistr2(&q_d->uni_share, sharename, UNI_STR_TERMINATE);
243	q_d->level = info_level;
244	q_d->ptr_server = q_d->ptr_share = 1;
245	return True;
246}
247
248/************************************************************
249 Read/write a DFS_Q_GET_INFO structure
250 ************************************************************/
251
252BOOL dfs_io_q_dfs_get_info(const char *desc, DFS_Q_DFS_GET_INFO* q_i, prs_struct* ps, int depth)
253{
254	if(q_i == NULL)
255		return False;
256
257	prs_debug(ps, depth, desc, "dfs_io_q_dfs_get_info");
258	depth++;
259
260	if(!smb_io_unistr2("",&q_i->uni_path, 1, ps, depth))
261		return False;
262
263	if(!prs_align(ps))
264		return False;
265
266	if(!prs_uint32("ptr_server", ps, depth, &q_i->ptr_server))
267		return False;
268
269	if(q_i->ptr_server)
270		if (!smb_io_unistr2("",&q_i->uni_server, q_i->ptr_server, ps, depth))
271			return False;
272	if(!prs_align(ps))
273		return False;
274
275	if(!prs_uint32("ptr_share", ps, depth, &q_i->ptr_share))
276		return False;
277	if(q_i->ptr_share)
278		if(!smb_io_unistr2("", &q_i->uni_share, q_i->ptr_share, ps, depth))
279			return False;
280	if(!prs_align(ps))
281		return False;
282
283	if(!prs_uint32("level", ps, depth, &q_i->level))
284		return False;
285	return True;
286}
287
288/************************************************************
289 Read/write a DFS_R_GET_INFO structure
290 ************************************************************/
291
292BOOL dfs_io_r_dfs_get_info(const char *desc, DFS_R_DFS_GET_INFO* r_i, prs_struct* ps, int depth)
293{
294	if(r_i == NULL)
295		return False;
296
297	if(!prs_uint32("level", ps, depth, &r_i->level))
298		return False;
299	if(!prs_uint32("ptr_ctr", ps, depth, &r_i->ptr_ctr))
300		return False;
301
302	if(!dfs_io_dfs_info_ctr("", &r_i->ctr, 1, r_i->level, ps, depth))
303		return False;
304	if(!prs_werror("status", ps, depth, &r_i->status))
305		return False;
306	return True;
307}
308
309/************************************************************
310 Make a DFS_Q_DFS_ENUM structure
311 ************************************************************/
312BOOL init_dfs_q_dfs_enum(DFS_Q_DFS_ENUM *q_d, uint32 level, DFS_INFO_CTR *ctr)
313{
314	q_d->level = level;
315	q_d->maxpreflen = -1;
316	q_d->ptr_buffer = 1;
317	q_d->level2 = level;
318
319	q_d->ptr_num_entries = 1;
320	q_d->num_entries = 0;
321	q_d->num_entries2 = 0;
322	q_d->reshnd.ptr_hnd = 1;
323	q_d->reshnd.handle = 0;
324	return True;
325}
326
327/************************************************************
328 Read or write the DFS_Q_DFS_ENUM structure
329 ************************************************************/
330
331BOOL dfs_io_q_dfs_enum(const char *desc, DFS_Q_DFS_ENUM *q_d, prs_struct *ps, int depth)
332{
333	if(q_d == NULL)
334		return False;
335
336	prs_debug(ps, depth, desc, "dfs_io_q_dfs_enum");
337	depth++;
338
339	if(!prs_align(ps))
340		return False;
341
342	if(!prs_uint32("level", ps, depth, &q_d->level))
343		return False;
344	if(!prs_uint32("maxpreflen", ps, depth, &q_d->maxpreflen))
345		return False;
346	if(!prs_uint32("ptr_buffer", ps, depth, &q_d->ptr_buffer))
347		return False;
348	if(!prs_uint32("level2", ps, depth, &q_d->level2))
349		return False;
350	if(!prs_uint32("level3", ps, depth, &q_d->level2))
351		return False;
352
353	if(!prs_uint32("ptr_num_entries", ps, depth, &q_d->ptr_num_entries))
354		return False;
355	if(!prs_uint32("num_entries", ps, depth, &q_d->num_entries))
356		return False;
357	if(!prs_uint32("num_entries2", ps, depth, &q_d->num_entries2))
358		return False;
359	if(!smb_io_enum_hnd("resume_hnd",&q_d->reshnd, ps, depth))
360		return False;
361	return True;
362}
363
364/************************************************************
365 Read/write a DFS_INFO_CTR structure
366 ************************************************************/
367
368BOOL dfs_io_dfs_info_ctr(const char *desc, DFS_INFO_CTR* ctr, uint32 num_entries, uint32 level, prs_struct* ps, int depth)
369{
370	int i=0;
371
372	switch(level) {
373	case 1:
374		depth++;
375		/* should depend on whether marshalling or unmarshalling! */
376		if(UNMARSHALLING(ps)) {
377			ctr->dfs.info1 = (DFS_INFO_1 *)prs_alloc_mem(ps, sizeof(DFS_INFO_1)*num_entries);
378			if (!ctr->dfs.info1)
379				return False;
380		}
381
382		for(i=0;i<num_entries;i++) {
383			if(!prs_uint32("ptr_entrypath",ps, depth, &ctr->dfs.info1[i].ptr_entrypath))
384				return False;
385		}
386		for(i=0;i<num_entries;i++) {
387			if(!smb_io_unistr2("", &ctr->dfs.info1[i].entrypath, ctr->dfs.info1[i].ptr_entrypath, ps, depth))
388				return False;
389			if(!prs_align(ps))
390				return False;
391		}
392		depth--;
393		break;
394	case 2:
395		depth++;
396		if(UNMARSHALLING(ps)) {
397			ctr->dfs.info2 = (DFS_INFO_2 *)prs_alloc_mem(ps, num_entries*sizeof(DFS_INFO_2));
398			if (!ctr->dfs.info2)
399				return False;
400		}
401
402		for(i=0;i<num_entries;i++) {
403			if(!prs_uint32("ptr_entrypath", ps, depth, &ctr->dfs.info2[i].ptr_entrypath))
404				return False;
405			if(!prs_uint32("ptr_comment", ps, depth, &ctr->dfs.info2[i].ptr_comment))
406				return False;
407			if(!prs_uint32("state", ps, depth, &ctr->dfs.info2[i].state))
408				return False;
409			if(!prs_uint32("num_storages", ps, depth, &ctr->dfs.info2[i].num_storages))
410				return False;
411		}
412		for(i=0;i<num_entries;i++) {
413			if(!smb_io_unistr2("", &ctr->dfs.info2[i].entrypath, ctr->dfs.info2[i].ptr_entrypath, ps, depth))
414				return False;
415			if(!prs_align(ps))
416				return False;
417			if(!smb_io_unistr2("",&ctr->dfs.info2[i].comment, ctr->dfs.info2[i].ptr_comment, ps, depth))
418				return False;
419			if(!prs_align(ps))
420				return False;
421		}
422		depth--;
423		break;
424	case 3:
425		depth++;
426		if(UNMARSHALLING(ps)) {
427			ctr->dfs.info3 = (DFS_INFO_3 *)prs_alloc_mem(ps, num_entries*sizeof(DFS_INFO_3));
428			if (!ctr->dfs.info3)
429				return False;
430		}
431
432		for(i=0;i<num_entries;i++) {
433			if(!prs_uint32("ptr_entrypath", ps, depth, &ctr->dfs.info3[i].ptr_entrypath))
434				return False;
435			if(!prs_uint32("ptr_comment", ps, depth, &ctr->dfs.info3[i].ptr_comment))
436				return False;
437			if(!prs_uint32("state", ps, depth, &ctr->dfs.info3[i].state))
438				return False;
439			if(!prs_uint32("num_storages", ps, depth, &ctr->dfs.info3[i].num_storages))
440				return False;
441			if(!prs_uint32("ptr_storages", ps, depth, &ctr->dfs.info3[i].ptr_storages))
442				return False;
443		}
444		for(i=0;i<num_entries;i++) {
445			if(!smb_io_unistr2("", &ctr->dfs.info3[i].entrypath, ctr->dfs.info3[i].ptr_entrypath, ps, depth))
446				return False;
447			if(!prs_align(ps))
448				return False;
449			if(!smb_io_unistr2("", &ctr->dfs.info3[i].comment, ctr->dfs.info3[i].ptr_comment, ps, depth))
450				return False;
451			if(!prs_align(ps))
452				return False;
453			if(!prs_uint32("num_storage_infos", ps, depth, &ctr->dfs.info3[i].num_storage_infos))
454				return False;
455
456			if(!dfs_io_dfs_storage_info("storage_info", &ctr->dfs.info3[i], ps, depth))
457				return False;
458		}
459	}
460
461	return True;
462}
463
464/************************************************************
465 Read/write a DFS_R_DFS_ENUM structure
466 ************************************************************/
467
468BOOL dfs_io_r_dfs_enum(const char *desc, DFS_R_DFS_ENUM *q_d, prs_struct *ps, int depth)
469{
470	DFS_INFO_CTR *ctr;
471	if(q_d == NULL)
472		return False;
473	ctr = q_d->ctr;
474	if(ctr == NULL)
475		return False;
476
477	prs_debug(ps, depth, desc, "dfs_io_r_dfs_enum");
478	depth++;
479
480	if(!prs_align(ps))
481		return False;
482
483	if(!prs_uint32("ptr_buffer", ps, depth, &q_d->ptr_buffer))
484		return False;
485	if(!prs_uint32("level", ps, depth, &q_d->level))
486		return False;
487	if(!prs_uint32("level2", ps, depth, &ctr->switch_value))
488		return False;
489	if(!prs_uint32("ptr_num_entries", ps, depth, &q_d->ptr_num_entries))
490		return False;
491	if(q_d->ptr_num_entries)
492		if(!prs_uint32("num_entries", ps, depth, &q_d->num_entries))
493			return False;
494	if(!prs_uint32("ptr_num_entries2", ps, depth, &q_d->ptr_num_entries2))
495		return False;
496	if(q_d->ptr_num_entries2)
497		if(!prs_uint32("num_entries2", ps, depth, &ctr->num_entries))
498			return False;
499
500	if(!dfs_io_dfs_info_ctr("", ctr, q_d->num_entries, q_d->level, ps, depth))
501		return False;
502
503	if(!smb_io_enum_hnd("resume_hnd", &q_d->reshnd, ps, depth))
504		return False;
505	if(!prs_werror("status", ps, depth, &q_d->status))
506		return False;
507	return True;
508}
509
510BOOL dfs_io_dfs_storage_info(const char *desc, DFS_INFO_3* info3, prs_struct *ps, int depth)
511{
512	int i=0;
513	if(info3 == NULL)
514		return False;
515
516	prs_debug(ps, depth, desc, "smb_io_dfs_storage_info");
517	depth++;
518
519	if(UNMARSHALLING(ps)) {
520		info3->storages = (DFS_STORAGE_INFO *)prs_alloc_mem(ps, info3->num_storage_infos*sizeof(DFS_STORAGE_INFO));
521		if (!info3->storages)
522			return False;
523	}
524
525	for(i=0;i<info3->num_storage_infos;i++) {
526		if(!prs_uint32("storage_state", ps, depth, &info3->storages[i].state))
527			return False;
528		if(!prs_uint32("ptr_servername", ps, depth, &info3->storages[i].ptr_servername))
529			return False;
530		if(!prs_uint32("ptr_sharename", ps, depth, &info3->storages[i].ptr_sharename))
531			return False;
532	}
533
534	for(i=0;i<info3->num_storage_infos;i++) {
535		if(!smb_io_unistr2("servername", &info3->storages[i].servername, info3->storages[i].ptr_servername, ps, depth))
536			return False;
537		if(!prs_align(ps))
538			return False;
539		if(!smb_io_unistr2("sharename", &info3->storages[i].sharename, info3->storages[i].ptr_sharename, ps, depth))
540			return False;
541		if(!prs_align(ps))
542			return False;
543	}
544
545	return True;
546}
547