Renamed silc_server_get_client_resolve to silc_server_query_client,
[silc.git] / apps / silcd / packet_receive.c
index ed8ad2f02233f60144601d03e16a4a5f08571f07..4589ab7c0c6b25d02a58cee8101c8df081c3fcc8 100644 (file)
@@ -43,7 +43,7 @@ void silc_server_notify(SilcServer server,
   SilcClientEntry client = NULL, client2 = NULL;
   SilcServerEntry server_entry = NULL;
   SilcChannelClientEntry chl;
-  SilcIDCacheEntry cache;
+  SilcIDCacheEntry cache = NULL;
   SilcHashTableList htl;
   SilcUInt32 mode;
   unsigned char *tmp;
@@ -166,15 +166,17 @@ void silc_server_notify(SilcServer server,
        entry for the client. */
     client = silc_idlist_find_client_by_id(server->global_list, 
                                           client_id, server->server_type, 
-                                          NULL);
+                                          &cache);
     if (!client) {
       client = silc_idlist_find_client_by_id(server->local_list, 
                                             client_id, server->server_type,
-                                            NULL);
+                                            &cache);
       if (!client) {
        /* If router did not find the client the it is bogus */
-       if (server->server_type != SILC_SERVER)
+       if (server->server_type != SILC_SERVER) {
+         silc_free(client_id);
          goto out;
+       }
 
        client = 
          silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
@@ -189,6 +191,7 @@ void silc_server_notify(SilcServer server,
        client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
       }
     }
+    silc_free(client_id);
 
     /* Do not process the notify if the client is not registered */
     if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED))
