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