1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*
27 * Legacy encode/decode routines for door clients and servers.
28 */
29
30#ifndef _KERNEL
31#include <errno.h>
32#include <string.h>
33#include <strings.h>
34#else
35#include <sys/types.h>
36#include <sys/sunddi.h>
37#include <sys/errno.h>
38#endif
39
40#include <smbsrv/wintypes.h>
41#include <smbsrv/smb_share.h>
42#include <smbsrv/smb_door.h>
43#include <smbsrv/alloc.h>
44#include <smbsrv/smbinfo.h>
45
46smb_dr_ctx_t *
47smb_dr_decode_start(char *ptr, int size)
48{
49	smb_dr_ctx_t *ctx = MEM_MALLOC("CommonDoor", sizeof (smb_dr_ctx_t));
50	if (ctx) {
51		ctx->start_ptr = ctx->ptr = ptr;
52		ctx->end_ptr = ptr + size;
53		ctx->status = 0;
54	}
55	return (ctx);
56}
57
58int
59smb_dr_decode_finish(smb_dr_ctx_t *ctx)
60{
61	int status = ctx->status;
62	if (status == 0 && ctx->ptr != ctx->end_ptr)
63		status = ENOTEMPTY;
64
65	MEM_FREE("CommonDoor", ctx);
66	return (status);
67}
68
69smb_dr_ctx_t *
70smb_dr_encode_start(char *ptr, int size)
71{
72	smb_dr_ctx_t *ctx = MEM_MALLOC("CommonDoor",  sizeof (smb_dr_ctx_t));
73	if (ctx) {
74		ctx->start_ptr = ctx->ptr = ptr;
75		ctx->end_ptr = ptr + size;
76		ctx->status = 0;
77	}
78	return (ctx);
79}
80
81int
82smb_dr_encode_finish(smb_dr_ctx_t *ctx, unsigned int *used)
83{
84	int status = ctx->status;
85	if (status == 0) {
86		if (ctx->ptr < ctx->end_ptr) {
87			/*LINTED E_PTRDIFF_OVERFLOW*/
88			*used = ctx->ptr - ctx->start_ptr;
89		} else {
90			status = ENOSPC;
91		}
92	}
93
94	MEM_FREE("CommonDoor", ctx);
95	return (status);
96}
97
98DWORD
99smb_dr_get_dword(smb_dr_ctx_t *ctx)
100{
101	DWORD num = 0;
102	if (ctx->status == 0) {
103		if (ctx->ptr + sizeof (DWORD) <= ctx->end_ptr) {
104			(void) memcpy(&num, ctx->ptr, sizeof (DWORD));
105			ctx->ptr += sizeof (DWORD);
106		} else {
107			ctx->status = ENOSPC;
108		}
109	}
110	return (num);
111}
112
113int32_t
114smb_dr_get_int32(smb_dr_ctx_t *ctx)
115{
116	int32_t num = 0;
117	if (ctx->status == 0) {
118		if (ctx->ptr + sizeof (int32_t) <= ctx->end_ptr) {
119			(void) memcpy(&num, ctx->ptr, sizeof (int32_t));
120			ctx->ptr += sizeof (int32_t);
121		} else {
122			ctx->status = ENOSPC;
123		}
124	}
125	return (num);
126}
127
128uint32_t
129smb_dr_get_uint32(smb_dr_ctx_t *ctx)
130{
131	return ((uint32_t)smb_dr_get_int32(ctx));
132}
133
134char *
135smb_dr_get_string(smb_dr_ctx_t *ctx)
136{
137	char *buf = NULL;
138	int len = smb_dr_get_int32(ctx);
139
140	if (ctx->status == 0) {
141		if (len == -1)
142			return (buf);
143
144		if (ctx->ptr + len <= ctx->end_ptr) {
145			buf = MEM_MALLOC("CommonDoor", len +1);
146			if (buf) {
147				if (len == 0) {
148					(void) strcpy(buf, "");
149				} else {
150					(void) memcpy(buf, ctx->ptr, len);
151					ctx->ptr += len;
152					*(buf + len) = '\0';
153				}
154			} else {
155#ifndef _KERNEL
156				ctx->status = errno;
157#else
158				ctx->status = ENOMEM;
159#endif
160			}
161		} else {
162			ctx->status = ENOSPC;
163		}
164	}
165	return (buf);
166}
167
168void
169smb_dr_put_dword(smb_dr_ctx_t *ctx, DWORD num)
170{
171	if (ctx->status == 0) {
172		if (ctx->ptr + sizeof (DWORD) <= ctx->end_ptr) {
173			(void) memcpy(ctx->ptr, &num, sizeof (DWORD));
174			ctx->ptr += sizeof (DWORD);
175		} else {
176			ctx->status = ENOSPC;
177		}
178	}
179}
180
181void
182smb_dr_put_int32(smb_dr_ctx_t *ctx, int32_t num)
183{
184	if (ctx->status == 0) {
185		if (ctx->ptr + sizeof (int32_t) <= ctx->end_ptr) {
186			(void) memcpy(ctx->ptr, &num, sizeof (int32_t));
187			ctx->ptr += sizeof (int32_t);
188		} else {
189			ctx->status = ENOSPC;
190		}
191	}
192}
193
194void
195smb_dr_put_uint32(smb_dr_ctx_t *ctx, uint32_t num)
196{
197	smb_dr_put_int32(ctx, (int32_t)num);
198}
199
200void
201smb_dr_put_string(smb_dr_ctx_t *ctx, const char *buf)
202{
203	int len;
204
205	if (!buf)
206		len = -1;
207	else
208		len = strlen(buf);
209
210	if (ctx->status == 0) {
211		smb_dr_put_int32(ctx, len);
212		if (len <= 0)
213			return;
214
215		if (ctx->ptr + len <= ctx->end_ptr) {
216			(void) memcpy(ctx->ptr, buf, len);
217			ctx->ptr += len;
218		} else {
219			ctx->status = ENOSPC;
220		}
221	}
222}
223
224void
225smb_dr_free_string(char *buf)
226{
227	if (buf)
228		MEM_FREE("CommonDoor", buf);
229}
230
231int64_t
232smb_dr_get_int64(smb_dr_ctx_t *ctx)
233{
234	int64_t num = 0;
235	if (ctx->status == 0) {
236		if (ctx->ptr + sizeof (int64_t) <= ctx->end_ptr) {
237			(void) memcpy(&num, ctx->ptr, sizeof (int64_t));
238			ctx->ptr += sizeof (int64_t);
239		} else {
240			ctx->status = ENOSPC;
241		}
242	}
243	return (num);
244}
245
246uint64_t
247smb_dr_get_uint64(smb_dr_ctx_t *ctx)
248{
249	return ((uint64_t)smb_dr_get_int64(ctx));
250}
251
252
253void
254smb_dr_put_int64(smb_dr_ctx_t *ctx, int64_t num)
255{
256	if (ctx->status == 0) {
257		if (ctx->ptr + sizeof (int64_t) <= ctx->end_ptr) {
258			(void) memcpy(ctx->ptr, &num, sizeof (int64_t));
259			ctx->ptr += sizeof (int64_t);
260		} else {
261			ctx->status = ENOSPC;
262		}
263	}
264}
265
266void
267smb_dr_put_uint64(smb_dr_ctx_t *ctx, uint64_t num)
268{
269	smb_dr_put_int64(ctx, (int64_t)num);
270}
271
272void
273smb_dr_put_short(smb_dr_ctx_t *ctx, short num)
274{
275	if (ctx->status == 0) {
276		if (ctx->ptr + sizeof (short) <= ctx->end_ptr) {
277			(void) memcpy(ctx->ptr, &num, sizeof (short));
278			ctx->ptr += sizeof (short);
279		} else {
280			ctx->status = ENOSPC;
281		}
282	}
283}
284
285short
286smb_dr_get_short(smb_dr_ctx_t *ctx)
287{
288	short num = 0;
289	if (ctx->status == 0) {
290		if (ctx->ptr + sizeof (short) <= ctx->end_ptr) {
291			(void) memcpy(&num, ctx->ptr, sizeof (short));
292			ctx->ptr += sizeof (short);
293		} else {
294			ctx->status = ENOSPC;
295		}
296	}
297	return (num);
298}
299
300void
301smb_dr_put_ushort(smb_dr_ctx_t *ctx, unsigned short num)
302{
303	smb_dr_put_short(ctx, (short)num);
304}
305
306unsigned short
307smb_dr_get_ushort(smb_dr_ctx_t *ctx)
308{
309	return ((unsigned short)smb_dr_get_short(ctx));
310}
311
312void
313smb_dr_put_word(smb_dr_ctx_t *ctx, WORD num)
314{
315	smb_dr_put_ushort(ctx, num);
316}
317
318WORD
319smb_dr_get_word(smb_dr_ctx_t *ctx)
320{
321	return (smb_dr_get_ushort(ctx));
322}
323
324void
325smb_dr_put_BYTE(smb_dr_ctx_t *ctx, BYTE byte)
326{
327	if (ctx->status == 0) {
328		if (ctx->ptr + sizeof (BYTE) <= ctx->end_ptr) {
329			(void) memcpy(ctx->ptr, &byte, sizeof (BYTE));
330			ctx->ptr += sizeof (BYTE);
331		} else {
332			ctx->status = ENOSPC;
333		}
334	}
335}
336
337BYTE
338smb_dr_get_BYTE(smb_dr_ctx_t *ctx)
339{
340	BYTE byte = 0;
341	if (ctx->status == 0) {
342		if (ctx->ptr + sizeof (BYTE) <= ctx->end_ptr) {
343			(void) memcpy(&byte, ctx->ptr, sizeof (BYTE));
344			ctx->ptr += sizeof (BYTE);
345		} else {
346			ctx->status = ENOSPC;
347		}
348	}
349	return (byte);
350}
351
352void
353smb_dr_put_buf(smb_dr_ctx_t *ctx, unsigned char *start, int len)
354{
355	smb_dr_put_int32(ctx, len);
356	if (ctx->status == 0) {
357		if (ctx->ptr + len <= ctx->end_ptr) {
358			(void) memcpy(ctx->ptr, start, len);
359			ctx->ptr += len;
360		} else {
361			ctx->status = ENOSPC;
362		}
363	}
364}
365
366int
367smb_dr_get_buf(smb_dr_ctx_t *ctx, unsigned char *buf, int bufsize)
368{
369	int len = -1;
370
371	if (!buf)
372		return (-1);
373
374	len = smb_dr_get_int32(ctx);
375	if (ctx->status == 0) {
376		if (bufsize < len) {
377			ctx->status = ENOSPC;
378			return (-2);
379		}
380
381		if (ctx->ptr + len <= ctx->end_ptr) {
382			(void) memcpy(buf, ctx->ptr, len);
383			ctx->ptr += len;
384		} else {
385			ctx->status = ENOSPC;
386			return (-3);
387		}
388	}
389
390	return (len);
391}
392
393void
394smb_dr_get_share(smb_dr_ctx_t *ctx, smb_share_t *si)
395{
396	if (ctx->status == 0) {
397		if (smb_dr_get_int32(ctx)) {
398			(void) memcpy(si, ctx->ptr, sizeof (smb_share_t));
399			ctx->ptr += sizeof (smb_share_t);
400		} else {
401			bzero(si, sizeof (smb_share_t));
402		}
403	} else {
404		bzero(si, sizeof (smb_share_t));
405	}
406}
407
408void
409smb_dr_put_share(smb_dr_ctx_t *ctx, smb_share_t *si)
410{
411	if (si) {
412		smb_dr_put_int32(ctx, 1);
413		if (ctx->ptr + sizeof (smb_share_t) <= ctx->end_ptr) {
414			(void) memcpy(ctx->ptr, si, sizeof (smb_share_t));
415			ctx->ptr += sizeof (smb_share_t);
416		} else {
417			ctx->status = ENOSPC;
418		}
419	} else {
420		smb_dr_put_int32(ctx, 0);
421	}
422}
423