Added preliminary support for dynamic connection during joining.
authorPekka Riikonen <priikone@silcnet.org>
Sun, 10 Jun 2007 19:32:58 +0000 (19:32 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 10 Jun 2007 19:32:58 +0000 (19:32 +0000)
apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/packet_receive.c
apps/silcd/server.c
apps/silcd/server_query.c

index f2211f50877cbdaa3be76a01f8e367227a5a54c5..e52244a30a6677408a6a085185d5df033adb988e 100644 (file)
@@ -2294,36 +2294,37 @@ static void silc_server_command_join_channel(SilcServer server,
 /* Server side of command JOIN. Joins client into requested channel. If
    the channel does not exist it will be created. */
 
-/* Ways of creating channel with dynamic connections:
-
-   1. If channels are not local (no local_channels in silcd.conf) then
-      /join silc, will create connection to default router if it is
-      specified in the silcd.conf.  If it isn't, it creates local channel.
-
-   2. If channels are not local then /join silc@silcnet.org, will create
-      connection to default if it is specified in the silcd.conf and if it
-      isn't or join fails it creates connection to silcnet.org and sends
-      the JOIN command to that server/router.
-
-   3. If channels are local (local_channels set in silcd.conf) then
-      /join silc, will create local channel.  No connections are created
-      to anywhere.
-
-   4. If channels are local then /join silc@silcnet.org will create
-      connection to default router if it is specified in the silcd.conf and
-      if it isn't, or join fails it creates connection to silcnet.org and
-      send the JOIN command to that server/router.
-
-   5. If we create connection to a remote that already has a channel that
-      we also have as a local channel, should we merge those channels?
-      Should I announce my local channels when I connect to router?  Should
-      I keep local channels local, unless I say /join localch@silcnet.org
-      in which case the local channel 'localch' becomes global?
-
-   6. After we have connection established to router, depending on the
-      local_channels setting /join silc will join locally or globally.
-      /join silc@silcnet.org would always join globally.
-*/
+void silc_server_command_join_connected(SilcServer server,
+                                       SilcServerEntry server_entry,
+                                       void *context)
+{
+  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+
+  if (!server_entry) {
+    SilcUInt32 tmp_len;
+    unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+    char serv[256 + 1];
+
+    SILC_LOG_DEBUG(("Connecting to router failed"));
+    silc_parse_userfqdn(tmp, NULL, 0, serv, sizeof(serv));
+
+    if (serv[0]) {
+      silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
+                                          SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
+                                          2, serv, strlen(serv));
+    } else {
+      silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
+                                          SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
+                                          2, tmp, tmp_len);
+    }
+    silc_server_command_free(cmd);
+    return;
+  }
+
+  /* Reprocess command */
+  SILC_LOG_DEBUG(("Reprocess JOIN after connecting to router"));
+  silc_server_command_join(cmd, NULL);
+}
 
 SILC_SERVER_CMD_FUNC(join)
 {
@@ -2357,10 +2358,49 @@ SILC_SERVER_CMD_FUNC(join)
   }
 
   /* Parse server name from the channel name */
-  silc_parse_userfqdn(channel_name, parsed, sizeof(parsed), serv,
+  silc_parse_userfqdn(tmp, parsed, sizeof(parsed), serv,
                      sizeof(serv));
   channel_name = parsed;
 
+  /* If server name is not specified but local channels is FALSE then the
+     channel will be global, based on our router name. */
+  if (!serv[0] && !server->config->local_channels) {
+    if (!server->standalone) {
+      silc_snprintf(serv, sizeof(serv), server->router->server_name);
+    } else {
+      SilcServerConfigRouter *router;
+      router = silc_server_config_get_primary_router(server);
+      if (router) {
+       /* Create connection to primary router */
+       SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d",
+                       router->host, router->port));
+       silc_server_create_connection(server, FALSE, TRUE,
+                                     router->host, router->port,
+                                     silc_server_command_join_connected, cmd);
+       return;
+      }
+    }
+  }
+
+  /* If server name is ours, ignore it. */
+  if (serv[0] && silc_utf8_strcasecmp(serv, server->server_name))
+    memset(serv, 0, sizeof(serv));
+
+  /* Create connection */
+  if (serv[0] && server->standalone) {
+    SilcServerConfigRouter *router;
+    router = silc_server_config_get_primary_router(server);
+    if (router) {
+      /* Create connection to primary router */
+      SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d",
+                     router->host, router->port));
+      silc_server_create_connection(server, FALSE, TRUE,
+                                   router->host, router->port,
+                                   silc_server_command_join_connected, cmd);
+      return;
+    }
+  }
+
   /* Check for valid channel name.  This is cached, the original is saved
      in the channel context. */
   channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
