2 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
3 * Copyright (c) 2000, Boris Popov
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Boris Popov.
17 * 4. Neither the name of the author nor the names of any co-contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * $Id: rap.c,v 1.5 2004/12/13 00:25:23 lindak Exp $
35 * This is very simple implementation of RAP protocol.
38 #include <sys/param.h>
39 #include <sys/errno.h>
41 #include <sys/isa_defs.h>
51 #include <netsmb/mchain.h>
52 #include <netsmb/smb_lib.h>
53 #include <netsmb/smb_rap.h>
57 smb_rap_parserqparam(const char *s
, char **next
, int *rlen
)
84 len
*= strtoul(s
, &np
, 10);
88 *(const char **)next
= s
;
93 smb_rap_parserpparam(const char *s
, char **next
, int *rlen
)
113 len
*= strtoul(s
, &np
, 10);
117 *(const char **)next
= s
;
122 smb_rap_parserpdata(const char *s
, char **next
, int *rlen
)
143 len
*= strtoul(s
, &np
, 10);
147 *(const char **)next
= s
;
152 smb_rap_rqparam_z(struct smb_rap
*rap
, const char *value
)
154 int len
= strlen(value
) + 1;
156 bcopy(value
, rap
->r_npbuf
, len
);
163 * Marshal RAP request parameters.
164 * Note: value is in host order.
167 smb_rap_rqparam(struct smb_rap
*rap
, char ptype
, char plen
, int value
)
170 uint_t uv
= (uint_t
)value
;
179 sp
= (uint16_t *)rap
->r_npbuf
;
185 lp
= (uint32_t *)rap
->r_npbuf
;
202 smb_rap_create(int fn
, const char *param
, const char *data
,
203 struct smb_rap
**rapp
)
207 int plen
= 0, len
= 0;
209 rap
= malloc(sizeof (*rap
));
212 bzero(rap
, sizeof (*rap
));
213 p
= rap
->r_sparam
= rap
->r_nparam
= strdup(param
);
214 rap
->r_sdata
= rap
->r_ndata
= strdup(data
);
217 * Calculate length of request parameter block
219 len
= 2 + strlen(param
) + 1 + strlen(data
) + 1;
221 if (smb_rap_parserqparam(p
, &p
, &plen
) != 0)
225 rap
->r_pbuf
= rap
->r_npbuf
= malloc(len
);
226 if (rap
->r_pbuf
== NULL
)
228 (void) smb_rap_rqparam(rap
, 'W', 1, fn
);
229 (void) smb_rap_rqparam_z(rap
, rap
->r_sparam
);
230 (void) smb_rap_rqparam_z(rap
, rap
->r_sdata
);
236 smb_rap_done(struct smb_rap
*rap
)
250 smb_rap_setNparam(struct smb_rap
*rap
, int value
)
252 char *p
= rap
->r_nparam
;
256 error
= smb_rap_parserqparam(p
, &p
, &plen
);
261 rap
->r_rcvbuflen
= value
;
266 error
= smb_rap_rqparam(rap
, ptype
, plen
, value
);
276 smb_rap_setPparam(struct smb_rap
*rap
, void *value
)
278 char *p
= rap
->r_nparam
;
282 error
= smb_rap_parserqparam(p
, &p
, &plen
);
287 rap
->r_rcvbuf
= value
;
297 smb_rap_getNparam(struct smb_rap
*rap
, long *value
)
299 char *p
= rap
->r_nparam
;
304 error
= smb_rap_parserpparam(p
, &p
, &plen
);
310 te
= (uint16_t *)rap
->r_npbuf
;
311 *value
= letohs(*te
);
316 rap
->r_npbuf
+= plen
;
322 smb_rap_request(struct smb_rap
*rap
, struct smb_ctx
*ctx
)
324 uint16_t *rp
, conv
, *tmp
;
326 char *dp
, *p
= rap
->r_nparam
;
328 int error
, rdatacnt
, rparamcnt
, entries
, done
, dlen
, buffer_oflow
;
330 rdatacnt
= rap
->r_rcvbuflen
;
331 rparamcnt
= rap
->r_plen
;
332 error
= smb_t2_request(ctx
->ct_dev_fd
,
333 0, NULL
, "\\PIPE\\LANMAN",
334 rap
->r_plen
, rap
->r_pbuf
, /* int tparamcnt,void *tparam */
335 0, NULL
, /* int tdatacnt, void *tdata */
336 &rparamcnt
, rap
->r_pbuf
, /* rparamcnt, void *rparam */
337 &rdatacnt
, rap
->r_rcvbuf
, /* int *rdatacnt, void *rdata */
343 rp
= (uint16_t *)rap
->r_pbuf
;
346 * Note: First is a "LanMan API" error code.
347 * See: usr/src/uts/common/smbsrv/lmerr.h
351 rap
->r_result
= letohs(*rp
);
352 rp
++; rparamcnt
-= 2;
354 if (rap
->r_result
!= 0) {
356 * Could also return zero and let the caller
357 * come get r_result via smb_rap_error(),
358 * but in case they dont...
360 return (rap
->r_result
| SMB_RAP_ERROR
);
366 rp
++; rparamcnt
-= 2;
368 rap
->r_npbuf
= (char *)rp
;
369 rap
->r_entries
= entries
= 0;
370 /* Save the returned data length */
371 rap
->r_rcvbuflen
= rdatacnt
;
374 while (!done
&& *p
) {
381 tmp
= (uint16_t *)rap
->r_npbuf
;
382 rap
->r_entries
= entries
= letohs(*tmp
);
390 #if 0 /* commented out in Darwin. Why? */
391 error
= smb_rap_parserpparam(p
, &p
, &plen
);
393 smb_error(dgettext(TEXT_DOMAIN
,
394 "reply parameter mismatch %s"), 0, p
);
401 * In general, unpacking entries we may need to relocate
402 * entries for proper aligning. For now use them as is.
409 error
= smb_rap_parserpdata(p
, &p
, &dlen
);
411 smb_error(dgettext(TEXT_DOMAIN
,
412 "reply data mismatch %s"), 0, p
);
420 p32
= (uint32_t *)dp
;
421 *p32
= (letohl(*p32
) & 0xffff) - conv
;
432 smb_rap_error(struct smb_rap
*rap
, int error
)
436 if (rap
->r_result
== 0)
438 return (rap
->r_result
| SMB_RAP_ERROR
);