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/07/05 06:06:35 priikone
28 * Global cosmetic change.
30 * Revision 1.1.1.1 2000/06/27 11:36:55 priikone
31 * Imported from internal CVS/Added Log headers.
36 #include "silcincludes.h"
38 /* Formats the arguments sent and puts them into the buffer sent as
39 argument. The buffer must be initialized beforehand and it must have
40 enough free space to include the formatted data. If this function
41 fails caller should not trust the buffer anymore and should free it.
42 This function is used, for example, to create packets to send over
45 int silc_buffer_format(SilcBuffer dst, ...)
48 SilcBufferParamType fmt;
49 unsigned char *start_ptr = dst->data;
53 /* Parse the arguments by formatting type. */
55 fmt = va_arg(ap, SilcBufferParamType);
58 case SILC_BUFFER_PARAM_SI8_CHAR:
60 char x = va_arg(ap, char);
61 silc_buffer_put(dst, &x, 1);
62 silc_buffer_pull(dst, 1);
65 case SILC_BUFFER_PARAM_UI8_CHAR:
67 unsigned char x = va_arg(ap, unsigned char);
68 silc_buffer_put(dst, &x, 1);
69 silc_buffer_pull(dst, 1);
72 case SILC_BUFFER_PARAM_SI16_SHORT:
75 short x = va_arg(ap, short);
76 SILC_PUT16_MSB(x, xf);
77 silc_buffer_put(dst, xf, 2);
78 silc_buffer_pull(dst, 2);
81 case SILC_BUFFER_PARAM_UI16_SHORT:
84 unsigned short x = va_arg(ap, unsigned short);
85 SILC_PUT16_MSB(x, xf);
86 silc_buffer_put(dst, xf, 2);
87 silc_buffer_pull(dst, 2);
90 case SILC_BUFFER_PARAM_SI32_INT:
93 int x = va_arg(ap, 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_UI32_INT:
102 unsigned int x = va_arg(ap, unsigned int);
103 SILC_PUT32_MSB(x, xf);
104 silc_buffer_put(dst, xf, 4);
105 silc_buffer_pull(dst, 4);
108 case SILC_BUFFER_PARAM_UI16_STRING:
109 case SILC_BUFFER_PARAM_UI32_STRING:
110 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
111 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
113 unsigned char *x = va_arg(ap, unsigned char *);
114 silc_buffer_put(dst, x, strlen(x));
115 silc_buffer_pull(dst, strlen(x));
118 case SILC_BUFFER_PARAM_UI16_NSTRING:
119 case SILC_BUFFER_PARAM_UI32_NSTRING:
120 case SILC_BUFFER_PARAM_UI_XNSTRING:
121 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
122 case SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC:
123 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
125 unsigned char *x = va_arg(ap, unsigned char *);
126 unsigned int len = va_arg(ap, unsigned int);
127 silc_buffer_put(dst, x, len);
128 silc_buffer_pull(dst, len);
131 case SILC_BUFFER_PARAM_END:
135 SILC_LOG_ERROR(("Bad buffer formatting type `%d'. Could not "
136 "format the data.", fmt));
143 SILC_LOG_ERROR(("Error occured while formatting data"));
147 /* Push the buffer back to where it belongs. */
148 silc_buffer_push(dst, dst->data - start_ptr);
152 /* Unformats the buffer sent as argument. The unformatted data is returned
153 to the variable argument list of pointers. The buffer must point to the
154 start of the data area to be unformatted. Buffer maybe be safely free'd
155 after this returns succesfully. */
157 int silc_buffer_unformat(SilcBuffer src, ...)
160 SilcBufferParamType fmt;
161 unsigned char *start_ptr = src->data;
166 /* Parse the arguments by formatting type. */
168 fmt = va_arg(ap, SilcBufferParamType);
171 case SILC_BUFFER_PARAM_SI8_CHAR:
173 char *x = va_arg(ap, char *);
176 silc_buffer_pull(src, 1);
179 case SILC_BUFFER_PARAM_UI8_CHAR:
181 unsigned char *x = va_arg(ap, unsigned char *);
184 silc_buffer_pull(src, 1);
187 case SILC_BUFFER_PARAM_SI16_SHORT:
189 short *x = va_arg(ap, short *);
191 SILC_GET16_MSB(*x, src->data);
192 silc_buffer_pull(src, 2);
195 case SILC_BUFFER_PARAM_UI16_SHORT:
197 unsigned short *x = va_arg(ap, unsigned short *);
199 SILC_GET16_MSB(*x, src->data);
200 silc_buffer_pull(src, 2);
203 case SILC_BUFFER_PARAM_SI32_INT:
205 int *x = va_arg(ap, int *);
207 SILC_GET32_MSB(*x, src->data);
208 silc_buffer_pull(src, 4);
211 case SILC_BUFFER_PARAM_UI32_INT:
213 unsigned int *x = va_arg(ap, unsigned int *);
215 SILC_GET32_MSB(*x, src->data);
216 silc_buffer_pull(src, 4);
219 case SILC_BUFFER_PARAM_UI16_STRING:
222 unsigned char **x = va_arg(ap, unsigned char **);
223 SILC_GET16_MSB(len2, src->data);
224 silc_buffer_pull(src, 2);
225 if ((len2 > src->len))
230 memcpy(x, src->data, len2);
231 silc_buffer_pull(src, len2);
234 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
237 unsigned char **x = va_arg(ap, unsigned char **);
238 SILC_GET16_MSB(len2, src->data);
239 silc_buffer_pull(src, 2);
240 if ((len2 > src->len))
245 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
246 memcpy(*x, src->data, len2);
248 silc_buffer_pull(src, len2);
251 case SILC_BUFFER_PARAM_UI32_STRING:
254 unsigned char **x = va_arg(ap, unsigned char **);
255 SILC_GET32_MSB(len2, src->data);
256 silc_buffer_pull(src, 4);
257 if ((len2 > src->len))
262 memcpy(x, src->data, len2);
263 silc_buffer_pull(src, len2);
266 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
269 unsigned char **x = va_arg(ap, unsigned char **);
270 SILC_GET32_MSB(len2, src->data);
271 silc_buffer_pull(src, 4);
272 if ((len2 > src->len))
277 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
278 memcpy(*x, src->data, len2);
280 silc_buffer_pull(src, len2);
283 case SILC_BUFFER_PARAM_UI16_NSTRING:
286 unsigned char **x = va_arg(ap, unsigned char **);
287 unsigned short *len = va_arg(ap, unsigned short *);
288 SILC_GET16_MSB(len2, src->data);
289 silc_buffer_pull(src, 2);
290 if ((len2 > src->len))
297 memcpy(x, src->data, len2);
298 silc_buffer_pull(src, len2);
301 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
304 unsigned char **x = va_arg(ap, unsigned char **);
305 unsigned short *len = va_arg(ap, unsigned short *);
306 SILC_GET16_MSB(len2, src->data);
307 silc_buffer_pull(src, 2);
308 if ((len2 > src->len))
315 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
316 memcpy(*x, src->data, len2);
318 silc_buffer_pull(src, len2);
321 case SILC_BUFFER_PARAM_UI32_NSTRING:
324 unsigned char **x = va_arg(ap, unsigned char **);
325 unsigned int *len = va_arg(ap, unsigned int *);
326 SILC_GET32_MSB(len2, src->data);
327 silc_buffer_pull(src, 4);
328 if ((len2 > src->len))
335 memcpy(x, src->data, len2);
336 silc_buffer_pull(src, len2);
339 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
341 unsigned char **x = va_arg(ap, unsigned char **);
342 unsigned int len = va_arg(ap, unsigned int);
344 *x = silc_calloc(len + 1, sizeof(unsigned char));
345 memcpy(*x, src->data, len);
347 silc_buffer_pull(src, len);
350 case SILC_BUFFER_PARAM_UI_XNSTRING:
352 unsigned char **x = va_arg(ap, unsigned char **);
353 unsigned int len = va_arg(ap, unsigned int);
355 memcpy(x, src->data, len);
356 silc_buffer_pull(src, len);
359 case SILC_BUFFER_PARAM_END:
363 SILC_LOG_ERROR(("Bad buffer formatting type `%d'. Could not "
364 "format the data.", fmt));
371 SILC_LOG_ERROR(("Error occured while unformatting buffer"));
375 /* Push the buffer back to the start. */
376 len = src->data - start_ptr;
377 silc_buffer_push(src, len);