updates.
authorPekka Riikonen <priikone@silcnet.org>
Tue, 3 Apr 2001 14:07:01 +0000 (14:07 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 3 Apr 2001 14:07:01 +0000 (14:07 +0000)
33 files changed:
CHANGES
TODO
apps/silc/client_ops.c
apps/silcd/command.c
apps/silcd/command.h
apps/silcd/command_reply.c
apps/silcd/idlist.c
apps/silcd/idlist.h
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/packet_send.h
apps/silcd/protocol.c
apps/silcd/server.c
apps/silcd/server.h
doc/draft-riikonen-silc-pp-02.nroff
doc/draft-riikonen-silc-spec-02.nroff
lib/silcclient/client_notify.c
lib/silcclient/command.c
lib/silcclient/command.h
lib/silcclient/command_reply.c
lib/silcclient/command_reply.h
lib/silcclient/idlist.c
lib/silcclient/protocol.c
lib/silccore/silcchannel.c
lib/silccore/silccommand.h
lib/silccore/silcnotify.c
lib/silccore/silcnotify.h
lib/silccore/silcpayload.c
lib/silccore/silcpayload.h
lib/silccrypt/silchmac.c
lib/silcske/payload.c
lib/silcutil/silctask.c
lib/silcutil/silctask.h

diff --git a/CHANGES b/CHANGES
index 14b5f3fadad8b703486156b77aa53e318a3a2ced..7976d137ad530b3420c8971d131ea5dc3dfd6ae1 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,48 @@
+Tue Apr  3 16:39:19 EEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Implemented the sending of the SERVER_SIGNOFF notify in the
+         server.  Affected file is silcd/server.c.
+
+       * Added silc_server_send_notify_args into silcd/packet_send.[ch].
+         Added also silc_notify_payload_encode_args into the
+         lib/silccore/silcnotify.[ch].
+
+       * Implemented ther SERVER_SIGNOFF notify handling in the server.
+         Affected file silcd/packet_receive.c.
+
+       * Implemented the SERVER_SIGNOFF notify handling in the client
+         library.  Affected file lib/silcclient/client_notify.c.  Also,
+         implemnted the printing of the SERVER_SIGNOFF info to the
+         application.  Affected file silc/client_ops.c.
+
+       * The silc_idlist_del_server now returns TRUE or FALSE to indicate
+         if the deleting was successful.  Affected file silcd/idlist.[ch].
+
+       * Added support for public key authentication in the connection
+         authentication protocol in the client library.  Affected file
+         lib/silcclient/protocol.c.
+
+       * Changed the server's silc_idlist_get_clients_by_* interface
+         to support already allocated array so that new entries may be
+         added to pre-allocated array.  Affected file silcd/idlist.[ch].
+         This fixes some bugs with WHOIS, WHOWAS and IDENTIFY commands
+         and command replies.
+
+       * All command reply functions in the server now calls the 
+         pending command callback even if error occured.  This way the
+         error will be delivered to the client as well.  Affected files
+         silcd/command.c and silcd/command_reply.c.
+
+       * Fixed INFO command to return local server's info if no server
+         was provided.  Affected file lib/silcclient/command.c.
+
+       * Removed RESTART command for good.  Updated the code and the
+         protocol specs.
+
+       * Rewrote parts of the task system.  It is a bit simpler now.
+         Removed unsued task priorities. The affected files are
+         lib/silcutil/silctask.[ch].
+
 Mon Apr  2 20:02:33 EEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Moved the USERS printing from the library to the application.
diff --git a/TODO b/TODO
index 13beb86d0e651192bba149c56478a3f111cbe28b..f0871b358508113bb9cfb2c9f49d1f8114476d87 100644 (file)
--- a/TODO
+++ b/TODO
@@ -8,8 +8,8 @@ TODO General
    datatype should be defined.
 
 
-TODO In SILC Client Library
-===========================
+TODO/bugs In SILC Client Library
+================================
 
  o Client library crashes if for example server timeouts protocol
    execution and disconnects the client.  The client, on the other hand
@@ -18,10 +18,6 @@ TODO In SILC Client Library
    the SilcSocketConnection reference counter at all.  This must be
    fixed.
 
- o I guess, public key authentication (when connecting to a server)
-   is not working currently.  It is just matter of loading the keys
-   from file and using them (see corresponding code in server).
-
  o Add client library parameters or options that handle what kind of
    messages the library should print out (using `say' client operation,
    for example) and what is left for the application to print.  The
@@ -33,38 +29,27 @@ TODO In SILC Client Library
    fix it.
 
 
-TODO In SILC Server
-===================
-
- o TODO in commands (command.c and command_reply.c):
-
-       o RESTART is not implemented
-       o In servers all command reply funtions should still call the
-         pending command reply even if the reply was error.  In client
-         it is not called but in server, I think, it must be called.
-         When implementing this check that all commands handle the
-         situation correctly when it is called as pending command
-         (it should most likely check that cmd->pending == TRUE/FALSE).
-
- o TODO in notify types (packet_receive.c):
+TODO/bugs In SILC Server
+========================
 
-       o SERVER_SIGNOFF notify type is not implemented
+ o When server quits and all clients of that server are removed from all
+   channels the channel keys are re-generated for all clients.  This is
+   a bug and should be done only once per channel after all clients of
+   the server has been removed.
 
  o Acceptance of incoming connections (client and server connections)
    should be checked before key exchange protocol.  Currently it is
    checked at the authentication phase after KE, that is ok, but it should
-   be checked before starting KE, as well.
+   be checked before starting KE, as well.  This should be done so that
+   is first checks denied connections, then client connections and then
+   server connections.  There is no use to execute the SKE if the connection
+   will not be allowed.
 
  o DNS/IP lookup blocks the server.  This must be fixed.  Check the
    resolver stuff (resolver(3), resolver(5)).  Either we have to do the
    own resolver stuff (through scheduler, if possible without writing
    too much own stuff) or use threads.
 
- o Packet processing can be made faster. All packet function in the
-   packet_receive.c has same prototypes.  Instead of calling those from
-   huge switch() make a table of callback functions that can be called
-   directly by the packet type.
-
  o Server says that it is able to listen on multiple ports but currently
    that is bogus.  It can, but internals are for single server.
 
@@ -74,11 +59,12 @@ TODO In SILC Server
    as well, IP/MASK, and not just plain IP.
 
  o Connection classes should be actually implemented in serverconfig.c.
-   They can be defined but they are totally ignored currently.
+   They can be defined but they are totally ignored currently.  And they
+   should be redefined also.
 
 
-TODO In SILC Libraries
-======================
+TODO/bugs In SILC Libraries
+===========================
 
  o Implement PFS (Perfect Forward Secrecy) flag in SKE (and in client and
    server, actually).  If PFS is set, re-key must cause new key exchange.
@@ -92,21 +78,17 @@ TODO In SILC Libraries
    not in distribution), but it is not used yet, and it requires some
    tweaking on the Makefiles (we want static lib not shared).
 
- o Rewrite the task system.  I made it too complex and too "neat" and
-   it really should be rewritten.  We don't need priorities really, one
-   priority is enough.  This will simplify a lot the task system.
-
- o SIM support for SILC PKCS API needs to made so that they could be
-   used as SIM's.  At the same time some work is required on prime
-   generation as the way it is done now sucks.  Read from code for
-   more (silcpkcs.h).
-
  o Random Number Generator needs some tweaking.  Reading /dev/random may
    block resulting slow initialization of RNG.  Some other things in the
    RNG may block as well.  Also, I have some pending changes to the RNG 
    that needs to be commited (from Schneier's Yarrow-160 paper).  They 
    should make the RNG even better.
 
+ o SIM support for SILC PKCS API needs to made so that they could be
+   used as SIM's.  At the same time some work is required on prime
+   generation as the way it is done now sucks.  Read from code for
+   more (silcpkcs.h).
+
 
 TODO in the protocol before SILC 0.x
 ====================================
index 074cdfe2f296c92168ab90e2f22e062b73b00c3d..647aa5b1473311c82d1738c4b09e2c3a9f87875f 100644 (file)
@@ -321,6 +321,31 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
     }
     break;
 
+  case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
+    {
+      SilcClientEntry *clients;
+      unsigned int clients_count;
+      int i;
+
+      (void)va_arg(vp, void *);
+      clients = va_arg(vp, SilcClientEntry *);
+      clients_count = va_arg(vp, unsigned int);
+
+      for (i = 0; i < clients_count; i++) {
+       if (clients[i]->server)
+         snprintf(message, sizeof(message), "Server signoff: %s@%s %s%s%s", 
+                  clients[i]->nickname, clients[i]->server,
+                  tmp ? "(" : "", tmp ? tmp : "", tmp ? ")" : "");
+       else
+         snprintf(message, sizeof(message), "Server signoff: %s %s%s%s", 
+                  clients[i]->nickname,
+                  tmp ? "(" : "", tmp ? tmp : "", tmp ? ")" : "");
+       silc_print(client, "*** %s", message);
+       memset(message, 0, sizeof(message));
+      }
+      return;
+    }
+
   default:
     break;
   }
index 75afbfd92f472408088af380bf379badd5d83149..d72636f44453ef5404c368b2eebcc8f3c4230ca6 100644 (file)
@@ -62,8 +62,7 @@ SilcServerCommand silc_command_list[] =
   SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
   SILC_SERVER_CMD(cumode, CUMODE, 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(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
   SILC_SERVER_CMD(close, CLOSE,
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
   SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG | 
@@ -72,7 +71,6 @@ SilcServerCommand silc_command_list[] =
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
-  SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
 
   { NULL, 0 },
 };
@@ -488,7 +486,7 @@ silc_server_command_whois_check(SilcServerCommandContext cmd,
   for (i = 0; i < clients_count; i++) {
     entry = clients[i];
 
-    if (entry->data.registered == FALSE)
+    if (!entry || entry->data.registered == FALSE)
       continue;
 
     if (!entry->nickname || !entry->username || !entry->userinfo) {
@@ -717,37 +715,33 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
       }
     }
   } else {
-    clients = silc_idlist_get_clients_by_hash(server->local_list, 
-                                             nick, server->md5hash,
-                                             &clients_count);
-    if (!clients)
-      clients = silc_idlist_get_clients_by_nickname(server->local_list, 
-                                                   nick, server_name,
-                                                   &clients_count);
+    if (!silc_idlist_get_clients_by_hash(server->local_list, 
+                                        nick, server->md5hash,
+                                        &clients, &clients_count))
+      silc_idlist_get_clients_by_nickname(server->local_list, 
+                                         nick, server_name,
+                                         &clients, &clients_count);
   }
   
   /* Check global list as well */
-  if (!clients) {
-    if (client_id_count) {
-      /* Check all Client ID's received in the command packet */
-      for (i = 0; i < client_id_count; i++) {
-       entry = silc_idlist_find_client_by_id(server->global_list, 
-                                             client_id[i], NULL);
-       if (entry) {
-         clients = silc_realloc(clients, sizeof(*clients) * 
-                                (clients_count + 1));
-         clients[clients_count++] = entry;
-       }
+  if (client_id_count) {
+    /* Check all Client ID's received in the command packet */
+    for (i = 0; i < client_id_count; i++) {
+      entry = silc_idlist_find_client_by_id(server->global_list, 
+                                           client_id[i], NULL);
+      if (entry) {
+       clients = silc_realloc(clients, sizeof(*clients) * 
+                              (clients_count + 1));
+       clients[clients_count++] = entry;
       }
-    } else {
-      clients = silc_idlist_get_clients_by_hash(server->global_list, 
-                                               nick, server->md5hash,
-                                               &clients_count);
-      if (!clients)
-       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
-                                                     nick, server_name,
-                                                     &clients_count);
     }
+  } else {
+    if (!silc_idlist_get_clients_by_hash(server->global_list, 
+                                        nick, server->md5hash,
+                                        &clients, &clients_count))
+      silc_idlist_get_clients_by_nickname(server->global_list, 
+                                         nick, server_name,
+                                         &clients, &clients_count);
   }
   
   if (!clients) {
@@ -828,17 +822,16 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
       }
     }
   } else {
-    clients = silc_idlist_get_clients_by_hash(server->local_list, 
-                                             nick, server->md5hash,
-                                             &clients_count);
-    if (!clients)
-      clients = silc_idlist_get_clients_by_nickname(server->local_list, 
-                                                   nick, server_name,
-                                                   &clients_count);
+    if (!silc_idlist_get_clients_by_hash(server->local_list, 
+                                        nick, server->md5hash,
+                                        &clients, &clients_count))
+      silc_idlist_get_clients_by_nickname(server->local_list, 
+                                         nick, server_name,
+                                         &clients, &clients_count);
   }
   
   /* If we are router we will check our global list as well. */
-  if (!clients && server->server_type == SILC_ROUTER) {
+  if (server->server_type == SILC_ROUTER) {
     if (client_id_count) {
       /* Check all Client ID's received in the command packet */
       for (i = 0; i < client_id_count; i++) {
@@ -851,13 +844,12 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
        }
       }
     } else {
-      clients = silc_idlist_get_clients_by_hash(server->global_list, 
-                                               nick, server->md5hash,
-                                               &clients_count);
-      if (!clients)
-       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
-                                                     nick, server_name,
-                                                     &clients_count);
+      if (!silc_idlist_get_clients_by_hash(server->global_list, 
+                                          nick, server->md5hash,
+                                          &clients, &clients_count))
+       silc_idlist_get_clients_by_nickname(server->global_list, 
+                                           nick, server_name,
+                                           &clients, &clients_count);
     }
   }
 
@@ -1165,24 +1157,20 @@ silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
     return 0;
 
   /* Get all clients matching that nickname from local list */
-  clients = silc_idlist_get_clients_by_nickname(server->local_list, 
-                                               nick, server_name,
-                                               &clients_count);
-  if (!clients)
-    clients = silc_idlist_get_clients_by_hash(server->local_list, 
-                                             nick, server->md5hash,
-                                             &clients_count);
+  if (!silc_idlist_get_clients_by_nickname(server->local_list, 
+                                          nick, server_name,
+                                          &clients, &clients_count))
+    silc_idlist_get_clients_by_hash(server->local_list, 
+                                   nick, server->md5hash,
+                                   &clients, &clients_count);
   
   /* Check global list as well */
-  if (!clients) {
-    clients = silc_idlist_get_clients_by_nickname(server->global_list, 
-                                                 nick, server_name,
-                                                 &clients_count);
-    if (!clients)
-      clients = silc_idlist_get_clients_by_hash(server->global_list, 
-                                               nick, server->md5hash,
-                                               &clients_count);
-  }
+  if (!silc_idlist_get_clients_by_nickname(server->global_list, 
+                                          nick, server_name,
+                                          &clients, &clients_count))
+    silc_idlist_get_clients_by_hash(server->global_list, 
+                                   nick, server->md5hash,
+                                   &clients, &clients_count);
   
   if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
     ret = -1;
@@ -1219,23 +1207,21 @@ silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
   /* Process the command request. Let's search for the requested client and
      send reply to the requesting server. */
 
-  clients = silc_idlist_get_clients_by_nickname(server->local_list, 
-                                               nick, server_name,
-                                               &clients_count);
-  if (!clients)
-    clients = silc_idlist_get_clients_by_hash(server->local_list, 
-                                             nick, server->md5hash,
-                                             &clients_count);
+  if (!silc_idlist_get_clients_by_nickname(server->local_list, 
+                                          nick, server_name,
+                                          &clients, &clients_count))
+    silc_idlist_get_clients_by_hash(server->local_list, 
+                                   nick, server->md5hash,
+                                   &clients, &clients_count);
   
   /* If we are router we will check our global list as well. */
-  if (!clients && server->server_type == SILC_ROUTER) {
-    clients = silc_idlist_get_clients_by_nickname(server->global_list, 
-                                                 nick, server_name,
-                                                 &clients_count);
-    if (!clients)
-      clients = silc_idlist_get_clients_by_hash(server->global_list, 
-                                               nick, server->md5hash,
-                                               &clients_count);
+  if (server->server_type == SILC_ROUTER) {
+    if (!silc_idlist_get_clients_by_nickname(server->global_list, 
+                                            nick, server_name,
+                                            &clients, &clients_count))
+      silc_idlist_get_clients_by_hash(server->global_list, 
+                                     nick, server->md5hash,
+                                     &clients, &clients_count);
   }
 
   if (!clients) {
@@ -1301,7 +1287,7 @@ silc_server_command_identify_check(SilcServerCommandContext cmd,
   for (i = 0; i < clients_count; i++) {
     entry = clients[i];
 
-    if (entry->data.registered == FALSE)
+    if (!entry || entry->data.registered == FALSE)
       continue;
 
     if (!entry->nickname) {
@@ -1508,37 +1494,33 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
       }
     }
   } else {
-    clients = silc_idlist_get_clients_by_hash(server->local_list, 
-                                             nick, server->md5hash,
-                                             &clients_count);
-    if (!clients)
-      clients = silc_idlist_get_clients_by_nickname(server->local_list, 
-                                                   nick, server_name,
-                                                   &clients_count);
+    if (!silc_idlist_get_clients_by_hash(server->local_list, 
+                                        nick, server->md5hash,
+                                        &clients, &clients_count))
+      silc_idlist_get_clients_by_nickname(server->local_list, 
+                                         nick, server_name,
+                                         &clients, &clients_count);
   }
   
   /* Check global list as well */
-  if (!clients) {
-    if (client_id_count) {
-      /* Check all Client ID's received in the command packet */
-      for (i = 0; i < client_id_count; i++) {
-       entry = silc_idlist_find_client_by_id(server->global_list, 
-                                             client_id[i], NULL);
-       if (entry) {
-         clients = silc_realloc(clients, sizeof(*clients) * 
-                                (clients_count + 1));
-         clients[clients_count++] = entry;
-       }
+  if (client_id_count) {
+    /* Check all Client ID's received in the command packet */
+    for (i = 0; i < client_id_count; i++) {
+      entry = silc_idlist_find_client_by_id(server->global_list, 
+                                           client_id[i], NULL);
+      if (entry) {
+       clients = silc_realloc(clients, sizeof(*clients) * 
+                              (clients_count + 1));
+       clients[clients_count++] = entry;
       }
-    } else {
-      clients = silc_idlist_get_clients_by_hash(server->global_list, 
-                                               nick, server->md5hash,
-                                               &clients_count);
-      if (!clients)
-       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
-                                                     nick, server_name,
-                                                     &clients_count);
     }
+  } else {
+    if (!silc_idlist_get_clients_by_hash(server->global_list, 
+                                        nick, server->md5hash,
+                                        &clients, &clients_count))
+      silc_idlist_get_clients_by_nickname(server->global_list, 
+                                         nick, server_name,
+                                         &clients, &clients_count);
   }
   
   if (!clients) {
@@ -1616,17 +1598,16 @@ silc_server_command_identify_from_server(SilcServerCommandContext cmd)
       }
     }
   } else {
-    clients = silc_idlist_get_clients_by_hash(server->local_list, 
-                                             nick, server->md5hash,
-                                             &clients_count);
-    if (!clients)
-      clients = silc_idlist_get_clients_by_nickname(server->local_list, 
-                                                   nick, server_name,
-                                                   &clients_count);
+    if (!silc_idlist_get_clients_by_hash(server->local_list, 
+                                        nick, server->md5hash,
+                                        &clients, &clients_count))
+      silc_idlist_get_clients_by_nickname(server->local_list, 
+                                         nick, server_name,
+                                         &clients, &clients_count);
   }
   
   /* If we are router we will check our global list as well. */
-  if (!clients && server->server_type == SILC_ROUTER) {
+  if (server->server_type == SILC_ROUTER) {
     if (client_id_count) {
       /* Check all Client ID's received in the command packet */
       for (i = 0; i < client_id_count; i++) {
@@ -1639,13 +1620,12 @@ silc_server_command_identify_from_server(SilcServerCommandContext cmd)
        }
       }
     } else {
-      clients = silc_idlist_get_clients_by_hash(server->global_list, 
-                                               nick, server->md5hash,
-                                               &clients_count);
-      if (!clients)
-       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
-                                                     nick, server_name,
-                                                     &clients_count);
+      if (!silc_idlist_get_clients_by_hash(server->global_list, 
+                                          nick, server->md5hash,
+                                          &clients, &clients_count))
+       silc_idlist_get_clients_by_nickname(server->global_list, 
+                                           nick, server_name,
+                                           &clients, &clients_count);
     }
   }
 
@@ -4363,10 +4343,139 @@ SILC_SERVER_CMD_FUNC(connect)
   silc_server_command_free(cmd);
 }
 
-SILC_SERVER_CMD_FUNC(restart)
+/* Server side of command BAN. This is used to manage the ban list of the
+   channel. To add clients and remove clients from the ban list. */
+
+SILC_SERVER_CMD_FUNC(ban)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  SilcServer server = cmd->server;
+  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcBuffer packet;
+  SilcChannelEntry channel;
+  SilcChannelClientEntry chl;
+  SilcChannelID *channel_id = NULL;
+  unsigned char *id, *add, *del;
+  unsigned int id_len, tmp_len;
+  unsigned short ident = silc_command_get_ident(cmd->payload);
+
+  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+    goto out;
+
+  SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
+
+  /* Get Channel ID */
+  id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
+  if (id) {
+    channel_id = silc_id_payload_parse_id(id, id_len);
+    if (!channel_id) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
+      goto out;
+    }
+  }
+
+  /* Get channel entry. The server must know about the channel since the
+     client is expected to be on the channel. */
+  channel = silc_idlist_find_channel_by_id(server->local_list, 
+                                          channel_id, NULL);
+  if (!channel) {
+    channel = silc_idlist_find_channel_by_id(server->global_list, 
+                                            channel_id, NULL);
+    if (!channel) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
+      goto out;
+    }
+  }
+
+  /* Check whether this client is on the channel */
+  if (!silc_server_client_on_channel(client, channel)) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+                                         SILC_STATUS_ERR_NOT_ON_CHANNEL);
+    goto out;
+  }
+
+  /* Get entry to the channel user list */
+  silc_list_start(channel->user_list);
+  while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
+    if (chl->client == client)
+      break;
+
+  /* The client must be at least channel operator. */
+  if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV);
+    goto out;
+  }
+
+  /* Get the new ban and add it to the ban list */
+  add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+  if (add) {
+    if (!channel->ban_list)
+      channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
+    else
+      channel->ban_list = silc_realloc(channel->ban_list, 
+                                      sizeof(*channel->ban_list) * 
+                                      (tmp_len + 
+                                       strlen(channel->ban_list) + 2));
+    if (add[tmp_len - 1] == ',')
+      add[tmp_len - 1] = '\0';
+
+    strncat(channel->ban_list, add, tmp_len);
+    strncat(channel->ban_list, ",", 1);
+  }
+
+  /* Get the ban to be removed and remove it from the list */
+  del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
+  if (del && channel->ban_list) {
+    char *start, *end, *n;
+
+    if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
+      silc_free(channel->ban_list);
+      channel->ban_list = NULL;
+    } else {
+      start = strstr(channel->ban_list, del);
+      if (start && strlen(start) >= tmp_len) {
+       end = start + tmp_len;
+       n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
+       strncat(n, channel->ban_list, start - channel->ban_list);
+       strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
+                            end) - 1);
+       silc_free(channel->ban_list);
+       channel->ban_list = n;
+      }
+    }
+  }
+
+  /* Send the BAN notify type to our primary router. */
+  if (!server->standalone && (add || del))
+    silc_server_send_notify_ban(server, server->router->connection,
+                               server->server_type == SILC_ROUTER ?
+                               TRUE : FALSE, channel, add, del);
+
+  /* Send the reply back to the client */
+  if (channel->ban_list)
+    packet = 
+      silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
+                                          SILC_STATUS_OK, ident, 2,
+                                          2, id, id_len,
+                                          3, channel->ban_list, 
+                                          strlen(channel->ban_list) - 1);
+  else
+    packet = 
+      silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
+                                          SILC_STATUS_OK, ident, 1,
+                                          2, id, id_len);
+
+  silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
+                         packet->data, packet->len, FALSE);
+    
+  silc_buffer_free(packet);
 
+ out:
+  if (channel_id)
+    silc_free(channel_id);
   silc_server_command_free(cmd);
 }
 
@@ -4471,7 +4580,7 @@ SILC_SERVER_CMD_FUNC(leave)
   SilcServer server = cmd->server;
   SilcSocketConnection sock = cmd->sock;
   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
-  SilcChannelID *id;
+  SilcChannelID *id = NULL;
   SilcChannelEntry channel;
   unsigned int len;
   unsigned char *tmp;
@@ -4540,6 +4649,8 @@ SILC_SERVER_CMD_FUNC(leave)
   silc_free(id);
 
  out:
+  if (id)
+    silc_free(id);
   silc_server_command_free(cmd);
 }
 
@@ -4646,139 +4757,3 @@ SILC_SERVER_CMD_FUNC(users)
  out:
   silc_server_command_free(cmd);
 }
-
-/* Server side of command BAN. This is used to manage the ban list of the
-   channel. To add clients and remove clients from the ban list. */
-
-SILC_SERVER_CMD_FUNC(ban)
-{
-  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
-  SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
-  SilcBuffer packet;
-  SilcChannelEntry channel;
-  SilcChannelClientEntry chl;
-  SilcChannelID *channel_id = NULL;
-  unsigned char *id, *add, *del;
-  unsigned int id_len, tmp_len;
-  unsigned short ident = silc_command_get_ident(cmd->payload);
-
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
-    goto out;
-
-  SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
-
-  /* Get Channel ID */
-  id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
-  if (id) {
-    channel_id = silc_id_payload_parse_id(id, id_len);
-    if (!channel_id) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
-                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
-      goto out;
-    }
-  }
-
-  /* Get channel entry. The server must know about the channel since the
-     client is expected to be on the channel. */
-  channel = silc_idlist_find_channel_by_id(server->local_list, 
-                                          channel_id, NULL);
-  if (!channel) {
-    channel = silc_idlist_find_channel_by_id(server->global_list, 
-                                            channel_id, NULL);
-    if (!channel) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
-                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
-      goto out;
-    }
-  }
-
-  /* Check whether this client is on the channel */
-  if (!silc_server_client_on_channel(client, channel)) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
-                                         SILC_STATUS_ERR_NOT_ON_CHANNEL);
-    goto out;
-  }
-
-  /* Get entry to the channel user list */
-  silc_list_start(channel->user_list);
-  while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
-    if (chl->client == client)
-      break;
-
-  /* The client must be at least channel operator. */
-  if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
-                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV);
-    goto out;
-  }
-
-  /* Get the new ban and add it to the ban list */
-  add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
-  if (add) {
-    if (!channel->ban_list)
-      channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
-    else
-      channel->ban_list = silc_realloc(channel->ban_list, 
-                                      sizeof(*channel->ban_list) * 
-                                      (tmp_len + 
-                                       strlen(channel->ban_list) + 2));
-    if (add[tmp_len - 1] == ',')
-      add[tmp_len - 1] = '\0';
-
-    strncat(channel->ban_list, add, tmp_len);
-    strncat(channel->ban_list, ",", 1);
-  }
-
-  /* Get the ban to be removed and remove it from the list */
-  del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
-  if (del && channel->ban_list) {
-    char *start, *end, *n;
-
-    if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
-      silc_free(channel->ban_list);
-      channel->ban_list = NULL;
-    } else {
-      start = strstr(channel->ban_list, del);
-      if (start && strlen(start) >= tmp_len) {
-       end = start + tmp_len;
-       n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
-       strncat(n, channel->ban_list, start - channel->ban_list);
-       strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
-                            end) - 1);
-       silc_free(channel->ban_list);
-       channel->ban_list = n;
-      }
-    }
-  }
-
-  /* Send the BAN notify type to our primary router. */
-  if (!server->standalone && (add || del))
-    silc_server_send_notify_ban(server, server->router->connection,
-                               server->server_type == SILC_ROUTER ?
-                               TRUE : FALSE, channel, add, del);
-
-  /* Send the reply back to the client */
-  if (channel->ban_list)
-    packet = 
-      silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
-                                          SILC_STATUS_OK, ident, 2,
-                                          2, id, id_len,
-                                          3, channel->ban_list, 
-                                          strlen(channel->ban_list) - 1);
-  else
-    packet = 
-      silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
-                                          SILC_STATUS_OK, ident, 1,
-                                          2, id, id_len);
-
-  silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
-                         packet->data, packet->len, FALSE);
-    
-  silc_buffer_free(packet);
-
- out:
-  if (channel_id)
-    silc_free(channel_id);
-  silc_server_command_free(cmd);
-}
index f8b7a5fe20088bef9c6b6de4a2ad3874b7637fb5..b33221db9d75397e1fb2a30e78fa73ea08ffb823 100644 (file)
@@ -148,12 +148,11 @@ SILC_SERVER_CMD_FUNC(cmode);
 SILC_SERVER_CMD_FUNC(cumode);
 SILC_SERVER_CMD_FUNC(kick);
 SILC_SERVER_CMD_FUNC(ignore);
-SILC_SERVER_CMD_FUNC(restart);
+SILC_SERVER_CMD_FUNC(ban);
 SILC_SERVER_CMD_FUNC(close);
 SILC_SERVER_CMD_FUNC(shutdown);
 SILC_SERVER_CMD_FUNC(silcoper);
 SILC_SERVER_CMD_FUNC(leave);
 SILC_SERVER_CMD_FUNC(users);
-SILC_SERVER_CMD_FUNC(ban);
 
 #endif
index 588c1a0ca30b3187beb600033a4f0558d9f5d9d2..88211f55beec9d53ce02f99865534dcdf4ea1b58 100644 (file)
 #include "server_internal.h"
 #include "command_reply.h"
 
+/* All functions that call the COMMAND_CHECK_STATUS or the
+   COMMAND_CHECK_STATUS_LIST macros must have out: goto label. */
+
 #define COMMAND_CHECK_STATUS                                             \
 do {                                                                     \
   SILC_LOG_DEBUG(("Start"));                                             \
   SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); \
-  if (status != SILC_STATUS_OK) {                                        \
-    silc_server_command_reply_free(cmd);                                 \
-    return;                                                              \
-  }                                                                      \
+  if (status != SILC_STATUS_OK)                                                  \
+    goto out;                                                            \
 } while(0)
 
 #define COMMAND_CHECK_STATUS_LIST                                        \
 do {                                                                     \
   SILC_LOG_DEBUG(("Start"));                                             \
   SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); \
-  if (status != SILC_STATUS_OK &&                                        \
+  if (status != SILC_STATUS_OK &&                                        \
       status != SILC_STATUS_LIST_START &&                                \
       status != SILC_STATUS_LIST_ITEM &&                                 \
-      status != SILC_STATUS_LIST_END) {                                          \
-    silc_server_command_reply_free(cmd);                                 \
-    return;                                                              \
-  }                                                                      \
+      status != SILC_STATUS_LIST_END)                                    \
+    goto out;                                                            \
 } while(0)
 
 /* Server command reply list. Not all commands have reply function as
@@ -250,10 +249,15 @@ SILC_SERVER_CMD_REPLY_FUNC(whois)
   if (!silc_server_command_reply_whois_save(cmd))
     goto out;
 
-  /* Execute any pending commands */
-  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
+  /* Pending callbacks are not executed if this was an list entry */
+  if (status != SILC_STATUS_OK &&
+      status != SILC_STATUS_LIST_END) {
+    silc_server_command_reply_free(cmd);
+    return;
+  }
 
  out:
+  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
   SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOIS);
   silc_server_command_reply_free(cmd);
 }
@@ -370,10 +374,15 @@ SILC_SERVER_CMD_REPLY_FUNC(whowas)
   if (!silc_server_command_reply_whowas_save(cmd))
     goto out;
 
-  /* Execute any pending commands */
-  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
+  /* Pending callbacks are not executed if this was an list entry */
+  if (status != SILC_STATUS_OK &&
+      status != SILC_STATUS_LIST_END) {
+    silc_server_command_reply_free(cmd);
+    return;
+  }
 
  out:
+  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
   SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOWAS);
   silc_server_command_reply_free(cmd);
 }
@@ -492,10 +501,15 @@ SILC_SERVER_CMD_REPLY_FUNC(identify)
   if (!silc_server_command_reply_identify_save(cmd))
     goto out;
 
-  /* Execute any pending commands */
-  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
+  /* Pending callbacks are not executed if this was an list entry */
+  if (status != SILC_STATUS_OK &&
+      status != SILC_STATUS_LIST_END) {
+    silc_server_command_reply_free(cmd);
+    return;
+  }
 
  out:
+  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
   SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_IDENTIFY);
   silc_server_command_reply_free(cmd);
 }
@@ -550,10 +564,8 @@ SILC_SERVER_CMD_REPLY_FUNC(info)
 
   entry->server_info = tmp ? strdup(tmp) : NULL;
 
-  /* Execute any pending commands */
-  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
-
  out:
+  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
   SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INFO);
   silc_server_command_reply_free(cmd);
 }
@@ -565,7 +577,7 @@ SILC_SERVER_CMD_REPLY_FUNC(motd)
   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
   SilcServer server = cmd->server;
   SilcCommandStatus status;
-  SilcServerEntry entry;
+  SilcServerEntry entry = NULL;
   SilcServerID *server_id;
   unsigned int tmp_len;
   unsigned char *tmp;
@@ -595,14 +607,13 @@ SILC_SERVER_CMD_REPLY_FUNC(motd)
 
   entry->motd = tmp;
 
-  /* Execute any pending commands */
-  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
-
-  entry->motd = NULL;
-
  out:
+  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
   SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_MOTD);
   silc_server_command_reply_free(cmd);
+
+  if (entry)
+    entry->motd = NULL;
 }
 
 /* Received reply for forwarded JOIN command. Router has created or joined
@@ -623,7 +634,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
   unsigned char *id_string;
   char *channel_name, *tmp;
   unsigned int mode, created;
-  SilcBuffer keyp = NULL, client_id_list, client_mode_list;
+  SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
 
   COMMAND_CHECK_STATUS;
 
@@ -794,17 +805,17 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
                                    client_id, client_id_list,
                                    client_mode_list, list_count);
 
-  silc_buffer_free(client_id_list);
-  silc_buffer_free(client_mode_list);
-
-  /* Execute any pending commands */
-  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
-
  out:
+  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
   SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_JOIN);
   if (client_id)
     silc_free(client_id);
   silc_server_command_reply_free(cmd);
+
+  if (client_id_list)
+    silc_buffer_free(client_id_list);
+  if (client_mode_list)
+    silc_buffer_free(client_mode_list);
 }
 
 SILC_SERVER_CMD_REPLY_FUNC(users)
@@ -872,10 +883,8 @@ SILC_SERVER_CMD_REPLY_FUNC(users)
   silc_buffer_free(client_id_list);
   silc_buffer_free(client_mode_list);
 
-  /* Execute any pending commands */
-  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
-
  out:
+  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
   SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
   if (channel_id)
     silc_free(channel_id);
index 02f9f41e5890d0ce2ef879f54ceae46c9aa4cf47..ed4f506594187e62966bdb85ba018db63f49a5a4 100644 (file)
@@ -248,13 +248,14 @@ silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
 
 /* Removes and free's server entry from ID list */
 
-void silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry)
+int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry)
 {
   if (entry) {
     /* Remove from cache */
     if (entry->id)
-      silc_idcache_del_by_id(id_list->servers, SILC_ID_SERVER, 
-                            (void *)entry->id);
+      if (!silc_idcache_del_by_id(id_list->servers, SILC_ID_SERVER, 
+                                 (void *)entry->id))
+       return FALSE;
 
     /* Free data */
     if (entry->server_name)
@@ -264,7 +265,10 @@ void silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry)
 
     memset(entry, 'F', sizeof(*entry));
     silc_free(entry);
+    return TRUE;
   }
+
+  return FALSE;
 }
 
 /******************************************************************************
@@ -346,35 +350,36 @@ int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
 /* Returns all clients matching requested nickname. Number of clients is
    returned to `clients_count'. Caller must free the returned table. */
 
-SilcClientEntry *
-silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
-                                   char *server, unsigned int *clients_count)
+int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
+                                       char *server, 
+                                       SilcClientEntry **clients,
+                                       unsigned int *clients_count)
 {
   SilcIDCacheList list = NULL;
   SilcIDCacheEntry id_cache = NULL;
-  SilcClientEntry *clients;
   int i;
 
   SILC_LOG_DEBUG(("Start"));
 
   if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
-    return NULL;
+    return FALSE;
 
-  clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
+  *clients = silc_realloc(*clients, 
+                         (silc_idcache_list_count(list) + *clients_count) * 
+                         sizeof(**clients));
 
   i = 0;
   silc_idcache_list_first(list, &id_cache);
-  clients[i++] = (SilcClientEntry)id_cache->context;
+  (*clients)[i++] = (SilcClientEntry)id_cache->context;
 
   while (silc_idcache_list_next(list, &id_cache))
-    clients[i++] = (SilcClientEntry)id_cache->context;
+    (*clients)[i++] = (SilcClientEntry)id_cache->context;
   
   silc_idcache_list_free(list);
   
-  if (clients_count)
-    *clients_count = i;
+  *clients_count += i;
 
-  return clients;
+  return TRUE;
 }
 
 /* Returns all clients matching requested nickname. Number of clients is
@@ -384,14 +389,13 @@ silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
    list may have hash.  Thus, this is not fully reliable function.
    Instead this should probably check the hash from the list of client ID's. */
 
