Added preliminary support for non-backup-aware servers in cell
authorPekka Riikonen <priikone@silcnet.org>
Tue, 25 Jun 2002 21:43:18 +0000 (21:43 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 25 Jun 2002 21:43:18 +0000 (21:43 +0000)
for backup router.
Fixed version string parsing crash.
Fixed NICK_CHANGE notify crash in client library.

15 files changed:
CHANGES
TODO
apps/silcd/idlist.c
apps/silcd/packet_send.c
apps/silcd/server.c
apps/silcd/server.h
apps/silcd/server_backup.c
apps/silcd/server_internal.h
apps/silcd/server_util.c
apps/silcd/server_util.h
apps/silcd/serverconfig.c
apps/silcd/serverconfig.h
lib/silcclient/client_notify.c
lib/silcutil/silcconfig.c
lib/silcutil/silcutil.c

diff --git a/CHANGES b/CHANGES
index d0b13bfa43e3b3f349b10058aa6e7ba5bc8b2344..c046e6276c6d44e9a03fc1c52a201e182a9c68c6 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,32 @@
+Tue Jun 25 18:47:39 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
+
+       * Enable all local server connections before updating client
+         caches when we've become backup router.  Otherwise, signoff
+         packets may not reach the clients.  Affected files are
+         silcd/server.c and silcd/server_util.[ch].
+
+       * Fixed a bug in version string parsing which could crash
+         the program with specially formatted version string.
+         Bug reported and patch provided by Ville Räsänen.  Affected
+         file lib/silcutil/silcutil.c.
+
+       * Handle the disconnection immediately when DISCONNECT
+         packet is received in server.  Affected file silcd/server.c.
+
+       * Primary router now waits a short time (10 seconds) for
+         backup router connection before accepting any other
+         connection (except local).  Affected file silcd/server.c,
+         serverconfig.[ch].
+
+       * Fixed a crash in client libary in NICK_CHANGE notify when
+         NICK_CHANGE arrived for client entry we are resolving
+         currently.  Affected file lib/silcclient/client_notify.c.
+
+       * Call the sconn->callback completion even if error had
+         occurred.  Start reconnecting always if connection to
+         primary router fails during backup router protocol.
+         Affected files silcd/server.c and server_backup.c.
+
 Mon Jun 24 17:47:52 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
 
        * Added functions silc_server_send_opers and
 Mon Jun 24 17:47:52 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
 
        * Added functions silc_server_send_opers and
diff --git a/TODO b/TODO
index 48ae543a37173dd784f48d814de01fe62fcff640..c01886b18d0de35ed8aba4ae16374db24ea2e271 100644 (file)
--- a/TODO
+++ b/TODO
@@ -27,6 +27,9 @@ TODO/bugs In SILC Server
    the core library, client and server.  Maybe implementations of
    RFC 2425 and RFC 2426 to make it complete.
 
    the core library, client and server.  Maybe implementations of
    RFC 2425 and RFC 2426 to make it complete.
 
+ o Add special handling in router and server for "connection timed out"
+   error.  Be optimistic.
+
  o Backup router related issues (Fix this to 0.9.x):
 
        o Complete backup router support with standalone router
  o Backup router related issues (Fix this to 0.9.x):
 
        o Complete backup router support with standalone router
@@ -35,6 +38,11 @@ TODO/bugs In SILC Server
          cell use it.  When primary goes down, also those that are
          not using it (are not connected locally) are signoffed.
 
          cell use it.  When primary goes down, also those that are
          not using it (are not connected locally) are signoffed.
 
+         o When primary goes down and removing clients of non-backup
+           aware server the SERVER_SIGNOFF includes the router's ID
+           not the server's ID, which it should include.  The notify
+           is sent by backup.
+
        o Testing
 
  o Add a timeout to handling incoming JOIN commands.  It should be 
        o Testing
 
  o Add a timeout to handling incoming JOIN commands.  It should be 
index c9599deb2ed21ff1236496e9a8007689dc81a23e..80d1e91e2f959687957de5e885e172153951464b 100644 (file)
@@ -290,13 +290,14 @@ silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
 
 int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry)
 {
 
 int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry)
 {
-  SILC_LOG_DEBUG(("Start"));
-
   if (entry) {
     /* Remove from cache */
     if (!silc_idcache_del_by_context(id_list->servers, entry))
       return FALSE;
 
   if (entry) {
     /* Remove from cache */
     if (!silc_idcache_del_by_context(id_list->servers, entry))
       return FALSE;
 
+    SILC_LOG_DEBUG(("Deleting server %s", entry->server_name ?
+                   entry->server_name : ""));
+
     /* Free data */
     silc_free(entry->server_name);
     silc_free(entry->id);
     /* Free data */
     silc_free(entry->server_name);
     silc_free(entry->id);
index 5a60a9f9c00d7fb648876c2808f16e84143cf31a..b159c9314a66ea41108ddb1082739c8efc421b7c 100644 (file)
@@ -97,8 +97,10 @@ void silc_server_packet_send(SilcServer server,
     return;
 
   /* If entry is disabled do not sent anything. */
     return;
 
   /* If entry is disabled do not sent anything. */
-  if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED)
+  if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED) {
+    SILC_LOG_DEBUG(("Connection is disabled"));
     return;
     return;
+  }
 
   /* Get data used in the packet sending, keys and stuff */
   switch(sock->type) {
 
   /* Get data used in the packet sending, keys and stuff */
   switch(sock->type) {
@@ -157,8 +159,10 @@ void silc_server_packet_send_dest(SilcServer server,
   idata = (SilcIDListData)sock->user_data;
 
   /* If entry is disabled do not sent anything. */
   idata = (SilcIDListData)sock->user_data;
 
   /* If entry is disabled do not sent anything. */
-  if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED)
+  if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED) {
+    SILC_LOG_DEBUG(("Connection is disabled"));
     return;
     return;
+  }
 
   SILC_LOG_DEBUG(("Sending %s packet", silc_get_packet_name(type)));
 
 
   SILC_LOG_DEBUG(("Sending %s packet", silc_get_packet_name(type)));
 
index 15c1263c6e1bc3b22a0588fa1d503cc3e9485646..ebb3e811fc4b5f1184ed35882db0b7dd83a8127d 100644 (file)
@@ -673,6 +673,11 @@ void silc_server_stop(SilcServer server)
       if (!server->sockets[i])
        continue;
       if (!SILC_IS_LISTENER(server->sockets[i])) {
       if (!server->sockets[i])
        continue;
       if (!SILC_IS_LISTENER(server->sockets[i])) {
+       SilcIDListData idata = server->sockets[i]->user_data;
+
+       if (idata)
+         idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
+
        silc_schedule_task_del_by_context(server->schedule,
                                          server->sockets[i]);
        silc_server_disconnect_remote(server, server->sockets[i], 
        silc_schedule_task_del_by_context(server->schedule,
                                          server->sockets[i]);
        silc_server_disconnect_remote(server, server->sockets[i], 
@@ -920,6 +925,10 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router)
                    ptr->initiator ? "Initiator" : "Responder",
                    ptr->host, ptr->port));
 
                    ptr->initiator ? "Initiator" : "Responder",
                    ptr->host, ptr->port));
 
+    if (server->server_type == SILC_ROUTER && ptr->backup_router &&
+       ptr->initiator == FALSE && !server->backup_router)
+      server->wait_backup = TRUE;
+
     if (ptr->initiator) {
       /* Check whether we are connected to this host already */
       if (silc_server_num_sockets_by_remote(server, 
     if (ptr->initiator) {
       /* Check whether we are connected to this host already */
       if (silc_server_num_sockets_by_remote(server, 
@@ -995,6 +1004,11 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
                             SILC_TASK_PRI_NORMAL);
       return;
     }
                             SILC_TASK_PRI_NORMAL);
       return;
     }
+
+    /* Call completion to indicate error */
+    if (sconn->callback)
+      (*sconn->callback)(server, NULL, sconn->callback_context);
+
     silc_server_config_unref(&sconn->conn);
     silc_free(sconn->remote_host);
     silc_free(sconn->backup_replace_ip);
     silc_server_config_unref(&sconn->conn);
     silc_free(sconn->remote_host);
     silc_free(sconn->backup_replace_ip);
@@ -1035,6 +1049,11 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
                             SILC_TASK_PRI_NORMAL);
       return;
     }
                             SILC_TASK_PRI_NORMAL);
       return;
     }
