5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 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; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
20 /* Channel Payload, Channel Message Payload and Channel Key Payload
24 #include "silcincludes.h"
25 #include "silcchannel.h"
26 #include "silcchannel_i.h"
28 /* Parses channel payload returning new channel payload structure. */
30 SilcChannelPayload silc_channel_payload_parse(const unsigned char *payload,
31 SilcUInt32 payload_len)
33 SilcBufferStruct buffer;
34 SilcChannelPayload newp;
37 SILC_LOG_DEBUG(("Parsing channel payload"));
39 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
40 newp = silc_calloc(1, sizeof(*newp));
44 /* Parse the Channel Payload. Ignore the padding. */
45 ret = silc_buffer_unformat(&buffer,
46 SILC_STR_UI16_NSTRING_ALLOC(&newp->channel_name,
48 SILC_STR_UI16_NSTRING_ALLOC(&newp->channel_id,
50 SILC_STR_UI_INT(&newp->mode),
55 if ((newp->name_len < 1 || newp->name_len > buffer.len - 8) ||
56 (newp->id_len < 1 || newp->id_len > buffer.len - 8) ||
57 (newp->id_len + newp->name_len > buffer.len - 8)) {
58 SILC_LOG_ERROR(("Incorrect channel payload in packet, packet dropped"));
65 silc_channel_payload_free(newp);
69 /* Parses list of channel payloads returning list of payloads. */
71 SilcDList silc_channel_payload_parse_list(const unsigned char *payload,
72 SilcUInt32 payload_len)
74 SilcBufferStruct buffer;
76 SilcChannelPayload newp;
79 SILC_LOG_DEBUG(("Parsing channel payload list"));
81 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
82 list = silc_dlist_init();
85 newp = silc_calloc(1, sizeof(*newp));
88 ret = silc_buffer_unformat(&buffer,
89 SILC_STR_UI16_NSTRING_ALLOC(&newp->channel_name,
91 SILC_STR_UI16_NSTRING_ALLOC(&newp->channel_id,
93 SILC_STR_UI_INT(&newp->mode),
98 if ((newp->name_len < 1 || newp->name_len > buffer.len) ||
99 (newp->id_len < 1 || newp->id_len > buffer.len)) {
100 SILC_LOG_ERROR(("Incorrect channel payload in packet, packet dropped"));
104 len = 2 + newp->name_len + 2 + newp->id_len + 4;
105 if (buffer.len < len)
107 silc_buffer_pull(&buffer, len);
109 silc_dlist_add(list, newp);
115 silc_channel_payload_list_free(list);
119 /* Encode new channel payload and returns it as buffer. */
121 SilcBuffer silc_channel_payload_encode(const unsigned char *channel_name,
122 SilcUInt16 channel_name_len,
123 const unsigned char *channel_id,
124 SilcUInt32 channel_id_len,
129 SILC_LOG_DEBUG(("Encoding message payload"));
131 buffer = silc_buffer_alloc_size(2 + channel_name_len + 2 +
136 /* Encode the Channel Payload */
137 silc_buffer_format(buffer,
138 SILC_STR_UI_SHORT(channel_name_len),
139 SILC_STR_UI_XNSTRING(channel_name, channel_name_len),
140 SILC_STR_UI_SHORT(channel_id_len),
141 SILC_STR_UI_XNSTRING(channel_id, channel_id_len),
142 SILC_STR_UI_INT(mode),
148 /* Frees Channel Payload */
150 void silc_channel_payload_free(SilcChannelPayload payload)
152 silc_free(payload->channel_name);
153 silc_free(payload->channel_id);
157 /* Free's list of Channel Payloads */
159 void silc_channel_payload_list_free(SilcDList list)
161 SilcChannelPayload entry;
163 silc_dlist_start(list);
164 while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
165 silc_free(entry->channel_name);
166 silc_free(entry->channel_id);
167 silc_dlist_del(list, entry);
171 silc_dlist_uninit(list);
174 /* Return the channel name */
176 unsigned char *silc_channel_get_name(SilcChannelPayload payload,
177 SilcUInt32 *channel_name_len)
179 if (channel_name_len)
180 *channel_name_len = payload->name_len;
182 return payload->channel_name;
185 /* Return the channel ID */
187 unsigned char *silc_channel_get_id(SilcChannelPayload payload,
188 SilcUInt32 *channel_id_len)
191 *channel_id_len = payload->id_len;
193 return payload->channel_id;
196 /* Return the channel ID as parsed ID. */
198 SilcChannelID *silc_channel_get_id_parse(SilcChannelPayload payload)
200 return silc_id_str2id(payload->channel_id, payload->id_len,
204 /* Return the mode. The mode is arbitrary. It can be the mode of the
205 channel or perhaps the mode of the client on the channel. The protocol
206 dictates what the usage of the mode is in different circumstances. */
208 SilcUInt32 silc_channel_get_mode(SilcChannelPayload payload)
210 return payload->mode;
214 /******************************************************************************
218 ******************************************************************************/
220 /* Parses channel key payload returning new channel key payload structure */
222 SilcChannelKeyPayload
223 silc_channel_key_payload_parse(const unsigned char *payload,
224 SilcUInt32 payload_len)
226 SilcBufferStruct buffer;
227 SilcChannelKeyPayload newp;
230 SILC_LOG_DEBUG(("Parsing channel key payload"));
232 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
233 newp = silc_calloc(1, sizeof(*newp));
237 /* Parse the Channel Key Payload */
239 silc_buffer_unformat(&buffer,
240 SILC_STR_UI16_NSTRING_ALLOC(&newp->id, &newp->id_len),
241 SILC_STR_UI16_NSTRING_ALLOC(&newp->cipher,
243 SILC_STR_UI16_NSTRING_ALLOC(&newp->key,
249 if (newp->id_len < 1 || newp->key_len < 1 || newp->cipher_len < 1 ||
250 newp->id_len + newp->cipher_len + newp->key_len > buffer.len - 6) {
251 SILC_LOG_ERROR(("Incorrect channel key payload in packet"));
261 silc_free(newp->cipher);
263 silc_free(newp->key);
268 /* Encodes channel key payload into a buffer and returns it. This is used
269 to add channel key payload into a packet. */
271 SilcBuffer silc_channel_key_payload_encode(SilcUInt16 id_len,
272 const unsigned char *id,
273 SilcUInt16 cipher_len,
274 const unsigned char *cipher,
276 const unsigned char *key)
281 SILC_LOG_DEBUG(("Encoding channel key payload"));
283 /* Allocate channel payload buffer. Length is 2 + id + 2 + key +
285 len = 2 + id_len + 2 + key_len + 2 + cipher_len;
286 buffer = silc_buffer_alloc_size(len);
290 /* Encode the Channel Payload */
291 silc_buffer_format(buffer,
292 SILC_STR_UI_SHORT(id_len),
293 SILC_STR_UI_XNSTRING(id, id_len),
294 SILC_STR_UI_SHORT(cipher_len),
295 SILC_STR_UI_XNSTRING(cipher, cipher_len),
296 SILC_STR_UI_SHORT(key_len),
297 SILC_STR_UI_XNSTRING(key, key_len),
303 /* Frees Channel Key Payload */
305 void silc_channel_key_payload_free(SilcChannelKeyPayload payload)
308 silc_free(payload->id);
309 silc_free(payload->cipher);
311 memset(payload->key, 0, payload->key_len);
312 silc_free(payload->key);
320 unsigned char *silc_channel_key_get_id(SilcChannelKeyPayload payload,
324 *id_len = payload->id_len;
329 /* Return cipher name */
331 unsigned char *silc_channel_key_get_cipher(SilcChannelKeyPayload payload,
332 SilcUInt32 *cipher_len)
335 *cipher_len = payload->cipher_len;
337 return payload->cipher;
342 unsigned char *silc_channel_key_get_key(SilcChannelKeyPayload payload,
346 *key_len = payload->key_len;