+
+/* 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;
+
+ 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) {
+ 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);
+}