Merge commit 'origin/silc.1.1.branch'
[silc.git] / apps / silcd / server.c
index bb5b3b279e819a72d240fa388f5b8fb7610d0e0a..f03581bcd081bbe9135d07e59bf6ba2f103be4a4 100644 (file)
@@ -201,6 +201,8 @@ static void silc_server_packet_eos(SilcPacketEngine engine,
 
   if (server->router_conn && server->router_conn->sock == stream &&
       !server->router && server->standalone) {
+    if (idata->sconn && idata->sconn->callback)
+      (*idata->sconn->callback)(server, NULL, idata->sconn->callback_context);
     silc_server_create_connections(server);
     silc_server_free_sock_user_data(server, stream, NULL);
   } else {
@@ -212,6 +214,8 @@ static void silc_server_packet_eos(SilcPacketEngine engine,
         server->backup_closed = TRUE;
     }
 
+    if (idata->sconn && idata->sconn->callback)
+      (*idata->sconn->callback)(server, NULL, idata->sconn->callback_context);
     silc_server_free_sock_user_data(server, stream, NULL);
   }
 
@@ -239,6 +243,8 @@ SILC_TASK_CALLBACK(silc_server_packet_error_timeout)
         server->backup_closed = TRUE;
     }
 
+    if (idata->sconn && idata->sconn->callback)
+      (*idata->sconn->callback)(server, NULL, idata->sconn->callback_context);
     silc_server_free_sock_user_data(server, stream, NULL);
   }
 
@@ -695,6 +701,10 @@ void silc_server_free(SilcServer server)
   silc_skr_free(server->repository);
   silc_packet_engine_stop(server->packet_engine);
 
+  silc_schedule_task_del_by_context(server->schedule, server);
+  silc_schedule_uninit(server->schedule);
+  server->schedule = NULL;
+
   silc_free(server->local_list);
   silc_free(server->global_list);
   silc_free(server->server_name);
@@ -929,7 +939,6 @@ SilcBool silc_server_init(SilcServer server)
   } else {
     server->stat.routers = 1;
   }
-
   /* If we are normal server we'll retrieve network statisticial information
      once in a while from the router. */
   if (server->server_type != SILC_ROUTER)
