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/09/13 17:45:16 priikone
28 * Splitted SILC core library. Core library includes now only
29 * SILC protocol specific stuff. New utility library includes the
30 * old stuff from core library that is more generic purpose stuff.
32 * Revision 1.2 2000/07/05 06:06:35 priikone
33 * Global cosmetic change.
35 * Revision 1.1.1.1 2000/06/27 11:36:55 priikone
36 * Imported from internal CVS/Added Log headers.
41 #include "silcincludes.h"
43 /* Formats the arguments sent and puts them into the buffer sent as
44 argument. The buffer must be initialized beforehand and it must have
45 enough free space to include the formatted data. If this function
46 fails caller should not trust the buffer anymore and should free it.
47 This function is used, for example, to create packets to send over
50 int silc_buffer_format(SilcBuffer dst, ...)
53 SilcBufferParamType fmt;
54 unsigned char *start_ptr = dst->data;
58 /* Parse the arguments by formatting type. */
60 fmt = va_arg(ap, SilcBufferParamType);
63 case SILC_BUFFER_PARAM_SI8_CHAR:
65 char x = va_arg(ap, char);
66 silc_buffer_put(dst, &x, 1);
67 silc_buffer_pull(dst, 1);
70 case SILC_BUFFER_PARAM_UI8_CHAR:
72 unsigned char x = va_arg(ap, unsigned char);
73 silc_buffer_put(dst, &x, 1);
74 silc_buffer_pull(dst, 1);
77 case SILC_BUFFER_PARAM_SI16_SHORT:
80 short x = va_arg(ap, short);
81 SILC_PUT16_MSB(x, xf);
82 silc_buffer_put(dst, xf, 2);
83 silc_buffer_pull(dst, 2);
86 case SILC_BUFFER_PARAM_UI16_SHORT:
89 unsigned short x = va_arg(ap, unsigned short);
90 SILC_PUT16_MSB(x, xf);
91 silc_buffer_put(dst, xf, 2);
92 silc_buffer_pull(dst, 2);
95 case SILC_BUFFER_PARAM_SI32_INT:
98 int x = va_arg(ap, int);
99 SILC_PUT32_MSB(x, xf);
100 silc_buffer_put(dst, xf, 4);
101 silc_buffer_pull(dst, 4);
104 case SILC_BUFFER_PARAM_UI32_INT:
107 unsigned int x = va_arg(ap, unsigned int);
108 SILC_PUT32_MSB(x, xf);
109 silc_buffer_put(dst, xf, 4);
110 silc_buffer_pull(dst, 4);
113 case SILC_BUFFER_PARAM_UI16_STRING:
114 case SILC_BUFFER_PARAM_UI32_STRING:
115 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
116 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
118 unsigned char *x = va_arg(ap, unsigned char *);
119 silc_buffer_put(dst, x, strlen(x));
120 silc_buffer_pull(dst, strlen(x));
123 case SILC_BUFFER_PARAM_UI16_NSTRING:
124 case SILC_BUFFER_PARAM_UI32_NSTRING:
125 case SILC_BUFFER_PARAM_UI_XNSTRING:
126 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
127 case SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC:
128 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
130 unsigned char *x = va_arg(ap, unsigned char *);
131 unsigned int len = va_arg(ap, unsigned int);
132 silc_buffer_put(dst, x, len);
133 silc_buffer_pull(dst, len);
136 case SILC_BUFFER_PARAM_END:
140 SILC_LOG_ERROR(("Bad buffer formatting type `%d'. Could not "
141 "format the data.", fmt));
148 SILC_LOG_ERROR(("Error occured while formatting data"));
152 /* Push the buffer back to where it belongs. */
153 silc_buffer_push(dst, dst->data - start_ptr);
157 /* Unformats the buffer sent as argument. The unformatted data is returned
158 to the variable argument list of pointers. The buffer must point to the
159 start of the data area to be unformatted. Buffer maybe be safely free'd
160 after this returns succesfully. */
162 int silc_buffer_unformat(SilcBuffer src, ...)
165 SilcBufferParamType fmt;
166 unsigned char *start_ptr = src->data;
171 /* Parse the arguments by formatting type. */
173 fmt = va_arg(ap, SilcBufferParamType);
176 case SILC_BUFFER_PARAM_SI8_CHAR:
178 char *x = va_arg(ap, char *);
181 silc_buffer_pull(src, 1);
184 case SILC_BUFFER_PARAM_UI8_CHAR:
186 unsigned char *x = va_arg(ap, unsigned char *);
189 silc_buffer_pull(src, 1);
192 case SILC_BUFFER_PARAM_SI16_SHORT:
194 short *x = va_arg(ap, short *);
196 SILC_GET16_MSB(*x, src->data);
197 silc_buffer_pull(src, 2);
200 case SILC_BUFFER_PARAM_UI16_SHORT:
202 unsigned short *x = va_arg(ap, unsigned short *);
204 SILC_GET16_MSB(*x, src->data);
205 silc_buffer_pull(src, 2);
208 case SILC_BUFFER_PARAM_SI32_INT:
210 int *x = va_arg(ap, int *);
212 SILC_GET32_MSB(*x, src->data);
213 silc_buffer_pull(src, 4);
216 case SILC_BUFFER_PARAM_UI32_INT:
218 unsigned int *x = va_arg(ap, unsigned int *);
220 SILC_GET32_MSB(*x, src->data);
221 silc_buffer_pull(src, 4);
224 case SILC_BUFFER_PARAM_UI16_STRING:
227 unsigned char **x = va_arg(ap, unsigned char **);
228 SILC_GET16_MSB(len2, src->data);
229 silc_buffer_pull(src, 2);
230 if ((len2 > src->len))
235 memcpy(x, src->data, len2);
236 silc_buffer_pull(src, len2);
239 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
242 unsigned char **x = va_arg(ap, unsigned char **);
243 SILC_GET16_MSB(len2, src->data);
244 silc_buffer_pull(src, 2);
245 if ((len2 > src->len))
250 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
251 memcpy(*x, src->data, len2);
253 silc_buffer_pull(src, len2);
256 case SILC_BUFFER_PARAM_UI32_STRING:
259 unsigned char **x = va_arg(ap, unsigned char **);
260 SILC_GET32_MSB(len2, src->data);
261 silc_buffer_pull(src, 4);
262 if ((len2 > src->len))
267 memcpy(x, src->data, len2);
268 silc_buffer_pull(src, len2);
271 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
274 unsigned char **x = va_arg(ap, unsigned char **);
275 SILC_GET32_MSB(len2, src->data);
276 silc_buffer_pull(src, 4);
277 if ((len2 > src->len))
282 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
283 memcpy(*x, src->data, len2);
285 silc_buffer_pull(src, len2);
288 case SILC_BUFFER_PARAM_UI16_NSTRING:
291 unsigned char **x = va_arg(ap, unsigned char **);
292 unsigned short *len = va_arg(ap, unsigned short *);
293 SILC_GET16_MSB(len2, src->data);
294 silc_buffer_pull(src, 2);
295 if ((len2 > src->len))
302 memcpy(x, src->data, len2);
303 silc_buffer_pull(src, len2);
306 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
309 unsigned char **x = va_arg(ap, unsigned char **);
310 unsigned short *len = va_arg(ap, unsigned short *);
311 SILC_GET16_MSB(len2, src->data);
312 silc_buffer_pull(src, 2);
313 if ((len2 > src->len))
320 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
321 memcpy(*x, src->data, len2);
323 silc_buffer_pull(src, len2);
326 case SILC_BUFFER_PARAM_UI32_NSTRING:
329 unsigned char **x = va_arg(ap, unsigned char **);
330 unsigned int *len = va_arg(ap, unsigned int *);
331 SILC_GET32_MSB(len2, src->data);
332 silc_buffer_pull(src, 4);
333 if ((len2 > src->len))
340 memcpy(x, src->data, len2);
341 silc_buffer_pull(src, len2);
344 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
346 unsigned char **x = va_arg(ap, unsigned char **);
347 unsigned int len = va_arg(ap, unsigned int);
349 *x = silc_calloc(len + 1, sizeof(unsigned char));
350 memcpy(*x, src->data, len);
352 silc_buffer_pull(src, len);
355 case SILC_BUFFER_PARAM_UI_XNSTRING:
357 unsigned char **x = va_arg(ap, unsigned char **);
358 unsigned int len = va_arg(ap, unsigned int);
360 memcpy(x, src->data, len);
361 silc_buffer_pull(src, len);
364 case SILC_BUFFER_PARAM_END:
368 SILC_LOG_ERROR(("Bad buffer formatting type `%d'. Could not "
369 "format the data.", fmt));
376 SILC_LOG_ERROR(("Error occured while unformatting buffer"));
380 /* Push the buffer back to the start. */
381 len = src->data - start_ptr;
382 silc_buffer_push(src, len);