Added KILL command.
authorPekka Riikonen <priikone@silcnet.org>
Mon, 19 Mar 2001 15:19:06 +0000 (15:19 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 19 Mar 2001 15:19:06 +0000 (15:19 +0000)
14 files changed:
CHANGES
TODO
apps/silc/client_ops.c
apps/silcd/command.c
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/packet_send.h
apps/silcd/server.c
apps/silcd/server.h
apps/silcd/testi2.conf
lib/silcclient/client_notify.c
lib/silcclient/command.c
lib/silcclient/command_reply.c
lib/silccore/silcsockconn.h

diff --git a/CHANGES b/CHANGES
index 65971497fc78f89e1d1ce37dbeb0f4110dceac32..47a58cafaacbee6b26f5ae867222cf50e1634c74 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,48 @@
+Mon Mar 19 16:13:07 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Added silc_server_get_client_route to resolve the route to
+         the client indicated by the client ID.  Affected file is
+         silcd/server.[ch].
+
+       * Added silc_server_relay_packet as general function to relay
+         packet to arbitrary destination.  This deprecates functions
+         like _send_private_message_key, _relay_notify etc.  Affected
+         file is silcd/packet_send.[ch].
+
+         Removed silc_server_send_key_agreement, 
+         silc_server_send_private_message_key and
+         silc_server_packet_relay_notify functions from the file
+         silcd/packet_send.[ch].
+
+       * Updated TODO.
+
+       * Implemented the SILC_NOTIFY_TYPE_KILLED notify handling in the
+         server.  Affected file silcd/packet_receive.[ch].
+
+       * Implemented the KILL command to the client.  Implemented the
+         SILC_NOTIFY_TYPE_KILLED notify handling in the client library.
+         Affected files lib/silcclient/command[_reply].c and
+         lib/silcclient/client_notify.c.  Implemented the KILL notify
+         printing in the user inteface.
+
+       * Fixed a lot silc_parse_nick memory leaks from the client
+         library in the file lib/silcclient/command.c.
+
+       * Changed the silc_server_send_notify_on_channels's `sender'
+         argument from SilcSocketConnection to SilcClientEntry to 
+         check the sender as entry and not as connection object and not
+         to send to the client provided as argument.  The affected file
+         is silcd/packet_send.[ch].
+
+       * The notify packets that are destined directly to the client used
+         to not to be processed by the server.  Now changed that and the
+         server processes all notify packets.  After relaying the packet
+         to the client the notify packet is processed in the server.
+
+       * The silc_server_free_client_data now checks whether there is
+         pending outgoing traffic for the client and purges the data to
+         the network before removing the client entry.
+
 Sun Mar 18 21:02:47 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Added SILC_NOTIFY_TYPE_KILLED notify type.  It is sent when
@@ -16,7 +61,7 @@ Sun Mar 18 21:02:47 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
          whereto relay the notify.  Affected file is 
          silcd/packet_receive.[ch].
 
-       * Implemented KILL command to the server.
+       * Implemented the KILL command to the server.
 
        * Updated TODO.
 
diff --git a/TODO b/TODO
index 133d751a31ad2ddf48231c0a3a196bf1968d0afe..8001456e7e45af26a5efbed0ea39ee968208bed2 100644 (file)
--- a/TODO
+++ b/TODO
@@ -100,18 +100,6 @@ TODO In SILC Client Library
 TODO In SILC Server
 ===================
 
- o Functions such as silc_server_private_message, 
-   silc_server_private_message_key and 
-   silc_server_packet_process_relay_notify can be optimized.  I don't think
-   we need such a big lookups to lookup the router to the destination,
-   it is already provided in the client entry.
-
- o silc_server_send_key_agreement and silc_server_send_private_message_key
-   are one and same function (also silc_server_send_private_message is
-   almost same function).  These should be unified to one generic named
-   function and use that (silc_server_packet_relay_notify is also
-   same function).
-
  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
index edb174780aac618b6d59e871daf6dcfb1a468a45..f2096c6662546c0bd6bc2ef62d5c46fc92a418aa 100644 (file)
@@ -250,6 +250,25 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
     }
     break;
 
+  case SILC_NOTIFY_TYPE_KILLED:
+    client_entry = va_arg(vp, SilcClientEntry);
+    tmp = va_arg(vp, char *);
+    channel_entry = va_arg(vp, SilcChannelEntry);
+
+    if (client_entry == conn->local_entry) {
+      snprintf(message, sizeof(message), 
+              "You have been killed from the SILC Network %s%s%s", 
+              tmp ? "(" : "", tmp ? tmp : "", tmp ? ")" : "");
+    } else {
+      snprintf(message, sizeof(message), 
+              "%s%s%s has been killed from the SILC Network %s%s%s", 
+              client_entry->nickname, 
+              client_entry->server ? "@" : "",
+              client_entry->server ? client_entry->server : "",
+              tmp ? "(" : "", tmp ? tmp : "", tmp ? ")" : "");
+    }
+    break;
+
   default:
     break;
   }
index 4133e7ce0517a4e380f9353dc1d2bf2e7e970532..0cded085d1121da73102d33eb43359cb7af5238f 100644 (file)
@@ -1965,7 +1965,7 @@ SILC_TASK_CALLBACK(silc_server_command_quit_cb)
   /* Free all client specific data, such as client entry and entires
      on channels this client may be on. */
   silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
-                              q->signoff);
+                              TRUE, q->signoff);
   q->sock->user_data = NULL;
 
   /* Close the connection on our side */
@@ -2021,16 +2021,19 @@ SILC_SERVER_CMD_FUNC(kill)
   SilcClientEntry remote_client;
   SilcClientID *client_id;
   unsigned char *tmp, *comment;
-  unsigned int tmp_len;
-  SilcBuffer idp;
+  unsigned int tmp_len, tmp_len2;
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
 
   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
     goto out;
 
-  if (server->server_type != SILC_ROUTER)
+  /* KILL command works only on router */
+  if (server->server_type != SILC_ROUTER) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+                                         SILC_STATUS_ERR_NO_ROUTER_PRIV);
     goto out;
+  }
 
   /* Check whether client has the permissions. */
   if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
@@ -2067,27 +2070,32 @@ SILC_SERVER_CMD_FUNC(kill)
   }
 
   /* Get comment */
-  comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+  comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
+  if (tmp_len2 > 128)
+    comment = NULL;
 
   /* Send reply to the sender */
   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
                                        SILC_STATUS_OK);
 