index acf1e2dd4438f94729db70a1bfa75c4d3bfcd88e..97aedf0e8e37455267c4818136418a9c24510b9f 100644 (file)
@@ -1199,7 +1199,8 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
     silc_hmac_free(hmac);
   silc_server_command_reply_free(cmd);
 
-  silc_pkcs_public_key_free(founder_key);
+  if (founder_key)
+    silc_pkcs_public_key_free(founder_key);
   if (client_id_list)
     silc_buffer_free(client_id_list);
   if (client_mode_list)
index f17e28546da22623d727fbc1ee90826b65544281..04eeb0d32938ec5eb2c9c8cdf9714a295a0ff408 100644 (file)
@@ -2637,7 +2637,8 @@ static void silc_server_new_id_real(SilcServer server,
         global list. Cell wide information however is kept in the local
         list. */
       entry = silc_idlist_add_client(id_list, NULL, NULL, NULL,
-                                    &id, router, NULL);
+                                    silc_id_dup(&id, SILC_ID_CLIENT),
+                                    router, NULL);
       if (!entry) {
        SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
 
index d4770c1f11f489def1cef96471d1e071fd8544c8..ca41f9bef5676c38796fb7f7859945a8db56cd23 100644 (file)
@@ -79,6 +79,9 @@ static SilcBool silc_server_packet_receive(SilcPacketEngine engine,
   SilcServer server = callback_context;
   SilcIDListData idata = stream_context;
 
+  if (!idata)
+    return FALSE;
+
   /* Packets we do not handle */
   switch (packet->type) {
   case SILC_PACKET_HEARTBEAT:
@@ -211,6 +214,33 @@ static void silc_server_packet_eos(SilcPacketEngine engine,
   silc_server_close_connection(server, stream);
 }
 
+SILC_TASK_CALLBACK(silc_server_packet_error_timeout)
+{
+  SilcServer server = app_context;
+  SilcPacketStream stream = context;
+  SilcIDListData idata = silc_packet_get_context(stream);
+
+  if (!idata)
+    return;
+
+  if (server->router_conn && server->router_conn->sock == stream &&
+      !server->router && server->standalone) {
+    silc_server_create_connections(server);
+  } else {
+    /* If backup disconnected then mark that resuming will not be allowed */
+     if (server->server_type == SILC_ROUTER && !server->backup_router &&
+         idata->conn_type == SILC_CONN_SERVER) {
+      SilcServerEntry server_entry = (SilcServerEntry)idata;
+      if (server_entry->server_type == SILC_BACKUP_ROUTER)
+        server->backup_closed = TRUE;
+    }
+
+    silc_server_free_sock_user_data(server, stream, NULL);
+  }
+
+  silc_server_close_connection(server, stream);
+}
+
 /* Packet engine callback to indicate error */
 
 static void silc_server_packet_error(SilcPacketEngine engine,
@@ -235,22 +265,9 @@ static void silc_server_packet_error(SilcPacketEngine engine,
                  SILC_CONNTYPE_STRING(idata->conn_type),
                  silc_packet_error_string(error)));
 
-  if (server->router_conn && server->router_conn->sock == stream &&
-      !server->router && server->standalone) {
-    silc_server_create_connections(server);
-  } else {
-    /* If backup disconnected then mark that resuming will not be allowed */
-     if (server->server_type == SILC_ROUTER && !server->backup_router &&
-         idata->conn_type == SILC_CONN_SERVER) {
-      SilcServerEntry server_entry = (SilcServerEntry)idata;
-      if (server_entry->server_type == SILC_BACKUP_ROUTER)
-        server->backup_closed = TRUE;
-    }
-
-    silc_server_free_sock_user_data(server, stream, NULL);
-  }
-
-  silc_server_close_connection(server, stream);
+  silc_schedule_task_add_timeout(server->schedule,
+                                silc_server_packet_error_timeout,
+                                stream, 0, 0);
 }
 
 /* Packet stream callbacks */
@@ -1539,6 +1556,17 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
          silc_server_backup_add(server, server->id_entry, sock->ip,
                                 sconn->remote_port, TRUE);
 #endif /* 0 */
+      } else {
+       /* 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_connection_free(sconn);
+       silc_free(entry);
+       return;
       }
     } else {
       /* Add this server to be our backup router */
@@ -2084,7 +2112,13 @@ silc_server_accept_get_auth(SilcConnAuth connauth,
 
   /* Remote end is server */
   if (conn_type == SILC_CONN_SERVER) {
-    SilcServerConfigServer *sconfig = entry->sconfig.ref_ptr;
+    SilcServerConfigServer *sconfig;
+
+    /* If we are normal server, don't accept the connection */
+    if (server->server_type == SILC_SERVER)
+      return FALSE;
+
+    sconfig = entry->sconfig.ref_ptr;
     if (!sconfig)
       return FALSE;
 
@@ -2965,6 +2999,9 @@ void silc_server_free_client_data(SilcServer server,
   SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
   silc_schedule_task_del_by_context(server->schedule, client);
 
+  if (client->data.sconn)
+    silc_server_connection_free(client->data.sconn);
+
   /* We will not delete the client entry right away. We will take it
      into history (for WHOWAS command) for 5 minutes, unless we're
      shutting down server. */
@@ -3019,8 +3056,6 @@ void silc_server_free_sock_user_data(SilcServer server,
       SilcClientEntry client_entry = (SilcClientEntry)idata;
       silc_server_free_client_data(server, sock, client_entry, TRUE,
                                   signoff_message);
-      if (idata->sconn)
-       silc_server_connection_free(idata->sconn);
       silc_packet_set_context(sock, NULL);
       break;
     }
@@ -3182,6 +3217,9 @@ void silc_server_free_sock_user_data(SilcServer server,
       }
       server->backup_noswitch = FALSE;
 
+      if (idata->sconn)
+       silc_server_connection_free(idata->sconn);
+
       /* Free the server entry */
       silc_server_backup_del(server, user_data);
       silc_server_backup_replaced_del(server, user_data);
@@ -3212,8 +3250,6 @@ void silc_server_free_sock_user_data(SilcServer server,
                                      backup_router->connection);
       }
 
-      if (idata->sconn)
-       silc_server_connection_free(idata->sconn);
       silc_packet_set_context(sock, NULL);
       break;
     }
index 634a15fa38232cebb8bffb23b9e1619169f6f7a9..d3a243a5f85f972aad03713eed57d77676f4270d 100644 (file)
@@ -76,6 +76,7 @@ typedef struct {
   unsigned int dynamic_prim  : 1;   /* Dynamic connection attempt to primary */
   unsigned int dynamic_retry : 1;   /* Primary returned error, send to
                                       nick@serv server. */
+  unsigned int parsed        : 1;   /* Set when query is parsed */
 } *SilcServerQuery;
 
 
@@ -94,7 +95,8 @@ void silc_server_query_add_error_id(SilcServer server,
                                    void *id, SilcIdType id_type);
 void silc_server_query_send_router(SilcServer server, SilcServerQuery query);
 void silc_server_query_send_router_reply(void *context, void *reply);
-void silc_server_query_parse(SilcServer server, SilcServerQuery query);
+SilcBool silc_server_query_parse(SilcServer server, SilcServerQuery query,
+                                SilcBool parse_only);
 void silc_server_query_process(SilcServer server, SilcServerQuery query,
                               SilcBool resolve);
 void silc_server_query_resolve(SilcServer server, SilcServerQuery query,
@@ -254,6 +256,8 @@ SilcBool silc_server_query_command(SilcServer server,
         (!silc_argument_get_arg_type(cmd->args, 1, NULL) &&
          !silc_argument_get_arg_type(cmd->args, 4, NULL) &&
          silc_argument_get_arg_type(cmd->args, 3, NULL)))) {
+      if (!silc_server_query_parse(server, query, TRUE))
+       return FALSE;
       silc_server_query_send_router(server, query);
       return TRUE;
     }
@@ -275,6 +279,8 @@ SilcBool silc_server_query_command(SilcServer server,
     if (server->server_type == SILC_SERVER && !server->standalone &&
        cmd->sock != SILC_PRIMARY_ROUTE(server) &&
        !silc_argument_get_arg_type(cmd->args, 5, NULL)) {
+      if (!silc_server_query_parse(server, query, TRUE))
+       return FALSE;
       silc_server_query_send_router(server, query);
       return TRUE;
     }
@@ -287,7 +293,7 @@ SilcBool silc_server_query_command(SilcServer server,
   }
 
   /* Now parse the request */
-  silc_server_query_parse(server, query);
+  silc_server_query_parse(server, query, FALSE);
 
   return TRUE;
 }
@@ -387,11 +393,11 @@ void silc_server_query_send_router_reply(void *context, void *reply)
        returned error. */
     if (query->nick_server[0] && !query->dynamic_retry &&
        !silc_server_num_sockets_by_remote(server, query->nick_server,
-                                          query->nick_server, 706)) {
+                                          query->nick_server, 1334)) {
       SILC_LOG_DEBUG(("Retry query by connecting to %s:%d",
                      query->nick_server, 706));
       silc_server_create_connection(server, FALSE, TRUE, query->nick_server,
-                                   706, silc_server_query_connected,
+                                   1334, silc_server_query_connected,
                                    query);
       query->dynamic_retry = TRUE;
       query->resolved = FALSE;
@@ -417,12 +423,13 @@ void silc_server_query_send_router_reply(void *context, void *reply)
   }
 
   /* Continue with parsing */
-  silc_server_query_parse(server, query);
+  silc_server_query_parse(server, query, FALSE);
 }
 
 /* Parse the command query and start processing the queries in detail. */
 
-void silc_server_query_parse(SilcServer server, SilcServerQuery query)
+SilcBool silc_server_query_parse(SilcServer server, SilcServerQuery query,
+                                SilcBool parse_only)
 {
   SilcServerCommandContext cmd = query->cmd;
   SilcIDListData idata = silc_packet_get_context(cmd->sock);
@@ -434,6 +441,9 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
   SILC_LOG_DEBUG(("Parsing %s query",
                  silc_get_command_name(query->querycmd)));
 
+  if (query->parsed)
+    goto parsed;
+
   switch (query->querycmd) {
 
   case SILC_COMMAND_WHOIS:
@@ -460,7 +470,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
        silc_server_query_send_error(server, query,
                                     SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
        silc_server_query_free(query);
-       return;
+       return FALSE;
       }
 
       /* Get the nickname@server string and parse it */
@@ -472,7 +482,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
        silc_server_query_send_error(server, query,
                                     SILC_STATUS_ERR_BAD_NICKNAME, 0);
        silc_server_query_free(query);
-       return;
+       return FALSE;
       }
 
       /* Check nickname */
@@ -483,45 +493,13 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
          silc_server_query_send_error(server, query,
                                       SILC_STATUS_ERR_BAD_NICKNAME, 0);
          silc_server_query_free(query);
-         return;
+         return FALSE;
        }
        memset(query->nickname, 0, sizeof(query->nickname));
        silc_snprintf(query->nickname, sizeof(query->nickname), "%s", tmp);
        silc_free(tmp);
       }
 