+
+    /* Call completion to indicate error */
+    if (sconn->callback)
+      (*sconn->callback)(server, NULL, sconn->callback_context);
+
     silc_server_config_unref(&sconn->conn);
     silc_free(sconn->remote_host);
     silc_free(sconn->backup_replace_ip);
     silc_server_config_unref(&sconn->conn);
     silc_free(sconn->remote_host);
     silc_free(sconn->backup_replace_ip);
@@ -1140,7 +1159,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
   SilcServer server = (SilcServer)ctx->server;
   SilcServerConnection sconn = (SilcServerConnection)ctx->context;
   SilcSocketConnection sock = ctx->sock;
   SilcServer server = (SilcServer)ctx->server;
   SilcServerConnection sconn = (SilcServerConnection)ctx->context;
   SilcSocketConnection sock = ctx->sock;
-  SilcServerEntry id_entry;
+  SilcServerEntry id_entry = NULL;
   SilcBuffer packet;
   SilcServerHBContext hb_context;
   unsigned char *id_string;
   SilcBuffer packet;
   SilcServerHBContext hb_context;
   unsigned char *id_string;
@@ -1235,7 +1254,8 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
   sock->user_data = (void *)id_entry;
   sock->type = SILC_SOCKET_TYPE_ROUTER;
   idata = (SilcIDListData)sock->user_data;
   sock->user_data = (void *)id_entry;
   sock->type = SILC_SOCKET_TYPE_ROUTER;
   idata = (SilcIDListData)sock->user_data;
-  idata->status |= SILC_IDLIST_STATUS_REGISTERED;
+  idata->status |= (SILC_IDLIST_STATUS_REGISTERED |
+                   SILC_IDLIST_STATUS_LOCAL);
 
   conn = sconn->conn.ref_ptr;
   param = &server->config->param;
 
   conn = sconn->conn.ref_ptr;
   param = &server->config->param;
@@ -1287,12 +1307,12 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
 
   sock->protocol = NULL;
 
 
   sock->protocol = NULL;
 
+ out:
   /* Call the completion callback to indicate that we've connected to
      the router */
   if (sconn->callback)
     (*sconn->callback)(server, id_entry, sconn->callback_context);
 
   /* Call the completion callback to indicate that we've connected to
      the router */
   if (sconn->callback)
     (*sconn->callback)(server, id_entry, sconn->callback_context);
 
- out:
   /* Free the temporary connection data context */
   if (sconn) {
     silc_server_config_unref(&sconn->conn);
   /* Free the temporary connection data context */
   if (sconn) {
     silc_server_config_unref(&sconn->conn);
@@ -1618,6 +1638,14 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_second)
                           SILC_TASK_PRI_LOW);
 }
 
                           SILC_TASK_PRI_LOW);
 }
 
+/* After this is called, server don't wait for backup router anymore */
+
+SILC_TASK_CALLBACK(silc_server_backup_router_wait)
+{
+  SilcServer server = context;
+  server->wait_backup = FALSE;
+}
+
 /* Final part of accepting new connection. The connection has now
    been authenticated and keys has been exchanged. We also know whether
    this is client or server connection. */
 /* Final part of accepting new connection. The connection has now
    been authenticated and keys has been exchanged. We also know whether
    this is client or server connection. */
@@ -1673,6 +1701,36 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
        goto out;
       }
 
        goto out;
       }
 