+  /* Send the KILL notify packets. First send it to the channel, then
+     to our primary router and then directly to the client who is being
+     killed right now. */
+
   /* Send KILLED notify to the channels. It is not sent to the client
      as it will be sent differently destined directly to the client and not
      to the channel. */
-  idp = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
-  silc_server_send_notify_on_channels(server, remote_client->connection, 
+  silc_server_send_notify_on_channels(server, remote_client, 
                                      remote_client, SILC_NOTIFY_TYPE_KILLED,
                                      comment ? 2 : 1,
-                                     idp->data, idp->len,
-                                     comment, comment ? strlen(comment) : 0);
-  silc_buffer_free(idp);
+                                     tmp, tmp_len,
+                                     comment, comment ? tmp_len2 : 0);
 
-  /* Remove the client from all channels. This generates new keys to the
-     channels as well. */
-  silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
-                                  NULL, TRUE);
+  /* Send KILLED notify to primary route */
+  if (!server->standalone)
+    silc_server_send_notify_killed(server, server->router->connection, TRUE,
+                                  remote_client->id, SILC_ID_CLIENT_LEN,
+                                  comment);
 
   /* Send KILLED notify to the client directly */
   silc_server_send_notify_killed(server, remote_client->connection ? 
@@ -2096,13 +2104,23 @@ SILC_SERVER_CMD_FUNC(kill)
                                 remote_client->id, SILC_ID_CLIENT_LEN,
                                 comment);
 
-  /* Send KILLED notify to primary route */
-  if (!server->standalone)
-    silc_server_send_notify_killed(server, server->router->connection,
-                                  server->server_type == SILC_ROUTER ?
-                                  TRUE : FALSE,
-                                  remote_client->id, SILC_ID_CLIENT_LEN,
-                                  comment);
+  /* Remove the client from all channels. This generates new keys to the
+     channels as well. */
+  silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
+                                  NULL, TRUE);
+
+  /* Remove the client entry, If it is locally connected then we will also
+     disconnect the client here */
+  if (remote_client->data.registered && remote_client->connection) {
+    /* Remove locally conneted client */
+    SilcSocketConnection sock = remote_client->connection;
+    silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
+    silc_server_close_connection(server, sock);
+  } else {
+    /* Remove remote client */
+    if (!silc_idlist_del_client(server->global_list, remote_client))
+      silc_idlist_del_client(server->local_list, remote_client);
+  }
 
  out:
   silc_server_command_free(cmd);
@@ -3873,7 +3891,7 @@ SILC_SERVER_CMD_FUNC(users)
 
   /* Send reply */
   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
-                                               SILC_STATUS_OK, 0, 4,
+                                               SILC_STATUS_OK, ident, 4,
                                                2, channel_id, channel_id_len,
                                                3, lc, 4,
                                                4, client_id_list->data,
index 83e19b8ef7ef4d8949adcc009ca129b43ea7ce65..2a40208bc9616c73d89294ede1cf0c8d1c467338 100644 (file)
 
 extern char *server_version;
 
-/* Check whereto relay the received notify packet that was destined
-   to a client. */
-
-static void 
-silc_server_packet_process_relay_notify(SilcServer server,
-                                       SilcSocketConnection sock,
-                                       SilcPacketContext *packet)
-{
-  SilcClientID *id;
-  SilcServerEntry router;
-  SilcSocketConnection dst_sock;
-  SilcClientEntry client;
-  SilcIDListData idata;
-
-  SILC_LOG_DEBUG(("Start"));
-
-  /* Decode destination Client ID */
-  id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT);
-  if (!id) {
-    SILC_LOG_ERROR(("Could not decode destination Client ID, dropped"));
-    return;
-  }
-
-  /* If the destination belongs to our server we don't have to route
-     the packet anywhere but to send it to the local destination. */
-  client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
-  if (client) {
-    /* It exists, now deliver the packet to the destination */
-    dst_sock = (SilcSocketConnection)client->connection;
-
-    /* If we are router and the client has router then the client is in
-       our cell but not directly connected to us. */
-    if (server->server_type == SILC_ROUTER && client->router) {
-      /* We are of course in this case the client's router thus the real
-        "router" of the client is the server who owns the client. Thus
-        we will send the packet to that server. */
-      router = (SilcServerEntry)client->router;
-      idata = (SilcIDListData)router;
-      silc_server_packet_relay_notify(server, router->connection,
-                                     idata->send_key,
-                                     idata->hmac,
-                                     packet);
-      silc_free(id);
-      return;
-    }
-
-    /* Seems that client really is directly connected to us */
-    idata = (SilcIDListData)client;
-    silc_server_packet_relay_notify(server, dst_sock, 
-                                   idata->send_key,
-                                   idata->hmac, packet);
-    silc_free(id);
-    return;
-  }
-
-  /* Destination belongs to someone not in this server. If we are normal
-     server our action is to send the packet to our router. */
-  if (server->server_type == SILC_SERVER && !server->standalone) {
-    router = server->router;
-
-    /* Send to primary route */
-    if (router) {
-      dst_sock = (SilcSocketConnection)router->connection;
-      idata = (SilcIDListData)router;
-      silc_server_packet_relay_notify(server, dst_sock, 
-                                     idata->send_key,
-                                     idata->hmac, packet);
-    }
-    silc_free(id);
-    return;
-  }
-
-  /* We are router and we will perform route lookup for the destination 
-     and send the packet to fastest route. */
-  if (server->server_type == SILC_ROUTER && !server->standalone) {
-    /* Check first that the ID is valid */
-    client = silc_idlist_find_client_by_id(server->global_list, id, NULL);
-    if (client) {
-      dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT);
-      router = (SilcServerEntry)dst_sock->user_data;
-      idata = (SilcIDListData)router;
-
-      /* Get fastest route and send packet. */
-      if (router)
-       silc_server_packet_relay_notify(server, dst_sock, 
-                                       idata->send_key,
-                                       idata->hmac, packet);
-      silc_free(id);
-      return;
-    }
-  }
-}
-
 /* Received notify packet. Server can receive notify packets from router. 
    Server then relays the notify messages to clients if needed. */
 
@@ -145,11 +52,22 @@ void silc_server_notify(SilcServer server,
       packet->src_id_type != SILC_ID_SERVER)
     return;
 
