xref: /freebsd/contrib/smbfs/lib/smb/rap.c (revision 7d475e356f0ac58a291132b1086c50a1eaf9c65b)
1f1b9d127SSheldon Hearn /*
2f1b9d127SSheldon Hearn  * Copyright (c) 2000, Boris Popov
3f1b9d127SSheldon Hearn  * All rights reserved.
4f1b9d127SSheldon Hearn  *
5f1b9d127SSheldon Hearn  * Redistribution and use in source and binary forms, with or without
6f1b9d127SSheldon Hearn  * modification, are permitted provided that the following conditions
7f1b9d127SSheldon Hearn  * are met:
8f1b9d127SSheldon Hearn  * 1. Redistributions of source code must retain the above copyright
9f1b9d127SSheldon Hearn  *    notice, this list of conditions and the following disclaimer.
10f1b9d127SSheldon Hearn  * 2. Redistributions in binary form must reproduce the above copyright
11f1b9d127SSheldon Hearn  *    notice, this list of conditions and the following disclaimer in the
12f1b9d127SSheldon Hearn  *    documentation and/or other materials provided with the distribution.
13f1b9d127SSheldon Hearn  * 3. All advertising materials mentioning features or use of this software
14f1b9d127SSheldon Hearn  *    must display the following acknowledgement:
15f1b9d127SSheldon Hearn  *    This product includes software developed by Boris Popov.
16f1b9d127SSheldon Hearn  * 4. Neither the name of the author nor the names of any co-contributors
17f1b9d127SSheldon Hearn  *    may be used to endorse or promote products derived from this software
18f1b9d127SSheldon Hearn  *    without specific prior written permission.
19f1b9d127SSheldon Hearn  *
20f1b9d127SSheldon Hearn  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21f1b9d127SSheldon Hearn  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22f1b9d127SSheldon Hearn  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23f1b9d127SSheldon Hearn  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24f1b9d127SSheldon Hearn  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25f1b9d127SSheldon Hearn  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26f1b9d127SSheldon Hearn  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27f1b9d127SSheldon Hearn  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28f1b9d127SSheldon Hearn  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29f1b9d127SSheldon Hearn  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30f1b9d127SSheldon Hearn  * SUCH DAMAGE.
31f1b9d127SSheldon Hearn  *
32f1b9d127SSheldon Hearn  * $Id: rap.c,v 1.8 2001/02/24 15:56:05 bp Exp $
3326c4b7deSPeter Wemm  * $FreeBSD$
34f1b9d127SSheldon Hearn  *
35f1b9d127SSheldon Hearn  * This is very simple implementation of RAP protocol.
36f1b9d127SSheldon Hearn  */
37f1b9d127SSheldon Hearn #include <sys/param.h>
38f1b9d127SSheldon Hearn #include <sys/errno.h>
39f1b9d127SSheldon Hearn #include <sys/stat.h>
40f1b9d127SSheldon Hearn #include <ctype.h>
41f1b9d127SSheldon Hearn #include <err.h>
42f1b9d127SSheldon Hearn #include <stdio.h>
43f1b9d127SSheldon Hearn #include <unistd.h>
4426c4b7deSPeter Wemm #include <string.h>
45f1b9d127SSheldon Hearn #include <stdlib.h>
46f1b9d127SSheldon Hearn #include <sysexits.h>
47f1b9d127SSheldon Hearn 
48f1b9d127SSheldon Hearn #include <sys/mchain.h>
49f1b9d127SSheldon Hearn 
50f1b9d127SSheldon Hearn #include <netsmb/smb_lib.h>
51f1b9d127SSheldon Hearn #include <netsmb/smb_conn.h>
52f1b9d127SSheldon Hearn #include <netsmb/smb_rap.h>
53f1b9d127SSheldon Hearn 
54f1b9d127SSheldon Hearn /*#include <sys/ioctl.h>*/
55f1b9d127SSheldon Hearn 
56f1b9d127SSheldon Hearn static int
57f1b9d127SSheldon Hearn smb_rap_parserqparam(const char *s, char **next, int *rlen)
58f1b9d127SSheldon Hearn {
59f1b9d127SSheldon Hearn 	char *np;
60f1b9d127SSheldon Hearn 	int len, m;
61f1b9d127SSheldon Hearn 
62f1b9d127SSheldon Hearn 	m = 1;
63f1b9d127SSheldon Hearn 	switch (*s++) {
64f1b9d127SSheldon Hearn 	    case 'L':
65f1b9d127SSheldon Hearn 	    case 'T':
66f1b9d127SSheldon Hearn 	    case 'W':
67f1b9d127SSheldon Hearn 		len = 2;
68f1b9d127SSheldon Hearn 		break;
69f1b9d127SSheldon Hearn 	    case 'D':
70f1b9d127SSheldon Hearn 	    case 'O':
71f1b9d127SSheldon Hearn 		len = 4;
72f1b9d127SSheldon Hearn 		break;
73f1b9d127SSheldon Hearn 	    case 'b':
74f1b9d127SSheldon Hearn 	    case 'F':
75f1b9d127SSheldon Hearn 		len = 1;
76f1b9d127SSheldon Hearn 		break;
77f1b9d127SSheldon Hearn 	    case 'r':
78f1b9d127SSheldon Hearn 	    case 's':
79f1b9d127SSheldon Hearn 		len = 0;
80f1b9d127SSheldon Hearn 		break;
81f1b9d127SSheldon Hearn 	    default:
82f1b9d127SSheldon Hearn 		return EINVAL;
83f1b9d127SSheldon Hearn 	}
84f1b9d127SSheldon Hearn 	if (isdigit(*s)) {
85f1b9d127SSheldon Hearn 		len *= strtoul(s, &np, 10);
86f1b9d127SSheldon Hearn 		s = np;
87f1b9d127SSheldon Hearn 	}
88f1b9d127SSheldon Hearn 	*rlen = len;
89f1b9d127SSheldon Hearn 	*(const char**)next = s;
90f1b9d127SSheldon Hearn 	return 0;
91f1b9d127SSheldon Hearn }
92f1b9d127SSheldon Hearn 
93f1b9d127SSheldon Hearn static int
94f1b9d127SSheldon Hearn smb_rap_parserpparam(const char *s, char **next, int *rlen)
95f1b9d127SSheldon Hearn {
96f1b9d127SSheldon Hearn 	char *np;
97f1b9d127SSheldon Hearn 	int len, m;
98f1b9d127SSheldon Hearn 
99f1b9d127SSheldon Hearn 	m = 1;
100f1b9d127SSheldon Hearn 	switch (*s++) {
101f1b9d127SSheldon Hearn 	    case 'e':
102f1b9d127SSheldon Hearn 	    case 'h':
103f1b9d127SSheldon Hearn 		len = 2;
104f1b9d127SSheldon Hearn 		break;
105f1b9d127SSheldon Hearn 	    case 'i':
106f1b9d127SSheldon Hearn 		len = 4;
107f1b9d127SSheldon Hearn 		break;
108f1b9d127SSheldon Hearn 	    case 'g':
109f1b9d127SSheldon Hearn 		len = 1;
110f1b9d127SSheldon Hearn 		break;
111f1b9d127SSheldon Hearn 	    default:
112f1b9d127SSheldon Hearn 		return EINVAL;
113f1b9d127SSheldon Hearn 	}
114f1b9d127SSheldon Hearn 	if (isdigit(*s)) {
115f1b9d127SSheldon Hearn 		len *= strtoul(s, &np, 10);
116f1b9d127SSheldon Hearn 		s = np;
117f1b9d127SSheldon Hearn 	}
118f1b9d127SSheldon Hearn 	*rlen = len;
119f1b9d127SSheldon Hearn 	*(const char**)next = s;
120f1b9d127SSheldon Hearn 	return 0;
121f1b9d127SSheldon Hearn }
122f1b9d127SSheldon Hearn 
123f1b9d127SSheldon Hearn static int
124f1b9d127SSheldon Hearn smb_rap_parserpdata(const char *s, char **next, int *rlen)
125f1b9d127SSheldon Hearn {
126f1b9d127SSheldon Hearn 	char *np;
127f1b9d127SSheldon Hearn 	int len, m;
128f1b9d127SSheldon Hearn 
129f1b9d127SSheldon Hearn 	m = 1;
130f1b9d127SSheldon Hearn 	switch (*s++) {
131f1b9d127SSheldon Hearn 	    case 'B':
132f1b9d127SSheldon Hearn 		len = 1;
133f1b9d127SSheldon Hearn 		break;
134f1b9d127SSheldon Hearn 	    case 'W':
135f1b9d127SSheldon Hearn 		len = 2;
136f1b9d127SSheldon Hearn 		break;
137f1b9d127SSheldon Hearn 	    case 'D':
138f1b9d127SSheldon Hearn 	    case 'O':
139f1b9d127SSheldon Hearn 	    case 'z':
140f1b9d127SSheldon Hearn 		len = 4;
141f1b9d127SSheldon Hearn 		break;
142f1b9d127SSheldon Hearn 	    default:
143f1b9d127SSheldon Hearn 		return EINVAL;
144f1b9d127SSheldon Hearn 	}
145f1b9d127SSheldon Hearn 	if (isdigit(*s)) {
146f1b9d127SSheldon Hearn 		len *= strtoul(s, &np, 10);
147f1b9d127SSheldon Hearn 		s = np;
148f1b9d127SSheldon Hearn 	}
149f1b9d127SSheldon Hearn 	*rlen = len;
150f1b9d127SSheldon Hearn 	*(const char**)next = s;
151f1b9d127SSheldon Hearn 	return 0;
152f1b9d127SSheldon Hearn }
153f1b9d127SSheldon Hearn 
154f1b9d127SSheldon Hearn static int
155f1b9d127SSheldon Hearn smb_rap_rqparam_z(struct smb_rap *rap, const char *value)
156f1b9d127SSheldon Hearn {
157f1b9d127SSheldon Hearn 	int len = strlen(value) + 1;
158f1b9d127SSheldon Hearn 
159f1b9d127SSheldon Hearn 	bcopy(value, rap->r_npbuf, len);
160f1b9d127SSheldon Hearn 	rap->r_npbuf += len;
161f1b9d127SSheldon Hearn 	rap->r_plen += len;
162f1b9d127SSheldon Hearn 	return 0;
163f1b9d127SSheldon Hearn }
164f1b9d127SSheldon Hearn 
165f1b9d127SSheldon Hearn static int
166f1b9d127SSheldon Hearn smb_rap_rqparam(struct smb_rap *rap, char ptype, char plen, long value)
167f1b9d127SSheldon Hearn {
168f1b9d127SSheldon Hearn 	char *p = rap->r_npbuf;
169f1b9d127SSheldon Hearn 	int len;
170f1b9d127SSheldon Hearn 
171f1b9d127SSheldon Hearn 	switch (ptype) {
172f1b9d127SSheldon Hearn 	    case 'L':
173f1b9d127SSheldon Hearn 	    case 'W':
174f1b9d127SSheldon Hearn 		setwle(p, 0, value);
175f1b9d127SSheldon Hearn 		len = 2;
176f1b9d127SSheldon Hearn 		break;
177f1b9d127SSheldon Hearn 	    case 'D':
178f1b9d127SSheldon Hearn 		setdle(p, 0, value);
179f1b9d127SSheldon Hearn 		len = 4;
180f1b9d127SSheldon Hearn 		break;
181f1b9d127SSheldon Hearn 	    case 'b':
182f1b9d127SSheldon Hearn 		memset(p, value, plen);
183f1b9d127SSheldon Hearn 		len = plen;
184f1b9d127SSheldon Hearn 	    default:
185f1b9d127SSheldon Hearn 		return EINVAL;
186f1b9d127SSheldon Hearn 	}
187f1b9d127SSheldon Hearn 	rap->r_npbuf += len;
188f1b9d127SSheldon Hearn 	rap->r_plen += len;
189f1b9d127SSheldon Hearn 	return 0;
190f1b9d127SSheldon Hearn }
191f1b9d127SSheldon Hearn 
192f1b9d127SSheldon Hearn int
193f1b9d127SSheldon Hearn smb_rap_create(int fn, const char *param, const char *data,
194f1b9d127SSheldon Hearn 	struct smb_rap **rapp)
195f1b9d127SSheldon Hearn {
196f1b9d127SSheldon Hearn 	struct smb_rap *rap;
197f1b9d127SSheldon Hearn 	char *p;
198f1b9d127SSheldon Hearn 	int plen, len;
199f1b9d127SSheldon Hearn 
200f1b9d127SSheldon Hearn 	rap = malloc(sizeof(*rap));
201f1b9d127SSheldon Hearn 	if (rap == NULL)
2027d475e35SLukas Ertl 		return ENOMEM;
203f1b9d127SSheldon Hearn 	bzero(rap, sizeof(*rap));
204f1b9d127SSheldon Hearn 	p = rap->r_sparam = rap->r_nparam = strdup(param);
205f1b9d127SSheldon Hearn 	rap->r_sdata = rap->r_ndata = strdup(data);
206f1b9d127SSheldon Hearn 	/*
207f1b9d127SSheldon Hearn 	 * Calculate length of request parameter block
208f1b9d127SSheldon Hearn 	 */
209f1b9d127SSheldon Hearn 	len = 2 + strlen(param) + 1 + strlen(data) + 1;
210f1b9d127SSheldon Hearn 
211f1b9d127SSheldon Hearn 	while (*p) {
212f1b9d127SSheldon Hearn 		if (smb_rap_parserqparam(p, &p, &plen) != 0)
213f1b9d127SSheldon Hearn 			break;
214f1b9d127SSheldon Hearn 		len += plen;
215f1b9d127SSheldon Hearn 	}
216f1b9d127SSheldon Hearn 	rap->r_pbuf = rap->r_npbuf = malloc(len);
217f1b9d127SSheldon Hearn 	smb_rap_rqparam(rap, 'W', 1, fn);
218f1b9d127SSheldon Hearn 	smb_rap_rqparam_z(rap, rap->r_sparam);
219f1b9d127SSheldon Hearn 	smb_rap_rqparam_z(rap, rap->r_sdata);
220f1b9d127SSheldon Hearn 	*rapp = rap;
221f1b9d127SSheldon Hearn 	return 0;
222f1b9d127SSheldon Hearn }
223f1b9d127SSheldon Hearn 
224f1b9d127SSheldon Hearn void
225f1b9d127SSheldon Hearn smb_rap_done(struct smb_rap *rap)
226f1b9d127SSheldon Hearn {
227f1b9d127SSheldon Hearn 	if (rap->r_sparam)
228f1b9d127SSheldon Hearn 		free(rap->r_sparam);
229f1b9d127SSheldon Hearn 	if (rap->r_sdata)
230f1b9d127SSheldon Hearn 		free(rap->r_sdata);
231f1b9d127SSheldon Hearn 	free(rap);
232f1b9d127SSheldon Hearn }
233f1b9d127SSheldon Hearn 
234f1b9d127SSheldon Hearn int
235f1b9d127SSheldon Hearn smb_rap_setNparam(struct smb_rap *rap, long value)
236f1b9d127SSheldon Hearn {
237f1b9d127SSheldon Hearn 	char *p = rap->r_nparam;
238f1b9d127SSheldon Hearn 	char ptype = *p;
239f1b9d127SSheldon Hearn 	int error, plen;
240f1b9d127SSheldon Hearn 
241f1b9d127SSheldon Hearn 	error = smb_rap_parserqparam(p, &p, &plen);
242f1b9d127SSheldon Hearn 	if (error)
243f1b9d127SSheldon Hearn 		return error;
244f1b9d127SSheldon Hearn 	switch (ptype) {
245f1b9d127SSheldon Hearn 	    case 'L':
246f1b9d127SSheldon Hearn 		rap->r_rcvbuflen = value;
247f1b9d127SSheldon Hearn 		/* FALLTHROUGH */
248f1b9d127SSheldon Hearn 	    case 'W':
249f1b9d127SSheldon Hearn 	    case 'D':
250f1b9d127SSheldon Hearn 	    case 'b':
251f1b9d127SSheldon Hearn 		error = smb_rap_rqparam(rap, ptype, plen, value);
252f1b9d127SSheldon Hearn 		break;
253f1b9d127SSheldon Hearn 	    default:
254f1b9d127SSheldon Hearn 		return EINVAL;
255f1b9d127SSheldon Hearn 	}
256f1b9d127SSheldon Hearn 	rap->r_nparam = p;
257f1b9d127SSheldon Hearn 	return 0;
258f1b9d127SSheldon Hearn }
259f1b9d127SSheldon Hearn 
260f1b9d127SSheldon Hearn int
261f1b9d127SSheldon Hearn smb_rap_setPparam(struct smb_rap *rap, void *value)
262f1b9d127SSheldon Hearn {
263f1b9d127SSheldon Hearn 	char *p = rap->r_nparam;
264f1b9d127SSheldon Hearn 	char ptype = *p;
265f1b9d127SSheldon Hearn 	int error, plen;
266f1b9d127SSheldon Hearn 
267f1b9d127SSheldon Hearn 	error = smb_rap_parserqparam(p, &p, &plen);
268f1b9d127SSheldon Hearn 	if (error)
269f1b9d127SSheldon Hearn 		return error;
270f1b9d127SSheldon Hearn 	switch (ptype) {
271f1b9d127SSheldon Hearn 	    case 'r':
272f1b9d127SSheldon Hearn 		rap->r_rcvbuf = value;
273f1b9d127SSheldon Hearn 		break;
274f1b9d127SSheldon Hearn 	    default:
275f1b9d127SSheldon Hearn 		return EINVAL;
276f1b9d127SSheldon Hearn 	}
277f1b9d127SSheldon Hearn 	rap->r_nparam = p;
278f1b9d127SSheldon Hearn 	return 0;
279f1b9d127SSheldon Hearn }
280f1b9d127SSheldon Hearn 
281f1b9d127SSheldon Hearn static int
282f1b9d127SSheldon Hearn smb_rap_getNparam(struct smb_rap *rap, long *value)
283f1b9d127SSheldon Hearn {
284f1b9d127SSheldon Hearn 	char *p = rap->r_nparam;
285f1b9d127SSheldon Hearn 	char ptype = *p;
286f1b9d127SSheldon Hearn 	int error, plen;
287f1b9d127SSheldon Hearn 
288f1b9d127SSheldon Hearn 	error = smb_rap_parserpparam(p, &p, &plen);
289f1b9d127SSheldon Hearn 	if (error)
290f1b9d127SSheldon Hearn 		return error;
291f1b9d127SSheldon Hearn 	switch (ptype) {
292f1b9d127SSheldon Hearn 	    case 'h':
293f1b9d127SSheldon Hearn 		*value = letohs(*(u_int16_t*)rap->r_npbuf);
294f1b9d127SSheldon Hearn 		break;
295f1b9d127SSheldon Hearn 	    default:
296f1b9d127SSheldon Hearn 		return EINVAL;
297f1b9d127SSheldon Hearn 	}
298f1b9d127SSheldon Hearn 	rap->r_npbuf += plen;
299f1b9d127SSheldon Hearn 	rap->r_nparam = p;
300f1b9d127SSheldon Hearn 	return 0;
301f1b9d127SSheldon Hearn }
302f1b9d127SSheldon Hearn 
303f1b9d127SSheldon Hearn int
304f1b9d127SSheldon Hearn smb_rap_request(struct smb_rap *rap, struct smb_ctx *ctx)
305f1b9d127SSheldon Hearn {
306f1b9d127SSheldon Hearn 	u_int16_t *rp, conv;
307f1b9d127SSheldon Hearn 	u_int32_t *p32;
308f1b9d127SSheldon Hearn 	char *dp, *p = rap->r_nparam;
309f1b9d127SSheldon Hearn 	char ptype;
310f1b9d127SSheldon Hearn 	int error, rdatacnt, rparamcnt, entries, done, dlen;
311f1b9d127SSheldon Hearn 
312f1b9d127SSheldon Hearn 	rdatacnt = rap->r_rcvbuflen;
313f1b9d127SSheldon Hearn 	rparamcnt = rap->r_plen;
314f1b9d127SSheldon Hearn 	error = smb_t2_request(ctx, 0, 0, "\\PIPE\\LANMAN",
315f1b9d127SSheldon Hearn 	    rap->r_plen, rap->r_pbuf,		/* int tparamcnt, void *tparam */
316f1b9d127SSheldon Hearn 	    0, NULL,				/* int tdatacnt, void *tdata */
317f1b9d127SSheldon Hearn 	    &rparamcnt, rap->r_pbuf,		/* rparamcnt, void *rparam */
318f1b9d127SSheldon Hearn 	    &rdatacnt, rap->r_rcvbuf		/* int *rdatacnt, void *rdata */
319f1b9d127SSheldon Hearn 	);
320f1b9d127SSheldon Hearn 	if (error)
321f1b9d127SSheldon Hearn 		return error;
322f1b9d127SSheldon Hearn 	rp = (u_int16_t*)rap->r_pbuf;
323f1b9d127SSheldon Hearn 	rap->r_result = letohs(*rp++);
324f1b9d127SSheldon Hearn 	conv = letohs(*rp++);
325f1b9d127SSheldon Hearn 	rap->r_npbuf = (char*)rp;
326f1b9d127SSheldon Hearn 	rap->r_entries = entries = 0;
327f1b9d127SSheldon Hearn 	done = 0;
328f1b9d127SSheldon Hearn 	while (!done && *p) {
329f1b9d127SSheldon Hearn 		ptype = *p;
330f1b9d127SSheldon Hearn 		switch (ptype) {
331f1b9d127SSheldon Hearn 		    case 'e':
332f1b9d127SSheldon Hearn 			rap->r_entries = entries = letohs(*(u_int16_t*)rap->r_npbuf);
333f1b9d127SSheldon Hearn 			rap->r_npbuf += 2;
334f1b9d127SSheldon Hearn 			p++;
335f1b9d127SSheldon Hearn 			break;
336f1b9d127SSheldon Hearn 		    default:
337f1b9d127SSheldon Hearn 			done = 1;
338f1b9d127SSheldon Hearn 		}
339f1b9d127SSheldon Hearn /*		error = smb_rap_parserpparam(p, &p, &plen);
340f1b9d127SSheldon Hearn 		if (error) {
341f1b9d127SSheldon Hearn 			smb_error("reply parameter mismath %s", 0, p);
342f1b9d127SSheldon Hearn 			return EBADRPC;
343f1b9d127SSheldon Hearn 		}*/
344f1b9d127SSheldon Hearn 	}
345f1b9d127SSheldon Hearn 	rap->r_nparam = p;
346f1b9d127SSheldon Hearn 	/*
347f1b9d127SSheldon Hearn 	 * In general, unpacking entries we may need to relocate
348f1b9d127SSheldon Hearn 	 * entries for proper alingning. For now use them as is.
349f1b9d127SSheldon Hearn 	 */
350f1b9d127SSheldon Hearn 	dp = rap->r_rcvbuf;
351f1b9d127SSheldon Hearn 	while (entries--) {
352f1b9d127SSheldon Hearn 		p = rap->r_sdata;
353f1b9d127SSheldon Hearn 		while (*p) {
354f1b9d127SSheldon Hearn 			ptype = *p;
355f1b9d127SSheldon Hearn 			error = smb_rap_parserpdata(p, &p, &dlen);
356f1b9d127SSheldon Hearn 			if (error) {
357f1b9d127SSheldon Hearn 				smb_error("reply data mismath %s", 0, p);
358f1b9d127SSheldon Hearn 				return EBADRPC;
359f1b9d127SSheldon Hearn 			}
360f1b9d127SSheldon Hearn 			switch (ptype) {
361f1b9d127SSheldon Hearn 			    case 'z':
362f1b9d127SSheldon Hearn 				p32 = (u_int32_t*)dp;
363f1b9d127SSheldon Hearn 				*p32 = (*p32 & 0xffff) - conv;
364f1b9d127SSheldon Hearn 				break;
365f1b9d127SSheldon Hearn 			}
366f1b9d127SSheldon Hearn 			dp += dlen;
367f1b9d127SSheldon Hearn 		}
368f1b9d127SSheldon Hearn 	}
369f1b9d127SSheldon Hearn 	return error;
370f1b9d127SSheldon Hearn }
371f1b9d127SSheldon Hearn 
372f1b9d127SSheldon Hearn int
373f1b9d127SSheldon Hearn smb_rap_error(struct smb_rap *rap, int error)
374f1b9d127SSheldon Hearn {
375f1b9d127SSheldon Hearn 	if (error)
376f1b9d127SSheldon Hearn 		return error;
377f1b9d127SSheldon Hearn 	if (rap->r_result == 0)
378f1b9d127SSheldon Hearn 		return 0;
379f1b9d127SSheldon Hearn 	return rap->r_result | SMB_RAP_ERROR;
380f1b9d127SSheldon Hearn }
381f1b9d127SSheldon Hearn 
382f1b9d127SSheldon Hearn int
383f1b9d127SSheldon Hearn smb_rap_NetShareEnum(struct smb_ctx *ctx, int sLevel, void *pbBuffer,
384f1b9d127SSheldon Hearn 	int cbBuffer, int *pcEntriesRead, int *pcTotalAvail)
385f1b9d127SSheldon Hearn {
386f1b9d127SSheldon Hearn 	struct smb_rap *rap;
387f1b9d127SSheldon Hearn 	long lval;
388f1b9d127SSheldon Hearn 	int error;
389f1b9d127SSheldon Hearn 
390f1b9d127SSheldon Hearn 	error = smb_rap_create(0, "WrLeh", "B13BWz", &rap);
391f1b9d127SSheldon Hearn 	if (error)
392f1b9d127SSheldon Hearn 		return error;
393f1b9d127SSheldon Hearn 	smb_rap_setNparam(rap, sLevel);		/* W - sLevel */
394f1b9d127SSheldon Hearn 	smb_rap_setPparam(rap, pbBuffer);	/* r - pbBuffer */
395f1b9d127SSheldon Hearn 	smb_rap_setNparam(rap, cbBuffer);	/* L - cbBuffer */
396f1b9d127SSheldon Hearn 	error = smb_rap_request(rap, ctx);
397f1b9d127SSheldon Hearn 	if (error == 0) {
398f1b9d127SSheldon Hearn 		*pcEntriesRead = rap->r_entries;
399f1b9d127SSheldon Hearn 		error = smb_rap_getNparam(rap, &lval);
400f1b9d127SSheldon Hearn 		*pcTotalAvail = lval;
401f1b9d127SSheldon Hearn 	}
402f1b9d127SSheldon Hearn 	error = smb_rap_error(rap, error);
403f1b9d127SSheldon Hearn 	smb_rap_done(rap);
404f1b9d127SSheldon Hearn 	return error;
405f1b9d127SSheldon Hearn }
406