-SilcClientEntry *
-silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
-                               SilcHash md5hash,
-                               unsigned int *clients_count)
+int silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
+                                   SilcHash md5hash,
+                                   SilcClientEntry **clients,
+                                   unsigned int *clients_count)
 {
   SilcIDCacheList list = NULL;
   SilcIDCacheEntry id_cache = NULL;
-  SilcClientEntry *clients;
   unsigned char hash[32];
   int i;
 
@@ -400,23 +404,24 @@ silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
   silc_hash_make(md5hash, nickname, strlen(nickname), hash);
 
   if (!silc_idcache_find_by_data(id_list->clients, hash, &list))
-    return NULL;
+    return FALSE;
 
-  clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
+  *clients = silc_realloc(*clients, 
+                         (silc_idcache_list_count(list) + *clients_count) * 
+                         sizeof(**clients));
 
   i = 0;
   silc_idcache_list_first(list, &id_cache);
-  clients[i++] = (SilcClientEntry)id_cache->context;
+  (*clients)[i++] = (SilcClientEntry)id_cache->context;
 
   while (silc_idcache_list_next(list, &id_cache))
-    clients[i++] = (SilcClientEntry)id_cache->context;
+    (*clients)[i++] = (SilcClientEntry)id_cache->context;
   
   silc_idcache_list_free(list);
   
-  if (clients_count)
-    *clients_count = i;
+  *clients_count += i;
 
-  return clients;
+  return TRUE;
 }
 
 /* Finds client by nickname hash. */
