Register remote router automatically when connecting to it.
Rewrote IDENTIFY command.
IDList find routines returns the ID Cache Entry now.
+Fri Dec 15 15:55:12 EET 2000 Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ * Changed char *data to unsigned char *data in ID Cache system to
+ support binary data as ID Cache data. Changed code to support
+ binary data in lib/silccore/idcache.c.
+
+ * Renamed silc_server_packet_relay_command_reply to
+ silc_server_command_reply as it is normal packet receiving
+ function. Rewrote the function to accept command replys for
+ servers and not only for clients.
+
+ * Mark remote router always as registered server if we are connecting
+ to it. Otherwise, commands sent by the router to us are ignored.
+
+ * All ID List find routines now returns the ID Cache Entry pointer
+ as well if requested.
+
+ * WHOIS command works now in router environment, tested with two
+ routers, two servers and two clients.
+
+ * Cleaned up and rewrote IDENTIFY command. IDENTIFY should work now
+ in router environment (as it is almost equivalent to WHOIS) but
+ hasn't been tested thoroughly. Added new functions:
+
+ silc_server_command_identify_parse
+ silc_server_command_identify_send_reply
+ silc_server_command_identify_from_client
+ silc_server_command_identify_from_server
+
+ * Disabled route cache adding because adding two different ID's with
+ same IP replaces the old cache entry thus giving wrong route.
+ The entry->router->connection is always the fastest route anyway
+ so route cache may not be needed. Of course, new routes maybe
+ established after receiving the ID when the entry->router->connection
+ might not be anymore the most optimal.
+
Thu Dec 14 15:55:35 EET 2000 Pekka Riikonen <priikone@poseidon.pspt.fi>
* Add route cache for received ID for fast routing.
[cipher]
-twofish:/home/priikone/silc/lib/silcsim/modules/twofish.sim.so:16:16
-rc6:/home/priikone/silc/lib/silcsim/modules/rc6.sim.so:16:16
-mars:/home/priikone/silc/lib/silcsim/modules/mars.sim.so:16:16
-none:/home/priikone/silc/lib/silcsim/modules/none.sim.so:0:0
+twofish:/home/silc/silc/lib/silcsim/modules/twofish.sim.so:16:16
+rc6:/home/silc/silc/lib/silcsim/modules/rc6.sim.so:16:16
+mars:/home/silc/silc/lib/silcsim/modules/mars.sim.so:16:16
+none:/home/silc/silc/lib/silcsim/modules/none.sim.so:0:0
[hash]
md5::64:16
[cipher]
-twofish:/home/priikone/silc/lib/silcsim/modules/twofish.sim.so:16:16
-rc6:/home/priikone/silc/lib/silcsim/modules/rc6.sim.so:16:16
-mars:/home/priikone/silc/lib/silcsim/modules/mars.sim.so:16:16
-none:/home/priikone/silc/lib/silcsim/modules/none.sim.so:0:0
+twofish:/home/silc/silc/lib/silcsim/modules/twofish.sim.so:16:16
+rc6:/home/silc/silc/lib/silcsim/modules/rc6.sim.so:16:16
+mars:/home/silc/silc/lib/silcsim/modules/mars.sim.so:16:16
+none:/home/silc/silc/lib/silcsim/modules/none.sim.so:0:0
[hash]
md5::64:16
[commands]
#/server lassi:1333
-/server lassi:1334
+#/server lassi:1334
#/server leevi:1333
{
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
- int tmp_len;
+ int argc, tmp_len;
char *tmp, *channel_name = NULL, *cipher = NULL;
SilcChannelEntry channel;
unsigned int umode = 0;
int created = FALSE;
- SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 3);
+ SILC_LOG_DEBUG(("Start"));
+
+ /* Check number of parameters */
+ argc = silc_argument_get_arg_num(cmd->args);
+ if (argc < 1) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
+ SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+ goto out;
+ }
+ if (argc > 3) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
+ SILC_STATUS_ERR_TOO_MANY_PARAMS);
+ goto out;
+ }
/* Get channel name */
tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
SilcCommandPayload payload;
SilcArgumentPayload args;
SilcPacketContext *packet;
- int pending;
+ int pending; /* Command is being re-processed when TRUE */
} *SilcServerCommandContext;
/* Structure holding pending commands. If command is pending it will be
SilcServerCommandReply silc_command_reply_list[] =
{
SILC_SERVER_CMD_REPLY(join, JOIN),
- SILC_SERVER_CMD_REPLY(identify, WHOIS),
+ SILC_SERVER_CMD_REPLY(whois, WHOIS),
SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
{ NULL, 0 },
}
/* Caches the received WHOIS information. If we are normal server currently
- we cache global information only for short period of time. If we are
- router we want to cache them a bit longer since we can receive information
- if any of the information becomes invalid. Normal server cannot receive
- that information. Returns FALSE if something was wrong with the reply. */
+ we cache global information only for short period of time. */
+/* XXX cache expirying not implemented yet! */
static char
silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
char *nickname, *username, *realname;
SilcClientID *client_id;
SilcClientEntry client;
+ SilcIDCacheEntry cache = NULL;
+ char global = FALSE;
+ char *nick;
id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
/* Check if we have this client cached already. */
- client = silc_idlist_find_client_by_id(server->local_list, client_id);
- if (!client && server->server_type == SILC_ROUTER)
- client = silc_idlist_find_client_by_id(server->global_list, client_id);
+ client = silc_idlist_find_client_by_id(server->local_list, client_id,
+ &cache);
+ if (!client) {
+ client = silc_idlist_find_client_by_id(server->global_list,
+ client_id, &cache);
+ global = TRUE;
+ }
if (!client) {
+ /* If router did not find such Client ID in its lists then this must
+ be bogus client or some router in the net is buggy. */
+ if (server->server_type == SILC_ROUTER)
+ return FALSE;
+
+ /* Take hostname out of nick string if it includes it. */
+ if (strchr(nickname, '@')) {
+ int len = strcspn(nickname, "@");
+ nick = silc_calloc(len + 1, sizeof(char));
+ memcpy(nick, nickname, len);
+ } else {
+ nick = strdup(nickname);
+ }
+
/* We don't have that client anywhere, add it. The client is added
- to global list since server or router didn't have it in the lists
- so it must be global. */
- silc_idlist_add_client(server->global_list, strdup(nickname),
- username, realname, client_id, NULL, NULL);
+ to global list since server didn't have it in the lists so it must be
+ global. */
+ silc_idlist_add_client(server->global_list, nick,
+ strdup(username),
+ strdup(realname), client_id, NULL, NULL);
} else {
/* We have the client already, update the data */
+ SILC_LOG_DEBUG(("Updating client data"));
+
+ /* Take hostname out of nick string if it includes it. */
+ if (strchr(nickname, '@')) {
+ int len = strcspn(nickname, "@");
+ nick = silc_calloc(len + 1, sizeof(char));
+ memcpy(nick, nickname, len);
+ } else {
+ nick = strdup(nickname);
+ }
+
+ if (client->nickname)
+ silc_free(client->nickname);
if (client->username)
silc_free(client->username);
if (client->userinfo)
silc_free(client->userinfo);
+ client->nickname = nick;
client->username = strdup(username);
client->userinfo = strdup(realname);
- }
- silc_free(client_id);
+ if (cache) {
+ cache->data = nick;
+ silc_idcache_sort_by_data(global ? server->global_list->clients :
+ server->local_list->clients);
+ }
+
+ silc_free(client_id);
+ }
return TRUE;
}
silc_server_command_reply_free(cmd);
}
+/* Caches the received IDENTIFY information. */
+
+static char
+silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
+{
+ SilcServer server = cmd->server;
+ int len, id_len;
+ unsigned char *id_data;
+ char *nickname, *username;
+ SilcClientID *client_id;
+ SilcClientEntry client;
+ SilcIDCacheEntry cache = NULL;
+ char global = FALSE;
+ char *nick = NULL;
+
+ id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
+ nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
+ username = silc_argument_get_arg_type(cmd->args, 4, &len);
+ if (!id_data)
+ return FALSE;
+
+ client_id = silc_id_payload_parse_id(id_data, id_len);
+
+ /* Check if we have this client cached already. */
+
+ client = silc_idlist_find_client_by_id(server->local_list, client_id,
+ &cache);
+ if (!client) {
+ client = silc_idlist_find_client_by_id(server->global_list,
+ client_id, &cache);
+ global = TRUE;
+ }
+
+ if (!client) {
+ /* If router did not find such Client ID in its lists then this must
+ be bogus client or some router in the net is buggy. */
+ if (server->server_type == SILC_ROUTER)
+ return FALSE;
+
+ /* Take hostname out of nick string if it includes it. */
+ if (nickname) {
+ if (strchr(nickname, '@')) {
+ int len = strcspn(nickname, "@");
+ nick = silc_calloc(len + 1, sizeof(char));
+ memcpy(nick, nickname, len);
+ } else {
+ nick = strdup(nickname);
+ }
+ }
+
+ /* We don't have that client anywhere, add it. The client is added
+ to global list since server didn't have it in the lists so it must be
+ global. */
+ silc_idlist_add_client(server->global_list, nick,
+ username ? strdup(username) : NULL, NULL,
+ client_id, NULL, NULL);
+ } else {
+ /* We have the client already, update the data */
+
+ SILC_LOG_DEBUG(("Updating client data"));
+
+ /* Take hostname out of nick string if it includes it. */
+ if (nickname) {
+ if (strchr(nickname, '@')) {
+ int len = strcspn(nickname, "@");
+ nick = silc_calloc(len + 1, sizeof(char));
+ memcpy(nick, nickname, len);
+ } else {
+ nick = strdup(nickname);
+ }
+ }
+
+ if (nickname && client->nickname) {
+ silc_free(client->nickname);
+ client->nickname = nick;
+ }
+
+ if (username && client->username) {
+ silc_free(client->username);
+ client->username = strdup(username);
+ }
+
+ if (nickname && cache) {
+ cache->data = nick;
+ silc_idcache_sort_by_data(global ? server->global_list->clients :
+ server->local_list->clients);
+ }
+
+ silc_free(client_id);
+ }
+
+ return TRUE;
+}
+
/* Received reply for forwarded IDENTIFY command. We have received the
requested identify information now and we will cache it. After this we
will call the pending command so that the requestee gets the information
SILC_SERVER_CMD_REPLY_FUNC(identify)
{
SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
- SilcServer server = cmd->server;
SilcCommandStatus status;
SILC_LOG_DEBUG(("Start"));
COMMAND_CHECK_STATUS_LIST;
- /* Process one identify reply */
+ if (!silc_server_command_reply_identify_save(cmd))
+ goto out;
+
+ /* XXX */
+
if (status == SILC_STATUS_OK) {
- SilcClientID *client_id;
- unsigned int len;
- unsigned char *id_data;
- char *nickname, *username;
-
- id_data = silc_argument_get_arg_type(cmd->args, 2, &len);
- nickname = silc_argument_get_arg_type(cmd->args, 3, NULL);
- if (!id_data || !nickname)
- goto out;
-
- username = silc_argument_get_arg_type(cmd->args, 4, NULL);
- client_id = silc_id_payload_parse_id(id_data, len);
-
- /* Add the client always to our global list. If normal or router server
- ever gets here it means they don't have this client's information
- in their cache. */
- silc_idlist_add_client(server->global_list, strdup(nickname),
- username, NULL, client_id, NULL, NULL);
+
}
if (status == SILC_STATUS_LIST_START) {
/* Finds server by Server ID */
SilcServerEntry
-silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id)
+silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id,
+ SilcIDCacheEntry *ret_entry)
{
SilcIDCacheEntry id_cache = NULL;
SilcServerEntry server;
server = (SilcServerEntry)id_cache->context;
+ if (ret_entry)
+ *ret_entry = id_cache;
+
return server;
}
return clients;
}
+/* Returns all clients matching requested nickname. Number of clients is
+ returned to `clients_count'. Caller must free the returned table. */
+
+SilcClientEntry *
+silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
+ SilcHash md5hash,
+ unsigned int *clients_count)
+{
+ SilcIDCacheList list = NULL;
+ SilcIDCacheEntry id_cache = NULL;
+ SilcClientEntry *clients;
+ unsigned char hash[32];
+ int i;
+
+ silc_hash_make(md5hash, nickname, strlen(nickname), hash);
+
+ if (!silc_idcache_find_by_data(id_list->clients, hash, &list))
+ return NULL;
+
+ clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
+
+ i = 0;
+ silc_idcache_list_first(list, &id_cache);
+ clients[i++] = (SilcClientEntry)id_cache->context;
+
+ while (silc_idcache_list_next(list, &id_cache))
+ clients[i++] = (SilcClientEntry)id_cache->context;
+
+ silc_idcache_list_free(list);
+
+ if (clients_count)
+ *clients_count = i;
+
+ return clients;
+}
+
/* Finds client entry by nickname. */
SilcClientEntry
silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
- char *server)
+ char *server, SilcIDCacheEntry *ret_entry)
{
SilcIDCacheList list = NULL;
SilcIDCacheEntry id_cache = NULL;
return NULL;
client = (SilcClientEntry)id_cache->context;
+
+ if (ret_entry)
+ *ret_entry = id_cache;
}
return client;
SilcClientEntry
silc_idlist_find_client_by_hash(SilcIDList id_list, char *nickname,
- SilcHash md5hash)
+ SilcHash md5hash, SilcIDCacheEntry *ret_entry)
{
SilcIDCacheList list = NULL;
SilcIDCacheEntry id_cache = NULL;
silc_idcache_list_free(list);
+ if (ret_entry)
+ *ret_entry = id_cache;
+
return client;
}
/* Finds client by Client ID */
SilcClientEntry
-silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id)
+silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id,
+ SilcIDCacheEntry *ret_entry)
{
SilcIDCacheEntry id_cache = NULL;
SilcClientEntry client;
client = (SilcClientEntry)id_cache->context;
+ if (ret_entry)
+ *ret_entry = id_cache;
+
return client;
}
client->id = new_id;
id_cache->id = (void *)new_id;
+ /* If the old ID Cache data was the hash value of the old Client ID
+ replace it with the hash of new Client ID */
+ if (id_cache->data && !SILC_ID_COMPARE_HASH(old_id, id_cache->data)) {
+ silc_free(id_cache->data);
+ id_cache->data = silc_calloc(sizeof(new_id->hash),
+ sizeof(unsigned char));
+ memcpy(id_cache->data, new_id->hash, sizeof(new_id->hash));
+ silc_idcache_sort_by_data(id_list->clients);
+ }
+
return client;
}
are not case-sensitive. */
SilcChannelEntry
-silc_idlist_find_channel_by_name(SilcIDList id_list, char *name)
+silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
+ SilcIDCacheEntry *ret_entry)
{
SilcIDCacheList list = NULL;
SilcIDCacheEntry id_cache = NULL;
channel = (SilcChannelEntry)id_cache->context;
+ if (ret_entry)
+ *ret_entry = id_cache;
+
silc_idcache_list_free(list);
return channel;
/* Finds channel by Channel ID. */
SilcChannelEntry
-silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id)
+silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id,
+ SilcIDCacheEntry *ret_entry)
{
SilcIDCacheEntry id_cache = NULL;
SilcChannelEntry channel;
channel = (SilcChannelEntry)id_cache->context;
+ if (ret_entry)
+ *ret_entry = id_cache;
+
return channel;
}
SilcServerID *id, SilcServerEntry router,
void *connection);
SilcServerEntry
-silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id);
+silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id,
+ SilcIDCacheEntry *ret_entry);
SilcServerEntry
silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
SilcServerID *new_id);
SilcClientEntry *
silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
char *server, unsigned int *clients_count);
+SilcClientEntry *
+silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
+ SilcHash md5hash,
+ unsigned int *clients_count);
SilcClientEntry
silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
- char *server);
+ char *server,
+ SilcIDCacheEntry *ret_entry);
SilcClientEntry
silc_idlist_find_client_by_hash(SilcIDList id_list, char *nickname,
- SilcHash md5hash);
+ SilcHash md5hash, SilcIDCacheEntry *ret_entry);
SilcClientEntry
-silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id);
+silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id,
+ SilcIDCacheEntry *ret_entry);
SilcClientEntry
silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
SilcClientID *new_id);
SilcCipher channel_key);
void silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry);
SilcChannelEntry
-silc_idlist_find_channel_by_name(SilcIDList id_list, char *name);
+silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
+ SilcIDCacheEntry *ret_entry);
SilcChannelEntry
-silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id);
+silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id,
+ SilcIDCacheEntry *ret_entry);
#endif
"No such nickname: Private message not sent");
}
-/* 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. */
+/* 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. */
void silc_server_command_reply(SilcServer server,
SilcSocketConnection sock,
void silc_server_private_message(SilcServer server,
SilcSocketConnection sock,
SilcPacketContext *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);
void silc_server_channel_message(SilcServer server,
SilcSocketConnection sock,
SilcPacketContext *packet);
sock->type = SILC_SOCKET_TYPE_ROUTER;
server->id_entry->router = id_entry;
server->router = id_entry;
+ server->router->data.registered = TRUE;
out:
/* Free the temporary connection data context */
* This must be the case here or we will ignore the packet.
*/
SILC_LOG_DEBUG(("Command Reply packet"));
- silc_server_packet_relay_command_reply(server, sock, packet);
+ silc_server_command_reply(server, sock, packet);
break;
/*
[Cipher]
-rc6:/home/priikone/silc/lib/silcsim/modules/rc6.sim.so:16:16
-twofish:/home/priikone/silc/lib/silcsim/modules/twofish.sim.so:16:16
-mars:/home/priikone/silc/lib/silcsim/modules/mars.sim.so:16:16
-none:/home/priikone/silc/lib/silcsim/modules/none.sim.so:0:0
+rc6:/home/silc/silc/lib/silcsim/modules/rc6.sim.so:16:16
+twofish:/home/silc/silc/lib/silcsim/modules/twofish.sim.so:16:16
+mars:/home/silc/silc/lib/silcsim/modules/mars.sim.so:16:16
+none:/home/silc/silc/lib/silcsim/modules/none.sim.so:0:0
[HashFunction]
md5::64:16
Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi
[ServerInfo]
-lassi.kuo.fi.ssh.com:10.2.1.6:Kuopio, Finland:1334
+lassi.kuo.fi.ssh.com:10.2.1.7:Kuopio, Finland:1334
[ListenPort]
-10.2.1.6:10.2.1.6:1334
+10.2.1.7:10.2.1.7:1334
[Logging]
infologfile:silcd2.log:10000
2:200:300:400
[ClientConnection]
-10.2.1.199:passwd:priikone:333:1
:::1333:1
:::1334:1
:::1335:1
+:::1336:1
[AdminConnection]
-10.2.1.199:passwd:priikone:priikone:1
[ServerConnection]
-10.2.1.6:passwd:priikone:1335:1:1
+10.2.1.7:passwd:priikone:1333:1:1
[RouterConnection]
-10.2.1.6:passwd:priikone:1335:1:1:0
+10.2.1.7:passwd:priikone:1335:1:1:1
[DenyConnection]
[RedirectClient]