-  /* If the packet is destined directly to a client, then we don't
-     process the packet at all but just relay it to the client. */
-  if (packet->dst_id_type == SILC_ID_CLIENT) {
-    silc_server_packet_process_relay_notify(server, sock, packet);
+  if (!packet->dst_id)
     return;
+
+  /* If the packet is destined directly to a client then relay the packet
+     before processing it. */
+  if (packet->dst_id_type == SILC_ID_CLIENT) {
+    SilcIDListData idata;
+    SilcSocketConnection dst_sock;
+
+    /* Get the route to the client */
+    dst_sock = silc_server_get_client_route(server, packet->dst_id,
+                                           packet->dst_id_len, &idata);
+    if (dst_sock)
+      /* Relay the packet */
+      silc_server_relay_packet(server, dst_sock, idata->send_key,
+                              idata->hmac, packet, TRUE);
   }
 
   /* If we are router and this packet is not already broadcast packet
@@ -639,13 +557,65 @@ void silc_server_notify(SilcServer server,
     break;
 
   case SILC_NOTIFY_TYPE_KILLED:
-    /* 
-     * Distribute the notify to local clients on channels
-     */
+    {
+      /* 
+       * Distribute the notify to local clients on channels
+       */
+      unsigned char *id;
+      unsigned int id_len;
     
-    SILC_LOG_DEBUG(("KILLED notify"));
+      SILC_LOG_DEBUG(("KILLED notify"));
       
-    break;
+      /* Get client ID */
+      id = silc_argument_get_arg_type(args, 1, &id_len);
+      if (!id)
+       goto out;
+      client_id = silc_id_payload_parse_id(id, id_len);
+      if (!client_id)
+       goto out;
+
+      /* If the the client is not in local list we check global list */
+      client = silc_idlist_find_client_by_id(server->local_list, 
+                                            client_id, NULL);
+      if (!client) {
+       client = silc_idlist_find_client_by_id(server->global_list, 
+                                              client_id, NULL);
+       if (!client) {
+         silc_free(client_id);
+         goto out;
+       }
+      }
+      silc_free(client_id);
+
+      /* If the client is one of ours, then close the connection to the
+        client now. This removes the client from all channels as well. */
+      if (packet->dst_id_type == SILC_ID_CLIENT && client->data.registered &&
+         client->connection) {
+       sock = client->connection;
+       silc_server_free_client_data(server, NULL, client, FALSE, NULL);
+       silc_server_close_connection(server, sock);
+       break;
+      }
+
+      /* Get comment */
+      tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+      if (tmp_len > 128)
+       tmp = NULL;
+
+      /* Send the notify to local clients on the channels except to the
+        client who is killed. */
+      silc_server_send_notify_on_channels(server, client, client,
+                                         SILC_NOTIFY_TYPE_KILLED, 
+                                         tmp ? 2 : 1,
+                                         id, id_len, 
+                                         tmp, tmp_len);
+
+      /* Remove the client from all channels */
+      silc_server_remove_from_channels(server, NULL, client, FALSE, NULL, 
+                                      FALSE);
+
+      break;
+    }
 
     /* Ignore rest of the notify types for now */
   case SILC_NOTIFY_TYPE_NONE:
@@ -722,10 +692,7 @@ void silc_server_private_message(SilcServer server,
                                 SilcSocketConnection sock,
                                 SilcPacketContext *packet)
 {
-  SilcClientID *id;
-  SilcServerEntry router;
   SilcSocketConnection dst_sock;
-  SilcClientEntry client;
   SilcIDListData idata;
 
   SILC_LOG_DEBUG(("Start"));
@@ -737,82 +704,15 @@ void silc_server_private_message(SilcServer server,
   if (!packet->dst_id)
     return;
 
-  /* Decode destination Client ID */
-  id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT);
-  if (!id) {
-    SILC_LOG_ERROR(("Could not decode destination Client ID, dropped"));
+  /* Get the route to the client */
+  dst_sock = silc_server_get_client_route(server, packet->dst_id,
+                                         packet->dst_id_len, &idata);
+  if (!dst_sock)
     return;
-  }
-
-  /* If the destination belongs to our server we don't have to route
-     the message anywhere but to send it to the local destination. */
-  client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
-  if (client) {
-    /* It exists, now deliver the message to the destination */
-    dst_sock = (SilcSocketConnection)client->connection;
-
-    /* If we are router and the client has router then the client is in
-       our cell but not directly connected to us. */
-    if (server->server_type == SILC_ROUTER && client->router) {
-      /* We are of course in this case the client's router thus the real
-        "router" of the client is the server who owns the client. Thus
-        we will send the packet to that server. */
-      router = (SilcServerEntry)client->router;
-      idata = (SilcIDListData)router;
-
-      silc_server_send_private_message(server, router->connection,
-                                      idata->send_key,
-                                      idata->hmac,
-                                      packet);
-      silc_free(id);
-      return;
-    }
-
-    /* Seems that client really is directly connected to us */
-    idata = (SilcIDListData)client;
-    silc_server_send_private_message(server, dst_sock, 
-                                    idata->send_key,
-                                    idata->hmac, packet);
-    silc_free(id);
-    return;
-  }
 
-  /* Destination belongs to someone not in this server. If we are normal
-     server our action is to send the packet to our router. */
-  if (server->server_type == SILC_SERVER && !server->standalone) {
-    router = server->router;
-
-    /* Send to primary route */
-    if (router) {
-      dst_sock = (SilcSocketConnection)router->connection;
-      idata = (SilcIDListData)router;
-      silc_server_send_private_message(server, dst_sock, 
-                                      idata->send_key,
-                                      idata->hmac, packet);
-    }
-    silc_free(id);
-    return;
-  }
-
-  /* We are router and we will perform route lookup for the destination 
-     and send the message to fastest route. */
-  if (server->server_type == SILC_ROUTER && !server->standalone) {
-    /* Check first that the ID is valid */
-    client = silc_idlist_find_client_by_id(server->global_list, id, NULL);
-    if (client) {
-      dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT);
-      router = (SilcServerEntry)dst_sock->user_data;
-      idata = (SilcIDListData)router;
-
-      /* Get fastest route and send packet. */
-      if (router)
-       silc_server_send_private_message(server, dst_sock, 
-                                        idata->send_key,
-                                        idata->hmac, packet);
-      silc_free(id);
-      return;
-    }
-  }
+  /* Send the private message */
+  silc_server_send_private_message(server, dst_sock, idata->send_key,
+                                  idata->hmac, packet);
 }
 
 /* Received private message key packet.. This packet is never for us. It is to
@@ -824,10 +724,7 @@ void silc_server_private_message_key(SilcServer server,
                                     SilcSocketConnection sock,
                                     SilcPacketContext *packet)
 {
-  SilcClientID *id;
-  SilcServerEntry router;
   SilcSocketConnection dst_sock;
-  SilcClientEntry client;
   SilcIDListData idata;
 
   SILC_LOG_DEBUG(("Start"));
@@ -839,81 +736,15 @@ void silc_server_private_message_key(SilcServer server,
   if (!packet->dst_id)
     return;
 
-  /* Decode destination Client ID */
-  id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT);
-  if (!id) {
-    SILC_LOG_ERROR(("Could not decode destination Client ID, dropped"));
+  /* Get the route to the client */
+  dst_sock = silc_server_get_client_route(server, packet->dst_id,
+                                         packet->dst_id_len, &idata);
+  if (!dst_sock)
     return;
-  }
-
-  /* If the destination belongs to our server we don't have to route
-     the message anywhere but to send it to the local destination. */
-  client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
-  if (client) {
-    /* It exists, now deliver the message to the destination */
-    dst_sock = (SilcSocketConnection)client->connection;
 
-    /* If we are router and the client has router then the client is in
-       our cell but not directly connected to us. */
-    if (server->server_type == SILC_ROUTER && client->router) {
-      /* We are of course in this case the client's router thus the real
-        "router" of the client is the server who owns the client. Thus
-        we will send the packet to that server. */
-      router = (SilcServerEntry)client->router;
-      idata = (SilcIDListData)router;
-      silc_server_send_private_message_key(server, router->connection,
-                                          idata->send_key,
-                                          idata->hmac,
-                                          packet);
-      silc_free(id);
-      return;
-    }
-
-    /* Seems that client really is directly connected to us */
-    idata = (SilcIDListData)client;
-    silc_server_send_private_message_key(server, dst_sock, 
-                                        idata->send_key,
-                                        idata->hmac, packet);
-    silc_free(id);
-    return;
-  }
-
-  /* Destination belongs to someone not in this server. If we are normal
-     server our action is to send the packet to our router. */
-  if (server->server_type == SILC_SERVER && !server->standalone) {
-    router = server->router;
-
-    /* Send to primary route */
-    if (router) {
-      dst_sock = (SilcSocketConnection)router->connection;
-      idata = (SilcIDListData)router;
-      silc_server_send_private_message_key(server, dst_sock, 
-                                          idata->send_key,
-                                          idata->hmac, packet);
-    }
-    silc_free(id);
-    return;
-  }
-
-  /* We are router and we will perform route lookup for the destination 
-     and send the packet to fastest route. */
-  if (server->server_type == SILC_ROUTER && !server->standalone) {
-    /* Check first that the ID is valid */
-    client = silc_idlist_find_client_by_id(server->global_list, id, NULL);
-    if (client) {
-      dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT);
-      router = (SilcServerEntry)dst_sock->user_data;
-      idata = (SilcIDListData)router;
-
-      /* Get fastest route and send packet. */
-      if (router)
-       silc_server_send_private_message_key(server, dst_sock, 
-                                            idata->send_key,
-                                            idata->hmac, packet);
-      silc_free(id);
-      return;
-    }
-  }
+  /* Relay the packet */
+  silc_server_relay_packet(server, dst_sock, idata->send_key,
+                          idata->hmac, packet, FALSE);
 }
 
 /* Processes incoming command reply packet. The command reply packet may
@@ -1771,10 +1602,7 @@ void silc_server_key_agreement(SilcServer server,
                               SilcSocketConnection sock,
                               SilcPacketContext *packet)
 {
-  SilcClientID *id;
-  SilcServerEntry router;
   SilcSocketConnection dst_sock;
-  SilcClientEntry client;
   SilcIDListData idata;
 
   SILC_LOG_DEBUG(("Start"));
@@ -1786,79 +1614,13 @@ void silc_server_key_agreement(SilcServer server,
   if (!packet->dst_id)
     return;
 
-  /* Decode destination Client ID */
-  id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT);
-  if (!id) {
-    SILC_LOG_ERROR(("Could not decode destination Client ID, dropped"));
-    return;
-  }
-
-  /* If the destination belongs to our server we don't have to route
-     the packet anywhere but to send it to the local destination. */
-  client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
-  if (client) {
-    /* It exists, now deliver the packet to the destination */
-    dst_sock = (SilcSocketConnection)client->connection;
-
-    /* If we are router and the client has router then the client is in
-       our cell but not directly connected to us. */
-    if (server->server_type == SILC_ROUTER && client->router) {
-      /* We are of course in this case the client's router thus the real
-        "router" of the client is the server who owns the client. Thus
-        we will send the packet to that server. */
-      router = (SilcServerEntry)client->router;
-      idata = (SilcIDListData)router;
-      silc_server_send_key_agreement(server, router->connection,
-                                    idata->send_key,
-                                    idata->hmac,
-                                    packet);
-      silc_free(id);
-      return;
-    }
-
-    /* Seems that client really is directly connected to us */
-    idata = (SilcIDListData)client;
-    silc_server_send_key_agreement(server, dst_sock, 
-                                  idata->send_key,
-                                  idata->hmac, packet);
-    silc_free(id);
-    return;
-  }
-
-  /* Destination belongs to someone not in this server. If we are normal
-     server our action is to send the packet to our router. */
-  if (server->server_type == SILC_SERVER && !server->standalone) {
-    router = server->router;
-
-    /* Send to primary route */
-    if (router) {
-      dst_sock = (SilcSocketConnection)router->connection;
-      idata = (SilcIDListData)router;
-      silc_server_send_key_agreement(server, dst_sock, 
-                                    idata->send_key,
-                                    idata->hmac, packet);
-    }
-    silc_free(id);
+  /* Get the route to the client */
+  dst_sock = silc_server_get_client_route(server, packet->dst_id,
+                                         packet->dst_id_len, &idata);
+  if (!dst_sock)
     return;
-  }
 
