updates.
[silc.git] / apps / silcd / server.c
index dfc4022578e6302bb65671d6847e58407525f30a..f7918f7d4458ff2c71c1fc1738f47731ffea472c 100644 (file)
@@ -312,6 +312,7 @@ int silc_server_init(SilcServer server)
       if (ptr->backup_router) {
        server->server_type = SILC_BACKUP_ROUTER;
        server->backup_router = TRUE;
+       server->id_entry->server_type = SILC_BACKUP_ROUTER;
        break;
       }
       ptr = ptr->next;
@@ -891,8 +892,9 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
   SILC_LOG_DEBUG(("New server id(%s)",
                  silc_id_render(ctx->dest_id, SILC_ID_SERVER)));
 
-  /* Add the connected router to local server list */
-  id_entry = silc_idlist_add_server(server->local_list, strdup(sock->hostname),
+  /* Add the connected router to global server list */
+  id_entry = silc_idlist_add_server(server->global_list, 
+                                   strdup(sock->hostname),
                                    SILC_ROUTER, ctx->dest_id, NULL, sock);
   if (!id_entry) {
     silc_free(ctx->dest_id);
@@ -1336,13 +1338,18 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
         server. We mark ourselves as router for this server if we really
         are router. */
       new_server = 
-       silc_idlist_add_server(server->local_list, NULL,
-                              ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
-                              SILC_SERVER : SILC_ROUTER, NULL, 
-                              ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
-                              server->id_entry : 
-                              (conn->backup_router ? server->id_entry : 
-                               NULL), sock);
+       silc_idlist_add_server((ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
+                               server->local_list : (conn->backup_router ?
+                                                     server->local_list :
+                                                     server->global_list)),
+                              NULL,
+                              (ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
+                               SILC_SERVER : SILC_ROUTER), 
+                              NULL, 
+                              (ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
+                               server->id_entry : (conn->backup_router ? 
+                                                   server->id_entry : NULL)),
+                              sock);
       if (!new_server) {
        SILC_LOG_ERROR(("Could not add new server to cache"));
        silc_free(sock->user_data);
@@ -1369,10 +1376,10 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
                               conn->backup_replace_port, conn->backup_local);
 
        /* Change it back to SERVER type since that's what it really is. */
-       if (conn->backup_local) {
+       if (conn->backup_local)
          ctx->conn_type = SILC_SOCKET_TYPE_SERVER;
-         new_server->server_type = SILC_BACKUP_ROUTER;
-       }
+
+       new_server->server_type = SILC_BACKUP_ROUTER;
       }
 
       /* Check whether this connection is to be our primary router connection
@@ -1441,6 +1448,7 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
   SilcIDListData idata;
   SilcCipher cipher = NULL;
   SilcHmac hmac = NULL;
+  uint32 sequence = 0;
   int ret;
 
   if (!sock)
@@ -1541,46 +1549,14 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
   if (idata) {
     cipher = idata->receive_key;
     hmac = idata->hmac_receive;
+    sequence = idata->psn_receive;
   }
  
   /* Process the packet. This will call the parser that will then
      decrypt and parse the packet. */
-  silc_packet_receive_process(sock, cipher, hmac, silc_server_packet_parse, 
-                             server);
-}
-
-/* Callback function that the silc_packet_decrypt will call to make the
-   decision whether the packet is normal or special packet. We will 
-   return TRUE if it is normal and FALSE if it is special */
-
-static int silc_server_packet_decrypt_check(SilcPacketType packet_type,
-                                           SilcBuffer buffer,
-                                           SilcPacketContext *packet,
-                                           void *context)
-{
-  SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
-  SilcServer server = (SilcServer)parse_ctx->context;
-
-  /* Packet is normal packet, if: 
-
-     1) packet is private message packet and does not have private key set
-     2) is other packet than channel message packet
-     3) is channel message packet and remote is router and we are router 
-
-     all other packets are special packets 
-  */
-
-  if (packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
-      (buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
-    return FALSE;
-
-  if (packet_type != SILC_PACKET_CHANNEL_MESSAGE || 
-      (packet_type == SILC_PACKET_CHANNEL_MESSAGE &&
-       parse_ctx->sock->type == SILC_SOCKET_TYPE_ROUTER &&
-       server->server_type == SILC_ROUTER))
-    return TRUE;
-
-  return FALSE;
+  silc_packet_receive_process(sock, server->server_type == SILC_ROUTER ? 
+                             TRUE : FALSE, cipher, hmac, sequence, 
+                             silc_server_packet_parse, server);
 }
   
 /* Parses whole packet, received earlier. */
@@ -1596,34 +1572,18 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
 
   SILC_LOG_DEBUG(("Start"));
 
-  /* Decrypt the received packet */
-  ret = silc_packet_decrypt(idata ? idata->receive_key : NULL, 
-                           idata ? idata->hmac_receive : NULL, 
-                           packet->buffer, packet,
-                           silc_server_packet_decrypt_check, parse_ctx);
-  if (ret < 0) {
-    SILC_LOG_WARNING(("Packet decryption failed for connection "
-                     "%s:%d [%s]", sock->hostname, sock->port,  
-                     (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
-                      sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
-                      sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
-                      "Router")));
-    goto out;
-  }
-
-  if (ret == 0) {
-    /* Parse the packet. Packet type is returned. */
-    ret = silc_packet_parse(packet);
-  } else {
-    /* Parse the packet header in special way as this is "special"
-       packet type. */
-    ret = silc_packet_parse_special(packet);
-  }
+  /* Parse the packet */
+  if (parse_ctx->normal)
+    ret = silc_packet_parse(packet, idata ? idata->receive_key : NULL);
+  else
+    ret = silc_packet_parse_special(packet, idata ? idata->receive_key : NULL);
 
   /* If entry is disabled ignore what we got. */
   if (ret != SILC_PACKET_RESUME_ROUTER &&
-      idata && idata->status & SILC_IDLIST_STATUS_DISABLED)
+      idata && idata->status & SILC_IDLIST_STATUS_DISABLED) {
+    SILC_LOG_DEBUG(("Connection is disabled"));
     goto out;
+  }
 
   if (ret == SILC_PACKET_NONE)
     goto out;
@@ -1690,10 +1650,15 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
 /* Parser callback called by silc_packet_receive_process. This merely
    registers timeout that will handle the actual parsing when appropriate. */
 
-void silc_server_packet_parse(SilcPacketParserContext *parser_context)
+void silc_server_packet_parse(SilcPacketParserContext *parser_context,
+                             void *context)
 {
-  SilcServer server = (SilcServer)parser_context->context;
+  SilcServer server = (SilcServer)context;
   SilcSocketConnection sock = parser_context->sock;
+  SilcIDListData idata = (SilcIDListData)sock->user_data;
+
+  if (idata)
+    idata->psn_receive = parser_context->packet->sequence + 1;
 
   switch (sock->type) {
   case SILC_SOCKET_TYPE_UNKNOWN:
@@ -2131,7 +2096,11 @@ void silc_server_packet_parse_type(SilcServer server,
     break;
 
   case SILC_PACKET_FTP:
-    /* Ignored */
+    /* FTP packet */
+    SILC_LOG_DEBUG(("FTP packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
+    silc_server_ftp(server, sock, packet);
     break;
 
   case SILC_PACKET_RESUME_ROUTER:
@@ -2275,12 +2244,15 @@ void silc_server_free_client_data(SilcServer server,
      to the network before removing the client entry. */
   silc_server_packet_queue_purge(server, sock);
 
+  if (!client->id)
+    return;
+
   /* Send SIGNOFF notify to routers. */
   if (notify && !server->standalone && server->router)
     silc_server_send_notify_signoff(server, server->router->connection,
                                    server->server_type == SILC_SERVER ?
                                    FALSE : TRUE, client->id, signoff);
-
+    
   /* Remove client from all channels */
   if (notify)
     silc_server_remove_from_channels(server, NULL, client, 
@@ -2288,7 +2260,7 @@ void silc_server_free_client_data(SilcServer server,
   else
     silc_server_remove_from_channels(server, NULL, client, 
                                     FALSE, NULL, FALSE);
-
+    
   /* We will not delete the client entry right away. We will take it
      into history (for WHOWAS command) for 5 minutes */
   i->server = server;
@@ -2393,13 +2365,15 @@ void silc_server_free_sock_user_data(SilcServer server,
           by the primary router and went down with the router.  */
        silc_server_update_clients_by_server(server, user_data, backup_router,
                                             TRUE, TRUE);
+       silc_server_update_servers_by_server(server, user_data, backup_router);
       }
 
       /* Free the server entry */
       silc_server_backup_del(server, user_data);
       silc_server_backup_replaced_del(server, user_data);
       silc_idlist_del_data(user_data);
-      silc_idlist_del_server(server->local_list, user_data);
+      if (!silc_idlist_del_server(server->local_list, user_data))
+       silc_idlist_del_server(server->global_list, user_data);
       server->stat.my_servers--;
       server->stat.servers--;
       if (server->server_type == SILC_ROUTER)
@@ -2478,9 +2452,10 @@ void silc_server_remove_from_channels(SilcServer server,
        silc_hash_table_count(channel->user_list) < 2) {
       if (channel->rekey)
        silc_schedule_task_del_by_context(server->schedule, channel->rekey);
-      if (!silc_idlist_del_channel(server->local_list, channel))
-       silc_idlist_del_channel(server->global_list, channel);
-      server->stat.my_channels--;
+      if (silc_idlist_del_channel(server->local_list, channel))
+       server->stat.my_channels--;
+      else if (silc_idlist_del_channel(server->global_list, channel))
+       server->stat.my_channels--;
       continue;
     }
 
@@ -2529,9 +2504,10 @@ void silc_server_remove_from_channels(SilcServer server,
       }
 
       /* Remove the channel entry */
-      if (!silc_idlist_del_channel(server->local_list, channel))
-       silc_idlist_del_channel(server->global_list, channel);
-      server->stat.my_channels--;
+      if (silc_idlist_del_channel(server->local_list, channel))
+       server->stat.my_channels--;
+      else if (silc_idlist_del_channel(server->global_list, channel))
+       server->stat.my_channels--;
       continue;
     }
 
@@ -2596,10 +2572,11 @@ int silc_server_remove_from_one_channel(SilcServer server,
       silc_hash_table_count(channel->user_list) < 2) {
     if (channel->rekey)
       silc_schedule_task_del_by_context(server->schedule, channel->rekey);
-    if (!silc_idlist_del_channel(server->local_list, channel))
-      silc_idlist_del_channel(server->global_list, channel);
+    if (silc_idlist_del_channel(server->local_list, channel))
+      server->stat.my_channels--;
+    else if (silc_idlist_del_channel(server->global_list, channel))
+      server->stat.my_channels--;
     silc_buffer_free(clidp);
-    server->stat.my_channels--;
     return FALSE;
   }
 
@@ -2647,9 +2624,10 @@ int silc_server_remove_from_one_channel(SilcServer server,
     }
 
     /* Remove the channel entry */
-    if (!silc_idlist_del_channel(server->local_list, channel))
-      silc_idlist_del_channel(server->global_list, channel);
-    server->stat.my_channels--;
+    if (silc_idlist_del_channel(server->local_list, channel))
+      server->stat.my_channels--;
+    else if (silc_idlist_del_channel(server->global_list, channel))
+      server->stat.my_channels--;
     return FALSE;
   }
 
@@ -2901,8 +2879,9 @@ bool silc_server_create_channel_key(SilcServer server,
   /* Generate HMAC key from the channel key data and set it */
   if (!channel->hmac)
     silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac);
-  silc_hash_make(channel->hmac->hash, channel->key, len, hash);
-  silc_hmac_set_key(channel->hmac, hash, silc_hash_len(channel->hmac->hash));
+  silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, len, hash);
+  silc_hmac_set_key(channel->hmac, hash, 
+                   silc_hash_len(silc_hmac_get_hash(channel->hmac)));
   memset(hash, 0, sizeof(hash));
 
   if (server->server_type == SILC_ROUTER) {
@@ -3008,8 +2987,9 @@ SilcChannelEntry silc_server_save_channel_key(SilcServer server,
   /* Generate HMAC key from the channel key data and set it */
   if (!channel->hmac)
     silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac);
-  silc_hash_make(channel->hmac->hash, tmp, tmp_len, hash);
-  silc_hmac_set_key(channel->hmac, hash, silc_hash_len(channel->hmac->hash));
+  silc_hash_make(silc_hmac_get_hash(channel->hmac), tmp, tmp_len, hash);
+  silc_hmac_set_key(channel->hmac, hash, 
+                   silc_hash_len(silc_hmac_get_hash(channel->hmac)));
 
   memset(hash, 0, sizeof(hash));
   memset(tmp, 0, tmp_len);