updates.
authorPekka Riikonen <priikone@silcnet.org>
Wed, 14 Mar 2001 19:38:18 +0000 (19:38 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Wed, 14 Mar 2001 19:38:18 +0000 (19:38 +0000)
CHANGES
apps/silcd/command.c
apps/silcd/idlist.h
doc/draft-riikonen-silc-spec-01.nroff
lib/silccore/silccommand.h

diff --git a/CHANGES b/CHANGES
index 03d80a67fe93851365915e16e81d83d240d4f4da..9333281e78b8d82416c95baa84af07e810d001cb 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,14 @@
+Wed Mar 14 20:37:35 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Added new SILC_CF_LAG_STRICT command flag that strictly forces
+         that the command may be executed only once in (about) 2 seconds.
+         The old SILC_CF_LAG flag is same but allows command bursts up
+         to five before limiting.
+
+         Added the support for CF_LAG and CF_LAG_STRICT flags to the
+         server code.  Various commands now includes the CF_LAG_STRICT
+         flag to disallow any kind of miss-use of the command.
+
 Wed Mar 14 16:10:30 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Changed the format of AdminConnection configuration section
index 9f0866a5dbb00e6d6b01826f2dfe69843ff6d1b6..6792f3c0f72ad40082c4ea82814b007ceabcbec7 100644 (file)
@@ -45,23 +45,23 @@ SilcServerCommand silc_command_list[] =
   SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
   SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
   SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
-  SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
-  SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
+  SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
+  SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
   SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
   SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
   SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
-  SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
+  SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
   SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
   SILC_SERVER_CMD(connect, CONNECT, 
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
   SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
   SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
-  SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
+  SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
   SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
   SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
   SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
   SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
-  SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
+  SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
   SILC_SERVER_CMD(restart, RESTART, 
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
   SILC_SERVER_CMD(close, CLOSE,
@@ -70,7 +70,7 @@ SilcServerCommand silc_command_list[] =
                  SILC_CF_OPER),
   SILC_SERVER_CMD(silcoper, SILCOPER,
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
-  SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
+  SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
 
   { NULL, 0 },
@@ -116,9 +116,8 @@ static int silc_server_is_registered(SilcServer server,
 
 /* Internal context to hold data when executed command with timeout. */
 typedef struct {
-  SilcServer server;
-  SilcSocketConnection sock;
-  SilcPacketContext *packet;
+  SilcServerCommandContext ctx;
+  SilcServerCommand *cmd;
 } *SilcServerCommandTimeout;
 
 /* Timeout callback to process commands with timeout for client. Client's
@@ -127,67 +126,61 @@ typedef struct {
 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
 {
   SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
-  SilcServerCommandContext ctx;
-  SilcServerCommand *cmd;
-  SilcClientEntry client = (SilcClientEntry)timeout->sock->user_data;
+  SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
 
   /* Update access time */
   client->last_command = time(NULL);
 
+  if (!(timeout->cmd->flags & SILC_CF_REG))
+    timeout->cmd->cb(timeout->ctx);
+  else if (silc_server_is_registered(timeout->ctx->server, 
+                                    timeout->ctx->sock, 
+                                    timeout->ctx, 
+                                    timeout->cmd->cmd))
+    timeout->cmd->cb(timeout->ctx);
+
+  silc_free(timeout);
+}
+
+/* Processes received command packet. */
+
+void silc_server_command_process(SilcServer server,
+                                SilcSocketConnection sock,
+                                SilcPacketContext *packet)
+{
+  SilcServerCommandContext ctx;
+  SilcServerCommand *cmd;
+
   /* Allocate command context. This must be free'd by the
      command routine receiving it. */
   ctx = silc_server_command_alloc();
-  ctx->server = timeout->server;
-  ctx->sock = timeout->sock;
-  ctx->packet = timeout->packet;
-
+  ctx->server = server;
+  ctx->sock = silc_socket_dup(sock);
+  ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
+  
   /* Parse the command payload in the packet */
-  ctx->payload = silc_command_payload_parse(ctx->packet->buffer);
+  ctx->payload = silc_command_payload_parse(packet->buffer);
   if (!ctx->payload) {
     SILC_LOG_ERROR(("Bad command payload, packet dropped"));
-    silc_buffer_free(ctx->packet->buffer);
+    silc_buffer_free(packet->buffer);
+    silc_packet_context_free(packet);
     silc_socket_free(ctx->sock);
-    silc_packet_context_free(ctx->packet);
     silc_free(ctx);
-    silc_free(timeout);
     return;
   }
   ctx->args = silc_command_get_args(ctx->payload);
   
-  /* Execute command. If this fails the packet is dropped. */
+  /* Get the command */
   for (cmd = silc_command_list; cmd->cb; cmd++)
-    if (cmd->cmd == silc_command_get(ctx->payload)) {
-
-      if (!(cmd->flags & SILC_CF_REG)) {
-       cmd->cb(ctx);
-       break;
-      }
-      
-      if (silc_server_is_registered(ctx->server, ctx->sock, ctx, cmd->cmd)) {
-       cmd->cb(ctx);
-       break;
-      }
-    }
+    if (cmd->cmd == silc_command_get(ctx->payload))
+      break;
 
   if (cmd == NULL) {
     SILC_LOG_ERROR(("Unknown command, packet dropped"));
     silc_server_command_free(ctx);
-    silc_free(timeout);
     return;
   }
 
-  silc_free(timeout);
-}
-
-/* Processes received command packet. */
-
-void silc_server_command_process(SilcServer server,
-                                SilcSocketConnection sock,
-                                SilcPacketContext *packet)
-{
-  SilcServerCommandContext ctx;
-  SilcServerCommand *cmd;
-
   /* Execute client's commands always with timeout.  Normally they are
      executed with zero (0) timeout but if client is sending command more
      frequently than once in 2 seconds, then the timeout may be 0 to 2
@@ -195,12 +188,22 @@ void silc_server_command_process(SilcServer server,
   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
     SilcClientEntry client = (SilcClientEntry)sock->user_data;
     SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
+    int fast;
 
-    timeout->server = server;
-    timeout->sock = silc_socket_dup(sock);
-    timeout->packet = silc_packet_context_dup(packet);
+    timeout->ctx = ctx;
+    timeout->cmd = cmd;
 
-    if (client->last_command && (time(NULL) - client->last_command) < 2)
+    if (client->last_command && (time(NULL) - client->last_command) < 2) {
+      client->fast_command++;
+      fast = FALSE;
+    } else {
+      client->fast_command = ((client->fast_command - 1) <= 0 ? 0 : 
+                             client->fast_command--);
+      fast = TRUE;
+    }
+
+    if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
+                 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
       silc_task_register(server->timeout_queue, sock->sock, 
                         silc_server_command_process_timeout,
                         (void *)timeout, 
@@ -217,45 +220,12 @@ void silc_server_command_process(SilcServer server,
     return;
   }
 
-  /* Allocate command context. This must be free'd by the
-     command routine receiving it. */
-  ctx = silc_server_command_alloc();
-  ctx->server = server;
-  ctx->sock = silc_socket_dup(sock);
-  ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
-  
-  /* Parse the command payload in the packet */
-  ctx->payload = silc_command_payload_parse(packet->buffer);
-  if (!ctx->payload) {
-    SILC_LOG_ERROR(("Bad command payload, packet dropped"));
-    silc_buffer_free(packet->buffer);
-    silc_packet_context_free(packet);
-    silc_socket_free(ctx->sock);
-    silc_free(ctx);
-    return;
-  }
-  ctx->args = silc_command_get_args(ctx->payload);
-  
-  /* Execute command. If this fails the packet is dropped. */
-  for (cmd = silc_command_list; cmd->cb; cmd++)
-    if (cmd->cmd == silc_command_get(ctx->payload)) {
-
-      if (!(cmd->flags & SILC_CF_REG)) {
-       cmd->cb(ctx);
-       break;
-      }
-      
-      if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
-       cmd->cb(ctx);
-       break;
-      }
-    }
+  /* Execute for server */
 
-  if (cmd == NULL) {
-    SILC_LOG_ERROR(("Unknown command, packet dropped"));
-    silc_server_command_free(ctx);
-    return;
-  }
+  if (!(cmd->flags & SILC_CF_REG))
+    cmd->cb(ctx);
+  else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
+    cmd->cb(ctx);
 }
 
 /* Allocate Command Context */
index e05bcbdab834b225b1148c9c6be526d6c5708856..9d29d74fdfc02a0c0f054673981b31099ffd4ddb 100644 (file)
@@ -241,6 +241,12 @@ typedef struct SilcChannelClientEntryStruct {
        not allow any command to be exeucted more than once in about
        2 seconds. This is result of normal time().
 
+   char fast_command
+
+       Counter to check command bursts.  By default, up to 5 commands
+       are allowed before limiting the execution.  See command flags
+       for more detail.
+
    SilcServerEntry router
 
        This is a pointer to the server list. This is the router server whose 
@@ -270,6 +276,7 @@ struct SilcClientEntryStruct {
   int mode;
 
   long last_command;
+  char fast_command;
 
   /* Pointer to the router */
   SilcServerEntry router;
index f36990e456381ba5584dd9db658349f9de811b19..fa5909171dd745fbaaa800b123ff8b468a5bdf4b 100644 (file)
@@ -847,8 +847,12 @@ however, choose ignore the command reply, but should not.
 It is expected that some of the commands may be miss-used by clients
 resulting various problems on the server side.  Every implementation
 should assure that commands may not be executed more than once, say,
-in two (2) seconds.  This should be sufficient to prevent the miss-use
-of commands.
+in two (2) seconds.  However, to keep response rate up, allowing for
+example five (5) commands before limiting is allowed.  It is recommended
+that commands such as SILC_COMMAND_NICK, SILC_COMMAND_JOIN and 
+SILC_COMMAND_LEAVE should be limited in all cases as they require
+heavy operations.  This should be sufficient to prevent the miss-use of
+commands.
 
 SILC commands are described in section 5 SILC Commands.
 
index ec34d8344b2cfa3c95abae57e70b27bfc50f8a40..dd20052dc81cf22d6e4470ca41260045616831a0 100644 (file)
@@ -36,19 +36,24 @@ typedef struct SilcCommandPayloadStruct *SilcCommandPayload;
 typedef enum {
   SILC_CF_NONE           = 0,
 
-  /* Command may only be used once per (about) 2 seconds */
+  /* Command may only be used once per (about) 2 seconds. Bursts up
+     to 5 commands are allowed though. */
   SILC_CF_LAG            = (1L << 1),
 
+  /* Command may only be used once per (about) 2 seconds. No bursts
+     are allowed at all. */
+  SILC_CF_LAG_STRICT     = (1L << 2),
+
   /* Command is available for registered connections (connections
      whose ID has been created. */
-  SILC_CF_REG            = (1L << 2),
+  SILC_CF_REG            = (1L << 3),
 
   /* Command is available only for server operators */
-  SILC_CF_OPER           = (1L << 3),
+  SILC_CF_OPER           = (1L << 4),
 
   /* Command is available only for SILC (router) operators. If this 
      is set SILC_CF_OPER is not necessary to be set. */
-  SILC_CF_SILC_OPER      = (1L << 4),
+  SILC_CF_SILC_OPER      = (1L << 5),
 
 } SilcCommandFlag;