-  /* We are router and we will perform route lookup for the destination 
-     and send the packet to fastest route. */
-  if (server->server_type == SILC_ROUTER && !server->standalone) {
-    /* Check first that the ID is valid */
-    client = silc_idlist_find_client_by_id(server->global_list, id, NULL);
-    if (client) {
-      dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT);
-      router = (SilcServerEntry)dst_sock->user_data;
-      idata = (SilcIDListData)router;
-
-      /* Get fastest route and send packet. */
-      if (router)
-       silc_server_send_key_agreement(server, dst_sock, 
-                                      idata->send_key,
-                                      idata->hmac, packet);
-      silc_free(id);
-      return;
-    }
-  }
+  /* Relay the packet */
+  silc_server_relay_packet(server, dst_sock, idata->send_key,
+                          idata->hmac, packet, FALSE);
 }
index 1fbb0e59c92215f9f293740310c84677e010908c..4476c4dfb8b689bd6196ff801e4b2cd0b2699238 100644 (file)
@@ -1149,14 +1149,15 @@ void silc_server_send_notify_to_channel(SilcServer server,
   silc_buffer_free(packet);
 }
 
-/* Send notify message to all clients the client has joined. It is quaranteed
+/* Send notify message to all channels the client has joined. It is quaranteed
    that the message is sent only once to a client (ie. if a client is joined
    on two same channel it will receive only one notify message). Also, this
    sends only to local clients (locally connected if we are server, and to
-   local servers if we are router). */
+   local servers if we are router). If `sender' is provided the packet is
+   not sent to that client at all. */
 
 void silc_server_send_notify_on_channels(SilcServer server,
-                                        SilcSocketConnection sender,
+                                        SilcClientEntry sender,
                                         SilcClientEntry client,
                                         SilcNotifyType type,
                                         unsigned int argc, ...)
@@ -1204,6 +1205,9 @@ void silc_server_send_notify_on_channels(SilcServer server,
     while ((chl2 = silc_list_get(channel->user_list)) != SILC_LIST_END) {
       c = chl2->client;
       
+      if (sender && c == sender)
+       continue;
+
       /* Check if we have sent the packet to this client already */
       for (k = 0; k < sent_clients_count; k++)
        if (sent_clients[k] == c)
@@ -1226,9 +1230,6 @@ void silc_server_send_notify_on_channels(SilcServer server,
        sock = (SilcSocketConnection)c->router->connection;
        idata = (SilcIDListData)c->router;
        
-       if (sender && sock == sender)
-         continue;
-
        packetdata.dst_id = silc_id_id2str(c->router->id, SILC_ID_SERVER);
        packetdata.dst_id_len = SILC_ID_SERVER_LEN;
        packetdata.dst_id_type = SILC_ID_SERVER;
@@ -1264,9 +1265,6 @@ void silc_server_send_notify_on_channels(SilcServer server,
        sock = (SilcSocketConnection)c->connection;
        idata = (SilcIDListData)c;
        
-       if (sender && sock == sender)
-         continue;
-
        packetdata.dst_id = silc_id_id2str(c->id, SILC_ID_CLIENT);
        packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
        packetdata.dst_id_type = SILC_ID_CLIENT;
@@ -1426,38 +1424,19 @@ void silc_server_send_heartbeat(SilcServer server,
                          NULL, 0, FALSE);
 }
 
-/* Routine used to send (relay, route) key agreement packets to some 
-   destination. */
+/* Generic function to relay packet we've received. This is used to relay
+   packets to a client but generally can be used to other purposes as well. */
 
-void silc_server_send_key_agreement(SilcServer server,
-                                   SilcSocketConnection dst_sock,
-                                   SilcCipher cipher,
-                                   SilcHmac hmac,
-                                   SilcPacketContext *packet)
+void silc_server_relay_packet(SilcServer server,
+                             SilcSocketConnection dst_sock,
+                             SilcCipher cipher,
+                             SilcHmac hmac,
+                             SilcPacketContext *packet,
+                             int force_send)
 {
   silc_buffer_push(packet->buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len 
                   + packet->dst_id_len + packet->padlen);
-  silc_packet_send_prepare(dst_sock, 0, 0, packet->buffer->len);
-  silc_buffer_put(dst_sock->outbuf, packet->buffer->data, packet->buffer->len);
-  
-  /* Re-encrypt packet */
-  silc_packet_encrypt(cipher, hmac, dst_sock->outbuf, packet->buffer->len);
-  
-  /* Send the packet */
-  silc_server_packet_send_real(server, dst_sock, FALSE);
-}
-
-/* Routine used to send (relay, route) private message key packets to some 
-   destination. */
 
-void silc_server_send_private_message_key(SilcServer server,
-                                         SilcSocketConnection dst_sock,
-                                         SilcCipher cipher,
-                                         SilcHmac hmac,
-                                         SilcPacketContext *packet)
-{
-  silc_buffer_push(packet->buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len 
-                  + packet->dst_id_len + packet->padlen);
   silc_packet_send_prepare(dst_sock, 0, 0, packet->buffer->len);
   silc_buffer_put(dst_sock->outbuf, packet->buffer->data, packet->buffer->len);
   
@@ -1465,27 +1444,8 @@ void silc_server_send_private_message_key(SilcServer server,
   silc_packet_encrypt(cipher, hmac, dst_sock->outbuf, packet->buffer->len);
   
   /* Send the packet */
-  silc_server_packet_send_real(server, dst_sock, FALSE);
-}
+  silc_server_packet_send_real(server, dst_sock, force_send);
 
-/* Routine used to relay notify packets to a client. The notify packets
-   may be destined directly to a client and this routine is used to do
-   that. */
-
-void silc_server_packet_relay_notify(SilcServer server,
-                                    SilcSocketConnection dst_sock,
-                                    SilcCipher cipher,
-                                    SilcHmac hmac,
-                                    SilcPacketContext *packet)
-{
-  silc_buffer_push(packet->buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len 
+  silc_buffer_pull(packet->buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len 
                   + packet->dst_id_len + packet->padlen);
-  silc_packet_send_prepare(dst_sock, 0, 0, packet->buffer->len);
-  silc_buffer_put(dst_sock->outbuf, packet->buffer->data, packet->buffer->len);
-  
-  /* Re-encrypt packet */
-  silc_packet_encrypt(cipher, hmac, dst_sock->outbuf, packet->buffer->len);
-  
-  /* Send the packet */
-  silc_server_packet_send_real(server, dst_sock, FALSE);
 }
index 08bb1e62f6281fd8cf7775c91af32fa71840cfa1..49520c84dbf8bb32b5e83aad06e0d3fbf2324c43 100644 (file)
@@ -182,7 +182,7 @@ void silc_server_send_notify_to_channel(SilcServer server,
                                        SilcNotifyType type,
                                        unsigned int argc, ...);
 void silc_server_send_notify_on_channels(SilcServer server,
-                                        SilcSocketConnection sender,
+                                        SilcClientEntry sender,
                                         SilcClientEntry client,
                                         SilcNotifyType type,
                                         unsigned int argc, ...);
@@ -207,20 +207,11 @@ void silc_server_send_command(SilcServer server,
                              unsigned int argc, ...);
 void silc_server_send_heartbeat(SilcServer server,
                                SilcSocketConnection sock);
-void silc_server_send_key_agreement(SilcServer server,
-                                   SilcSocketConnection dst_sock,
-                                   SilcCipher cipher,
-                                   SilcHmac hmac,
-                                   SilcPacketContext *packet);
-void silc_server_send_private_message_key(SilcServer server,
-                                         SilcSocketConnection dst_sock,
-                                         SilcCipher cipher,
-                                         SilcHmac hmac,
-                                         SilcPacketContext *packet);
-void silc_server_packet_relay_notify(SilcServer server,
-                                    SilcSocketConnection dst_sock,
-                                    SilcCipher cipher,
-                                    SilcHmac hmac,
-                                    SilcPacketContext *packet);
+void silc_server_relay_packet(SilcServer server,
+                             SilcSocketConnection dst_sock,
+                             SilcCipher cipher,
+                             SilcHmac hmac,
+                             SilcPacketContext *packet,
+                             int force_send);
 
 #endif
index 1487ee0f376bfd3194ffdea6351bbe4fc31044fb..34f7326fb878175055654fc62f1dbbd84b807d86 100644 (file)
@@ -1293,7 +1293,7 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
     server->stat.packets_sent++;
 
     if (sock->outbuf->data - sock->outbuf->head)
-      silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
+     silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
 
     ret = silc_server_packet_send_real(server, sock, TRUE);
 
@@ -1973,19 +1973,41 @@ SILC_TASK_CALLBACK(silc_server_free_client_data_timeout)
 
 void silc_server_free_client_data(SilcServer server, 
                                  SilcSocketConnection sock,
-                                 SilcClientEntry client, char *signoff)
+                                 SilcClientEntry client, 
+                                 int notify,
+                                 char *signoff)
 {
   FreeClientInternal i = silc_calloc(1, sizeof(*i));
 
+  /* If there is pending outgoing data for the client then purge it
+     to the network before removing the client entry. */
+  if (SILC_IS_OUTBUF_PENDING(sock) && (SILC_IS_DISCONNECTED(sock) == FALSE)) {
+    server->stat.packets_sent++;
+
+    if (sock->outbuf->data - sock->outbuf->head)
+     silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
+
+    silc_server_packet_send_real(server, sock, TRUE);
+
+    SILC_SET_CONNECTION_FOR_INPUT(sock->sock);
+    SILC_UNSET_OUTBUF_PENDING(sock);
+    silc_buffer_clear(sock->outbuf);
+  }
+
   /* Send SIGNOFF notify to routers. */
-  if (!server->standalone && server->router)
+  if (notify && !server->standalone && server->router)
     silc_server_send_notify_signoff(server, server->router->connection,
                                    server->server_type == SILC_SERVER ?
                                    FALSE : TRUE, client->id, 
                                    SILC_ID_CLIENT_LEN, signoff);
 
   /* Remove client from all channels */
-  silc_server_remove_from_channels(server, sock, client, TRUE, signoff, TRUE);
+  if (notify)
+    silc_server_remove_from_channels(server, NULL, client, 
+                                    TRUE, signoff, TRUE);
+  else
+    silc_server_remove_from_channels(server, NULL, client, 
+                                    FALSE, NULL, FALSE);
 
   /* We will not delete the client entry right away. We will take it
      into history (for WHOWAS command) for 5 minutes */
@@ -2017,7 +2039,7 @@ void silc_server_free_sock_user_data(SilcServer server,
   case SILC_SOCKET_TYPE_CLIENT:
     {
       SilcClientEntry user_data = (SilcClientEntry)sock->user_data;
-      silc_server_free_client_data(server, sock, user_data, NULL);
+      silc_server_free_client_data(server, sock, user_data, TRUE, NULL);
       break;
     }
   case SILC_SOCKET_TYPE_SERVER:
@@ -3079,3 +3101,76 @@ void silc_server_save_users_on_channel(SilcServer server,
     }
   }
 }
+
+/* Lookups route to the client indicated by `id' client ID. The connection
+   object and internal data object is returned. Returns NULL if route
+   could not be found to the client. */
+
+SilcSocketConnection silc_server_get_client_route(SilcServer server,
+                                                 unsigned char *id_data,
+                                                 unsigned int id_len,
+                                                 SilcIDListData *idata)
+{
+  SilcClientID *id;
+  SilcClientEntry client;
+
+  SILC_LOG_DEBUG(("Start"));
+
+  /* Decode destination Client ID */
+  id = silc_id_str2id(id_data, id_len, SILC_ID_CLIENT);
+  if (!id) {
+    SILC_LOG_ERROR(("Could not decode destination Client ID, dropped"));
+    return NULL;
+  }
+
+  /* If the destination belongs to our server we don't have to route
+     the packet anywhere but to send it to the local destination. */
+  client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
+  if (client) {
+    silc_free(id);
+
+    if (client && client->data.registered == FALSE)
+      return NULL;
+
+    /* If we are router and the client has router then the client is in
+       our cell but not directly connected to us. */
+    if (server->server_type == SILC_ROUTER && client->router) {
+      /* We are of course in this case the client's router thus the real
+        "router" of the client is the server who owns the client. Thus
+        we will send the packet to that server. */
+      *idata = (SilcIDListData)client->router;
+      return client->router->connection;
+    }
+
+    /* Seems that client really is directly connected to us */
+    *idata = (SilcIDListData)client;
+    return client->connection;
+  }
+
+  /* Destination belongs to someone not in this server. If we are normal
+     server our action is to send the packet to our router. */
+  if (server->server_type == SILC_SERVER && !server->standalone) {
+    silc_free(id);
+    *idata = (SilcIDListData)server->router;
+    return server->router->connection;
+  }
+
+  /* We are router and we will perform route lookup for the destination 
+     and send the packet to fastest route. */
+  if (server->server_type == SILC_ROUTER && !server->standalone) {
+    /* Check first that the ID is valid */
+    client = silc_idlist_find_client_by_id(server->global_list, id, NULL);
+    if (client) {
+      SilcSocketConnection dst_sock;
+
+      dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT);
+
+      silc_free(id);
+      *idata = (SilcIDListData)dst_sock->user_data;
+      return dst_sock;
+    }
+  }
+
+  silc_free(id);
+  return NULL;
+}
index e25f6f11f8fdb3b67f757cca5c2d4ce76c4912e7..28a87518aeb05d7c2f1777dfb925c7338e32f306 100644 (file)
@@ -96,7 +96,9 @@ void silc_server_close_connection(SilcServer server,
                                  SilcSocketConnection sock);
 void silc_server_free_client_data(SilcServer server, 
                                  SilcSocketConnection sock,
-                                 SilcClientEntry client, char *signoff);
+                                 SilcClientEntry client, 
+                                 int notify,
+                                 char *signoff);
 void silc_server_free_sock_user_data(SilcServer server, 
                                     SilcSocketConnection sock);
 int silc_server_channel_has_global(SilcChannelEntry channel);
