5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 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 /* Channel Payload and Channel Key Payload implementations. */
22 #include "silcincludes.h"
23 #include "silcchannel.h"
25 /******************************************************************************
29 ******************************************************************************/
31 /* Channel Message Payload structure. Contents of this structure is parsed
33 struct SilcChannelPayloadStruct {
34 unsigned char *channel_name;
35 unsigned char *channel_id;
41 /* Parses channel payload returning new channel payload structure. */
43 SilcChannelPayload silc_channel_payload_parse(const unsigned char *payload,
44 SilcUInt32 payload_len)
46 SilcBufferStruct buffer;
47 SilcChannelPayload newp;
50 SILC_LOG_DEBUG(("Parsing channel payload"));
52 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
53 newp = silc_calloc(1, sizeof(*newp));
57 /* Parse the Channel Payload. Ignore the padding. */
58 ret = silc_buffer_unformat(&buffer,
59 SILC_STR_UI16_NSTRING_ALLOC(&newp->channel_name,
61 SILC_STR_UI16_NSTRING_ALLOC(&newp->channel_id,
63 SILC_STR_UI_INT(&newp->mode),
68 if ((newp->name_len < 1 || newp->name_len > buffer.len - 8) ||
69 (newp->id_len < 1 || newp->id_len > buffer.len - 8) ||
70 (newp->id_len + newp->name_len > buffer.len - 8)) {
71 SILC_LOG_ERROR(("Incorrect channel payload in packet, packet dropped"));
78 silc_channel_payload_free(newp);
82 /* Parses list of channel payloads returning list of payloads. */
84 SilcDList silc_channel_payload_parse_list(const unsigned char *payload,
85 SilcUInt32 payload_len)
87 SilcBufferStruct buffer;
89 SilcChannelPayload newp;
93 SILC_LOG_DEBUG(("Parsing channel payload list"));
95 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
96 list = silc_dlist_init();
99 newp = silc_calloc(1, sizeof(*newp));
102 ret = silc_buffer_unformat(&buffer,
103 SILC_STR_UI16_NSTRING_ALLOC(&newp->channel_name,
105 SILC_STR_UI16_NSTRING_ALLOC(&newp->channel_id,
107 SILC_STR_UI_INT(&newp->mode),
112 if ((newp->name_len < 1 || newp->name_len > buffer.len) ||
113 (newp->id_len < 1 || newp->id_len > buffer.len)) {
114 SILC_LOG_ERROR(("Incorrect channel payload in packet, packet dropped"));
118 len = 2 + newp->name_len + 2 + newp->id_len + 4;
119 if (buffer.len < len)
121 silc_buffer_pull(&buffer, len);
123 silc_dlist_add(list, newp);
129 silc_channel_payload_list_free(list);
133 /* Encode new channel payload and returns it as buffer. */
135 SilcBuffer silc_channel_payload_encode(const unsigned char *channel_name,
136 SilcUInt16 channel_name_len,
137 const unsigned char *channel_id,
138 SilcUInt32 channel_id_len,
143 SILC_LOG_DEBUG(("Encoding message payload"));
145 buffer = silc_buffer_alloc_size(2 + channel_name_len + 2 +
150 /* Encode the Channel Payload */
151 silc_buffer_format(buffer,
152 SILC_STR_UI_SHORT(channel_name_len),
153 SILC_STR_UI_XNSTRING(channel_name, channel_name_len),
154 SILC_STR_UI_SHORT(channel_id_len),
155 SILC_STR_UI_XNSTRING(channel_id, channel_id_len),
156 SILC_STR_UI_INT(mode),
162 /* Frees Channel Payload */
164 void silc_channel_payload_free(SilcChannelPayload payload)
166 silc_free(payload->channel_name);
167 silc_free(payload->channel_id);
171 /* Free's list of Channel Payloads */
173 void silc_channel_payload_list_free(SilcDList list)
175 SilcChannelPayload entry;
177 silc_dlist_start(list);
178 while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
179 silc_free(entry->channel_name);
180 silc_free(entry->channel_id);
181 silc_dlist_del(list, entry);
185 silc_dlist_uninit(list);
188 /* Return the channel name */
190 unsigned char *silc_channel_get_name(SilcChannelPayload payload,
191 SilcUInt32 *channel_name_len)
193 if (channel_name_len)
194 *channel_name_len = payload->name_len;
196 return payload->channel_name;
199 /* Return the channel ID */
201 unsigned char *silc_channel_get_id(SilcChannelPayload payload,
202 SilcUInt32 *channel_id_len)
205 *channel_id_len = payload->id_len;
207 return payload->channel_id;
210 /* Return the channel ID as parsed ID. */
212 SilcChannelID *silc_channel_get_id_parse(SilcChannelPayload payload)
214 return silc_id_str2id(payload->channel_id, payload->id_len,
218 /* Return the mode. The mode is arbitrary. It can be the mode of the
219 channel or perhaps the mode of the client on the channel. The protocol
220 dictates what the usage of the mode is in different circumstances. */
222 SilcUInt32 silc_channel_get_mode(SilcChannelPayload payload)
224 return payload->mode;
228 /******************************************************************************
232 ******************************************************************************/
234 /* Channel Key Payload structrue. Channel keys are parsed from SILC
235 packets into this structure. */
236 struct SilcChannelKeyPayloadStruct {
238 unsigned char *cipher;
241 SilcUInt16 cipher_len;
245 /* Parses channel key payload returning new channel key payload structure */
247 SilcChannelKeyPayload
248 silc_channel_key_payload_parse(const unsigned char *payload,
249 SilcUInt32 payload_len)
251 SilcBufferStruct buffer;
252 SilcChannelKeyPayload newp;
255 SILC_LOG_DEBUG(("Parsing channel key payload"));
257 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
258 newp = silc_calloc(1, sizeof(*newp));
262 /* Parse the Channel Key Payload */
264 silc_buffer_unformat(&buffer,
265 SILC_STR_UI16_NSTRING_ALLOC(&newp->id, &newp->id_len),
266 SILC_STR_UI16_NSTRING_ALLOC(&newp->cipher,
268 SILC_STR_UI16_NSTRING_ALLOC(&newp->key,
274 if (newp->id_len < 1 || newp->key_len < 1 || newp->cipher_len < 1 ||
275 newp->id_len + newp->cipher_len + newp->key_len > buffer.len - 6) {
276 SILC_LOG_ERROR(("Incorrect channel key payload in packet"));
286 silc_free(newp->cipher);
288 silc_free(newp->key);
293 /* Encodes channel key payload into a buffer and returns it. This is used
294 to add channel key payload into a packet. */
296 SilcBuffer silc_channel_key_payload_encode(SilcUInt16 id_len,
297 const unsigned char *id,
298 SilcUInt16 cipher_len,
299 const unsigned char *cipher,
301 const unsigned char *key)
306 SILC_LOG_DEBUG(("Encoding channel key payload"));
308 /* Allocate channel payload buffer. Length is 2 + id + 2 + key +
310 len = 2 + id_len + 2 + key_len + 2 + cipher_len;
311 buffer = silc_buffer_alloc_size(len);
315 /* Encode the Channel Payload */
316 silc_buffer_format(buffer,
317 SILC_STR_UI_SHORT(id_len),
318 SILC_STR_UI_XNSTRING(id, id_len),
319 SILC_STR_UI_SHORT(cipher_len),
320 SILC_STR_UI_XNSTRING(cipher, cipher_len),
321 SILC_STR_UI_SHORT(key_len),
322 SILC_STR_UI_XNSTRING(key, key_len),
328 /* Frees Channel Key Payload */
330 void silc_channel_key_payload_free(SilcChannelKeyPayload payload)
333 silc_free(payload->id);
334 silc_free(payload->cipher);
336 memset(payload->key, 0, payload->key_len);
337 silc_free(payload->key);
345 unsigned char *silc_channel_key_get_id(SilcChannelKeyPayload payload,
349 *id_len = payload->id_len;
354 /* Return cipher name */
356 unsigned char *silc_channel_key_get_cipher(SilcChannelKeyPayload payload,
357 SilcUInt32 *cipher_len)
360 *cipher_len = payload->cipher_len;
362 return payload->cipher;
367 unsigned char *silc_channel_key_get_key(SilcChannelKeyPayload payload,
371 *key_len = payload->key_len;