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 #include "silcincludes.h"
29 /* Formats the arguments sent and puts them into the buffer sent as
30 argument. The buffer must be initialized beforehand and it must have
31 enough free space to include the formatted data. If this function
32 fails caller should not trust the buffer anymore and should free it.
33 This function is used, for example, to create packets to send over
36 int silc_buffer_format(SilcBuffer dst, ...)
39 SilcBufferParamType fmt;
40 unsigned char *start_ptr = dst->data;
44 /* Parse the arguments by formatting type. */
46 fmt = va_arg(ap, SilcBufferParamType);
49 case SILC_BUFFER_PARAM_SI8_CHAR:
51 char x = (char)va_arg(ap, int);
52 silc_buffer_put(dst, &x, 1);
53 silc_buffer_pull(dst, 1);
56 case SILC_BUFFER_PARAM_UI8_CHAR:
58 unsigned char x = (unsigned char)va_arg(ap, int);
59 silc_buffer_put(dst, &x, 1);
60 silc_buffer_pull(dst, 1);
63 case SILC_BUFFER_PARAM_SI16_SHORT:
66 short x = (short)va_arg(ap, int);
67 SILC_PUT16_MSB(x, xf);
68 silc_buffer_put(dst, xf, 2);
69 silc_buffer_pull(dst, 2);
72 case SILC_BUFFER_PARAM_UI16_SHORT:
75 unsigned short x = (unsigned short)va_arg(ap, int);
76 SILC_PUT16_MSB(x, xf);
77 silc_buffer_put(dst, xf, 2);
78 silc_buffer_pull(dst, 2);
81 case SILC_BUFFER_PARAM_SI32_INT:
84 int x = va_arg(ap, int);
85 SILC_PUT32_MSB(x, xf);
86 silc_buffer_put(dst, xf, 4);
87 silc_buffer_pull(dst, 4);
90 case SILC_BUFFER_PARAM_UI32_INT:
93 unsigned int x = va_arg(ap, unsigned int);
94 SILC_PUT32_MSB(x, xf);
95 silc_buffer_put(dst, xf, 4);
96 silc_buffer_pull(dst, 4);
99 case SILC_BUFFER_PARAM_UI16_STRING:
100 case SILC_BUFFER_PARAM_UI32_STRING:
101 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
102 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
104 unsigned char *x = va_arg(ap, unsigned char *);
105 silc_buffer_put(dst, x, strlen(x));
106 silc_buffer_pull(dst, strlen(x));
109 case SILC_BUFFER_PARAM_UI16_NSTRING:
110 case SILC_BUFFER_PARAM_UI32_NSTRING:
111 case SILC_BUFFER_PARAM_UI_XNSTRING:
112 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
113 case SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC:
114 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
116 unsigned char *x = va_arg(ap, unsigned char *);
117 unsigned int len = va_arg(ap, unsigned int);
118 silc_buffer_put(dst, x, len);
119 silc_buffer_pull(dst, len);
122 case SILC_BUFFER_PARAM_END:
126 SILC_LOG_ERROR(("Bad buffer formatting type `%d'. Could not "
127 "format the data.", fmt));
134 SILC_LOG_ERROR(("Error occured while formatting data"));
138 /* Push the buffer back to where it belongs. */
139 silc_buffer_push(dst, dst->data - start_ptr);
143 /* Unformats the buffer sent as argument. The unformatted data is returned
144 to the variable argument list of pointers. The buffer must point to the
145 start of the data area to be unformatted. Buffer maybe be safely free'd
146 after this returns succesfully. */
148 int silc_buffer_unformat(SilcBuffer src, ...)
151 SilcBufferParamType fmt;
152 unsigned char *start_ptr = src->data;
157 /* Parse the arguments by formatting type. */
159 fmt = va_arg(ap, SilcBufferParamType);
162 case SILC_BUFFER_PARAM_SI8_CHAR:
164 char *x = va_arg(ap, char *);
167 silc_buffer_pull(src, 1);
170 case SILC_BUFFER_PARAM_UI8_CHAR:
172 unsigned char *x = va_arg(ap, unsigned char *);
175 silc_buffer_pull(src, 1);
178 case SILC_BUFFER_PARAM_SI16_SHORT:
180 short *x = va_arg(ap, short *);
182 SILC_GET16_MSB(*x, src->data);
183 silc_buffer_pull(src, 2);
186 case SILC_BUFFER_PARAM_UI16_SHORT:
188 unsigned short *x = va_arg(ap, unsigned short *);
190 SILC_GET16_MSB(*x, src->data);
191 silc_buffer_pull(src, 2);
194 case SILC_BUFFER_PARAM_SI32_INT:
196 int *x = va_arg(ap, int *);
198 SILC_GET32_MSB(*x, src->data);
199 silc_buffer_pull(src, 4);
202 case SILC_BUFFER_PARAM_UI32_INT:
204 unsigned int *x = va_arg(ap, unsigned int *);
206 SILC_GET32_MSB(*x, src->data);
207 silc_buffer_pull(src, 4);
210 case SILC_BUFFER_PARAM_UI16_STRING:
213 unsigned char **x = va_arg(ap, unsigned char **);
214 SILC_GET16_MSB(len2, src->data);
215 silc_buffer_pull(src, 2);
216 if ((len2 > src->len))
221 memcpy(x, src->data, len2);
222 silc_buffer_pull(src, len2);
225 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
228 unsigned char **x = va_arg(ap, unsigned char **);
229 SILC_GET16_MSB(len2, src->data);
230 silc_buffer_pull(src, 2);
231 if ((len2 > src->len))
236 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
237 memcpy(*x, src->data, len2);
239 silc_buffer_pull(src, len2);
242 case SILC_BUFFER_PARAM_UI32_STRING:
245 unsigned char **x = va_arg(ap, unsigned char **);
246 SILC_GET32_MSB(len2, src->data);
247 silc_buffer_pull(src, 4);
248 if ((len2 > src->len))
253 memcpy(x, src->data, len2);
254 silc_buffer_pull(src, len2);
257 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
260 unsigned char **x = va_arg(ap, unsigned char **);
261 SILC_GET32_MSB(len2, src->data);
262 silc_buffer_pull(src, 4);
263 if ((len2 > src->len))
268 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
269 memcpy(*x, src->data, len2);
271 silc_buffer_pull(src, len2);
274 case SILC_BUFFER_PARAM_UI16_NSTRING:
277 unsigned char **x = va_arg(ap, unsigned char **);
278 unsigned short *len = va_arg(ap, unsigned short *);
279 SILC_GET16_MSB(len2, src->data);
280 silc_buffer_pull(src, 2);
281 if ((len2 > src->len))
288 memcpy(x, src->data, len2);
289 silc_buffer_pull(src, len2);
292 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
295 unsigned char **x = va_arg(ap, unsigned char **);
296 unsigned short *len = va_arg(ap, unsigned short *);
297 SILC_GET16_MSB(len2, src->data);
298 silc_buffer_pull(src, 2);
299 if ((len2 > src->len))
306 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
307 memcpy(*x, src->data, len2);
309 silc_buffer_pull(src, len2);
312 case SILC_BUFFER_PARAM_UI32_NSTRING:
315 unsigned char **x = va_arg(ap, unsigned char **);
316 unsigned int *len = va_arg(ap, unsigned int *);
317 SILC_GET32_MSB(len2, src->data);
318 silc_buffer_pull(src, 4);
319 if ((len2 > src->len))
326 memcpy(x, src->data, len2);
327 silc_buffer_pull(src, len2);
330 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
332 unsigned char **x = va_arg(ap, unsigned char **);
333 unsigned int len = va_arg(ap, unsigned int);
335 *x = silc_calloc(len + 1, sizeof(unsigned char));
336 memcpy(*x, src->data, len);
338 silc_buffer_pull(src, len);
341 case SILC_BUFFER_PARAM_UI_XNSTRING:
343 unsigned char **x = va_arg(ap, unsigned char **);
344 unsigned int len = va_arg(ap, unsigned int);
346 memcpy(x, src->data, len);
347 silc_buffer_pull(src, len);
350 case SILC_BUFFER_PARAM_END:
354 SILC_LOG_ERROR(("Bad buffer formatting type `%d'. Could not "
355 "format the data.", fmt));
362 SILC_LOG_ERROR(("Error occured while unformatting buffer"));
366 /* Push the buffer back to the start. */
367 len = src->data - start_ptr;
368 silc_buffer_push(src, len);