index f36a6a633dd34369d08f31f4bbff5788b6c8837c..0fd6207b0f5a1413b0dde7b919d6f92636605707 100644 (file)
@@ -520,20 +520,21 @@ silc_idlist_find_server_by_conn(SilcIDList id_list, char *hostname,
 SilcServerEntry
 silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
                              SilcServerID *new_id);
-void silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry);
+int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry);
 SilcClientEntry
 silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname, 
                       unsigned int nickname_len, char *username, 
                       char *userinfo, SilcClientID *id, 
                       SilcServerEntry router, void *connection);
 int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry);
-SilcClientEntry *
-silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
-                                   char *server, unsigned int *clients_count);
-SilcClientEntry *
-silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
-                               SilcHash md5hash,
-                               unsigned int *clients_count);
+int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
+                                       char *server, 
+                                       SilcClientEntry **clients,
+                                       unsigned int *clients_count);
+int silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
+                                   SilcHash md5hash,
+                                   SilcClientEntry **clients,
+                                   unsigned int *clients_count);
 SilcClientEntry
 silc_idlist_find_client_by_hash(SilcIDList id_list, char *nickname,
                                SilcHash md5hash, SilcIDCacheEntry *ret_entry);
index 8e50b85741a76a2460185a7ceceef98083ffae33..65ceb85dfb77001d369aa8439338658b2406b077 100644 (file)
@@ -39,8 +39,10 @@ void silc_server_notify(SilcServer server,
   SilcArgumentPayload args;
   SilcChannelID *channel_id, *channel_id2;
   SilcClientID *client_id, *client_id2;
+  SilcServerID *server_id;
   SilcChannelEntry channel;
   SilcClientEntry client;
+  SilcServerEntry server_entry;
   SilcChannelClientEntry chl;
   SilcIDCacheEntry cache;
   unsigned int mode;
@@ -680,7 +682,43 @@ void silc_server_notify(SilcServer server,
     break;
 
   case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
-    SILC_LOG_DEBUG(("SERVER SIGNOFF notify (not-impl XXX)"));
+    /* 
+     * Remove the server entry and all clients that this server owns.
+     */
+
+    SILC_LOG_DEBUG(("SERVER SIGNOFF notify"));
+
+    /* Get Server ID */
+    tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+    if (!tmp)
+      goto out;
+    server_id = silc_id_payload_parse_id(tmp, tmp_len);
+    if (!server_id)
+      goto out;
+
+    /* Get server entry */
+    server_entry = silc_idlist_find_server_by_id(server->global_list, 
+                                                server_id, NULL);
+    if (!server_entry) {
+      server_entry = silc_idlist_find_server_by_id(server->local_list, 
+                                                  server_id, NULL);
+      if (!server_entry) {
+       silc_free(server_id);
+       goto out;
+      }
+    }
+    silc_free(server_id);
+
+    /* Free all client entries that this server owns as they will
+       become invalid now as well. */
+    silc_server_remove_clients_by_server(server, server_entry, TRUE);
+
+    /* Remove the server entry */
+    if (!silc_idlist_del_server(server->global_list, server_entry))
+      silc_idlist_del_server(server->local_list, server_entry);
+
+    /* XXX update statistics */
+
     break;
 
   case SILC_NOTIFY_TYPE_KICKED:
@@ -1301,6 +1339,7 @@ SilcClientEntry silc_server_new_client(SilcServer server,
   cache->id = (void *)client_id;
   cache->type = SILC_ID_CLIENT;
   cache->data = username;
+  cache->data_len = strlen(username);
   silc_idcache_sort_by_data(server->local_list->clients);
 
   /* Notify our router about new client on the SILC network */
index 3ec4e53ce6edcea32c04994e7948919b3045072a..6b1a1a8de4ca0be961d5428ce2902de0183c34c0 100644 (file)
@@ -860,6 +860,24 @@ void silc_server_send_notify(SilcServer server,
   silc_buffer_free(packet);
 }
 
+/* Sends notify message and gets the arguments from the `args' Argument
+   Payloads. */
+
+void silc_server_send_notify_args(SilcServer server,
+                                 SilcSocketConnection sock,
+                                 int broadcast,
+                                 SilcNotifyType type,
+                                 unsigned int argc,
+                                 SilcBuffer args)
+{
+  SilcBuffer packet;
+
+  packet = silc_notify_payload_encode_args(type, argc, args);
+  silc_server_packet_send(server, sock, SILC_PACKET_NOTIFY, 0, 
+                         packet->data, packet->len, FALSE);
+  silc_buffer_free(packet);
+}
+
 /* Send CHANNEL_CHANGE notify type. This tells the receiver to replace the
    `old_id' with the `new_id'. */
 
@@ -1025,24 +1043,6 @@ void silc_server_send_notify_signoff(SilcServer server,
   silc_buffer_free(idp);
 }
 
-/* Sends SERVER_SIGNOFF notify type. This tells that `server_id' server
-   has quit SILC network. */
-
-void silc_server_send_notify_server_signoff(SilcServer server,
-                                           SilcSocketConnection sock,
-                                           int broadcast,
-                                           SilcServerID *server_id,
-                                           unsigned int server_id_len)
-{
-  SilcBuffer idp;
-
-  idp = silc_id_payload_encode((void *)server_id, SILC_ID_SERVER);
-  silc_server_send_notify(server, sock, broadcast,
-                         SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
-                         1, idp->data, idp->len);
-  silc_buffer_free(idp);
-}
-
 /* Sends TOPIC_SET notify type. This tells that `client_id' changed
    the `channel's topic to `topic'. The Notify packet is always destined
    to the channel. This function is used to send the topic set notifies
index 223709693d4c6bbacfaf06944840ddc8103670ec..3ec5de630762026ab6186bbb8fd116ed5ac18f25 100644 (file)
@@ -97,6 +97,12 @@ void silc_server_send_notify(SilcServer server,
                             int broadcast,
                             SilcNotifyType type,
                             unsigned int argc, ...);
+void silc_server_send_notify_args(SilcServer server,
+                                 SilcSocketConnection sock,
+                                 int broadcast,
+                                 SilcNotifyType type,
+                                 unsigned int argc,
+                                 SilcBuffer args);
 void silc_server_send_notify_channel_change(SilcServer server,
                                            SilcSocketConnection sock,
                                            int broadcast,
@@ -144,11 +150,6 @@ void silc_server_send_notify_signoff(SilcServer server,
                                     SilcClientID *client_id,
                                     unsigned int client_id_len,
                                     char *message);
-void silc_server_send_notify_server_signoff(SilcServer server,
-                                           SilcSocketConnection sock,
-                                           int broadcast,
-                                           SilcServerID *server_id,
-                                           unsigned int server_id_len);
 void silc_server_send_notify_topic_set(SilcServer server,
                                       SilcSocketConnection sock,
                                       int broadcast,
index cea428ca50164802dec07327ac020aec9b868d6d..240771e25df889f48ccfde83b14e99353b8b7914 100644 (file)
@@ -875,6 +875,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth)
            silc_server_get_public_key_auth(server, ctx->auth_data,
                                            sign, &auth_data_len,
                                            ctx->ske);
+           auth_data = silc_calloc(auth_data_len, sizeof(*auth_data));
+           memcpy(auth_data, sign, auth_data_len);
            break;
          }
        }
index b96d50435e2a85900674efa5afa5634ed2b47071..3003bbbff1fcf08e22671de803957248480f9081 100644 (file)
@@ -2087,18 +2087,9 @@ void silc_server_free_sock_user_data(SilcServer server,
     {
       SilcServerEntry user_data = (SilcServerEntry)sock->user_data;
 
-      /* Send REMOVE_ID packet to routers. */
-      if (!server->standalone && server->router)
-       silc_server_send_notify_server_signoff(server, 
-                                              server->router->connection,
-                                              server->server_type == 
-                                              SILC_SERVER ?
-                                              FALSE : TRUE, user_data->id, 
-                                              SILC_ID_SERVER_LEN);
-
-      /* Then also free all client entries that this server owns as
-        they will become invalid now as well. */
-      silc_server_remove_clients_by_server(server, user_data);
+      /* Free all client entries that this server owns as they will
+        become invalid now as well. */
+      silc_server_remove_clients_by_server(server, user_data, TRUE);
 
       /* If this was our primary router connection then we're lost to
         the outside world. */
@@ -2132,17 +2123,38 @@ void silc_server_free_sock_user_data(SilcServer server,
 
 /* This function is used to remove all client entries by the server `entry'.
    This is called when the connection is lost to the server. In this case
-   we must invalidate all the client entries owned by the server `entry'. */
+   we must invalidate all the client entries owned by the server `entry'. 
+   If the `server_signoff' is TRUE then the SERVER_SIGNOFF notify is
+   distributed to our local clients. */
 
 int silc_server_remove_clients_by_server(SilcServer server, 
-                                        SilcServerEntry entry)
+                                        SilcServerEntry entry,
+                                        int server_signoff)
 {
   SilcIDCacheList list = NULL;
   SilcIDCacheEntry id_cache = NULL;
   SilcClientEntry client = NULL;
+  SilcBuffer idp;
+  SilcClientEntry *clients = NULL;
+  unsigned int clients_c = 0;
+  unsigned char **argv = NULL;
+  unsigned int *argv_lens = NULL, *argv_types = NULL, argc = 0;
+  int i;
 
   SILC_LOG_DEBUG(("Start"));
 
+  if (server_signoff) {
+    idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
+    argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
+    argv_lens = silc_realloc(argv_lens,  sizeof(*argv_lens) * (argc + 1));
+    argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
+    argv[argc] = idp->data;
+    argv_lens[argc] = idp->len;
+    argv_types[argc] = argc + 1;
+    argc++;
+    silc_buffer_free(idp);
+  }
+
   if (silc_idcache_find_by_id(server->local_list->clients, 
                              SILC_ID_CACHE_ANY, SILC_ID_CLIENT, &list)) {
 
@@ -2151,15 +2163,37 @@ int silc_server_remove_clients_by_server(SilcServer server,
        client = (SilcClientEntry)id_cache->context;
        
        if (client->router != entry) {
+         if (server_signoff && client->connection) {
+           clients = silc_realloc(clients, 
+                                  sizeof(*clients) * (clients_c + 1));
+           clients[clients_c] = client;
+           clients_c++;
+         }
+
          if (!silc_idcache_list_next(list, &id_cache))
            break;
          else
            continue;
        }
 
+       if (server_signoff) {
+         idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+         argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
+         argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
+                                  (argc + 1));
+         argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
+                                   (argc + 1));
+         argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
+         memcpy(argv[argc], idp->data, idp->len);
+         argv_lens[argc] = idp->len;
+         argv_types[argc] = argc + 1;
+         argc++;
+         silc_buffer_free(idp);
+       }
+
        /* Remove the client entry */
-       silc_server_remove_from_channels(server, NULL, client, TRUE, 
-                                        NULL, TRUE);
+       silc_server_remove_from_channels(server, NULL, client, FALSE, 
+                                        NULL, FALSE);
        silc_idlist_del_client(server->local_list, client);
 
        if (!silc_idcache_list_next(list, &id_cache))
@@ -2177,15 +2211,37 @@ int silc_server_remove_clients_by_server(SilcServer server,
        client = (SilcClientEntry)id_cache->context;
        
        if (client->router != entry) {
+         if (server_signoff && client->connection) {
+           clients = silc_realloc(clients, 
+                                  sizeof(*clients) * (clients_c + 1));
+           clients[clients_c] = client;
+           clients_c++;
+         }
+
          if (!silc_idcache_list_next(list, &id_cache))
            break;
          else
            continue;
        }
 
+       if (server_signoff) {
+         idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+         argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
+         argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
+                                  (argc + 1));
+         argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
+                                   (argc + 1));
+         argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
+         memcpy(argv[argc], idp->data, idp->len);
+         argv_lens[argc] = idp->len;
+         argv_types[argc] = argc + 1;
+         argc++;
+         silc_buffer_free(idp);
+       }
+
        /* Remove the client entry */
-       silc_server_remove_from_channels(server, NULL, client, TRUE,
-                                        NULL, TRUE);
+       silc_server_remove_from_channels(server, NULL, client, FALSE,
+                                        NULL, FALSE);
        silc_idlist_del_client(server->global_list, client);
 
        if (!silc_idcache_list_next(list, &id_cache))
@@ -2194,7 +2250,40 @@ int silc_server_remove_clients_by_server(SilcServer server,
     }
     silc_idcache_list_free(list);
   }
-  
+
+  /* Send the SERVER_SIGNOFF notify */
+  if (server_signoff) {
+    SilcBuffer args;
+
+    /* Send SERVER_SIGNOFF notify to our primary router */
+    if (!server->standalone && server->router) {
+      args = silc_argument_payload_encode(1, argv, argv_lens,
+                                         argv_types);
+      silc_server_send_notify_args(server, 
+                                  server->router->connection,
+                                  server->server_type == 
+                                  SILC_SERVER ? FALSE : TRUE, 
+                                  SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
+                                  argc, args);
+      silc_buffer_free(args);
+    }
+
+    args = silc_argument_payload_encode(argc, argv, argv_lens,
+                                       argv_types);
+    /* Send to local clients */
+    for (i = 0; i < clients_c; i++) {
+      silc_server_send_notify_args(server, clients[i]->connection,
+                                  FALSE, SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
+                                  argc, args);
+    }
+
+    silc_free(clients);
+    silc_buffer_free(args);
+    silc_free(argv);
+    silc_free(argv_lens);
+    silc_free(argv_types);
+  }
+
   return TRUE;
 }
 
@@ -2353,7 +2442,7 @@ void silc_server_remove_from_channels(SilcServer server,
       silc_server_create_channel_key(server, channel, 0);
       
       /* Send the channel key to the channel. The key of course is not sent
-        to the client who was removed f rom the channel. */
+        to the client who was removed from the channel. */
       silc_server_send_channel_key(server, client->connection, channel, 
                                   server->server_type == SILC_ROUTER ? 
                                   FALSE : !server->standalone);
index 0cd883a5ec12ca1d05dfdbfe45bd95f8a3fdc7d8..e0d277ba360f97f872d70c9ca9e5ba2d8be19a42 100644 (file)
@@ -104,7 +104,8 @@ void silc_server_free_sock_user_data(SilcServer server,
 int silc_server_channel_has_global(SilcChannelEntry channel);
 int silc_server_channel_has_local(SilcChannelEntry channel);
 int silc_server_remove_clients_by_server(SilcServer server, 
-                                        SilcServerEntry entry);
+                                        SilcServerEntry entry,
+                                        int server_signoff);
 void silc_server_remove_from_channels(SilcServer server, 
                                      SilcSocketConnection sock,
                                      SilcClientEntry client,
index 5c08f6da147311dc2338e7885ed2fd323a035e03..1e734c3363a394934ed9ee31d1201982b6e23e0f 100644 (file)
@@ -1282,10 +1282,15 @@ ID's sent in arguments are sent inside ID Payload.
       Sent when server quits SILC network.  Those clients from this server
       that are on channels must be removed from the channel.
 
-      Max Arguments:  1
-          Arguments:  (1) <Server ID>
-
-      The <Server ID> is the server's ID.
+      Max Arguments:  2000
+          Arguments:  (1) <Server ID>   (n) [<Client ID>   [...]
+
+      The <Server ID> is the server's ID.  The rest of the arguments are
+      the Client ID's of the client's who are coming from this server and
+      are thus quitting the SILC network also.  If the maximum number of
+      arguments are reached another SILC_NOTIFY_TYPE_SERVER_SIGNOFF notify
+      packet must be sent.  When this notify packet is sent between routers
+      the Client ID's may be omitted.
 
 
 12    SILC_NOTIFY_TYPE_KICKED
index 40508c302e087aaac3c8de4818360d1d456308d7..6c6f800d6eba1df6f6ba77d8bcee57a3b17e8037 100644 (file)
@@ -3008,26 +3008,52 @@ List of all defined commands in SILC follows.
             SILC_STATUS_ERR_NO_CLIENT_ID
 
 
-   20   SILC_COMMAND_RESTART
+   20   SILC_COMMAND_BAN
 
-        Max Arguments:  0
-            Arguments:  None
+        Max Arguments:  3
+            Arguments:  (1) <Channel ID>         (2) [<adding client>]
+                        (3) [<removing client>]
+
+        This command is used to manage the ban list of the channel
+        indicated by the <Channel ID>.  A client that is banned from
+        channel is no longer able to join the channel.  The client which
+        is executing this command must have at least channel operator
+        privileges on the channel.
+
+        The <adding client> and <removing client> are used to add to and
+        remove from the ban list.  The format of the <adding client> and
+        the <removing client> is of following format:
+
+            [<nickname>[@<server>]!][<username>]@[<hostname>]
+
+        The server must send the notify type SILC_NOTIFY_TYPE_BAN to its
+        primary router after adding to or removing from the ban list.
+        The wildcards may be used with this command.  If adding or removing
+        from than one clients then the lists are an comma (`,') separated
+        list.
+
+        If this command is executed without the ban arguments the command
+        merely replies with the current ban list.
 
-        This command may only be used by server operator to force a
-        server to restart itself.
 
         Reply messages to the command:
 
-        Max Arguments:  1
-            Arguments:  (1) <Status Payload>
+        Max Arguments:  3
+            Arguments:  (1) <Status Payload>  (2) <Channel ID>
+                        (3) [<ban list>]
 
-        This command replies only with Status Payload.
+        This command replies with the <Channel ID> of the channel and
+        the current <ban list> of the channel if it exists.
 
         Status messages:
 
             SILC_STATUS_OK
             SILC_STATUS_ERR_NOT_REGISTERED
-            SILC_STATUS_ERR_NO_SERVER_PRIV
+            SILC_STATUS_ERR_TOO_MANY_PARAMS
+            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID
+            SILC_STATUS_ERR_NO_CHANNEL_ID
+            SILC_STATUS_ERR_NOT_ON_CHANNEL
+            SILC_STATUS_ERR_NO_CHANNEL_PRIV
 
 
    21   SILC_COMMAND_CLOSE
@@ -3200,54 +3226,6 @@ List of all defined commands in SILC follows.
             SILC_STATUS_ERR_NOT_ON_CHANNEL
 
 
-   26   SILC_COMMAND_BAN
-
-        Max Arguments:  3
-            Arguments:  (1) <Channel ID>         (2) [<adding client>]
-                        (3) [<removing client>]
-
-        This command is used to manage the ban list of the channel
-        indicated by the <Channel ID>.  A client that is banned from
-        channel is no longer able to join the channel.  The client which
-        is executing this command must have at least channel operator
-        privileges on the channel.
-
-        The <adding client> and <removing client> are used to add to and
-        remove from the ban list.  The format of the <adding client> and
-        the <removing client> is of following format:
-
-            [<nickname>[@<server>]!][<username>]@[<hostname>]
-
-        The server must send the notify type SILC_NOTIFY_TYPE_BAN to its
-        primary router after adding to or removing from the ban list.
-        The wildcards may be used with this command.  If adding or removing
-        from than one clients then the lists are an comma (`,') separated
-        list.
-
-        If this command is executed without the ban arguments the command
-        merely replies with the current ban list.
-
-
-        Reply messages to the command:
-
-        Max Arguments:  3
-            Arguments:  (1) <Status Payload>  (2) <Channel ID>
-                        (3) [<ban list>]
-
-        This command replies with the <Channel ID> of the channel and
-        the current <ban list> of the channel if it exists.
-
-        Status messages:
-
-            SILC_STATUS_OK
-            SILC_STATUS_ERR_NOT_REGISTERED
-            SILC_STATUS_ERR_TOO_MANY_PARAMS
-            SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID
-            SILC_STATUS_ERR_NO_CHANNEL_ID
-            SILC_STATUS_ERR_NOT_ON_CHANNEL
-            SILC_STATUS_ERR_NO_CHANNEL_PRIV
-
-
    27 - 199
 
         Currently undefined commands.
index afb95fc0d52c755f010cdb3d74acc938c02afc61..14b3b591f053c83c7a190fcf3155b3f84fb399a9 100644 (file)
@@ -688,9 +688,7 @@ void silc_client_notify_by_server(SilcClient client,
     /* Get comment */
     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
 
-    /* Notify application. The channel entry is sent last as this notify
-       is for channel but application don't know it from the arguments
-       sent by server. */
+    /* Notify application. */
     client->ops->notify(client, conn, type, client_entry, tmp);
 
     if (client_entry != conn->local_entry) {
@@ -713,6 +711,68 @@ void silc_client_notify_by_server(SilcClient client,
 
     break;
     
+  case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
+    {
+      /*
+       * A server quit the SILC network and some clients must be removed
+       * from channels as they quit as well.
+       */
+      SilcClientEntry *clients = NULL;
+      unsigned int clients_count = 0;
+      int i;
+
+      for (i = 1; i < silc_argument_get_arg_num(args); i++) {
+       /* Get Client ID */
+       tmp = silc_argument_get_arg_type(args, i + 1, &tmp_len);
+       if (tmp) {
+         client_id = silc_id_payload_parse_id(tmp, tmp_len);
+         if (!client_id)
+           goto out;
+         
+         /* Get the client entry */
+         client_entry = silc_client_get_client_by_id(client, conn, client_id);
+         if (client_entry) {
+           clients = silc_realloc(clients, sizeof(*clients) * 
+                                  (clients_count + 1));
+           clients[clients_count] = client_entry;
+           clients_count++;
+         }
+         silc_free(client_id);
+       }
+      }
+      client_id = NULL;
+
+      /* Notify application. We don't keep server entries so the server
+        entry is returned as NULL. The client's are returned as array
+        of SilcClientEntry pointers. */
+      client->ops->notify(client, conn, type, NULL, clients, clients_count);
+
+      for (i = 0; i < clients_count; i++) {
+       /* Remove client from all channels */
+       client_entry = clients[i];
+       if (client_entry == conn->local_entry)
+         continue;
+
+       silc_client_remove_from_channels(client, conn, client_entry);
+       silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
+                              client_entry->id);
+       if (client_entry->nickname)
+         silc_free(client_entry->nickname);
+       if (client_entry->server)
+         silc_free(client_entry->server);
+       if (client_entry->id)
+         silc_free(client_entry->id);
+       if (client_entry->send_key)
+         silc_cipher_free(client_entry->send_key);
+       if (client_entry->receive_key)
+         silc_cipher_free(client_entry->receive_key);
+       silc_free(client_entry);
+      }
+      silc_free(clients);
+
+    }
+    break;
+
   default:
     break;
   }
index 3a3e8d1490de584dd6d224873d4edcd9e7bc46fa..9f068e13acc6899edf7c6baa8e300cf8566ed59c 100644 (file)
@@ -48,8 +48,7 @@ SilcClientCommand silc_command_list[] =
   SILC_CLIENT_CMD(cmode, CMODE, "CMODE", SILC_CF_LAG | SILC_CF_REG, 4),
   SILC_CLIENT_CMD(cumode, CUMODE, "CUMODE", SILC_CF_LAG | SILC_CF_REG, 5),
   SILC_CLIENT_CMD(kick, KICK, "KICK", SILC_CF_LAG | SILC_CF_REG, 4),
-  SILC_CLIENT_CMD(restart, RESTART, "RESTART",
-                 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER, 2),
+  SILC_CLIENT_CMD(ban, BAN, "BAN", SILC_CF_LAG | SILC_CF_REG, 3),
   SILC_CLIENT_CMD(close, CLOSE, "CLOSE",
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER, 3),
   SILC_CLIENT_CMD(shutdown, SHUTDOWN, "SHUTDOWN",
@@ -58,7 +57,6 @@ SilcClientCommand silc_command_list[] =
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER, 3),
   SILC_CLIENT_CMD(leave, LEAVE, "LEAVE", SILC_CF_LAG | SILC_CF_REG, 2),
   SILC_CLIENT_CMD(users, USERS, "USERS", SILC_CF_LAG | SILC_CF_REG, 2),
-  SILC_CLIENT_CMD(ban, BAN, "BAN", SILC_CF_LAG | SILC_CF_REG, 3),
 
   { NULL, 0, NULL, 0, 0 },
 };
@@ -808,7 +806,7 @@ SILC_CLIENT_CMD_FUNC(info)
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
   SilcClientConnection conn = cmd->conn;
   SilcBuffer buffer;
-  char *name;
+  char *name = NULL;
 
   if (!cmd->conn) {
     SILC_NOT_CONNECTED(cmd->client, cmd->conn);
@@ -816,17 +814,21 @@ SILC_CLIENT_CMD_FUNC(info)
     goto out;
   }
 
-  if (cmd->argc < 2)
-    name = strdup(conn->remote_host);
-  else
+  if (cmd->argc == 2)
     name = strdup(cmd->argv[1]);
 
   /* Send the command */
-  buffer = silc_command_payload_encode_va(SILC_COMMAND_INFO, 0, 1, 
-                                         1, name, strlen(name));
+  if (name)
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_INFO, 0, 1, 
+                                           1, name, strlen(name));
+  else
+    buffer = silc_command_payload_encode(SILC_COMMAND_INFO, 0,
+                                        NULL, NULL, NULL, 0);
   silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, 
                          0, NULL, NULL, buffer->data, buffer->len, TRUE);
   silc_buffer_free(buffer);
+  if (name)
+    silc_free(name);
 
   /* Notify application */
   COMMAND;
@@ -1741,13 +1743,16 @@ SILC_CLIENT_CMD_FUNC(connect)
   silc_client_command_free(cmd);
 }
 
-/* RESTART command. Restarts the server. You must be server operator
-   to be able to use this command. */
+/* Command BAN. This is used to manage the ban list of the channel. */
 
-SILC_CLIENT_CMD_FUNC(restart)
+SILC_CLIENT_CMD_FUNC(ban)
 {
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
-  SilcBuffer buffer;
+  SilcClientConnection conn = cmd->conn;
+  SilcChannelEntry channel;
+  SilcBuffer buffer, chidp;
+  int type = 0;
+  char *name, *ban = NULL;
 
   if (!cmd->conn) {
     SILC_NOT_CONNECTED(cmd->client, cmd->conn);
@@ -1755,12 +1760,58 @@ SILC_CLIENT_CMD_FUNC(restart)
     goto out;
   }
 
-  buffer = silc_command_payload_encode(SILC_COMMAND_RESTART, 0,
-                                      NULL, NULL, NULL, 0);
-  silc_client_packet_send(cmd->client, cmd->conn->sock, SILC_PACKET_COMMAND, 
-                         NULL, 0, NULL, NULL, 
-                         buffer->data, buffer->len, TRUE);
+  if (cmd->argc < 2) {
+    cmd->client->ops->say(cmd->client, conn, 
+                  "Usage: /BAN <channel> "
+                  "[+|-[<nickname>[@<server>[!<username>[@hostname>]]]]]");
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  if (cmd->argv[1][0] == '*') {
+    if (!conn->current_channel) {
+      cmd->client->ops->say(cmd->client, conn, "You are not on any channel");
+      COMMAND_ERROR;
+      goto out;
+    }
+
+    channel = conn->current_channel;
+  } else {
+    name = cmd->argv[1];
+
+    channel = silc_client_get_channel(cmd->client, conn, name);
+    if (!channel) {
+      cmd->client->ops->say(cmd->client, conn, "You are on that channel");
+      COMMAND_ERROR;
+      goto out;
+    }
+  }
+
+  if (cmd->argc == 3) {
+    if (cmd->argv[2][0] == '+')
+      type = 2;
+    else
+      type = 3;
+
+    ban = cmd->argv[2];
+    ban++;
+  }
+
+  chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
+
+  /* Send the command */
+  if (ban)
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_BAN, 0, 2, 
+                                           1, chidp->data, chidp->len,
+                                           type, ban, strlen(ban));
+  else
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_BAN, 0, 1, 
+                                           1, chidp->data, chidp->len);
+
+  silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, 
+                         0, NULL, NULL, buffer->data, buffer->len, TRUE);
   silc_buffer_free(buffer);
+  silc_buffer_free(chidp);
 
   /* Notify application */
   COMMAND;
@@ -1998,80 +2049,3 @@ SILC_CLIENT_CMD_FUNC(users)
  out:
   silc_client_command_free(cmd);
 }
-
-/* Command BAN. This is used to manage the ban list of the channel. */
-
-SILC_CLIENT_CMD_FUNC(ban)
-{
-  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
-  SilcClientConnection conn = cmd->conn;
-  SilcChannelEntry channel;
-  SilcBuffer buffer, chidp;
-  int type = 0;
-  char *name, *ban = NULL;
-
-  if (!cmd->conn) {
-    SILC_NOT_CONNECTED(cmd->client, cmd->conn);
-    COMMAND_ERROR;
-    goto out;
-  }
-
-  if (cmd->argc < 2) {
-    cmd->client->ops->say(cmd->client, conn, 
-                  "Usage: /BAN <channel> "
-                  "[+|-[<nickname>[@<server>[!<username>[@hostname>]]]]]");
-    COMMAND_ERROR;
-    goto out;
-  }
-
-  if (cmd->argv[1][0] == '*') {
-    if (!conn->current_channel) {
-      cmd->client->ops->say(cmd->client, conn, "You are not on any channel");
-      COMMAND_ERROR;
-      goto out;
-    }
-
-    channel = conn->current_channel;
-  } else {
-    name = cmd->argv[1];
-
-    channel = silc_client_get_channel(cmd->client, conn, name);
-    if (!channel) {
-      cmd->client->ops->say(cmd->client, conn, "You are on that channel");
-      COMMAND_ERROR;
-      goto out;
-    }
-  }
-
-  if (cmd->argc == 3) {
-    if (cmd->argv[2][0] == '+')
-      type = 2;
-    else
-      type = 3;
-
-    ban = cmd->argv[2];
-    ban++;
-  }
-
-  chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
-
-  /* Send the command */
-  if (ban)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_BAN, 0, 2, 
-                                           1, chidp->data, chidp->len,
-                                           type, ban, strlen(ban));
-  else
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_BAN, 0, 1, 
-                                           1, chidp->data, chidp->len);
-
-  silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL, 
-                         0, NULL, NULL, buffer->data, buffer->len, TRUE);
-  silc_buffer_free(buffer);
-  silc_buffer_free(chidp);
-
-  /* Notify application */
-  COMMAND;
-
- out:
-  silc_client_command_free(cmd);
-}
index 64af6d8ca24c78fa2ec576b6439da4fe63c21f17..485a17ea7014bca9d687ee3d9b37fd4c44e449ec 100644 (file)
@@ -147,12 +147,11 @@ SILC_CLIENT_CMD_FUNC(umode);
 SILC_CLIENT_CMD_FUNC(cmode);
 SILC_CLIENT_CMD_FUNC(cumode);
 SILC_CLIENT_CMD_FUNC(kick);
-SILC_CLIENT_CMD_FUNC(restart);
+SILC_CLIENT_CMD_FUNC(ban);
 SILC_CLIENT_CMD_FUNC(close);
 SILC_CLIENT_CMD_FUNC(shutdown);
 SILC_CLIENT_CMD_FUNC(silcoper);
 SILC_CLIENT_CMD_FUNC(leave);
 SILC_CLIENT_CMD_FUNC(users);
-SILC_CLIENT_CMD_FUNC(ban);
 
 #endif
index be33b9caff544d137de43e3a0fa92a692539c5b6..b748e280856a61c9528f93b5ba367eb2b7979980 100644 (file)
@@ -57,7 +57,6 @@ SilcClientCommandReply silc_command_reply_list[] =
   SILC_CLIENT_CMD_REPLY(cmode, CMODE),
   SILC_CLIENT_CMD_REPLY(cumode, CUMODE),
   SILC_CLIENT_CMD_REPLY(kick, KICK),
-  SILC_CLIENT_CMD_REPLY(restart, RESTART),
   SILC_CLIENT_CMD_REPLY(close, CLOSE),
   SILC_CLIENT_CMD_REPLY(shutdown, SHUTDOWN),
   SILC_CLIENT_CMD_REPLY(silcoper, SILCOPER),
