updates.
[silc.git] / apps / silcd / server.c
index ae8592c432d80ec1ce3d28b4631b54256ef37363..869d6450b12cd80874a585ee10320051b5a8b92b 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;
@@ -1447,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)
@@ -1547,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. */
@@ -1602,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;
@@ -1696,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:
@@ -2281,12 +2240,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, 
@@ -2294,7 +2256,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;
@@ -2399,6 +2361,7 @@ 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 */
@@ -2485,9 +2448,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;
     }
 
@@ -2536,9 +2500,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;
     }
 
@@ -2603,10 +2568,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;
   }
 
@@ -2654,9 +2620,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;
   }
 
@@ -2908,8 +2875,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) {
@@ -3015,8 +2983,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);