-      /* Check server name.  If we are open server and don't yet have
-        connection to remote router, create it now. */
-      if (query->nick_server[0] && server->config->open_server &&
-         !query->resolved) {
-       /* If primary router is specified, use that.  Otherwise connect
-          to the server in nick@server string. */
-       SilcServerConfigRouter *router;
-
-       router = silc_server_config_get_primary_router(server);
-       if (router && server->standalone) {
-         /* Create connection to primary router */
-         SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d",
-                         router->host, router->port));
-         query->dynamic_prim = TRUE;
-         silc_server_create_connection(server, FALSE, TRUE,
-                                       router->host, router->port,
-                                       silc_server_query_connected, query);
-         return;
-       } else if (!silc_server_num_sockets_by_remote(server,
-                                                     query->nick_server,
-                                                     query->nick_server,
-                                                     706)) {
-         /* Create connection and handle the query after connection */
-         SILC_LOG_DEBUG(("Create dynamic connection to %s:%d",
-                         query->nick_server, 706));
-         silc_server_create_connection(server, FALSE, TRUE,
-                                       query->nick_server, 706,
-                                       silc_server_query_connected, query);
-         return;
-       }
-      }
-
     } else {
       /* Parse the IDs included in the query */
       query->ids = silc_calloc(argc, sizeof(*query->ids));
@@ -552,7 +530,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
              silc_free(query->ids);
              query->ids = NULL;
              query->ids_count = 0;
-             return;
+             return FALSE;
            }
          }
        }
