/*
* $Id$
* $Log$
+ * Revision 1.12 2000/07/26 07:05:11 priikone
+ * Fixed the server to server (server to router actually) connections
+ * and made the private message work inside a cell. Added functin
+ * silc_server_replace_id.
+ *
* Revision 1.11 2000/07/19 07:08:09 priikone
* Added version detection support to SKE.
*
count = atoi(tmp);
}
- /* Then, make the query from our local client list */
+ /* Find client */
entry = silc_idlist_find_client_by_nickname(server->local_list,
nick, NULL);
- if (!entry) {
-
- /* If we are normal server and are connected to a router we will
- make global query from the router. */
- if (server->server_type == SILC_SERVER && !server->standalone) {
- SilcBuffer buffer = cmd->packet->buffer;
-
- SILC_LOG_DEBUG(("Requesting identify from router"));
-
- /* Send IDENTIFY command to our router */
- silc_buffer_push(buffer, buffer->data - buffer->head);
- silc_server_packet_forward(server, (SilcSocketConnection)
- server->id_entry->router->connection,
- buffer->data, buffer->len, TRUE);
- goto out;
- }
+ if (!entry)
+ entry = silc_idlist_find_client_by_hash(server->global_list,
+ nick, server->md5hash);
+
+ /* If client was not found and if we are normal server and are connected
+ to a router we will make global query from the router. */
+ if (!entry && server->server_type == SILC_SERVER && !server->standalone &&
+ !cmd->pending) {
+ SilcBuffer buffer = cmd->packet->buffer;
- /* If we are router then we will check our global list as well. */
- if (server->server_type == SILC_ROUTER) {
- entry =
- silc_idlist_find_client_by_nickname(server->global_list,
- nick, NULL);
- if (!entry) {
- silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
- SILC_STATUS_ERR_NO_SUCH_NICK,
- 3, tmp, strlen(tmp));
- goto out;
- }
- goto ok;
- }
+ SILC_LOG_DEBUG(("Requesting identify from router"));
+
+ /* Send IDENTIFY command to our router */
+ silc_buffer_push(buffer, buffer->data - buffer->head);
+ silc_server_packet_forward(server, (SilcSocketConnection)
+ server->id_entry->router->connection,
+ buffer->data, buffer->len, TRUE);
+ return;
+ }
+
+ /* If we are router we have checked our local list by nickname and our
+ global list by hash so far. It is possible that the client is still not
+ found and we'll check it from local list by hash. */
+ if (!entry && server->server_type == SILC_ROUTER)
+ entry = silc_idlist_find_client_by_hash(server->local_list,
+ nick, server->md5hash);
+ if (!entry) {
+ /* The client definitely does not exist */
silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
SILC_STATUS_ERR_NO_SUCH_NICK,
3, tmp, strlen(tmp));
goto out;
}
- ok:
/* Send IDENTIFY reply */
id_string = silc_id_id2str(entry->id, SILC_ID_CLIENT);
tmp = silc_command_get_first_arg(cmd->payload, NULL);
2, id_string,
SILC_ID_CLIENT_LEN,
3, nick, strlen(nick));
-#if 0
if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
silc_server_packet_send_dest(server, cmd->sock,
id, cmd->packet->src_id_type,
packet->data, packet->len, FALSE);
silc_free(id);
- } else
-#endif
+ } else {
silc_server_packet_send(server, cmd->sock,
SILC_PACKET_COMMAND_REPLY, 0,
packet->data, packet->len, FALSE);
+ }
silc_free(id_string);
silc_buffer_free(packet);
/*
* $Id$
* $Log$
+ * Revision 1.5 2000/07/26 07:05:11 priikone
+ * Fixed the server to server (server to router actually) connections
+ * and made the private message work inside a cell. Added functin
+ * silc_server_replace_id.
+ *
* Revision 1.4 2000/07/12 05:59:41 priikone
* Major rewrite of ID Cache system. Support added for the new
* ID cache system. Major rewrite of ID List stuff on server. All
/* Process one identify reply */
if (status == SILC_STATUS_OK) {
+ SilcClientID *client_id;
unsigned char *id_data;
- char *nickname;
+ char *nickname, *username;
id_data = silc_command_get_arg_type(cmd->payload, 2, NULL);
nickname = silc_command_get_arg_type(cmd->payload, 3, NULL);
if (!id_data || !nickname)
goto out;
-#if 0
- /* Allocate client entry */
- client_entry = silc_calloc(1, sizeof(*client_entry));
- client_entry->id = silc_id_str2id(id_data, SILC_ID_CLIENT);
- client_entry->nickname = strdup(nickname);
+ username = silc_command_get_arg_type(cmd->payload, 4, NULL);
+
+ client_id = silc_id_str2id(id_data, SILC_ID_CLIENT);
- /* Save received Client ID to ID cache */
- silc_idcache_add(win->client_cache, client_entry->nickname,
- SILC_ID_CLIENT, client_entry->id, client_entry, TRUE);
-#endif
+ /* 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, NULL,
+ NULL, NULL, NULL, NULL);
}
if (status == SILC_STATUS_LIST_START) {
/*
* $Id$
* $Log$
+ * Revision 1.12 2000/07/26 07:05:11 priikone
+ * Fixed the server to server (server to router actually) connections
+ * and made the private message work inside a cell. Added functin
+ * silc_server_replace_id.
+ *
* Revision 1.11 2000/07/20 10:17:25 priikone
* Added dynamic protocol registering/unregistering support. The
* patch was provided by cras.
server->local_list->servers = silc_idcache_alloc(0);
server->local_list->channels = silc_idcache_alloc(0);
- if (server->server_type == SILC_ROUTER) {
- server->global_list->clients = silc_idcache_alloc(0);
- server->global_list->servers = silc_idcache_alloc(0);
- server->global_list->channels = silc_idcache_alloc(0);
- }
+ /* XXX for now these are allocated for normal server as well as these
+ hold some global information that the server has fetched from its
+ router. For router these are used as they are supposed to be used
+ on router. The XXX can be remoevd later if this is the way we are
+ going to do this in the normal server as well. */
+ server->global_list->clients = silc_idcache_alloc(0);
+ server->global_list->servers = silc_idcache_alloc(0);
+ server->global_list->channels = silc_idcache_alloc(0);
/* Allocate the entire socket list that is used in server. Eventually
all connections will have entry in this table (it is a table of
case SILC_PACKET_NEW_SERVER:
/*
* Received new server packet. This includes Server ID and some other
- * information that we may save. This is after server as connected to us.
+ * information that we may save. This is received after server has
+ * connected to us.
*/
SILC_LOG_DEBUG(("New Server packet"));
silc_server_new_server(server, sock, packet);
break;
+ case SILC_PACKET_NEW_CHANNEL:
+ break;
+
+ case SILC_PACKET_NEW_CHANNEL_USER:
+ break;
+
+ case SILC_PACKET_NEW_CHANNEL_LIST:
+ break;
+
+ case SILC_PACKET_NEW_CHANNEL_USER_LIST:
+ break;
+
+ case SILC_PACKET_REPLACE_ID:
+ /*
+ * Received replace ID packet. This sends the old ID that is to be
+ * replaced with the new one included into the packet. Client must not
+ * send this packet.
+ */
+ SILC_LOG_DEBUG(("Replace ID packet"));
+ silc_server_replace_id(server, sock, packet);
+ break;
+
+ case SILC_PACKET_REMOVE_ID:
+ break;
+
default:
SILC_LOG_ERROR(("Incorrect packet type %d, packet dropped", type));
break;
/* If we are router and the client has router then the client is in
our cell but not directly connected to us. */
if (server->server_type == SILC_ROUTER && client->router) {
+ /* We are of course in this case the client's router thus the real
+ "router" of the client is the server who owns the client. Thus
+ we will send the packet to that server. */
+ router = (SilcServerEntry)dst_sock->user_data;
+ assert(client->router == server->id_entry);
+
silc_server_private_message_send_internal(server, dst_sock,
- client->router->send_key,
- client->router->hmac,
+ router->send_key,
+ router->hmac,
packet);
goto out;
}
silc_buffer_free(packet);
}
+/* Received packet to replace a ID. This checks that the requested ID
+ exists and replaces it with the new one. */
+
+void silc_server_replace_id(SilcServer server,
+ SilcSocketConnection sock,
+ SilcPacketContext *packet)
+{
+ SilcBuffer buffer = packet->buffer;
+ unsigned char *old_id = NULL, *new_id = NULL;
+ SilcIdType old_id_type, new_id_type;
+ unsigned short old_id_len, new_id_len;
+ void *id = NULL, *id2 = NULL;
+
+ if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
+ packet->src_id_type == SILC_ID_CLIENT)
+ return;
+
+ SILC_LOG_DEBUG(("Replacing ID"));
+
+ silc_buffer_unformat(buffer,
+ SILC_STR_UI_SHORT(&old_id_type),
+ SILC_STR_UI16_NSTRING_ALLOC(&old_id, &old_id_len),
+ SILC_STR_UI_SHORT(&new_id_type),
+ SILC_STR_UI16_NSTRING_ALLOC(&new_id, &new_id_len),
+ SILC_STR_END);
+
+ if (old_id_type != new_id_type)
+ goto out;
+
+ if (old_id_len != silc_id_get_len(old_id_type) ||
+ new_id_len != silc_id_get_len(new_id_type))
+ goto out;
+
+ id = silc_id_str2id(old_id, old_id_type);
+ if (!id)
+ goto out;
+
+ id2 = silc_id_str2id(new_id, new_id_type);
+ if (!id2)
+ goto out;
+
+ /* Replace the old ID */
+ switch(old_id_type) {
+ case 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:
+ 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);
+ break;
+
+ case SILC_ID_CHANNEL:
+ /* XXX Hmm... Basically this cannot occur. Channel ID's cannot be
+ re-generated. */
+ silc_free(id2);
+ break;
+
+ default:
+ silc_free(id2);
+ break;
+ }
+
+ out:
+ if (id)
+ silc_free(id);
+ if (old_id)
+ silc_free(old_id);
+ if (new_id)
+ silc_free(new_id);
+}
+
/* Creates new channel. */
SilcChannelEntry silc_server_new_channel(SilcServer server,
SilcPacketContext *packet)
{
SilcBuffer buffer = packet->buffer;
+ SilcIDList id_list;
+ SilcServerEntry tmpserver, router;
+ SilcSocketConnection router_sock;
SilcIdType id_type;
unsigned char *id_string;
- void *id;
+ void *id, *tmpid;
SILC_LOG_DEBUG(("Processing new ID"));
if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
- server->server_type == SILC_SERVER)
+ server->server_type == SILC_SERVER ||
+ packet->src_id_type != SILC_ID_SERVER)
return;
silc_buffer_unformat(buffer,
if (!id)
goto out;
- /* XXX Do check whether the packet is coming outside the cell or
- from someone inside the cell. If outside use global lists otherwise
- local lists. */
- /* XXX If using local list set the idlist->connection to the sender's
- socket connection as it is used in packet sending */
+ /* 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);
+ tmpserver = (SilcServerEntry)sock->user_data;
+
+ if (!SILC_ID_SERVER_COMPARE(tmpid, tmpserver->id) &&
+ sock->type == SILC_SOCKET_TYPE_SERVER) {
+ id_list = server->local_list;
+ router_sock = sock;
+ router = server->id_entry;
+ } else {
+ id_list = server->global_list;
+ router_sock = (SilcSocketConnection)server->id_entry->router->connection;
+ router = server->id_entry->router;
+ }
+
+ silc_free(tmpid);
switch(id_type) {
case SILC_ID_CLIENT:
/* 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(server->local_list, NULL, NULL, NULL,
- id, sock->user_data, NULL, NULL,
- NULL, NULL, NULL, sock);
+ idlist = silc_idlist_add_client(id_list, NULL, NULL, NULL,
+ id, router, NULL, NULL,
+ NULL, NULL, NULL, router_sock);
}
break;
/* 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(server->local_list, NULL, 0,
- id, server->id_entry, NULL, NULL,
- NULL, NULL, NULL, sock);
+ idlist = silc_idlist_add_server(id_list, NULL, 0,
+ id, router, NULL, NULL,
+ NULL, NULL, NULL, router_sock);
}
break;
case SILC_ID_CHANNEL:
/* 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(server->local_list, NULL, 0, id,
- server->id_entry, NULL);
+ silc_idlist_add_channel(id_list, NULL, 0, id,
+ router, NULL);
break;
default: