SILC_LOG_DEBUG(("Start"));
- if (!packet->dst_id) {
- SILC_LOG_ERROR(("Bad Client ID in private message packet, dropped"));
+ if (!packet->dst_id)
goto err;
- }
/* Decode destination Client ID */
id = silc_id_str2id(packet->dst_id, SILC_ID_CLIENT);
/* If the destination belongs to our server we don't have to route
the message anywhere but to send it to the local destination. */
- client = silc_idlist_find_client_by_id(server->local_list, id);
+ client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
if (client) {
/* It exists, now deliver the message to the destination */
dst_sock = (SilcSocketConnection)client->connection;
we will send the packet to that server. */
router = (SilcServerEntry)dst_sock->user_data;
idata = (SilcIDListData)router;
- // assert(client->router == server->id_entry);
+ //assert(client->router == server->id_entry);
silc_server_send_private_message(server, dst_sock,
idata->send_key,
/* We are router and we will perform route lookup for the destination
and send the message to fastest route. */
if (server->server_type == SILC_ROUTER && !server->standalone) {
- dst_sock = silc_server_get_route(server, id, SILC_ID_CLIENT);
- router = (SilcServerEntry)dst_sock->user_data;
- idata = (SilcIDListData)router;
+ /* Check first that the ID is valid */
+ client = silc_idlist_find_client_by_id(server->global_list, id, NULL);
+ if (client) {
+ dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT);
+ router = (SilcServerEntry)dst_sock->user_data;
+ idata = (SilcIDListData)router;
- /* Get fastest route and send packet. */
- if (router)
- silc_server_send_private_message(server, dst_sock,
- idata->send_key,
- idata->hmac, packet);
- return;
+ /* Get fastest route and send packet. */
+ if (router)
+ silc_server_send_private_message(server, dst_sock,
+ idata->send_key,
+ idata->hmac, packet);
+ return;
+ }
}
err:
"No such nickname: Private message not sent");
}
-/* Relays received command reply packet to the correct destination. The
- destination must be one of our locally connected client or the packet
- will be ignored. This is called when server has forwarded one of
- client's command request to router and router has now replied to the
- command. */
+/* Processes incoming command reply packet. The command reply packet may
+ be destined to one of our clients or it may directly for us. We will
+ call the command reply routine after processing the packet. */
-void silc_server_packet_relay_command_reply(SilcServer server,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
+void silc_server_command_reply(SilcServer server,
+ SilcSocketConnection sock,
+ SilcPacketContext *packet)
{
SilcBuffer buffer = packet->buffer;
- SilcClientEntry client;
- SilcClientID *id;
+ SilcClientEntry client = NULL;
SilcSocketConnection dst_sock;
SilcIDListData idata;
+ SilcClientID *id = NULL;
SILC_LOG_DEBUG(("Start"));
sock->type != SILC_SOCKET_TYPE_ROUTER)
return;
- /* Destination must be client */
- if (packet->dst_id_type != SILC_ID_CLIENT)
+ if (packet->dst_id_type == SILC_ID_CHANNEL)
return;
- /* Execute command reply locally for the command */
- silc_server_command_reply_process(server, sock, buffer);
-
- id = silc_id_str2id(packet->dst_id, SILC_ID_CLIENT);
-
- /* Destination must be one of ours */
- client = silc_idlist_find_client_by_id(server->local_list, id);
- if (!client) {
- SILC_LOG_ERROR(("Cannot relay command reply to unknown client"));
- silc_free(id);
- return;
+ if (packet->dst_id_type == SILC_ID_CLIENT) {
+ /* Destination must be one of ours */
+ id = silc_id_str2id(packet->dst_id, SILC_ID_CLIENT);
+ client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
+ if (!client) {
+ SILC_LOG_ERROR(("Cannot process command reply to unknown client"));
+ silc_free(id);
+ return;
+ }
}
- /* Relay the packet to the client */
-
- dst_sock = (SilcSocketConnection)client->connection;
- silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len
- + packet->dst_id_len + packet->padlen);
-
- silc_packet_send_prepare(dst_sock, 0, 0, buffer->len);
- silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len);
+ if (packet->dst_id_type == SILC_ID_SERVER) {
+ /* For now this must be for us */
+ if (SILC_ID_SERVER_COMPARE(packet->dst_id, server->id_string)) {
+ SILC_LOG_ERROR(("Cannot process command reply to unknown server"));
+ return;
+ }
+ }
- idata = (SilcIDListData)client;
+ /* Execute command reply locally for the command */
+ silc_server_command_reply_process(server, sock, buffer);
- /* Encrypt packet */
- silc_packet_encrypt(idata->send_key, idata->hmac, dst_sock->outbuf,
- buffer->len);
+ if (packet->dst_id_type == SILC_ID_CLIENT && client && id) {
+ /* Relay the packet to the client */
+
+ dst_sock = (SilcSocketConnection)client->connection;
+ silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len
+ + packet->dst_id_len + packet->padlen);
+
+ silc_packet_send_prepare(dst_sock, 0, 0, buffer->len);
+ silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len);
+
+ idata = (SilcIDListData)client;
+
+ /* Encrypt packet */
+ silc_packet_encrypt(idata->send_key, idata->hmac, dst_sock->outbuf,
+ buffer->len);
- /* Send the packet */
- silc_server_packet_send_real(server, dst_sock, TRUE);
+ /* Send the packet */
+ silc_server_packet_send_real(server, dst_sock, TRUE);
- silc_free(id);
+ silc_free(id);
+ }
}
/* Process received channel message. The message can be originated from
/* Sanity checks */
if (packet->dst_id_type != SILC_ID_CHANNEL) {
- SILC_LOG_ERROR(("Received bad message for channel, dropped"));
SILC_LOG_DEBUG(("Received bad message for channel, dropped"));
goto out;
}
/* Find channel entry */
id = silc_id_str2id(packet->dst_id, SILC_ID_CHANNEL);
- channel = silc_idlist_find_channel_by_id(server->local_list, id);
+ channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
if (!channel) {
- SILC_LOG_DEBUG(("Could not find channel"));
- goto out;
+ channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
+ if (!channel) {
+ SILC_LOG_DEBUG(("Could not find channel"));
+ goto out;
+ }
}
/* See that this client is on the channel. If the message is coming
/* Received channel key packet. We distribute the key to all of our locally
connected clients on the channel. */
-/* XXX Router must accept this packet and distribute the key to all its
- server that has clients on the channel */
void silc_server_channel_key(SilcServer server,
SilcSocketConnection sock,
SilcPacketContext *packet)
{
SilcBuffer buffer = packet->buffer;
- SilcChannelKeyPayload payload = NULL;
- SilcChannelID *id = NULL;
SilcChannelEntry channel;
- SilcChannelClientEntry chl;
- unsigned char *tmp;
- unsigned int tmp_len;
- char *cipher;
-
- if (packet->src_id_type != SILC_ID_SERVER &&
- sock->type != SILC_SOCKET_TYPE_ROUTER)
- goto out;
-
- /* Decode channel key payload */
- payload = silc_channel_key_payload_parse(buffer);
- if (!payload) {
- SILC_LOG_ERROR(("Bad channel key payload, dropped"));
- goto out;
- }
-
- /* Get channel ID */
- tmp = silc_channel_key_get_id(payload, &tmp_len);
- id = silc_id_payload_parse_id(tmp, tmp_len);
- if (!id)
- goto out;
- /* Get the channel entry */
- channel = silc_idlist_find_channel_by_id(server->local_list, id);
- if (!channel) {
- SILC_LOG_ERROR(("Received key for non-existent channel"));
- goto out;
- }
-
- /* Save the key for us as well */
- tmp = silc_channel_key_get_key(payload, &tmp_len);
- if (!tmp)
- goto out;
- cipher = silc_channel_key_get_cipher(payload, NULL);;
- if (!cipher)
- goto out;
- if (!silc_cipher_alloc(cipher, &channel->channel_key))
- goto out;
+ if (packet->src_id_type != SILC_ID_SERVER)
+ return;
- /* Distribute the key to all clients on the channel */
- silc_list_start(channel->user_list);
- while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
- silc_server_packet_send(server, chl->client->connection,
- SILC_PACKET_CHANNEL_KEY, 0,
- buffer->data, buffer->len, TRUE);
- }
+ /* Save the channel key */
+ channel = silc_server_save_channel_key(server, buffer, NULL);
+ if (!channel)
+ return;
- channel->key_len = tmp_len * 8;
- channel->key = silc_calloc(tmp_len, sizeof(unsigned char));
- memcpy(channel->key, tmp, tmp_len);
- channel->channel_key->cipher->set_key(channel->channel_key->context,
- tmp, tmp_len);
- out:
- if (id)
- silc_free(id);
- if (payload)
- silc_channel_key_payload_free(payload);
+ /* 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, channel, FALSE);
}
/* Received packet to replace a ID. This checks that the requested ID
/* 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;
case SILC_ID_SERVER:
+ SILC_LOG_DEBUG(("Old Server ID id(%s)",
+ silc_id_render(id, SILC_ID_CLIENT)));
+ SILC_LOG_DEBUG(("New Server ID id(%s)",
+ silc_id_render(id2, SILC_ID_CLIENT)));
if (silc_idlist_replace_server_id(server->local_list, id, id2) == NULL)
if (server->server_type == SILC_ROUTER)
silc_idlist_replace_server_id(server->global_list, id, id2);
}
/* Processes incoming New ID packet. New ID Payload is used to distribute
- information about newly registered clients, servers and created
- channels. */
+ information about newly registered clients and servers. */
void silc_server_new_id(SilcServer server, SilcSocketConnection sock,
SilcPacketContext *packet)
{
SilcBuffer buffer = packet->buffer;
SilcIDList id_list;
- SilcServerEntry tmpserver, router;
+ SilcServerEntry router;
SilcSocketConnection router_sock;
SilcIDPayload idp;
SilcIdType id_type;
- void *id, *tmpid;
+ unsigned char *hash = NULL;
+ void *id;
SILC_LOG_DEBUG(("Processing new ID"));
buffer->data, buffer->len, FALSE);
}
+#if 0
/* If the packet is originated from the one who sent it to us we know
that the ID belongs to our cell, unless the sender was router. */
tmpid = silc_id_str2id(packet->src_id, SILC_ID_SERVER);
}
silc_free(tmpid);
+#endif
+
+ if (sock->type == SILC_SOCKET_TYPE_SERVER)
+ id_list = server->local_list;
+ else
+ id_list = server->global_list;
+
+ router_sock = sock;
+ router = sock->user_data;
switch(id_type) {
case SILC_ID_CLIENT:
{
- SilcClientEntry idlist;
+ SilcClientEntry entry;
SILC_LOG_DEBUG(("New client id(%s) from [%s] %s",
silc_id_render(id, SILC_ID_CLIENT),
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. The client is put to global list and we will take the hash
+ value of the Client ID and save it to the ID Cache system for fast
+ searching in the future. */
+ hash = silc_calloc(sizeof(((SilcClientID *)id)->hash),
+ sizeof(unsigned char));
+ memcpy(hash, ((SilcClientID *)id)->hash,
+ sizeof(((SilcClientID *)id)->hash));
+ entry = silc_idlist_add_client(id_list, hash, NULL, NULL, id,
+ router, router_sock);
+ entry->nickname = NULL;
- /* Add the client to our local list. We are router and we keep
- cell specific local database of all clients in the cell. */
- idlist = silc_idlist_add_client(id_list, NULL, NULL, NULL,
- id, router, router_sock);
+#if 0
+ /* XXX Adding two ID's with same IP number replaces the old entry thus
+ gives wrong route. Thus, now disabled until figured out a better way
+ to do this or when removed the whole thing. This could be removed
+ because entry->router->connection gives always the most optimal route
+ for the ID anyway (unless new routes (faster perhaps) are established
+ after receiving this ID, this we don't know however). */
+ /* Add route cache for this ID */
+ silc_server_route_add(silc_server_route_hash(
+ ((SilcClientID *)id)->ip.s_addr,
+ server->id->port), ((SilcClientID *)id)->ip.s_addr,
+ router);
+#endif
}
break;
case SILC_ID_SERVER:
- {
- SilcServerEntry idlist;
-
- 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));
+ 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. */
+ silc_idlist_add_server(id_list, NULL, 0, id, router, router_sock);
- /* Add the server to our local list. We are router and we keep
- cell specific local database of all servers in the cell. */
- idlist = silc_idlist_add_server(id_list, NULL, 0, id, router,
- router_sock);
- }
+#if 0
+ /* Add route cache for this ID */
+ silc_server_route_add(silc_server_route_hash(
+ ((SilcServerID *)id)->ip.s_addr,
+ ((SilcServerID *)id)->port),
+ ((SilcServerID *)id)->ip.s_addr,
+ router);
+#endif
break;
case SILC_ID_CHANNEL:
SILC_LOG_ERROR(("Channel cannot be registered with NEW_ID packet"));
-#if 0
- SILC_LOG_DEBUG(("New channel id(%s) from [%s] %s",
- silc_id_render(id, SILC_ID_CHANNEL),
- sock->type == SILC_SOCKET_TYPE_SERVER ?
- "Server" : "Router", sock->hostname));
-
- /* Add the channel to our local list. We are router and we keep
- cell specific local database of all channels in the cell. */
- silc_idlist_add_channel(id_list, NULL, 0, id, router, NULL);
-#endif
break;
default:
/* Received Remove Channel User packet to remove a user from a channel.
Routers notify other routers that user has left a channel. Client must
- not send this packet.. Normal server may send this packet but must not
+ not send this packet. Normal server may send this packet but must not
receive it. */
void silc_server_remove_channel_user(SilcServer server,
buffer->data, buffer->len, FALSE);
}
- /* XXX routers should check server->global_list as well */
/* Get channel entry */
- channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
- if (!channel)
- goto out;
-
- /* XXX routers should check server->global_list as well */
+ 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 entry */
- client = silc_idlist_find_client_by_id(server->local_list, client_id);
- if (!client)
- goto out;
+ client = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
+ if (!client) {
+ client = silc_idlist_find_client_by_id(server->global_list,
+ client_id, NULL);
+ if (!client)
+ goto out;
+ }
- /* Remove from channel */
- silc_server_remove_from_one_channel(server, sock, channel, client, FALSE);
+ /* Remove user from channel */
+ silc_server_remove_from_one_channel(server, sock, channel, client, TRUE);
out:
if (tmp1)
SilcNotifyPayload payload;
SilcNotifyType type;
SilcArgumentPayload args;
- int i;
+ SilcChannelID *channel_id;
+ SilcClientID *client_id;
+ SilcChannelEntry channel;
+ SilcClientEntry client;
+ unsigned char *tmp;
+ unsigned int tmp_len;
+
+ SILC_LOG_DEBUG(("Start"));
if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
packet->src_id_type != SILC_ID_SERVER)
return;
- /* For now we expect that the we are normal server and that the
+ /* XXX: For now we expect that the we are normal server and that the
sender is router. Server could send (protocol allows it) notify to
- router but we don't support it yet. XXX! */
+ router but we don't support it yet. */
if (server->server_type != SILC_SERVER &&
sock->type != SILC_SOCKET_TYPE_ROUTER)
return;
switch(type) {
case SILC_NOTIFY_TYPE_JOIN:
+ /*
+ * Distribute the notify to local clients on the channel
+ */
+ SILC_LOG_DEBUG(("JOIN notify"));
+
+ channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_type);
+ if (!channel_id)
+ goto out;
+
+ /* Get channel entry */
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
+ if (!channel) {
+ silc_free(channel_id);
+ goto out;
+ }
+
+ /* Get client ID */
+ tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+ if (!tmp) {
+ silc_free(channel_id);
+ goto out;
+ }
+ client_id = silc_id_payload_parse_id(tmp, tmp_len);
+
+ /* 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_id, NULL);
+ if (!client) {
+ SilcChannelClientEntry chl;
+
+ client = silc_idlist_find_client_by_id(server->global_list,
+ client_id, NULL);
+ if (!client)
+ client = silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
+ client_id, sock->user_data, sock);
+
+ /* The channel is global now */
+ channel->global_users = TRUE;
+
+ /* Now actually JOIN the global client to the channel */
+ chl = silc_calloc(1, sizeof(*chl));
+ chl->client = client;
+ chl->channel = channel;
+ silc_list_add(channel->user_list, chl);
+ silc_list_add(client->channels, chl);
+ } else {
+ silc_free(client_id);
+ }
+
+ /* Send to channel */
+ silc_server_packet_send_to_channel(server, channel, packet->type, FALSE,
+ packet->buffer->data,
+ packet->buffer->len, FALSE);
break;
case SILC_NOTIFY_TYPE_LEAVE:
+ /*
+ * Distribute the notify to local clients on the channel
+ */
+ SILC_LOG_DEBUG(("LEAVE notify"));
+
+ channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_type);
+ if (!channel_id)
+ goto out;
+
+ /* Get channel entry */
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
+ if (!channel) {
+ silc_free(channel_id);
+ goto out;
+ }
+
+ /* Get client ID */
+ tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+ if (!tmp) {
+ silc_free(channel_id);
+ goto out;
+ }
+ client_id = silc_id_payload_parse_id(tmp, tmp_len);
+
+ /* Send to channel */
+ silc_server_packet_send_to_channel(server, 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);
+ if (!client) {
+ client = silc_idlist_find_client_by_id(server->local_list,
+ client_id, NULL);
+ if (!client) {
+ silc_free(channel_id);
+ goto out;
+ }
+ }
+ silc_free(client_id);
+
+ /* Remove the user from channel */
+ silc_server_remove_from_one_channel(server, sock, channel, client, FALSE);
break;
case SILC_NOTIFY_TYPE_SIGNOFF:
+ /*
+ * Distribute the notify to local clients on the channel
+ */
+ SILC_LOG_DEBUG(("SIGNOFF 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);
+
+ /* 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)
+ goto out;
+ }
+ silc_free(client_id);
+
+ /* Remove the client from all channels */
+ silc_server_remove_from_channels(server, NULL, client);
+
+ /* Remove the client entry */
+ silc_idlist_del_client(server->global_list, client);
break;
/* Ignore rest notify types for now */
SilcBuffer clidp;
void *tmpid;
+ SILC_LOG_DEBUG(("Start"));
+
if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
server->server_type != SILC_ROUTER ||
packet->src_id_type != SILC_ID_SERVER)
goto out;
/* Decode the client ID */
- client_id = silc_id_str2id(tmpid1, SILC_ID_CLIENT);
+ client_id = silc_id_str2id(tmpid2, SILC_ID_CLIENT);
if (!client_id)
goto out;
+#if 0
/* If the packet is originated from the one who sent it to us we know
that the ID belongs to our cell, unless the sender was router. */
tmpid = silc_id_str2id(packet->src_id, SILC_ID_SERVER);
router = server->router;
}
silc_free(tmpid);
+#endif
+
+ router_sock = sock;
+ router = sock->user_data;
/* Find the channel */
- channel = silc_idlist_find_channel_by_id(id_list, channel_id);
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
if (!channel) {
- SILC_LOG_ERROR(("Received channel user for non-existent channel"));
- goto out;
+ channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel_id, NULL);
+ if (!channel)
+ goto out;
}
/* If we are router and this packet is not already broadcast packet
}
/* Get client entry */
- client = silc_idlist_find_client_by_id(id_list, client_id);
+ client = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
if (!client) {
- /* This is new client to us, add entry to ID list */
- client = silc_idlist_add_client(id_list, NULL, NULL, NULL,
- client_id, router, router_sock);
+ client = silc_idlist_find_client_by_id(server->global_list,
+ client_id, NULL);
if (!client)
goto out;
}
it is assured that this is sent only to our local clients and locally
connected servers if needed. */
clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
- silc_server_send_notify_to_channel(server, channel, TRUE,
+ silc_server_send_notify_to_channel(server, channel, FALSE,
SILC_NOTIFY_TYPE_JOIN,
1, clidp->data, clidp->len);
silc_buffer_free(clidp);
silc_free(tmpid1);
silc_free(tmpid2);
}
+
+/* Processes incoming REMOVE_ID packet. The packet is used to notify routers
+ that certain ID should be removed. After that the ID will become invalid. */
+
+void silc_server_remove_id(SilcServer server,
+ SilcSocketConnection sock,
+ SilcPacketContext *packet)
+{
+ SilcIDList id_list;
+ SilcIDPayload idp;
+ SilcIdType id_type;
+ void *id, *id_entry;
+
+ SILC_LOG_DEBUG(("Start"));
+
+ if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
+ server->server_type == SILC_SERVER ||
+ packet->src_id_type != SILC_ID_SERVER)
+ return;
+
+ idp = silc_id_payload_parse(packet->buffer);
+ if (!idp)
+ return;
+
+ id_type = silc_id_payload_get_type(idp);
+
+ id = silc_id_payload_get_id(idp);
+ 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 (!server->standalone && server->server_type == SILC_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_SERVER &&
+ !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+ SILC_LOG_DEBUG(("Broadcasting received Remove ID 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 (sock->type == SILC_SOCKET_TYPE_SERVER)
+ id_list = server->local_list;
+ else
+ id_list = server->global_list;
+
+ /* Remove the ID */
+ switch (id_type) {
+ case SILC_ID_CLIENT:
+ id_entry = silc_idlist_find_client_by_id(id_list, (SilcClientID *)id,
+ NULL);
+ if (id_entry) {
+ /* Remove from channels */
+ silc_server_remove_from_channels(server, NULL, id_entry);
+
+ /* Remove the client entry */
+ silc_idlist_del_client(id_list, (SilcClientEntry)id_entry);
+
+ SILC_LOG_DEBUG(("Removed client id(%s) from [%s] %s",
+ silc_id_render(id, SILC_ID_CLIENT),
+ sock->type == SILC_SOCKET_TYPE_SERVER ?
+ "Server" : "Router", sock->hostname));
+ }
+ break;
+
+ case SILC_ID_SERVER:
+ id_entry = silc_idlist_find_server_by_id(id_list, (SilcServerID *)id,
+ NULL);
+ if (id_entry) {
+ silc_idlist_del_server(id_list, (SilcServerEntry)id_entry);
+
+ SILC_LOG_DEBUG(("Removed server id(%s) from [%s] %s",
+ silc_id_render(id, SILC_ID_SERVER),
+ sock->type == SILC_SOCKET_TYPE_SERVER ?
+ "Server" : "Router", sock->hostname));
+ }
+ break;
+
+ case SILC_ID_CHANNEL:
+ id_entry = silc_idlist_find_channel_by_id(id_list, (SilcChannelID *)id,
+ NULL);
+ if (id_entry) {
+ silc_idlist_del_channel(id_list, (SilcChannelEntry)id_entry);
+
+ SILC_LOG_DEBUG(("Removed channel id(%s) from [%s] %s",
+ silc_id_render(id, SILC_ID_CHANNEL),
+ sock->type == SILC_SOCKET_TYPE_SERVER ?
+ "Server" : "Router", sock->hostname));
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ out:
+ silc_id_payload_free(idp);
+}