Merged from silc_1_0_branch (second merge).
[crypto.git] / apps / silcd / packet_receive.c
index 01aa8258e905e8c91e7102c3dbb71c2f6f9809c1..ee45290f0b1b779625c1142f201f2f8bc126f9e7 100644 (file)
@@ -1087,9 +1087,10 @@ void silc_server_notify(SilcServer server,
        goto out;
 
       if (action == 0 && !channel->invite_list)
-       channel->invite_list = silc_hash_table_alloc(0, silc_hash_ptr,
-                                                    NULL, NULL, NULL,
-                                                    NULL, NULL, TRUE);
+       channel->invite_list =
+         silc_hash_table_alloc(0, silc_hash_ptr,
+                               NULL, NULL, NULL,
+                               silc_server_inviteban_destruct, channel, TRUE);
 
       /* Proces the invite action */
       silc_server_inviteban_process(server, channel->invite_list, action,
@@ -1305,9 +1306,22 @@ void silc_server_notify(SilcServer server,
     }
     silc_free(server_id);
 
-    /* Sending SERVER_SIGNOFF is not right way to signoff local connection */
-    if (SILC_IS_LOCAL(server_entry))
+    /* For local entrys SERVER_SIGNOFF is processed only on backup router.
+       It is possible that router sends server signoff for a server.  If
+       backup router has it as local connection it will be closed. */
+    if (SILC_IS_LOCAL(server_entry)) {
+      if (server->server_type == SILC_BACKUP_ROUTER) {
+       sock = server_entry->connection;
+       SILC_LOG_DEBUG(("Closing connection %s after SERVER_SIGNOFF",
+                      sock->hostname));
+       SILC_SET_DISCONNECTING(sock);
+       if (sock->user_data)
+         silc_server_free_sock_user_data(server, sock, NULL);
+       silc_server_close_connection(server, sock);
+      }
+
       break;
+    }
 
     /* Remove all servers that are originated from this server, and
        remove the clients of those servers too. */
@@ -1661,9 +1675,10 @@ void silc_server_notify(SilcServer server,
        goto out;
 
       if (action == 0 && !channel->ban_list)
-       channel->ban_list = silc_hash_table_alloc(0, silc_hash_ptr,
-                                                 NULL, NULL, NULL,
-                                                 NULL, NULL, TRUE);
+       channel->ban_list =
+         silc_hash_table_alloc(0, silc_hash_ptr,
+                               NULL, NULL, NULL,
+                               silc_server_inviteban_destruct, channel, TRUE);
 
       /* Proces the ban action */
       silc_server_inviteban_process(server, channel->ban_list, action,
@@ -2094,9 +2109,12 @@ void silc_server_channel_key(SilcServer server,
 
   /* Save the channel key */
   channel = silc_server_save_channel_key(server, buffer, NULL);
-  if (!channel)
+  if (!channel) {
+    SILC_LOG_ERROR(("Bad channel key from %s (%s)",
+                   sock->hostname, sock->ip));
     return;
-
+  }
+    
   /* Distribute the key to everybody who is on the channel. If we are router
      we will also send it to locally connected servers. */
   silc_server_send_channel_key(server, sock, channel, FALSE);
@@ -2146,6 +2164,16 @@ SilcClientEntry silc_server_new_client(SilcServer server,
     return NULL;
   }
 
+  /* Make sure this client hasn't registered already */
+  if (idata->status & SILC_IDLIST_STATUS_REGISTERED) {
+    silc_server_disconnect_remote(server, sock, 
+                                 SILC_STATUS_ERR_OPERATION_ALLOWED,
+                                 "Too many registrations");
+    if (sock->user_data)
+      silc_server_free_sock_user_data(server, sock, NULL);
+    return NULL;
+  }
+
   /* Parse incoming packet */
   ret = silc_buffer_unformat(buffer,
                             SILC_STR_UI16_NSTRING_ALLOC(&username, 
@@ -2395,6 +2423,16 @@ SilcServerEntry silc_server_new_server(SilcServer server,
     local = FALSE;
   }
 
+  /* Make sure this server hasn't registered already */
+  if (idata->status & SILC_IDLIST_STATUS_REGISTERED) {
+    silc_server_disconnect_remote(server, sock, 
+                                 SILC_STATUS_ERR_OPERATION_ALLOWED,
+                                 "Too many registrations");
+    if (sock->user_data)
+      silc_server_free_sock_user_data(server, sock, NULL);
+    return NULL;
+  }
+
   /* Parse the incoming packet */
   ret = silc_buffer_unformat(buffer,
                             SILC_STR_UI16_NSTRING_ALLOC(&id_string, &id_len),
@@ -2456,19 +2494,38 @@ SilcServerEntry silc_server_new_server(SilcServer server,
   server_entry = silc_idlist_find_server_by_id(server->local_list, 
                                               server_id, TRUE, NULL);
   if (server_entry) {
-    silc_idcache_del_by_context(server->local_list->servers, server_entry);
+    if (SILC_IS_LOCAL(server_entry)) {
+      silc_server_disconnect_remote(server, server_entry->connection, 
+                                   SILC_STATUS_ERR_OPERATION_ALLOWED,
+                                   "Too many registrations");
+      if (((SilcSocketConnection)server_entry->connection)->user_data)
+       silc_server_free_sock_user_data(server, sock, NULL);
+    } else {
+      silc_idcache_del_by_context(server->local_list->servers, server_entry);
+    }
   } else {
     server_entry = silc_idlist_find_server_by_id(server->global_list, 
                                                 server_id, TRUE, NULL);
-    if (server_entry) 
-      silc_idcache_del_by_context(server->global_list->servers, server_entry);
+    if (server_entry) {
+      if (SILC_IS_LOCAL(server_entry)) {
+       silc_server_disconnect_remote(server, server_entry->connection, 
+                                     SILC_STATUS_ERR_OPERATION_ALLOWED,
+                                     "Too many registrations");
+       if (((SilcSocketConnection)server_entry->connection)->user_data)
+         silc_server_free_sock_user_data(server, server_entry->connection,
+                                         NULL);
+      } else {
+       silc_idcache_del_by_context(server->global_list->servers,
+                                   server_entry);
+      }
+    }
   }
 
   /* Update server entry */
   idata->status |= SILC_IDLIST_STATUS_REGISTERED;
   new_server->server_name = server_name;
   new_server->id = server_id;
-  
+
   SILC_LOG_DEBUG(("New server id(%s)",
                  silc_id_render(server_id, SILC_ID_SERVER)));
 
@@ -3920,5 +3977,4 @@ void silc_server_resume_client(SilcServer server,
   }
 
   silc_free(client_id);
-    silc_idlist_del_data(detached_client);
 }