The SILC Project

source navigation ]
identifier search ]
freetext search ]
file search ]

silc/lib/silccore/silcargument.c

  1 /*
  2 
  3   silcargument.c
  4 
  5   Author: Pekka Riikonen <priikone@silcnet.org>
  6 
  7   Copyright (C) 2001 - 2007 Pekka Riikonen
  8 
  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; version 2 of the License.
 12 
 13   This program is distributed in the hope that it will be useful,
 14   but WITHOUT ANY WARRANTY; without even the implied warranty of
 15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16   GNU General Public License for more details.
 17 
 18 */
 19 /* Implementation of Argument Payload routines */
 20 /* $Id: silcargument.c,v 1.19 2007/07/01 16:42:02 priikone Exp $ */
 21 
 22 #include "silc.h"
 23 #include "silcargument.h"
 24 
 25 /*************************** Argument Payload *******************************/
 26 
 27 struct SilcArgumentPayloadStruct {
 28   SilcUInt32 argc;
 29   unsigned char **argv;
 30   SilcUInt32 *argv_lens;
 31   SilcUInt32 *argv_types;
 32   SilcUInt32 pos;
 33 };
 34 
 35 /* Parses arguments and returns them into Argument Payload structure. */
 36 
 37 SilcArgumentPayload silc_argument_payload_parse(const unsigned char *payload,
 38                                                 SilcUInt32 payload_len,
 39                                                 SilcUInt32 argc)
 40 {
 41   SilcBufferStruct buffer;
 42   SilcArgumentPayload newp;
 43   SilcUInt16 p_len = 0;
 44   unsigned char arg_num = 0;
 45   unsigned char arg_type = 0;
 46   SilcUInt32 pull_len = 0;
 47   int i = 0, ret;
 48 
 49   silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
 50   newp = silc_calloc(1, sizeof(*newp));
 51   if (!newp)
 52     return NULL;
 53   newp->argv = silc_calloc(argc, sizeof(unsigned char *));
 54   if (!newp->argv)
 55     goto err;
 56   newp->argv_lens = silc_calloc(argc, sizeof(SilcUInt32));
 57   if (!newp->argv_lens)
 58     goto err;
 59   newp->argv_types = silc_calloc(argc, sizeof(SilcUInt32));
 60   if (!newp->argv_types)
 61     goto err;
 62 
 63   /* Get arguments */
 64   arg_num = 1;
 65   for (i = 0; i < argc; i++) {
 66     ret = silc_buffer_unformat(&buffer,
 67                                SILC_STR_UI_SHORT(&p_len),
 68                                SILC_STR_UI_CHAR(&arg_type),
 69                                SILC_STR_END);
 70     if (ret == -1 || p_len > silc_buffer_len(&buffer) - 3) {
 71       SILC_LOG_DEBUG(("Malformed argument payload"));
 72       goto err;
 73     }
 74 
 75     newp->argv_lens[i] = p_len;
 76     newp->argv_types[i] = arg_type;
 77 
 78     /* Get argument data */
 79     silc_buffer_pull(&buffer, 3);
 80     ret = silc_buffer_unformat(&buffer,
 81                                SILC_STR_UI_XNSTRING_ALLOC(&newp->argv[i],
 82                                                           p_len),
 83                                SILC_STR_END);
 84     if (ret == -1) {
 85       SILC_LOG_DEBUG(("Malformed argument payload"));
 86       goto err;
 87     }
 88 
 89     silc_buffer_pull(&buffer, p_len);
 90     pull_len += 3 + p_len;
 91   }
 92 
 93   if (silc_buffer_len(&buffer) != 0) {
 94     SILC_LOG_DEBUG(("Malformed argument payload"));
 95     goto err;
 96   }
 97 
 98   newp->argc = argc;
 99   newp->pos = 0;
100 
101   silc_buffer_push(&buffer, pull_len);
102 
103   return newp;
104 
105  err:
106   SILC_LOG_DEBUG(("Error parsing argument payload"));
107   if (i)
108     for (ret = 0; ret < i; ret++)
109       silc_free(newp->argv[ret]);
110 
111   silc_free(newp->argv);
112   silc_free(newp->argv_lens);
113   silc_free(newp->argv_types);
114   silc_free(newp);
115 
116   return NULL;
117 }
118 
119 /* Encodes arguments in to Argument Paylods returning them to SilcBuffer. */
120 
121 SilcBuffer silc_argument_payload_encode(SilcUInt32 argc,
122                                         unsigned char **argv,
123                                         SilcUInt32 *argv_lens,
124                                         SilcUInt32 *argv_types)
125 {
126   SilcBuffer buffer;
127   SilcUInt32 len;
128   int i;
129 
130   len = 0;
131   for (i = 0; i < argc; i++)
132     len += 3 + (SilcUInt16)argv_lens[i];
133 
134   buffer = silc_buffer_alloc_size(len);
135   if (!buffer)
136     return NULL;
137 
138   /* Put arguments */
139   for (i = 0; i < argc; i++) {
140     silc_buffer_format(buffer,
141                        SILC_STR_UI_SHORT(argv_lens[i]),
142                        SILC_STR_UI_CHAR(argv_types[i]),
143                        SILC_STR_UI_XNSTRING(argv[i], (SilcUInt16)argv_lens[i]),
144                        SILC_STR_END);
145     silc_buffer_pull(buffer, 3 + (SilcUInt16)argv_lens[i]);
146   }
147 
148   silc_buffer_push(buffer, len);
149 
150   return buffer;
151 }
152 
153 /* Encode one argument to buffer */
154 
155 SilcBuffer silc_argument_payload_encode_one(SilcBuffer args,
156                                             unsigned char *arg,
157                                             SilcUInt32 arg_len,
158                                             SilcUInt32 arg_type)
159 {
160   SilcBuffer buffer = args;
161   SilcUInt32 len;
162 
163   len = 3 + (SilcUInt16)arg_len;
164   buffer = silc_buffer_realloc(buffer,
165                                (buffer ? silc_buffer_truelen(buffer) +
166                                 len : len));
167   if (!buffer)
168     return NULL;
169   silc_buffer_pull(buffer, silc_buffer_len(buffer));
170   silc_buffer_pull_tail(buffer, len);
171   silc_buffer_format(buffer,
172                      SILC_STR_UI_SHORT(arg_len),
173                      SILC_STR_UI_CHAR(arg_type),
174                      SILC_STR_UI_XNSTRING(arg, (SilcUInt16)arg_len),
175                      SILC_STR_END);
176   silc_buffer_push(buffer, buffer->data - buffer->head);
177 
178   return buffer;
179 }
180 
181 /* Same as above but encode the buffer from SilcArgumentPayload structure
182    instead of raw data. */
183 
184 SilcBuffer silc_argument_payload_encode_payload(SilcArgumentPayload payload)
185 {
186   SilcBuffer buffer;
187   SilcUInt32 len;
188   int i;
189 
190   len = 0;
191   for (i = 0; i < payload->argc; i++)
192     len += 3 + payload->argv_lens[i];
193 
194   buffer = silc_buffer_alloc_size(len);
195   if (!buffer)
196     return NULL;
197 
198   /* Put arguments */
199   for (i = 0; i < payload->argc; i++) {
200     silc_buffer_format(buffer,
201                        SILC_STR_UI_SHORT(payload->argv_lens[i]),
202                        SILC_STR_UI_CHAR(payload->argv_types[i]),
203                        SILC_STR_UI_XNSTRING(payload->argv[i],
204                                             payload->argv_lens[i]),
205                        SILC_STR_END);
206     silc_buffer_pull(buffer, 3 + payload->argv_lens[i]);
207   }
208 
209   silc_buffer_push(buffer, len);
210 
211   return buffer;
212 }
213 
214 /* Frees Argument Payload */
215 
216 void silc_argument_payload_free(SilcArgumentPayload payload)
217 {
218   int i;
219 
220   if (payload) {
221     for (i = 0; i < payload->argc; i++)
222       silc_free(payload->argv[i]);
223 
224     silc_free(payload->argv);
225     silc_free(payload->argv_lens);
226     silc_free(payload->argv_types);
227     silc_free(payload);
228   }
229 }
230 
231 /* Returns number of arguments in payload */
232 
233 SilcUInt32 silc_argument_get_arg_num(SilcArgumentPayload payload)
234 {
235   return payload ? payload->argc : 0;
236 }
237 
238 /* Returns first argument from payload. */
239 
240 unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
241                                            SilcUInt32 *type,
242                                            SilcUInt32 *ret_len)
243 {
244   if (!payload)
245     return NULL;
246 
247   payload->pos = 0;
248 
249   if (type)
250     *type = payload->argv_types[payload->pos];
251   if (ret_len)
252     *ret_len = payload->argv_lens[payload->pos];
253 
254   return payload->argv[payload->pos++];
255 }
256 
257 /* Returns next argument from payload or NULL if no more arguments. */
258 
259 unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
260                                           SilcUInt32 *type,
261                                           SilcUInt32 *ret_len)
262 {
263   if (!payload)
264     return NULL;
265 
266   if (payload->pos >= payload->argc)
267     return NULL;
268 
269   if (type)
270     *type = payload->argv_types[payload->pos];
271   if (ret_len)
272     *ret_len = payload->argv_lens[payload->pos];
273 
274   return payload->argv[payload->pos++];
275 }
276 
277 /* Returns argument which type is `type'. */
278 
279 unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
280                                           SilcUInt32 type,
281                                           SilcUInt32 *ret_len)
282 {
283   int i;
284 
285   if (!payload)
286     return NULL;
287 
288   for (i = 0; i < payload->argc; i++)
289     if (payload->argv_types[i] == type)
290       break;
291 
292   if (i >= payload->argc)
293     return NULL;
294 
295   if (ret_len)
296     *ret_len = payload->argv_lens[i];
297 
298   return payload->argv[i];
299 }
300 
301 /* Return argument already decoded */
302 
303 static SilcBool silc_argument_decode(unsigned char *data,
304                                      SilcUInt32 data_len,
305                                      SilcArgumentDecodeType dec_type,
306                                      void *ret_arg,
307                                      void **ret_arg_alloc)
308 {
309   switch (dec_type) {
310 
311   case SILC_ARGUMENT_ID:
312     if (ret_arg)
313       if (!silc_id_payload_parse_id(data, data_len, (SilcID *)ret_arg))
314         return FALSE;
315 
316     if (ret_arg_alloc) {
317       SilcID id;
318       if (!silc_id_payload_parse_id(data, data_len, &id))
319         return FALSE;
320       *ret_arg_alloc = silc_memdup(&id, sizeof(id));
321     }
322     break;
323 
324   case SILC_ARGUMENT_PUBLIC_KEY:
325     {
326       SilcPublicKey public_key;
327 
328       if (!ret_arg_alloc)
329         return FALSE;
330 
331       if (!silc_public_key_payload_decode(data, data_len, &public_key))
332         return FALSE;
333 
334       *ret_arg_alloc = public_key;
335     }
336     break;
337 
338   case SILC_ARGUMENT_ATTRIBUTES:
339     if (!ret_arg_alloc)
340       return FALSE;
341 
342     *ret_arg_alloc = silc_attribute_payload_parse(data, data_len);
343     break;
344 
345   case SILC_ARGUMENT_UINT32:
346     if (data_len != 4)
347       return FALSE;
348 
349     if (ret_arg) {
350       SilcUInt32 *i = ret_arg;
351       SILC_GET32_MSB(*i, data);
352     }
353 
354     if (ret_arg_alloc) {
355       SilcUInt32 i;
356       SILC_GET32_MSB(i, data);
357       *ret_arg_alloc = silc_memdup(&i, sizeof(i));
358     }
359     break;
360 
361   case SILC_ARGUMENT_BOOL:
362     if (data_len != sizeof(SilcBool))
363       return FALSE;
364 
365     if (ret_arg) {
366       SilcBool *b = ret_arg;
367       *b = (data[0] == 0x01 ? TRUE : FALSE);
368     }
369 
370     if (ret_arg_alloc) {
371       SilcBool b;
372       b = (data[0] == 0x01 ? TRUE : FALSE);
373       *ret_arg_alloc = silc_memdup(&b, sizeof(b));
374     }
375     break;
376 
377   default:
378     return FALSE;
379   }
380 
381   return TRUE;
382 }
383 
384 /* Return argument already decoded */
385 
386 SilcBool silc_argument_get_decoded(SilcArgumentPayload payload,
387                                    SilcUInt32 type,
388                                    SilcArgumentDecodeType dec_type,
389                                    void *ret_arg,
390                                    void **ret_arg_alloc)
391 {
392   unsigned char *tmp;
393   SilcUInt32 tmp_len;
394 
395   tmp = silc_argument_get_arg_type(payload, type, &tmp_len);
396   if (!tmp)
397     return FALSE;
398 
399   return silc_argument_decode(tmp, tmp_len, dec_type, ret_arg, ret_arg_alloc);
400 }
401 
402 /************************* Argument List Payload ****************************/
403 
404 /* Parses argument payload list */
405 
406 SilcArgumentPayload
407 silc_argument_list_parse(const unsigned char *payload,
408                          SilcUInt32 payload_len)
409 {
410   SilcArgumentPayload arg;
411   SilcUInt16 argc;
412 
413   if (payload_len < 5)
414     return NULL;
415 
416   SILC_GET16_MSB(argc, payload);
417 
418   arg = silc_argument_payload_parse(payload + 2, payload_len - 2, argc);
419 
420   return arg;
421 }
422 
423 /* Parses argument payload list of specific argument types */
424 
425 SilcDList
426 silc_argument_list_parse_decoded(const unsigned char *payload,
427                                  SilcUInt32 payload_len,
428                                  SilcArgumentDecodeType dec_type)
429 {
430   SilcArgumentPayload arg;
431   SilcArgumentDecodedList dec;
432   unsigned char *data;
433   SilcUInt32 data_len, type;
434   SilcDList list;
435 
436   arg = silc_argument_list_parse(payload, payload_len);
437   if (!arg)
438     return NULL;
439 
440   list = silc_dlist_init();
441   if (!list) {
442     silc_argument_payload_free(arg);
443     return NULL;
444   }
445 
446   data = silc_argument_get_first_arg(arg, &type, &data_len);
447   while (data) {
448     dec = silc_calloc(1, sizeof(*dec));
449     if (!dec)
450       continue;
451     dec->arg_type = type;
452     if (silc_argument_decode(data, data_len, dec_type, NULL, &dec->argument))
453       silc_dlist_add(list, dec);
454     else
455       silc_free(dec);
456     data = silc_argument_get_next_arg(arg, &type, &data_len);
457   }
458 
459   silc_argument_payload_free(arg);
460 
461   silc_dlist_start(list);
462 
463   return list;
464 }
465 
466 /* Free decoded argument payload list */
467 
468 void silc_argument_list_free(SilcDList list, SilcArgumentDecodeType dec_type)
469 {
470   SilcArgumentDecodedList dec;
471 
472   if (!list)
473     return;
474 
475   silc_dlist_start(list);
476   while ((dec = silc_dlist_get(list))) {
477     switch (dec_type) {
478 
479     case SILC_ARGUMENT_ID:
480     case SILC_ARGUMENT_UINT32:
481     case SILC_ARGUMENT_BOOL:
482       silc_free(dec->argument);
483       break;
484 
485     case SILC_ARGUMENT_PUBLIC_KEY:
486       silc_pkcs_public_key_free(dec->argument);
487       break;
488 
489     case SILC_ARGUMENT_ATTRIBUTES:
490       silc_attribute_payload_free(dec->argument);
491       break;
492 
493     default:
494       break;
495     }
496 
497     silc_free(dec);
498   }
499 
500   silc_dlist_uninit(list);
501 }
502 

This page was automatically generated by the LXR engine.
Free-text search provided by Glimpse