@@ -577,7 +555,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
       silc_server_query_send_error(server, query,
                                   SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
       silc_server_query_free(query);
-      return;
+      return FALSE;
     }
 
     /* Get the nickname@server string and parse it */
@@ -587,7 +565,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
       silc_server_query_send_error(server, query,
                                   SILC_STATUS_ERR_BAD_NICKNAME, 0);
       silc_server_query_free(query);
-      return;
+      return FALSE;
     }
 
     /* Check nickname */
@@ -597,7 +575,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
       silc_server_query_send_error(server, query,
                                   SILC_STATUS_ERR_BAD_NICKNAME, 0);
       silc_server_query_free(query);
-      return;
+      return FALSE;
     }
     memset(query->nickname, 0, sizeof(query->nickname));
     silc_snprintf(query->nickname, sizeof(query->nickname), "%s", tmp);
@@ -633,7 +611,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
          silc_server_query_send_error(server, query,
                                       SILC_STATUS_ERR_BAD_NICKNAME, 0);
          silc_server_query_free(query);
-         return;
+         return FALSE;
        }
        memset(query->nickname, 0, sizeof(query->nickname));
        silc_snprintf(query->nickname, sizeof(query->nickname), "%s", tmp);
@@ -650,7 +628,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
          silc_server_query_send_error(server, query,
                                       SILC_STATUS_ERR_BAD_SERVER, 0);
          silc_server_query_free(query);
