1/*
2 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 */
5
6/*
7 * BSD 3 Clause License
8 *
9 * Copyright (c) 2007, The Storage Networking Industry Association.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 	- Redistributions of source code must retain the above copyright
15 *	  notice, this list of conditions and the following disclaimer.
16 *
17 * 	- Redistributions in binary form must reproduce the above copyright
18 *	  notice, this list of conditions and the following disclaimer in
19 *	  the documentation and/or other materials provided with the
20 *	  distribution.
21 *
22 *	- Neither the name of The Storage Networking Industry Association (SNIA)
23 *	  nor the names of its contributors may be used to endorse or promote
24 *	  products derived from this software without specific prior written
25 *	  permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40/*
41 * Provides encode/decode routines for all door servers/clients.
42 */
43
44#include <string.h>
45#include <errno.h>
46#include <stdlib.h>
47#include <libndmp.h>
48
49ndmp_door_ctx_t *
50ndmp_door_decode_start(char *ptr, int size)
51{
52	ndmp_door_ctx_t *ctx = malloc(sizeof (ndmp_door_ctx_t));
53	if (ctx) {
54		ctx->start_ptr = ctx->ptr = ptr;
55		ctx->end_ptr = ptr + size;
56		ctx->status = 0;
57	}
58	return (ctx);
59}
60
61int
62ndmp_door_decode_finish(ndmp_door_ctx_t *ctx)
63{
64	int status = ctx->status;
65	if ((status == 0) && (ctx->ptr != ctx->end_ptr)) {
66		status = ENOTEMPTY;
67	}
68	free(ctx);
69	return (status);
70}
71
72ndmp_door_ctx_t *
73ndmp_door_encode_start(char *ptr, int size)
74{
75	ndmp_door_ctx_t *ctx = malloc(sizeof (ndmp_door_ctx_t));
76	if (ctx) {
77		ctx->start_ptr = ctx->ptr = ptr;
78		ctx->end_ptr = ptr + size;
79		ctx->status = 0;
80	}
81	return (ctx);
82}
83
84int
85ndmp_door_encode_finish(ndmp_door_ctx_t *ctx, unsigned int *used)
86{
87	int status = ctx->status;
88	if (status == 0) {
89		if (ctx->ptr < ctx->end_ptr) {
90			/*LINTED E_PTRDIFF_OVERFLOW*/
91			*used = ctx->ptr - ctx->start_ptr;
92		} else {
93			status = ENOSPC;
94		}
95	}
96	free(ctx);
97	return (status);
98}
99
100int32_t
101ndmp_door_get_int32(ndmp_door_ctx_t *ctx)
102{
103	int32_t num = 0;
104	if (ctx->status == 0) {
105		if (ctx->ptr + sizeof (int32_t) <= ctx->end_ptr) {
106			(void) memcpy(&num, ctx->ptr, sizeof (int32_t));
107			ctx->ptr += sizeof (int32_t);
108		} else {
109			ctx->status = ENOSPC;
110		}
111	}
112	return (num);
113}
114
115uint32_t
116ndmp_door_get_uint32(ndmp_door_ctx_t *ctx)
117{
118	return ((uint32_t)ndmp_door_get_int32(ctx));
119}
120
121char *
122ndmp_door_get_string(ndmp_door_ctx_t *ctx)
123{
124	char *buf = NULL;
125	int len = ndmp_door_get_int32(ctx);
126
127	if (ctx->status == 0) {
128		if (len == -1)
129			return (buf);
130
131		if (ctx->ptr + len <= ctx->end_ptr) {
132			buf = malloc(len +1);
133			if (buf) {
134				if (len == 0) {
135					(void) strcpy(buf, "");
136				} else {
137					(void) memcpy(buf, ctx->ptr, len);
138					ctx->ptr += len;
139					*(buf + len) = '\0';
140				}
141			} else {
142				ctx->status = errno;
143			}
144		} else {
145			ctx->status = ENOSPC;
146		}
147	}
148	return (buf);
149}
150
151void
152ndmp_door_put_int32(ndmp_door_ctx_t *ctx, int32_t num)
153{
154	if (ctx->status == 0) {
155		if (ctx->ptr + sizeof (int32_t) <= ctx->end_ptr) {
156			(void) memcpy(ctx->ptr, &num, sizeof (int32_t));
157			ctx->ptr += sizeof (int32_t);
158		} else {
159			ctx->status = ENOSPC;
160		}
161	}
162}
163
164void
165ndmp_door_put_uint32(ndmp_door_ctx_t *ctx, uint32_t num)
166{
167	ndmp_door_put_int32(ctx, (int32_t)num);
168}
169
170void
171ndmp_door_put_string(ndmp_door_ctx_t *ctx, char *buf)
172{
173	int len;
174
175	if (!buf)
176		len = -1;
177	else
178		len = strlen(buf);
179
180	if (ctx->status == 0) {
181		ndmp_door_put_int32(ctx, len);
182		if (len <= 0)
183			return;
184
185		if (ctx->ptr + len <= ctx->end_ptr) {
186			(void) memcpy(ctx->ptr, buf, len);
187			ctx->ptr += len;
188		} else {
189			ctx->status = ENOSPC;
190		}
191	}
192}
193
194void
195ndmp_door_free_string(char *buf)
196{
197	free(buf);
198}
199
200int64_t
201ndmp_door_get_int64(ndmp_door_ctx_t *ctx)
202{
203	int64_t num = 0;
204	if (ctx->status == 0) {
205		if (ctx->ptr + sizeof (int64_t) <= ctx->end_ptr) {
206			(void) memcpy(&num, ctx->ptr, sizeof (int64_t));
207			ctx->ptr += sizeof (int64_t);
208		} else {
209			ctx->status = ENOSPC;
210		}
211	}
212	return (num);
213}
214
215uint64_t
216ndmp_door_get_uint64(ndmp_door_ctx_t *ctx)
217{
218	return ((uint64_t)ndmp_door_get_int64(ctx));
219}
220
221
222void
223ndmp_door_put_int64(ndmp_door_ctx_t *ctx, int64_t num)
224{
225	if (ctx->status == 0) {
226		if (ctx->ptr + sizeof (int64_t) <= ctx->end_ptr) {
227			(void) memcpy(ctx->ptr, &num, sizeof (int64_t));
228			ctx->ptr += sizeof (int64_t);
229		} else {
230			ctx->status = ENOSPC;
231		}
232	}
233}
234
235void
236ndmp_door_put_uint64(ndmp_door_ctx_t *ctx, uint64_t num)
237{
238	ndmp_door_put_int64(ctx, (int64_t)num);
239}
240
241void
242ndmp_door_put_short(ndmp_door_ctx_t *ctx, short num)
243{
244	if (ctx->status == 0) {
245		if (ctx->ptr + sizeof (short) <= ctx->end_ptr) {
246			(void) memcpy(ctx->ptr, &num, sizeof (short));
247			ctx->ptr += sizeof (short);
248		} else {
249			ctx->status = ENOSPC;
250		}
251	}
252}
253
254short
255ndmp_door_get_short(ndmp_door_ctx_t *ctx)
256{
257	short num = 0;
258	if (ctx->status == 0) {
259		if (ctx->ptr + sizeof (short) <= ctx->end_ptr) {
260			(void) memcpy(&num, ctx->ptr, sizeof (short));
261			ctx->ptr += sizeof (short);
262		} else {
263			ctx->status = ENOSPC;
264		}
265	}
266	return (num);
267}
268
269void
270ndmp_door_put_ushort(ndmp_door_ctx_t *ctx, unsigned short num)
271{
272	ndmp_door_put_short(ctx, (short)num);
273}
274
275unsigned short
276ndmp_door_get_ushort(ndmp_door_ctx_t *ctx)
277{
278	return ((unsigned short)ndmp_door_get_short(ctx));
279}
280
281void
282ndmp_door_put_buf(ndmp_door_ctx_t *ctx, unsigned char *start, int len)
283{
284	ndmp_door_put_int32(ctx, len);
285	if (ctx->status == 0) {
286		if (ctx->ptr + len <= ctx->end_ptr) {
287			(void) memcpy(ctx->ptr, start, len);
288			ctx->ptr += len;
289		} else {
290			ctx->status = ENOSPC;
291		}
292	}
293}
294
295int
296ndmp_door_get_buf(ndmp_door_ctx_t *ctx, unsigned char *buf, int bufsize)
297{
298	int len = -1;
299
300	if (!buf)
301		return (-1);
302
303	len = ndmp_door_get_int32(ctx);
304	if (ctx->status == 0) {
305		if (bufsize < len) {
306			ctx->status = ENOSPC;
307			return (-2);
308		}
309
310		if (ctx->ptr + len <= ctx->end_ptr) {
311			(void) memcpy(buf, ctx->ptr, len);
312			ctx->ptr += len;
313		} else {
314			ctx->status = ENOSPC;
315			return (-3);
316		}
317	}
318
319	return (len);
320}
321