@@ -155,5 +157,9 @@ void silc_server_save_users_on_channel(SilcServer server,
                                       SilcBuffer user_list,
                                       SilcBuffer mode_list,
                                       unsigned int user_count);
+SilcSocketConnection silc_server_get_client_route(SilcServer server,
+                                                 unsigned char *id_data,
+                                                 unsigned int id_len,
+                                                 SilcIDListData *idata);
 
 #endif
index 964d073e4a37c87fa01b27b7e531f9cc7088b41e..e584862bc54b776543fdc5caa78fdd7c1dd172dc 100644 (file)
@@ -1,23 +1,17 @@
 [Cipher]
-aes-256-cbc:../lib/silcsim/modules/aes.sim.so:32:16
-aes-192-cbc:../lib/silcsim/modules/aes.sim.so:24:16
-aes-128-cbc:../lib/silcsim/modules/aes.sim.so:16:16
-twofish-256-cbc:../lib/silcsim/modules/twofish.sim.so:32:16
-twofish-192-cbc:../lib/silcsim/modules/twofish.sim.so:24:16
-twofish-128-cbc:../lib/silcsim/modules/twofish.sim.so:16:16
-mars-256-cbc:../lib/silcsim/modules/mars.sim.so:32:16
-mars-192-cbc:../lib/silcsim/modules/mars.sim.so:24:16
-mars-128-cbc:../lib/silcsim/modules/mars.sim.so:16:16
+rc6:../lib/silcsim/modules/rc6.sim.so:16:16
+twofish:../lib/silcsim/modules/twofish.sim.so:16:16
+mars:../lib/silcsim/modules/mars.sim.so:16:16
 none:../lib/silcsim/modules/none.sim.so:0:0
 
