5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
20 /* XXX: These routines needs to be made more stable as these can crash
21 if the data (for unformatting for example) is malformed or the buffer
22 is too short. Must be fixed. There are some other obvious bugs as
27 * Revision 1.1 2000/06/27 11:36:55 priikone
33 #include "silcincludes.h"
35 /* Formats the arguments sent and puts them into the buffer sent as
36 argument. The buffer must be initialized beforehand and it must have
37 enough free space to include the formatted data. If this function
38 fails caller should not trust the buffer anymore and should free it.
39 This function is used, for example, to create packets to send over
42 int silc_buffer_format(SilcBuffer dst, ...)
45 SilcBufferParamType fmt;
46 unsigned char *start_ptr = dst->data;
50 /* Parse the arguments by formatting type. */
52 fmt = va_arg(ap, SilcBufferParamType);
55 case SILC_BUFFER_PARAM_SI8_CHAR:
57 char x = va_arg(ap, char);
58 silc_buffer_put(dst, &x, 1);
59 silc_buffer_pull(dst, 1);
62 case SILC_BUFFER_PARAM_UI8_CHAR:
64 unsigned char x = va_arg(ap, unsigned char);
65 silc_buffer_put(dst, &x, 1);
66 silc_buffer_pull(dst, 1);
69 case SILC_BUFFER_PARAM_SI16_SHORT:
72 short x = va_arg(ap, short);
73 SILC_PUT16_MSB(x, xf);
74 silc_buffer_put(dst, xf, 2);
75 silc_buffer_pull(dst, 2);
78 case SILC_BUFFER_PARAM_UI16_SHORT:
81 unsigned short x = va_arg(ap, unsigned short);
82 SILC_PUT16_MSB(x, xf);
83 silc_buffer_put(dst, xf, 2);
84 silc_buffer_pull(dst, 2);
87 case SILC_BUFFER_PARAM_SI32_INT:
90 int x = va_arg(ap, int);
91 SILC_PUT32_MSB(x, xf);
92 silc_buffer_put(dst, xf, 4);
93 silc_buffer_pull(dst, 4);
96 case SILC_BUFFER_PARAM_UI32_INT:
99 unsigned int x = va_arg(ap, unsigned int);
100 SILC_PUT32_MSB(x, xf);
101 silc_buffer_put(dst, xf, 4);
102 silc_buffer_pull(dst, 4);
105 case SILC_BUFFER_PARAM_UI16_STRING:
106 case SILC_BUFFER_PARAM_UI32_STRING:
107 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
108 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
110 unsigned char *x = va_arg(ap, unsigned char *);
111 silc_buffer_put(dst, x, strlen(x));
112 silc_buffer_pull(dst, strlen(x));
115 case SILC_BUFFER_PARAM_UI16_NSTRING:
116 case SILC_BUFFER_PARAM_UI32_NSTRING:
117 case SILC_BUFFER_PARAM_UI_XNSTRING:
118 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
119 case SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC:
120 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
122 unsigned char *x = va_arg(ap, unsigned char *);
123 unsigned int len = va_arg(ap, unsigned int);
124 silc_buffer_put(dst, x, len);
125 silc_buffer_pull(dst, len);
128 case SILC_BUFFER_PARAM_END:
132 SILC_LOG_ERROR(("Bad buffer formatting type `%d'. Could not "
133 "format the data.", fmt));
140 SILC_LOG_ERROR(("Error occured while formatting data"));
144 /* Push the buffer back to where it belongs. */
145 silc_buffer_push(dst, dst->data - start_ptr);
149 /* Unformats the buffer sent as argument. The unformatted data is returned
150 to the variable argument list of pointers. The buffer must point to the
151 start of the data area to be unformatted. Buffer maybe be safely free'd
152 after this returns succesfully. */
154 int silc_buffer_unformat(SilcBuffer src, ...)
157 SilcBufferParamType fmt;
158 unsigned char *start_ptr = src->data;
163 /* Parse the arguments by formatting type. */
165 fmt = va_arg(ap, SilcBufferParamType);
168 case SILC_BUFFER_PARAM_SI8_CHAR:
170 char *x = va_arg(ap, char *);
173 silc_buffer_pull(src, 1);
176 case SILC_BUFFER_PARAM_UI8_CHAR:
178 unsigned char *x = va_arg(ap, unsigned char *);
181 silc_buffer_pull(src, 1);
184 case SILC_BUFFER_PARAM_SI16_SHORT:
186 short *x = va_arg(ap, short *);
188 SILC_GET16_MSB(*x, src->data);
189 silc_buffer_pull(src, 2);
192 case SILC_BUFFER_PARAM_UI16_SHORT:
194 unsigned short *x = va_arg(ap, unsigned short *);
196 SILC_GET16_MSB(*x, src->data);
197 silc_buffer_pull(src, 2);
200 case SILC_BUFFER_PARAM_SI32_INT:
202 int *x = va_arg(ap, int *);
204 SILC_GET32_MSB(*x, src->data);
205 silc_buffer_pull(src, 4);
208 case SILC_BUFFER_PARAM_UI32_INT:
210 unsigned int *x = va_arg(ap, unsigned int *);
212 SILC_GET32_MSB(*x, src->data);
213 silc_buffer_pull(src, 4);
216 case SILC_BUFFER_PARAM_UI16_STRING:
219 unsigned char **x = va_arg(ap, unsigned char **);
220 SILC_GET16_MSB(len2, src->data);
221 silc_buffer_pull(src, 2);
222 if ((len2 > src->len))
227 memcpy(x, src->data, len2);
228 silc_buffer_pull(src, len2);
231 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
234 unsigned char **x = va_arg(ap, unsigned char **);
235 SILC_GET16_MSB(len2, src->data);
236 silc_buffer_pull(src, 2);
237 if ((len2 > src->len))
242 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
243 memcpy(*x, src->data, len2);
245 silc_buffer_pull(src, len2);
248 case SILC_BUFFER_PARAM_UI32_STRING:
251 unsigned char **x = va_arg(ap, unsigned char **);
252 SILC_GET32_MSB(len2, src->data);
253 silc_buffer_pull(src, 4);
254 if ((len2 > src->len))
259 memcpy(x, src->data, len2);
260 silc_buffer_pull(src, len2);
263 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
266 unsigned char **x = va_arg(ap, unsigned char **);
267 SILC_GET32_MSB(len2, src->data);
268 silc_buffer_pull(src, 4);
269 if ((len2 > src->len))
274 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
275 memcpy(*x, src->data, len2);
277 silc_buffer_pull(src, len2);
280 case SILC_BUFFER_PARAM_UI16_NSTRING:
283 unsigned char **x = va_arg(ap, unsigned char **);
284 unsigned short *len = va_arg(ap, unsigned short *);
285 SILC_GET16_MSB(len2, src->data);
286 silc_buffer_pull(src, 2);
287 if ((len2 > src->len))
294 memcpy(x, src->data, len2);
295 silc_buffer_pull(src, len2);
298 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
301 unsigned char **x = va_arg(ap, unsigned char **);
302 unsigned short *len = va_arg(ap, unsigned short *);
303 SILC_GET16_MSB(len2, src->data);
304 silc_buffer_pull(src, 2);
305 if ((len2 > src->len))
312 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
313 memcpy(*x, src->data, len2);
315 silc_buffer_pull(src, len2);
318 case SILC_BUFFER_PARAM_UI32_NSTRING:
321 unsigned char **x = va_arg(ap, unsigned char **);
322 unsigned int *len = va_arg(ap, unsigned int *);
323 SILC_GET32_MSB(len2, src->data);
324 silc_buffer_pull(src, 4);
325 if ((len2 > src->len))
332 memcpy(x, src->data, len2);
333 silc_buffer_pull(src, len2);
336 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
338 unsigned char **x = va_arg(ap, unsigned char **);
339 unsigned int len = va_arg(ap, unsigned int);
341 *x = silc_calloc(len + 1, sizeof(unsigned char));
342 memcpy(*x, src->data, len);
344 silc_buffer_pull(src, len);
347 case SILC_BUFFER_PARAM_UI_XNSTRING:
349 unsigned char **x = va_arg(ap, unsigned char **);
350 unsigned int len = va_arg(ap, unsigned int);
352 memcpy(x, src->data, len);
353 silc_buffer_pull(src, len);
356 case SILC_BUFFER_PARAM_END:
360 SILC_LOG_ERROR(("Bad buffer formatting type `%d'. Could not "
361 "format the data.", fmt));
368 SILC_LOG_ERROR(("Error occured while unformatting buffer"));
372 /* Push the buffer back to the start. */
373 len = src->data - start_ptr;
374 silc_buffer_push(src, len);