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