@@ -1395,33 +1394,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(connect)
   silc_client_command_reply_free(cmd);
 }
 
-SILC_CLIENT_CMD_REPLY_FUNC(restart)
-{
-  SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
-  SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
-  SilcCommandStatus status;
-  unsigned char *tmp;
-
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
-  if (status != SILC_STATUS_OK) {
-    cmd->client->ops->say(cmd->client, conn,
-            "%s", silc_client_command_status_message(status));
-    COMMAND_REPLY_ERROR;
-    goto out;
-  }
-
-  /* Notify application */
-  COMMAND_REPLY((ARGS));
-
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_RESTART);
-
- out:
-  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_RESTART);
-  silc_client_command_reply_free(cmd);
-}
 SILC_CLIENT_CMD_REPLY_FUNC(close)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
index f1ebd1c3c3d20a6f8754e4b1c8c53a06e87fa954..30e669893e8bc7baaac9e117955195054d434058 100644 (file)
@@ -92,7 +92,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(umode);
 SILC_CLIENT_CMD_REPLY_FUNC(cmode);
 SILC_CLIENT_CMD_REPLY_FUNC(cumode);
 SILC_CLIENT_CMD_REPLY_FUNC(kick);
-SILC_CLIENT_CMD_REPLY_FUNC(restart);
 SILC_CLIENT_CMD_REPLY_FUNC(close);
 SILC_CLIENT_CMD_REPLY_FUNC(shutdown);
 SILC_CLIENT_CMD_REPLY_FUNC(silcoper);
index 875b808c63c5ec8aa68264006cac784d59a09924..07e060cc94f0d9ae8431ad0ba3512acb400c593e 100644 (file)
@@ -298,8 +298,6 @@ void silc_client_get_clients_by_list(SilcClient client,
     silc_free(client_id);
     silc_buffer_pull(client_id_list, idp_len);
   }
-  silc_buffer_push(client_id_list, client_id_list->data - 
-                  client_id_list->head);
 
   /* Query the client information from server if the list included clients
      that we don't know about. */
@@ -320,6 +318,8 @@ void silc_client_get_clients_by_list(SilcClient client,
                                silc_client_command_get_clients_list_callback, 
                                (void *)in);
 
+    silc_buffer_push(client_id_list, client_id_list->data - 
+                    client_id_list->head);
     silc_buffer_free(res_cmd);
     silc_free(res_argv);
     silc_free(res_argv_lens);
@@ -327,6 +327,9 @@ void silc_client_get_clients_by_list(SilcClient client,
     return;
   }
 
+  silc_buffer_push(client_id_list, client_id_list->data - 
+                  client_id_list->head);
+
   /* We have the clients in cache, get them and call the completion */
   silc_client_command_get_clients_list_callback((void *)in);
 }
index 16124421af678bb091c334f1bbb3133e7c307889..064c3b21d945dd83a3ba489e18d27a8dcc04ac49 100644 (file)
@@ -428,6 +428,53 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
  * Connection Authentication protocol functions
  */
 
