+Tue Mar 20 15:45:14 EET 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ * Added new notify type SILC_NOTIFY_TYPE_UMODE_CHANGE that is
+ used by routers as broadcast packet to inform other routers
+ about the changed user mode.
+
+ Implemented the notify handling in the server. Affected file is
+ silcd/packet_receive.c. Added the function
+ silc_server_send_notify_umode to the silcd/packet_send.[ch].
+
+ * Added new generic Channel Payload and deprecated the New Channel
+ Payload. The New Channel Payload is now the generic Channel
+ Payload.
+
+ * Added new argument `mode' to the silc_server_send_new_channel
+ as it is required in the Channel Payload now.
+
+ * Renamed the SilcChannelPayload to SilcChannelMessagePayload
+ and created a new and real SilChannelPayload to represent the
+ new generic Channel Payload. Implemented the encode/decode
+ for Channel Payload. Affected file lib/silccore/silcchannel.[ch].
+
+ * Added silc_server_get_client_channel_list to return the list
+ of channels the client has joined for WHOIS command reply.
+ Affected file silcd/server.[ch].
+
+ * Implemented the channel list sending in the WHOIS command reply
+ in server and in the client.
+
+ Implemented the channel list displaying on the user interface
+ as well. Affected file silc/client_ops.c.
+
+ * Added silc_channel_payload_parse_list to parse list of Channel
+ Payloads. It returns SilcDList list of SilcChannelPayloads.
+ Client for example can use this function to parse the list of
+ channels it receives in the WHOIS command reply. The caller
+ must free the list by calling silc_channel_payload_list_free.
+ Affected files lib/silccore/silcchannel.[ch].
+
Mon Mar 19 21:39:15 EET 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
* Added one new argument <user mode> to the WHOIS command reply
char buf[1024], *nickname, *username, *realname;
int len;
unsigned int idle, mode;
+ SilcBuffer channels;
if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
char *tmp;
nickname = va_arg(vp, char *);
username = va_arg(vp, char *);
realname = va_arg(vp, char *);
- (void)va_arg(vp, void *);
+ channels = va_arg(vp, SilcBuffer);
mode = va_arg(vp, unsigned int);
idle = va_arg(vp, unsigned int);
client->ops->say(client, conn, "%s", buf);
+ if (channels) {
+ SilcDList list = silc_channel_payload_parse_list(channels);
+ if (list) {
+ SilcChannelPayload entry;
+
+ memset(buf, 0, sizeof(buf));
+ strcat(buf, "on channels: ");
+
+ silc_dlist_start(list);
+ while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
+ char *m = silc_client_chumode_char(silc_channel_get_mode(entry));
+ unsigned int name_len;
+ char *name = silc_channel_get_name(entry, &name_len);
+
+ if (m)
+ strncat(buf, m, strlen(m));
+ strncat(buf, name, name_len);
+ strncat(buf, " ", 1);
+ silc_free(m);
+ }
+
+ client->ops->say(client, conn, "%s", buf);
+ silc_channel_payload_list_free(list);
+ }
+ }
+
if (mode)
client->ops->say(client, conn, "%s is %s", nickname,
(mode & SILC_UMODE_SERVER_OPERATOR) ?
SilcServer server = cmd->server;
char *tmp;
int i, count = 0, len;
- SilcBuffer packet, idp;
+ SilcBuffer packet, idp, channels;
SilcClientEntry entry;
SilcCommandStatus status;
unsigned short ident = silc_command_get_ident(cmd->payload);
len = strlen(hsock->hostname);
strncat(uh, hsock->hostname, len);
}
+
+ channels = silc_server_get_client_channel_list(server, entry);
+ SILC_PUT32_MSB(entry->mode, mode);
+
if (entry->connection) {
SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
}
- SILC_PUT32_MSB(entry->mode, mode);
-
- packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
- status, ident, 6,
- 2, idp->data, idp->len,
- 3, nh, strlen(nh),
- 4, uh, strlen(uh),
- 5, entry->userinfo,
- strlen(entry->userinfo),
- 7, mode, 4,
- 8, idle, 4);
+ if (channels)
+ packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
+ status, ident, 7,
+ 2, idp->data, idp->len,
+ 3, nh, strlen(nh),
+ 4, uh, strlen(uh),
+ 5, entry->userinfo,
+ strlen(entry->userinfo),
+ 6, channels->data,
+ channels->len,
+ 7, mode, 4,
+ 8, idle, 4);
+ else
+ packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
+ status, ident, 6,
+ 2, idp->data, idp->len,
+ 3, nh, strlen(nh),
+ 4, uh, strlen(uh),
+ 5, entry->userinfo,
+ strlen(entry->userinfo),
+ 7, mode, 4,
+ 8, idle, 4);
silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
0, packet->data, packet->len, FALSE);
silc_buffer_free(packet);
silc_buffer_free(idp);
+ if (channels)
+ silc_buffer_free(channels);
}
}
client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
}
+ /* Send UMODE change to primary router */
+ if (!server->standalone)
+ silc_server_send_notify_umode(server, server->router->connection, TRUE,
+ client->id, SILC_ID_CLIENT_LEN,
+ client->mode);
+
/* Send command reply to sender */
packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
SILC_STATUS_OK, ident, 1,
/* Client is now server operator */
client->mode |= SILC_UMODE_SERVER_OPERATOR;
+ /* Send UMODE change to primary router */
+ if (!server->standalone)
+ silc_server_send_notify_umode(server, server->router->connection, TRUE,
+ client->id, SILC_ID_CLIENT_LEN,
+ client->mode);
+
/* Send reply to the sender */
silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
SILC_STATUS_OK);
/* Client is now router operator */
client->mode |= SILC_UMODE_ROUTER_OPERATOR;
+ /* Send UMODE change to primary router */
+ if (!server->standalone)
+ silc_server_send_notify_umode(server, server->router->connection, TRUE,
+ client->id, SILC_ID_CLIENT_LEN,
+ client->mode);
+
/* Send reply to the sender */
silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
SILC_STATUS_OK);
/* Get port */
tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
- if (tmp) {
+ if (tmp)
SILC_GET32_MSB(port, tmp);
- }
/* Create the connection. It is done with timeout and is async. */
silc_server_create_connection(server, host, port);
/* Get port */
tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
- if (tmp) {
+ if (tmp)
SILC_GET32_MSB(port, tmp);
- }
server_entry = silc_idlist_find_server_by_conn(server->local_list,
name, port, NULL);
}
tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
- if (tmp) {
+ if (tmp)
SILC_GET32_MSB(mode, tmp);
- }
-
client_id = silc_id_payload_parse_id(id_data, id_len);
if (!client_id)
goto out;
/* Get channel entry */
- channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel = silc_idlist_find_channel_by_id(server->global_list,
channel_id, NULL);
if (!channel) {
- channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
silc_free(channel_id);
/* If the the client is not in local list we check global list (ie. the
channel will be global channel) and if it does not exist then create
entry for the client. */
- client = silc_idlist_find_client_by_id(server->local_list,
+ client = silc_idlist_find_client_by_id(server->global_list,
client_id, NULL);
if (!client) {
- client = silc_idlist_find_client_by_id(server->global_list,
+ client = silc_idlist_find_client_by_id(server->local_list,
client_id, NULL);
if (!client) {
/* If router did not find the client the it is bogus */
goto out;
/* Get channel entry */
- channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel = silc_idlist_find_channel_by_id(server->global_list,
channel_id, NULL);
if (!channel) {
- channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
silc_free(channel_id);
goto out;
/* Get channel entry */
- channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel = silc_idlist_find_channel_by_id(server->global_list,
channel_id, NULL);
if (!channel) {
- channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
silc_free(channel_id);
goto out;
/* Get channel entry */
- channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel = silc_idlist_find_channel_by_id(server->global_list,
channel_id, NULL);
if (!channel) {
- channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
silc_free(channel_id);
goto out;
/* Get channel entry */
- channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel = silc_idlist_find_channel_by_id(server->global_list,
channel_id, NULL);
if (!channel) {
- channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
silc_free(channel_id);
goto out;
/* Get channel entry */
- channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel = silc_idlist_find_channel_by_id(server->global_list,
channel_id, NULL);
if (!channel) {
- channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel = silc_idlist_find_channel_by_id(server->local_list,
channel_id, NULL);
if (!channel) {
silc_free(channel_id);
packet->buffer->len, FALSE);
/* If the the client is not in local list we check global list */
- client = silc_idlist_find_client_by_id(server->local_list,
+ client = silc_idlist_find_client_by_id(server->global_list,
client_id, NULL);
if (!client) {
- client = silc_idlist_find_client_by_id(server->global_list,
+ client = silc_idlist_find_client_by_id(server->local_list,
client_id, NULL);
if (!client) {
silc_free(client_id);
goto out;
/* If the the client is not in local list we check global list */
- client = silc_idlist_find_client_by_id(server->local_list,
+ client = silc_idlist_find_client_by_id(server->global_list,
client_id, NULL);
if (!client) {
- client = silc_idlist_find_client_by_id(server->global_list,
+ client = silc_idlist_find_client_by_id(server->local_list,
client_id, NULL);
if (!client) {
silc_free(client_id);
break;
}
+ case SILC_NOTIFY_TYPE_UMODE_CHANGE:
+ /*
+ * Save the mode of the client.
+ */
+
+ SILC_LOG_DEBUG(("UMODE_CHANGE notify"));
+
+ /* Get client ID */
+ tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+ if (!tmp)
+ goto out;
+ client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ if (!client_id)
+ goto out;
+
+ /* Get client entry */
+ client = silc_idlist_find_client_by_id(server->global_list,
+ client_id, NULL);
+ if (!client) {
+ client = silc_idlist_find_client_by_id(server->local_list,
+ client_id, NULL);
+ if (!client) {
+ silc_free(client_id);
+ goto out;
+ }
+ }
+ silc_free(client_id);
+
+ /* Get the mode */
+ tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+ if (!tmp)
+ goto out;
+
+ /* Save the mode */
+ SILC_GET32_MSB(client->mode, tmp);
+
+ break;
+
/* Ignore rest of the notify types for now */
case SILC_NOTIFY_TYPE_NONE:
case SILC_NOTIFY_TYPE_MOTD:
/* Encode new payload. This encrypts it also. */
SILC_GET16_MSB(data_len, packet->buffer->data);
- chp = silc_channel_payload_encode(data_len, packet->buffer->data + 2,
- iv_len, channel->iv,
- channel->channel_key,
- channel->hmac, server->rng);
+ chp = silc_channel_message_payload_encode(data_len,
+ packet->buffer->data + 2,
+ iv_len, channel->iv,
+ channel->channel_key,
+ channel->hmac, server->rng);
silc_buffer_put(packet->buffer, chp->data, chp->len);
silc_buffer_free(chp);
}
SilcSocketConnection sock,
SilcPacketContext *packet)
{
- unsigned char *id;
+ SilcChannelPayload payload;
SilcChannelID *channel_id;
- unsigned short channel_id_len;
char *channel_name;
- int ret;
+ unsigned int name_len;
+ unsigned char *id;
+ unsigned int id_len;
SILC_LOG_DEBUG(("Processing New Channel"));
server->server_type == SILC_SERVER)
return;
- /* Parse payload */
- ret = silc_buffer_unformat(packet->buffer,
- SILC_STR_UI16_STRING_ALLOC(&channel_name),
- SILC_STR_UI16_NSTRING_ALLOC(&id, &channel_id_len),
- SILC_STR_END);
- if (ret == -1) {
- if (channel_name)
- silc_free(channel_name);
- if (id)
- silc_free(id);
+ /* Parse the channel payload */
+ payload = silc_channel_payload_parse(packet->buffer);
+ if (!payload)
return;
- }
- /* Decode the channel ID */
- channel_id = silc_id_str2id(id, channel_id_len, SILC_ID_CHANNEL);
- if (!channel_id)
+ /* Get the channel ID */
+ channel_id = silc_channel_get_id_parse(payload);
+ if (!channel_id) {
+ silc_channel_payload_free(payload);
return;
+ }
+
+ channel_name = silc_channel_get_name(payload, &name_len);
+ if (name_len > 256)
+ channel_name[255] = '\0';
+
+ id = silc_channel_get_id(payload, &id_len);
if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
/* Add the server to global list as it is coming from router. It
silc_id_render(channel_id, SILC_ID_CHANNEL),
sock->hostname));
- silc_idlist_add_channel(server->global_list, channel_name, 0, channel_id,
- server->router->connection, NULL, NULL);
+ silc_idlist_add_channel(server->global_list, strdup(channel_name),
+ 0, channel_id, server->router->connection,
+ NULL, NULL);
server->stat.channels++;
} else {
channel = silc_server_create_new_channel_with_id(server, NULL, NULL,
channel_name,
channel_id, FALSE);
- if (!channel)
+ if (!channel) {
+ silc_channel_payload_free(payload);
+ silc_free(channel_id);
return;
+ }
/* Send the new channel key to the server */
- chk = silc_channel_key_payload_encode(channel_id_len, id,
+ chk = silc_channel_key_payload_encode(id_len, id,
strlen(channel->channel_key->
cipher->name),
channel->channel_key->cipher->name,
silc_server_send_channel_key(server, sock, channel, FALSE);
/* Send to the server */
- chk = silc_channel_key_payload_encode(channel_id_len, id,
+ chk = silc_channel_key_payload_encode(id_len, id,
strlen(channel->channel_key->
cipher->name),
channel->channel_key->cipher->name,
silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
chk->data, chk->len, FALSE);
silc_buffer_free(chk);
+ silc_free(channel_id);
/* Since the channel is coming from server and we also know about it
then send the JOIN notify to the server so that it see's our
/* XXX TODO **/
}
}
-
- silc_free(id);
}
/* Received New Channel List packet, list of New Channel List payloads inside
(len2 > buffer->truelen))
break;
- silc_buffer_pull_tail(buffer, 4 + len1 + len2);
- silc_buffer_put(buffer, packet->buffer->data, 4 + len1 + len2);
+ silc_buffer_pull_tail(buffer, 8 + len1 + len2);
+ silc_buffer_put(buffer, packet->buffer->data, 8 + len1 + len2);
/* Process the New Channel */
silc_server_new_channel(server, sock, new);
- silc_buffer_push_tail(buffer, 4 + len1 + len2);
- silc_buffer_pull(packet->buffer, 4 + len1 + len2);
+ silc_buffer_push_tail(buffer, 8 + len1 + len2);
+ silc_buffer_pull(packet->buffer, 8 + len1 + len2);
}
silc_buffer_free(buffer);
memcpy(tmp, data, data_len);
/* Decrypt the channel message (we don't check the MAC) */
- if (!silc_channel_payload_decrypt(tmp, data_len,
- channel->channel_key,
- NULL)) {
+ if (!silc_channel_message_payload_decrypt(tmp, data_len,
+ channel->channel_key,
+ NULL)) {
memset(tmp, 0, data_len);
silc_free(tmp);
continue;
silc_buffer_free(idp);
}
+/* Sends UMODE_CHANGE notify type. This tells that `client_id' client's
+ user mode in the SILC Network was changed. This function is used to
+ send the packet between routers as broadcast packet. */
+
+void silc_server_send_notify_umode(SilcServer server,
+ SilcSocketConnection sock,
+ int broadcast,
+ SilcClientID *client_id,
+ unsigned int client_id_len,
+ unsigned int mode_mask)
+{
+ SilcBuffer idp;
+ unsigned char mode[4];
+
+ idp = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
+ SILC_PUT32_MSB(mode_mask, mode);
+
+ silc_server_send_notify(server, sock, broadcast,
+ SILC_NOTIFY_TYPE_UMODE_CHANGE, 2,
+ idp->data, idp->len,
+ mode, 4);
+ silc_buffer_free(idp);
+}
+
/* Sends notify message destined to specific entity. */
void silc_server_send_notify_dest(SilcServer server,
int broadcast,
char *channel_name,
void *channel_id,
- unsigned int channel_id_len)
+ unsigned int channel_id_len,
+ unsigned int mode)
{
SilcBuffer packet;
unsigned char *cid;
if (!cid)
return;
- packet = silc_buffer_alloc(2 + 2 + name_len + channel_id_len);
- silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
- silc_buffer_format(packet,
- SILC_STR_UI_SHORT(name_len),
- SILC_STR_UI_XNSTRING(channel_name, name_len),
- SILC_STR_UI_SHORT(channel_id_len),
- SILC_STR_UI_XNSTRING(cid, channel_id_len),
- SILC_STR_END);
-
+ /* Encode the channel payload */
+ packet = silc_channel_payload_encode(channel_name, name_len,
+ cid, channel_id_len, mode);
silc_server_packet_send(server, sock, SILC_PACKET_NEW_CHANNEL,
broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
SilcClientID *client_id,
unsigned int client_id_len,
char *comment);
+void silc_server_send_notify_umode(SilcServer server,
+ SilcSocketConnection sock,
+ int broadcast,
+ SilcClientID *client_id,
+ unsigned int client_id_len,
+ unsigned int mode_mask);
void silc_server_send_notify_dest(SilcServer server,
SilcSocketConnection sock,
int broadcast,
int broadcast,
char *channel_name,
void *channel_id,
- unsigned int channel_id_len);
+ unsigned int channel_id_len,
+ unsigned int mode);
void silc_server_send_channel_key(SilcServer server,
SilcSocketConnection sender,
SilcChannelEntry channel,
/* Notify other routers about the new channel. We send the packet
to our primary route. */
- if (broadcast && server->standalone == FALSE) {
+ if (broadcast && server->standalone == FALSE)
silc_server_send_new_channel(server, server->router->connection, TRUE,
- channel_name, entry->id, SILC_ID_CHANNEL_LEN);
- }
+ channel_name, entry->id, SILC_ID_CHANNEL_LEN,
+ entry->mode);
server->stat.my_channels++;
/* Notify other routers about the new channel. We send the packet
to our primary route. */
- if (broadcast && server->standalone == FALSE) {
+ if (broadcast && server->standalone == FALSE)
silc_server_send_new_channel(server, server->router->connection, TRUE,
- channel_name, entry->id, SILC_ID_CHANNEL_LEN);
- }
+ channel_name, entry->id, SILC_ID_CHANNEL_LEN,
+ entry->mode);
server->stat.my_channels++;
cid = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
name_len = strlen(channel->channel_name);
- len = 4 + name_len + SILC_ID_CHANNEL_LEN;
+ len = 4 + name_len + SILC_ID_CHANNEL_LEN + 4;
*channels =
silc_buffer_realloc(*channels,
(*channels ? (*channels)->truelen + len : len));
name_len),
SILC_STR_UI_SHORT(SILC_ID_CHANNEL_LEN),
SILC_STR_UI_XNSTRING(cid, SILC_ID_CHANNEL_LEN),
+ SILC_STR_UI_INT(0),
SILC_STR_END);
silc_buffer_pull(*channels, len);
silc_free(id);
return NULL;
}
+
+/* Encodes and returns channel list of channels the `client' has joined.
+ Secret channels are not put to the list. */
+
+SilcBuffer silc_server_get_client_channel_list(SilcServer server,
+ SilcClientEntry client)
+{
+ SilcBuffer buffer = NULL;
+ SilcChannelEntry channel;
+ SilcChannelClientEntry chl;
+ unsigned char *cid;
+ unsigned short name_len;
+ int len;
+
+ silc_list_start(client->channels);
+ while ((chl = silc_list_get(client->channels)) != SILC_LIST_END) {
+ channel = chl->channel;
+
+ if (channel->mode & SILC_CHANNEL_MODE_SECRET)
+ continue;
+
+ cid = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
+ name_len = strlen(channel->channel_name);
+
+ len = 4 + name_len + SILC_ID_CHANNEL_LEN + 4;
+ buffer = silc_buffer_realloc(buffer,
+ (buffer ? (buffer)->truelen + len : len));
+ silc_buffer_pull_tail(buffer, ((buffer)->end - (buffer)->data));
+ silc_buffer_format(buffer,
+ SILC_STR_UI_SHORT(name_len),
+ SILC_STR_UI_XNSTRING(channel->channel_name,
+ name_len),
+ SILC_STR_UI_SHORT(SILC_ID_CHANNEL_LEN),
+ SILC_STR_UI_XNSTRING(cid, SILC_ID_CHANNEL_LEN),
+ SILC_STR_UI_INT(chl->mode), /* Client's mode */
+ SILC_STR_END);
+ silc_buffer_pull(buffer, len);
+ silc_free(cid);
+ }
+
+ silc_buffer_push(buffer, buffer->data - buffer->head);
+ return buffer;
+}
unsigned char *id_data,
unsigned int id_len,
SilcIDListData *idata);
+SilcBuffer silc_server_get_client_channel_list(SilcServer server,
+ SilcClientEntry client);
#endif
[Cipher]
-aes-256-cbc:../lib/silcsim/modules/aes.sim.so:32:16
-aes-192-cbc:../lib/silcsim/modules/aes.sim.so:24:16
-aes-128-cbc:../lib/silcsim/modules/aes.sim.so:16:16
-twofish-256-cbc:../lib/silcsim/modules/twofish.sim.so:32:16
-twofish-192-cbc:../lib/silcsim/modules/twofish.sim.so:24:16
-twofish-128-cbc:../lib/silcsim/modules/twofish.sim.so:16:16
-mars-256-cbc:../lib/silcsim/modules/mars.sim.so:32:16
-mars-192-cbc:../lib/silcsim/modules/mars.sim.so:24:16
-mars-128-cbc:../lib/silcsim/modules/mars.sim.so:16:16
+rc6:../lib/silcsim/modules/rc6.sim.so:16:16
+twofish:../lib/silcsim/modules/twofish.sim.so:16:16
+mars:../lib/silcsim/modules/mars.sim.so:16:16
none:../lib/silcsim/modules/none.sim.so:0:0
-[Hash]
+[Hash]
md5::64:16
sha1::64:20
[hmac]
hmac-sha1-96:sha1:12
hmac-md5-96:md5:12
-hmac-sha1:sha1:20
+hmac-sha1:sha1:20
hmac-md5:md5:16
#[PKCS]
Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi
[ServerInfo]
-lassi.kuo.fi.ssh.com:212.146.42.253:Kuopio, Finland:1334
+lassi.kuo.fi.ssh.com:10.2.1.7:Kuopio, Finland:1334
[ListenPort]
-212.146.42.253:212.146.42.253:1334
+10.2.1.7:10.2.1.7:1334
[Logging]
infologfile:silcd2.log:10000
:::1336:1
[AdminConnection]
-*:priikone:*:passwd:testi
+*:silc:silc:passwd:testi
[ServerConnection]
-212.146.42.253:passwd:priikone:1336:1:1
+10.2.1.7:passwd:priikone:1333:1:1
[RouterConnection]
-212.146.42.253:passwd:priikone:1335:1:1:0
+10.2.1.7:passwd:priikone:1335:1:1:0
[DenyConnection]
[RedirectClient]
2.3.2 Generic payloads .................................... 16
2.3.2.1 ID Payload .................................. 16
2.3.2.2 Argument Payload ............................ 16
+ 2.3.2.3 Channel Payload ............................. XXX
2.3.3 Disconnect Payload .................................. 17
2.3.4 Success Payload ..................................... 18
2.3.5 Failure Payload ..................................... 18
Figure 2: SILC Packet Header
Figure 3: ID Payload
Figure 4: Argument Payload
-Figure 5: Disconnect Payload
-Figure 6: Success Payload
-Figure 7: Failure Payload
-Figure 8: Reject Payload
-Figure 9: Notify Payload
-Figure 10: Error Payload
-Figure 11: Channel Message Payload
-Figure 12: Channel Key Payload
-Figure 13: Private Message Payload
-Figure 14: Private Message Key Payload
-Figure 15: Command Payload
-Figure 16: Connection Auth Request Payload
-Figure 17: New Client Payload
-Figure 18: New Server Payload
-Figure 19: New Channel Payload
+Figure 5: Channel Payload
+Figure 6: Disconnect Payload
+Figure 7: Success Payload
+Figure 8: Failure Payload
+Figure 9: Reject Payload
+Figure 10: Notify Payload
+Figure 11: Error Payload
+Figure 12: Channel Message Payload
+Figure 13: Channel Key Payload
+Figure 14: Private Message Payload
+Figure 15: Private Message Key Payload
+Figure 16: Command Payload
+Figure 17: Connection Auth Request Payload
+Figure 18: New Client Payload
+Figure 19: New Server Payload
+Figure 20: Key Agreement Payload
+Figure 21: Cell Routers Payload
.ti 0
payloads must cause rejection of the packet. The following diagram represents
the Argument Payload.
+The following diagram represents the Argument Payload.
.in 5
.nf
.in 3
+.ti 0
+2.3.2.3 Channel Payload
+
+Generic Channel Payload may be used information about channel, its name,
+the Channel ID and a mode.
+
+The following diagram represents the Channel Payload Payload.
+
+
+.in 5
+.nf
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Channel Name Length | |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
+| |
+~ Channel Name ~
+| |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Channel ID Length | |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
+| |
+~ Channel ID ~
+| |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Mode Mask |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 5: New Channel Payload
+
+
+.in 6
+o Channel Name Length (2 bytes) - Length of the channel name
+ field.
+
+o Channel Name (variable length) - The name of the channel.
+
+o Channel ID Length (2 bytes) - Length of the Channel ID field.
+
+o Channel ID (variable length) - The Channel ID.
+
+o Mode Mask (4 bytes) - A mode. This can be the mode of the
+ channel but it can also be the mode of the client on the
+ channel. The contents of this field is dependent of the
+ usage of this payload. The usage is defined separately
+ when this payload is used. This is a 32 bit MSB first value.
+.in 3
+
+
.ti 0
2.3.3 Disconnect Payload
.in 3
.ce
-Figure 5: Disconnect Payload
+Figure 6: Disconnect Payload
.in 3
.ce
-Figure 6: Success Payload
+Figure 7: Success Payload
.in 6
.in 3
.ce
-Figure 7: Failure Payload
+Figure 8: Failure Payload
.in 6
.in 3
.ce
-Figure 8: Reject Payload
+Figure 9: Reject Payload
.in 6
.in 3
.ce
-Figure 9: Notify Payload
+Figure 10: Notify Payload
.in 6
The killer may have set the <comment> to indicate the reason for
the killing.
+
+14 SILC_NOTIFY_TYPE_UMODE_CHANGE
+
+ Sent when user's mode in the SILC changes. This type is sent only
+ between routers as broadcast packet.
+
+ Max Arguments: 2
+ Arguments: (1) <Client ID> (2) <mode mask>
+
+ The <Client ID> is the client which mode was changed. The <mode mask>
+ is the new mode mask.
+
.in 3
Notify types starting from 16384 are reserved for private notify
.in 3
.ce
-Figure 10: Error Payload
+Figure 11: Error Payload
.in 6
.in 3
.ce
-Figure 11: Channel Message Payload
+Figure 12: Channel Message Payload
.in 6
.in 3
.ce
-Figure 12: Channel Key Payload
+Figure 13: Channel Key Payload
.in 3
.ce
-Figure 13: Private Message Payload
+Figure 14: Private Message Payload
.in 6
.in 3
.ce
-Figure 14: Private Message Key Payload
+Figure 15: Private Message Key Payload
.in 3
.ce
-Figure 15: Command Payload
+Figure 16: Command Payload
.in 6
.in 3
.ce
-Figure 16: Connection Auth Request Payload
+Figure 17: Connection Auth Request Payload
.in 6
.in 3
.ce
-Figure 17: New Client Payload
+Figure 18: New Client Payload
.in 6
.in 3
.ce
-Figure 18: New Server Payload
+Figure 19: New Server Payload
.in 6
then processes the command and creates the channel. Client never sends
this packet.
-The payload may only be sent with SILC_PACKET_NEW_CHANNEL packet.
-It must not be sent in any other packet type. The following diagram
-represents the New Channel Payload.
-
-
-.in 5
-.nf
- 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| Channel Name Length | |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
-| |
-~ Channel Name ~
-| |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| Channel ID Length | |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
-| |
-~ Channel ID ~
-| |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-.in 3
-
-.ce
-Figure 19: New Channel Payload
-
-
-
-.in 6
-o Channel Name Length (2 bytes) - Length of the channel name.
-
-o Channel Name (variable length) - The name of the created
- channel.
-
-o Channel ID Length (2 bytes) - Length of the Channel ID.
-
-o Channel ID (variable length) - The created Channel ID.
-.in 3
+The packet uses generic Channel Payload as New Channel Payload. See
+section 2.3.2.3 for generic Channel Payload. The Mode Mask field in the
+Channel Payload is the mode of the channel.
.ti 0
This, on the other hand, leads to cellular like network, where routers
are in the center of the cell and servers are connected to the router.
-Following diagram represents SILC network topology.
+The following diagram represents SILC network topology.
its local server first to the router of the cell, and from the router
to the other server in the cell.
-Following diagram represents this scenario:
+The following diagram represents this scenario:
.in 25
the message is routed to the router server to which the destination
server belongs, if the local router is connected to destination router.
If there is no direct connection to the destination router, the local
-router routes the message to its primary route. Following diagram
+router routes the message to its primary route. The following diagram
represents message sending between cells.
.ti 0
3.2.3 SILC Server Ports
-Following ports has been assigned by IANA for the SILC protocol:
+The following ports has been assigned by IANA for the SILC protocol:
.in 10
silc 706/tcp SILC
commas (`,') and wildcard characters.
Channels can have operators that can administrate the channel and
-operate all of its modes. Following operators on channel exist on SILC
+operate all of its modes. The following operators on channel exist on SILC
network.
.in 6
definition of how it must be done. SILC has a mandatory algorithm that
must be supported in order to be compliant with this protocol.
-Following ciphers are defined in SILC protocol:
+The following ciphers are defined in SILC protocol:
.in 6
aes-256-cbc AES in CBC mode, 256 bit key (mandatory)
and to perform other tasks related to public key cryptography. The
public keys are also used in the SILC Key Exchange protocol [SILC3].
-Following public key algorithms are defined in SILC protocol:
+The following public key algorithms are defined in SILC protocol:
.in 6
rsa RSA (mandatory)
DSS is described in [Menezes]. The RSA must be implemented according
PKCS #1 [PKCS1]. The mandatory PKCS #1 implementation in SILC must be
-compliant to either PKCS #1 version 1.5 or newer with the following
+compliant to either PKCS #1 version 1.5 or newer with the the following
notes: The signature encoding is always in same format as the encryption
encoding regardles of the PKCS #1 version. The signature with appendix
(with hash algorithm OID in the data) must not be used in the SILC. The
section. They are also used in the SILC Key Exchange protocol defined
in the [SILC3].
-Following Hash algorithm are defined in SILC protocol:
+The following Hash algorithm are defined in SILC protocol:
sha1 SHA-1, length = 20 (mandatory)
md5 MD5, length = 16 (optional)
(MAC) of the packet data. See [SILC2] for details how to compute the
MAC.
-Following MAC algorithms are defined in SILC protocol:
+The following MAC algorithms are defined in SILC protocol:
.in 6
hmac-sha1-96 HMAC-SHA1, length = 12 (mandatory)
use compression which is the mode that must be supported by all SILC
implementations.
-Following compression algorithms are defined:
+The following compression algorithms are defined:
.in 6
none No compression (mandatory)
o Identifier (variable length) - Indicates the identifier
of the public key. This data can be used to identify
- the owner of the key. The identifier is of following
+ the owner of the key. The identifier is of the following
format:
UN User name
The version detection of both client and server is performed at the
connection phase while executing the SILC Key Exchange protocol. The
version identifier is exchanged between initiator and responder. The
-version identifier is of following format:
+version identifier is of the following format:
.in 6
SILC-<protocol version>-<software version>
.in 3
-The version strings are of following format:
+The version strings are of the following format:
.in 6
protocol version = <major>.<minor>
key, then the key is distributed as described in section Processing the
Key Material in [SILC3]. After both parties has regenerated the session
key, both send SILC_PACKET_REKEY_DONE packet to each other. These packets
-are still secured with the old key. After these packets, following
+are still secured with the old key. After these packets, the following
packets must be protected with the new key.
so that all users are searched. However, the server still must
search its locally connected clients. The router must send
this command to the server who owns the requested client. That
- server must reply to the command. Server should not send whois
+ server must reply to the command. Server must not send whois
replies to the client until it has received the reply from its
router.
Max Arguments: 8
Arguments: (1) <Status Payload> (2) <Client ID>
(3) <nickname>[@<server>] (4) <username@host>
- (5) <real name> (6) [<channel list>]
+ (5) <real name> (6) [<Channel Payload
+ list>]
(7) [<user mode>] (8) [<idle time>]
<count> option were defined in the query there will be only
<count> many replies from the server.
+ The server may return the list of channel the client has joined.
+ In this case the list is list of Channel Payloads. The Mode Mask
+ in the Channel Payload (see [SILC2] and section 2.3.2.3 for the
+ Channel Payload) is the client's mode on the channel. The list
+ is encoded by adding the Channel Payloads one after the other.
+
Status messages:
SILC_STATUS_OK
SILC_STATUS_ERR_TOO_MANY_PARAMS
-
-
2 SILC_COMMAND_WHOWAS
Max Arguments: 2
give to the removed client some information why it was removed
from the network.
+ When killing a client the router must first send notify type
+ SILC_NOTIFY_TYPE_KILLED to all channels the client has joined.
+ The packet must not be sent to the killed client on the channel.
+ Then, the router must send the same notify type to its primary
+ router. Finally, the router must send the same notify type to
+ the client who was killed.
+
Reply messages to the command:
Max Arguments: 1
for user on client's screen or it may be public key or certificate
authentication data (data signed with private key).
+ After changing the mode server must send the notify type
+ SILC_NOTIFY_TYPE_UMODE_CHANGE to its primary router.
+
Reply messages to the command:
Max Arguments: 1
locally so that the mode setting/unsetting would work without
problems. Client may change only its own modes.
- Following client modes are defined:
+ After changing the mode server must send the notify type
+ SILC_NOTIFY_TYPE_UMODE_CHANGE to its primary router.
+
+ The following client modes are defined:
0x0000 SILC_UMODE_NONE
When the mode is changed SILC_NOTIFY_TYPE_CMODE_CHANGE notify
type is distributed to the channel.
- Following channel modes are defined:
+ The following channel modes are defined:
0x0000 SILC_CMODE_NONE
When the mode is changed SILC_NOTIFY_TYPE_CUMODE_CHANGE notify
type is distributed to the channel.
- Following channel modes are defined:
+ The following channel modes are defined:
0x0000 SILC_CUMODE_NONE
local properties, such as, local connections and normal server
administration.
+ After changing the mode server must send the notify type
+ SILC_NOTIFY_TYPE_UMODE_CHANGE to its primary router.
+
Reply messages to the command:
Max Arguments: 1
Command Status Payload is sent in command reply messages to indicate
the status of the command. The payload is one of argument in the
command thus this is the data area in Command Argument Payload described
-in [SILC2]. The payload is only 2 bytes of length. Following diagram
+in [SILC2]. The payload is only 2 bytes of length. The following diagram
represents the Command Status Payload (field is always in MSB order).
silc_hash_make(client->md5hash, channel->iv, iv_len, channel->iv);
/* Encode the channel payload. This also encrypts the message payload. */
- payload = silc_channel_payload_encode(data_len, data, iv_len,
- channel->iv, cipher, hmac,
- client->rng);
+ payload = silc_channel_message_payload_encode(data_len, data, iv_len,
+ channel->iv, cipher, hmac,
+ client->rng);
/* Get data used in packet header encryption, keys and stuff. */
cipher = conn->send_key;
{
SilcClientConnection conn = (SilcClientConnection)sock->user_data;
SilcBuffer buffer = packet->buffer;
- SilcChannelPayload payload = NULL;
+ SilcChannelMessagePayload payload = NULL;
SilcChannelID *id = NULL;
SilcChannelEntry channel;
SilcChannelUser chu;
all private keys and check what decrypts correctly. */
if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
/* Parse the channel message payload. This also decrypts the payload */
- payload = silc_channel_payload_parse(buffer, channel->channel_key,
- channel->hmac);
+ payload = silc_channel_message_payload_parse(buffer, channel->channel_key,
+ channel->hmac);
if (!payload)
goto out;
} else if (channel->private_keys) {
silc_dlist_start(channel->private_keys);
while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
/* Parse the channel message payload. This also decrypts the payload */
- payload = silc_channel_payload_parse(buffer, entry->cipher,
- entry->hmac);
+ payload = silc_channel_message_payload_parse(buffer, entry->cipher,
+ entry->hmac);
if (payload)
break;
}
goto out;
}
- message = silc_channel_get_data(payload, NULL);
+ message = silc_channel_message_get_data(payload, NULL);
/* Find client entry */
silc_list_start(channel->clients);
if (client_id)
silc_free(client_id);
if (payload)
- silc_channel_payload_free(payload);
+ silc_channel_message_payload_free(payload);
}
/* Saves channel key from encoded `key_payload'. This is used when we
char *nickname = NULL, *username = NULL;
char *realname = NULL;
unsigned int idle = 0, mode = 0;
+ SilcBuffer channels = NULL;
argc = silc_argument_get_arg_num(cmd->args);
return;
}
- tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
+ tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
if (tmp) {
- SILC_GET32_MSB(mode, tmp);
+ channels = silc_buffer_alloc(len);
+ silc_buffer_pull_tail(channels, SILC_BUFFER_END(channels));
+ silc_buffer_put(channels, tmp, len);
}
+ tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
+ if (tmp)
+ SILC_GET32_MSB(mode, tmp);
+
tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
- if (tmp) {
+ if (tmp)
SILC_GET32_MSB(idle, tmp);
- }
/* Check if we have this client cached already. */
if (!silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
/* Notify application */
if (!cmd->callback)
COMMAND_REPLY((ARGS, client_entry, nickname, username, realname,
- NULL, mode, idle));
+ channels, mode, idle));
+
+ if (channels)
+ silc_buffer_free(channels);
}
/* Received reply for WHOIS command. This maybe called several times
/* Get channel mode */
tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
- if (tmp) {
+ if (tmp)
SILC_GET32_MSB(mode, tmp);
- } else {
+ else
mode = 0;
- }
/* Get channel key */
tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
GNU General Public License for more details.
*/
-/* Channel Payload and Channel Key Payload implementations. */
+/* Channel Payload, Channel Message Payload and Channel Key Payload
+ implementations. */
/* $Id$ */
#include "silcincludes.h"
/******************************************************************************
- Channel Message Payload
+ Channel Payload
******************************************************************************/
/* Channel Message Payload structure. Contents of this structure is parsed
from SILC packets. */
struct SilcChannelPayloadStruct {
+ unsigned short name_len;
+ unsigned char *channel_name;
+ unsigned short id_len;
+ unsigned char *channel_id;
+ unsigned int mode;
+};
+
+/* Parses channel payload returning new channel payload structure. */
+
+SilcChannelPayload silc_channel_payload_parse(SilcBuffer buffer)
+{
+ SilcChannelPayload new;
+ int ret;
+
+ SILC_LOG_DEBUG(("Parsing channel payload"));
+
+ new = silc_calloc(1, sizeof(*new));
+
+ /* Parse the Channel Payload. Ignore the padding. */
+ ret = silc_buffer_unformat(buffer,
+ SILC_STR_UI16_NSTRING_ALLOC(&new->channel_name,
+ &new->name_len),
+ SILC_STR_UI16_NSTRING_ALLOC(&new->channel_id,
+ &new->id_len),
+ SILC_STR_UI_INT(&new->mode),
+ SILC_STR_END);
+ if (ret == -1)
+ goto err;
+
+ if ((new->name_len < 1 || new->name_len > buffer->len) ||
+ (new->id_len < 1 || new->id_len > buffer->len)) {
+ SILC_LOG_ERROR(("Incorrect channel payload in packet, packet dropped"));
+ goto err;
+ }
+
+ return new;
+
+ err:
+ silc_channel_payload_free(new);
+ return NULL;
+}
+
+/* Parses list of channel payloads returning list of payloads. */
+
+SilcDList silc_channel_payload_parse_list(SilcBuffer buffer)
+{
+ SilcDList list;
+ SilcChannelPayload new;
+ int len, ret;
+
+ SILC_LOG_DEBUG(("Parsing channel payload list"));
+
+ list = silc_dlist_init();
+
+ while (buffer->len) {
+ new = silc_calloc(1, sizeof(*new));
+ ret = silc_buffer_unformat(buffer,
+ SILC_STR_UI16_NSTRING_ALLOC(&new->channel_name,
+ &new->name_len),
+ SILC_STR_UI16_NSTRING_ALLOC(&new->channel_id,
+ &new->id_len),
+ SILC_STR_UI_INT(&new->mode),
+ SILC_STR_END);
+ if (ret == -1)
+ goto err;
+
+ if ((new->name_len < 1 || new->name_len > buffer->len) ||
+ (new->id_len < 1 || new->id_len > buffer->len)) {
+ SILC_LOG_ERROR(("Incorrect channel payload in packet, packet dropped"));
+ goto err;
+ }
+
+ len = 2 + new->name_len + 2 + new->id_len + 4;
+ if (buffer->len < len)
+ break;
+ silc_buffer_pull(buffer, len);
+
+ silc_dlist_add(list, new);
+ }
+
+ return list;
+
+ err:
+ silc_channel_payload_list_free(list);
+ return NULL;
+}
+
+/* Encode new channel payload and returns it as buffer. */
+
+SilcBuffer silc_channel_payload_encode(unsigned char *channel_name,
+ unsigned short channel_name_len,
+ unsigned char *channel_id,
+ unsigned int channel_id_len,
+ unsigned int mode)
+{
+ SilcBuffer buffer;
+
+ SILC_LOG_DEBUG(("Encoding message payload"));
+
+ buffer = silc_buffer_alloc(2 + channel_name_len + 2 + channel_id_len + 4);
+ silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
+
+ /* Encode the Channel Payload */
+ silc_buffer_format(buffer,
+ SILC_STR_UI_SHORT(channel_name_len),
+ SILC_STR_UI_XNSTRING(channel_name, channel_name_len),
+ SILC_STR_UI_SHORT(channel_id_len),
+ SILC_STR_UI_XNSTRING(channel_id, channel_id_len),
+ SILC_STR_UI_INT(mode),
+ SILC_STR_END);
+
+ return buffer;
+}
+
+/* Free's Channel Payload */
+
+void silc_channel_payload_free(SilcChannelPayload payload)
+{
+ silc_free(payload->channel_name);
+ silc_free(payload->channel_id);
+ silc_free(payload);
+}
+
+/* Free's list of Channel Payloads */
+
+void silc_channel_payload_list_free(SilcDList list)
+{
+ SilcChannelPayload entry;
+
+ silc_dlist_start(list);
+ while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
+ silc_free(entry->channel_name);
+ silc_free(entry->channel_id);
+ silc_free(entry);
+ silc_dlist_del(list, entry);
+ }
+
+ silc_dlist_uninit(list);
+}
+
+/* Return the channel name */
+
+unsigned char *silc_channel_get_name(SilcChannelPayload payload,
+ unsigned int *channel_name_len)
+{
+ if (channel_name_len)
+ *channel_name_len = payload->name_len;
+
+ return payload->channel_name;
+}
+
+/* Return the channel ID */
+
+unsigned char *silc_channel_get_id(SilcChannelPayload payload,
+ unsigned int *channel_id_len)
+{
+ if (channel_id_len)
+ *channel_id_len = payload->id_len;
+
+ return payload->channel_id;
+}
+
+/* Return the channel ID as parsed ID. */
+
+SilcChannelID *silc_channel_get_id_parse(SilcChannelPayload payload)
+{
+ return silc_id_str2id(payload->channel_id, payload->id_len,
+ SILC_ID_CHANNEL);
+}
+
+/* Return the mode. The mode is arbitrary. It can be the mode of the
+ channel or perhaps the mode of the client on the channel. The protocol
+ dictates what the usage of the mode is in different circumstances. */
+
+unsigned int silc_channel_get_mode(SilcChannelPayload payload)
+{
+ return payload->mode;
+}
+
+/******************************************************************************
+
+ Channel Message Payload
+
+******************************************************************************/
+
+/* Channel Message Payload structure. Contents of this structure is parsed
+ from SILC packets. */
+struct SilcChannelMessagePayloadStruct {
unsigned short data_len;
unsigned char *data;
unsigned char *mac;
/* Decrypts the channel message payload. */
-int silc_channel_payload_decrypt(unsigned char *data,
- size_t data_len,
- SilcCipher cipher,
- SilcHmac hmac)
+int silc_channel_message_payload_decrypt(unsigned char *data,
+ size_t data_len,
+ SilcCipher cipher,
+ SilcHmac hmac)
{
unsigned int iv_len, mac_len;
unsigned char *end, *mac, mac2[32];
return TRUE;
}
-/* Parses channel payload returning new channel payload structure. This
- also decrypts it and checks the MAC. */
+/* Parses channel message payload returning new channel payload structure.
+ This also decrypts it and checks the MAC. */
-SilcChannelPayload silc_channel_payload_parse(SilcBuffer buffer,
- SilcCipher cipher,
- SilcHmac hmac)
+SilcChannelMessagePayload
+silc_channel_message_payload_parse(SilcBuffer buffer,
+ SilcCipher cipher,
+ SilcHmac hmac)
{
- SilcChannelPayload new;
+ SilcChannelMessagePayload new;
int ret;
unsigned int iv_len, mac_len;
- SILC_LOG_DEBUG(("Parsing channel payload"));
+ SILC_LOG_DEBUG(("Parsing channel message payload"));
/* Decrypt the payload */
- ret = silc_channel_payload_decrypt(buffer->data, buffer->len,
+ ret = silc_channel_message_payload_decrypt(buffer->data, buffer->len,
cipher, hmac);
if (ret == FALSE)
return NULL;
new = silc_calloc(1, sizeof(*new));
- /* Parse the Channel Payload. Ignore the padding. */
+ /* Parse the Channel Message Payload. Ignore the padding. */
ret = silc_buffer_unformat(buffer,
SILC_STR_UI16_NSTRING_ALLOC(&new->data,
&new->data_len),
goto err;
if (new->data_len < 1 || new->data_len > buffer->len) {
- SILC_LOG_ERROR(("Incorrect channel payload in packet, packet dropped"));
+ SILC_LOG_ERROR(("Incorrect channel messaeg payload in packet, "
+ "packet dropped"));
goto err;
}
return new;
err:
- silc_channel_payload_free(new);
+ silc_channel_message_payload_free(new);
return NULL;
}
-/* Encodes channel payload into a buffer and returns it. This is used
- to add channel payload into a packet. As the channel payload is
+/* Encodes channel message payload into a buffer and returns it. This is used
+ to add channel message payload into a packet. As the channel payload is
encrypted separately from other parts of the packet padding must
be applied to the payload. */
-SilcBuffer silc_channel_payload_encode(unsigned short data_len,
- unsigned char *data,
- unsigned short iv_len,
- unsigned char *iv,
- SilcCipher cipher,
- SilcHmac hmac,
- SilcRng rng)
+SilcBuffer silc_channel_message_payload_encode(unsigned short data_len,
+ unsigned char *data,
+ unsigned short iv_len,
+ unsigned char *iv,
+ SilcCipher cipher,
+ SilcHmac hmac,
+ SilcRng rng)
{
int i;
SilcBuffer buffer;
unsigned char pad[SILC_PACKET_MAX_PADLEN];
unsigned char mac[32];
- SILC_LOG_DEBUG(("Encoding channel payload"));
+ SILC_LOG_DEBUG(("Encoding channel message payload"));
/* Calculate length of padding. IV is not included into the calculation
since it is not encrypted. */
/* Generate padding */
for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte(rng);
- /* Encode the Channel Payload */
+ /* Encode the Channel Message Payload */
silc_buffer_pull_tail(buffer, 4 + data_len + pad_len);
silc_buffer_format(buffer,
SILC_STR_UI_SHORT(data_len),
return buffer;
}
-/* Free's Channel Payload */
+/* Free's Channel Message Payload */
-void silc_channel_payload_free(SilcChannelPayload payload)
+void silc_channel_message_payload_free(SilcChannelMessagePayload payload)
{
- if (payload) {
- if (payload->data) {
- memset(payload->data, 0, payload->data_len);
- silc_free(payload->data);
- }
- silc_free(payload);
+ if (payload->data) {
+ memset(payload->data, 0, payload->data_len);
+ silc_free(payload->data);
}
+ silc_free(payload);
}
/* Return data */
-unsigned char *silc_channel_get_data(SilcChannelPayload payload,
- unsigned int *data_len)
+unsigned char *silc_channel_message_get_data(SilcChannelMessagePayload payload,
+ unsigned int *data_len)
{
if (data_len)
*data_len = payload->data_len;
/* Return MAC. The caller knows the length of the MAC */
-unsigned char *silc_channel_get_mac(SilcChannelPayload payload)
+unsigned char *silc_channel_mesage_get_mac(SilcChannelMessagePayload payload)
{
return payload->mac;
}
/* Return IV. The caller knows the length of the IV */
-unsigned char *silc_channel_get_iv(SilcChannelPayload payload)
+unsigned char *silc_channel_message_get_iv(SilcChannelMessagePayload payload)
{
return payload->iv;
}
#ifndef SILCCHANNEL_H
#define SILCCHANNEL_H
-/* Forward declaration for Channel Message Payload parsed from packet. The
+#include "silcdlist.h"
+
+/* Forward declaration for Channel Payload parsed from packet. The
actual structure is defined in source file and is private data. */
typedef struct SilcChannelPayloadStruct *SilcChannelPayload;
+/* Forward declaration for Channel Message Payload parsed from packet. The
+ actual structure is defined in source file and is private data. */
+typedef struct SilcChannelMessagePayloadStruct *SilcChannelMessagePayload;
+
/* Forward declaration for Channel Key Payload parsed from packet. The
actual structure is defined in source file and is private data. */
typedef struct SilcChannelKeyPayloadStruct *SilcChannelKeyPayload;
/* Prototypes */
-int silc_channel_payload_decrypt(unsigned char *data,
- size_t data_len,
- SilcCipher cipher,
- SilcHmac hmac);
-SilcChannelPayload silc_channel_payload_parse(SilcBuffer buffer,
- SilcCipher cipher,
- SilcHmac hmac);
-SilcBuffer silc_channel_payload_encode(unsigned short data_len,
- unsigned char *data,
- unsigned short iv_len,
- unsigned char *iv,
- SilcCipher cipher,
- SilcHmac hmac,
- SilcRng rng);
+SilcChannelPayload silc_channel_payload_parse(SilcBuffer buffer);
+SilcDList silc_channel_payload_parse_list(SilcBuffer buffer);
+SilcBuffer silc_channel_payload_encode(unsigned char *channel_name,
+ unsigned short channel_name_len,
+ unsigned char *channel_id,
+ unsigned int channel_id_len,
+ unsigned int mode);
void silc_channel_payload_free(SilcChannelPayload payload);
-unsigned char *silc_channel_get_data(SilcChannelPayload payload,
+void silc_channel_payload_list_free(SilcDList list);
+unsigned char *silc_channel_get_name(SilcChannelPayload payload,
+ unsigned int *channel_name_len);
+unsigned char *silc_channel_get_id(SilcChannelPayload payload,
+ unsigned int *channel_id_len);
+SilcChannelID *silc_channel_get_id_parse(SilcChannelPayload payload);
+unsigned int silc_channel_get_mode(SilcChannelPayload payload);
+int silc_channel_message_payload_decrypt(unsigned char *data,
+ size_t data_len,
+ SilcCipher cipher,
+ SilcHmac hmac);
+SilcChannelMessagePayload
+silc_channel_message_payload_parse(SilcBuffer buffer,
+ SilcCipher cipher,
+ SilcHmac hmac);
+SilcBuffer silc_channel_message_payload_encode(unsigned short data_len,
+ unsigned char *data,
+ unsigned short iv_len,
+ unsigned char *iv,
+ SilcCipher cipher,
+ SilcHmac hmac,
+ SilcRng rng);
+void silc_channel_message_payload_free(SilcChannelMessagePayload payload);
+unsigned char *silc_channel_message_get_data(SilcChannelMessagePayload payload,
unsigned int *data_len);
-unsigned char *silc_channel_get_mac(SilcChannelPayload payload);
-unsigned char *silc_channel_get_iv(SilcChannelPayload payload);
+unsigned char *silc_channel_message_get_mac(SilcChannelMessagePayload payload);
+unsigned char *silc_channel_message_get_iv(SilcChannelMessagePayload payload);
SilcChannelKeyPayload silc_channel_key_payload_parse(SilcBuffer buffer);
SilcBuffer silc_channel_key_payload_encode(unsigned short id_len,
unsigned char *id,
#define SILC_NOTIFY_TYPE_SERVER_SIGNOFF 11 /* Server quitting SILC */
#define SILC_NOTIFY_TYPE_KICKED 12 /* Kicked from channel */
#define SILC_NOTIFY_TYPE_KILLED 13 /* Killed from the network */
+#define SILC_NOTIFY_TYPE_UMODE_CHANGE 14 /* user mode was changed */
/* Prototypes */
SilcNotifyPayload silc_notify_payload_parse(SilcBuffer buffer);