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
;
203 smb_rap_create(int fn
, const char *param
, const char *data
,
204 struct smb_rap
**rapp
)
208 int plen
= 0, len
= 0;
210 rap
= malloc(sizeof (*rap
));
213 bzero(rap
, sizeof (*rap
));
214 p
= rap
->r_sparam
= rap
->r_nparam
= strdup(param
);
215 rap
->r_sdata
= rap
->r_ndata
= strdup(data
);
218 * Calculate length of request parameter block
220 len
= 2 + strlen(param
) + 1 + strlen(data
) + 1;
222 if (smb_rap_parserqparam(p
, &p
, &plen
) != 0)
226 rap
->r_pbuf
= rap
->r_npbuf
= malloc(len
);
227 if (rap
->r_pbuf
== NULL
)
229 (void) smb_rap_rqparam(rap
, 'W', 1, fn
);
230 (void) smb_rap_rqparam_z(rap
, rap
->r_sparam
);
231 (void) smb_rap_rqparam_z(rap
, rap
->r_sdata
);
237 smb_rap_done(struct smb_rap
*rap
)
251 smb_rap_setNparam(struct smb_rap
*rap
, int value
)
253 char *p
= rap
->r_nparam
;
257 error
= smb_rap_parserqparam(p
, &p
, &plen
);
262 rap
->r_rcvbuflen
= value
;
267 error
= smb_rap_rqparam(rap
, ptype
, plen
, value
);
277 smb_rap_setPparam(struct smb_rap
*rap
, void *value
)
279 char *p
= rap
->r_nparam
;
283 error
= smb_rap_parserqparam(p
, &p
, &plen
);
288 rap
->r_rcvbuf
= value
;
298 smb_rap_getNparam(struct smb_rap
*rap
, long *value
)
300 char *p
= rap
->r_nparam
;
305 error
= smb_rap_parserpparam(p
, &p
, &plen
);
311 te
= (uint16_t *)rap
->r_npbuf
;
312 *value
= letohs(*te
);
317 rap
->r_npbuf
+= plen
;
323 smb_rap_request(struct smb_rap
*rap
, struct smb_ctx
*ctx
)
325 uint16_t *rp
, conv
, *tmp
;
327 char *dp
, *p
= rap
->r_nparam
;
329 int error
, rdatacnt
, rparamcnt
, entries
, done
, dlen
, buffer_oflow
;
331 rdatacnt
= rap
->r_rcvbuflen
;
332 rparamcnt
= rap
->r_plen
;
333 error
= smb_t2_request(ctx
->ct_dev_fd
,
334 0, NULL
, "\\PIPE\\LANMAN",
335 rap
->r_plen
, rap
->r_pbuf
, /* int tparamcnt,void *tparam */
336 0, NULL
, /* int tdatacnt, void *tdata */
337 &rparamcnt
, rap
->r_pbuf
, /* rparamcnt, void *rparam */
338 &rdatacnt
, rap
->r_rcvbuf
, /* int *rdatacnt, void *rdata */
344 rp
= (uint16_t *)rap
->r_pbuf
;
347 * Note: First is a "LanMan API" error code.
348 * See: usr/src/uts/common/smbsrv/lmerr.h
352 rap
->r_result
= letohs(*rp
);
353 rp
++; rparamcnt
-= 2;
355 if (rap
->r_result
!= 0) {
357 * Could also return zero and let the caller
358 * come get r_result via smb_rap_error(),
359 * but in case they dont...
361 return (rap
->r_result
| SMB_RAP_ERROR
);
367 rp
++; rparamcnt
-= 2;
369 rap
->r_npbuf
= (char *)rp
;
370 rap
->r_entries
= entries
= 0;
371 /* Save the returned data length */
372 rap
->r_rcvbuflen
= rdatacnt
;
375 while (!done
&& *p
) {
382 tmp
= (uint16_t *)rap
->r_npbuf
;
383 rap
->r_entries
= entries
= letohs(*tmp
);
391 #if 0 /* commented out in Darwin. Why? */
392 error
= smb_rap_parserpparam(p
, &p
, &plen
);
394 smb_error(dgettext(TEXT_DOMAIN
,
395 "reply parameter mismatch %s"), 0, p
);
402 * In general, unpacking entries we may need to relocate
403 * entries for proper aligning. For now use them as is.
410 error
= smb_rap_parserpdata(p
, &p
, &dlen
);
412 smb_error(dgettext(TEXT_DOMAIN
,
413 "reply data mismatch %s"), 0, p
);
421 p32
= (uint32_t *)dp
;
422 *p32
= (letohl(*p32
) & 0xffff) - conv
;
433 smb_rap_error(struct smb_rap
*rap
, int error
)
437 if (rap
->r_result
== 0)
439 return (rap
->r_result
| SMB_RAP_ERROR
);