+static int
+silc_client_get_public_key_auth(SilcClient client,
+                               char *filepath,
+                               unsigned char *auth_data,
+                               unsigned int *auth_data_len,
+                               SilcSKE ske)
+{
+  int len;
+  SilcPKCS pkcs;
+  SilcBuffer auth;
+  SilcPublicKey pub_key;
+
+  if (!silc_pkcs_load_public_key(filepath,&pub_key, SILC_PKCS_FILE_PEM))
+    if (!silc_pkcs_load_public_key(filepath, &pub_key, SILC_PKCS_FILE_BIN))
+      return FALSE;
+
+  silc_pkcs_alloc(pub_key->name, &pkcs);
+  if (!silc_pkcs_public_key_set(pkcs, pub_key)) {
+    silc_pkcs_free(pkcs);
+    silc_pkcs_public_key_free(pub_key);
+    return FALSE;
+  }
+
+  /* Make the authentication data. Protocol says it is HASH plus
+     KE Start Payload. */
+  len = ske->hash_len + ske->start_payload_copy->len;
+  auth = silc_buffer_alloc(len);
+  silc_buffer_pull_tail(auth, len);
+  silc_buffer_format(auth,
+                    SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
+                    SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
+                                         ske->start_payload_copy->len),
+                    SILC_STR_END);
+
+  if (silc_pkcs_sign(pkcs, auth->data, auth->len, auth_data, auth_data_len)) {
+    silc_pkcs_free(pkcs);
+    silc_buffer_free(auth);
+    silc_pkcs_public_key_free(pub_key);
+    return TRUE;
+  }
+
+  silc_pkcs_free(pkcs);
+  silc_buffer_free(auth);
+  silc_pkcs_public_key_free(pub_key);
+  return FALSE;
+}
+
 SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
 {
   SilcProtocol protocol = (SilcProtocol)context;
@@ -474,8 +521,17 @@ SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
        break;
 
       case SILC_AUTH_PUBLIC_KEY:
-       /* XXX */
-       break;
+       {
+         unsigned char sign[1024];
+
+         /* Public key authentication */
+         silc_client_get_public_key_auth(client, ctx->auth_data,
+                                         sign, &auth_data_len, 
+                                         ctx->ske);
+         auth_data = silc_calloc(auth_data_len, sizeof(*auth_data));
+         memcpy(auth_data, sign, auth_data_len);
+         break;
+       }
       }
 
       payload_len = 4 + auth_data_len;
index d9c19deb5f93313d6c54bff2d3410322c3487895..1dc0f438b6250116926a12280e3c88994ff9f8fa 100644 (file)
@@ -526,10 +526,8 @@ SilcBuffer silc_channel_key_payload_encode(unsigned short id_len,
 void silc_channel_key_payload_free(SilcChannelKeyPayload payload)
 {
   if (payload) {
-    if (payload->id)
-      silc_free(payload->id);
-    if (payload->cipher)
-      silc_free(payload->cipher);
+    silc_free(payload->id);
+    silc_free(payload->cipher);
     if (payload->key) {
       memset(payload->key, 0, payload->key_len);
       silc_free(payload->key);
index acd3b1cb421bed5a709ed57fc425c60887985a7a..16b384edb5521e4ce89e13cd2532593eecc56891 100644 (file)
@@ -79,13 +79,12 @@ typedef enum {
 #define SILC_COMMAND_CMODE             17
 #define SILC_COMMAND_CUMODE            18
 #define SILC_COMMAND_KICK              19
-#define        SILC_COMMAND_RESTART            20
+#define SILC_COMMAND_BAN               20
 #define        SILC_COMMAND_CLOSE              21
 #define        SILC_COMMAND_SHUTDOWN           22
 #define SILC_COMMAND_SILCOPER          23
 #define SILC_COMMAND_LEAVE             24
 #define SILC_COMMAND_USERS             25
-#define SILC_COMMAND_BAN               26
 
 /* Reserved */
 #define SILC_COMMAND_RESERVED           255
index e3c8169dafb35166cdb7f1dad098faf1c38eb149..210a3e1fb7d1ca198e3114fef725d266256b740b 100644 (file)
@@ -135,6 +135,35 @@ SilcBuffer silc_notify_payload_encode(SilcNotifyType type, unsigned int argc,
   return buffer;
 }
 
+/* Same as above but takes argument from the `args' Argument Payload. */
+
+SilcBuffer silc_notify_payload_encode_args(SilcNotifyType type, 
+                                          unsigned int argc,
+                                          SilcBuffer args)
+{
+  SilcBuffer buffer;
+  int len;
+
+  len = 5 + (args ? args->len : 0);
+  buffer = silc_buffer_alloc(len);
+  silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
+  silc_buffer_format(buffer,
+                    SILC_STR_UI_SHORT(type),
+                    SILC_STR_UI_SHORT(len),
+                    SILC_STR_UI_CHAR(argc),
+                    SILC_STR_END);
+
+  if (args) {
+    silc_buffer_pull(buffer, 5);
+    silc_buffer_format(buffer,
+                      SILC_STR_UI_XNSTRING(args->data, args->len),
+                      SILC_STR_END);
+    silc_buffer_push(buffer, 5);
+  }
+
+  return buffer;
+}
+
 /* Free's notify payload */
 
 void silc_notify_payload_free(SilcNotifyPayload payload)
index 08a2fc918c4125d625f00db7c984bff796b3e54b..ca64ca14e5c63b2035d0b2a1382eafaff3523c1d 100644 (file)
@@ -50,6 +50,9 @@ typedef unsigned short SilcNotifyType;
 SilcNotifyPayload silc_notify_payload_parse(SilcBuffer buffer);
 SilcBuffer silc_notify_payload_encode(SilcNotifyType type, unsigned int argc, 
                                      va_list ap);
+SilcBuffer silc_notify_payload_encode_args(SilcNotifyType type, 
+                                          unsigned int argc,
+                                          SilcBuffer args);
 void silc_notify_payload_free(SilcNotifyPayload payload);
 SilcNotifyType silc_notify_get_type(SilcNotifyPayload payload);
 unsigned int silc_notify_get_arg_num(SilcNotifyPayload payload);
index 8d4f4248806e13c454e811e225bc8cea2af04d09..c919a94aa106a14244159a4ce2aae710d48dd793 100644 (file)
@@ -125,8 +125,9 @@ void *silc_id_payload_parse_id(unsigned char *data, unsigned int len)
   SilcBuffer buffer;
   SilcIdType type;
   unsigned short idlen;
-  unsigned char *id;
+  unsigned char *id_data;
   int ret;
+  void *id;
 
   buffer = silc_buffer_alloc(len);
   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
@@ -145,14 +146,16 @@ void *silc_id_payload_parse_id(unsigned char *data, unsigned int len)
     goto err;
 
   ret = silc_buffer_unformat(buffer,
-                            SILC_STR_UI_XNSTRING_ALLOC(&id, idlen),
+                            SILC_STR_UI_XNSTRING_ALLOC(&id_data, idlen),
                             SILC_STR_END);
   if (ret == -1)
     goto err;
 
   silc_buffer_free(buffer);
 
-  return silc_id_str2id(id, idlen, type);
+  id = silc_id_str2id(id_data, idlen, type);
+  silc_free(id_data);
+  return id;
 
  err:
   silc_buffer_free(buffer);
@@ -192,6 +195,7 @@ void silc_id_payload_free(SilcIDPayload payload)
 {
   if (payload) {
     silc_free(payload->id);
+    silc_free(payload);
   }
 }
 
@@ -401,6 +405,8 @@ void silc_argument_payload_free(SilcArgumentPayload payload)
       silc_free(payload->argv[i]);
 
     silc_free(payload->argv);
+    silc_free(payload->argv_lens);
+    silc_free(payload->argv_types);
     silc_free(payload);
   }
 }
index a1d4fb66b88da8d1272be7c985e78bc44ea14d83..06cd2a0cc579a3cc89604a8c7e122249fac5a9d6 100644 (file)
@@ -27,8 +27,6 @@ typedef struct SilcArgumentPayloadStruct *SilcArgumentPayload;
 
 /* Prototypes */
 SilcIDPayload silc_id_payload_parse(SilcBuffer buffer);
-SilcArgumentPayload silc_argument_payload_parse(SilcBuffer buffer,
-                                               unsigned int argc);
 SilcIDPayload silc_id_payload_parse_data(unsigned char *data, 
                                         unsigned int len);
 void *silc_id_payload_parse_id(unsigned char *data, unsigned int len);
@@ -38,6 +36,8 @@ SilcIdType silc_id_payload_get_type(SilcIDPayload payload);
 void *silc_id_payload_get_id(SilcIDPayload payload);
 unsigned char *silc_id_payload_get_data(SilcIDPayload payload);
 unsigned int silc_id_payload_get_len(SilcIDPayload payload);
+SilcArgumentPayload silc_argument_payload_parse(SilcBuffer buffer,
+                                               unsigned int argc);
 SilcBuffer silc_argument_payload_encode(unsigned int argc,
                                        unsigned char **argv,
                                        unsigned int *argv_lens,
index d3484983c7ce2f0d39fae90c744d79e5232714f7..4e6971bc9288381e46271eadfbcdae6c0214a350 100644 (file)
@@ -250,6 +250,7 @@ void silc_hmac_make_internal(SilcHmac hmac, unsigned char *data,
   hash->hash->final(hash_context, mac);
   memcpy(return_hash, mac, hmac->hmac->len);
   memset(mac, 0, sizeof(mac));
+  silc_free(hash_context);
 }
 
 /* Create the HMAC. This is thee make_hmac function pointer.  This
index ea9313f10760585a5c14c522f49ba5685bbbd1e2..ce14c9faca8312f7d5e7decaa426563745d6c09d 100644 (file)
@@ -250,7 +250,7 @@ SilcSKEStatus silc_ske_payload_ke_decode(SilcSKE ske,
 {
   SilcSKEStatus status = SILC_SKE_STATUS_ERROR;
   SilcSKEKEPayload *payload;
-  unsigned char *x;
+  unsigned char *x = NULL;
   unsigned short x_len;
   unsigned int tot_len = 0, len2;
   int ret;
@@ -331,6 +331,8 @@ SilcSKEStatus silc_ske_payload_ke_decode(SilcSKE ske,
     silc_free(payload->pk_data);
   if (payload->sign_data)
     silc_free(payload->sign_data);
+  if (x)
+    silc_free(x);
   silc_free(payload);
   ske->status = status;
   return status;
index 688594c92cb092ec0bda0c79d57e27aff928cd40..45ecdbff1251b42a798d878ef43475a24194ce34 100644 (file)
@@ -35,10 +35,6 @@ void silc_task_queue_alloc(SilcTaskQueue *new, int valid)
   /* Set the pointers */
   (*new)->valid = valid;
   (*new)->task = NULL;
-  (*new)->register_task = silc_task_register;
-  (*new)->unregister_task = silc_task_unregister;
-  (*new)->set_iotype = silc_task_set_iotype;
-  (*new)->reset_iotype = silc_task_reset_iotype;
 }
 
 /* Free's a task queue. */
@@ -75,8 +71,7 @@ SilcTask silc_task_add(SilcTaskQueue queue, SilcTask new,
        but after tasks with higher priority. */
     prev = task->prev;
     while(prev != task) {
-      if (prev->priority > SILC_TASK_PRI_LOW &&
-         prev->priority <= SILC_TASK_PRI_REALTIME)
+      if (prev->priority > SILC_TASK_PRI_LOW)
        break;
       prev = prev->prev;
     }
@@ -100,49 +95,6 @@ SilcTask silc_task_add(SilcTaskQueue queue, SilcTask new,
       next->prev = new;
     }
     break;
-  case SILC_TASK_PRI_HIGH:
-    /* High priority. The task is added before lower priority tasks
-       but after tasks with higher priority. */
-    prev = task->prev;
-    while(prev != task) {
-      if (prev->priority > SILC_TASK_PRI_NORMAL &&
-         prev->priority <= SILC_TASK_PRI_REALTIME)
-       break;
-      prev = prev->prev;
-    }
-    if (prev == task) {
-      /* There are only lower priorities in the list, we will
-        sit before them and become the first task in the queue. */
-      prev = task->prev;
-      new->prev = prev;
-      new->next = task;
-      task->prev = new;
-      prev->next = new;
-
-      /* We are now the first task in queue */
-      queue->task = new;
-    } else {
-      /* Found a spot from the list, add the task to the list. */
-      next = prev->next;
-      new->prev = prev;
-      new->next = next;
-      prev->next = new;
-      next->prev = new;
-    }
-    break;
-  case SILC_TASK_PRI_REALTIME:
-    /* Highest priority. The task is added at the head of the list. 
-       The last registered task is added to the very head of the list
-       thus we get the LIFO (Last-In-First-Out) order. */
-    prev = task->prev;
-    new->prev = prev;
-    new->next = task;
-    prev->next = new;
-    task->prev = new;
-
-    /* We are the first task in the queue */
-    queue->task = new;
-    break;
   default:
     silc_free(new);
     return NULL;
@@ -151,32 +103,6 @@ SilcTask silc_task_add(SilcTaskQueue queue, SilcTask new,
   return new;
 }
 
-#if 0
-void dump_tasks(SilcTaskQueue queue)
-{
-  SilcTask first, prev;
-
-  if (!queue->task)
-    return;
-
-  first = queue->task;
-
-  fprintf(stderr, "\nqueue->task:\t%p\t%d\n", queue->task,
-         queue->task->timeout.tv_sec);
-
-  prev = first->prev;
-  while (1) {
-    if (first == prev)
-      break;
-
-    fprintf(stderr, "task       :\t%p\t%d\n", prev, prev->timeout.tv_sec);
-
-    prev = prev->prev;
-  }
-  fprintf(stderr, "\n");
-}
-#endif
-
 /* Return the timeout task with smallest timeout. */
 
 static SilcTask silc_task_get_first(SilcTaskQueue queue, SilcTask first)
@@ -291,92 +217,48 @@ SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask new,
       queue->task = new;
     }
     break;
-  case SILC_TASK_PRI_HIGH:
-    /* High priority. The task is added before lower priority tasks
-       but after tasks with higher priority. */
-    while(prev != task) {
-
-      /* If we have longer timeout than with the task head of us
-        we have found our spot. */
-      if (silc_task_timeout_compare(&prev->timeout, &new->timeout))
-       break;
-
-      /* If we are equal size of timeout, priority kicks in place. */
-      if (!silc_task_timeout_compare(&new->timeout, &prev->timeout))
-       if (prev->priority >= SILC_TASK_PRI_HIGH)
-         break;
-
-      /* We have shorter timeout or higher priority, compare to next one. */
-      prev = prev->prev;
-    }
-    /* Found a spot from the list, add the task to the list. */
-    next = prev->next;
-    new->prev = prev;
-    new->next = next;
-    prev->next = new;
-    next->prev = new;
-    
-    if (prev == task) {
-      /* Check if we are going to be the first task in the queue */
-      if (silc_task_timeout_compare(&prev->timeout, &new->timeout))
-       break;
-      if (!silc_task_timeout_compare(&new->timeout, &prev->timeout))
-       if (prev->priority >= SILC_TASK_PRI_HIGH)
-         break;
-
-      /* We are now the first task in queue */
-      queue->task = new;
-    }
-    break;
-  case SILC_TASK_PRI_REALTIME:
-    /* Highest priority. The task is added at the head of the list. 
-       The last registered task is added to the very head of the list
-       thus we get the LIFO (Last-In-First-Out) order. */
-    next = task->next;
-    while(next != task) {
-
-      /* If we have shorter timeout than the next task we've found
-        our spot. */
-      if (silc_task_timeout_compare(&new->timeout, &next->timeout))
-       break;
-
-      /* If we are equal size of timeout we will be first. */
-      if (!silc_task_timeout_compare(&next->timeout, &new->timeout))
-       break;
-
-      /* We have longer timeout, compare to next one. */
-      next = next->next;
-    }
-    /* Found a spot from the list, add the task to the list. */
-    prev = next->prev;
-    new->next = next;
-    new->prev = prev;
-    prev->next = new;
-    next->prev = new;
-    
-    if (next == task) {
-      /* Check if we are going to be the first task in the queue */
-      if (silc_task_timeout_compare(&next->timeout, &new->timeout))
-       break;
-
-      /* We are now the first task in queue */
-      queue->task = new;
-    }
   default:
     silc_free(new);
     return NULL;
   }
 
-#if 0
-  dump_tasks(queue);
-#endif
-
   return new;
 }
 
-/* Registers a new task into the task queue. The task becomes valid
-   automatically when it is registered. Returns a pointer to the 
-   registered task. */
+/* Registers a new task to the task queue. Arguments are as follows:
+      
+   SilcTaskQueue queue        Queue where the task is to be registered
+   int fd                     File descriptor
+   SilcTaskCallback cb        Callback function to call
+   void *context              Context to be passed to callback function
+   long seconds               Seconds to timeout
+   long useconds              Microseconds to timeout
+   SilcTaskType type          Type of the task
+   SilcTaskPriority priority  Priority of the task
+   
+   The same function is used to register all types of tasks. The type
+   argument tells what type of the task is. Note that when registering
+   non-timeout tasks one should also pass 0 as timeout as timeout will
+   be ignored anyway. Also, note, that one cannot register timeout task
+   with 0 timeout. There cannot be zero timeouts, passing zero means
+   no timeout is used for the task and SILC_TASK_FD_TASK is used as
+   default task type in this case.
+   
+   One should be careful not to register timeout tasks to the non-timeout
+   task queue, because they will never expire. As one should not register
+   non-timeout tasks to timeout task queue because they will never get
+   scheduled.
+   
+   There is a one distinct difference between timeout and non-timeout
+   tasks when they are executed. Non-timeout tasks remain on the task
+   queue after execution. Timeout tasks, however, are removed from the
+   task queue after they have expired. It is safe to re-register a task 
+   in its own callback function. It is also safe to unregister a task 
+   in a callback function.
+   
+   Generic tasks apply to all file descriptors, however, one still must
+   pass the correct file descriptor to the function when registering
+   generic tasks. */
 
 SilcTask silc_task_register(SilcTaskQueue queue, int fd, 
                            SilcTaskCallback cb, void *context, 
@@ -499,12 +381,7 @@ int silc_task_remove(SilcTaskQueue queue, SilcTask task)
        queue->task = NULL;
       if (queue->task == old)
        queue->task = silc_task_get_first(queue, next);
-      /*queue->task = next;*/
       
-#if 0
-      dump_tasks(queue);
-#endif
-
       silc_free(old);
       return TRUE;
     }
@@ -515,9 +392,15 @@ int silc_task_remove(SilcTaskQueue queue, SilcTask task)
   }
 }
 
