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 - 8) ||
113 (newp->id_len < 1 || newp->id_len > buffer.len - 8) ||
114 (newp->id_len + newp->name_len > buffer.len - 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 (buffer.len < 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 SilcChannelID *silc_channel_get_id_parse(SilcChannelPayload payload)
215 return silc_id_str2id(payload->channel_id, payload->id_len,
219 /* Return the mode. The mode is arbitrary. It can be the mode of the
220 channel or perhaps the mode of the client on the channel. The protocol
221 dictates what the usage of the mode is in different circumstances. */
223 SilcUInt32 silc_channel_get_mode(SilcChannelPayload payload)
225 return payload->mode;
229 /******************************************************************************
233 ******************************************************************************/
235 /* Channel Key Payload structrue. Channel keys are parsed from SILC
236 packets into this structure. */
237 struct SilcChannelKeyPayloadStruct {
239 unsigned char *cipher;
242 SilcUInt16 cipher_len;
246 /* Parses channel key payload returning new channel key payload structure */
248 SilcChannelKeyPayload
249 silc_channel_key_payload_parse(const unsigned char *payload,
250 SilcUInt32 payload_len)
252 SilcBufferStruct buffer;
253 SilcChannelKeyPayload newp;
256 SILC_LOG_DEBUG(("Parsing channel key payload"));
258 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
259 newp = silc_calloc(1, sizeof(*newp));
263 /* Parse the Channel Key Payload */
265 silc_buffer_unformat(&buffer,
266 SILC_STR_UI16_NSTRING_ALLOC(&newp->id, &newp->id_len),
267 SILC_STR_UI16_NSTRING_ALLOC(&newp->cipher,
269 SILC_STR_UI16_NSTRING_ALLOC(&newp->key,
275 if (newp->id_len < 1 || newp->key_len < 1 || newp->cipher_len < 1 ||
276 newp->id_len + newp->cipher_len + newp->key_len > buffer.len - 6) {
277 SILC_LOG_ERROR(("Incorrect channel key payload in packet"));
287 silc_free(newp->cipher);
289 silc_free(newp->key);
294 /* Encodes channel key payload into a buffer and returns it. This is used
295 to add channel key payload into a packet. */
297 SilcBuffer silc_channel_key_payload_encode(SilcUInt16 id_len,
298 const unsigned char *id,
299 SilcUInt16 cipher_len,
300 const unsigned char *cipher,
302 const unsigned char *key)
307 SILC_LOG_DEBUG(("Encoding channel key payload"));
309 /* Allocate channel payload buffer. Length is 2 + id + 2 + key +
311 len = 2 + id_len + 2 + key_len + 2 + cipher_len;
312 buffer = silc_buffer_alloc_size(len);
316 /* Encode the Channel Payload */
317 silc_buffer_format(buffer,
318 SILC_STR_UI_SHORT(id_len),
319 SILC_STR_UI_XNSTRING(id, id_len),
320 SILC_STR_UI_SHORT(cipher_len),
321 SILC_STR_UI_XNSTRING(cipher, cipher_len),
322 SILC_STR_UI_SHORT(key_len),
323 SILC_STR_UI_XNSTRING(key, key_len),
329 /* Frees Channel Key Payload */
331 void silc_channel_key_payload_free(SilcChannelKeyPayload payload)
334 silc_free(payload->id);
335 silc_free(payload->cipher);
337 memset(payload->key, 0, payload->key_len);
338 silc_free(payload->key);
346 unsigned char *silc_channel_key_get_id(SilcChannelKeyPayload payload,
350 *id_len = payload->id_len;
355 /* Return cipher name */
357 unsigned char *silc_channel_key_get_cipher(SilcChannelKeyPayload payload,
358 SilcUInt32 *cipher_len)
361 *cipher_len = payload->cipher_len;
363 return payload->cipher;
368 unsigned char *silc_channel_key_get_key(SilcChannelKeyPayload payload,
372 *key_len = payload->key_len;