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 
49 ndmp_door_ctx_t *
ndmp_door_decode_start(char * ptr,int size)50 ndmp_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 
61 int
ndmp_door_decode_finish(ndmp_door_ctx_t * ctx)62 ndmp_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 
72 ndmp_door_ctx_t *
ndmp_door_encode_start(char * ptr,int size)73 ndmp_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 
84 int
ndmp_door_encode_finish(ndmp_door_ctx_t * ctx,unsigned int * used)85 ndmp_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 
100 int32_t
ndmp_door_get_int32(ndmp_door_ctx_t * ctx)101 ndmp_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 
115 uint32_t
ndmp_door_get_uint32(ndmp_door_ctx_t * ctx)116 ndmp_door_get_uint32(ndmp_door_ctx_t *ctx)
117 {
118 	return ((uint32_t)ndmp_door_get_int32(ctx));
119 }
120 
121 char *
ndmp_door_get_string(ndmp_door_ctx_t * ctx)122 ndmp_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 
151 void
ndmp_door_put_int32(ndmp_door_ctx_t * ctx,int32_t num)152 ndmp_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 
164 void
ndmp_door_put_uint32(ndmp_door_ctx_t * ctx,uint32_t num)165 ndmp_door_put_uint32(ndmp_door_ctx_t *ctx, uint32_t num)
166 {
167 	ndmp_door_put_int32(ctx, (int32_t)num);
168 }
169 
170 void
ndmp_door_put_string(ndmp_door_ctx_t * ctx,char * buf)171 ndmp_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 
194 void
ndmp_door_free_string(char * buf)195 ndmp_door_free_string(char *buf)
196 {
197 	free(buf);
198 }
199 
200 int64_t
ndmp_door_get_int64(ndmp_door_ctx_t * ctx)201 ndmp_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 
215 uint64_t
ndmp_door_get_uint64(ndmp_door_ctx_t * ctx)216 ndmp_door_get_uint64(ndmp_door_ctx_t *ctx)
217 {
218 	return ((uint64_t)ndmp_door_get_int64(ctx));
219 }
220 
221 
222 void
ndmp_door_put_int64(ndmp_door_ctx_t * ctx,int64_t num)223 ndmp_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 
235 void
ndmp_door_put_uint64(ndmp_door_ctx_t * ctx,uint64_t num)236 ndmp_door_put_uint64(ndmp_door_ctx_t *ctx, uint64_t num)
237 {
238 	ndmp_door_put_int64(ctx, (int64_t)num);
239 }
240 
241 void
ndmp_door_put_short(ndmp_door_ctx_t * ctx,short num)242 ndmp_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 
254 short
ndmp_door_get_short(ndmp_door_ctx_t * ctx)255 ndmp_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 
269 void
ndmp_door_put_ushort(ndmp_door_ctx_t * ctx,unsigned short num)270 ndmp_door_put_ushort(ndmp_door_ctx_t *ctx, unsigned short num)
271 {
272 	ndmp_door_put_short(ctx, (short)num);
273 }
274 
275 unsigned short
ndmp_door_get_ushort(ndmp_door_ctx_t * ctx)276 ndmp_door_get_ushort(ndmp_door_ctx_t *ctx)
277 {
278 	return ((unsigned short)ndmp_door_get_short(ctx));
279 }
280 
281 void
ndmp_door_put_buf(ndmp_door_ctx_t * ctx,unsigned char * start,int len)282 ndmp_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 
295 int
ndmp_door_get_buf(ndmp_door_ctx_t * ctx,unsigned char * buf,int bufsize)296 ndmp_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