-[Hash]
+[Hash] 
 md5::64:16
 sha1::64:20
 
 [hmac]
 hmac-sha1-96:sha1:12
 hmac-md5-96:md5:12
-hmac-sha1:sha1:20   
+hmac-sha1:sha1:20
 hmac-md5:md5:16
 
 #[PKCS]
@@ -31,10 +25,10 @@ nobody:nobody
 Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi
 
 [ServerInfo]
-lassi.kuo.fi.ssh.com:212.146.42.253:Kuopio, Finland:1334
+lassi.kuo.fi.ssh.com:10.2.1.7:Kuopio, Finland:1334
 
 [ListenPort]
-212.146.42.253:212.146.42.253:1334
+10.2.1.7:10.2.1.7:1334
 
 [Logging]
 infologfile:silcd2.log:10000
@@ -53,12 +47,13 @@ errorlogfile:silcd2.log:10000
 :::1336:1
 
 [AdminConnection]
+*:silc:silc:passwd:testi
 
 [ServerConnection]
-212.146.42.253:passwd:priikone:1336:1:1
+10.2.1.7:passwd:priikone:1333:1:1
 
 [RouterConnection]
-212.146.42.253:passwd:priikone:1335:1:1:0
+10.2.1.7:passwd:priikone:1334:1:1:0
 
 [DenyConnection]
 [RedirectClient]
