xref: /plan9/sys/src/cmd/cifs/trans.c (revision 912e5f5442636b48aaa52937edbb904e279d1987)
1671dfc47SDavid du Colombier #include <u.h>
2671dfc47SDavid du Colombier #include <libc.h>
3671dfc47SDavid du Colombier #include <fcall.h>
4671dfc47SDavid du Colombier #include <thread.h>
5671dfc47SDavid du Colombier #include <9p.h>
6671dfc47SDavid du Colombier #include "cifs.h"
7671dfc47SDavid du Colombier #include "remsmb.h"
8671dfc47SDavid du Colombier #include "apinums.h"
9671dfc47SDavid du Colombier 
10671dfc47SDavid du Colombier static Pkt *
thdr(Session * s,Share * sp)11671dfc47SDavid du Colombier thdr(Session *s, Share *sp)
12671dfc47SDavid du Colombier {
13671dfc47SDavid du Colombier 	Pkt *p;
14671dfc47SDavid du Colombier 
15671dfc47SDavid du Colombier 	p = cifshdr(s, sp, SMB_COM_TRANSACTION);
16671dfc47SDavid du Colombier 	p->tbase = pl16(p, 0);	/* 0  Total parameter bytes to be sent, filled later */
17671dfc47SDavid du Colombier 	pl16(p, 0);		/* 2  Total data bytes to be sent, filled later */
18671dfc47SDavid du Colombier 	pl16(p, 64);			/* 4  Max parameter to return */
19671dfc47SDavid du Colombier 	pl16(p, MTU - T2HDRLEN - 128);	/* 6  Max data to return */
20671dfc47SDavid du Colombier 	pl16(p, 1);			/* 8  Max setup count to return */
21671dfc47SDavid du Colombier 	pl16(p, 0);			/* 10 Flags */
22671dfc47SDavid du Colombier 	pl32(p, 1000);			/* 12 Timeout (ms) */
23671dfc47SDavid du Colombier 	pl16(p, 0);			/* 16 Reserved */
24671dfc47SDavid du Colombier 	pl16(p, 0);			/* 18 Parameter count, filled later */
25671dfc47SDavid du Colombier 	pl16(p, 0);			/* 20 Parameter offset, filled later */
26671dfc47SDavid du Colombier 	pl16(p, 0);			/* 22 Data count, filled later */
27671dfc47SDavid du Colombier 	pl16(p, 0);			/* 24 Data offset, filled later */
28671dfc47SDavid du Colombier 	pl16(p, 0);			/* 26 Setup count (in words) */
29671dfc47SDavid du Colombier 	pbytes(p);			/* end of cifs words section */
30671dfc47SDavid du Colombier 	return p;
31671dfc47SDavid du Colombier }
32671dfc47SDavid du Colombier 
33671dfc47SDavid du Colombier static void
ptparam(Pkt * p)34671dfc47SDavid du Colombier ptparam(Pkt *p)
35671dfc47SDavid du Colombier {
36671dfc47SDavid du Colombier 	uchar *pos;
37671dfc47SDavid du Colombier 
38671dfc47SDavid du Colombier 	if(((p->pos - p->tbase) % 2) != 0)
39671dfc47SDavid du Colombier 		p8(p, 0);			/* pad to word boundry */
40671dfc47SDavid du Colombier 	pos = p->pos;
41671dfc47SDavid du Colombier 	p->pos = p->tbase + 20;
42671dfc47SDavid du Colombier 	pl16(p, pos - p->buf - NBHDRLEN);	/* param offset */
43671dfc47SDavid du Colombier 	p->tparam = p->pos = pos;
44671dfc47SDavid du Colombier }
45671dfc47SDavid du Colombier 
46671dfc47SDavid du Colombier static void
ptdata(Pkt * p)47671dfc47SDavid du Colombier ptdata(Pkt *p)
48671dfc47SDavid du Colombier {
49671dfc47SDavid du Colombier 	uchar *pos = p->pos;
50671dfc47SDavid du Colombier 
51671dfc47SDavid du Colombier 	assert(p->tparam != 0);
52671dfc47SDavid du Colombier 	if(((p->pos - p->tbase) % 2) != 0)
53671dfc47SDavid du Colombier 		p8(p, 0);		/* pad to word boundry */
54671dfc47SDavid du Colombier 
55671dfc47SDavid du Colombier 	p->pos = p->tbase + 0;
56671dfc47SDavid du Colombier 	pl16(p, pos - p->tparam);	/* total param count */
57671dfc47SDavid du Colombier 
58671dfc47SDavid du Colombier 	p->pos = p->tbase + 18;
59671dfc47SDavid du Colombier 	pl16(p, pos - p->tparam);	/* param count */
60671dfc47SDavid du Colombier 
61671dfc47SDavid du Colombier 	p->pos = p->tbase + 24;
62671dfc47SDavid du Colombier 	pl16(p, pos - p->buf - NBHDRLEN); /* data offset */
63671dfc47SDavid du Colombier 
64671dfc47SDavid du Colombier 	p->tdata = p->pos = pos;
65671dfc47SDavid du Colombier }
66671dfc47SDavid du Colombier 
67671dfc47SDavid du Colombier static int
trpc(Pkt * p)68671dfc47SDavid du Colombier trpc(Pkt *p)
69671dfc47SDavid du Colombier {
70671dfc47SDavid du Colombier 	int got;
71671dfc47SDavid du Colombier 	uchar *pos = p->pos;
72671dfc47SDavid du Colombier 
73671dfc47SDavid du Colombier 	assert(p->tbase != 0);
74671dfc47SDavid du Colombier 	assert(p->tdata != 0);
75671dfc47SDavid du Colombier 
76671dfc47SDavid du Colombier 	p->pos = p->tbase + 2;
77671dfc47SDavid du Colombier 	pl16(p, pos - p->tdata);	/* total data count */
78671dfc47SDavid du Colombier 
79671dfc47SDavid du Colombier 	p->pos = p->tbase + 22;
80671dfc47SDavid du Colombier 	pl16(p, pos - p->tdata);	/* data count */
81671dfc47SDavid du Colombier 
82671dfc47SDavid du Colombier 	p->pos = pos;
83671dfc47SDavid du Colombier 	if((got = cifsrpc(p)) == -1)
84671dfc47SDavid du Colombier 		return -1;
85671dfc47SDavid du Colombier 
86671dfc47SDavid du Colombier 	gl16(p);			/* Total parameter count */
87671dfc47SDavid du Colombier 	gl16(p);			/* Total data count */
88671dfc47SDavid du Colombier 	gl16(p);			/* Reserved */
89671dfc47SDavid du Colombier 	gl16(p);			/* Parameter count in this buffer */
90671dfc47SDavid du Colombier 	p->tparam = p->buf + NBHDRLEN + gl16(p); /* Parameter offset */
91671dfc47SDavid du Colombier 	gl16(p);			/* Parameter displacement */
92671dfc47SDavid du Colombier 	gl16(p);			/* Data count (this buffer); */
93671dfc47SDavid du Colombier 	p->tdata = p->buf + NBHDRLEN + gl16(p); /* Data offset */
94671dfc47SDavid du Colombier 	gl16(p);			/* Data displacement */
95671dfc47SDavid du Colombier 	g8(p);				/* Setup count */
96671dfc47SDavid du Colombier 	g8(p);				/* Reserved */
97671dfc47SDavid du Colombier 	return got;
98671dfc47SDavid du Colombier }
99671dfc47SDavid du Colombier 
100671dfc47SDavid du Colombier static void
gtparam(Pkt * p)101671dfc47SDavid du Colombier gtparam(Pkt *p)
102671dfc47SDavid du Colombier {
103671dfc47SDavid du Colombier 	p->pos = p->tparam;
104671dfc47SDavid du Colombier }
105671dfc47SDavid du Colombier 
106671dfc47SDavid du Colombier static void
gtdata(Pkt * p)107671dfc47SDavid du Colombier gtdata(Pkt *p)
108671dfc47SDavid du Colombier {
109671dfc47SDavid du Colombier 	p->pos = p->tdata;
110671dfc47SDavid du Colombier }
111671dfc47SDavid du Colombier 
112671dfc47SDavid du Colombier 
113671dfc47SDavid du Colombier int
RAPshareenum(Session * s,Share * sp,Share ** ent)114671dfc47SDavid du Colombier RAPshareenum(Session *s, Share *sp, Share **ent)
115671dfc47SDavid du Colombier {
116671dfc47SDavid du Colombier 	int ngot = 0, err, navail, nret;
117671dfc47SDavid du Colombier 	char tmp[1024];
118671dfc47SDavid du Colombier 	Pkt *p;
119671dfc47SDavid du Colombier 	Share *q;
120671dfc47SDavid du Colombier 
121671dfc47SDavid du Colombier 	p = thdr(s, sp);
122671dfc47SDavid du Colombier 	pstr(p, "\\PIPE\\LANMAN");
123671dfc47SDavid du Colombier 	ptparam(p);
124671dfc47SDavid du Colombier 
125671dfc47SDavid du Colombier 	pl16(p, API_WShareEnum);
126671dfc47SDavid du Colombier 	pascii(p, REMSmb_NetShareEnum_P);	/* request descriptor */
127671dfc47SDavid du Colombier 	pascii(p, REMSmb_share_info_0);		/* reply descriptor */
128671dfc47SDavid du Colombier 	pl16(p, 0);				/* detail level */
129671dfc47SDavid du Colombier 	pl16(p, MTU - 200);			/* receive buffer length */
130671dfc47SDavid du Colombier 	ptdata(p);
131671dfc47SDavid du Colombier 
132671dfc47SDavid du Colombier 	if(trpc(p) == -1){
133671dfc47SDavid du Colombier 		free(p);
134671dfc47SDavid du Colombier 		return -1;
135671dfc47SDavid du Colombier 	}
136671dfc47SDavid du Colombier 
137671dfc47SDavid du Colombier 	gtparam(p);
138671dfc47SDavid du Colombier 	err = gl16(p);				/* error code */
139671dfc47SDavid du Colombier 	gl16(p);				/* rx buffer offset */
140671dfc47SDavid du Colombier 	nret = gl16(p);				/* number of entries returned */
141671dfc47SDavid du Colombier 	navail = gl16(p);			/* number of entries available */
142671dfc47SDavid du Colombier 
143671dfc47SDavid du Colombier 	if(err && err != RAP_ERR_MOREINFO){
144671dfc47SDavid du Colombier 		werrstr("%s", raperrstr(err));
145671dfc47SDavid du Colombier 		free(p);
146671dfc47SDavid du Colombier 		return -1;
147671dfc47SDavid du Colombier 	}
148671dfc47SDavid du Colombier 
149671dfc47SDavid du Colombier 	if(ngot == 0){
150671dfc47SDavid du Colombier 		*ent = emalloc9p(sizeof(Share) * navail);
151671dfc47SDavid du Colombier 		memset(*ent, 0, sizeof(Share) * navail);
152671dfc47SDavid du Colombier 	}
153671dfc47SDavid du Colombier 
154671dfc47SDavid du Colombier 	q = *ent + ngot;
155671dfc47SDavid du Colombier 	for (; ngot < navail && nret--; ngot++){
156671dfc47SDavid du Colombier 		gmem(p, tmp, 13); 		/* name */
157671dfc47SDavid du Colombier 		tmp[13] = 0;
158671dfc47SDavid du Colombier 		q->name = estrdup9p(tmp);
159671dfc47SDavid du Colombier 		q++;
160671dfc47SDavid du Colombier 	}
161671dfc47SDavid du Colombier 
162671dfc47SDavid du Colombier 	if(ngot < navail)
163*912e5f54SDavid du Colombier 		fprint(2, "%s: %d/%d - share list incomplete\n", argv0, ngot, navail);
164671dfc47SDavid du Colombier 
165671dfc47SDavid du Colombier 	free(p);
166671dfc47SDavid du Colombier 	return ngot;
167671dfc47SDavid du Colombier }
168671dfc47SDavid du Colombier 
169671dfc47SDavid du Colombier 
170671dfc47SDavid du Colombier int
RAPshareinfo(Session * s,Share * sp,char * share,Shareinfo2 * si2p)171671dfc47SDavid du Colombier RAPshareinfo(Session *s, Share *sp, char *share, Shareinfo2 *si2p)
172671dfc47SDavid du Colombier {
173671dfc47SDavid du Colombier 	int conv, err;
174671dfc47SDavid du Colombier 	char tmp[1024];
175671dfc47SDavid du Colombier 	Pkt *p;
176671dfc47SDavid du Colombier 
177671dfc47SDavid du Colombier 	p = thdr(s, sp);
178671dfc47SDavid du Colombier 	pstr(p, "\\PIPE\\LANMAN");
179671dfc47SDavid du Colombier 
180671dfc47SDavid du Colombier 	ptparam(p);
181671dfc47SDavid du Colombier 	pl16(p, API_WShareGetInfo);
182671dfc47SDavid du Colombier 	pascii(p, REMSmb_NetShareGetInfo_P);	/* request descriptor */
183671dfc47SDavid du Colombier 	pascii(p, REMSmb_share_info_2);		/* reply descriptor */
184671dfc47SDavid du Colombier 	pascii(p, share);
185671dfc47SDavid du Colombier 	pl16(p, 1);				/* detail level */
186671dfc47SDavid du Colombier 	pl16(p, MTU - 200);			/* receive buffer length */
187671dfc47SDavid du Colombier 
188671dfc47SDavid du Colombier 	ptdata(p);
189671dfc47SDavid du Colombier 
190671dfc47SDavid du Colombier 	if(trpc(p) == -1){
191671dfc47SDavid du Colombier 		free(p);
192671dfc47SDavid du Colombier 		return -1;
193671dfc47SDavid du Colombier 	}
194671dfc47SDavid du Colombier 
195671dfc47SDavid du Colombier 	gtparam(p);
196671dfc47SDavid du Colombier 	err = gl16(p);				/* error code */
197671dfc47SDavid du Colombier 	conv = gl16(p);				/* rx buffer offset */
198671dfc47SDavid du Colombier 	gl16(p);				/* number of entries returned */
199671dfc47SDavid du Colombier 	gl16(p);				/* number of entries available */
200671dfc47SDavid du Colombier 
201671dfc47SDavid du Colombier 	if(err){
202671dfc47SDavid du Colombier 		werrstr("%s", raperrstr(err));
203671dfc47SDavid du Colombier 		free(p);
204671dfc47SDavid du Colombier 		return -1;
205671dfc47SDavid du Colombier 	}
206671dfc47SDavid du Colombier 
207671dfc47SDavid du Colombier 	memset(si2p, 0, sizeof(Shareinfo2));
208671dfc47SDavid du Colombier 
209671dfc47SDavid du Colombier 	gmem(p, tmp, 13);
210671dfc47SDavid du Colombier 	tmp[13] = 0;
211671dfc47SDavid du Colombier 	g8(p);					/* padding */
212671dfc47SDavid du Colombier 	si2p->name = estrdup9p(tmp);
213671dfc47SDavid du Colombier 	si2p->type = gl16(p);
214671dfc47SDavid du Colombier 	gconv(p, conv, tmp, sizeof tmp);
215671dfc47SDavid du Colombier 	si2p->comment = estrdup9p(tmp);
216671dfc47SDavid du Colombier 	gl16(p);				/* comment offset high (unused) */
217671dfc47SDavid du Colombier 	si2p->perms = gl16(p);
218671dfc47SDavid du Colombier 	si2p->maxusrs = gl16(p);
219671dfc47SDavid du Colombier 	si2p->activeusrs = gl16(p);
220671dfc47SDavid du Colombier 	gconv(p, conv, tmp, sizeof tmp);
221671dfc47SDavid du Colombier 	si2p->path = estrdup9p(tmp);
222671dfc47SDavid du Colombier 	gl16(p);				/* path offset high (unused) */
223671dfc47SDavid du Colombier 	gmem(p, tmp, 9);
224671dfc47SDavid du Colombier 	tmp[9] = 0;
225671dfc47SDavid du Colombier 	si2p->passwd = estrdup9p(tmp);
226671dfc47SDavid du Colombier 
227671dfc47SDavid du Colombier 	free(p);
228671dfc47SDavid du Colombier 	return 0;
229671dfc47SDavid du Colombier }
230671dfc47SDavid du Colombier 
231671dfc47SDavid du Colombier /*
232671dfc47SDavid du Colombier  * Tried to split sessionenum into two passes, one getting the names
233671dfc47SDavid du Colombier  * of the connected workstations and the other collecting the detailed info,
234671dfc47SDavid du Colombier  * however API_WSessionGetInfo doesn't seem to work agains win2k3 for infolevel
235671dfc47SDavid du Colombier  * ten and infolevel one and two are priviledged calls.  This means this code
236671dfc47SDavid du Colombier  * will work for small numbers of sessions agains win2k3 and fail for samba 3.0
237671dfc47SDavid du Colombier  * as it supports info levels zero and two only.
238671dfc47SDavid du Colombier  */
239671dfc47SDavid du Colombier int
RAPsessionenum(Session * s,Share * sp,Sessinfo ** sip)240671dfc47SDavid du Colombier RAPsessionenum(Session *s, Share *sp, Sessinfo **sip)
241671dfc47SDavid du Colombier {
242671dfc47SDavid du Colombier 	int ngot = 0, conv, err, navail, nret;
243671dfc47SDavid du Colombier 	char tmp[1024];
244671dfc47SDavid du Colombier 	Pkt *p;
245671dfc47SDavid du Colombier 	Sessinfo *q;
246671dfc47SDavid du Colombier 
247671dfc47SDavid du Colombier 	p = thdr(s, sp);
248671dfc47SDavid du Colombier 	pstr(p, "\\PIPE\\LANMAN");
249671dfc47SDavid du Colombier 	ptparam(p);
250671dfc47SDavid du Colombier 
251671dfc47SDavid du Colombier 	pl16(p, API_WSessionEnum);
252671dfc47SDavid du Colombier 	pascii(p, REMSmb_NetSessionEnum_P);	/* request descriptor */
253671dfc47SDavid du Colombier 	pascii(p, REMSmb_session_info_10);	/* reply descriptor */
254671dfc47SDavid du Colombier 	pl16(p, 10);				/* detail level */
255671dfc47SDavid du Colombier 	pl16(p, MTU - 200);			/* receive buffer length */
256671dfc47SDavid du Colombier 	ptdata(p);
257671dfc47SDavid du Colombier 
258671dfc47SDavid du Colombier 	if(trpc(p) == -1){
259671dfc47SDavid du Colombier 		free(p);
260671dfc47SDavid du Colombier 		return -1;
261671dfc47SDavid du Colombier 	}
262671dfc47SDavid du Colombier 
263671dfc47SDavid du Colombier 	gtparam(p);
264671dfc47SDavid du Colombier 	err = gl16(p);				/* error code */
265671dfc47SDavid du Colombier 	conv = gl16(p);				/* rx buffer offset */
266671dfc47SDavid du Colombier 	nret = gl16(p);				/* number of entries returned */
267671dfc47SDavid du Colombier 	navail = gl16(p);			/* number of entries available */
268671dfc47SDavid du Colombier 
269671dfc47SDavid du Colombier 	if(err && err != RAP_ERR_MOREINFO){
270671dfc47SDavid du Colombier 		werrstr("%s", raperrstr(err));
271671dfc47SDavid du Colombier 		free(p);
272671dfc47SDavid du Colombier 		return -1;
273671dfc47SDavid du Colombier 	}
274671dfc47SDavid du Colombier 
275671dfc47SDavid du Colombier 	if(ngot == 0){
276671dfc47SDavid du Colombier 		*sip = emalloc9p(sizeof(Sessinfo) * navail);
277671dfc47SDavid du Colombier 		memset(*sip, 0, sizeof(Sessinfo) * navail);
278671dfc47SDavid du Colombier 	}
279671dfc47SDavid du Colombier 
280671dfc47SDavid du Colombier 	q = *sip + ngot;
281671dfc47SDavid du Colombier 	while(nret-- != 0){
282671dfc47SDavid du Colombier 		gconv(p, conv, tmp, sizeof tmp);
283671dfc47SDavid du Colombier 		q->wrkstn = estrdup9p(tmp);
284671dfc47SDavid du Colombier 		gconv(p, conv, tmp, sizeof tmp);
285671dfc47SDavid du Colombier 		q->user = estrdup9p(tmp);
286671dfc47SDavid du Colombier 		q->sesstime = gl32(p);
287671dfc47SDavid du Colombier 		q->idletime = gl32(p);
288671dfc47SDavid du Colombier 		ngot++;
289*912e5f54SDavid du Colombier 		q++;
290671dfc47SDavid du Colombier 	}
291671dfc47SDavid du Colombier 	if(ngot < navail)
292*912e5f54SDavid du Colombier 		fprint(2, "warning: %d/%d - session list incomplete\n", ngot, navail);
293671dfc47SDavid du Colombier 	free(p);
294671dfc47SDavid du Colombier 	return ngot;
295671dfc47SDavid du Colombier }
296671dfc47SDavid du Colombier 
297671dfc47SDavid du Colombier 
298671dfc47SDavid du Colombier int
RAPgroupenum(Session * s,Share * sp,Namelist ** nlp)299671dfc47SDavid du Colombier RAPgroupenum(Session *s, Share *sp, Namelist **nlp)
300671dfc47SDavid du Colombier {
301671dfc47SDavid du Colombier 	int ngot, err, navail, nret;
302671dfc47SDavid du Colombier 	char tmp[1024];
303671dfc47SDavid du Colombier 	Pkt *p;
304671dfc47SDavid du Colombier 	Namelist *q;
305671dfc47SDavid du Colombier 
306671dfc47SDavid du Colombier 	ngot = 0;
307671dfc47SDavid du Colombier 	p = thdr(s, sp);
308671dfc47SDavid du Colombier 	pstr(p, "\\PIPE\\LANMAN");
309671dfc47SDavid du Colombier 	ptparam(p);
310671dfc47SDavid du Colombier 
311671dfc47SDavid du Colombier 	pl16(p, API_WGroupEnum);
312671dfc47SDavid du Colombier 	pascii(p, REMSmb_NetGroupEnum_P);	/* request descriptor */
313671dfc47SDavid du Colombier 	pascii(p, REMSmb_group_info_0);		/* reply descriptor */
314671dfc47SDavid du Colombier 	pl16(p, 0);				/* detail level */
315671dfc47SDavid du Colombier 	pl16(p, MTU - 200);			/* receive buffer length */
316671dfc47SDavid du Colombier 	ptdata(p);
317671dfc47SDavid du Colombier 
318671dfc47SDavid du Colombier 	if(trpc(p) == -1){
319671dfc47SDavid du Colombier 		free(p);
320671dfc47SDavid du Colombier 		return -1;
321671dfc47SDavid du Colombier 	}
322671dfc47SDavid du Colombier 
323671dfc47SDavid du Colombier 	gtparam(p);
324671dfc47SDavid du Colombier 	err = gl16(p);				/* error code */
325671dfc47SDavid du Colombier 	gl16(p);				/* rx buffer offset */
326671dfc47SDavid du Colombier 	nret = gl16(p);				/* number of entries returned */
327671dfc47SDavid du Colombier 	navail = gl16(p);			/* number of entries available */
328671dfc47SDavid du Colombier 
329671dfc47SDavid du Colombier 	if(err && err != RAP_ERR_MOREINFO){
330671dfc47SDavid du Colombier 		werrstr("%s", raperrstr(err));
331671dfc47SDavid du Colombier 		free(p);
332671dfc47SDavid du Colombier 		return -1;
333671dfc47SDavid du Colombier 	}
334671dfc47SDavid du Colombier 
335671dfc47SDavid du Colombier 	*nlp = emalloc9p(sizeof(Namelist) * navail);
336671dfc47SDavid du Colombier 	memset(*nlp, 0, sizeof(Namelist) * navail);
337671dfc47SDavid du Colombier 
338671dfc47SDavid du Colombier 	q = *nlp + ngot;
339671dfc47SDavid du Colombier 	while(ngot < navail && nret--){
340671dfc47SDavid du Colombier  		gmem(p, tmp, 21);
341671dfc47SDavid du Colombier 		tmp[21] = 0;
342671dfc47SDavid du Colombier 		q->name = estrdup9p(tmp);
343671dfc47SDavid du Colombier 		ngot++;
344*912e5f54SDavid du Colombier 		q++;
345*912e5f54SDavid du Colombier 		if(p->pos >= p->eop)		/* Windows seems to lie somtimes */
346671dfc47SDavid du Colombier 			break;
347671dfc47SDavid du Colombier 	}
348671dfc47SDavid du Colombier 	free(p);
349671dfc47SDavid du Colombier 	return ngot;
350671dfc47SDavid du Colombier }
351671dfc47SDavid du Colombier 
352671dfc47SDavid du Colombier 
353671dfc47SDavid du Colombier int
RAPgroupusers(Session * s,Share * sp,char * group,Namelist ** nlp)354671dfc47SDavid du Colombier RAPgroupusers(Session *s, Share *sp, char *group, Namelist **nlp)
355671dfc47SDavid du Colombier {
356671dfc47SDavid du Colombier 	int ngot, err, navail, nret;
357671dfc47SDavid du Colombier 	char tmp[1024];
358671dfc47SDavid du Colombier 	Pkt *p;
359671dfc47SDavid du Colombier 	Namelist *q;
360671dfc47SDavid du Colombier 
361671dfc47SDavid du Colombier 	ngot = 0;
362671dfc47SDavid du Colombier 	p = thdr(s, sp);
363671dfc47SDavid du Colombier 	pstr(p, "\\PIPE\\LANMAN");
364671dfc47SDavid du Colombier 	ptparam(p);
365671dfc47SDavid du Colombier 
366671dfc47SDavid du Colombier 	pl16(p, API_WGroupGetUsers);
367671dfc47SDavid du Colombier 	pascii(p, REMSmb_NetGroupGetUsers_P);	/* request descriptor */
368671dfc47SDavid du Colombier 	pascii(p, REMSmb_user_info_0);		/* reply descriptor */
369671dfc47SDavid du Colombier 	pascii(p, group);			/* group name for list */
370671dfc47SDavid du Colombier 	pl16(p, 0);				/* detail level */
371671dfc47SDavid du Colombier 	pl16(p, MTU - 200);			/* receive buffer length */
372671dfc47SDavid du Colombier 	ptdata(p);
373671dfc47SDavid du Colombier 
374671dfc47SDavid du Colombier 	if(trpc(p) == -1){
375671dfc47SDavid du Colombier 		free(p);
376671dfc47SDavid du Colombier 		return -1;
377671dfc47SDavid du Colombier 	}
378671dfc47SDavid du Colombier 
379671dfc47SDavid du Colombier 	gtparam(p);
380671dfc47SDavid du Colombier 	err = gl16(p);				/* error code */
381671dfc47SDavid du Colombier 	gl16(p);				/* rx buffer offset */
382671dfc47SDavid du Colombier 	nret = gl16(p);				/* number of entries returned */
383671dfc47SDavid du Colombier 	navail = gl16(p);			/* number of entries available */
384671dfc47SDavid du Colombier 
385671dfc47SDavid du Colombier 	if(err && err != RAP_ERR_MOREINFO){
386671dfc47SDavid du Colombier 		werrstr("%s", raperrstr(err));
387671dfc47SDavid du Colombier 		free(p);
388671dfc47SDavid du Colombier 		return -1;
389671dfc47SDavid du Colombier 	}
390671dfc47SDavid du Colombier 
391671dfc47SDavid du Colombier 	*nlp = emalloc9p(sizeof(Namelist) * navail);
392671dfc47SDavid du Colombier 	memset(*nlp, 0, sizeof(Namelist) * navail);
393671dfc47SDavid du Colombier 
394671dfc47SDavid du Colombier 	q = *nlp + ngot;
395671dfc47SDavid du Colombier 	while(ngot < navail && nret--){
396671dfc47SDavid du Colombier  		gmem(p, tmp, 21);
397671dfc47SDavid du Colombier 		tmp[21] = 0;
398671dfc47SDavid du Colombier 		q->name = estrdup9p(tmp);
399671dfc47SDavid du Colombier 		ngot++;
400*912e5f54SDavid du Colombier 		q++;
401*912e5f54SDavid du Colombier 		if(p->pos >= p->eop)		/* Windows seems to lie somtimes */
402671dfc47SDavid du Colombier 			break;
403671dfc47SDavid du Colombier 	}
404671dfc47SDavid du Colombier 	free(p);
405671dfc47SDavid du Colombier 	return ngot;
406671dfc47SDavid du Colombier }
407671dfc47SDavid du Colombier 
408671dfc47SDavid du Colombier int
RAPuserenum(Session * s,Share * sp,Namelist ** nlp)409671dfc47SDavid du Colombier RAPuserenum(Session *s, Share *sp, Namelist **nlp)
410671dfc47SDavid du Colombier {
411671dfc47SDavid du Colombier 	int ngot, err, navail, nret;
412671dfc47SDavid du Colombier 	char tmp[1024];
413671dfc47SDavid du Colombier 	Pkt *p;
414671dfc47SDavid du Colombier 	Namelist *q;
415671dfc47SDavid du Colombier 
416671dfc47SDavid du Colombier 	ngot = 0;
417671dfc47SDavid du Colombier 	p = thdr(s, sp);
418671dfc47SDavid du Colombier 	pstr(p, "\\PIPE\\LANMAN");
419671dfc47SDavid du Colombier 	ptparam(p);
420671dfc47SDavid du Colombier 
421671dfc47SDavid du Colombier 	pl16(p, API_WUserEnum);
422671dfc47SDavid du Colombier 	pascii(p, REMSmb_NetUserEnum_P);	/* request descriptor */
423671dfc47SDavid du Colombier 	pascii(p, REMSmb_user_info_0);		/* reply descriptor */
424671dfc47SDavid du Colombier 	pl16(p, 0);				/* detail level */
425671dfc47SDavid du Colombier 	pl16(p, MTU - 200);			/* receive buffer length */
426671dfc47SDavid du Colombier 	ptdata(p);
427671dfc47SDavid du Colombier 
428671dfc47SDavid du Colombier 	if(trpc(p) == -1){
429671dfc47SDavid du Colombier 		free(p);
430671dfc47SDavid du Colombier 		return -1;
431671dfc47SDavid du Colombier 	}
432671dfc47SDavid du Colombier 
433671dfc47SDavid du Colombier 	gtparam(p);
434671dfc47SDavid du Colombier 	err = gl16(p);				/* error code */
435671dfc47SDavid du Colombier 	gl16(p);				/* rx buffer offset */
436671dfc47SDavid du Colombier 	nret = gl16(p);				/* number of entries returned */
437671dfc47SDavid du Colombier 	navail = gl16(p);			/* number of entries available */
438671dfc47SDavid du Colombier 
439671dfc47SDavid du Colombier 	if(err && err != RAP_ERR_MOREINFO){
440671dfc47SDavid du Colombier 		werrstr("%s", raperrstr(err));
441671dfc47SDavid du Colombier 		free(p);
442671dfc47SDavid du Colombier 		return -1;
443671dfc47SDavid du Colombier 	}
444671dfc47SDavid du Colombier 
445671dfc47SDavid du Colombier 	*nlp = emalloc9p(sizeof(Namelist) * navail);
446671dfc47SDavid du Colombier 	memset(*nlp, 0, sizeof(Namelist) * navail);
447671dfc47SDavid du Colombier 
448671dfc47SDavid du Colombier 	q = *nlp + ngot;
449671dfc47SDavid du Colombier 	while(ngot < navail && nret--){
450671dfc47SDavid du Colombier  		gmem(p, tmp, 21);
451671dfc47SDavid du Colombier 		tmp[21] = 0;
452671dfc47SDavid du Colombier 		q->name = estrdup9p(tmp);
453671dfc47SDavid du Colombier 		ngot++;
454*912e5f54SDavid du Colombier 		q++;
455*912e5f54SDavid du Colombier 		if(p->pos >= p->eop)		/* Windows seems to lie somtimes */
456671dfc47SDavid du Colombier 			break;
457671dfc47SDavid du Colombier 	}
458671dfc47SDavid du Colombier 	free(p);
459671dfc47SDavid du Colombier 	return ngot;
460671dfc47SDavid du Colombier }
461671dfc47SDavid du Colombier 
462671dfc47SDavid du Colombier int
RAPuserenum2(Session * s,Share * sp,Namelist ** nlp)463671dfc47SDavid du Colombier RAPuserenum2(Session *s, Share *sp, Namelist **nlp)
464671dfc47SDavid du Colombier {
465671dfc47SDavid du Colombier 	int ngot, resume, err, navail, nret;
466671dfc47SDavid du Colombier 	char tmp[1024];
467671dfc47SDavid du Colombier 	Pkt *p;
468671dfc47SDavid du Colombier 	Namelist *q;
469671dfc47SDavid du Colombier 
470671dfc47SDavid du Colombier 	ngot = 0;
471671dfc47SDavid du Colombier 	resume = 0;
472671dfc47SDavid du Colombier more:
473671dfc47SDavid du Colombier 	p = thdr(s, sp);
474671dfc47SDavid du Colombier 	pstr(p, "\\PIPE\\LANMAN");
475671dfc47SDavid du Colombier 	ptparam(p);
476671dfc47SDavid du Colombier 
477671dfc47SDavid du Colombier 	pl16(p, API_WUserEnum2);
478671dfc47SDavid du Colombier 	pascii(p, REMSmb_NetUserEnum2_P);	/* request descriptor */
479671dfc47SDavid du Colombier 	pascii(p, REMSmb_user_info_0);		/* reply descriptor */
480671dfc47SDavid du Colombier 	pl16(p, 0);				/* detail level */
481671dfc47SDavid du Colombier 	pl16(p, MTU - 200);			/* receive buffer length */
482671dfc47SDavid du Colombier 	pl32(p, resume);			/* resume key to allow multiple fetches */
483671dfc47SDavid du Colombier 	ptdata(p);
484671dfc47SDavid du Colombier 
485671dfc47SDavid du Colombier 	if(trpc(p) == -1){
486671dfc47SDavid du Colombier 		free(p);
487671dfc47SDavid du Colombier 		return -1;
488671dfc47SDavid du Colombier 	}
489671dfc47SDavid du Colombier 
490671dfc47SDavid du Colombier 	gtparam(p);
491671dfc47SDavid du Colombier 	err = gl16(p);				/* error code */
492671dfc47SDavid du Colombier 	gl16(p);				/* rx buffer offset */
493671dfc47SDavid du Colombier 	resume = gl32(p);			/* resume key returned */
494671dfc47SDavid du Colombier 	nret = gl16(p);				/* number of entries returned */
495671dfc47SDavid du Colombier 	navail = gl16(p);			/* number of entries available */
496671dfc47SDavid du Colombier 
497671dfc47SDavid du Colombier 	if(err && err != RAP_ERR_MOREINFO){
498671dfc47SDavid du Colombier 		werrstr("%s", raperrstr(err));
499671dfc47SDavid du Colombier 		free(p);
500671dfc47SDavid du Colombier 		return -1;
501671dfc47SDavid du Colombier 	}
502671dfc47SDavid du Colombier 
503671dfc47SDavid du Colombier 	if(ngot == 0){
504671dfc47SDavid du Colombier 		*nlp = emalloc9p(sizeof(Namelist) * navail);
505671dfc47SDavid du Colombier 		memset(*nlp, 0, sizeof(Namelist) * navail);
506671dfc47SDavid du Colombier 	}
507671dfc47SDavid du Colombier 	q = *nlp + ngot;
508671dfc47SDavid du Colombier 	while(ngot < navail && nret--){
509671dfc47SDavid du Colombier  		gmem(p, tmp, 21);
510671dfc47SDavid du Colombier 		tmp[21] = 0;
511671dfc47SDavid du Colombier 		q->name = estrdup9p(tmp);
512671dfc47SDavid du Colombier 		ngot++;
513*912e5f54SDavid du Colombier 		q++;
514*912e5f54SDavid du Colombier 		if(p->pos >= p->eop)		/* Windows seems to lie somtimes */
515671dfc47SDavid du Colombier 			break;
516671dfc47SDavid du Colombier 	}
517671dfc47SDavid du Colombier 	free(p);
518671dfc47SDavid du Colombier 	if(ngot < navail)
519671dfc47SDavid du Colombier 		goto more;
520671dfc47SDavid du Colombier 	return ngot;
521671dfc47SDavid du Colombier }
522671dfc47SDavid du Colombier 
523671dfc47SDavid du Colombier int
RAPuserinfo(Session * s,Share * sp,char * user,Userinfo * uip)524671dfc47SDavid du Colombier RAPuserinfo(Session *s, Share *sp, char *user, Userinfo *uip)
525671dfc47SDavid du Colombier {
526671dfc47SDavid du Colombier 	int conv, err;
527671dfc47SDavid du Colombier 	char tmp[1024];
528671dfc47SDavid du Colombier 	Pkt *p;
529671dfc47SDavid du Colombier 
530671dfc47SDavid du Colombier 	p = thdr(s, sp);
531671dfc47SDavid du Colombier 	pstr(p, "\\PIPE\\LANMAN");
532671dfc47SDavid du Colombier 	ptparam(p);
533671dfc47SDavid du Colombier 
534671dfc47SDavid du Colombier 	pl16(p, API_WUserGetInfo);
535671dfc47SDavid du Colombier 	pascii(p, REMSmb_NetUserGetInfo_P);	/* request descriptor */
536671dfc47SDavid du Colombier 	pascii(p, REMSmb_user_info_10);		/* reply descriptor */
537671dfc47SDavid du Colombier 	pascii(p, user);			/* username */
538671dfc47SDavid du Colombier 	pl16(p, 10);				/* detail level */
539671dfc47SDavid du Colombier 	pl16(p, MTU - 200);			/* receive buffer length */
540671dfc47SDavid du Colombier 	ptdata(p);
541671dfc47SDavid du Colombier 
542671dfc47SDavid du Colombier 	if(trpc(p) == -1){
543671dfc47SDavid du Colombier 		free(p);
544671dfc47SDavid du Colombier 		return -1;
545671dfc47SDavid du Colombier 	}
546671dfc47SDavid du Colombier 
547671dfc47SDavid du Colombier 	gtparam(p);
548671dfc47SDavid du Colombier 	err = gl16(p);				/* error code */
549671dfc47SDavid du Colombier 	conv = gl16(p);				/* rx buffer offset */
550671dfc47SDavid du Colombier 	gl16(p);				/* number of entries returned */
551671dfc47SDavid du Colombier 	gl16(p);				/* number of entries available */
552671dfc47SDavid du Colombier 
553671dfc47SDavid du Colombier 	if(err && err != RAP_ERR_MOREINFO){
554671dfc47SDavid du Colombier 		werrstr("%s", raperrstr(err));
555671dfc47SDavid du Colombier 		free(p);
556671dfc47SDavid du Colombier 		return -1;
557671dfc47SDavid du Colombier 	}
558671dfc47SDavid du Colombier 
559671dfc47SDavid du Colombier  	gmem(p, tmp, 21);
560671dfc47SDavid du Colombier 	tmp[21] = 0;
561671dfc47SDavid du Colombier 	uip->user = estrdup9p(tmp);
562671dfc47SDavid du Colombier 	g8(p);				/* padding */
563671dfc47SDavid du Colombier 	gconv(p, conv, tmp, sizeof tmp);
564671dfc47SDavid du Colombier 	uip->comment = estrdup9p(tmp);
565671dfc47SDavid du Colombier 	gconv(p, conv, tmp, sizeof tmp);
566671dfc47SDavid du Colombier 	uip->user_comment = estrdup9p(tmp);
567671dfc47SDavid du Colombier 	gconv(p, conv, tmp, sizeof tmp);
568671dfc47SDavid du Colombier 	uip->fullname = estrdup9p(tmp);
569671dfc47SDavid du Colombier 
570671dfc47SDavid du Colombier 	free(p);
571671dfc47SDavid du Colombier 	return 0;
572671dfc47SDavid du Colombier }
573671dfc47SDavid du Colombier 
574671dfc47SDavid du Colombier /*
575671dfc47SDavid du Colombier  * This works agains win2k3 but fails
576671dfc47SDavid du Colombier  * against XP with the undocumented error 71/0x47
577671dfc47SDavid du Colombier  */
578671dfc47SDavid du Colombier int
RAPServerenum2(Session * s,Share * sp,char * workgroup,int type,int * more,Serverinfo ** si)579671dfc47SDavid du Colombier RAPServerenum2(Session *s, Share *sp, char *workgroup, int type, int *more,
580671dfc47SDavid du Colombier 	Serverinfo **si)
581671dfc47SDavid du Colombier {
582671dfc47SDavid du Colombier 	int ngot = 0, conv, err, nret, navail;
583671dfc47SDavid du Colombier 	char tmp[1024];
584671dfc47SDavid du Colombier 	Pkt *p;
585671dfc47SDavid du Colombier 	Serverinfo *q;
586671dfc47SDavid du Colombier 
587671dfc47SDavid du Colombier 	p = thdr(s, sp);
588671dfc47SDavid du Colombier 	pstr(p, "\\PIPE\\LANMAN");
589671dfc47SDavid du Colombier 
590671dfc47SDavid du Colombier 	ptparam(p);
591671dfc47SDavid du Colombier 	pl16(p, API_NetServerEnum2);
592671dfc47SDavid du Colombier 	pascii(p, REMSmb_NetServerEnum2_P);	/* request descriptor */
593671dfc47SDavid du Colombier 	pascii(p, REMSmb_server_info_1);	/* reply descriptor */
594671dfc47SDavid du Colombier 	pl16(p, 1);				/* detail level */
595671dfc47SDavid du Colombier 	pl16(p, MTU - 200);			/* receive buffer length */
596671dfc47SDavid du Colombier 	pl32(p, type);
597671dfc47SDavid du Colombier 	pascii(p, workgroup);
598671dfc47SDavid du Colombier 
599671dfc47SDavid du Colombier 	ptdata(p);
600671dfc47SDavid du Colombier 
601671dfc47SDavid du Colombier 	if(trpc(p) == -1){
602671dfc47SDavid du Colombier 		free(p);
603671dfc47SDavid du Colombier 		return -1;
604671dfc47SDavid du Colombier 	}
605671dfc47SDavid du Colombier 
606671dfc47SDavid du Colombier 	gtparam(p);
607671dfc47SDavid du Colombier 	err = gl16(p);				/* error code */
608671dfc47SDavid du Colombier 	conv = gl16(p);				/* rx buffer offset */
609671dfc47SDavid du Colombier 	nret = gl16(p);				/* number of entries returned */
610671dfc47SDavid du Colombier 	navail = gl16(p);			/* number of entries available */
611671dfc47SDavid du Colombier 
612671dfc47SDavid du Colombier 	if(err && err != RAP_ERR_MOREINFO){
613671dfc47SDavid du Colombier 		werrstr("%s", raperrstr(err));
614671dfc47SDavid du Colombier 		free(p);
615671dfc47SDavid du Colombier 		return -1;
616671dfc47SDavid du Colombier 	}
617671dfc47SDavid du Colombier 
618671dfc47SDavid du Colombier 	*si = emalloc9p(sizeof(Serverinfo) * navail);
619671dfc47SDavid du Colombier 	memset(*si, 0, sizeof(Serverinfo) * navail);
620671dfc47SDavid du Colombier 
621671dfc47SDavid du Colombier 	q = *si;
622671dfc47SDavid du Colombier 	for (; nret-- != 0 && ngot < navail; ngot++){
623671dfc47SDavid du Colombier 		gmem(p, tmp, 16);
624671dfc47SDavid du Colombier 		tmp[16] = 0;
625671dfc47SDavid du Colombier 		q->name = estrdup9p(tmp);
626671dfc47SDavid du Colombier 		q->major = g8(p);
627671dfc47SDavid du Colombier 		q->minor = g8(p);
628671dfc47SDavid du Colombier 		q->type = gl32(p);
629671dfc47SDavid du Colombier 		gconv(p, conv, tmp, sizeof tmp);
630671dfc47SDavid du Colombier 		q->comment = estrdup9p(tmp);
631671dfc47SDavid du Colombier 		q++;
632671dfc47SDavid du Colombier 	}
633671dfc47SDavid du Colombier 	free(p);
634671dfc47SDavid du Colombier 	*more = err == RAP_ERR_MOREINFO;
635671dfc47SDavid du Colombier 	return ngot;
636671dfc47SDavid du Colombier }
637671dfc47SDavid du Colombier 
638671dfc47SDavid du Colombier int
RAPServerenum3(Session * s,Share * sp,char * workgroup,int type,int last,Serverinfo * si)639671dfc47SDavid du Colombier RAPServerenum3(Session *s, Share *sp, char *workgroup, int type, int last,
640671dfc47SDavid du Colombier 	Serverinfo *si)
641671dfc47SDavid du Colombier {
642671dfc47SDavid du Colombier 	int conv, err, ngot, nret, navail;
643671dfc47SDavid du Colombier 	char *first, tmp[1024];
644671dfc47SDavid du Colombier 	Pkt *p;
645671dfc47SDavid du Colombier 	Serverinfo *q;
646671dfc47SDavid du Colombier 
647671dfc47SDavid du Colombier 	ngot = last +1;
648671dfc47SDavid du Colombier 	first = si[last].name;
649671dfc47SDavid du Colombier more:
650671dfc47SDavid du Colombier 	p = thdr(s, sp);
651671dfc47SDavid du Colombier 	pstr(p, "\\PIPE\\LANMAN");
652671dfc47SDavid du Colombier 
653671dfc47SDavid du Colombier 	ptparam(p);
654671dfc47SDavid du Colombier 	pl16(p, API_NetServerEnum3);
655671dfc47SDavid du Colombier 	pascii(p, REMSmb_NetServerEnum3_P);	/* request descriptor */
656671dfc47SDavid du Colombier 	pascii(p, REMSmb_server_info_1);	/* reply descriptor */
657671dfc47SDavid du Colombier 	pl16(p, 1);				/* detail level */
658671dfc47SDavid du Colombier 	pl16(p, MTU - 200);			/* receive buffer length */
659671dfc47SDavid du Colombier 	pl32(p, type);
660671dfc47SDavid du Colombier 	pascii(p, workgroup);
661671dfc47SDavid du Colombier 	pascii(p, first);
662671dfc47SDavid du Colombier 
663671dfc47SDavid du Colombier 	ptdata(p);
664671dfc47SDavid du Colombier 
665671dfc47SDavid du Colombier 	if(trpc(p) == -1){
666671dfc47SDavid du Colombier 		free(p);
667671dfc47SDavid du Colombier 		return -1;
668671dfc47SDavid du Colombier 	}
669671dfc47SDavid du Colombier 
670671dfc47SDavid du Colombier 	gtparam(p);
671671dfc47SDavid du Colombier 	err = gl16(p);				/* error code */
672671dfc47SDavid du Colombier 	conv = gl16(p);				/* rx buffer offset */
673671dfc47SDavid du Colombier 	nret = gl16(p);				/* number of entries returned */
674671dfc47SDavid du Colombier 	navail = gl16(p);			/* number of entries available */
675671dfc47SDavid du Colombier 
676671dfc47SDavid du Colombier 	if(err && err != RAP_ERR_MOREINFO){
677671dfc47SDavid du Colombier 		werrstr("%s", raperrstr(err));
678671dfc47SDavid du Colombier 		free(p);
679671dfc47SDavid du Colombier 		return -1;
680671dfc47SDavid du Colombier 	}
681671dfc47SDavid du Colombier 
682671dfc47SDavid du Colombier 	if(nret < 2){				/* paranoia */
683671dfc47SDavid du Colombier 		free(p);
684671dfc47SDavid du Colombier 		return ngot;
685671dfc47SDavid du Colombier 	}
686671dfc47SDavid du Colombier 
687671dfc47SDavid du Colombier 	q = si+ngot;
688671dfc47SDavid du Colombier 	while(nret-- != 0 && ngot < navail){
689671dfc47SDavid du Colombier 		gmem(p, tmp, 16);
690671dfc47SDavid du Colombier 		tmp[16] = 0;
691671dfc47SDavid du Colombier 		q->name = estrdup9p(tmp);
692671dfc47SDavid du Colombier 		q->major = g8(p);
693671dfc47SDavid du Colombier 		q->minor = g8(p);
694671dfc47SDavid du Colombier 		q->type = gl32(p);
695671dfc47SDavid du Colombier 		gconv(p, conv, tmp, sizeof tmp);
696671dfc47SDavid du Colombier 		tmp[sizeof tmp - 1] = 0;
697671dfc47SDavid du Colombier 		q->comment = estrdup9p(tmp);
698671dfc47SDavid du Colombier 		if(strcmp(first, tmp) == 0){ /* 1st one thru _may_ be a repeat */
699671dfc47SDavid du Colombier 			free(q->name);
700671dfc47SDavid du Colombier 			free(q->comment);
701671dfc47SDavid du Colombier 			continue;
702671dfc47SDavid du Colombier 		}
703671dfc47SDavid du Colombier 		ngot++;
704*912e5f54SDavid du Colombier 		q++;
705671dfc47SDavid du Colombier 	}
706671dfc47SDavid du Colombier 	free(p);
707671dfc47SDavid du Colombier 	if(ngot < navail)
708671dfc47SDavid du Colombier 		goto more;
709671dfc47SDavid du Colombier 	return ngot;
710671dfc47SDavid du Colombier }
711671dfc47SDavid du Colombier 
712671dfc47SDavid du Colombier /* Only the Administrator has permission to do this */
713671dfc47SDavid du Colombier int
RAPFileenum2(Session * s,Share * sp,char * user,char * path,Fileinfo ** fip)714671dfc47SDavid du Colombier RAPFileenum2(Session *s, Share *sp, char *user, char *path, Fileinfo **fip)
715671dfc47SDavid du Colombier {
716671dfc47SDavid du Colombier 	int conv, err, ngot, resume, nret, navail;
717671dfc47SDavid du Colombier 	char tmp[1024];
718671dfc47SDavid du Colombier 	Pkt *p;
719671dfc47SDavid du Colombier 	Fileinfo *q;
720671dfc47SDavid du Colombier 
721671dfc47SDavid du Colombier 	ngot = 0;
722671dfc47SDavid du Colombier 	resume = 0;
723671dfc47SDavid du Colombier more:
724671dfc47SDavid du Colombier 	p = thdr(s, sp);
725671dfc47SDavid du Colombier 	pstr(p, "\\PIPE\\LANMAN");
726671dfc47SDavid du Colombier 
727671dfc47SDavid du Colombier 	ptparam(p);
728671dfc47SDavid du Colombier 	pl16(p, API_WFileEnum2);
729671dfc47SDavid du Colombier 	pascii(p, REMSmb_NetFileEnum2_P);	/* request descriptor */
730*912e5f54SDavid du Colombier 	pascii(p, REMSmb_file_info_1);		/* reply descriptor */
731671dfc47SDavid du Colombier 	pascii(p, path);
732671dfc47SDavid du Colombier 	pascii(p, user);
733*912e5f54SDavid du Colombier 	pl16(p, 1);				/* detail level */
734671dfc47SDavid du Colombier 	pl16(p, MTU - 200);			/* receive buffer length */
735671dfc47SDavid du Colombier 	pl32(p, resume);			/* resume key */
736671dfc47SDavid du Colombier /* FIXME: maybe the padding and resume key are the wrong way around? */
737671dfc47SDavid du Colombier 	pl32(p, 0);				/* padding ? */
738671dfc47SDavid du Colombier 
739671dfc47SDavid du Colombier 	ptdata(p);
740671dfc47SDavid du Colombier 
741671dfc47SDavid du Colombier 	if(trpc(p) == -1){
742671dfc47SDavid du Colombier 		free(p);
743671dfc47SDavid du Colombier 		return -1;
744671dfc47SDavid du Colombier 	}
745671dfc47SDavid du Colombier 
746671dfc47SDavid du Colombier 	gtparam(p);
747671dfc47SDavid du Colombier 	err = gl16(p);				/* error code */
748671dfc47SDavid du Colombier 	conv = gl16(p);				/* rx buffer offset */
749671dfc47SDavid du Colombier 	resume = gl32(p);			/* resume key returned */
750671dfc47SDavid du Colombier 	nret = gl16(p);				/* number of entries returned */
751671dfc47SDavid du Colombier 	navail = gl16(p);			/* number of entries available */
752671dfc47SDavid du Colombier 
753671dfc47SDavid du Colombier 	if(err && err != RAP_ERR_MOREINFO){
754671dfc47SDavid du Colombier 		werrstr("%s", raperrstr(err));
755671dfc47SDavid du Colombier 		free(p);
756671dfc47SDavid du Colombier 		return -1;
757671dfc47SDavid du Colombier 	}
758671dfc47SDavid du Colombier 
759671dfc47SDavid du Colombier 	if(nret < 2){				/* paranoia */
760671dfc47SDavid du Colombier 		free(p);
761671dfc47SDavid du Colombier 		return ngot;
762671dfc47SDavid du Colombier 	}
763671dfc47SDavid du Colombier 
764671dfc47SDavid du Colombier 	if(ngot == 0){
765671dfc47SDavid du Colombier 		*fip = emalloc9p(sizeof(Fileinfo) * navail);
766671dfc47SDavid du Colombier 		memset(*fip, 0, sizeof(Fileinfo) * navail);
767671dfc47SDavid du Colombier 	}
768671dfc47SDavid du Colombier 	q = *fip + ngot;
769671dfc47SDavid du Colombier 	for(; nret-- && ngot < navail; ngot++){
770671dfc47SDavid du Colombier 		q->ident = gl16(p);
771671dfc47SDavid du Colombier 		q->perms = gl16(p);
772671dfc47SDavid du Colombier 		q->locks = gl16(p);
773671dfc47SDavid du Colombier 		gconv(p, conv, tmp, sizeof tmp);
774671dfc47SDavid du Colombier 		tmp[sizeof tmp - 1] = 0;
775671dfc47SDavid du Colombier 		q->path = estrdup9p(tmp);
776671dfc47SDavid du Colombier 		gconv(p, conv, tmp, sizeof tmp);
777671dfc47SDavid du Colombier 		tmp[sizeof tmp - 1] = 0;
778671dfc47SDavid du Colombier 		q->user = estrdup9p(tmp);
779671dfc47SDavid du Colombier 		q++;
780671dfc47SDavid du Colombier 	}
781671dfc47SDavid du Colombier 	free(p);
782671dfc47SDavid du Colombier 	if(ngot < navail)
783671dfc47SDavid du Colombier 		goto more;
784671dfc47SDavid du Colombier 	return ngot;
785671dfc47SDavid du Colombier }
786