+      /* If we are primary router and we have backup router configured
+        but it has not connected to use yet, do not accept any other
+        connection. */
+      if (server->wait_backup && server->server_type == SILC_ROUTER &&
+         !server->backup_router) {
+       SilcServerConfigRouter *router;
+       router = silc_server_config_get_backup_router(server);
+       if (router && strcmp(server->config->server_info->primary->server_ip,
+                            sock->ip) &&
+           silc_server_find_socket_by_host(server,
+                                           SILC_SOCKET_TYPE_SERVER,
+                                           router->backup_replace_ip, 0)) {
+         SILC_LOG_INFO(("Will not accept connections because we do "
+                        "not have backup router connection established"));
+         silc_server_disconnect_remote(server, sock, 
+                                       SILC_STATUS_ERR_PERM_DENIED,
+                                       "We do not have connection to backup "
+                                       "router established, try later");
+         silc_free(sock->user_data);
+         server->stat.auth_failures++;
+
+         /* From here on, wait 10 seconds for the backup router to appear. */
+         silc_schedule_task_add(server->schedule, 0,
+                                silc_server_backup_router_wait,
+                                (void *)server, 10, 0,
+                                SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+         goto out;
+       }
+      }
+
       SILC_LOG_DEBUG(("Remote host is client"));
       SILC_LOG_INFO(("Connection %s (%s) is client", sock->hostname,
                     sock->ip));
       SILC_LOG_DEBUG(("Remote host is client"));
       SILC_LOG_INFO(("Connection %s (%s) is client", sock->hostname,
                     sock->ip));
@@ -1780,6 +1838,36 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
        }
       }
 
        }
       }
 
