Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
- Copyright (C) 1997 - 2000 Pekka Riikonen
+ Copyright (C) 1997 - 2001 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
goto err;
/* Decode destination Client ID */
- id = silc_id_str2id(packet->dst_id, SILC_ID_CLIENT);
+ id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT);
if (!id) {
SILC_LOG_ERROR(("Could not decode destination Client ID, dropped"));
goto err;
if (packet->dst_id_type == SILC_ID_CLIENT) {
/* Destination must be one of ours */
- id = silc_id_str2id(packet->dst_id, SILC_ID_CLIENT);
+ id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT);
+ if (!id)
+ return;
client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
if (!client) {
SILC_LOG_ERROR(("Cannot process command reply to unknown client"));
}
/* Find channel entry */
- id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
+ id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
+ if (!id)
+ goto out;
channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
if (!channel) {
channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
from router we won't do the check as the message is from client that
we don't know about. Also, if the original sender is not client
(as it can be server as well) we don't do the check. */
- sender = silc_id_str2id(packet->src_id, packet->src_id_type);
+ sender = silc_id_str2id(packet->src_id, packet->src_id_len,
+ packet->src_id_type);
+ if (!sender)
+ goto out;
if (sock->type != SILC_SOCKET_TYPE_ROUTER &&
packet->src_id_type == SILC_ID_CLIENT) {
silc_list_start(channel->user_list);
SilcIdType old_id_type, new_id_type;
unsigned short old_id_len, new_id_len;
void *id = NULL, *id2 = NULL;
+ int ret;
if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
packet->src_id_type == SILC_ID_CLIENT)
SILC_LOG_DEBUG(("Replacing ID"));
- silc_buffer_unformat(buffer,
- SILC_STR_UI_SHORT(&old_id_type),
- SILC_STR_UI16_NSTRING_ALLOC(&old_id, &old_id_len),
- SILC_STR_UI_SHORT(&new_id_type),
- SILC_STR_UI16_NSTRING_ALLOC(&new_id, &new_id_len),
- SILC_STR_END);
+ ret = silc_buffer_unformat(buffer,
+ SILC_STR_UI_SHORT(&old_id_type),
+ SILC_STR_UI16_NSTRING_ALLOC(&old_id, &old_id_len),
+ SILC_STR_UI_SHORT(&new_id_type),
+ SILC_STR_UI16_NSTRING_ALLOC(&new_id, &new_id_len),
+ SILC_STR_END);
+ if (ret == -1)
+ goto out;
if (old_id_type != new_id_type)
goto out;
new_id_len != silc_id_get_len(new_id_type))
goto out;
- id = silc_id_str2id(old_id, old_id_type);
+ id = silc_id_str2id(old_id, old_id_len, old_id_type);
if (!id)
goto out;
- id2 = silc_id_str2id(new_id, new_id_type);
+ id2 = silc_id_str2id(new_id, new_id_len, new_id_type);
if (!id2)
goto out;
/* Replace the old ID */
switch(old_id_type) {
case SILC_ID_CLIENT:
- SILC_LOG_DEBUG(("Old Client ID id(%s)",
- silc_id_render(id, SILC_ID_CLIENT)));
- SILC_LOG_DEBUG(("New Client ID id(%s)",
- silc_id_render(id2, SILC_ID_CLIENT)));
- if (silc_idlist_replace_client_id(server->local_list, id, id2) == NULL)
- if (server->server_type == SILC_ROUTER)
- silc_idlist_replace_client_id(server->global_list, id, id2);
- break;
+ {
+ SilcBuffer nidp, oidp;
+ SilcClientEntry client = NULL;
+
+ SILC_LOG_DEBUG(("Old Client ID id(%s)",
+ silc_id_render(id, SILC_ID_CLIENT)));
+ SILC_LOG_DEBUG(("New Client ID id(%s)",
+ silc_id_render(id2, SILC_ID_CLIENT)));
+
+ if ((client = silc_idlist_replace_client_id(server->local_list,
+ id, id2)) == NULL)
+ if (server->server_type == SILC_ROUTER)
+ client = silc_idlist_replace_client_id(server->global_list, id, id2);
+
+ if (client) {
+ oidp = silc_id_payload_encode(id, SILC_ID_CLIENT);
+ nidp = silc_id_payload_encode(id2, SILC_ID_CLIENT);
+
+ /* Send the NICK_CHANGE notify type to local clients on the channels
+ this client is joined to. */
+ silc_server_send_notify_on_channels(server, client,
+ SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
+ oidp->data, oidp->len,
+ nidp->data, nidp->len);
+
+ silc_buffer_free(nidp);
+ silc_buffer_free(oidp);
+ }
+ break;
+ }
case SILC_ID_SERVER:
SILC_LOG_DEBUG(("Old Server ID id(%s)",
SilcBuffer reply;
SilcIDListData idata;
char *username = NULL, *realname = NULL, *id_string;
+ int ret;
SILC_LOG_DEBUG(("Creating new client"));
}
/* Parse incoming packet */
- silc_buffer_unformat(buffer,
- SILC_STR_UI16_STRING_ALLOC(&username),
- SILC_STR_UI16_STRING_ALLOC(&realname),
- SILC_STR_END);
+ ret = silc_buffer_unformat(buffer,
+ SILC_STR_UI16_STRING_ALLOC(&username),
+ SILC_STR_UI16_STRING_ALLOC(&realname),
+ SILC_STR_END);
+ if (ret == -1) {
+ if (username)
+ silc_free(username);
+ if (realname)
+ silc_free(realname);
+ return NULL;
+ }
/* Create Client ID */
silc_id_create_client_id(server->id, server->rng, server->md5hash,
SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
("Welcome to the SILC Network %s@%s",
username, sock->hostname));
+ SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+ ("Your host is %s, running version %s",
+ server->config->server_info->server_name,
+ server_version));
if (server->server_type == SILC_ROUTER) {
SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
("There are %d clients on %d servers in SILC "
"Network", server->stat.clients,
- server->stat.servers));
+ server->stat.servers + 1));
SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
("There are %d clients on %d server in our cell",
server->stat.cell_clients,
("%d operators online",
server->stat.my_server_ops));
}
- SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
- ("Your host is %s, running version %s",
- server->config->server_info->server_name,
- server_version));
SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
("Your connection is secured with %s cipher, "
"key length %d bits",
SilcIDListData idata;
unsigned char *server_name, *id_string;
unsigned short id_len;
+ int ret;
SILC_LOG_DEBUG(("Creating new server"));
}
/* Parse the incoming packet */
- silc_buffer_unformat(buffer,
- SILC_STR_UI16_NSTRING_ALLOC(&id_string, &id_len),
- SILC_STR_UI16_STRING_ALLOC(&server_name),
- SILC_STR_END);
+ ret = silc_buffer_unformat(buffer,
+ SILC_STR_UI16_NSTRING_ALLOC(&id_string, &id_len),
+ SILC_STR_UI16_STRING_ALLOC(&server_name),
+ SILC_STR_END);
+ if (ret == -1) {
+ if (id_string)
+ silc_free(id_string);
+ if (server_name)
+ silc_free(server_name);
+ return NULL;
+ }
if (id_len > buffer->len) {
silc_free(id_string);
}
/* Get Server ID */
- server_id = silc_id_str2id(id_string, SILC_ID_SERVER);
+ server_id = silc_id_str2id(id_string, id_len, SILC_ID_SERVER);
+ if (!server_id) {
+ silc_free(id_string);
+ silc_free(server_name);
+ return NULL;
+ }
silc_free(id_string);
/* Update client entry */
TRUE, new_server->id, SILC_ID_SERVER,
SILC_ID_SERVER_LEN);
+ if (server->server_type == SILC_ROUTER)
+ server->stat.cell_servers++;
+
return new_server;
}
{
SilcBuffer buffer = packet->buffer;
unsigned char *tmp1 = NULL, *tmp2 = NULL;
+ unsigned int tmp1_len, tmp2_len;
SilcClientID *client_id = NULL;
SilcChannelID *channel_id = NULL;
SilcChannelEntry channel;
SilcClientEntry client;
+ int ret;
SILC_LOG_DEBUG(("Removing user from channel"));
server->server_type == SILC_SERVER)
return;
- silc_buffer_unformat(buffer,
- SILC_STR_UI16_STRING_ALLOC(&tmp1),
- SILC_STR_UI16_STRING_ALLOC(&tmp2),
- SILC_STR_END);
-
- if (!tmp1 || !tmp2)
+ ret = silc_buffer_unformat(buffer,
+ SILC_STR_UI16_NSTRING_ALLOC(&tmp1, &tmp1_len),
+ SILC_STR_UI16_NSTRING_ALLOC(&tmp2, &tmp2_len),
+ SILC_STR_END);
+ if (ret == -1)
goto out;
- client_id = silc_id_str2id(tmp1, SILC_ID_CLIENT);
- channel_id = silc_id_str2id(tmp2, SILC_ID_CHANNEL);
+ client_id = silc_id_str2id(tmp1, tmp1_len, SILC_ID_CLIENT);
+ channel_id = silc_id_str2id(tmp2, tmp2_len, SILC_ID_CHANNEL);
if (!client_id || !channel_id)
goto out;
SilcChannelID *channel_id;
unsigned short channel_id_len;
char *channel_name;
+ int ret;
SILC_LOG_DEBUG(("Processing New Channel"));
return;
/* Parse payload */
- if (!silc_buffer_unformat(packet->buffer,
- SILC_STR_UI16_STRING_ALLOC(&channel_name),
- SILC_STR_UI16_NSTRING_ALLOC(&id, &channel_id_len),
- SILC_STR_END))
+ 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);
return;
+ }
- if (!channel_name || !id)
- return;
-
/* Decode the channel ID */
- channel_id = silc_id_str2id(id, SILC_ID_CHANNEL);
+ channel_id = silc_id_str2id(id, channel_id_len, SILC_ID_CHANNEL);
if (!channel_id)
return;
silc_free(id);
SilcNotifyType type;
SilcArgumentPayload args;
SilcChannelID *channel_id;
- SilcClientID *client_id;
+ SilcClientID *client_id, *client_id2;
SilcChannelEntry channel;
SilcClientEntry client;
unsigned char *tmp;
*/
SILC_LOG_DEBUG(("JOIN notify"));
- channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_type);
+ channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
+ packet->dst_id_type);
if (!channel_id)
goto out;
goto out;
}
client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ if (!client_id) {
+ silc_free(channel_id);
+ goto out;
+ }
/* Send to channel */
silc_server_packet_send_to_channel(server, NULL, channel, packet->type,
client = silc_idlist_find_client_by_id(server->global_list,
client_id, NULL);
- if (!client)
+ if (!client) {
client = silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
client_id, sock->user_data, sock);
+ if (!client) {
+ silc_free(channel_id);
+ silc_free(client_id);
+ goto out;
+ }
+ }
/* The channel is global now */
channel->global_users = TRUE;
*/
SILC_LOG_DEBUG(("LEAVE notify"));
- channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_type);
+ channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
+ packet->dst_id_type);
if (!channel_id)
goto out;
goto out;
}
client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ if (!client_id) {
+ silc_free(channel_id);
+ goto out;
+ }
/* Send to channel */
silc_server_packet_send_to_channel(server, NULL, channel, packet->type,
client = silc_idlist_find_client_by_id(server->local_list,
client_id, NULL);
if (!client) {
+ silc_free(client_id);
silc_free(channel_id);
goto out;
}
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,
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
client_id, NULL);
- if (!client)
+ if (!client) {
+ silc_free(client_id);
goto out;
+ }
}
silc_free(client_id);
silc_idlist_del_client(server->global_list, client);
break;
- /* Ignore rest notify types for now */
- case SILC_NOTIFY_TYPE_NONE:
- case SILC_NOTIFY_TYPE_INVITE:
+ case SILC_NOTIFY_TYPE_NICK_CHANGE:
+ {
+ /*
+ * Distribute the notify to local clients on the channel
+ */
+ unsigned char *id, *id2;
+
+ SILC_LOG_DEBUG(("NICK CHANGE notify"));
+
+ /* Get old client ID */
+ id = silc_argument_get_arg_type(args, 1, &tmp_len);
+ if (!id)
+ goto out;
+ client_id = silc_id_payload_parse_id(id, tmp_len);
+ if (!client_id)
+ goto out;
+
+ /* Get new client ID */
+ id2 = silc_argument_get_arg_type(args, 2, &tmp_len);
+ if (!id2)
+ goto out;
+ client_id2 = silc_id_payload_parse_id(id2, tmp_len);
+ if (!client_id2)
+ goto out;
+
+ SILC_LOG_DEBUG(("Old Client ID id(%s)",
+ silc_id_render(client_id, SILC_ID_CLIENT)));
+ SILC_LOG_DEBUG(("New Client ID id(%s)",
+ silc_id_render(client_id2, SILC_ID_CLIENT)));
+
+ /* Replace the Client ID */
+ client = silc_idlist_replace_client_id(server->global_list, client_id,
+ client_id2);
+ if (!client)
+ client = silc_idlist_replace_client_id(server->local_list, client_id,
+ client_id2);
+
+ if (client)
+ /* Send the NICK_CHANGE notify type to local clients on the channels
+ this client is joined to. */
+ silc_server_send_notify_on_channels(server, client,
+ SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
+ id, tmp_len,
+ id2, tmp_len);
+
+ silc_free(client_id);
+ if (!client)
+ silc_free(client_id2);
+ break;
+ }
case SILC_NOTIFY_TYPE_TOPIC_SET:
+ /*
+ * Distribute the notify to local clients on the channel
+ */
+ SILC_LOG_DEBUG(("TOPIC SET notify (not-impl XXX)"));
+ break;
+
case SILC_NOTIFY_TYPE_CMODE_CHANGE:
+ /*
+ * Distribute the notify to local clients on the channel
+ */
+ SILC_LOG_DEBUG(("CMODE CHANGE notify (not-impl XXX)"));
+ break;
+
case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
+ /*
+ * Distribute the notify to local clients on the channel
+ */
+ SILC_LOG_DEBUG(("CUMODE CHANGE notify (not-impl XXX)"));
+ break;
+
+ /* Ignore rest notify types for now */
+ case SILC_NOTIFY_TYPE_NONE:
+ case SILC_NOTIFY_TYPE_INVITE:
case SILC_NOTIFY_TYPE_MOTD:
default:
break;
SilcChannelEntry channel;
SilcChannelClientEntry chl;
SilcBuffer clidp;
+ int ret;
SILC_LOG_DEBUG(("Start"));
return;
/* Parse payload */
- if (!silc_buffer_unformat(packet->buffer,
- SILC_STR_UI16_NSTRING_ALLOC(&tmpid1,
- &channel_id_len),
- SILC_STR_UI16_NSTRING_ALLOC(&tmpid2,
- &client_id_len),
- SILC_STR_END))
- return;
-
- if (!tmpid1 || !tmpid2)
+ ret = silc_buffer_unformat(packet->buffer,
+ SILC_STR_UI16_NSTRING_ALLOC(&tmpid1,
+ &channel_id_len),
+ SILC_STR_UI16_NSTRING_ALLOC(&tmpid2,
+ &client_id_len),
+ SILC_STR_END);
+ if (ret == -1) {
+ if (tmpid1)
+ silc_free(tmpid1);
+ if (tmpid2)
+ silc_free(tmpid2);
return;
+ }
/* Decode the channel ID */
- channel_id = silc_id_str2id(tmpid1, SILC_ID_CHANNEL);
+ channel_id = silc_id_str2id(tmpid1, channel_id_len, SILC_ID_CHANNEL);
if (!channel_id)
goto out;
/* Decode the client ID */
- client_id = silc_id_str2id(tmpid2, SILC_ID_CLIENT);
+ client_id = silc_id_str2id(tmpid2, client_id_len, SILC_ID_CLIENT);
if (!client_id)
goto out;
out:
silc_id_payload_free(idp);
}
+
+/* Processes received SET_MODE packet. The packet is used to distribute
+ the information about changed channel's or client's channel modes. */
+
+void silc_server_set_mode(SilcServer server,
+ SilcSocketConnection sock,
+ SilcPacketContext *packet)
+{
+ SilcSetModePayload payload = NULL;
+ SilcArgumentPayload args = NULL;
+ unsigned short mode_type;
+ unsigned int mode_mask;
+ unsigned char *tmp, *tmp2;
+ unsigned int tmp_len, tmp_len2;
+ unsigned char mode[4];
+ SilcClientID *client_id;
+ SilcChannelID *channel_id = NULL;
+ SilcClientEntry client;
+ SilcChannelEntry channel;
+ SilcChannelClientEntry chl;
+
+ if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
+ packet->src_id_type == SILC_ID_CLIENT)
+ return;
+
+ SILC_LOG_DEBUG(("Start"));
+
+ /* If we are router and this packet is not already broadcast packet
+ we will broadcast it. The sending socket really cannot be router or
+ the router is buggy. If this packet is coming from router then it must
+ have the broadcast flag set already and we won't do anything. */
+ if (!server->standalone && server->server_type == SILC_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_SERVER &&
+ !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+ SILC_LOG_DEBUG(("Broadcasting received Set Mode packet"));
+ silc_server_packet_send(server, server->router->connection, packet->type,
+ packet->flags | SILC_PACKET_FLAG_BROADCAST,
+ packet->buffer->data, packet->buffer->len, FALSE);
+ }
+
+ /* Parse Set Mode payload */
+ payload = silc_set_mode_payload_parse(packet->buffer);
+ if (!payload)
+ return;
+
+ mode_type = silc_set_mode_get_type(payload);
+ args = silc_set_mode_get_args(payload);
+ if (!args)
+ goto out;
+
+ mode_mask = silc_set_mode_get_mode(payload);
+ SILC_PUT32_MSB(mode_mask, mode);
+
+ switch (mode_type) {
+ case SILC_MODE_TYPE_CHANNEL:
+ /* Get Channel ID */
+ tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+ if (!tmp)
+ goto out;
+ channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+ if (!channel_id)
+ goto out;
+
+ /* Get channel entry */
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
+ if (!channel) {
+ channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel_id, NULL);
+ if (!channel)
+ goto out;
+ }
+
+ /* Get Client ID payload */
+ tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+ if (!tmp)
+ goto out;
+
+ /* Send CMODE_CHANGE notify to local channel */
+ silc_server_send_notify_to_channel(server, sock, channel, FALSE,
+ SILC_NOTIFY_TYPE_CMODE_CHANGE,
+ 2, tmp, tmp_len,
+ mode, sizeof(mode));
+
+ /* Change the mode */
+ channel->mode = mode_mask;
+ break;
+
+ case SILC_MODE_TYPE_UCHANNEL:
+ /* Get Channel ID */
+ tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+ if (!tmp)
+ goto out;
+ channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+ if (!channel_id)
+ goto out;
+
+ /* Get channel entry */
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
+ if (!channel) {
+ channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel_id, NULL);
+ if (!channel)
+ goto out;
+ }
+
+ /* Get Client ID payload */
+ tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+ if (!tmp)
+ goto out;
+
+ /* Get target Client ID */
+ tmp2 = silc_argument_get_arg_type(args, 3, &tmp_len2);
+ if (!tmp2)
+ goto out;
+ client_id = silc_id_payload_parse_id(tmp2, tmp_len2);
+ if (!client_id)
+ goto out;
+
+ /* Get target 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);
+
+ /* Send CUMODE_CHANGE notify to local channel */
+ silc_server_send_notify_to_channel(server, sock, channel, FALSE,
+ SILC_NOTIFY_TYPE_CUMODE_CHANGE, 2,
+ tmp, tmp_len,
+ mode, sizeof(mode),
+ tmp2, tmp_len2);
+
+ /* Get entry to the channel user list */
+ silc_list_start(channel->user_list);
+ while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
+ if (chl->client == client) {
+ /* Change the mode */
+ chl->mode = mode_mask;
+ break;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ out:
+ if (channel_id)
+ silc_free(channel_id);
+ if (args)
+ silc_argument_payload_free(args);
+ if (payload)
+ silc_set_mode_payload_free(payload);
+}