@@ -233,10 +236,13 @@ void silc_server_notify(SilcServer server,
 
     silc_hash_table_add(channel->user_list, client, chl);
     silc_hash_table_add(client->channels, channel, chl);
-    silc_free(client_id);
     channel->user_count++;
     channel->disabled = FALSE;
 
+    /* Make sure we don't expire clients that are on channel */
+    if (cache)
+      cache->expire = 0;
+
     /* Update statistics */
     if (server->server_type == SILC_ROUTER) {
       if (sock->type != SILC_SOCKET_TYPE_ROUTER)
@@ -422,6 +428,7 @@ void silc_server_notify(SilcServer server,
        goto out;
       }
     }
+    silc_free(channel_id);
 
     if (channel->topic && !strcmp(channel->topic, tmp)) {
       SILC_LOG_DEBUG(("Topic is already set and same"));
@@ -448,7 +455,6 @@ void silc_server_notify(SilcServer server,
     silc_server_packet_send_to_channel(server, NULL, channel, packet->type, 
                                       FALSE, packet->buffer->data, 
                                       packet->buffer->len, FALSE);
-    silc_free(channel_id);
     break;
 
   case SILC_NOTIFY_TYPE_NICK_CHANGE:
@@ -475,8 +481,10 @@ void silc_server_notify(SilcServer server,
       if (!id2)
        goto out;
       client_id2 = silc_id_payload_parse_id(id2, tmp_len, NULL);
-      if (!client_id2)
+      if (!client_id2) {
+       silc_free(client_id);
        goto out;
+      }
       
       SILC_LOG_DEBUG(("Old Client ID id(%s)", 
                      silc_id_render(client_id, SILC_ID_CLIENT)));
@@ -1222,10 +1230,16 @@ void silc_server_notify(SilcServer server,
     if (!server_id)
       goto out;
 
+    /* If the ID is mine, this notify is not allowed. */
+    if (SILC_ID_SERVER_COMPARE(server_id, server->id)) {
+      SILC_LOG_DEBUG(("Ignoring my own ID for SERVER_SIGNOFF"));
+      break;
+    }
+
     /* Get server entry */
     server_entry = silc_idlist_find_server_by_id(server->global_list, 
                                                 server_id, TRUE, NULL);
-    local = TRUE;
+    local = FALSE;
     if (!server_entry) {
       server_entry = silc_idlist_find_server_by_id(server->local_list, 
                                                   server_id, TRUE, NULL);
@@ -1284,6 +1298,7 @@ void silc_server_notify(SilcServer server,
              silc_server_del_from_watcher_list(server, client);
 
            /* Remove the client */
+           silc_idlist_del_data(client);
            silc_idlist_del_client(local ? server->local_list :
                                   server->global_list, client);
          }
@@ -1578,6 +1593,8 @@ void silc_server_notify(SilcServer server,
          server->stat.detached--;
       }
     }
+    SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
+    SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
 
     /* Change the mode */
     client->mode = mode;
@@ -1684,6 +1701,7 @@ void silc_server_notify(SilcServer server,
          if (client) {
            silc_server_remove_from_channels(server, NULL, client, TRUE, 
                                             NULL, TRUE);
+           silc_idlist_del_data(client);
            silc_idlist_del_client(server->global_list, client);
          }
          silc_free(client_id);
@@ -2278,6 +2296,25 @@ SilcClientEntry silc_server_new_client(SilcServer server,
     snprintf(&nickname[strlen(nickname) - 1], 1, "%d", nickfail);
   }
 
+  /* If client marked as anonymous, scramble the username and hostname */
+  if (client->mode & SILC_UMODE_ANONYMOUS) {
+    char *scramble;
+
+    if (strlen(username) >= 2) {
+      username[0] = silc_rng_get_byte_fast(server->rng);
+      username[1] = silc_rng_get_byte_fast(server->rng);
+    }
+
+    scramble = silc_hash_babbleprint(server->sha1hash, username,
+                                    strlen(username));
+    scramble[5] = '@';
+    scramble[11] = '.';
+    memcpy(&scramble[16], ".silc", 5);
+    scramble[21] = '\0';
+    silc_free(username);
+    username = scramble;
+  }
+
   /* Update client entry */
   idata->status |= SILC_IDLIST_STATUS_REGISTERED;
   client->nickname = nickname;
@@ -2779,7 +2816,7 @@ void silc_server_new_id_list(SilcServer server, SilcSocketConnection sock,
      data buffer, which we will here now fetch from the original buffer. */
   new_id = silc_packet_context_alloc();
   new_id->type = SILC_PACKET_NEW_ID;
-  new_id->flags = packet->flags;
+  new_id->flags = packet->flags & (~SILC_PACKET_FLAG_LIST);
   new_id->src_id = packet->src_id;
   new_id->src_id_len = packet->src_id_len;
   new_id->src_id_type = packet->src_id_type;
@@ -2874,7 +2911,7 @@ void silc_server_new_channel(SilcServer server,
                                0, channel_id, sock->user_data, NULL, NULL, 0);
       if (!channel)
        return;
-      channel->disabled = TRUE;
+      channel->disabled = TRUE;    /* Disabled until someone JOINs */
 
       server->stat.channels++;
       if (server->server_type == SILC_ROUTER)
@@ -2909,13 +2946,15 @@ void silc_server_new_channel(SilcServer server,
          !SILC_ID_COMPARE(channel_id, server->id, server->id->ip.data_len)) {
        SilcChannelID *tmp;
        SILC_LOG_DEBUG(("Forcing the server to change Channel ID"));
-       
        if (silc_id_create_channel_id(server, server->id, server->rng, &tmp)) {
          silc_server_send_notify_channel_change(server, sock, FALSE, 
                                                 channel_id, tmp);
          silc_free(channel_id);
-         channel_id = tmp;
+         silc_free(tmp);
        }
+
+       /* Wait that server re-announces this channel */
+       return;
       }
 
       /* Create the channel with the provided Channel ID */
@@ -2927,9 +2966,16 @@ void silc_server_new_channel(SilcServer server,
        silc_free(channel_id);
        return;
       }
-      channel->disabled = TRUE;
+      channel->disabled = TRUE;    /* Disabled until someone JOINs */
+
+#if 0 /* We assume that CMODE_CHANGE notify is sent to us after this. */
+
+      /* XXX Dunno if this is supposed to be set in any server type.  If set
+        here the CMODE_CHANGE that may follow sets mode that we already
+        have, and we may loose data from the CMODE_CHANGE notify. */
       if (server_entry->server_type != SILC_BACKUP_ROUTER)
        channel->mode = silc_channel_get_mode(payload);
+#endif
 
       /* Send the new channel key to the server */
       id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
@@ -3052,6 +3098,24 @@ void silc_server_new_channel(SilcServer server,
     }
   }
 
+  /* If the sender of this packet is server and we are router we need to
+     broadcast this packet to other routers in the network. Broadcast
+     this list packet instead of multiple New Channel packets. */
+  if (server->server_type == SILC_ROUTER &&
+      sock->type == SILC_SOCKET_TYPE_SERVER &&
+      !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+    SILC_LOG_DEBUG(("Broadcasting received New Channel packet"));
+    silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
+                           packet->type, 
+                           packet->flags | SILC_PACKET_FLAG_BROADCAST,
+                           packet->buffer->data, 
+                           packet->buffer->len, FALSE);
+    silc_server_backup_send(server, sock->user_data, 
+                           packet->type, packet->flags,
+                           packet->buffer->data, packet->buffer->len, 
+                           FALSE, TRUE);
+  }
+
   silc_channel_payload_free(payload);
 }
 
@@ -3073,29 +3137,11 @@ void silc_server_new_channel_list(SilcServer server,
       server->server_type == SILC_SERVER)
     return;
 
-  /* If the sender of this packet is server and we are router we need to
-     broadcast this packet to other routers in the network. Broadcast
-     this list packet instead of multiple New Channel packets. */
-  if (server->server_type == SILC_ROUTER &&
-      sock->type == SILC_SOCKET_TYPE_SERVER &&
-      !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
-    SILC_LOG_DEBUG(("Broadcasting received New Channel List packet"));
-    silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
-                           packet->type, 
-                           packet->flags | SILC_PACKET_FLAG_BROADCAST,
-                           packet->buffer->data, 
-                           packet->buffer->len, FALSE);
-    silc_server_backup_send(server, sock->user_data, 
-                           packet->type, packet->flags,
-                           packet->buffer->data, packet->buffer->len, 
-                           FALSE, TRUE);
-  }
-
   /* Make copy of the original packet context, except for the actual
      data buffer, which we will here now fetch from the original buffer. */
   new = silc_packet_context_alloc();
   new->type = SILC_PACKET_NEW_CHANNEL;
-  new->flags = packet->flags;
+  new->flags = packet->flags & (~SILC_PACKET_FLAG_LIST);
   new->src_id = packet->src_id;
   new->src_id_len = packet->src_id_len;
   new->src_id_type = packet->src_id_type;
@@ -3345,6 +3391,8 @@ SILC_SERVER_CMD_FUNC(resume_resolve)
        silc_server_free_sock_user_data(server, sock, NULL);
       goto out;
     }
+
+    client->data.status |= SILC_IDLIST_STATUS_RESUME_RES;
   }
 
   /* Reprocess the packet */
@@ -3368,6 +3416,7 @@ void silc_server_resume_client(SilcServer server,
 {
   SilcBuffer buffer = packet->buffer, buf;
   SilcIDListData idata;
+  SilcIDCacheEntry id_cache = NULL;
   SilcClientEntry detached_client;
   SilcClientID *client_id = NULL;
   unsigned char *id_string, *auth = NULL;
@@ -3414,8 +3463,8 @@ void silc_server_resume_client(SilcServer server,
     idata = (SilcIDListData)client;
 
     /* Get entry to the client, and resolve it if we don't have it. */
-    detached_client = silc_server_get_client_resolve(server, client_id, FALSE,
-                                                    &resolved);
+    detached_client = silc_server_query_client(server, client_id, FALSE,
+                                              &resolved);
     if (!detached_client) {
       if (resolved) {
        /* The client info is being resolved. Reprocess this packet after
@@ -3451,13 +3500,15 @@ void silc_server_resume_client(SilcServer server,
       resolve = TRUE;
     if (!detached_client->nickname)
       resolve = TRUE;
+    if (detached_client->data.status & SILC_IDLIST_STATUS_RESUME_RES)
+      resolve = FALSE;
 
     if (resolve) {
       if (server->server_type == SILC_SERVER && !server->standalone) {
        /* The client info is being resolved. Reprocess this packet after
           receiving the reply to the query. */
        SILC_LOG_DEBUG(("Resolving client info"));
-       silc_server_get_client_resolve(server, client_id, TRUE, NULL);
+       silc_server_query_client(server, client_id, TRUE, NULL);
        r = silc_calloc(1, sizeof(*r));
        if (!r)
          return;
@@ -3570,6 +3621,7 @@ void silc_server_resume_client(SilcServer server,
     silc_idlist_add_data(detached_client, idata);
     detached_client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
     detached_client->data.status |= SILC_IDLIST_STATUS_RESUMED;
+    detached_client->data.status &= ~SILC_IDLIST_STATUS_RESUME_RES;
     detached_client->mode &= ~SILC_UMODE_DETACHED;
     server->stat.my_detached--;
 
@@ -3602,8 +3654,10 @@ void silc_server_resume_client(SilcServer server,
     server->stat.clients--;
     if (server->stat.cell_clients)
       server->stat.cell_clients--;
+    silc_server_remove_from_channels(server, NULL, client, FALSE, NULL, FALSE);
     silc_server_del_from_watcher_list(server, client);
-    silc_idlist_del_client(server->local_list, client);
+    if (!silc_idlist_del_client(server->local_list, client))
+      silc_idlist_del_client(server->global_list, client);
     client = detached_client;
 
     /* If the ID is not based in our ID then change it */
@@ -3737,10 +3791,12 @@ void silc_server_resume_client(SilcServer server,
 
     /* Get entry to the client, and resolve it if we don't have it. */
     detached_client = silc_idlist_find_client_by_id(server->local_list, 
-                                                   client_id, TRUE, NULL);
+                                                   client_id, TRUE,
+                                                   &id_cache);
     if (!detached_client) {
       detached_client = silc_idlist_find_client_by_id(server->global_list,
-                                                     client_id, TRUE, NULL);
+                                                     client_id, TRUE,
+                                                     &id_cache);
       if (!detached_client) {
        SILC_LOG_DEBUG(("Resuming client is unknown"));
        silc_free(client_id);
@@ -3770,10 +3826,41 @@ void silc_server_resume_client(SilcServer server,
       return;
     }
 
+    SILC_LOG_DEBUG(("Resuming detached client"));
+
+    /* 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->server_type == SILC_ROUTER &&
+       sock->type == SILC_SOCKET_TYPE_SERVER &&
+       !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+      SILC_LOG_DEBUG(("Broadcasting received Resume Client packet"));
+      silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
+                             packet->type, 
+                             packet->flags | SILC_PACKET_FLAG_BROADCAST,
+                             buffer->data, buffer->len, FALSE);
+      silc_server_backup_send(server, sock->user_data, 
+                             packet->type, packet->flags,
+                             packet->buffer->data, packet->buffer->len, 
+                             FALSE, TRUE);
+    }
+
     /* Client is detached, and now it is resumed.  Remove the detached
        mode and mark that it is resumed. */
     detached_client->mode &= ~SILC_UMODE_DETACHED;
     detached_client->data.status |= SILC_IDLIST_STATUS_RESUMED;
+    detached_client->data.status &= ~SILC_IDLIST_STATUS_LOCAL;
+    id_cache->expire = 0;
+
+    /* Update channel information regarding global clients on channel. */
+    if (server->server_type == SILC_SERVER) {
+      silc_hash_table_list(detached_client->channels, &htl);
+      while (silc_hash_table_get(&htl, NULL, (void **)&chl))
+       chl->channel->global_users = 
+         silc_server_channel_has_global(chl->channel);
+      silc_hash_table_list_reset(&htl);
+    }
+
+    silc_schedule_task_del_by_context(server->schedule, detached_client);
 
     /* Get the new owner of the resumed client */
     server_id = silc_id_str2id(packet->src_id, packet->src_id_len,
@@ -3786,11 +3873,11 @@ void silc_server_resume_client(SilcServer server,
     /* Get server entry */
     server_entry = silc_idlist_find_server_by_id(server->global_list, 
                                                 server_id, TRUE, NULL);
-    local = TRUE;
+    local = FALSE;
     if (!server_entry) {
       server_entry = silc_idlist_find_server_by_id(server->local_list, 
                                                   server_id, TRUE, NULL);
-      local = FALSE;
+      local = TRUE;
       if (!server_entry) {
        silc_free(server_id);
        silc_free(client_id);
@@ -3803,8 +3890,6 @@ void silc_server_resume_client(SilcServer server,
        server_entry->server_type == SILC_ROUTER)
       local = FALSE;
 
-    SILC_LOG_DEBUG(("Resuming detached client"));
-
     /* Change the client to correct list. */
     if (!silc_idcache_del_by_context(server->local_list->clients,
                                     detached_client))
@@ -3815,38 +3900,9 @@ void silc_server_resume_client(SilcServer server,
                     server->global_list->clients, 
                     detached_client->nickname,
                     detached_client->id, detached_client, FALSE, NULL);
-    detached_client->data.status &= ~SILC_IDLIST_STATUS_LOCAL;
-
-    /* Change the owner of the client if needed */
-    if (detached_client->router != server_entry)
-      detached_client->router = server_entry;
-
-    /* Update channel information regarding global clients on channel. */
-    if (server->server_type == SILC_SERVER) {
-      silc_hash_table_list(detached_client->channels, &htl);
-      while (silc_hash_table_get(&htl, NULL, (void **)&chl))
-       chl->channel->global_users = 
-         silc_server_channel_has_global(chl->channel);
-      silc_hash_table_list_reset(&htl);
-    }
-
-    silc_schedule_task_del_by_context(server->schedule, detached_client);
 
-    /* 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->server_type == SILC_ROUTER &&
-       sock->type == SILC_SOCKET_TYPE_SERVER &&
-       !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
-      SILC_LOG_DEBUG(("Broadcasting received Resume Client packet"));
-      silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
-                             packet->type, 
-                             packet->flags | SILC_PACKET_FLAG_BROADCAST,
-                             buffer->data, buffer->len, FALSE);
-      silc_server_backup_send(server, sock->user_data, 
-                             packet->type, packet->flags,
-                             packet->buffer->data, packet->buffer->len, 
-                             FALSE, TRUE);
-    }
+    /* Change the owner of the client */
+    detached_client->router = server_entry;
 
     silc_free(server_id);
   }