index e398d96c25e8fcc1bc807354e1ea69a7a0f5619f..d1668cae208d21dd6b99a92940ff4de875faf9ba 100644 (file)
@@ -410,6 +410,7 @@ void silc_client_notify_by_server(SilcClient client,
       silc_cipher_free(client_entry->send_key);
     if (client_entry->receive_key)
       silc_cipher_free(client_entry->receive_key);
+    silc_free(client_entry);
     break;
 
   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
@@ -597,8 +598,7 @@ void silc_client_notify_by_server(SilcClient client,
       goto out;
 
     /* Find Client entry */
-    client_entry = 
-      silc_client_get_client_by_id(client, conn, client_id);
+    client_entry = silc_client_get_client_by_id(client, conn, client_id);
     if (!client_entry)
       goto out;
 
@@ -634,6 +634,51 @@ void silc_client_notify_by_server(SilcClient client,
       silc_free(channel);
     }
     break;
+
+  case SILC_NOTIFY_TYPE_KILLED:
+    /*
+     * A client (maybe me) was killed from the network.
+     */
+
+    /* Get Client ID */
+    tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+    if (!tmp)
+      goto out;
+
+    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    if (!client_id)
+      goto out;
+
+    /* Find Client entry */
+    client_entry = silc_client_get_client_by_id(client, conn, client_id);
+    if (!client_entry)
+      goto out;
+
+    /* 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. */
+    client->ops->notify(client, conn, type, client_entry, tmp);
+
+    if (client_entry != conn->local_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);
+    }
+
+    break;
     
   default:
     break;
index 4b3214b4d8f3c56e65467fcfef1b6ccd2326ded3..f6dca33316e8e9cba3d61259cebb3fbef7e2a8f9 100644 (file)
@@ -54,7 +54,7 @@ SilcClientCommand silc_command_list[] =
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER, 3),
   SILC_CLIENT_CMD(shutdown, SHUTDOWN, "SHUTDOWN",
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER, 1),
-  SILC_CLIENT_CMD(silcoper, SILCOPER, "SILOPER",
+  SILC_CLIENT_CMD(silcoper, SILCOPER, "SILCOPER",
                  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),
@@ -334,7 +334,7 @@ SILC_CLIENT_CMD_FUNC(identify)
   buffer = silc_command_payload_encode(SILC_COMMAND_IDENTIFY,
                                       cmd->argc - 1, ++cmd->argv,
                                       ++cmd->argv_lens, ++cmd->argv_types,
-                                      0);
+                                      ++conn->cmd_ident);
   silc_client_packet_send(cmd->client, cmd->conn->sock,
                          SILC_PACKET_COMMAND, NULL, 0, NULL, NULL,
                          buffer->data, buffer->len, TRUE);
@@ -528,7 +528,7 @@ SILC_CLIENT_CMD_FUNC(invite)
 
     /* Client entry not found, it was requested thus mark this to be
        pending command. */
