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_type = 0;
45 SilcUInt32 pull_len = 0;
48 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
49 newp = silc_calloc(1, sizeof(*newp));
52 newp->argv = silc_calloc(argc, sizeof(unsigned char *));
55 newp->argv_lens = silc_calloc(argc, sizeof(SilcUInt32));
58 newp->argv_types = silc_calloc(argc, sizeof(SilcUInt32));
59 if (!newp->argv_types)
63 for (i = 0; i < argc; i++) {
64 ret = silc_buffer_unformat(&buffer,
65 SILC_STR_UI_SHORT(&p_len),
66 SILC_STR_UI_CHAR(&arg_type),
68 if (ret == -1 || p_len > silc_buffer_len(&buffer) - 3) {
69 SILC_LOG_DEBUG(("Malformed argument payload"));
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],
83 SILC_LOG_DEBUG(("Malformed argument payload"));
87 silc_buffer_pull(&buffer, p_len);
88 pull_len += 3 + p_len;
91 if (silc_buffer_len(&buffer) != 0) {
92 SILC_LOG_DEBUG(("Malformed argument payload"));
99 silc_buffer_push(&buffer, pull_len);
104 SILC_LOG_DEBUG(("Error parsing argument payload"));
106 for (ret = 0; ret < i; ret++)
107 silc_free(newp->argv[ret]);
109 silc_free(newp->argv);
110 silc_free(newp->argv_lens);
111 silc_free(newp->argv_types);
117 /* Encodes arguments in to Argument Paylods returning them to SilcBuffer. */
119 SilcBuffer silc_argument_payload_encode(SilcUInt32 argc,
120 unsigned char **argv,
121 SilcUInt32 *argv_lens,
122 SilcUInt32 *argv_types)
129 for (i = 0; i < argc; i++)
130 len += 3 + (SilcUInt16)argv_lens[i];
132 buffer = silc_buffer_alloc_size(len);
137 for (i = 0; i < argc; i++) {
138 silc_buffer_format(buffer,
139 SILC_STR_UI_SHORT(argv_lens[i]),
140 SILC_STR_UI_CHAR(argv_types[i]),
141 SILC_STR_UI_XNSTRING(argv[i], (SilcUInt16)argv_lens[i]),
143 silc_buffer_pull(buffer, 3 + (SilcUInt16)argv_lens[i]);
146 silc_buffer_push(buffer, len);
151 /* Encode one argument to buffer */
153 SilcBuffer silc_argument_payload_encode_one(SilcBuffer args,
158 SilcBuffer buffer = args;
161 len = 3 + (SilcUInt16)arg_len;
162 buffer = silc_buffer_realloc(buffer,
163 (buffer ? silc_buffer_truelen(buffer) +
167 silc_buffer_pull(buffer, silc_buffer_len(buffer));
168 silc_buffer_pull_tail(buffer, len);
169 silc_buffer_format(buffer,
170 SILC_STR_UI_SHORT(arg_len),
171 SILC_STR_UI_CHAR(arg_type),
172 SILC_STR_UI_XNSTRING(arg, (SilcUInt16)arg_len),
174 silc_buffer_push(buffer, buffer->data - buffer->head);
179 /* Same as above but encode the buffer from SilcArgumentPayload structure
180 instead of raw data. */
182 SilcBuffer silc_argument_payload_encode_payload(SilcArgumentPayload payload)
189 for (i = 0; i < payload->argc; i++)
190 len += 3 + payload->argv_lens[i];
192 buffer = silc_buffer_alloc_size(len);
197 for (i = 0; i < payload->argc; i++) {
198 silc_buffer_format(buffer,
199 SILC_STR_UI_SHORT(payload->argv_lens[i]),
200 SILC_STR_UI_CHAR(payload->argv_types[i]),
201 SILC_STR_UI_XNSTRING(payload->argv[i],
202 payload->argv_lens[i]),
204 silc_buffer_pull(buffer, 3 + payload->argv_lens[i]);
207 silc_buffer_push(buffer, len);
212 /* Frees Argument Payload */
214 void silc_argument_payload_free(SilcArgumentPayload payload)
219 for (i = 0; i < payload->argc; i++)
220 silc_free(payload->argv[i]);
222 silc_free(payload->argv);
223 silc_free(payload->argv_lens);
224 silc_free(payload->argv_types);
229 /* Returns number of arguments in payload */
231 SilcUInt32 silc_argument_get_arg_num(SilcArgumentPayload payload)
233 return payload ? payload->argc : 0;
236 /* Returns first argument from payload. */
238 unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
248 *type = payload->argv_types[payload->pos];
250 *ret_len = payload->argv_lens[payload->pos];
252 return payload->argv[payload->pos++];
255 /* Returns next argument from payload or NULL if no more arguments. */
257 unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
264 if (payload->pos >= payload->argc)
268 *type = payload->argv_types[payload->pos];
270 *ret_len = payload->argv_lens[payload->pos];
272 return payload->argv[payload->pos++];
275 /* Returns argument which type is `type'. */
277 unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
286 for (i = 0; i < payload->argc; i++)
287 if (payload->argv_types[i] == type)
290 if (i >= payload->argc)
294 *ret_len = payload->argv_lens[i];
296 return payload->argv[i];
299 /* Return argument already decoded */
301 static SilcBool silc_argument_decode(unsigned char *data,
303 SilcArgumentDecodeType dec_type,
305 void **ret_arg_alloc)
309 case SILC_ARGUMENT_ID:
311 if (!silc_id_payload_parse_id(data, data_len, (SilcID *)ret_arg))
316 if (!silc_id_payload_parse_id(data, data_len, &id))
318 *ret_arg_alloc = silc_memdup(&id, sizeof(id));
322 case SILC_ARGUMENT_PUBLIC_KEY:
324 SilcPublicKey public_key;
329 if (!silc_public_key_payload_decode(data, data_len, &public_key))
332 *ret_arg_alloc = public_key;
336 case SILC_ARGUMENT_ATTRIBUTES:
340 *ret_arg_alloc = silc_attribute_payload_parse(data, data_len);
343 case SILC_ARGUMENT_UINT32:
348 SilcUInt32 *i = ret_arg;
349 SILC_GET32_MSB(*i, data);
354 SILC_GET32_MSB(i, data);
355 *ret_arg_alloc = silc_memdup(&i, sizeof(i));
359 case SILC_ARGUMENT_BOOL:
360 if (data_len != sizeof(SilcBool))
364 SilcBool *b = ret_arg;
365 *b = (data[0] == 0x01 ? TRUE : FALSE);
370 b = (data[0] == 0x01 ? TRUE : FALSE);
371 *ret_arg_alloc = silc_memdup(&b, sizeof(b));
382 /* Return argument already decoded */
384 SilcBool silc_argument_get_decoded(SilcArgumentPayload payload,
386 SilcArgumentDecodeType dec_type,
388 void **ret_arg_alloc)
393 tmp = silc_argument_get_arg_type(payload, type, &tmp_len);
397 return silc_argument_decode(tmp, tmp_len, dec_type, ret_arg, ret_arg_alloc);
400 /************************* Argument List Payload ****************************/
402 /* Parses argument payload list */
405 silc_argument_list_parse(const unsigned char *payload,
406 SilcUInt32 payload_len)
408 SilcArgumentPayload arg;
414 SILC_GET16_MSB(argc, payload);
416 arg = silc_argument_payload_parse(payload + 2, payload_len - 2, argc);
421 /* Parses argument payload list of specific argument types */
424 silc_argument_list_parse_decoded(const unsigned char *payload,
425 SilcUInt32 payload_len,
426 SilcArgumentDecodeType dec_type)
428 SilcArgumentPayload arg;
429 SilcArgumentDecodedList dec;
431 SilcUInt32 data_len, type;
434 arg = silc_argument_list_parse(payload, payload_len);
438 list = silc_dlist_init();
440 silc_argument_payload_free(arg);
444 data = silc_argument_get_first_arg(arg, &type, &data_len);
446 dec = silc_calloc(1, sizeof(*dec));
449 dec->arg_type = type;
450 if (silc_argument_decode(data, data_len, dec_type, NULL, &dec->argument))
451 silc_dlist_add(list, dec);
454 data = silc_argument_get_next_arg(arg, &type, &data_len);
457 silc_argument_payload_free(arg);
459 silc_dlist_start(list);
464 /* Free decoded argument payload list */
466 void silc_argument_list_free(SilcDList list, SilcArgumentDecodeType dec_type)
468 SilcArgumentDecodedList dec;
473 silc_dlist_start(list);
474 while ((dec = silc_dlist_get(list))) {
477 case SILC_ARGUMENT_ID:
478 case SILC_ARGUMENT_UINT32:
479 case SILC_ARGUMENT_BOOL:
480 silc_free(dec->argument);
483 case SILC_ARGUMENT_PUBLIC_KEY:
484 silc_pkcs_public_key_free(dec->argument);
487 case SILC_ARGUMENT_ATTRIBUTES:
488 silc_attribute_payload_free(dec->argument);
498 silc_dlist_uninit(list);