-/* Unregisters a task from the task queue. This is the unregister_task
-   function pointer in task queue object. One should use this function
-   to unregister tasks. This function invalidates the task. */
+/* Unregisters a task already in the queue. Arguments are as follows:
+   
+   SilcTaskQueue queue      Queue where from the task is unregistered
+   SilcTask task            Task to be unregistered
+   
+   The same function is used to unregister timeout and non-timeout 
+   tasks. One can also unregister all tasks from the queue by passing
+   SILC_ALL_TASKS as task to the function. It is safe to unregister
+   a task in a callback function. */
 
 void silc_task_unregister(SilcTaskQueue queue, SilcTask task)
 {
@@ -616,15 +499,27 @@ void silc_task_unregister_by_context(SilcTaskQueue queue, void *context)
   }
 }
 
-/* Sets the I/O mask for the task. Only one I/O type can be set at a
-   time. */
+/* Sets the I/O type of the task. The scheduler checks for this value
+   and a task must always have at least one of the I/O types set at 
+   all time. When registering new task the type is set by default to
+   SILC_TASK_READ. If the task doesn't perform reading one must reset
+   the value to SILC_TASK_WRITE.
+   
+   The type sent as argumenet is masked into the task. If the tasks 
+   I/O mask already includes this type this function has no effect. 
+   Only one I/O type can be added at once. If the task must perform
+   both reading and writing one must call this function for value
+   SILC_TASK_WRITE as well. */
 
 void silc_task_set_iotype(SilcTask task, int type)
 {
   task->iomask |= (1L << type);
 }
 
-/* Resets the I/O mask to the type sent as argument. */
+/* Resets the mask to the type sent as argument. Note that this resets
+   the previous values to zero and then adds the type sent as argument.
+   This function can be used to remove one of the types masked earlier
+   to the task. */
 
 void silc_task_reset_iotype(SilcTask task, int type)
 {
index 6fff792ed983573fb562577f7e42fbd5bc981b77..1c211c8dd152b2dd3f354608dce1ffbf8808e98e 100644 (file)
@@ -135,33 +135,10 @@ typedef enum {
        For non-timeout tasks this priority behaves same way. Tasks are run 
        in FIFO (First-In-First-Out) order.
 
-   SILC_TASK_PRI_HIGH
-   
-       High priority for important tasks. This priority should be used only
-       for important tasks. Life is very fair for tasks with this priority.
-       These tasks are run as soon as its timeout has expired. They are run 
-       before normal or lower tasks, respectively. For non-timeout tasks
-       this priority behaves same way. Tasks are run in FIFO order.
-
-   SILC_TASK_PRI_REALTIME
-
-       Highest priority. This priority should be used very carefully because
-       it can make the scheduler extremely unfair to other tasks. The task
-       will be run as soon as its timeout has expired. The task is run before
-       any other task. It is also quaranteed that the last registered task
-       with this priority is the first task to be run when its timeout
-       expires. Tasks are run in LIFO (Last-In-First-Out) order. To make
-       scheduler fair there should never be more than one task in the queue
-       with this priority. Currently none of the tasks in SILC are important
-       enough to use this priority. For non-timeout tasks this priority
-       behaves same way.
-
 */
 typedef enum {
   SILC_TASK_PRI_LOW,
   SILC_TASK_PRI_NORMAL,
-  SILC_TASK_PRI_HIGH,
-  SILC_TASK_PRI_REALTIME,
 } SilcTaskPriority;
 
 /* 
@@ -206,94 +183,12 @@ typedef enum {
        task queue this is not defined. This is meant only for internal
        use and it should be considered to be read-only field.
 
-   SilcTask (*register_task)(SilcTaskQueue, int, 
-                             SilcTaskCallback, void *, 
-                            long, long, 
-                            SilcTaskType,
-                            SilcTaskPriority)
-
-       Registers a new task to the task queue. Arguments are as follows:
-
-       SilcTaskQueue queue        Queue where the task is to be registered
-       int fd                     File descriptor
-       SilcTaskCallback cb        Callback function to call
-       void *context              Context to be passed to callback function
-       long seconds               Seconds to timeout
-       long useconds              Microseconds to timeout
-       SilcTaskType type          Type of the task
-       SilcTaskPriority priority  Priority of the task
-
-       The same function is used to register all types of tasks. The type
-       argument tells what type of the task is. Note that when registering
-       non-timeout tasks one should also pass 0 as timeout as timeout will
-       be ignored anyway. Also, note, that one cannot register timeout task
-       with 0 timeout. There cannot be zero timeouts, passing zero means
-       no timeout is used for the task and SILC_TASK_FD_TASK is used as
-       default task type in this case.
-
-       One should be careful not to register timeout tasks to the non-timeout
-       task queue, because they will never expire. As one should not register
-       non-timeout tasks to timeout task queue because they will never get
-       scheduled.
-
-       There is a one distinct difference between timeout and non-timeout
-       tasks when they are executed. Non-timeout tasks remain on the task
-       queue after execution. Timeout tasks, however, are removed from the
-       task queue after they have expired. It is safe to re-register a task 
-       in its own callback function. It is also safe to unregister a task 
-       in a callback function.
-
-       Generic tasks apply to all file descriptors, however, one still must
-       pass the correct file descriptor to the function when registering
-       generic tasks.
-
-   void (*unregister_task)(SilcTaskQueue, SilcTask)
-
-       Unregisters a task already in the queue. Arguments are as follows:
-
-       SilcTaskQueue queue      Queue where from the task is unregistered
-       SilcTask task            Task to be unregistered
-
-       The same function is used to unregister timeout and non-timeout 
-       tasks. One can also unregister all tasks from the queue by passing
-       SILC_ALL_TASKS as task to the function. It is safe to unregister
-       a task in a callback function.
-
-   void (*set_iotype)(SilcTask, int type)
-
-       Sets the I/O type of the task. The scheduler checks for this value
-       and a task must always have at least one of the I/O types set at 
-       all time. When registering new task the type is set by default to
-       SILC_TASK_READ. If the task doesn't perform reading one must reset
-       the value to SILC_TASK_WRITE.
-
-       The type sent as argumenet is masked into the task. If the tasks 
-       I/O mask already includes this type this function has no effect. 
-       Only one I/O type can be added at once. If the task must perform
-       both reading and writing one must call this function for value
-       SILC_TASK_WRITE as well.
-
-   void (*reset_iotype)(SilcTask, int type)
-
-       Resets the mask to the type sent as argument. Note that this resets
-       the previous values to zero and then adds the type sent as argument.
-       This function can be used to remove one of the types masked earlier
-       to the task.
-
 */
 
 typedef struct SilcTaskQueueStruct {
   SilcTask task;
   int valid;
   struct timeval timeout;
-
-  /* Method functions */
-  SilcTask (*register_task)(struct SilcTaskQueueStruct *, int, 
-                           SilcTaskCallback, void *, long, long, 
-                           SilcTaskType, SilcTaskPriority);
-  void (*unregister_task)(struct SilcTaskQueueStruct *, SilcTask);
-  void (*set_iotype)(SilcTask, int type);
-  void (*reset_iotype)(SilcTask, int type);
 } SilcTaskQueueObject;
 
 typedef SilcTaskQueueObject *SilcTaskQueue;