SilcNotifyPayload payload;
SilcNotifyType type;
SilcArgumentPayload args;
- SilcChannelID *channel_id, *channel_id2;
+ SilcChannelID *channel_id = NULL, *channel_id2;
SilcClientID *client_id, *client_id2;
SilcServerID *server_id;
SilcChannelEntry channel;
idata->hmac_receive, packet, TRUE);
}
+ /* Parse the Notify Payload */
+ payload = silc_notify_payload_parse(packet->buffer);
+ if (!payload)
+ return;
+
/* 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
sock->type == SILC_SOCKET_TYPE_SERVER &&
!(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
SILC_LOG_DEBUG(("Broadcasting received Notify packet"));
- silc_server_packet_send(server, server->router->connection, packet->type,
- packet->flags | SILC_PACKET_FLAG_BROADCAST,
- packet->buffer->data, packet->buffer->len, FALSE);
- }
+ if (packet->dst_id_type == SILC_ID_CHANNEL) {
+ /* Packet is destined to channel */
+ channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
+ packet->dst_id_type);
+ if (!channel_id)
+ goto out;
- payload = silc_notify_payload_parse(packet->buffer);
- if (!payload)
- return;
+ silc_server_packet_send_dest(server, server->router->connection,
+ packet->type,
+ packet->flags | SILC_PACKET_FLAG_BROADCAST,
+ channel_id, SILC_ID_CHANNEL,
+ packet->buffer->data, packet->buffer->len,
+ FALSE);
+ silc_server_backup_send_dest(server, (SilcServerEntry)sock->user_data,
+ packet->type, packet->flags,
+ channel_id, SILC_ID_CHANNEL,
+ packet->buffer->data, packet->buffer->len,
+ FALSE, TRUE);
+ } else {
+ /* Packet is destined to client or server */
+ silc_server_packet_send(server, server->router->connection,
+ packet->type,
+ packet->flags | SILC_PACKET_FLAG_BROADCAST,
+ packet->buffer->data, packet->buffer->len,
+ FALSE);
+ silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
+ packet->type, packet->flags,
+ packet->buffer->data, packet->buffer->len,
+ FALSE, TRUE);
+ }
+ }
type = silc_notify_get_type(payload);
args = silc_notify_get_args(payload);
if (!client_id)
goto out;
- /* Send to channel */
- silc_server_packet_send_to_channel(server, sock, channel, packet->type,
- FALSE, packet->buffer->data,
- packet->buffer->len, FALSE);
-
/* 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->global_list,
- client_id, NULL);
+ client_id, server->server_type,
+ NULL);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, NULL);
+ client_id, server->server_type,
+ NULL);
if (!client) {
/* If router did not find the client the it is bogus */
- if (server->server_type == SILC_ROUTER)
+ if (server->server_type != SILC_SERVER)
goto out;
client =
silc_id_dup(client_id, SILC_ID_CLIENT),
sock->user_data, NULL);
if (!client) {
+ SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
silc_free(client_id);
goto out;
}
- client->data.registered = TRUE;
+ client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
}
}
/* Do not process the notify if the client is not registered */
- if (client->data.registered == FALSE)
+ if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED))
break;
/* Do not add client to channel if it is there already */
if (silc_server_client_on_channel(client, channel))
break;
- if (server->server_type == SILC_SERVER &&
+ /* Send to channel */
+ silc_server_packet_send_to_channel(server, sock, channel, packet->type,
+ FALSE, packet->buffer->data,
+ packet->buffer->len, FALSE);
+
+ if (server->server_type != SILC_ROUTER &&
sock->type == SILC_SOCKET_TYPE_ROUTER)
/* The channel is global now */
channel->global_users = TRUE;
chl = silc_calloc(1, sizeof(*chl));
chl->client = client;
chl->channel = channel;
+
+ /* If this is the first one on the channel then it is the founder of
+ the channel. */
+ if (!silc_hash_table_count(channel->user_list))
+ chl->mode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
+
silc_hash_table_add(channel->user_list, client, chl);
silc_hash_table_add(client->channels, channel, chl);
silc_free(client_id);
*/
SILC_LOG_DEBUG(("LEAVE notify"));
- channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
- packet->dst_id_type);
- if (!channel_id)
- goto out;
+ if (!channel_id) {
+ channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
+ packet->dst_id_type);
+ if (!channel_id)
+ goto out;
+ }
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->global_list,
goto out;
}
- /* Send to channel */
- silc_server_packet_send_to_channel(server, sock, channel, packet->type,
- FALSE, packet->buffer->data,
- packet->buffer->len, FALSE);
-
/* Get client entry */
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, NULL);
+ client_id, TRUE, NULL);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, NULL);
+ client_id, TRUE, NULL);
if (!client) {
silc_free(client_id);
silc_free(channel_id);
}
silc_free(client_id);
+ /* Check if on channel */
+ if (!silc_server_client_on_channel(client, channel))
+ break;
+
+ /* Send the leave notify to channel */
+ silc_server_packet_send_to_channel(server, sock, channel, packet->type,
+ FALSE, packet->buffer->data,
+ packet->buffer->len, FALSE);
+
/* Remove the user from channel */
silc_server_remove_from_one_channel(server, sock, channel, client, FALSE);
break;
/* Get client entry */
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, &cache);
+ client_id, TRUE, &cache);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, &cache);
+ client_id, TRUE, &cache);
if (!client) {
silc_free(client_id);
goto out;
/* Remove the client from all channels. */
silc_server_remove_from_channels(server, NULL, client, TRUE, tmp, FALSE);
- client->data.registered = FALSE;
+ client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
server->stat.clients--;
if (server->server_type == SILC_ROUTER)
SILC_LOG_DEBUG(("TOPIC SET notify"));
- channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
- packet->dst_id_type);
- if (!channel_id)
- goto out;
+ if (!channel_id) {
+ channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
+ packet->dst_id_type);
+ if (!channel_id)
+ goto out;
+ }
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->global_list,
SILC_LOG_DEBUG(("CMODE CHANGE notify"));
- channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
- packet->dst_id_type);
- if (!channel_id)
- goto out;
+ if (!channel_id) {
+ channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
+ packet->dst_id_type);
+ if (!channel_id)
+ goto out;
+ }
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->global_list,
}
}
- /* Send the same notify to the channel */
- silc_server_packet_send_to_channel(server, sock, channel, packet->type,
- FALSE, packet->buffer->data,
- packet->buffer->len, FALSE);
-
/* Get the mode */
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
if (!tmp) {
SILC_GET32_MSB(mode, tmp);
+ /* Check if mode changed */
+ if (channel->mode == mode)
+ break;
+
+ /* Send the same notify to the channel */
+ silc_server_packet_send_to_channel(server, sock, channel, packet->type,
+ FALSE, packet->buffer->data,
+ packet->buffer->len, FALSE);
+
/* If the channel had private keys set and the mode was removed then
we must re-generate and re-distribute a new channel key */
if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY &&
!(mode & SILC_CHANNEL_MODE_PRIVKEY)) {
/* Re-generate channel key */
- silc_server_create_channel_key(server, channel, 0);
+ if (!silc_server_create_channel_key(server, channel, 0))
+ goto out;
/* Send the channel key. This sends it to our local clients and if
we are normal server to our router as well. */
SILC_LOG_DEBUG(("CUMODE CHANGE notify"));
- channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
- packet->dst_id_type);
- if (!channel_id)
- goto out;
+ if (!channel_id) {
+ channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
+ packet->dst_id_type);
+ if (!channel_id)
+ goto out;
+ }
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->global_list,
/* Get client entry */
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, NULL);
+ client_id, TRUE, NULL);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, NULL);
+ client_id, TRUE, NULL);
if (!client) {
silc_free(client_id);
goto out;
SilcBuffer idp;
unsigned char cumode[4];
+ if (chl->client == client && chl->mode == mode) {
+ notify_sent = TRUE;
+ break;
+ }
+
mode &= ~SILC_CHANNEL_UMODE_CHANFO;
silc_server_send_notify_cumode(server, sock, FALSE, channel, mode,
client->id, SILC_ID_CLIENT,
}
if (chl->client == client) {
+ if (chl->mode == mode) {
+ notify_sent = TRUE;
+ break;
+ }
+
/* Change the mode */
chl->mode = mode;
if (!(mode & SILC_CHANNEL_UMODE_CHANFO))
/* Get server entry */
server_entry = silc_idlist_find_server_by_id(server->global_list,
- server_id, NULL);
+ server_id, TRUE, NULL);
if (!server_entry) {
server_entry = silc_idlist_find_server_by_id(server->local_list,
- server_id, NULL);
+ server_id, TRUE, NULL);
if (!server_entry) {
silc_free(server_id);
goto out;
SILC_LOG_DEBUG(("KICKED notify"));
- channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
- packet->dst_id_type);
- if (!channel_id)
- goto out;
+ if (!channel_id) {
+ channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
+ packet->dst_id_type);
+ if (!channel_id)
+ goto out;
+ }
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->global_list,
if (!client_id)
goto out;
- /* Send to channel */
- silc_server_packet_send_to_channel(server, sock, channel, packet->type,
- FALSE, packet->buffer->data,
- 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->global_list,
- client_id, NULL);
+ client_id, TRUE, NULL);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, NULL);
+ client_id, TRUE, NULL);
if (!client) {
silc_free(client_id);
goto out;
}
}
+ /* Send to channel */
+ silc_server_packet_send_to_channel(server, sock, channel, packet->type,
+ FALSE, packet->buffer->data,
+ packet->buffer->len, FALSE);
+
/* Remove the client from channel */
silc_server_remove_from_one_channel(server, sock, channel, client, FALSE);
/* If the the client is not in local list we check global list */
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, NULL);
+ client_id, TRUE, NULL);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, NULL);
+ client_id, TRUE, NULL);
if (!client) {
silc_free(client_id);
goto out;
/* If the client is one of ours, then close the connection to the
client now. This removes the client from all channels as well. */
- if (packet->dst_id_type == SILC_ID_CLIENT && client->data.registered &&
- client->connection) {
+ if (packet->dst_id_type == SILC_ID_CLIENT && client->connection) {
sock = client->connection;
silc_server_free_client_data(server, NULL, client, FALSE, NULL);
silc_server_close_connection(server, sock);
/* Get client entry */
client = silc_idlist_find_client_by_id(server->global_list,
- client_id, NULL);
+ client_id, TRUE, NULL);
if (!client) {
client = silc_idlist_find_client_by_id(server->local_list,
- client_id, NULL);
+ client_id, TRUE, NULL);
if (!client) {
silc_free(client_id);
goto out;
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);
+ client = silc_idlist_find_client_by_id(server->local_list, id, TRUE, NULL);
if (!client) {
SILC_LOG_ERROR(("Cannot process command reply to unknown client"));
silc_free(id);
goto out;
if (packet->src_id_type == SILC_ID_CLIENT) {
sender_entry = silc_idlist_find_client_by_id(server->local_list,
- sender, NULL);
+ sender, TRUE, NULL);
if (!sender_entry)
sender_entry = silc_idlist_find_client_by_id(server->global_list,
- sender, NULL);
+ sender, TRUE, NULL);
if (!sender_entry || !silc_server_client_on_channel(sender_entry,
channel)) {
SILC_LOG_DEBUG(("Client not on channel"));
/* Distribute the key to everybody who is on the channel. If we are router
we will also send it to locally connected servers. */
silc_server_send_channel_key(server, sock, channel, FALSE);
+
+ if (server->server_type != SILC_BACKUP_ROUTER) {
+ /* Distribute to local cell backup routers. */
+ silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
+ SILC_PACKET_CHANNEL_KEY, 0,
+ buffer->data, buffer->len, FALSE, TRUE);
+ }
}
/* Received New Client packet and processes it. Creates Client ID for the
uint32 id_len;
int ret;
char *hostname, *nickname;
+ int nickfail = 0;
SILC_LOG_DEBUG(("Creating new client"));
}
/* Create Client ID */
- silc_id_create_client_id(server->id, server->rng, server->md5hash,
- username, &client_id);
+ while (!silc_id_create_client_id(server, server->id, server->rng,
+ server->md5hash, nickname, &client_id)) {
+ nickfail++;
+ snprintf(&nickname[strlen(nickname) - 1], 1, "%d", nickfail);
+ }
/* Update client entry */
- idata->registered = TRUE;
+ idata->status |= SILC_IDLIST_STATUS_REGISTERED;
client->nickname = nickname;
client->username = username;
client->userinfo = realname ? realname : strdup(" ");
silc_free(id_string);
/* Update server entry */
- idata->registered = TRUE;
+ idata->status |= SILC_IDLIST_STATUS_REGISTERED;
new_server->server_name = server_name;
new_server->id = server_id;
/* Add again the entry to the ID cache. */
silc_idcache_add(server->local_list->servers, server_name, server_id,
- server, FALSE);
+ new_server, FALSE);
/* Distribute the information about new server in the SILC network
to our router. If we are normal server we won't send anything
if (server->server_type == SILC_ROUTER)
server->stat.cell_servers++;
+ /* Check whether this router connection has been replaced by an
+ backup router. If it has been then we'll disable the server and will
+ ignore everything it will send until the backup router resuming
+ protocol has been completed. */
+ if (sock->type == SILC_SOCKET_TYPE_ROUTER &&
+ silc_server_backup_replaced_get(server, server_id, NULL)) {
+ /* Send packet to the server indicating that it cannot use this
+ connection as it has been replaced by backup router. */
+ SilcBuffer packet = silc_buffer_alloc(2);
+ silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
+ silc_buffer_format(packet,
+ SILC_STR_UI_CHAR(20),
+ SILC_STR_UI_CHAR(0),
+ SILC_STR_END);
+ silc_server_packet_send(server, sock,
+ SILC_PACKET_RESUME_ROUTER, 0,
+ packet->data, packet->len, TRUE);
+ silc_buffer_free(packet);
+
+ /* Mark the server disabled. The data sent earlier will go but nothing
+ after this does not go to this connection. */
+ idata->status |= SILC_IDLIST_STATUS_DISABLED;
+ }
+
return new_server;
}
if (!id)
goto out;
- /* If the sender of this packet is server and we are router we need to
- broadcast this packet to other routers in the network. */
- if (broadcast && !server->standalone && server->server_type == SILC_ROUTER &&
- sock->type == SILC_SOCKET_TYPE_SERVER &&
- !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
- SILC_LOG_DEBUG(("Broadcasting received New ID packet"));
- silc_server_packet_send(server, server->router->connection,
- packet->type,
- packet->flags | SILC_PACKET_FLAG_BROADCAST,
- buffer->data, buffer->len, FALSE);
- }
-
if (sock->type == SILC_SOCKET_TYPE_SERVER)
id_list = server->local_list;
else
void *sender_id = silc_id_str2id(packet->src_id, packet->src_id_len,
packet->src_id_type);
router = silc_idlist_find_server_by_id(server->global_list,
- sender_id, NULL);
+ sender_id, TRUE, NULL);
if (!router)
router = silc_idlist_find_server_by_id(server->local_list,
- sender_id, NULL);
+ sender_id, TRUE, NULL);
silc_free(sender_id);
if (!router)
goto out;
{
SilcClientEntry entry;
+ /* Check that we do not have this client already */
+ entry = silc_idlist_find_client_by_id(server->global_list,
+ id, server->server_type,
+ NULL);
+ if (!entry)
+ entry = silc_idlist_find_client_by_id(server->local_list,
+ id, server->server_type,
+ NULL);
+ if (entry) {
+ SILC_LOG_DEBUG(("Ignoring client that we already have"));
+ goto out;
+ }
+
SILC_LOG_DEBUG(("New client id(%s) from [%s] %s",
silc_id_render(id, SILC_ID_CLIENT),
sock->type == SILC_SOCKET_TYPE_SERVER ?
list. */
entry = silc_idlist_add_client(id_list, NULL, NULL, NULL,
id, router, NULL);
+ if (!entry) {
+ SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
+
+ /* Inform the sender that the ID is not usable */
+ silc_server_send_notify_signoff(server, sock, FALSE, id, NULL);
+ goto out;
+ }
entry->nickname = NULL;
- entry->data.registered = TRUE;
+ entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
if (sock->type == SILC_SOCKET_TYPE_SERVER)
server->stat.cell_clients++;
break;
case SILC_ID_SERVER:
- /* If the ID is mine, ignore it. */
- if (SILC_ID_SERVER_COMPARE(id, server->id)) {
- SILC_LOG_DEBUG(("Ignoring my own ID as new ID"));
- break;
- }
+ {
+ SilcServerEntry entry;
- SILC_LOG_DEBUG(("New server id(%s) from [%s] %s",
- silc_id_render(id, SILC_ID_SERVER),
- sock->type == SILC_SOCKET_TYPE_SERVER ?
- "Server" : "Router", sock->hostname));
+ /* If the ID is mine, ignore it. */
+ if (SILC_ID_SERVER_COMPARE(id, server->id)) {
+ SILC_LOG_DEBUG(("Ignoring my own ID as new ID"));
+ break;
+ }
- /* As a router we keep information of all global information in our global
- list. Cell wide information however is kept in the local list. */
- silc_idlist_add_server(id_list, NULL, 0, id, router, router_sock);
+ /* If the ID is the sender's ID, ignore it (we have it already) */
+ if (SILC_ID_SERVER_COMPARE(id, router->id)) {
+ SILC_LOG_DEBUG(("Ignoring sender's own ID"));
+ break;
+ }
+
+ /* Check that we do not have this server already */
+ entry = silc_idlist_find_server_by_id(server->global_list,
+ id, server->server_type,
+ NULL);
+ if (!entry)
+ entry = silc_idlist_find_server_by_id(server->local_list,
+ id, server->server_type,
+ NULL);
+ if (entry) {
+ SILC_LOG_DEBUG(("Ignoring server that we already have"));
+ goto out;
+ }
- if (sock->type == SILC_SOCKET_TYPE_SERVER)
- server->stat.cell_servers++;
- server->stat.servers++;
+ SILC_LOG_DEBUG(("New server id(%s) from [%s] %s",
+ silc_id_render(id, SILC_ID_SERVER),
+ sock->type == SILC_SOCKET_TYPE_SERVER ?
+ "Server" : "Router", sock->hostname));
+
+ /* As a router we keep information of all global information in our
+ global list. Cell wide information however is kept in the local
+ list. */
+ entry = silc_idlist_add_server(id_list, NULL, 0, id, router,
+ router_sock);
+ if (!entry) {
+ SILC_LOG_ERROR(("Could not add new server to the ID Cache"));
+ goto out;
+ }
+ entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
+
+ if (sock->type == SILC_SOCKET_TYPE_SERVER)
+ server->stat.cell_servers++;
+ server->stat.servers++;
+ }
break;
case SILC_ID_CHANNEL:
SILC_LOG_ERROR(("Channel cannot be registered with NEW_ID packet"));
+ goto out;
break;
default:
+ goto out;
break;
}
+ /* If the sender of this packet is server and we are router we need to
+ broadcast this packet to other routers in the network. */
+ if (broadcast && !server->standalone && server->server_type == SILC_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_SERVER &&
+ !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+ SILC_LOG_DEBUG(("Broadcasting received New ID packet"));
+ silc_server_packet_send(server, server->router->connection,
+ packet->type,
+ packet->flags | SILC_PACKET_FLAG_BROADCAST,
+ buffer->data, buffer->len, FALSE);
+ silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
+ packet->type, packet->flags,
+ packet->buffer->data, packet->buffer->len,
+ FALSE, TRUE);
+ }
+
out:
silc_id_payload_free(idp);
}
packet->type,
packet->flags | SILC_PACKET_FLAG_BROADCAST,
packet->buffer->data, packet->buffer->len, FALSE);
+ silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
+ packet->type, packet->flags,
+ packet->buffer->data, packet->buffer->len,
+ FALSE, TRUE);
}
/* Make copy of the original packet context, except for the actual
unsigned char *id;
uint32 id_len;
uint32 mode;
+ SilcChannelEntry channel;
SILC_LOG_DEBUG(("Processing New Channel"));
/* Add the channel to global list as it is coming from router. It
cannot be our own channel as it is coming from router. */
- SILC_LOG_DEBUG(("New channel id(%s) from [Router] %s",
- silc_id_render(channel_id, SILC_ID_CHANNEL),
- sock->hostname));
+ /* Check that we don't already have this channel */
+ channel = silc_idlist_find_channel_by_name(server->local_list,
+ channel_name, NULL);
+ if (!channel)
+ channel = silc_idlist_find_channel_by_name(server->global_list,
+ channel_name, NULL);
+ if (!channel) {
+ SILC_LOG_DEBUG(("New channel id(%s) from [Router] %s",
+ silc_id_render(channel_id, SILC_ID_CHANNEL),
+ sock->hostname));
- silc_idlist_add_channel(server->global_list, strdup(channel_name),
- 0, channel_id, sock->user_data, NULL, NULL);
-
- server->stat.channels++;
+ silc_idlist_add_channel(server->global_list, strdup(channel_name),
+ 0, channel_id, sock->user_data, NULL, NULL);
+ server->stat.channels++;
+ }
} else {
/* The channel is coming from our server, thus it is in our cell
we will add it to our local list. */
- SilcChannelEntry channel;
SilcBuffer chk;
- SILC_LOG_DEBUG(("New channel id(%s) from [Server] %s",
+ SILC_LOG_DEBUG(("Channel id(%s) from [Server] %s",
silc_id_render(channel_id, SILC_ID_CHANNEL),
sock->hostname));
-
+
/* Check that we don't already have this channel */
channel = silc_idlist_find_channel_by_name(server->local_list,
channel_name, NULL);
channel = silc_idlist_find_channel_by_name(server->global_list,
channel_name, NULL);
- /* If the channel does not exist, then create it. We create the channel
- with the channel ID provided by the server. This creates a new
+ /* If the channel does not exist, then create it. This creates a new
key to the channel as well that we will send to the server. */
if (!channel) {
+ /* The protocol says that the Channel ID's IP address must be based
+ on the router's IP address. Check whether the ID is based in our
+ IP and if it is not then create a new ID and enforce the server
+ to switch the ID. */
+ if (!SILC_ID_COMPARE(channel_id, server->id, server->id->ip.data_len)) {
+ SilcChannelID *tmp;
+ SILC_LOG_DEBUG(("Forcing the server to change Channel ID"));
+
+ if (silc_id_create_channel_id(server, server->id, server->rng, &tmp)) {
+ silc_server_send_notify_channel_change(server, sock, FALSE,
+ channel_id, tmp);
+ silc_free(channel_id);
+ channel_id = tmp;
+ }
+ }
+
+ /* Create the channel with the provided Channel ID */
channel = silc_server_create_new_channel_with_id(server, NULL, NULL,
channel_name,
channel_id, FALSE);
SilcBuffer users = NULL, users_modes = NULL;
if (!channel->id)
- channel_id = silc_id_dup(channel_id, SILC_ID_CHANNEL);
+ channel->id = silc_id_dup(channel_id, SILC_ID_CHANNEL);
if (!SILC_ID_CHANNEL_COMPARE(channel_id, channel->id)) {
/* They don't match, send CHANNEL_CHANGE notify to the server to
everybody else possibly on the channel. */
if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
- silc_server_create_channel_key(server, channel, 0);
+ if (!silc_server_create_channel_key(server, channel, 0))
+ return;
/* Send to the channel */
silc_server_send_channel_key(server, sock, channel, FALSE);
packet->type,
packet->flags | SILC_PACKET_FLAG_BROADCAST,
packet->buffer->data, packet->buffer->len, FALSE);
+ silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
+ packet->type, packet->flags,
+ packet->buffer->data, packet->buffer->len,
+ FALSE, TRUE);
}
/* Make copy of the original packet context, except for the actual
actually be received at anytime but usually it is used only during
the connection authentication phase. Now, protocol says that this packet
can come from client or server, however, we support only this coming
- from client and expect that server's always knows what authentication
+ from client and expect that server always knows what authentication
method to use. */
void silc_server_connection_auth_request(SilcServer server,
{
SilcServerConfigSectionClientConnection *client = NULL;
uint16 conn_type;
- int ret;
+ int ret, port;
SilcAuthMethod auth_meth;
SILC_LOG_DEBUG(("Start"));
/* Get the authentication method for the client */
auth_meth = SILC_AUTH_NONE;
+ port = server->sockets[server->sock]->port; /* Listenning port */
client = silc_server_config_find_client_conn(server->config,
sock->ip,
- sock->port);
+ port);
if (!client)
client = silc_server_config_find_client_conn(server->config,
sock->hostname,
- sock->port);
+ port);
if (client)
auth_meth = client->auth_meth;