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.2 2000/09/29 07:11:27 priikone
28 * Explcitly cast some va_arg()s as it requires it nowadays.
30 * Revision 1.1 2000/09/13 17:45:16 priikone
31 * Splitted SILC core library. Core library includes now only
32 * SILC protocol specific stuff. New utility library includes the
33 * old stuff from core library that is more generic purpose stuff.
35 * Revision 1.2 2000/07/05 06:06:35 priikone
36 * Global cosmetic change.
38 * Revision 1.1.1.1 2000/06/27 11:36:55 priikone
39 * Imported from internal CVS/Added Log headers.
44 #include "silcincludes.h"
46 /* Formats the arguments sent and puts them into the buffer sent as
47 argument. The buffer must be initialized beforehand and it must have
48 enough free space to include the formatted data. If this function
49 fails caller should not trust the buffer anymore and should free it.
50 This function is used, for example, to create packets to send over
53 int silc_buffer_format(SilcBuffer dst, ...)
56 SilcBufferParamType fmt;
57 unsigned char *start_ptr = dst->data;
61 /* Parse the arguments by formatting type. */
63 fmt = va_arg(ap, SilcBufferParamType);
66 case SILC_BUFFER_PARAM_SI8_CHAR:
68 char x = (char)va_arg(ap, int);
69 silc_buffer_put(dst, &x, 1);
70 silc_buffer_pull(dst, 1);
73 case SILC_BUFFER_PARAM_UI8_CHAR:
75 unsigned char x = (unsigned char)va_arg(ap, int);
76 silc_buffer_put(dst, &x, 1);
77 silc_buffer_pull(dst, 1);
80 case SILC_BUFFER_PARAM_SI16_SHORT:
83 short x = (short)va_arg(ap, int);
84 SILC_PUT16_MSB(x, xf);
85 silc_buffer_put(dst, xf, 2);
86 silc_buffer_pull(dst, 2);
89 case SILC_BUFFER_PARAM_UI16_SHORT:
92 unsigned short x = (unsigned short)va_arg(ap, int);
93 SILC_PUT16_MSB(x, xf);
94 silc_buffer_put(dst, xf, 2);
95 silc_buffer_pull(dst, 2);
98 case SILC_BUFFER_PARAM_SI32_INT:
101 int x = va_arg(ap, int);
102 SILC_PUT32_MSB(x, xf);
103 silc_buffer_put(dst, xf, 4);
104 silc_buffer_pull(dst, 4);
107 case SILC_BUFFER_PARAM_UI32_INT:
110 unsigned int x = va_arg(ap, unsigned int);
111 SILC_PUT32_MSB(x, xf);
112 silc_buffer_put(dst, xf, 4);
113 silc_buffer_pull(dst, 4);
116 case SILC_BUFFER_PARAM_UI16_STRING:
117 case SILC_BUFFER_PARAM_UI32_STRING:
118 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
119 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
121 unsigned char *x = va_arg(ap, unsigned char *);
122 silc_buffer_put(dst, x, strlen(x));
123 silc_buffer_pull(dst, strlen(x));
126 case SILC_BUFFER_PARAM_UI16_NSTRING:
127 case SILC_BUFFER_PARAM_UI32_NSTRING:
128 case SILC_BUFFER_PARAM_UI_XNSTRING:
129 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
130 case SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC:
131 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
133 unsigned char *x = va_arg(ap, unsigned char *);
134 unsigned int len = va_arg(ap, unsigned int);
135 silc_buffer_put(dst, x, len);
136 silc_buffer_pull(dst, len);
139 case SILC_BUFFER_PARAM_END:
143 SILC_LOG_ERROR(("Bad buffer formatting type `%d'. Could not "
144 "format the data.", fmt));
151 SILC_LOG_ERROR(("Error occured while formatting data"));
155 /* Push the buffer back to where it belongs. */
156 silc_buffer_push(dst, dst->data - start_ptr);
160 /* Unformats the buffer sent as argument. The unformatted data is returned
161 to the variable argument list of pointers. The buffer must point to the
162 start of the data area to be unformatted. Buffer maybe be safely free'd
163 after this returns succesfully. */
165 int silc_buffer_unformat(SilcBuffer src, ...)
168 SilcBufferParamType fmt;
169 unsigned char *start_ptr = src->data;
174 /* Parse the arguments by formatting type. */
176 fmt = va_arg(ap, SilcBufferParamType);
179 case SILC_BUFFER_PARAM_SI8_CHAR:
181 char *x = va_arg(ap, char *);
184 silc_buffer_pull(src, 1);
187 case SILC_BUFFER_PARAM_UI8_CHAR:
189 unsigned char *x = va_arg(ap, unsigned char *);
192 silc_buffer_pull(src, 1);
195 case SILC_BUFFER_PARAM_SI16_SHORT:
197 short *x = va_arg(ap, short *);
199 SILC_GET16_MSB(*x, src->data);
200 silc_buffer_pull(src, 2);
203 case SILC_BUFFER_PARAM_UI16_SHORT:
205 unsigned short *x = va_arg(ap, unsigned short *);
207 SILC_GET16_MSB(*x, src->data);
208 silc_buffer_pull(src, 2);
211 case SILC_BUFFER_PARAM_SI32_INT:
213 int *x = va_arg(ap, int *);
215 SILC_GET32_MSB(*x, src->data);
216 silc_buffer_pull(src, 4);
219 case SILC_BUFFER_PARAM_UI32_INT:
221 unsigned int *x = va_arg(ap, unsigned int *);
223 SILC_GET32_MSB(*x, src->data);
224 silc_buffer_pull(src, 4);
227 case SILC_BUFFER_PARAM_UI16_STRING:
230 unsigned char **x = va_arg(ap, unsigned char **);
231 SILC_GET16_MSB(len2, src->data);
232 silc_buffer_pull(src, 2);
233 if ((len2 > src->len))
238 memcpy(x, src->data, len2);
239 silc_buffer_pull(src, len2);
242 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
245 unsigned char **x = va_arg(ap, unsigned char **);
246 SILC_GET16_MSB(len2, src->data);
247 silc_buffer_pull(src, 2);
248 if ((len2 > src->len))
253 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
254 memcpy(*x, src->data, len2);
256 silc_buffer_pull(src, len2);
259 case SILC_BUFFER_PARAM_UI32_STRING:
262 unsigned char **x = va_arg(ap, unsigned char **);
263 SILC_GET32_MSB(len2, src->data);
264 silc_buffer_pull(src, 4);
265 if ((len2 > src->len))
270 memcpy(x, src->data, len2);
271 silc_buffer_pull(src, len2);
274 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
277 unsigned char **x = va_arg(ap, unsigned char **);
278 SILC_GET32_MSB(len2, src->data);
279 silc_buffer_pull(src, 4);
280 if ((len2 > src->len))
285 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
286 memcpy(*x, src->data, len2);
288 silc_buffer_pull(src, len2);
291 case SILC_BUFFER_PARAM_UI16_NSTRING:
294 unsigned char **x = va_arg(ap, unsigned char **);
295 unsigned short *len = va_arg(ap, unsigned short *);
296 SILC_GET16_MSB(len2, src->data);
297 silc_buffer_pull(src, 2);
298 if ((len2 > src->len))
305 memcpy(x, src->data, len2);
306 silc_buffer_pull(src, len2);
309 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
312 unsigned char **x = va_arg(ap, unsigned char **);
313 unsigned short *len = va_arg(ap, unsigned short *);
314 SILC_GET16_MSB(len2, src->data);
315 silc_buffer_pull(src, 2);
316 if ((len2 > src->len))
323 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
324 memcpy(*x, src->data, len2);
326 silc_buffer_pull(src, len2);
329 case SILC_BUFFER_PARAM_UI32_NSTRING:
332 unsigned char **x = va_arg(ap, unsigned char **);
333 unsigned int *len = va_arg(ap, unsigned int *);
334 SILC_GET32_MSB(len2, src->data);
335 silc_buffer_pull(src, 4);
336 if ((len2 > src->len))
343 memcpy(x, src->data, len2);
344 silc_buffer_pull(src, len2);
347 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
349 unsigned char **x = va_arg(ap, unsigned char **);
350 unsigned int len = va_arg(ap, unsigned int);
352 *x = silc_calloc(len + 1, sizeof(unsigned char));
353 memcpy(*x, src->data, len);
355 silc_buffer_pull(src, len);
358 case SILC_BUFFER_PARAM_UI_XNSTRING:
360 unsigned char **x = va_arg(ap, unsigned char **);
361 unsigned int len = va_arg(ap, unsigned int);
363 memcpy(x, src->data, len);
364 silc_buffer_pull(src, len);
367 case SILC_BUFFER_PARAM_END:
371 SILC_LOG_ERROR(("Bad buffer formatting type `%d'. Could not "
372 "format the data.", fmt));
379 SILC_LOG_ERROR(("Error occured while unformatting buffer"));
383 /* Push the buffer back to the start. */
384 len = src->data - start_ptr;
385 silc_buffer_push(src, len);