-    silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 0,
+    silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, conn->cmd_ident,
                                silc_client_command_destructor,
                                silc_client_command_invite, 
                                silc_client_command_dup(cmd));
@@ -564,6 +564,10 @@ SILC_CLIENT_CMD_FUNC(invite)
   COMMAND;
 
  out:
+  if (nickname)
+    silc_free(nickname);
+  if (server)
+    silc_free(server);
   silc_client_command_free(cmd);
 }
 
@@ -625,8 +629,96 @@ SILC_CLIENT_CMD_FUNC(quit)
   silc_client_command_free(cmd);
 }
 
+/* Command KILL. Router operator can use this command to remove an client
+   fromthe SILC Network. */
+
 SILC_CLIENT_CMD_FUNC(kill)
 {
+  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+  SilcClientConnection conn = cmd->conn;
+  SilcBuffer buffer, idp;
+  SilcClientEntry target;
+  unsigned int num = 0;
+  char *nickname = NULL, *server = 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: /KILL <nickname> [<comment>]");
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  /* Parse the typed nickname. */
+  if (!silc_parse_nickname(cmd->argv[1], &nickname, &server, &num)) {
+    cmd->client->ops->say(cmd->client, conn, "Bad nickname");
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  /* Get the target client */
+  target = silc_idlist_get_client(cmd->client, conn, nickname, 
+                                 server, num, TRUE);
+  if (!target) {
+    silc_free(nickname);
+    if (server)
+      silc_free(server);
+
+    /* Client entry not found, it was requested thus mark this to be
+       pending command. */
+    silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 
+                               conn->cmd_ident,  
+                               silc_client_command_destructor,
+                               silc_client_command_kill, 
+                               silc_client_command_dup(cmd));
+    cmd->pending = 1;
+    return;
+  }
+
+  /* Send the KILL command to the server */
+  idp = silc_id_payload_encode(target->id, SILC_ID_CLIENT);
+  if (cmd->argc == 2)
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_KILL, 0, 1, 
+                                           1, idp->data, idp->len);
+  else
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_KILL, 0, 2, 
+                                           1, idp->data, idp->len,
+                                           2, cmd->argv[2], 
+                                           strlen(cmd->argv[2]));
+  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(idp);
+
+  /* Notify application */
+  COMMAND;
+
+  /* Remove the client entry to be killed */
+  silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
+                        target->id);
+  if (target->nickname)
+    silc_free(target->nickname);
+  if (target->server)
+    silc_free(target->server);
+  if (target->id)
+    silc_free(target->id);
+  if (target->send_key)
+    silc_cipher_free(target->send_key);
+  if (target->receive_key)
+    silc_cipher_free(target->receive_key);
+  silc_free(target);
+
+ out:
+  if (nickname)
+    silc_free(nickname);
+  if (server)
+    silc_free(server);
+  silc_client_command_free(cmd);
 }
 
 /* Command INFO. Request information about specific server. If specific
@@ -1091,7 +1183,8 @@ SILC_CLIENT_CMD_FUNC(cumode)
   if (!client_entry) {
     /* Client entry not found, it was requested thus mark this to be
        pending command. */
-    silc_client_command_pending(conn, SILC_COMMAND_CUMODE, 0,  
+    silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 
+                               conn->cmd_ident,  
                                silc_client_command_destructor,
                                silc_client_command_cumode, 
                                silc_client_command_dup(cmd));
@@ -1165,6 +1258,10 @@ SILC_CLIENT_CMD_FUNC(cumode)
   COMMAND;
 
  out:
+  if (nickname)
+    silc_free(nickname);
+  if (server)
+    silc_free(server);
   silc_client_command_free(cmd);
 }
 
@@ -1190,7 +1287,7 @@ SILC_CLIENT_CMD_FUNC(kick)
 
   if (cmd->argc < 3) {
     cmd->client->ops->say(cmd->client, conn, 
-                         "Usage: /KICK <channel> <client> [<comment>]");
+                         "Usage: /KICK <channel> <nickname> [<comment>]");
     COMMAND_ERROR;
     goto out;
   }
@@ -1261,6 +1358,10 @@ SILC_CLIENT_CMD_FUNC(kick)
   COMMAND;
 
  out:
+  if (nickname)
+    silc_free(nickname);
+  if (server)
+    silc_free(server);
   silc_client_command_free(cmd);
 }
 
@@ -1642,7 +1743,8 @@ SILC_CLIENT_CMD_FUNC(users)
   if (!cmd->pending) {
     /* Send USERS command to the server */
     idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL);
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1, 
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 
+                                           ++conn->cmd_ident, 1, 
                                            1, idp->data, idp->len);
     silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, 
                            NULL, 0, NULL, NULL, buffer->data, 
@@ -1653,7 +1755,7 @@ SILC_CLIENT_CMD_FUNC(users)
     /* Register pending callback which will recall this command callback with
        same context and reprocesses the command. When reprocessing we actually
        display the information on the screen. */
-    silc_client_command_pending(conn, SILC_COMMAND_USERS, 0
+    silc_client_command_pending(conn, SILC_COMMAND_USERS, conn->cmd_ident
                                silc_client_command_destructor,
                                silc_client_command_users, 
                                silc_client_command_dup(cmd));
index a9833571d2974604810ae453fe85a647cbc69e52..a2e3e1c42b187ced3c93ebcd4b310ba49792421e 100644 (file)
@@ -673,9 +673,34 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite)
   SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INVITE);
   silc_client_command_reply_free(cmd);
 }
+
+/* Received reply to the KILL command. */
  
 SILC_CLIENT_CMD_REPLY_FUNC(kill)
 {
+  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_CLOSE);
+
+ out:
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_CLOSE);
+  silc_client_command_reply_free(cmd);
 }
 
 /* Received reply to INFO command. We receive the server ID and some
index 8a7967eb52f1c874c3542aa9dddc4182ca1119da..b54f12180424f1aaa342a3f08b762077392c76d3 100644 (file)
@@ -144,7 +144,7 @@ struct SilcSocketConnectionHB {
 /* Generic manipulation of flags */
 #define SF_SET(x, f) (x)->flags |= (1L << (f))
 #define SF_UNSET(x, f) (x)->flags &= ~(1L << (f))
-#define SF_IS(x, f) (x)->flags & (1L << (f))
+#define SF_IS(x, f) ((x)->flags & (1L << (f)))
 
 /* Setting/Unsetting flags */
 #define SILC_SET_OUTBUF_PENDING(x) SF_SET((x), SILC_SF_OUTBUF_PENDING)