@@ -1263,6 +1272,8 @@ SILC_TASK_CALLBACK(silc_server_purge_expired_clients)
 
   silc_dlist_start(server->expired_clients);
   while ((client = silc_dlist_get(server->expired_clients))) {
+      continue;
+
     /* For unregistered clients the created timestamp is actually
        unregistered timestamp.  Make sure client remains in history
        at least 500 seconds. */
@@ -1322,7 +1333,8 @@ void silc_server_create_connection(SilcServer server,
   sconn->no_conf = dynamic;
   sconn->server = server;
 
-  SILC_LOG_DEBUG(("Created connection %p", sconn));
+  SILC_LOG_DEBUG(("Created connection %p to %s:%d", sconn,
+                 remote_host, port));
 
   silc_schedule_task_add_timeout(server->schedule, silc_server_connect_router,
                                 sconn, 0, 0);
@@ -1366,8 +1378,6 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
     if (sconn->callback)
       (*sconn->callback)(server, NULL, sconn->callback_context);
     silc_server_free_sock_user_data(server, sconn->sock, NULL);
-    silc_server_disconnect_remote(server, sconn->sock,
-                                 SILC_STATUS_ERR_AUTH_FAILED, NULL);
     return;
   }
 
@@ -1389,11 +1399,11 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
                                      strdup(sconn->remote_host),
                                      SILC_SERVER, NULL, NULL, sconn->sock);
     if (!id_entry) {
+      silc_server_disconnect_remote(server, sconn->sock,
+                                   SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
       if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
       silc_server_free_sock_user_data(server, sconn->sock, NULL);
-      silc_server_disconnect_remote(server, sconn->sock,
-                                   SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
       return;
     }
 
@@ -1418,11 +1428,11 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
                             SILC_STR_DATA(server->server_name,
                                           strlen(server->server_name)),
                             SILC_STR_END)) {
+      silc_server_disconnect_remote(server, sconn->sock,
+                                   SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
       if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
       silc_server_free_sock_user_data(server, sconn->sock, NULL);
-      silc_server_disconnect_remote(server, sconn->sock,
-                                   SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
       return;
     }
 
@@ -1468,8 +1478,6 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
       if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
       silc_server_free_sock_user_data(server, sconn->sock, NULL);
-      silc_server_disconnect_remote(server, sconn->sock,
-                                   SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
       return;
     }
 
@@ -1479,6 +1487,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
     idata->status |= (SILC_IDLIST_STATUS_REGISTERED |
                      SILC_IDLIST_STATUS_LOCAL);
     idata->sconn = sconn;
+    idata->sconn->callback = NULL;
 
     /* Statistics */
     server->stat.my_routers++;
@@ -1529,6 +1538,8 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
        /* We already have primary router.  Disconnect this connection */
        SILC_LOG_DEBUG(("We already have primary router, disconnect"));
        silc_idlist_del_server(server->global_list, id_entry);
+       silc_server_disconnect_remote(server, sconn->sock,
+                                     SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
        if (sconn->callback)
          (*sconn->callback)(server, NULL, sconn->callback_context);
        silc_server_free_sock_user_data(server, sconn->sock, NULL);
@@ -1547,11 +1558,11 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
     break;
 
   default:
+    silc_server_disconnect_remote(server, sconn->sock,
+                                 SILC_STATUS_ERR_AUTH_FAILED, NULL);
     if (sconn->callback)
       (*sconn->callback)(server, NULL, sconn->callback_context);
     silc_server_free_sock_user_data(server, sconn->sock, NULL);
-    silc_server_disconnect_remote(server, sconn->sock,
-                                 SILC_STATUS_ERR_AUTH_FAILED, NULL);
     return;
   }
 
@@ -1591,9 +1602,9 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
 {
   SilcPacketStream sock = context;
   SilcUnknownEntry entry = silc_packet_get_context(sock);
-  SilcServerConnection sconn = entry->data.sconn;
-  SilcServer server = entry->server;
-  SilcServerConfigRouter *conn = sconn->conn.ref_ptr;
+  SilcServerConnection sconn;
+  SilcServer server;
+  SilcServerConfigRouter *conn;
   SilcAuthMethod auth_meth = SILC_AUTH_NONE;
   void *auth_data = NULL;
   SilcUInt32 auth_data_len = 0;
@@ -1602,10 +1613,13 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
   SilcHmac hmac_send, hmac_receive;
   SilcHash hash;
 
-  SILC_LOG_DEBUG(("Connection %p, SKE completed, entry %p", sconn, entry));
-
+  server = entry->server;
+  sconn = entry->data.sconn;
+  conn = sconn->conn.ref_ptr;
   entry->op = NULL;
 
+  SILC_LOG_DEBUG(("Connection %p, SKE completed, entry %p", sconn, entry));
+
   if (status != SILC_SKE_STATUS_OK) {
     /* SKE failed */
     SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
@@ -1624,8 +1638,6 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
     if (sconn->callback)
       (*sconn->callback)(server, NULL, sconn->callback_context);
     silc_server_free_sock_user_data(server, sconn->sock, NULL);
-    silc_server_disconnect_remote(server, sconn->sock,
-                                 SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
     return;
   }
 
@@ -1646,11 +1658,11 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
     }
 
     /* Error setting keys */
+    silc_server_disconnect_remote(server, sconn->sock,
+                                 SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
     if (sconn->callback)
       (*sconn->callback)(server, NULL, sconn->callback_context);
     silc_server_free_sock_user_data(server, sconn->sock, NULL);
-    silc_server_disconnect_remote(server, sconn->sock,
-                                 SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
     return;
   }
   silc_packet_set_keys(sconn->sock, send_key, receive_key, hmac_send,
@@ -1673,11 +1685,11 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
     }
 
     /** Error allocating auth protocol */
+    silc_server_disconnect_remote(server, sconn->sock,
+                                 SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
     if (sconn->callback)
       (*sconn->callback)(server, NULL, sconn->callback_context);
     silc_server_free_sock_user_data(server, sconn->sock, NULL);
-    silc_server_disconnect_remote(server, sconn->sock,
-                                 SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
     return;
   }
 
@@ -2097,7 +2109,6 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router)
     sconn->no_reconnect = param->reconnect_keep_trying == FALSE;
 
     SILC_LOG_DEBUG(("Created connection %p", sconn));
-
     if (!server->router_conn && !sconn->backup)
       server->router_conn = sconn;
 
@@ -2595,6 +2606,7 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
   sconn->remote_port = port;
   silc_dlist_add(server->conns, sconn);
   idata->sconn = sconn;
+  idata->sconn->callback = NULL;
   idata->last_receive = time(NULL);
 
   /* Add the common data structure to the ID entry. */
@@ -2809,6 +2821,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status,
   entry->port = port;
   entry->server = server;
   entry->data.conn_type = SILC_CONN_UNKNOWN;
+  entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
   silc_packet_set_context(packet_stream, entry);
 
   SILC_LOG_DEBUG(("Created unknown connection %p", entry));
@@ -3003,8 +3016,6 @@ void silc_server_close_connection(SilcServer server,
   SilcUInt16 port;
 
   if (!silc_packet_stream_is_valid(sock))
-    return;
-
   memset(tmp, 0, sizeof(tmp));
   //  silc_socket_get_error(sock, tmp, sizeof(tmp));
   silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),