if (dst_sock)
/* Relay the packet */
silc_server_relay_packet(server, dst_sock, idata->send_key,
- idata->hmac_receive, packet, TRUE);
+ idata->hmac_receive, idata->psn_send++,
+ packet, TRUE);
}
/* Parse the Notify Payload */
- payload = silc_notify_payload_parse(packet->buffer);
+ payload = silc_notify_payload_parse(packet->buffer->data,
+ packet->buffer->len);
if (!payload)
return;
break;
/* Do not add client to channel if it is there already */
- if (silc_server_client_on_channel(client, channel))
+ if (silc_server_client_on_channel(client, channel)) {
+ SILC_LOG_DEBUG(("Client already on channel"));
break;
+ }
/* Send to channel */
silc_server_packet_send_to_channel(server, sock, channel, packet->type,
/* Set the HMAC key out of current channel key. The client must do
this locally. */
- silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
+ silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
+ channel->key_len / 8,
hash);
silc_hmac_set_key(channel->hmac, hash,
- silc_hash_len(channel->hmac->hash));
+ silc_hash_len(silc_hmac_get_hash(channel->hmac)));
memset(hash, 0, sizeof(hash));
}
server_entry = silc_idlist_find_server_by_id(server->local_list,
server_id, TRUE, NULL);
if (!server_entry) {
+ /* If we are normal server then we might not have the server. Check
+ whether router was kind enough to send the list of all clients
+ that actually was to be removed. Remove them if the list is
+ available. */
+ if (server->server_type != SILC_ROUTER &&
+ silc_argument_get_arg_num(args) > 1) {
+ int i;
+
+ for (i = 1; i < silc_argument_get_arg_num(args); i++) {
+ /* Get Client ID */
+ tmp = silc_argument_get_arg_type(args, i + 1, &tmp_len);
+ if (!tmp)
+ continue;
+ client_id = silc_id_payload_parse_id(tmp, tmp_len);
+ if (!client_id)
+ continue;
+
+ /* Get client entry */
+ client = silc_idlist_find_client_by_id(server->global_list,
+ client_id, TRUE, &cache);
+ if (!client) {
+ client = silc_idlist_find_client_by_id(server->local_list,
+ client_id, TRUE, &cache);
+ if (!client) {
+ silc_free(client_id);
+ continue;
+ }
+ }
+ silc_free(client_id);
+
+ /* Remove the client from all channels. */
+ silc_server_remove_from_channels(server, NULL, client,
+ TRUE, NULL, FALSE);
+
+ client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+ cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
+ server->stat.clients--;
+ if (server->server_type == SILC_ROUTER)
+ server->stat.cell_clients--;
+ }
+ }
+
silc_free(server_id);
goto out;
}
SILC_LOG_DEBUG(("Start"));
if (packet->src_id_type != SILC_ID_CLIENT ||
- packet->dst_id_type != SILC_ID_CLIENT)
- return;
-
- if (!packet->dst_id)
+ packet->dst_id_type != SILC_ID_CLIENT || !packet->dst_id)
return;
/* Get the route to the client */
dst_sock = silc_server_get_client_route(server, packet->dst_id,
packet->dst_id_len, NULL, &idata);
- if (!dst_sock)
+ if (!dst_sock) {
+ /* Send IDENTIFY command reply with error status to indicate that
+ such destination ID does not exist or is invalid */
+ SilcBuffer idp = silc_id_payload_encode_data(packet->dst_id,
+ packet->dst_id_len,
+ packet->dst_id_type);
+ if (!idp)
+ return;
+
+ silc_server_send_command_reply(server, sock, SILC_COMMAND_IDENTIFY,
+ SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0, 1,
+ 2, idp, idp->len);
+ silc_buffer_free(idp);
return;
+ }
/* Send the private message */
silc_server_send_private_message(server, dst_sock, idata->send_key,
- idata->hmac_send, packet);
+ idata->hmac_send, idata->psn_send++,
+ packet);
}
/* Received private message key packet.. This packet is never for us. It is to
/* Relay the packet */
silc_server_relay_packet(server, dst_sock, idata->send_key,
- idata->hmac_send, packet, FALSE);
+ idata->hmac_send, idata->psn_send++, packet, FALSE);
}
/* Processes incoming command reply packet. The command reply packet may
idata = (SilcIDListData)client;
/* Encrypt packet */
- silc_packet_encrypt(idata->send_key, idata->hmac_send, dst_sock->outbuf,
- buffer->len);
+ silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++,
+ dst_sock->outbuf, buffer->len);
/* Send the packet */
silc_server_packet_send_real(server, dst_sock, TRUE);
SilcChannelID *id = NULL;
void *sender = NULL;
void *sender_entry = NULL;
+ bool local = TRUE;
SILC_LOG_DEBUG(("Processing channel message"));
if (packet->src_id_type == SILC_ID_CLIENT) {
sender_entry = silc_idlist_find_client_by_id(server->local_list,
sender, TRUE, NULL);
- if (!sender_entry)
+ if (!sender_entry) {
+ local = FALSE;
sender_entry = silc_idlist_find_client_by_id(server->global_list,
sender, TRUE, NULL);
+ }
if (!sender_entry || !silc_server_client_on_channel(sender_entry,
channel)) {
SILC_LOG_DEBUG(("Client not on channel"));
goto out;
}
+
+ /* If the packet is coming from router, but the client entry is
+ local entry to us then some router is rerouting this to us and it is
+ not allowed. */
+ if (server->server_type == SILC_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_ROUTER && local) {
+ SILC_LOG_DEBUG(("Channel message rerouted to the sender, drop it"));
+ goto out;
+ }
}
/* Distribute the packet to our local clients. This will send the
SilcClientID *client_id;
SilcBuffer reply;
SilcIDListData idata;
+ SilcIDCacheEntry id_cache = NULL;
char *username = NULL, *realname = NULL, *id_string;
uint32 id_len;
int ret;
client = (SilcClientEntry)sock->user_data;
idata = (SilcIDListData)client;
- /* Remove the old cache entry */
+ /* Remove the old cache entry. */
if (!silc_idcache_del_by_context(server->local_list->clients, client)) {
SILC_LOG_ERROR(("Lost client's cache entry - bad thing"));
silc_server_disconnect_remote(server, sock, "Server closed connection: "
SilcPacketContext *packet)
{
SilcBuffer buffer = packet->buffer;
- SilcServerEntry new_server;
+ SilcServerEntry new_server, server_entry;
SilcServerID *server_id;
SilcIDListData idata;
unsigned char *server_name, *id_string;
uint16 id_len, name_len;
int ret;
+ bool local = TRUE;
SILC_LOG_DEBUG(("Creating new server"));
idata = (SilcIDListData)new_server;
/* Remove the old cache entry */
- silc_idcache_del_by_context(server->local_list->servers, new_server);
+ if (!silc_idcache_del_by_context(server->local_list->servers, new_server)) {
+ silc_idcache_del_by_context(server->global_list->servers, new_server);
+ local = FALSE;
+ }
/* Parse the incoming packet */
ret = silc_buffer_unformat(buffer,
}
silc_free(id_string);
+ /* Check that we do not have this ID already */
+ server_entry = silc_idlist_find_server_by_id(server->local_list,
+ server_id, TRUE, NULL);
+ if (server_entry) {
+ silc_idcache_del_by_context(server->local_list->servers, server_entry);
+ } else {
+ server_entry = silc_idlist_find_server_by_id(server->global_list,
+ server_id, TRUE, NULL);
+ if (server_entry)
+ silc_idcache_del_by_context(server->global_list->servers, server_entry);
+ }
+
/* Update server entry */
idata->status |= SILC_IDLIST_STATUS_REGISTERED;
new_server->server_name = server_name;
new_server->id = server_id;
+
+ SILC_LOG_DEBUG(("New server id(%s)",
+ silc_id_render(server_id, SILC_ID_SERVER)));
/* Add again the entry to the ID cache. */
- silc_idcache_add(server->local_list->servers, server_name, server_id,
+ silc_idcache_add(local ? server->local_list->servers :
+ server->global_list->servers, server_name, server_id,
new_server, FALSE);
/* Distribute the information about new server in the SILC network
packet->data, packet->len, TRUE);
silc_buffer_free(packet);
- /* Mark the server disabled. The data sent earlier will go but nothing
+ /* Mark the router disabled. The data sent earlier will go but nothing
after this does not go to this connection. */
idata->status |= SILC_IDLIST_STATUS_DISABLED;
+ } else {
+ /* If it is router announce our stuff to it. */
+ if (sock->type == SILC_SOCKET_TYPE_ROUTER &&
+ server->server_type == SILC_ROUTER) {
+ silc_server_announce_servers(server, FALSE, 0, sock);
+ silc_server_announce_clients(server, 0, sock);
+ silc_server_announce_channels(server, 0, sock);
+ }
}
return new_server;
{
SilcBuffer buffer = packet->buffer;
SilcIDList id_list;
- SilcServerEntry router;
+ SilcServerEntry router, server_entry;
SilcSocketConnection router_sock;
SilcIDPayload idp;
SilcIdType id_type;
packet->src_id_type != SILC_ID_SERVER)
return;
- idp = silc_id_payload_parse(buffer);
+ idp = silc_id_payload_parse(buffer->data, buffer->len);
if (!idp)
return;
id_type = silc_id_payload_get_type(idp);
/* Normal server cannot have other normal server connections */
- if (id_type == SILC_ID_SERVER && sock->type == SILC_SOCKET_TYPE_SERVER)
+ server_entry = (SilcServerEntry)sock->user_data;
+ if (id_type == SILC_ID_SERVER && sock->type == SILC_SOCKET_TYPE_SERVER &&
+ server_entry->server_type == SILC_SERVER)
goto out;
id = silc_id_payload_get_id(idp);
if (!id)
goto out;
- if (sock->type == SILC_SOCKET_TYPE_SERVER)
- id_list = server->local_list;
- else
- id_list = server->global_list;
-
/* If the packet is coming from server then use the sender as the
origin of the the packet. If it came from router then check the real
sender of the packet and use that as the origin. */
if (sock->type == SILC_SOCKET_TYPE_SERVER) {
+ id_list = server->local_list;
router_sock = sock;
router = sock->user_data;
+
+ /* If the sender is backup router and ID is server (and we are not
+ backup router) then switch the entry to global list. */
+ if (server_entry->server_type == SILC_BACKUP_ROUTER &&
+ id_type == SILC_ID_SERVER &&
+ server->id_entry->server_type != SILC_BACKUP_ROUTER) {
+ id_list = server->global_list;
+ router_sock = server->router ? server->router->connection : sock;
+ }
} else {
void *sender_id = silc_id_str2id(packet->src_id, packet->src_id_len,
packet->src_id_type);
if (!router)
goto out;
router_sock = sock;
+ id_list = server->global_list;
}
switch(id_type) {
return;
/* Parse the channel payload */
- payload = silc_channel_payload_parse(packet->buffer);
+ payload = silc_channel_payload_parse(packet->buffer->data,
+ packet->buffer->len);
if (!payload)
return;
We also create a new key for the channel. */
SilcBuffer users = NULL, users_modes = NULL;
- if (!channel->id)
- 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
force the ID change. */
/* Relay the packet */
silc_server_relay_packet(server, dst_sock, idata->send_key,
- idata->hmac_send, packet, FALSE);
+ idata->hmac_send, idata->psn_send++,
+ packet, FALSE);
}
/* Received connection auth request packet that is used during connection
/* Run the protocol */
silc_protocol_execute(protocol, server->schedule, 0, 0);
}
+
+/* Received file transger packet. This packet is never for us. It is to
+ the client in the packet's destination ID. Sending of this sort of packet
+ equals sending private message, ie. it is sent point to point from
+ one client to another. */
+
+void silc_server_ftp(SilcServer server,
+ SilcSocketConnection sock,
+ SilcPacketContext *packet)
+{
+ SilcSocketConnection dst_sock;
+ SilcIDListData idata;
+
+ SILC_LOG_DEBUG(("Start"));
+
+ if (packet->src_id_type != SILC_ID_CLIENT ||
+ packet->dst_id_type != SILC_ID_CLIENT)
+ return;
+
+ if (!packet->dst_id)
+ return;
+
+ /* Get the route to the client */
+ dst_sock = silc_server_get_client_route(server, packet->dst_id,
+ packet->dst_id_len, NULL, &idata);
+ if (!dst_sock)
+ return;
+
+ /* Relay the packet */
+ silc_server_relay_packet(server, dst_sock, idata->send_key,
+ idata->hmac_send, idata->psn_send++,
+ packet, FALSE);
+}