Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 - 2006 Pekka Riikonen
+ Copyright (C) 2001 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "silc.h"
#include "silcargument.h"
-/******************************************************************************
-
- Argument Payload
-
-******************************************************************************/
+/*************************** Argument Payload *******************************/
struct SilcArgumentPayloadStruct {
SilcUInt32 argc;
SILC_STR_UI_SHORT(&p_len),
SILC_STR_UI_CHAR(&arg_type),
SILC_STR_END);
- if (ret == -1 || p_len > silc_buffer_len(&buffer) - 3)
+ if (ret == -1 || p_len > silc_buffer_len(&buffer) - 3) {
+ SILC_LOG_DEBUG(("Malformed argument payload"));
goto err;
+ }
newp->argv_lens[i] = p_len;
newp->argv_types[i] = arg_type;
SILC_STR_UI_XNSTRING_ALLOC(&newp->argv[i],
p_len),
SILC_STR_END);
- if (ret == -1)
+ if (ret == -1) {
+ SILC_LOG_DEBUG(("Malformed argument payload"));
goto err;
+ }
silc_buffer_pull(&buffer, p_len);
pull_len += 3 + p_len;
/* Return argument already decoded */
-SilcBool silc_argument_get_decoded(SilcArgumentPayload payload,
- SilcUInt32 type,
- SilcArgumentDecodeType dec_type,
- void *ret_arg,
- void **ret_arg_alloc)
+static SilcBool silc_argument_decode(unsigned char *data,
+ SilcUInt32 data_len,
+ SilcArgumentDecodeType dec_type,
+ void *ret_arg,
+ void **ret_arg_alloc)
{
- unsigned char *tmp;
- SilcUInt32 tmp_len;
-
- tmp = silc_argument_get_arg_type(payload, type, &tmp_len);
- if (!tmp)
- return FALSE;
-
switch (dec_type) {
case SILC_ARGUMENT_ID:
if (ret_arg)
- if (!silc_id_payload_parse_id(tmp, tmp_len, (SilcID *)ret_arg))
+ if (!silc_id_payload_parse_id(data, data_len, (SilcID *)ret_arg))
return FALSE;
if (ret_arg_alloc) {
SilcID id;
- if (!silc_id_payload_parse_id(tmp, tmp_len, &id))
+ if (!silc_id_payload_parse_id(data, data_len, &id))
return FALSE;
*ret_arg_alloc = silc_memdup(&id, sizeof(id));
}
if (!ret_arg_alloc)
return FALSE;
- if (!silc_public_key_payload_decode(tmp, tmp_len, &public_key))
+ if (!silc_public_key_payload_decode(data, data_len, &public_key))
return FALSE;
*ret_arg_alloc = public_key;
if (!ret_arg_alloc)
return FALSE;
- *ret_arg_alloc = silc_attribute_payload_parse(tmp, tmp_len);
+ *ret_arg_alloc = silc_attribute_payload_parse(data, data_len);
break;
case SILC_ARGUMENT_UINT32:
- if (tmp_len != 4)
+ if (data_len != 4)
return FALSE;
if (ret_arg) {
SilcUInt32 *i = ret_arg;
- SILC_GET32_MSB(*i, tmp);
+ SILC_GET32_MSB(*i, data);
}
if (ret_arg_alloc) {
SilcUInt32 i;
- SILC_GET32_MSB(i, tmp);
+ SILC_GET32_MSB(i, data);
*ret_arg_alloc = silc_memdup(&i, sizeof(i));
}
break;
case SILC_ARGUMENT_BOOL:
- if (tmp_len != 1)
+ if (data_len != sizeof(SilcBool))
return FALSE;
if (ret_arg) {
SilcBool *b = ret_arg;
- *b = (tmp[0] == 0x01 ? TRUE : FALSE);
+ *b = (data[0] == 0x01 ? TRUE : FALSE);
}
if (ret_arg_alloc) {
SilcBool b;
- b = (tmp[0] == 0x01 ? TRUE : FALSE);
+ b = (data[0] == 0x01 ? TRUE : FALSE);
*ret_arg_alloc = silc_memdup(&b, sizeof(b));
}
break;
return TRUE;
}
+
+/* Return argument already decoded */
+
+SilcBool silc_argument_get_decoded(SilcArgumentPayload payload,
+ SilcUInt32 type,
+ SilcArgumentDecodeType dec_type,
+ void *ret_arg,
+ void **ret_arg_alloc)
+{
+ unsigned char *tmp;
+ SilcUInt32 tmp_len;
+
+ tmp = silc_argument_get_arg_type(payload, type, &tmp_len);
+ if (!tmp)
+ return FALSE;
+
+ return silc_argument_decode(tmp, tmp_len, dec_type, ret_arg, ret_arg_alloc);
+}
+
+/************************* Argument List Payload ****************************/
+
+/* Parses argument payload list */
+
+SilcArgumentPayload
+silc_argument_list_parse(const unsigned char *payload,
+ SilcUInt32 payload_len)
+{
+ SilcArgumentPayload arg;
+ SilcUInt16 argc;
+
+ if (payload_len < 5)
+ return NULL;
+
+ SILC_GET16_MSB(argc, payload);
+
+ arg = silc_argument_payload_parse(payload + 2, payload_len - 2, argc);
+
+ return arg;
+}
+
+/* Parses argument payload list of specific argument types */
+
+SilcDList
+silc_argument_list_parse_decoded(const unsigned char *payload,
+ SilcUInt32 payload_len,
+ SilcArgumentDecodeType dec_type)
+{
+ SilcArgumentPayload arg;
+ SilcArgumentDecodedList dec;
+ unsigned char *data;
+ SilcUInt32 data_len, type;
+ SilcDList list;
+
+ arg = silc_argument_list_parse(payload, payload_len);
+ if (!arg)
+ return NULL;
+
+ list = silc_dlist_init();
+ if (!list) {
+ silc_argument_payload_free(arg);
+ return NULL;
+ }
+
+ data = silc_argument_get_first_arg(arg, &type, &data_len);
+ while (data) {
+ dec = silc_calloc(1, sizeof(*dec));
+ if (!dec)
+ continue;
+ dec->arg_type = type;
+ if (silc_argument_decode(data, data_len, dec_type, NULL, &dec->argument))
+ silc_dlist_add(list, dec);
+ else
+ silc_free(dec);
+ data = silc_argument_get_next_arg(arg, &type, &data_len);
+ }
+
+ silc_argument_payload_free(arg);
+
+ silc_dlist_start(list);
+
+ return list;
+}
+
+/* Free decoded argument payload list */
+
+void silc_argument_list_free(SilcDList list, SilcArgumentDecodeType dec_type)
+{
+ SilcArgumentDecodedList dec;
+
+ if (!list)
+ return;
+
+ silc_dlist_start(list);
+ while ((dec = silc_dlist_get(list))) {
+ switch (dec_type) {
+
+ case SILC_ARGUMENT_ID:
+ case SILC_ARGUMENT_UINT32:
+ case SILC_ARGUMENT_BOOL:
+ silc_free(dec->argument);
+ break;
+
+ case SILC_ARGUMENT_PUBLIC_KEY:
+ silc_pkcs_public_key_free(dec->argument);
+ break;
+
+ case SILC_ARGUMENT_ATTRIBUTES:
+ silc_attribute_payload_free(dec->argument);
+ break;
+
+ default:
+ break;
+ }
+
+ silc_free(dec);
+ }
+
+ silc_dlist_uninit(list);
+}