Fixed the server to server (server to router actually) connections
authorPekka Riikonen <priikone@silcnet.org>
Wed, 26 Jul 2000 07:05:11 +0000 (07:05 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Wed, 26 Jul 2000 07:05:11 +0000 (07:05 +0000)
and made the private message work inside a cell. Added functin
silc_server_replace_id.

apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/server.c
apps/silcd/server.h

index e3e810ee0327c0a35bae54703e1a959f00f6c7cd..419b778aa33fa2fad0480a844a643bac0fcbc824 100644 (file)
 /*
  * $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.
  *
@@ -552,47 +557,44 @@ SILC_SERVER_CMD_FUNC(identify)
     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);
@@ -601,7 +603,6 @@ SILC_SERVER_CMD_FUNC(identify)
                                                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, 
@@ -609,11 +610,11 @@ SILC_SERVER_CMD_FUNC(identify)
                                 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);
index b3054faed7d3e07354912ca511c70ebee2b8f9e5..08cee1c7baee3b23ce95479d325a082defd80c3f 100644 (file)
 /*
  * $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
@@ -165,24 +170,25 @@ SILC_SERVER_CMD_REPLY_FUNC(identify)
 
   /* 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) {
index 5863369729351c391c1dcf7dc7f1cb262e8a5cdf..cdd1ab2f6c11db4ac59fb290f617921afa2ad220 100644 (file)
 /*
  * $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.
@@ -242,11 +247,14 @@ int silc_server_init(SilcServer server)
   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 
@@ -1506,12 +1514,38 @@ void silc_server_packet_parse_type(SilcServer server,
   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;
@@ -2447,9 +2481,15 @@ void silc_server_private_message(SilcServer server,
     /* 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;
     }
@@ -2789,6 +2829,81 @@ void silc_server_send_replace_id(SilcServer server,
   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, 
@@ -3032,14 +3147,18 @@ void silc_server_new_id(SilcServer server, SilcSocketConnection sock,
                        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,
@@ -3055,11 +3174,23 @@ void silc_server_new_id(SilcServer server, SilcSocketConnection sock,
   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:
@@ -3068,9 +3199,9 @@ void silc_server_new_id(SilcServer server, SilcSocketConnection sock,
 
       /* 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;
 
@@ -3080,17 +3211,17 @@ void silc_server_new_id(SilcServer server, SilcSocketConnection 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(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:
index b080b9f1d3da3b7fadfb449051a8156f140f6104..c89c4abbc2eeca5a9b40a23ecc610eceed31d502 100644 (file)
@@ -137,6 +137,9 @@ void silc_server_send_replace_id(SilcServer server,
                                 unsigned int old_id_len,
                                 void *new_id, SilcIdType new_id_type,
                                 unsigned int new_id_len);
+void silc_server_replace_id(SilcServer server,
+                           SilcSocketConnection sock,
+                           SilcPacketContext *packet);
 SilcChannelEntry silc_server_new_channel(SilcServer server, 
                                         SilcServerID *router_id,
                                         char *cipher, char *channel_name);