updates.
authorPekka Riikonen <priikone@silcnet.org>
Sun, 18 Mar 2001 21:38:10 +0000 (21:38 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 18 Mar 2001 21:38:10 +0000 (21:38 +0000)
14 files changed:
CHANGES
README
TODO
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
doc/draft-riikonen-silc-pp-01.nroff
doc/draft-riikonen-silc-spec-01.nroff
lib/silccore/silcnotify.h
lib/silccore/silcpacket.h

diff --git a/CHANGES b/CHANGES
index 84f84aba29408d6bc7faf3adecaef675397f7592..65971497fc78f89e1d1ce37dbeb0f4110dceac32 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,42 @@
+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
+         an client is killed from the SILC Network.  Updated the protocol
+         specs accordingly.
+
+         Added new function silc_server_send_notify_killed to the
+         silcd/packet_send.[ch].
+
+       * Added function silc_server_packet_relay_notify to relay notify
+         packets that are destined directly to a client.  In this case
+         the server does not process the notify packets but merely relays
+         it to the client.  Affected file silcd/packet_send.[ch].
+
+         Added also silc_server_packet_process_relay_notify to check
+         whereto relay the notify.  Affected file is 
+         silcd/packet_receive.[ch].
+
+       * Implemented KILL command to the server.
+
+       * Updated TODO.
+
+       * Added the backup schema desgined last fall to the protocol
+         specs for everyone to see.  The specification is in the
+         *-spec-xx.txt draft and the packet type definitions for the
+         backup routers is in *-pp-xx.txt draft.  Thusly, added also
+         new packet type SILC_PACKET_CELL_ROUTERS.
+
+       * A big security problem in the implementation discovered.  The
+         signoff of an client did not cause new channel key generation
+         which it of course should've done.  The channel keys must be
+         always re-generated when client leaves (or signoffs) the channel.
+         The silc_server_remove_from_channels funtion now handles
+         the channel key re-generation.
+
+       * Added `sender' argument to the silc_server_send_notify_on_channels
+         to not to send the client provided as argument.  Affected file
+         silcd/packet_send.[ch].
+
 Fri Mar 16 15:52:49 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Implemented OPER and SILCOPER commands into the server and
diff --git a/README b/README
index 191ebd1e37e8daedb37867b2701f0512f28f5e0c..559ae953419e3fda2ad3dbafb76d9ba95072bfac 100644 (file)
--- a/README
+++ b/README
@@ -178,6 +178,11 @@ Following commands has been, at least partly, implemented:
 
                Obtains router operator privileges.
 
+       /KILL   <nickname> [<comment>]
+
+               Router operator can use this command to remove an client
+               from the SILC Network temporarily.
+
        /CONNECT <server> [<port>]
 
                Connects to server the remote <server>.  You must be
diff --git a/TODO b/TODO
index e524e5bb38c25789828f877c34d3219e2aa41c7c..133d751a31ad2ddf48231c0a3a196bf1968d0afe 100644 (file)
--- a/TODO
+++ b/TODO
@@ -100,15 +100,22 @@ TODO In SILC Client Library
 TODO In SILC Server
 ===================
 
- 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 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.
+   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
+   directly by the packet type.
 
  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
index ef844c0a082ae25b8ec3a419f7577e0079f73cb3..4133e7ce0517a4e380f9353dc1d2bf2e7e970532 100644 (file)
@@ -59,7 +59,7 @@ SilcServerCommand silc_command_list[] =
   SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
   SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
   SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
-  SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
+  SILC_SERVER_CMD(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, 
@@ -1686,7 +1686,7 @@ SILC_SERVER_CMD_FUNC(nick)
   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
   /* Send NICK_CHANGE notify to the client's channels */
-  silc_server_send_notify_on_channels(server, client, 
+  silc_server_send_notify_on_channels(server, NULL, client, 
                                      SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
                                      oidp->data, oidp->len, 
                                      nidp->data, nidp->len);
@@ -2010,8 +2010,102 @@ SILC_SERVER_CMD_FUNC(quit)
   silc_server_command_free(cmd);
 }
 
+/* Server side of command KILL. This command is used by router operator
+   to remove an client from the SILC Network temporarily. */
+
 SILC_SERVER_CMD_FUNC(kill)
 {
+  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  SilcServer server = cmd->server;
+  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcClientEntry remote_client;
+  SilcClientID *client_id;
+  unsigned char *tmp, *comment;
+  unsigned int tmp_len;
+  SilcBuffer idp;
+
+  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)
+    goto out;
+
+  /* Check whether client has the permissions. */
+  if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+                                         SILC_STATUS_ERR_NO_ROUTER_PRIV);
+    goto out;
+  }
+
+  /* Get the client ID */
+  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+  if (!tmp) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+    goto out;
+  }
+  client_id = silc_id_payload_parse_id(tmp, tmp_len);
+  if (!client_id) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+                                         SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
+    goto out;
+  }
+
+  /* Get the client entry */
+  remote_client = silc_idlist_find_client_by_id(server->local_list, 
+                                               client_id, NULL);
+  if (!remote_client) {
+    remote_client = silc_idlist_find_client_by_id(server->global_list, 
+                                                 client_id, NULL);
+    if (!remote_client) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
+      goto out;
+    }
+  }
+
+  /* Get comment */
+  comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+
+  /* Send reply to the sender */
+  silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
+                                       SILC_STATUS_OK);
+
+  /* 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, 
+                                     remote_client, SILC_NOTIFY_TYPE_KILLED,
+                                     comment ? 2 : 1,
+                                     idp->data, idp->len,
+                                     comment, comment ? strlen(comment) : 0);
+  silc_buffer_free(idp);
+
+  /* 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 the client directly */
+  silc_server_send_notify_killed(server, remote_client->connection ? 
+                                remote_client->connection : 
+                                remote_client->router->connection, FALSE,
+                                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);
+
+ out:
+  silc_server_command_free(cmd);
 }
 
 /* Server side of command INFO. This sends information about us to 
index 55ed8819d9508b6487dc988198f3d7abb6e111f3..83e19b8ef7ef4d8949adcc009ca129b43ea7ce65 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. */
 
@@ -52,6 +145,13 @@ 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);
+    return;
+  }
+
   /* If we are router and this packet is not already broadcast packet
      we will broadcast it. The sending socket really cannot be router or
      the router is buggy. If this packet is coming from router then it must
@@ -250,7 +350,7 @@ void silc_server_notify(SilcServer server,
       tmp = NULL;
 
     /* Remove the client from all channels */
-    silc_server_remove_from_channels(server, NULL, client, tmp);
+    silc_server_remove_from_channels(server, NULL, client, TRUE, tmp, TRUE);
 
     /* Remove the client entry */
     if (!silc_idlist_del_client(server->global_list, client))
@@ -346,7 +446,7 @@ void silc_server_notify(SilcServer server,
 
        /* Send the NICK_CHANGE notify type to local clients on the channels
           this client is joined to. */
-       silc_server_send_notify_on_channels(server, client, 
+       silc_server_send_notify_on_channels(server, NULL, client, 
                                            SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
                                            id, tmp_len, 
                                            id2, tmp_len);
@@ -538,6 +638,15 @@ void silc_server_notify(SilcServer server,
 
     break;
 
+  case SILC_NOTIFY_TYPE_KILLED:
+    /* 
+     * Distribute the notify to local clients on channels
+     */
+    
+    SILC_LOG_DEBUG(("KILLED notify"));
+      
+    break;
+
     /* Ignore rest of the notify types for now */
   case SILC_NOTIFY_TYPE_NONE:
   case SILC_NOTIFY_TYPE_MOTD:
@@ -655,6 +764,7 @@ void silc_server_private_message(SilcServer server,
                                       idata->send_key,
                                       idata->hmac,
                                       packet);
+      silc_free(id);
       return;
     }
 
@@ -663,6 +773,7 @@ void silc_server_private_message(SilcServer server,
     silc_server_send_private_message(server, dst_sock, 
                                     idata->send_key,
                                     idata->hmac, packet);
+    silc_free(id);
     return;
   }
 
@@ -679,6 +790,7 @@ void silc_server_private_message(SilcServer server,
                                       idata->send_key,
                                       idata->hmac, packet);
     }
+    silc_free(id);
     return;
   }
 
@@ -697,6 +809,7 @@ void silc_server_private_message(SilcServer server,
        silc_server_send_private_message(server, dst_sock, 
                                         idata->send_key,
                                         idata->hmac, packet);
+      silc_free(id);
       return;
     }
   }
@@ -752,6 +865,7 @@ void silc_server_private_message_key(SilcServer server,
                                           idata->send_key,
                                           idata->hmac,
                                           packet);
+      silc_free(id);
       return;
     }
 
@@ -760,6 +874,7 @@ void silc_server_private_message_key(SilcServer server,
     silc_server_send_private_message_key(server, dst_sock, 
                                         idata->send_key,
                                         idata->hmac, packet);
+    silc_free(id);
     return;
   }
 
@@ -776,6 +891,7 @@ void silc_server_private_message_key(SilcServer server,
                                           idata->send_key,
                                           idata->hmac, packet);
     }
+    silc_free(id);
     return;
   }
 
@@ -794,6 +910,7 @@ void silc_server_private_message_key(SilcServer server,
        silc_server_send_private_message_key(server, dst_sock, 
                                             idata->send_key,
                                             idata->hmac, packet);
+      silc_free(id);
       return;
     }
   }
@@ -1677,10 +1794,10 @@ void silc_server_key_agreement(SilcServer server,
   }
 
   /* If the destination belongs to our server we don't have to route
-     the message anywhere but to send it to the local destination. */
+     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 message to the destination */
+    /* 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
@@ -1695,6 +1812,7 @@ void silc_server_key_agreement(SilcServer server,
                                     idata->send_key,
                                     idata->hmac,
                                     packet);
+      silc_free(id);
       return;
     }
 
@@ -1703,6 +1821,7 @@ void silc_server_key_agreement(SilcServer server,
     silc_server_send_key_agreement(server, dst_sock, 
                                   idata->send_key,
                                   idata->hmac, packet);
+    silc_free(id);
     return;
   }
 
@@ -1719,6 +1838,7 @@ void silc_server_key_agreement(SilcServer server,
                                     idata->send_key,
                                     idata->hmac, packet);
     }
+    silc_free(id);
     return;
   }
 
@@ -1737,6 +1857,7 @@ void silc_server_key_agreement(SilcServer server,
        silc_server_send_key_agreement(server, dst_sock, 
                                       idata->send_key,
                                       idata->hmac, packet);
+      silc_free(id);
       return;
     }
   }
index 69bd04cd7bafad2e0470750f58f43b2be9f845d7..1fbb0e59c92215f9f293740310c84677e010908c 100644 (file)
@@ -1080,6 +1080,27 @@ void silc_server_send_notify_kicked(SilcServer server,
   silc_buffer_free(idp);
 }
 
+/* Send KILLED notify type. This tells that the `client_id' client was
+   killed from the network.  The `comment' may indicate the reason
+   for the killing. */
+
+void silc_server_send_notify_killed(SilcServer server,
+                                   SilcSocketConnection sock,
+                                   int broadcast,
+                                   SilcClientID *client_id,
+                                   unsigned int client_id_len,
+                                   char *comment)
+{
+  SilcBuffer idp;
+
+  idp = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
+  silc_server_send_notify_dest(server, sock, broadcast, (void *)client_id,
+                              SILC_ID_CLIENT, SILC_NOTIFY_TYPE_KILLED,
+                              comment ? 2 : 1, idp->data, idp->len,
+                              comment, comment ? strlen(comment) : 0);
+  silc_buffer_free(idp);
+}
+
 /* Sends notify message destined to specific entity. */
 
 void silc_server_send_notify_dest(SilcServer server,
@@ -1135,6 +1156,7 @@ void silc_server_send_notify_to_channel(SilcServer server,
    local servers if we are router). */
 
 void silc_server_send_notify_on_channels(SilcServer server,
+                                        SilcSocketConnection sender,
                                         SilcClientEntry client,
                                         SilcNotifyType type,
                                         unsigned int argc, ...)
@@ -1204,6 +1226,9 @@ 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;
@@ -1239,6 +1264,9 @@ 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;
@@ -1439,3 +1467,25 @@ void silc_server_send_private_message_key(SilcServer server,
   /* Send the packet */
   silc_server_packet_send_real(server, dst_sock, FALSE);
 }
+
+/* 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 
+                  + 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 b402c6aad3472077cc315ca9a024a8f7de8c6ec6..08bb1e62f6281fd8cf7775c91af32fa71840cfa1 100644 (file)
@@ -162,6 +162,12 @@ void silc_server_send_notify_kicked(SilcServer server,
                                    SilcClientID *client_id,
                                    unsigned int client_id_len,
                                    char *comment);
+void silc_server_send_notify_killed(SilcServer server,
+                                   SilcSocketConnection sock,
+                                   int broadcast,
+                                   SilcClientID *client_id,
+                                   unsigned int client_id_len,
+                                   char *comment);
 void silc_server_send_notify_dest(SilcServer server,
                                  SilcSocketConnection sock,
                                  int broadcast,
@@ -176,6 +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 client,
                                         SilcNotifyType type,
                                         unsigned int argc, ...);
@@ -210,5 +217,10 @@ void silc_server_send_private_message_key(SilcServer server,
                                          SilcCipher cipher,
                                          SilcHmac hmac,
                                          SilcPacketContext *packet);
+void silc_server_packet_relay_notify(SilcServer server,
+                                    SilcSocketConnection dst_sock,
+                                    SilcCipher cipher,
+                                    SilcHmac hmac,
+                                    SilcPacketContext *packet);
 
 #endif
index 47a62ddb9b579ddc8782e3cef4becfa0969dc11b..1487ee0f376bfd3194ffdea6351bbe4fc31044fb 100644 (file)
@@ -1977,7 +1977,7 @@ void silc_server_free_client_data(SilcServer server,
 {
   FreeClientInternal i = silc_calloc(1, sizeof(*i));
 
-  /* Send REMOVE_ID packet to routers. */
+  /* Send SIGNOFF notify to routers. */
   if (!server->standalone && server->router)
     silc_server_send_notify_signoff(server, server->router->connection,
                                    server->server_type == SILC_SERVER ?
@@ -1985,7 +1985,7 @@ void silc_server_free_client_data(SilcServer server,
                                    SILC_ID_CLIENT_LEN, signoff);
 
   /* Remove client from all channels */
-  silc_server_remove_from_channels(server, sock, client, signoff);
+  silc_server_remove_from_channels(server, sock, client, TRUE, signoff, TRUE);
 
   /* We will not delete the client entry right away. We will take it
      into history (for WHOWAS command) for 5 minutes */
@@ -2096,7 +2096,8 @@ int silc_server_remove_clients_by_server(SilcServer server,
        }
 
        /* Remove the client entry */
-       silc_server_remove_from_channels(server, NULL, client, NULL);
+       silc_server_remove_from_channels(server, NULL, client, TRUE, 
+                                        NULL, TRUE);
        silc_idlist_del_client(server->local_list, client);
 
        if (!silc_idcache_list_next(list, &id_cache))
@@ -2121,7 +2122,8 @@ int silc_server_remove_clients_by_server(SilcServer server,
        }
 
        /* Remove the client entry */
-       silc_server_remove_from_channels(server, NULL, client, NULL);
+       silc_server_remove_from_channels(server, NULL, client, TRUE,
+                                        NULL, TRUE);
        silc_idlist_del_client(server->global_list, client);
 
        if (!silc_idcache_list_next(list, &id_cache))
@@ -2173,7 +2175,9 @@ int silc_server_channel_has_local(SilcChannelEntry channel)
 void silc_server_remove_from_channels(SilcServer server, 
                                      SilcSocketConnection sock,
                                      SilcClientEntry client,
-                                     char *signoff_message)
+                                     int notify,
+                                     char *signoff_message,
+                                     int keygen)
 {
   SilcChannelEntry channel;
   SilcChannelClientEntry chl;
@@ -2220,7 +2224,7 @@ void silc_server_remove_from_channels(SilcServer server,
     if (server->server_type == SILC_SERVER &&
        !silc_server_channel_has_local(channel)) {
       /* Notify about leaving client if this channel has global users. */
-      if (channel->global_users)
+      if (notify && channel->global_users)
        silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
                                           SILC_NOTIFY_TYPE_SIGNOFF, 
                                           signoff_message ? 2 : 1,
@@ -2236,12 +2240,24 @@ void silc_server_remove_from_channels(SilcServer server,
 
     /* Send notify to channel about client leaving SILC and thus
        the entire channel. */
-    silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
-                                      SILC_NOTIFY_TYPE_SIGNOFF, 
-                                      signoff_message ? 2 : 1,
-                                      clidp->data, clidp->len,
-                                      signoff_message, signoff_message ?
-                                      strlen(signoff_message) : 0);
+    if (notify)
+      silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
+                                        SILC_NOTIFY_TYPE_SIGNOFF, 
+                                        signoff_message ? 2 : 1,
+                                        clidp->data, clidp->len,
+                                        signoff_message, signoff_message ?
+                                        strlen(signoff_message) : 0);
+
+    if (keygen) {
+      /* Re-generate channel key */
+      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. */
+      silc_server_send_channel_key(server, client->connection, channel, 
+                                  server->server_type == SILC_ROUTER ? 
+                                  FALSE : !server->standalone);
+    }
   }
 
   silc_buffer_free(clidp);
@@ -2502,6 +2518,8 @@ void silc_server_create_channel_key(SilcServer server,
   unsigned char channel_key[32], hash[32];
   unsigned int len;
 
+  SILC_LOG_DEBUG(("Generating channel key"));
+
   if (!channel->channel_key)
     if (!silc_cipher_alloc("aes-256-cbc", &channel->channel_key))
       return;
index 296c35cc4605029c1afea237fc57c45049d8fec6..e25f6f11f8fdb3b67f757cca5c2d4ce76c4912e7 100644 (file)
@@ -106,7 +106,9 @@ int silc_server_remove_clients_by_server(SilcServer server,
 void silc_server_remove_from_channels(SilcServer server, 
                                      SilcSocketConnection sock,
                                      SilcClientEntry client,
-                                     char *signoff_message);
+                                     int notify,
+                                     char *signoff_message,
+                                     int keygen);
 int silc_server_remove_from_one_channel(SilcServer server, 
                                        SilcSocketConnection sock,
                                        SilcChannelEntry channel,
index 214b7f723d1f827fd0c3cac7d4ec1f39954b1f51..964d073e4a37c87fa01b27b7e531f9cc7088b41e 100644 (file)
@@ -3,7 +3,7 @@ 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-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
@@ -17,7 +17,7 @@ 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 +31,10 @@ nobody:nobody
 Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi
 
 [ServerInfo]
-lassi.kuo.fi.ssh.com:10.2.1.7:Kuopio, Finland:1334
+lassi.kuo.fi.ssh.com:212.146.42.253:Kuopio, Finland:1334
 
 [ListenPort]
-10.2.1.7:10.2.1.7:1334
+212.146.42.253:212.146.42.253:1334
 
 [Logging]
 infologfile:silcd2.log:10000
@@ -55,10 +55,10 @@ errorlogfile:silcd2.log:10000
 [AdminConnection]
 
 [ServerConnection]
-10.2.1.7:passwd:priikone:1333:1:1
+212.146.42.253:passwd:priikone:1336:1:1
 
 [RouterConnection]
-10.2.1.7:passwd:priikone:1335:1:1:0
+212.146.42.253:passwd:priikone:1335:1:1:0
 
 [DenyConnection]
 [RedirectClient]
index 0b1dcf77f1add69d195fa9b41c3169a418cece22..2a1dd374e41beaf6e2563dd45158ff7d9d9c15ea 100644 (file)
@@ -726,7 +726,20 @@ List of SILC Packet types are defined as follows.
           Payload of the packet:  See section 2.3.20 Key Agreement Payload
 
 
-     26 - 199
+    26    SILC_PACKET_CELL_ROUTERS
+
+          This packet is used by primary router in the cell to notify its
+          primary router what other routers (backup routers) exist in the
+          cell.  In case of failure of the primary router in the cell the
+          first router in the list will act as primary router of the cell.
+          This packet may be sent at anytime after connection has been
+          registered to the primary router.  The client must not send this
+          packet.
+
+          Payload of the packet:  See section 2.3.21 Cell Routers Payload
+
+
+     27 - 199
 
          Currently undefined commands.
 
@@ -1214,6 +1227,24 @@ ID's sent in arguments are sent inside ID Payload.
       The kicker may have set the <comment> to indicate the reason for
       the kicking.
 
+
+13    SILC_NOTIFY_TYPE_KILLED
+
+      Sent when a client has been killed from the network.  This is sent 
+      also to the client who was killed from the network.  The client
+      who was killed from the network must be removed from the network.
+      This notify type is destined directly to the client who was killed
+      and to channel if the client is on any channel.  The router or
+      server receiving the packet distributes this type to the local
+      clients on the channel and broadcast it to the network.
+
+      Max Arguments:  2
+          Arguments:  (1) <Client ID>  (2) [<comment>]
+
+      The <Client ID> is the client who was killed from the network.
+      The killer may have set the <comment> to indicate the reason for
+      the killing.
+
 .in 3
 
 Notify types starting from 16384 are reserved for private notify
@@ -1786,8 +1817,8 @@ set the real nickname of the user which is then used to create new
 client ID.
 
 The payload may only be sent with SILC_PACKET_NEW_CLIENT packet.  It
-must not be sent in any other packet type.  The following diagram represents
-the New Client Payload.
+must not be sent in any other packet type.  The following diagram
+represents the New Client Payload.
 
 
 
@@ -1979,7 +2010,6 @@ represents the Key Agreement Payload.
 Figure 20:  Key Agreement Payload
 
 
-
 .in 6
 o Hostname Length (2 bytes) - Indicates the length of the Hostname
   field.
@@ -2005,6 +2035,65 @@ it is intended to be used as private message keys.  Any other use for
 the key material is undefined.
 
 
+.ti 0
+2.3.21 Cell Routers Payload
+
+Cell Routers payload is used by router to notify its primary router what
+other routers exist in the cell.  The other routers are considered to be
+backup routers and one of them will come active only in the case of
+failure of the primary router.  Normal server can send this packet if it
+is acting as backup router.  Client must not send this packet.  To send
+more than one backup router set the List flag and assemble the payloads
+as list.
+
+The payload may only be sent with SILC_PACKET_CELL_ROUTERS packet.  It
+must not be sent in any other packet type.  The Following diagram
+represents the Cell Routers Payload.
+
+         
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|        Hostname Length        |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                           Hostname                            ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                             Port                              |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|        Server ID Length       |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                           Server ID                           ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 21:  Cell Routers Payload
+
+
+.in 6
+o Hostname Length (2 bytes) - Indicates the length of the Hostname
+  field.
+
+o Hostname (variable length) - The hostname or IP address of
+  the backup router.
+
+o Port (4 bytes) - The port of the backup router it currently uses.
+  This is a 32 bit MSB first order value.
+
+o Server ID Length (2 bytes) - Indicates the length of the Server
+  ID field.
+
+o Server ID (variable length) - Consists of the Server ID of the
+  backup router.
+.in 3
+
+
 .ti 0
 2.4 SILC ID Types
 
index 79e6fafd5b52fac41ee289b143959b50d79dc5a4..ec7ba80c3850985242061157dac1f386875d3b5a 100644 (file)
@@ -79,6 +79,7 @@ Table of Contents
   2.3 Communication in the Network ..............................  6
   2.4 Channel Communication .....................................  7
   2.5 Router Connections ........................................  7
+  2.6 Backup Routers ............................................ XX
 3 SILC Specification ............................................  8
   3.1 Client ....................................................  8
       3.1.1 Client ID ...........................................  9
@@ -417,6 +418,76 @@ broadcast packets.  Usually all router wide information in the network is
 distributed by SILC broadcast packets.
 
 
+.ti 0
+2.6 Backup Routers
+
+Backup routers may exist in the cell in addition of the primary router.
+However, they must not be active routers and act as routers in the cell.
+Only one router may be acting as primary router in the cell.  In the case
+of failure of the primary router may one of the backup routers become
+active.  The purpose of backup routers are in case of failure of the
+primary router to maintain working connections inside the cell and outside
+the cell and to avoid netsplits.
+
+Backup routers are normal servers in the cell that are prepared to take
+over the tasks of primary router if needed.  They need to have at least
+one direct and active connection to the primary router of the cell.
+This communication channel is used to send the router information to
+the backup router.  Backup router must know everything that the primary
+router knows to be able to take over the tasks of the primary router.
+It is the primary router's responsibility to feed the data to the backup
+router.  If the backup router does not know all the data in the case of
+failure some connections may be lost.  The primary router of the cell
+must consider the backup router being normal router server and feed the
+data accordingly.
+
+In addition of having direct connection to the primary router of the
+cell the backup router must also have connection to the same router
+the primary router of the cell has connected.  However, it must not be
+active router connection meaning that the backup router must not use
+that channel as its primary route and it must not notify the router
+about having connected servers, channels and clients behind it.  It
+merely connects to the router.  This sort of connection is later
+referred as being passive connection.  Some keepalive actions may be
+needed by the router to keep the connection alive.
+
+The primary router notifies its primary router about having backup
+routers in the cell by sending SILC_PACKET_CELL_ROUTERS packet.  If
+and when the primary router of the cell becomes unresponsive, its
+primary router knows that there exists backup routers in the cell.  
+After that it will start using the first backup router sent in the
+packet as router of that cell.  In this case the backup router must
+notify its new primary router about the servers, channels and clients
+it has connected to it.  The primary router knows that this server
+has become a router of the cell because of failure of the primary
+router in the cell.  It must also cope with the fact that the servers,
+channels and clients that the new backup router announces are not
+really new, since they used to exist in the primary router of the
+cell.
+
+It is required that other normal servers has passive connections to
+the backup router(s) in the cell.  Some keepalive actions may be needed
+by the server to keep the connection alive.  After they notice the
+failure of the primary router they must start using the connection to
+the first backup router as their primary route.
+
+It is recommended that there would be at least one backup router in
+the cell.  It is not recommended to have all servers in the cell acting
+as backup routers as it requires establishing several connections to
+several servers in the cell.  Large cells can easily have several
+backup routers in the cell.  The order of the backup routers are decided
+at the primary router of the cell and servers and backup servers in the
+cell must be configured accordingly.  It is not required that the backup
+server is actually active server in the cell.  Backup router may be spare
+server in the cell that does not accept normal client connections at all.
+It maybe reserved purely for the backup purposes.  These, however, are
+cell management issues.
+
+If the first backup router is down as well and there is another backup
+router in the cell then it will start acting as the primary router as
+described above.
+
+
 .ti 0
 3. SILC Specification
 
index 8aa9d5800837eac6c1db50e92065b638a3c18ba5..9f25ededf3cec7f2f64bc4f37dfe30f72a95c72a 100644 (file)
@@ -43,6 +43,7 @@ typedef unsigned short SilcNotifyType;
 #define SILC_NOTIFY_TYPE_CHANNEL_CHANGE  10 /* Channel's ID has changed */
 #define SILC_NOTIFY_TYPE_SERVER_SIGNOFF  11 /* Server quitting SILC */
 #define SILC_NOTIFY_TYPE_KICKED          12 /* Kicked from channel */
+#define SILC_NOTIFY_TYPE_KILLED          13 /* Killed from the network */
 
 /* Prototypes */
 SilcNotifyPayload silc_notify_payload_parse(SilcBuffer buffer);
index e3f98a524901cad2cce5420c36e6ecf9e34198c0..7d1b11ba1c837fb2a9f8f551b682dea318f489f1 100644 (file)
@@ -219,6 +219,7 @@ typedef int (*SilcPacketCheckDecrypt)(SilcPacketType packet_type,
 #define SILC_PACKET_REKEY_DONE           23      /* Re-key done */
 #define SILC_PACKET_HEARTBEAT            24      /* Heartbeat */
 #define SILC_PACKET_KEY_AGREEMENT        25      /* Key Agreement request */
+#define SILC_PACKET_CELL_ROUTERS         26      /* Cell routers backup */
 
 #define SILC_PACKET_PRIVATE              200     /* Private range start  */
 #define SILC_PACKET_MAX                  255     /* RESERVED */