-         return;
+         return FALSE;
        }
        query->server_name = tmp;
       }
@@ -665,7 +643,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
          silc_server_query_send_error(server, query,
                                       SILC_STATUS_ERR_BAD_CHANNEL, 0);
          silc_server_query_free(query);
-         return;
+         return FALSE;
        }
        query->channel_name = tmp;
       }
@@ -674,39 +652,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
        silc_server_query_send_error(server, query,
                                     SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
        silc_server_query_free(query);
-       return;
-      }
-
-      /* Check server name.  If we are open server and don't yet have
-        connection to remote router, create it now. */
-      if (query->nick_server[0] && server->config->open_server &&
-         !query->resolved) {
-       /* If primary router is specified, use that.  Otherwise connect
-          to the server in nick@server string. */
-       SilcServerConfigRouter *router;
-
-       router = silc_server_config_get_primary_router(server);
-       if (router && server->standalone) {
-         /* Create connection to primary router */
-         SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d",
-                         router->host, router->port));
-         query->dynamic_prim = TRUE;
-         silc_server_create_connection(server, FALSE, TRUE,
-                                       router->host, router->port,
-                                       silc_server_query_connected, query);
-         return;
-       } else if (!silc_server_num_sockets_by_remote(server,
-                                                     query->nick_server,
-                                                     query->nick_server,
-                                                     706)) {
-         /* Create connection and handle the query after connection */
-         SILC_LOG_DEBUG(("Create dynamic connection to %s:%d",
-                         query->nick_server, 706));
-         silc_server_create_connection(server, FALSE, TRUE,
-                                       query->nick_server, 706,
-                                       silc_server_query_connected, query);
-         return;
-       }
+       return FALSE;
       }
 
     } else {
@@ -740,7 +686,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
                silc_free(query->ids);
                query->ids = NULL;
                query->ids_count = 0;
-               return;
+               return FALSE;
              }
            }
          } else {
@@ -752,7 +698,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
            silc_free(query->ids);
            query->ids = NULL;
            query->ids_count = 0;
-           return;
+           return FALSE;
          }
        }
 
@@ -777,8 +723,52 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
     break;
   }
 
+  query->parsed = TRUE;
+
+ parsed:
+  if (!parse_only && query->nickname) {
+    switch (query->querycmd) {
+    case SILC_COMMAND_WHOIS:
+    case SILC_COMMAND_IDENTIFY:
+      /* Check server name.  If we are open server and don't yet have
+        connection to remote router, create it now. */
+      if (query->nick_server[0] && server->config->dynamic_server &&
+         !query->resolved) {
+       /* If primary router is specified, use that.  Otherwise connect
+          to the server in nick@server string. */
+       SilcServerConfigRouter *router;
+
+       router = silc_server_config_get_primary_router(server);
+       if (router && server->standalone) {
+         /* Create connection to primary router */
+         SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d",
+                         router->host, router->port));
+         query->dynamic_prim = TRUE;
+         silc_server_create_connection(server, FALSE, TRUE,
+                                       router->host, router->port,
+                                       silc_server_query_connected, query);
+         return FALSE;
+       } else if (!silc_server_num_sockets_by_remote(server,
+                                                     query->nick_server,
+                                                     query->nick_server,
+                                                     706)) {
+         /* Create connection and handle the query after connection */
+         SILC_LOG_DEBUG(("Create dynamic connection to %s:%d",
+                         query->nick_server, 706));
+         silc_server_create_connection(server, FALSE, TRUE,
+                                       query->nick_server, 706,
+                                       silc_server_query_connected, query);
+         return FALSE;
+       }
+      }
+    }
+  }
+
   /* Start processing the query information */
-  silc_server_query_process(server, query, TRUE);
+  if (!parse_only)
+    silc_server_query_process(server, query, TRUE);
+
+  return TRUE;
 }
 
 /* Context for holding clients searched by public key. */