5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005 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. */
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 > silc_buffer_len(&buffer) - 8) ||
69 (newp->id_len < 1 || newp->id_len > silc_buffer_len(&buffer) - 8) ||
70 (newp->id_len + newp->name_len > silc_buffer_len(&buffer) - 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();
98 while (silc_buffer_len(&buffer)) {
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 > silc_buffer_len(&buffer) - 8) ||
113 (newp->id_len < 1 || newp->id_len > silc_buffer_len(&buffer) - 8) ||
114 (newp->id_len + newp->name_len > silc_buffer_len(&buffer) - 8)) {
115 SILC_LOG_ERROR(("Incorrect channel payload in packet, packet dropped"));
119 len = 2 + newp->name_len + 2 + newp->id_len + 4;
120 if (silc_buffer_len(&buffer) < len)
122 silc_buffer_pull(&buffer, len);
124 silc_dlist_add(list, newp);
130 silc_channel_payload_list_free(list);
134 /* Encode new channel payload and returns it as buffer. */
136 SilcBuffer silc_channel_payload_encode(const unsigned char *channel_name,
137 SilcUInt16 channel_name_len,
138 const unsigned char *channel_id,
139 SilcUInt32 channel_id_len,
144 SILC_LOG_DEBUG(("Encoding message payload"));
146 buffer = silc_buffer_alloc_size(2 + channel_name_len + 2 +
151 /* Encode the Channel Payload */
152 silc_buffer_format(buffer,
153 SILC_STR_UI_SHORT(channel_name_len),
154 SILC_STR_UI_XNSTRING(channel_name, channel_name_len),
155 SILC_STR_UI_SHORT(channel_id_len),
156 SILC_STR_UI_XNSTRING(channel_id, channel_id_len),
157 SILC_STR_UI_INT(mode),
163 /* Frees Channel Payload */
165 void silc_channel_payload_free(SilcChannelPayload payload)
167 silc_free(payload->channel_name);
168 silc_free(payload->channel_id);
172 /* Free's list of Channel Payloads */
174 void silc_channel_payload_list_free(SilcDList list)
176 SilcChannelPayload entry;
178 silc_dlist_start(list);
179 while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
180 silc_free(entry->channel_name);
181 silc_free(entry->channel_id);
182 silc_dlist_del(list, entry);
186 silc_dlist_uninit(list);
189 /* Return the channel name */
191 unsigned char *silc_channel_get_name(SilcChannelPayload payload,
192 SilcUInt32 *channel_name_len)
194 if (channel_name_len)
195 *channel_name_len = payload->name_len;
197 return payload->channel_name;
200 /* Return the channel ID */
202 unsigned char *silc_channel_get_id(SilcChannelPayload payload,
203 SilcUInt32 *channel_id_len)
206 *channel_id_len = payload->id_len;
208 return payload->channel_id;
211 /* Return the channel ID as parsed ID. */
213 SilcBool silc_channel_get_id_parse(SilcChannelPayload payload,
214 SilcChannelID *ret_channel_id)
216 return silc_id_str2id(payload->channel_id, payload->id_len,
217 SILC_ID_CHANNEL, ret_channel_id,
218 sizeof(SilcChannelID));
221 /* Return the mode. The mode is arbitrary. It can be the mode of the
222 channel or perhaps the mode of the client on the channel. The protocol
223 dictates what the usage of the mode is in different circumstances. */
225 SilcUInt32 silc_channel_get_mode(SilcChannelPayload payload)
227 return payload->mode;
231 /******************************************************************************
235 ******************************************************************************/
237 /* Channel Key Payload structrue. Channel keys are parsed from SILC
238 packets into this structure. */
239 struct SilcChannelKeyPayloadStruct {
241 unsigned char *cipher;
244 SilcUInt16 cipher_len;
248 /* Parses channel key payload returning new channel key payload structure */
250 SilcChannelKeyPayload
251 silc_channel_key_payload_parse(const unsigned char *payload,
252 SilcUInt32 payload_len)
254 SilcBufferStruct buffer;
255 SilcChannelKeyPayload newp;
258 SILC_LOG_DEBUG(("Parsing channel key payload"));
260 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
261 newp = silc_calloc(1, sizeof(*newp));
265 /* Parse the Channel Key Payload */
267 silc_buffer_unformat(&buffer,
268 SILC_STR_UI16_NSTRING_ALLOC(&newp->id, &newp->id_len),
269 SILC_STR_UI16_NSTRING_ALLOC(&newp->cipher,
271 SILC_STR_UI16_NSTRING_ALLOC(&newp->key,
277 if (newp->id_len < 1 || newp->key_len < 1 || newp->cipher_len < 1 ||
278 newp->id_len + newp->cipher_len + newp->key_len > silc_buffer_len(&buffer) - 6) {
279 SILC_LOG_ERROR(("Incorrect channel key payload in packet"));
289 silc_free(newp->cipher);
291 silc_free(newp->key);
296 /* Encodes channel key payload into a buffer and returns it. This is used
297 to add channel key payload into a packet. */
299 SilcBuffer silc_channel_key_payload_encode(SilcUInt16 id_len,
300 const unsigned char *id,
301 SilcUInt16 cipher_len,
302 const unsigned char *cipher,
304 const unsigned char *key)
309 SILC_LOG_DEBUG(("Encoding channel key payload"));
311 /* Allocate channel payload buffer. Length is 2 + id + 2 + key +
313 len = 2 + id_len + 2 + key_len + 2 + cipher_len;
314 buffer = silc_buffer_alloc_size(len);
318 /* Encode the Channel Payload */
319 silc_buffer_format(buffer,
320 SILC_STR_UI_SHORT(id_len),
321 SILC_STR_UI_XNSTRING(id, id_len),
322 SILC_STR_UI_SHORT(cipher_len),
323 SILC_STR_UI_XNSTRING(cipher, cipher_len),
324 SILC_STR_UI_SHORT(key_len),
325 SILC_STR_UI_XNSTRING(key, key_len),
331 /* Frees Channel Key Payload */
333 void silc_channel_key_payload_free(SilcChannelKeyPayload payload)
336 silc_free(payload->id);
337 silc_free(payload->cipher);
339 memset(payload->key, 0, payload->key_len);
340 silc_free(payload->key);
348 unsigned char *silc_channel_key_get_id(SilcChannelKeyPayload payload,
352 *id_len = payload->id_len;
357 /* Return cipher name */
359 unsigned char *silc_channel_key_get_cipher(SilcChannelKeyPayload payload,
360 SilcUInt32 *cipher_len)
363 *cipher_len = payload->cipher_len;
365 return payload->cipher;
370 unsigned char *silc_channel_key_get_key(SilcChannelKeyPayload payload,
374 *key_len = payload->key_len;