5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 - 2007 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) {
71 SILC_LOG_DEBUG(("Malformed argument payload"));
75 newp->argv_lens[i] = p_len;
76 newp->argv_types[i] = arg_type;
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],
85 SILC_LOG_DEBUG(("Malformed argument payload"));
89 silc_buffer_pull(&buffer, p_len);
90 pull_len += 3 + p_len;
93 if (silc_buffer_len(&buffer) != 0) {
94 SILC_LOG_DEBUG(("Malformed argument payload"));
101 silc_buffer_push(&buffer, pull_len);
106 SILC_LOG_DEBUG(("Error parsing argument payload"));
108 for (ret = 0; ret < i; ret++)
109 silc_free(newp->argv[ret]);
111 silc_free(newp->argv);
112 silc_free(newp->argv_lens);
113 silc_free(newp->argv_types);
119 /* Encodes arguments in to Argument Paylods returning them to SilcBuffer. */
121 SilcBuffer silc_argument_payload_encode(SilcUInt32 argc,
122 unsigned char **argv,
123 SilcUInt32 *argv_lens,
124 SilcUInt32 *argv_types)
131 for (i = 0; i < argc; i++)
132 len += 3 + (SilcUInt16)argv_lens[i];
134 buffer = silc_buffer_alloc_size(len);
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]),
145 silc_buffer_pull(buffer, 3 + (SilcUInt16)argv_lens[i]);
148 silc_buffer_push(buffer, len);
153 /* Encode one argument to buffer */
155 SilcBuffer silc_argument_payload_encode_one(SilcBuffer args,
160 SilcBuffer buffer = args;
163 len = 3 + (SilcUInt16)arg_len;
164 buffer = silc_buffer_realloc(buffer,
165 (buffer ? silc_buffer_truelen(buffer) +
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),
176 silc_buffer_push(buffer, buffer->data - buffer->head);
181 /* Same as above but encode the buffer from SilcArgumentPayload structure
182 instead of raw data. */
184 SilcBuffer silc_argument_payload_encode_payload(SilcArgumentPayload payload)
191 for (i = 0; i < payload->argc; i++)
192 len += 3 + payload->argv_lens[i];
194 buffer = silc_buffer_alloc_size(len);
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]),
206 silc_buffer_pull(buffer, 3 + payload->argv_lens[i]);
209 silc_buffer_push(buffer, len);
214 /* Frees Argument Payload */
216 void silc_argument_payload_free(SilcArgumentPayload payload)
221 for (i = 0; i < payload->argc; i++)
222 silc_free(payload->argv[i]);
224 silc_free(payload->argv);
225 silc_free(payload->argv_lens);
226 silc_free(payload->argv_types);
231 /* Returns number of arguments in payload */
233 SilcUInt32 silc_argument_get_arg_num(SilcArgumentPayload payload)
235 return payload ? payload->argc : 0;
238 /* Returns first argument from payload. */
240 unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
250 *type = payload->argv_types[payload->pos];
252 *ret_len = payload->argv_lens[payload->pos];
254 return payload->argv[payload->pos++];
257 /* Returns next argument from payload or NULL if no more arguments. */
259 unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
266 if (payload->pos >= payload->argc)
270 *type = payload->argv_types[payload->pos];
272 *ret_len = payload->argv_lens[payload->pos];
274 return payload->argv[payload->pos++];
277 /* Returns argument which type is `type'. */
279 unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
288 for (i = 0; i < payload->argc; i++)
289 if (payload->argv_types[i] == type)
292 if (i >= payload->argc)
296 *ret_len = payload->argv_lens[i];
298 return payload->argv[i];
301 /* Return argument already decoded */
303 static SilcBool silc_argument_decode(unsigned char *data,
305 SilcArgumentDecodeType dec_type,
307 void **ret_arg_alloc)
311 case SILC_ARGUMENT_ID:
313 if (!silc_id_payload_parse_id(data, data_len, (SilcID *)ret_arg))
318 if (!silc_id_payload_parse_id(data, data_len, &id))
320 *ret_arg_alloc = silc_memdup(&id, sizeof(id));
324 case SILC_ARGUMENT_PUBLIC_KEY:
326 SilcPublicKey public_key;
331 if (!silc_public_key_payload_decode(data, data_len, &public_key))
334 *ret_arg_alloc = public_key;
338 case SILC_ARGUMENT_ATTRIBUTES:
342 *ret_arg_alloc = silc_attribute_payload_parse(data, data_len);
345 case SILC_ARGUMENT_UINT32:
350 SilcUInt32 *i = ret_arg;
351 SILC_GET32_MSB(*i, data);
356 SILC_GET32_MSB(i, data);
357 *ret_arg_alloc = silc_memdup(&i, sizeof(i));
361 case SILC_ARGUMENT_BOOL:
362 if (data_len != sizeof(SilcBool))
366 SilcBool *b = ret_arg;
367 *b = (data[0] == 0x01 ? TRUE : FALSE);
372 b = (data[0] == 0x01 ? TRUE : FALSE);
373 *ret_arg_alloc = silc_memdup(&b, sizeof(b));
384 /* Return argument already decoded */
386 SilcBool silc_argument_get_decoded(SilcArgumentPayload payload,
388 SilcArgumentDecodeType dec_type,
390 void **ret_arg_alloc)
395 tmp = silc_argument_get_arg_type(payload, type, &tmp_len);
399 return silc_argument_decode(tmp, tmp_len, dec_type, ret_arg, ret_arg_alloc);
402 /************************* Argument List Payload ****************************/
404 /* Parses argument payload list */
407 silc_argument_list_parse(const unsigned char *payload,
408 SilcUInt32 payload_len)
410 SilcArgumentPayload arg;
416 SILC_GET16_MSB(argc, payload);
418 arg = silc_argument_payload_parse(payload + 2, payload_len - 2, argc);
423 /* Parses argument payload list of specific argument types */
426 silc_argument_list_parse_decoded(const unsigned char *payload,
427 SilcUInt32 payload_len,
428 SilcArgumentDecodeType dec_type)
430 SilcArgumentPayload arg;
431 SilcArgumentDecodedList dec;
433 SilcUInt32 data_len, type;
436 arg = silc_argument_list_parse(payload, payload_len);
440 list = silc_dlist_init();
442 silc_argument_payload_free(arg);
446 data = silc_argument_get_first_arg(arg, &type, &data_len);
448 dec = silc_calloc(1, sizeof(*dec));
451 dec->arg_type = type;
452 if (silc_argument_decode(data, data_len, dec_type, NULL, &dec->argument))
453 silc_dlist_add(list, dec);
456 data = silc_argument_get_next_arg(arg, &type, &data_len);
459 silc_argument_payload_free(arg);
461 silc_dlist_start(list);
466 /* Free decoded argument payload list */
468 void silc_argument_list_free(SilcDList list, SilcArgumentDecodeType dec_type)
470 SilcArgumentDecodedList dec;
475 silc_dlist_start(list);
476 while ((dec = silc_dlist_get(list))) {
479 case SILC_ARGUMENT_ID:
480 case SILC_ARGUMENT_UINT32:
481 case SILC_ARGUMENT_BOOL:
482 silc_free(dec->argument);
485 case SILC_ARGUMENT_PUBLIC_KEY:
486 silc_pkcs_public_key_free(dec->argument);
489 case SILC_ARGUMENT_ATTRIBUTES:
490 silc_attribute_payload_free(dec->argument);
500 silc_dlist_uninit(list);