5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 - 2006 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; version 2 of the License.
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.
19 /* Implementation of Argument Payload routines */
23 #include "silcargument.h"
25 /*************************** Argument Payload *******************************/
27 struct SilcArgumentPayloadStruct {
30 SilcUInt32 *argv_lens;
31 SilcUInt32 *argv_types;
35 /* Parses arguments and returns them into Argument Payload structure. */
37 SilcArgumentPayload silc_argument_payload_parse(const unsigned char *payload,
38 SilcUInt32 payload_len,
41 SilcBufferStruct buffer;
42 SilcArgumentPayload newp;
44 unsigned char arg_num = 0;
45 unsigned char arg_type = 0;
46 SilcUInt32 pull_len = 0;
49 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
50 newp = silc_calloc(1, sizeof(*newp));
53 newp->argv = silc_calloc(argc, sizeof(unsigned char *));
56 newp->argv_lens = silc_calloc(argc, sizeof(SilcUInt32));
59 newp->argv_types = silc_calloc(argc, sizeof(SilcUInt32));
60 if (!newp->argv_types)
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),
70 if (ret == -1 || p_len > silc_buffer_len(&buffer) - 3)
73 newp->argv_lens[i] = p_len;
74 newp->argv_types[i] = arg_type;
76 /* Get argument data */
77 silc_buffer_pull(&buffer, 3);
78 ret = silc_buffer_unformat(&buffer,
79 SILC_STR_UI_XNSTRING_ALLOC(&newp->argv[i],
85 silc_buffer_pull(&buffer, p_len);
86 pull_len += 3 + p_len;
89 if (silc_buffer_len(&buffer) != 0) {
90 SILC_LOG_DEBUG(("Malformed argument payload"));
97 silc_buffer_push(&buffer, pull_len);
102 SILC_LOG_DEBUG(("Error parsing argument payload"));
104 for (ret = 0; ret < i; ret++)
105 silc_free(newp->argv[ret]);
107 silc_free(newp->argv);
108 silc_free(newp->argv_lens);
109 silc_free(newp->argv_types);
115 /* Encodes arguments in to Argument Paylods returning them to SilcBuffer. */
117 SilcBuffer silc_argument_payload_encode(SilcUInt32 argc,
118 unsigned char **argv,
119 SilcUInt32 *argv_lens,
120 SilcUInt32 *argv_types)
127 for (i = 0; i < argc; i++)
128 len += 3 + (SilcUInt16)argv_lens[i];
130 buffer = silc_buffer_alloc_size(len);
135 for (i = 0; i < argc; i++) {
136 silc_buffer_format(buffer,
137 SILC_STR_UI_SHORT(argv_lens[i]),
138 SILC_STR_UI_CHAR(argv_types[i]),
139 SILC_STR_UI_XNSTRING(argv[i], (SilcUInt16)argv_lens[i]),
141 silc_buffer_pull(buffer, 3 + (SilcUInt16)argv_lens[i]);
144 silc_buffer_push(buffer, len);
149 /* Encode one argument to buffer */
151 SilcBuffer silc_argument_payload_encode_one(SilcBuffer args,
156 SilcBuffer buffer = args;
159 len = 3 + (SilcUInt16)arg_len;
160 buffer = silc_buffer_realloc(buffer,
161 (buffer ? silc_buffer_truelen(buffer) +
165 silc_buffer_pull(buffer, silc_buffer_len(buffer));
166 silc_buffer_pull_tail(buffer, len);
167 silc_buffer_format(buffer,
168 SILC_STR_UI_SHORT(arg_len),
169 SILC_STR_UI_CHAR(arg_type),
170 SILC_STR_UI_XNSTRING(arg, (SilcUInt16)arg_len),
172 silc_buffer_push(buffer, buffer->data - buffer->head);
177 /* Same as above but encode the buffer from SilcArgumentPayload structure
178 instead of raw data. */
180 SilcBuffer silc_argument_payload_encode_payload(SilcArgumentPayload payload)
187 for (i = 0; i < payload->argc; i++)
188 len += 3 + payload->argv_lens[i];
190 buffer = silc_buffer_alloc_size(len);
195 for (i = 0; i < payload->argc; i++) {
196 silc_buffer_format(buffer,
197 SILC_STR_UI_SHORT(payload->argv_lens[i]),
198 SILC_STR_UI_CHAR(payload->argv_types[i]),
199 SILC_STR_UI_XNSTRING(payload->argv[i],
200 payload->argv_lens[i]),
202 silc_buffer_pull(buffer, 3 + payload->argv_lens[i]);
205 silc_buffer_push(buffer, len);
210 /* Frees Argument Payload */
212 void silc_argument_payload_free(SilcArgumentPayload payload)
217 for (i = 0; i < payload->argc; i++)
218 silc_free(payload->argv[i]);
220 silc_free(payload->argv);
221 silc_free(payload->argv_lens);
222 silc_free(payload->argv_types);
227 /* Returns number of arguments in payload */
229 SilcUInt32 silc_argument_get_arg_num(SilcArgumentPayload payload)
231 return payload ? payload->argc : 0;
234 /* Returns first argument from payload. */
236 unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
246 *type = payload->argv_types[payload->pos];
248 *ret_len = payload->argv_lens[payload->pos];
250 return payload->argv[payload->pos++];
253 /* Returns next argument from payload or NULL if no more arguments. */
255 unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
262 if (payload->pos >= payload->argc)
266 *type = payload->argv_types[payload->pos];
268 *ret_len = payload->argv_lens[payload->pos];
270 return payload->argv[payload->pos++];
273 /* Returns argument which type is `type'. */
275 unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
284 for (i = 0; i < payload->argc; i++)
285 if (payload->argv_types[i] == type)
288 if (i >= payload->argc)
292 *ret_len = payload->argv_lens[i];
294 return payload->argv[i];
297 /* Return argument already decoded */
299 static SilcBool silc_argument_decode(unsigned char *data,
301 SilcArgumentDecodeType dec_type,
303 void **ret_arg_alloc)
307 case SILC_ARGUMENT_ID:
309 if (!silc_id_payload_parse_id(data, data_len, (SilcID *)ret_arg))
314 if (!silc_id_payload_parse_id(data, data_len, &id))
316 *ret_arg_alloc = silc_memdup(&id, sizeof(id));
320 case SILC_ARGUMENT_PUBLIC_KEY:
322 SilcPublicKey public_key;
327 if (!silc_public_key_payload_decode(data, data_len, &public_key))
330 *ret_arg_alloc = public_key;
334 case SILC_ARGUMENT_ATTRIBUTES:
338 *ret_arg_alloc = silc_attribute_payload_parse(data, data_len);
341 case SILC_ARGUMENT_UINT32:
346 SilcUInt32 *i = ret_arg;
347 SILC_GET32_MSB(*i, data);
352 SILC_GET32_MSB(i, data);
353 *ret_arg_alloc = silc_memdup(&i, sizeof(i));
357 case SILC_ARGUMENT_BOOL:
358 if (data_len != sizeof(SilcBool))
362 SilcBool *b = ret_arg;
363 *b = (data[0] == 0x01 ? TRUE : FALSE);
368 b = (data[0] == 0x01 ? TRUE : FALSE);
369 *ret_arg_alloc = silc_memdup(&b, sizeof(b));
380 /* Return argument already decoded */
382 SilcBool silc_argument_get_decoded(SilcArgumentPayload payload,
384 SilcArgumentDecodeType dec_type,
386 void **ret_arg_alloc)
391 tmp = silc_argument_get_arg_type(payload, type, &tmp_len);
395 return silc_argument_decode(tmp, tmp_len, dec_type, ret_arg, ret_arg_alloc);
398 /************************* Argument List Payload ****************************/
400 /* Parses argument payload list */
403 silc_argument_list_parse(const unsigned char *payload,
404 SilcUInt32 payload_len)
406 SilcArgumentPayload arg;
412 SILC_GET16_MSB(argc, payload);
414 arg = silc_argument_payload_parse(payload + 2, payload_len - 2, argc);
419 /* Parses argument payload list of specific argument types */
422 silc_argument_list_parse_decoded(const unsigned char *payload,
423 SilcUInt32 payload_len,
424 SilcArgumentDecodeType dec_type)
426 SilcArgumentPayload arg;
427 SilcArgumentDecodedList dec;
429 SilcUInt32 data_len, type;
432 arg = silc_argument_list_parse(payload, payload_len);
436 list = silc_dlist_init();
438 silc_argument_payload_free(arg);
442 data = silc_argument_get_first_arg(arg, &type, &data_len);
444 dec = silc_calloc(1, sizeof(*dec));
447 dec->arg_type = type;
448 if (silc_argument_decode(data, data_len, dec_type, NULL, &dec->argument))
449 silc_dlist_add(list, dec);
452 data = silc_argument_get_next_arg(arg, &type, &data_len);
455 silc_argument_payload_free(arg);
457 silc_dlist_start(list);
462 /* Free decoded argument payload list */
464 void silc_argument_list_free(SilcDList list, SilcArgumentDecodeType dec_type)
466 SilcArgumentDecodedList dec;
471 silc_dlist_start(list);
472 while ((dec = silc_dlist_get(list))) {
475 case SILC_ARGUMENT_ID:
476 case SILC_ARGUMENT_UINT32:
477 case SILC_ARGUMENT_BOOL:
478 silc_free(dec->argument);
481 case SILC_ARGUMENT_PUBLIC_KEY:
482 silc_pkcs_public_key_free(dec->argument);
485 case SILC_ARGUMENT_ATTRIBUTES:
486 silc_attribute_payload_free(dec->argument);
496 silc_dlist_uninit(list);