+      /* If we are primary router and we have backup router configured
+        but it has not connected to use yet, do not accept any other
+        connection. */
+      if (server->wait_backup && server->server_type == SILC_ROUTER &&
+         !server->backup_router && !backup_router) {
+       SilcServerConfigRouter *router;
+       router = silc_server_config_get_backup_router(server);
+       if (router && strcmp(server->config->server_info->primary->server_ip,
+                            sock->ip) &&
+           silc_server_find_socket_by_host(server,
+                                           SILC_SOCKET_TYPE_SERVER,
+                                           router->backup_replace_ip, 0)) {
+         SILC_LOG_INFO(("Will not accept connections because we do "
+                        "not have backup router connection established"));
+         silc_server_disconnect_remote(server, sock, 
+                                       SILC_STATUS_ERR_PERM_DENIED,
+                                       "We do not have connection to backup "
+                                       "router established, try later");
+         silc_free(sock->user_data);
+         server->stat.auth_failures++;
+
+         /* From here on, wait 10 seconds for the backup router to appear. */
+         silc_schedule_task_add(server->schedule, 0,
+                                silc_server_backup_router_wait,
+                                (void *)server, 10, 0,
+                                SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+         goto out;
+       }
+      }
+
       SILC_LOG_DEBUG(("Remote host is %s",
                      ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
                      "server" : (backup_router ?
       SILC_LOG_DEBUG(("Remote host is %s",
                      ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
                      "server" : (backup_router ?
@@ -1829,6 +1917,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
          ctx->conn_type = SILC_SOCKET_TYPE_SERVER;
 
        new_server->server_type = SILC_BACKUP_ROUTER;
          ctx->conn_type = SILC_SOCKET_TYPE_SERVER;
 
        new_server->server_type = SILC_BACKUP_ROUTER;
+       server->wait_backup = FALSE;
       }
 
       /* Statistics */
       }
 
       /* Statistics */
@@ -2076,7 +2165,7 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
   /* Check that the the current client ID is same as in the client's packet. */
   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
     SilcClientEntry client = (SilcClientEntry)sock->user_data;
   /* Check that the the current client ID is same as in the client's packet. */
   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
     SilcClientEntry client = (SilcClientEntry)sock->user_data;
-    if (client && client->id) {
+    if (client && client->id && packet->src_id) {
       void *id = silc_id_str2id(packet->src_id, packet->src_id_len,
                                packet->src_id_type);
       if (!id || !SILC_ID_CLIENT_COMPARE(client->id, id)) {
       void *id = silc_id_str2id(packet->src_id, packet->src_id_len,
                                packet->src_id_type);
       if (!id || !SILC_ID_CLIENT_COMPARE(client->id, id)) {
@@ -2091,7 +2180,7 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
   if (server->server_type == SILC_ROUTER) {
     /* Route the packet if it is not destined to us. Other ID types but
        server are handled separately after processing them. */
   if (server->server_type == SILC_ROUTER) {
     /* Route the packet if it is not destined to us. Other ID types but
        server are handled separately after processing them. */
-    if (!(packet->flags & SILC_PACKET_FLAG_BROADCAST) &&
+    if (packet->dst_id && !(packet->flags & SILC_PACKET_FLAG_BROADCAST) &&
        packet->dst_id_type == SILC_ID_SERVER &&
        sock->type != SILC_SOCKET_TYPE_CLIENT &&
        memcmp(packet->dst_id, server->id_string, server->id_string_len)) {
        packet->dst_id_type == SILC_ID_SERVER &&
        sock->type != SILC_SOCKET_TYPE_CLIENT &&
        memcmp(packet->dst_id, server->id_string, server->id_string_len)) {
@@ -2230,6 +2319,11 @@ void silc_server_packet_parse_type(SilcServer server,
                     silc_get_status_message(status), status,
                     message ? message : ""));
       silc_free(message);
                     silc_get_status_message(status), status,
                     message ? message : ""));
       silc_free(message);
+
+      /* Handle the disconnection from our end too */
+      if (sock->user_data && SILC_IS_LOCAL(sock->user_data))
+       silc_server_free_sock_user_data(server, sock, NULL);
+      silc_server_close_connection(server, sock);
     }
     break;
 
     }
     break;
 
@@ -2660,7 +2754,10 @@ void silc_server_close_connection(SilcServer server,
                                  SilcSocketConnection sock)
 {
   if (!server->sockets[sock->sock] && SILC_IS_DISCONNECTED(sock)) {
                                  SilcSocketConnection sock)
 {
   if (!server->sockets[sock->sock] && SILC_IS_DISCONNECTED(sock)) {
-    silc_socket_free(sock);
+    silc_schedule_task_add(server->schedule, 0,
+                          silc_server_close_connection_final,
+                          (void *)sock, 0, 1, SILC_TASK_TIMEOUT,
+                          SILC_TASK_PRI_NORMAL);
     return;
   }
 
     return;
   }
 
@@ -2895,7 +2992,7 @@ void silc_server_free_sock_user_data(SilcServer server,
            server->router_connect = time(0);
            server->backup_primary = TRUE;
          } else {
            server->router_connect = time(0);
            server->backup_primary = TRUE;
          } else {
-           SILC_LOG_INFO(("We are now new router in this cell"));
+           SILC_LOG_INFO(("We are now new primary router in this cell"));
            server->id_entry->router = NULL;
            server->router = NULL;
            server->standalone = TRUE;
            server->id_entry->router = NULL;
            server->router = NULL;
            server->standalone = TRUE;
@@ -2942,10 +3039,10 @@ void silc_server_free_sock_user_data(SilcServer server,
        /* Update the client entries of this server to the new backup
           router. This also removes the clients that *really* was owned
           by the primary router and went down with the router.  */
        /* Update the client entries of this server to the new backup
           router. This also removes the clients that *really* was owned
           by the primary router and went down with the router.  */
+       silc_server_local_servers_toggle_enabled(server, TRUE);
        silc_server_update_clients_by_server(server, user_data, backup_router,
                                             TRUE, TRUE);
        silc_server_update_clients_by_server(server, user_data, backup_router,
                                             TRUE, TRUE);
-       silc_server_update_servers_by_server(server, user_data, backup_router,
-                                            TRUE);
+       silc_server_update_servers_by_server(server, user_data, backup_router);
        if (server->server_type == SILC_SERVER)
          silc_server_update_channels_by_server(server, user_data,
                                                backup_router);
        if (server->server_type == SILC_SERVER)
          silc_server_update_channels_by_server(server, user_data,
                                                backup_router);
@@ -4082,13 +4179,12 @@ void silc_server_announce_get_channels(SilcServer server,
        (*channel_topics)[i] = NULL;
        silc_server_announce_get_channel_topic(server, channel,
                                               &(*channel_topics)[i]);
        (*channel_topics)[i] = NULL;
        silc_server_announce_get_channel_topic(server, channel,
                                               &(*channel_topics)[i]);
+       (*channel_users_modes_c)++;
        i++;
 
        if (!silc_idcache_list_next(list, &id_cache))
          break;
       }
        i++;
 
        if (!silc_idcache_list_next(list, &id_cache))
          break;
       }
-
-      *channel_users_modes_c += i;
     }
 
     silc_idcache_list_free(list);
     }
 
     silc_idcache_list_free(list);
index 5ba6a0bacb417627446b13b14cd52b18a2a5c247..19828bda6c8842c28140dcb97acffd543f8dabec 100644 (file)
@@ -26,7 +26,7 @@ typedef struct SilcServerBackupStruct *SilcServerBackup;
 
 /* Callback function that is called after the key exchange and connection
    authentication protocols has been completed with a remote router. The
 
 /* Callback function that is called after the key exchange and connection
    authentication protocols has been completed with a remote router. The
-   `server_entry' is the remote router entry. */
+   `server_entry' is the remote router entry or NULL on error. */
 typedef void (*SilcServerConnectRouterCallback)(SilcServer server,
                                                SilcServerEntry server_entry,
                                                void *context);
 typedef void (*SilcServerConnectRouterCallback)(SilcServer server,
                                                SilcServerEntry server_entry,
                                                void *context);
index 1383e6ceb201dc2e78409ed015965a1cb0e0236a..19b467844a231eb70c8567abe33d59acaac2909a 100644 (file)
@@ -22,6 +22,9 @@
 #include "server_internal.h"
 
 SILC_TASK_CALLBACK(silc_server_protocol_backup_done);
 #include "server_internal.h"
 
 SILC_TASK_CALLBACK(silc_server_protocol_backup_done);
+static void silc_server_backup_connect_primary(SilcServer server,
+                                              SilcServerEntry server_entry,
+                                              void *context);
 
 /* Backup router */
 typedef struct {
 
 /* Backup router */
 typedef struct {
@@ -534,7 +537,7 @@ SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
 
   /* Connect to remote host */
   server_ip = server->config->server_info->primary == NULL ? NULL :
 
   /* Connect to remote host */
   server_ip = server->config->server_info->primary == NULL ? NULL :
-               server->config->server_info->primary->server_ip;
+    server->config->server_info->primary->server_ip;
   sock = silc_net_create_connection(server_ip, sconn->remote_port,
                                    sconn->remote_host);
   if (sock < 0) {
   sock = silc_net_create_connection(server_ip, sconn->remote_port,
                                    sconn->remote_host);
   if (sock < 0) {
@@ -566,6 +569,7 @@ void silc_server_backup_reconnect(SilcServer server,
   sconn->remote_port = port;
   sconn->callback = callback;
   sconn->callback_context = context;
   sconn->remote_port = port;
   sconn->callback = callback;
   sconn->callback_context = context;
+  sconn->no_reconnect = TRUE;
   silc_schedule_task_add(server->schedule, 0, 
                         silc_server_backup_connect_to_router,
                         sconn, 1, 0, SILC_TASK_TIMEOUT,
   silc_schedule_task_add(server->schedule, 0, 
                         silc_server_backup_connect_to_router,
                         sconn, 1, 0, SILC_TASK_TIMEOUT,
@@ -600,8 +604,21 @@ void silc_server_backup_connected(SilcServer server,
                                  void *context)
 {
   SilcServerBackupProtocolContext proto_ctx;
                                  void *context)
 {
   SilcServerBackupProtocolContext proto_ctx;
-  SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
+  SilcSocketConnection sock;
 
 
+  if (!server_entry) {
+    /* Try again */
+    SilcServerConfigRouter *primary;
+    primary = silc_server_config_get_primary_router(server);
+    if (primary)
+      silc_server_backup_reconnect(server,
+                                  primary->host, primary->port,
+                                  silc_server_backup_connected,
+                                  context);
+    return;
+  }
+
+  sock = (SilcSocketConnection)server_entry->connection;
   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
   proto_ctx->server = server;
   proto_ctx->sock = sock;
   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
   proto_ctx->server = server;
   proto_ctx->sock = sock;
@@ -627,12 +644,27 @@ static void silc_server_backup_connect_primary(SilcServer server,
                                               void *context)
 {
   SilcSocketConnection backup_router = (SilcSocketConnection)context;
                                               void *context)
 {
   SilcSocketConnection backup_router = (SilcSocketConnection)context;
-  SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection;
-  SilcIDListData idata = (SilcIDListData)server_entry;
-  SilcServerBackupProtocolContext ctx = 
-    (SilcServerBackupProtocolContext)backup_router->protocol->context;
+  SilcServerBackupProtocolContext ctx;
+  SilcSocketConnection sock;
+  SilcIDListData idata;
   SilcBuffer buffer;
 
   SilcBuffer buffer;
 
+  if (!server_entry) {
+    /* Try again */
+    SilcServerConfigRouter *primary;
+    primary = silc_server_config_get_primary_router(server);
+    if (primary)
+      silc_server_backup_reconnect(server,
+                                  primary->host, primary->port,
+                                  silc_server_backup_connect_primary,
+                                  context);
+    return;
+  }
+
+  ctx = (SilcServerBackupProtocolContext)backup_router->protocol->context;
+  sock = (SilcSocketConnection)server_entry->connection;
+  idata = (SilcIDListData)server_entry;
+
   SILC_LOG_DEBUG(("Sending CONNECTED packet (session %d)", ctx->session));
 
   /* Send the CONNECTED packet back to the backup router. */
   SILC_LOG_DEBUG(("Sending CONNECTED packet (session %d)", ctx->session));
 
   /* Send the CONNECTED packet back to the backup router. */
@@ -926,8 +958,9 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
 
       /* Switch announced informations to our primary router of using the
         backup router. */
 
       /* Switch announced informations to our primary router of using the
         backup router. */
+      silc_server_local_servers_toggle_enabled(server, TRUE);
       silc_server_update_servers_by_server(server, ctx->sock->user_data, 
       silc_server_update_servers_by_server(server, ctx->sock->user_data, 
-                                          server->router, TRUE);
+                                          server->router);
       silc_server_update_clients_by_server(server, ctx->sock->user_data,
                                           server->router, TRUE, FALSE);
       if (server->server_type == SILC_SERVER)
       silc_server_update_clients_by_server(server, ctx->sock->user_data,
                                           server->router, TRUE, FALSE);
       if (server->server_type == SILC_SERVER)
@@ -1054,10 +1087,6 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
 
          SILC_LOG_INFO(("Switching back to primary router %s",
                         server->router->server_name));
 
          SILC_LOG_INFO(("Switching back to primary router %s",
                         server->router->server_name));
-
-         /* We cannot talk to backup router connection anymore, it's
-            enabled again if primary goes down. */
-         backup_router->data.status |= SILC_IDLIST_STATUS_DISABLED;
        } else {
          /* We are connected to new primary and now continue using it */
          router->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
        } else {
          /* We are connected to new primary and now continue using it */
          router->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
@@ -1067,8 +1096,8 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
 
        /* Update the client entries of the backup router to the new 
           router */
 
        /* Update the client entries of the backup router to the new 
           router */
-       silc_server_update_servers_by_server(server, backup_router, router,
-                                            FALSE);
+       silc_server_local_servers_toggle_enabled(server, FALSE);
+       silc_server_update_servers_by_server(server, backup_router, router);
        silc_server_update_clients_by_server(server, NULL, router, 
                                             FALSE, FALSE);
        if (server->server_type == SILC_SERVER)
        silc_server_update_clients_by_server(server, NULL, router, 
                                             FALSE, FALSE);
        if (server->server_type == SILC_SERVER)
@@ -1142,6 +1171,14 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
        server_entry = (SilcServerEntry)id_cache->context;
        sock = (SilcSocketConnection)server_entry->connection;
 
        server_entry = (SilcServerEntry)id_cache->context;
        sock = (SilcSocketConnection)server_entry->connection;
 
+       /* XXXX */
+       if (!sock) {
+         SILC_LOG_DEBUG(("******** REMOVE THIS TEST, IT ALLOWS A BUG"));
+         if (!silc_idcache_list_next(list, &id_cache))
+           break;
+         continue;
+       }
+
        if (sock->protocol == protocol) {
          sock->protocol = NULL;
 
        if (sock->protocol == protocol) {
          sock->protocol = NULL;
 
@@ -1162,6 +1199,14 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
        server_entry = (SilcServerEntry)id_cache->context;
        sock = (SilcSocketConnection)server_entry->connection;
 
        server_entry = (SilcServerEntry)id_cache->context;
        sock = (SilcSocketConnection)server_entry->connection;
 
+       /* XXXX */
+       if (!sock) {
+         SILC_LOG_DEBUG(("******** REMOVE THIS TEST, IT ALLOWS A BUG"));
+         if (!silc_idcache_list_next(list, &id_cache))
+           break;
+         continue;
+       }
+
        if (sock->protocol == protocol) {
          sock->protocol = NULL;
 
        if (sock->protocol == protocol) {
          sock->protocol = NULL;
 
index 1d679b0b30a5bbeaa2c127a226614fe654ccaeba..f7e70f46f103db00a4663f7c216ccf18272068cb 100644 (file)
@@ -81,6 +81,8 @@ struct SilcServerStruct {
   unsigned int backup_router  : 1;   /* Set if this is backup router */
   unsigned int backup_primary : 1;   /* Set if we've switched our primary
                                        router to a backup router. */
   unsigned int backup_router  : 1;   /* Set if this is backup router */
   unsigned int backup_primary : 1;   /* Set if we've switched our primary
                                        router to a backup router. */
+  unsigned int wait_backup    : 1;   /* Set if we are waiting for backup
+                                       router to connect to us. */
 
   SilcServerEntry router;           /* Pointer to the primary router */
   unsigned long router_connect;             /* Time when router was connected */
 
   SilcServerEntry router;           /* Pointer to the primary router */
   unsigned long router_connect;             /* Time when router was connected */
@@ -163,9 +165,8 @@ typedef struct {
 #define SILC_BROADCAST(server) (server->server_type == SILC_ROUTER) 
 
 /* Return TRUE if entry is locally connected or local to us */
 #define SILC_BROADCAST(server) (server->server_type == SILC_ROUTER) 
 
 /* Return TRUE if entry is locally connected or local to us */
-#define SILC_IS_LOCAL(entry)                                           \
-  ((entry)->connection ? TRUE :                                                \
-   (entry)->data.status & SILC_IDLIST_STATUS_LOCAL ? TRUE : FALSE)
+#define SILC_IS_LOCAL(entry) \
+  (((SilcIDListData)entry)->status & SILC_IDLIST_STATUS_LOCAL)
 
 /* Registers generic task for file descriptor for reading from network and
    writing to network. As being generic task the actual task is allocated 
 
 /* Registers generic task for file descriptor for reading from network and
    writing to network. As being generic task the actual task is allocated 
index c5b6a696c3522b3428ed2f672e04ba05672cdb28..75091e945e0e12916a1c545993684463ba95167e 100644 (file)
@@ -140,6 +140,9 @@ bool silc_server_remove_clients_by_server(SilcServer server,
   SilcHashTable channels, clients;
   int i;
 
   SilcHashTable channels, clients;
   int i;
 
+  if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED))
+    return FALSE;
+
   SILC_LOG_DEBUG(("Start"));
 
   /* Allocate the hash table that holds the channels that require
   SILC_LOG_DEBUG(("Start"));
 
   /* Allocate the hash table that holds the channels that require
@@ -521,8 +524,12 @@ void silc_server_update_clients_by_server(SilcServer server,
              client->router = 
                silc_server_update_clients_by_real_server(server, from, client,
                                                          local, id_cache);
              client->router = 
                silc_server_update_clients_by_real_server(server, from, client,
                                                          local, id_cache);
-             if (!client->router)
-               client->router = to;
+             if (!client->router) {
+               if (server->server_type == SILC_ROUTER)
+                 client->router = from;
+               else
+                 client->router = to;
+             }
            } else {
              client->router = to;
            }
            } else {
              client->router = to;
            }
@@ -532,6 +539,10 @@ void silc_server_update_clients_by_server(SilcServer server,
          client->router = to;
        }
 
          client->router = to;
        }
 
+       if (client->router)
+         SILC_LOG_DEBUG(("Client changed to %s", 
+                         silc_id_render(client->router->id, SILC_ID_CLIENT)));
+
        if (!silc_idcache_list_next(list, &id_cache))
          break;
       }
        if (!silc_idcache_list_next(list, &id_cache))
          break;
       }
@@ -578,7 +589,7 @@ void silc_server_update_clients_by_server(SilcServer server,
                silc_server_update_clients_by_real_server(server, from, client,
                                                          local, id_cache);
              if (!client->router)
                silc_server_update_clients_by_real_server(server, from, client,
                                                          local, id_cache);
              if (!client->router)
-               client->router = from; /* on local list put old from */
+               client->router = from;
            } else {
              client->router = to;
            }
            } else {
              client->router = to;
            }
@@ -588,6 +599,10 @@ void silc_server_update_clients_by_server(SilcServer server,
          client->router = to;
        }
 
          client->router = to;
        }
 
+       if (client->router)
+         SILC_LOG_DEBUG(("Client changed to %s", 
+                         silc_id_render(client->router->id, SILC_ID_CLIENT)));
+
        if (!silc_idcache_list_next(list, &id_cache))
          break;
       }
        if (!silc_idcache_list_next(list, &id_cache))
          break;
       }
@@ -603,46 +618,55 @@ void silc_server_update_clients_by_server(SilcServer server,
 }
 
 /* Updates servers that are from `from' to be originated from `to'.  This
 }
 
 /* Updates servers that are from `from' to be originated from `to'.  This
-   will also update the server's connection to `to's connection. If
-   `local_toggle_enabled' is TRUE then local server's connections are
-   enabled, if FALSE they are disabled. */
+   will also update the server's connection to `to's connection. */
 
 void silc_server_update_servers_by_server(SilcServer server, 
                                          SilcServerEntry from,
 
 void silc_server_update_servers_by_server(SilcServer server, 
                                          SilcServerEntry from,
-                                         SilcServerEntry to,
-                                         bool local_toggle_enabled)
+                                         SilcServerEntry to)
 {
   SilcIDCacheList list = NULL;
   SilcIDCacheEntry id_cache = NULL;
   SilcServerEntry server_entry = NULL;
 
 {
   SilcIDCacheList list = NULL;
   SilcIDCacheEntry id_cache = NULL;
   SilcServerEntry server_entry = NULL;
 
+  SILC_LOG_DEBUG(("Updating servers"));
+
   if (silc_idcache_get_all(server->local_list->servers, &list)) {
     if (silc_idcache_list_first(list, &id_cache)) {
       while (id_cache) {
        server_entry = (SilcServerEntry)id_cache->context;
 
   if (silc_idcache_get_all(server->local_list->servers, &list)) {
     if (silc_idcache_list_first(list, &id_cache)) {
       while (id_cache) {
        server_entry = (SilcServerEntry)id_cache->context;
 
-       if (SILC_IS_LOCAL(server_entry)) {
-         if (server_entry != server->id_entry) {
-           if (local_toggle_enabled)
-             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
-           else
-             server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
-         }
-
-         /* If entry is local to us, do not switch it to any oneelse,
-            it is ours. */
+       /* If entry is local to us, do not switch it to any anyone else,
+          it is ours. */
+       if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
+           server_entry == from) {
          if (!silc_idcache_list_next(list, &id_cache))
            break;
          else
            continue;
        }
 
          if (!silc_idcache_list_next(list, &id_cache))
            break;
          else
            continue;
        }
 
-       if (server_entry->router == from) {
-         SILC_LOG_DEBUG(("Updating server (local) %s",
-                         server_entry->server_name ? 
-                         server_entry->server_name : ""));
-         server_entry->router = to;
-         server_entry->connection = to->connection;
+       /* If we are standalone router, any server that is not directly
+          connected to cannot exist anymore.  If we are not standalone
+          we update it correctly. */
+       if (server->server_type == SILC_ROUTER && server->standalone) {
+         silc_server_backup_del(server, server_entry);
+         silc_server_backup_replaced_del(server, server_entry);
+         silc_idlist_del_data(server_entry);
+         silc_idlist_del_server(server->local_list, server_entry);
+         server->stat.servers--;
+         server->stat.cell_servers--;
+       } else {
+         /* XXX if we are not standalone, do a check from local config
+            whether this server is in our cell, but not connected to
+            us (in which case we must remove it). */
+
+         if (server_entry->router == from) {
+           SILC_LOG_DEBUG(("Updating server (local) %s",
+                           server_entry->server_name ? 
+                           server_entry->server_name : ""));
+           server_entry->router = to;
+           server_entry->connection = to->connection;
+         }
        }
 
        if (!silc_idcache_list_next(list, &id_cache))
        }
 
        if (!silc_idcache_list_next(list, &id_cache))
@@ -657,30 +681,99 @@ void silc_server_update_servers_by_server(SilcServer server,
       while (id_cache) {
        server_entry = (SilcServerEntry)id_cache->context;
 
       while (id_cache) {
        server_entry = (SilcServerEntry)id_cache->context;
 
-       if (SILC_IS_LOCAL(server_entry)) {
-         if (server_entry != server->id_entry) {
-           if (local_toggle_enabled)
-             server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
-           else
-             server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
+       /* If entry is local to us, do not switch it to anyone else,
+          it is ours. */
+       if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
+           server_entry == from) {
+         if (!silc_idcache_list_next(list, &id_cache))
+           break;
+         else
+           continue;
+       }
+
+       /* If we are standalone router, any server that is not directly
+          connected to cannot exist anymore.  If we are not standalone
+          we update it correctly. */
+       if (server->server_type == SILC_ROUTER && server->standalone) {
+         silc_server_backup_del(server, server_entry);
+         silc_server_backup_replaced_del(server, server_entry);
+         silc_idlist_del_data(server_entry);
+         silc_idlist_del_server(server->global_list, server_entry);
+         server->stat.servers--;
+         server->stat.cell_servers--;
+       } else {
+         /* XXX if we are not standalone, do a check from local config
+            whether this server is in our cell, but not connected to
+            us (in which case we must remove it). */
+
+         if (server_entry->router == from) {
+           SILC_LOG_DEBUG(("Updating server (global) %s",
+                           server_entry->server_name ? 
+                           server_entry->server_name : ""));
+           server_entry->router = to;
+           server_entry->connection = to->connection;
          }
          }
+       }
+
+       if (!silc_idcache_list_next(list, &id_cache))
+         break;
+      }
+    }
+    silc_idcache_list_free(list);
+  }
+}
 
 
-         /* If entry is local to us, do not switch it to anyone else,
-            it is ours. */
+
+/* Toggles the enabled/disabled status of local server connections.  Packets
+   can be sent to the servers when `toggle_enabled' is TRUE and will be
+   dropped if `toggle_enabled' is FALSE, after this function is called. */
+
+void silc_server_local_servers_toggle_enabled(SilcServer server,
+                                             bool toggle_enabled)
+{
+  SilcIDCacheList list = NULL;
+  SilcIDCacheEntry id_cache = NULL;
+  SilcServerEntry server_entry = NULL;
+
+  if (silc_idcache_get_all(server->local_list->servers, &list)) {
+    if (silc_idcache_list_first(list, &id_cache)) {
+      while (id_cache) {
+       server_entry = (SilcServerEntry)id_cache->context;
+       if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
          if (!silc_idcache_list_next(list, &id_cache))
            break;
          else
            continue;
        }
 
          if (!silc_idcache_list_next(list, &id_cache))
            break;
          else
            continue;
        }
 
-       if (server_entry->router == from) {
-         SILC_LOG_DEBUG(("Updating server (global) %s",
-                         server_entry->server_name ? 
-                         server_entry->server_name : ""));
-         server_entry->router = to;
-         server_entry->connection = to->connection;
+       if (toggle_enabled)
+         server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
+       else
+         server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
+
+       if (!silc_idcache_list_next(list, &id_cache))
+         break;
+      }
+    }
+    silc_idcache_list_free(list);
+  }
+
+  if (silc_idcache_get_all(server->global_list->servers, &list)) {
+    if (silc_idcache_list_first(list, &id_cache)) {
+      while (id_cache) {
+       server_entry = (SilcServerEntry)id_cache->context;
+       if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
+         if (!silc_idcache_list_next(list, &id_cache))
+           break;
+         else
+           continue;
        }
 
        }
 
+       if (toggle_enabled)
+         server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
+       else
+         server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
+
        if (!silc_idcache_list_next(list, &id_cache))
          break;
       }
        if (!silc_idcache_list_next(list, &id_cache))
          break;
       }
@@ -688,7 +781,6 @@ void silc_server_update_servers_by_server(SilcServer server,
     silc_idcache_list_free(list);
   }
 }
     silc_idcache_list_free(list);
   }
 }
-
 /* Removes channels that are from `from. */
 
 void silc_server_remove_channels_by_server(SilcServer server, 
 /* Removes channels that are from `from. */
 
 void silc_server_remove_channels_by_server(SilcServer server, 
index ec434bc2ef99bb9b64da9e9cbb27809ac4818772..6d906485d32ddca51f9195181ec4c501734db73f 100644 (file)
@@ -46,13 +46,16 @@ void silc_server_update_clients_by_server(SilcServer server,
                                          bool remove_from);
 
 /* Updates servers that are from `from' to be originated from `to'.  This
                                          bool remove_from);
 
 /* Updates servers that are from `from' to be originated from `to'.  This
-   will also update the server's connection to `to's connection. If
-   `local_toggle_enabled' is TRUE then local server's connections are
-   enabled, if FALSE they are disabled. */
-void silc_server_update_servers_by_server(SilcServer server, 
+   will also update the server's connection to `to's connection. */
+void silc_server_update_servers_by_server(SilcServer server,
                                          SilcServerEntry from,
                                          SilcServerEntry from,
-                                         SilcServerEntry to,
-                                         bool local_toggle_enabled);
+                                         SilcServerEntry to);
+
+/* Toggles the enabled/disabled status of local server connections.  Packets
+   can be sent to the servers when `toggle_enabled' is TRUE and will be
+   dropped if `toggle_enabled' is FALSE, after this function is called. */
+void silc_server_local_servers_toggle_enabled(SilcServer server,
+                                             bool toggle_enabled);
 
 /* Removes channels that are from `from. */
 void silc_server_remove_channels_by_server(SilcServer server, 
 
 /* Removes channels that are from `from. */
 void silc_server_remove_channels_by_server(SilcServer server, 
index 4c576383f04a799756b6d0b4ff53e8794dcf152f..0eef766e6c867c94a2cd5bd4de8cd93a01daf62c 100644 (file)
@@ -1853,3 +1853,31 @@ silc_server_config_get_primary_router(SilcServer server)
 
   return NULL;
 }
 
   return NULL;
 }
+
+/* If we have backup router configured that is going to replace us this
+   function returns it. */
+
+SilcServerConfigRouter *
+silc_server_config_get_backup_router(SilcServer server)
+{
+  SilcServerConfig config = server->config;
+  SilcServerConfigRouter *serv = NULL;
+  int i;
+
+  if (server->server_type != SILC_ROUTER)
+    return NULL;
+
+  serv = config->routers;
+  for (i = 0; serv; i++) {
+    if (serv->initiator == FALSE && serv->backup_router == TRUE &&
+       serv->backup_local == TRUE &&
+       !strcmp(server->config->server_info->primary->server_ip,
+               serv->backup_replace_ip) &&
+       server->config->server_info->primary->port ==
+       serv->backup_replace_port)
+      return serv;
+    serv = serv->next;
+  }
+
+  return NULL;
+}
index 70674b81cb1630974407be26cf1e5c62e94706e4..fc6c109592c84e13229e7db28f69e0d2245a9385 100644 (file)
@@ -223,5 +223,7 @@ silc_server_config_find_router_conn(SilcServer server, char *host, int port);
 bool silc_server_config_is_primary_route(SilcServer server);
 SilcServerConfigRouter *
 silc_server_config_get_primary_router(SilcServer server);
 bool silc_server_config_is_primary_route(SilcServer server);
 SilcServerConfigRouter *
 silc_server_config_get_primary_router(SilcServer server);
+SilcServerConfigRouter *
+silc_server_config_get_backup_router(SilcServer server);
 
 #endif /* !SERVERCONFIG_H */
 
 #endif /* !SERVERCONFIG_H */
index a137ce47eef996e515066f43a779dd395cdc06d5..7258dc923fafab2517e462e258d80e0f46b62180 100644 (file)
@@ -572,6 +572,18 @@ void silc_client_notify_by_server(SilcClient client,
       goto out;
     silc_free(client_id);
 
       goto out;
     silc_free(client_id);
 
+    /* Wait for resolving if necessary */
+    if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) {
+      SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
+      res->packet = silc_packet_context_dup(packet);
+      res->context = client;
+      res->sock = silc_socket_dup(conn->sock);
+      silc_client_command_pending(conn, SILC_COMMAND_NONE, 
+                                 client_entry->resolve_cmd_ident,
+                                 silc_client_notify_by_server_pending, res);
+      goto out;
+    }
+
     client_entry->valid = FALSE;
 
     /* Get new Client ID */
     client_entry->valid = FALSE;
 
     /* Get new Client ID */
index 69375d60c77e46361c9f5405556fb49161a7b2e2..692846f6e2b9fa08f01a2377520ea47d553bc404 100644 (file)
@@ -273,16 +273,6 @@ SilcConfigFile *silc_config_open(const char *configfile)
 void silc_config_close(SilcConfigFile *file)
 {
   if (file) {
 void silc_config_close(SilcConfigFile *file)
 {
   if (file) {
-    /* XXX FIXME: this check could probably be removed later */
-    SilcUInt32 my_len = (SilcUInt32) (strchr(file->base, EOF) - file->base);
-    SILC_CONFIG_DEBUG(("file=0x%x name=\"%s\" level=%d line=%lu",
-                      (SilcUInt32) file, file->filename, file->level,
-                      file->line));
-    if (my_len != file->len) {
-      fprintf(stderr,
-             "FATAL ERROR: saved len and current len does not match!\n");
-      abort();
-    }
     silc_free(file->filename);
     memset(file->base, 'F', file->len);
     silc_free(file->base);
     silc_free(file->filename);
     memset(file->base, 'F', file->len);
     silc_free(file->base);
index 57931f7e649d4ae8f78bb810011f31927659ce54..8bc4e2c32a736c0f788e67067ba1e752b422d176 100644 (file)
@@ -783,11 +783,12 @@ bool silc_parse_version_string(const char *version,
   /* Take protocol version */
 
   maj = atoi(cp);
   /* Take protocol version */
 
   maj = atoi(cp);
-  cp = strchr(cp, '.');
-  if (cp) {
-    min = atoi(cp + 1);
-    cp++;
-  }
+  if (!strchr(cp, '.'))
+    return FALSE;
+  cp = strchr(cp, '.') + 1;
+  if (!cp || !(*cp))
+    return FALSE;
+  min = atoi(cp);
 
   memset(buf, 0, sizeof(buf));
   snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
 
   memset(buf, 0, sizeof(buf));
   snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
@@ -802,14 +803,18 @@ bool silc_parse_version_string(const char *version,
 
   maj = 0;
   min = 0;
 
   maj = 0;
   min = 0;
-  cp = strchr(cp, '-');
-  if (!cp)
+  if (!strchr(cp, '-'))
+    return FALSE;
+  cp = strchr(cp, '-') + 1;
+  if (!cp || !(*cp))
     return FALSE;
 
     return FALSE;
 
-  maj = atoi(cp + 1);
-  cp = strchr(cp, '.');
-  if (cp)
-    min = atoi(cp + 1);
+  maj = atoi(cp);
+  if (strchr(cp, '.')) {
+    cp = strchr(cp, '.') + 1;
+    if (cp && *cp)
+      min = atoi(cp);
+  }
 
   memset(buf, 0, sizeof(buf));
   snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
 
   memset(buf, 0, sizeof(buf));
   snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min);
@@ -822,11 +827,10 @@ bool silc_parse_version_string(const char *version,
 
   /* Take vendor string */
 
 
   /* Take vendor string */
 
-  cp++;
-  if (cp) {
-    cp = strchr(cp, '.');
-    if (cp && cp + 1 && vendor_version)
-      *vendor_version = strdup(cp + 1);
+  if (strchr(cp, '.')) {
+    cp = strchr(cp, '.') + 1;
+    if (cp && *cp && vendor_version)
+      *vendor_version = strdup(cp);
   }
 
   return TRUE;
   }
 
   return TRUE;