updates.
authorPekka Riikonen <priikone@silcnet.org>
Thu, 22 Feb 2001 17:07:37 +0000 (17:07 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 22 Feb 2001 17:07:37 +0000 (17:07 +0000)
23 files changed:
CHANGES
apps/silc/client_ops.c
apps/silcd/command.c
apps/silcd/idlist.c
apps/silcd/idlist.h
apps/silcd/packet_receive.c
apps/silcd/packet_receive.h
apps/silcd/packet_send.c
apps/silcd/packet_send.h
apps/silcd/server.c
apps/silcd/server.h
doc/draft-riikonen-silc-pp-01.nroff
doc/draft-riikonen-silc-spec-01.nroff
lib/silcclient/client.c
lib/silccore/Makefile.am
lib/silccore/id.c
lib/silccore/id.h
lib/silccore/silcmode.c [deleted file]
lib/silccore/silcmode.h
lib/silccore/silcnotify.h
lib/silccore/silcpacket.h
lib/silccore/silcpayload.c
lib/silccrypt/silcpkcs.c

diff --git a/CHANGES b/CHANGES
index 9bf31c6a3350c92c7b2ea7126f4005d07990b6f0..eca1b47e0a14331406d3f30f4932abc8ad47786d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,69 @@
+Thu Feb 22 15:08:20 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Added List flag (SILC_PACKET_FLAG_LIST) to indicate list of
+         payloads in one packet.
+
+       * Deprecated following packet types: NEW_ID_LIST, NEW_CHANNEL_LIST,
+         NEW_CHANNEL_USER_LIST, SET_MODE and SET_MODE_LIST.  List packets
+         use now the new List flag.
+
+       * Also deprecated the following packet types: REPLACE_ID,
+         NEW_CHANNEL_USER and REMOVE_CHANNEL_USER packet types.
+        
+       * Added list support for Notify packet in server.
+
+       * Added silc_server_send_notify_channel_change to send the
+         CHANNEL_CHANGE notify type to replace channel ID's.  Deprecates
+         the silc_server_send_replace_id.
+
+       * Added silc_server_send_notify_nick_change to send the
+         NICK_CHANGE notify type.  Deprecates the function
+         silc_server_send_replace_id.
+
+       * Added silc_server_send_notify_join to send the JOIN notify type.
+         Deprecates the function silc_server_send_new_channel_user.
+
+       * Added silc_server_send_notify_leave to send LEAVE notify type.
+         Deprecates the function silc_server_send_remove_channel_user.
+
+       * Added silc_server_send_notify_cmode and 
+         silc_server_send_notify_cumode to send CMODE and CUMODE notify
+         types.  Deprecates the silc_server_send_set_mode function.
+
+       * Added SERVER_SIGNOFF notify type to indicate that server has
+         quit.  This means that all clients on the channel from that 
+         server will drop.  This can be also used when netsplit happens.
+
+         Deprecated REMOVE_ID packet type since it is not needed anymore
+         even from server.
+
+         Added silc_server_send_notify_server_signoff to send the
+         SERVER_SIGNOFF notify type.  Deprecates the function
+         silc_server_send_remove_id.
+
+         Added also silc_server_send_notify_signoff to send the
+         SIGNOFF notify type.
+
+       * Employed the PKCS #1. It is the mandatory way to do RSA in the
+         SILC protocol from this day on.  Changed the protocol 
+         specification as well.
+
+       * Added silc_server_send_notify_topic_set to send TOPIC_SET
+         notify type.  It is used between routers to notify about
+         topic changes on a channel.
+
+       * Added silc_id_dup into lib/silccore/id.[ch] to duplicate
+         ID data.
+
+       * Partly updated the protocol specification to comply with the
+         changes now made.  It is still though a bit outdated.
+
+       * The JOIN notify type now takes one extra argument <Channel ID>.
+         The packet used to be destined to the channel but now the
+         JOIN type may be sent as list thus it is impossible to 
+         destine it to any specific channel.  By adding this argument
+         it is again possible.
+
 Wed Feb 21 22:39:30 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Added CREDITS file.  The CHANGES and CREDITS file will appear
index d87393a71c7a4cb8f03747ba3d8533000be359a1..0aeea8fed1c3b1da98d1018493a2541e469f5528 100644 (file)
@@ -186,10 +186,10 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
     client_entry2 = va_arg(vp, SilcClientEntry);
     channel_entry = va_arg(vp, SilcChannelEntry);
     if (tmp)
-      snprintf(message, sizeof(message), "%s changed %s mode to +%s", 
+      snprintf(message, sizeof(message), "%s changed %s's mode to +%s", 
               client_entry->nickname, client_entry2->nickname, tmp);
     else
-      snprintf(message, sizeof(message), "%s removed %s modes", 
+      snprintf(message, sizeof(message), "%s removed %s's modes", 
               client_entry->nickname, client_entry2->nickname);
     if (client_entry2 == conn->local_entry) {
       if (app->screen->bottom_line->mode)
index 5ddd61118abb889fa01bc4b67fa09da933ecd821..e0477ee45f0ddaf6ca6b26ca6a6f73f2153154ab 100644 (file)
@@ -1285,13 +1285,12 @@ SILC_SERVER_CMD_FUNC(nick)
 
   /* Send notify about nickname change to our router. We send the new
      ID and ask to replace it with the old one. If we are router the
-     packet is broadcasted. */
+     packet is broadcasted. Send NICK_CHANGE notify. */
   if (!server->standalone)
-    silc_server_send_replace_id(server, server->router->connection, 
-                               server->server_type == SILC_SERVER ? 
-                               FALSE : TRUE, client->id,
-                               SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
-                               new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
+    silc_server_send_notify_nick_change(server, server->router->connection, 
+                                       server->server_type == SILC_SERVER ? 
+                                       FALSE : TRUE, client->id,
+                                       new_id, SILC_ID_CLIENT_LEN);
 
   /* Remove old cache entry */
   silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT, 
@@ -1318,7 +1317,7 @@ SILC_SERVER_CMD_FUNC(nick)
 
   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
-  /* Send NICK_CHANGE notify */
+  /* Send NICK_CHANGE notify to the client's channels */
   silc_server_send_notify_on_channels(server, client, 
                                      SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
                                      oidp->data, oidp->len, 
@@ -1419,6 +1418,13 @@ SILC_SERVER_CMD_FUNC(topic)
       silc_free(channel->topic);
     channel->topic = strdup(tmp);
 
+    /* Send TOPIC_SET notify type to the network */
+    if (!server->standalone)
+      silc_server_send_notify_topic_set(server, server->router->connection,
+                                       server->server_type == SILC_ROUTER ?
+                                       TRUE : FALSE, channel, client->id,
+                                       SILC_ID_CLIENT_LEN, channel->topic);
+
     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
     /* Send notify about topic change to all clients on the channel */
@@ -1552,7 +1558,8 @@ SILC_SERVER_CMD_FUNC(invite)
   sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
 
   /* Send notify to the client that is invited to the channel */
-  silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
+  silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
+                              SILC_ID_CLIENT,
                               SILC_NOTIFY_TYPE_INVITE, 2, 
                               sidp->data, sidp->len, tmp, len);
 
@@ -1933,16 +1940,16 @@ static void silc_server_command_join_channel(SilcServer server,
   if (!cmd->pending) {
     /* Send JOIN notify to locally connected clients on the channel */
     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
-                                      SILC_NOTIFY_TYPE_JOIN, 1,
-                                      clidp->data, clidp->len);
+                                      SILC_NOTIFY_TYPE_JOIN, 2,
+                                      clidp->data, clidp->len,
+                                      chidp->data, chidp->len);
 
-    /* Send NEW_CHANNEL_USER packet to our primary router */
+    /* Send JOIN notify packet to our primary router */
     if (!server->standalone)
-      silc_server_send_new_channel_user(server, server->router->connection,
-                                       server->server_type == SILC_SERVER ?
-                                       FALSE : TRUE,
-                                       channel->id, SILC_ID_CHANNEL_LEN,
-                                       client->id, SILC_ID_CLIENT_LEN);
+      silc_server_send_notify_join(server, server->router->connection,
+                                  server->server_type == SILC_ROUTER ?
+                                  TRUE : FALSE, channel, client->id,
+                                  SILC_ID_CLIENT_LEN);
   }
 
   /* Send USERS command reply to the joined channel so the user sees who
@@ -2565,19 +2572,17 @@ SILC_SERVER_CMD_FUNC(cmode)
 
   /* Send CMODE_CHANGE notify */
   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
-  silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
+  silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
                                     SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
                                     cidp->data, cidp->len, 
                                     tmp_mask, tmp_len);
 
-  /* Set SET_MODE packet to network */
+  /* Set CMODE notify type to network */
   if (!server->standalone)
-    silc_server_send_set_mode(server, server->router->connection,
-                             server->server_type == SILC_ROUTER ? 
-                             TRUE : FALSE, SILC_MODE_TYPE_CHANNEL,
-                             mode_mask, 2,
-                             tmp_id, tmp_len2,
-                             cidp->data, cidp->len);
+    silc_server_send_notify_cmode(server, server->router->connection,
+                                 server->server_type == SILC_ROUTER ? 
+                                 TRUE : FALSE, channel,
+                                 mode_mask, client->id, SILC_ID_CLIENT_LEN);
 
   /* Send command reply to sender */
   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
@@ -2752,22 +2757,22 @@ SILC_SERVER_CMD_FUNC(cumode)
 
   /* Send notify to channel, notify only if mode was actually changed. */
   if (notify) {
-    silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
+    silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
                                       SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
                                       idp->data, idp->len,
                                       tmp_mask, 4, 
                                       tmp_id, tmp_len);
-  }
 
-  /* Set SET_MODE packet to network */
-  if (!server->standalone)
-    silc_server_send_set_mode(server, server->router->connection,
-                             server->server_type == SILC_ROUTER ? 
-                             TRUE : FALSE, SILC_MODE_TYPE_UCHANNEL,
-                             target_mask, 3,
-                             tmp_ch_id, tmp_ch_len,
-                             idp->data, idp->len,
-                             tmp_id, tmp_len);
+    /* Set CUMODE notify type to network */
+    if (!server->standalone)
+      silc_server_send_notify_cumode(server, server->router->connection,
+                                    server->server_type == SILC_ROUTER ? 
+                                    TRUE : FALSE, channel,
+                                    target_mask, client->id, 
+                                    SILC_ID_CLIENT_LEN,
+                                    target_client->id, 
+                                    SILC_ID_CLIENT_LEN);
+  }
 
   /* Send command reply to sender */
   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
@@ -2854,12 +2859,12 @@ SILC_SERVER_CMD_FUNC(leave)
   }
 
   /* Notify routers that they should remove this client from their list
-     of clients on the channel. */
+     of clients on the channel. Send LEAVE notify type. */
   if (!server->standalone)
-    silc_server_send_remove_channel_user(server, 
-                                        server->router->connection,
-                                        server->server_type == SILC_ROUTER ?
-                                        TRUE : FALSE, id_entry->id, id);
+    silc_server_send_notify_leave(server, server->router->connection,
+                                 server->server_type == SILC_ROUTER ?
+                                 TRUE : FALSE, channel, id_entry->id,
+                                 SILC_ID_CLIENT_LEN);
 
   /* Remove client from channel */
   i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
index 6323af367cead87a754cc6c4f17318b821ea5709..e50a87be957de6d7c761f67e9acd11c1ebddde73 100644 (file)
@@ -224,13 +224,14 @@ silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname,
 /* Free client entry. This free's everything and removes the entry
    from ID cache. Call silc_idlist_del_data before calling this one. */
 
-void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
+int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
 {
   if (entry) {
     /* Remove from cache */
     if (entry->id)
-      silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT, 
-                            (void *)entry->id);
+      if (!silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT, 
+                                 (void *)entry->id))
+       return FALSE;
 
     /* Free data */
     if (entry->nickname)
@@ -244,7 +245,11 @@ void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
 
     memset(entry, 'F', sizeof(*entry));
     silc_free(entry);
+
+    return TRUE;
   }
+
+  return FALSE;
 }
 
 /* Returns all clients matching requested nickname. Number of clients is
@@ -469,6 +474,8 @@ silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
     silc_idcache_sort_by_data(id_list->clients);
   }
 
+  SILC_LOG_DEBUG(("Replaced"));
+
   return client;
 }
 
index c9ce8cf6ef59ff57ca415b27f8e19a29eae02550..0929222740f566fddece6f04cf336defce614b6e 100644 (file)
@@ -470,7 +470,7 @@ SilcClientEntry
 silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname, 
                       char *username, char *userinfo, SilcClientID *id, 
                       SilcServerEntry router, void *connection);
-void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry);
+int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry);
 SilcClientEntry *
 silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
                                    char *server, unsigned int *clients_count);
index 5621960a3087bf90e976cff6f616c977172ecc49..b6c58ed1e5d66c174a3a66ffeec7eb36c74130eb 100644 (file)
 
 extern char *server_version;
 
-/* Received private message. This resolves the destination of the message 
-   and sends the packet. This is used by both server and router.  If the
-   destination is our locally connected client this sends the packet to
-   the client. This may also send the message for further routing if
-   the destination is not in our server (or router). */
+/* Received notify packet. Server can receive notify packets from router. 
+   Server then relays the notify messages to clients if needed. */
 
-void silc_server_private_message(SilcServer server,
-                                SilcSocketConnection sock,
-                                SilcPacketContext *packet)
+void silc_server_notify(SilcServer server,
+                       SilcSocketConnection sock,
+                       SilcPacketContext *packet)
 {
-  SilcClientID *id;
-  SilcServerEntry router;
-  SilcSocketConnection dst_sock;
+  SilcNotifyPayload payload;
+  SilcNotifyType type;
+  SilcArgumentPayload args;
+  SilcChannelID *channel_id;
+  SilcClientID *client_id, *client_id2;
+  SilcChannelEntry channel;
   SilcClientEntry client;
-  SilcIDListData idata;
+  SilcChannelClientEntry chl;
+  unsigned int mode;
+  unsigned char *tmp;
+  unsigned int tmp_len;
 
   SILC_LOG_DEBUG(("Start"));
 
-  if (!packet->dst_id)
-    goto err;
+  if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
+      packet->src_id_type != SILC_ID_SERVER)
+    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"));
-    goto err;
+  /* 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
+     have the broadcast flag set already and we won't do anything. */
+  if (!server->standalone && server->server_type == SILC_ROUTER &&
+      sock->type == SILC_SOCKET_TYPE_SERVER &&
+      !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+    SILC_LOG_DEBUG(("Broadcasting received Notify packet"));
+    silc_server_packet_send(server, server->router->connection, packet->type,
+                           packet->flags | SILC_PACKET_FLAG_BROADCAST, 
+                           packet->buffer->data, packet->buffer->len, FALSE);
   }
 
-  /* 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;
+  payload = silc_notify_payload_parse(packet->buffer);
+  if (!payload)
+    return;
 
-      silc_server_send_private_message(server, router->connection,
-                                      idata->send_key,
-                                      idata->hmac,
-                                      packet);
-      return;
-    }
+  type = silc_notify_get_type(payload);
+  args = silc_notify_get_args(payload);
+  if (!args)
+    goto out;
 
-    /* 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);
-    return;
-  }
+  switch(type) {
+  case SILC_NOTIFY_TYPE_JOIN:
+    /* 
+     * Distribute the notify to local clients on the channel
+     */
+    SILC_LOG_DEBUG(("JOIN notify"));
 
-  /* 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;
+    /* Get Channel ID */
+    tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+    if (!tmp)
+      goto out;
+    channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+    if (!channel_id)
+      goto out;
 
-    /* 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);
+    /* Get channel entry */
+    channel = silc_idlist_find_channel_by_id(server->local_list, 
+                                            channel_id, NULL);
+    if (!channel) {
+      channel = silc_idlist_find_channel_by_id(server->global_list, 
+                                              channel_id, NULL);
+      if (!channel) {
+       silc_free(channel_id);
+       goto out;
+      }
     }
-    return;
-  }
+    silc_free(channel_id);
 
-  /* 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 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;
 
-      /* Get fastest route and send packet. */
-      if (router)
-       silc_server_send_private_message(server, dst_sock, 
-                                        idata->send_key,
-                                        idata->hmac, packet);
-      return;
+    /* Send to channel */
+    silc_server_packet_send_to_channel(server, sock, channel, packet->type, 
+                                      FALSE, packet->buffer->data, 
+                                      packet->buffer->len, FALSE);
+
+    /* If the the client is not in local list we check global list (ie. the
+       channel will be global channel) and if it does not exist then create
+       entry for the client. */
+    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) {
+       /* If router did not find the client the it is bogus */
+       if (server->server_type == SILC_ROUTER)
+         goto out;
+
+       client = 
+         silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
+                                silc_id_dup(client_id, SILC_ID_CLIENT), 
+                                sock->user_data, NULL);
+       if (!client) {
+         silc_free(client_id);
+         goto out;
+       }
+      }
     }
-  }
 
- err:
-  silc_server_send_error(server, sock, 
-                        "No such nickname: Private message not sent");
-}
+    /* Do not add client to channel if it is there already */
+    if (silc_server_client_on_channel(client, channel))
+      break;
 
-/* Processes incoming command reply packet. The command reply packet may
-   be destined to one of our clients or it may directly for us. We will 
-   call the command reply routine after processing the packet. */
+    if (server->server_type == SILC_SERVER && 
+       sock->type == SILC_SOCKET_TYPE_ROUTER)
+      /* The channel is global now */
+      channel->global_users = TRUE;
 
-void silc_server_command_reply(SilcServer server,
-                              SilcSocketConnection sock,
-                              SilcPacketContext *packet)
-{
-  SilcBuffer buffer = packet->buffer;
-  SilcClientEntry client = NULL;
-  SilcSocketConnection dst_sock;
-  SilcIDListData idata;
-  SilcClientID *id = NULL;
+    /* JOIN the global client to the channel (local clients (if router 
+       created the channel) is joined in the pending JOIN command). */
+    chl = silc_calloc(1, sizeof(*chl));
+    chl->client = client;
+    chl->channel = channel;
+    silc_list_add(channel->user_list, chl);
+    silc_list_add(client->channels, chl);
+    silc_free(client_id);
 
-  SILC_LOG_DEBUG(("Start"));
+    break;
 
-  /* Source must be server or router */
-  if (packet->src_id_type != SILC_ID_SERVER &&
-      sock->type != SILC_SOCKET_TYPE_ROUTER)
-    return;
+  case SILC_NOTIFY_TYPE_LEAVE:
+    /* 
+     * Distribute the notify to local clients on the channel
+     */
+    SILC_LOG_DEBUG(("LEAVE notify"));
 
-  if (packet->dst_id_type == SILC_ID_CHANNEL)
-    return;
+    channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
+                               packet->dst_id_type);
+    if (!channel_id)
+      goto out;
 
-  if (packet->dst_id_type == SILC_ID_CLIENT) {
-    /* Destination must be one of ours */
-    id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT);
-    if (!id)
-      return;
-    client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
-    if (!client) {
-      SILC_LOG_ERROR(("Cannot process command reply to unknown client"));
-      silc_free(id);
-      return;
+    /* Get channel entry */
+    channel = silc_idlist_find_channel_by_id(server->local_list, 
+                                            channel_id, NULL);
+    if (!channel) { 
+      silc_free(channel_id);
+      goto out;
     }
-  }
 
-  if (packet->dst_id_type == SILC_ID_SERVER) {
-    /* For now this must be for us */
-    if (SILC_ID_SERVER_COMPARE(packet->dst_id, server->id_string)) {
-      SILC_LOG_ERROR(("Cannot process command reply to unknown server"));
-      return;
+    /* Get client ID */
+    tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+    if (!tmp) {
+      silc_free(channel_id);
+      goto out;
+    }
+    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    if (!client_id) {
+      silc_free(channel_id);
+      goto out;
     }
-  }
 
-  /* Execute command reply locally for the command */
-  silc_server_command_reply_process(server, sock, buffer);
+    /* Send to channel */
+    silc_server_packet_send_to_channel(server, sock, channel, packet->type, 
+                                      FALSE, packet->buffer->data, 
+                                      packet->buffer->len, FALSE);
 
-  if (packet->dst_id_type == SILC_ID_CLIENT && client && id) {
-    /* Relay the packet to the client */
-    
-    dst_sock = (SilcSocketConnection)client->connection;
-    silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len 
-                    + packet->dst_id_len + packet->padlen);
-    
-    silc_packet_send_prepare(dst_sock, 0, 0, buffer->len);
-    silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len);
-    
-    idata = (SilcIDListData)client;
-    
-    /* Encrypt packet */
-    silc_packet_encrypt(idata->send_key, idata->hmac, dst_sock->outbuf, 
-                       buffer->len);
-    
-    /* Send the packet */
-    silc_server_packet_send_real(server, dst_sock, TRUE);
-
-    silc_free(id);
-  }
-}
-
-/* Process received channel message. The message can be originated from
-   client or server. */
-
-void silc_server_channel_message(SilcServer server,
-                                SilcSocketConnection sock,
-                                SilcPacketContext *packet)
-{
-  SilcChannelEntry channel = NULL;
-  SilcChannelClientEntry chl;
-  SilcChannelID *id = NULL;
-  void *sender = NULL;
+    /* Get client entry */
+    client = silc_idlist_find_client_by_id(server->global_list, 
+                                          client_id, NULL);
+    if (!client) {
+      client = silc_idlist_find_client_by_id(server->local_list, 
+                                            client_id, NULL);
+      if (!client) {
+       silc_free(client_id);
+       silc_free(channel_id);
+       goto out;
+      }
+    }
+    silc_free(client_id);
 
-  SILC_LOG_DEBUG(("Processing channel message"));
+    /* Remove the user from channel */
+    silc_server_remove_from_one_channel(server, sock, channel, client, FALSE);
+    break;
 
-  /* Sanity checks */
-  if (packet->dst_id_type != SILC_ID_CHANNEL) {
-    SILC_LOG_DEBUG(("Received bad message for channel, dropped"));
-    goto out;
-  }
+  case SILC_NOTIFY_TYPE_SIGNOFF:
+    /* 
+     * Distribute the notify to local clients on the channel
+     */
+    SILC_LOG_DEBUG(("SIGNOFF notify"));
 
-  /* Find channel entry */
-  id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
-  if (!id)
-    goto out;
-  channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
-  if (!channel) {
-    channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
-    if (!channel) {
-      SILC_LOG_DEBUG(("Could not find channel"));
+    /* Get client ID */
+    tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+    if (!tmp)
       goto out;
-    }
-  }
-
-  /* See that this client is on the channel. If the message is coming
-     from router we won't do the check as the message is from client that
-     we don't know about. Also, if the original sender is not client
-     (as it can be server as well) we don't do the check. */
-  sender = silc_id_str2id(packet->src_id, packet->src_id_len, 
-                         packet->src_id_type);
-  if (!sender)
-    goto out;
-  if (sock->type != SILC_SOCKET_TYPE_ROUTER && 
-      packet->src_id_type == SILC_ID_CLIENT) {
-    silc_list_start(channel->user_list);
-    while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
-      if (chl->client && !SILC_ID_CLIENT_COMPARE(chl->client->id, sender))
-       break;
-    }
-    if (chl == SILC_LIST_END)
+    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    if (!client_id)
       goto out;
-  }
-
-  /* Distribute the packet to our local clients. This will send the
-     packet for further routing as well, if needed. */
-  silc_server_packet_relay_to_channel(server, sock, channel, sender,
-                                     packet->src_id_type,
-                                     packet->buffer->data,
-                                     packet->buffer->len, FALSE);
-
- out:
-  if (sender)
-    silc_free(sender);
-  if (id)
-    silc_free(id);
-}
-
-/* Received channel key packet. We distribute the key to all of our locally
-   connected clients on the channel. */
-
-void silc_server_channel_key(SilcServer server,
-                            SilcSocketConnection sock,
-                            SilcPacketContext *packet)
-{
-  SilcBuffer buffer = packet->buffer;
-  SilcChannelEntry channel;
-
-  if (packet->src_id_type != SILC_ID_SERVER)
-    return;
-
-  /* Save the channel key */
-  channel = silc_server_save_channel_key(server, buffer, NULL);
-  if (!channel)
-    return;
-
-  /* Distribute the key to everybody who is on the channel. If we are router
-     we will also send it to locally connected servers. */
-  silc_server_send_channel_key(server, sock, channel, FALSE);
-}
 
-/* Received packet to replace a ID. This checks that the requested ID
-   exists and replaces it with the new one. */
+    /* Get client entry */
+    client = silc_idlist_find_client_by_id(server->global_list, 
+                                          client_id, NULL);
+    if (!client) {
+      client = silc_idlist_find_client_by_id(server->local_list, 
+                                            client_id, NULL);
+      if (!client) {
+       silc_free(client_id);
+       goto out;
+      }
+    }
+    silc_free(client_id);
 
-void silc_server_replace_id(SilcServer server,
-                           SilcSocketConnection sock,
-                           SilcPacketContext *packet)
-{
-  SilcBuffer buffer = packet->buffer;
-  unsigned char *old_id = NULL, *new_id = NULL;
-  SilcIdType old_id_type, new_id_type;
-  unsigned short old_id_len, new_id_len;
-  void *id = NULL, *id2 = NULL;
-  int ret;
+    /* Remove the client from all channels */
+    silc_server_remove_from_channels(server, NULL, client);
 
-  if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
-      packet->src_id_type == SILC_ID_CLIENT)
-    return;
+    /* Remove the client entry */
+    if (!silc_idlist_del_client(server->global_list, client))
+      silc_idlist_del_client(server->local_list, client);
+    break;
 
-  SILC_LOG_DEBUG(("Replacing ID"));
+  case SILC_NOTIFY_TYPE_TOPIC_SET:
+    /* 
+     * Distribute the notify to local clients on the channel
+     */
 
-  ret = silc_buffer_unformat(buffer,
-                            SILC_STR_UI_SHORT(&old_id_type),
-                            SILC_STR_UI16_NSTRING_ALLOC(&old_id, &old_id_len),
-                            SILC_STR_UI_SHORT(&new_id_type),
-                            SILC_STR_UI16_NSTRING_ALLOC(&new_id, &new_id_len),
-                            SILC_STR_END);
-  if (ret == -1)
-    goto out;
+    SILC_LOG_DEBUG(("TOPIC SET notify"));
 
-  if (old_id_type != new_id_type)
-    goto out;
+    channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
+                               packet->dst_id_type);
+    if (!channel_id)
+      goto out;
 
-  if (old_id_len != silc_id_get_len(old_id_type) ||
-      new_id_len != silc_id_get_len(new_id_type))
-    goto out;
+    /* Get channel entry */
+    channel = silc_idlist_find_channel_by_id(server->local_list, 
+                                            channel_id, NULL);
+    if (!channel) {
+      channel = silc_idlist_find_channel_by_id(server->global_list, 
+                                              channel_id, NULL);
+      if (!channel) {
+       silc_free(channel_id);
+       goto out;
+      }
+    }
 
-  id = silc_id_str2id(old_id, old_id_len, old_id_type);
-  if (!id)
-    goto out;
+    /* Get the topic */
+    tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+    if (!tmp) {
+      silc_free(channel_id);
+      goto out;
+    }
 
-  id2 = silc_id_str2id(new_id, new_id_len, new_id_type);
-  if (!id2)
-    goto out;
+    if (channel->topic)
+      silc_free(channel->topic);
+    channel->topic = silc_calloc(tmp_len, sizeof(*channel->topic));
+    memcpy(channel->topic, tmp, tmp_len);
 
-  /* 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
-     have the broadcast flag set already and we won't do anything. */
-  if (!server->standalone && server->server_type == SILC_ROUTER &&
-      sock->type == SILC_SOCKET_TYPE_SERVER &&
-      !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
-    SILC_LOG_DEBUG(("Broadcasting received Replace ID packet"));
-    silc_server_packet_send(server, server->router->connection, packet->type,
-                           packet->flags | SILC_PACKET_FLAG_BROADCAST, 
-                           buffer->data, buffer->len, FALSE);
-  }
+    /* Send the same notify to the channel */
+    silc_server_packet_send_to_channel(server, sock, channel, packet->type, 
+                                      FALSE, packet->buffer->data, 
+                                      packet->buffer->len, FALSE);
+    silc_free(channel_id);
+    break;
 
-  /* Replace the old ID */
-  switch(old_id_type) {
-  case SILC_ID_CLIENT:
+  case SILC_NOTIFY_TYPE_NICK_CHANGE:
     {
-      SilcBuffer nidp, oidp;
-      SilcClientEntry client = NULL;
+      /* 
+       * Distribute the notify to local clients on the channel
+       */
+      unsigned char *id, *id2;
 
+      SILC_LOG_DEBUG(("NICK CHANGE notify"));
+      
+      /* Get old client ID */
+      id = silc_argument_get_arg_type(args, 1, &tmp_len);
+      if (!id)
+       goto out;
+      client_id = silc_id_payload_parse_id(id, tmp_len);
+      if (!client_id)
+       goto out;
+      
+      /* Get new client ID */
+      id2 = silc_argument_get_arg_type(args, 2, &tmp_len);
+      if (!id2)
+       goto out;
+      client_id2 = silc_id_payload_parse_id(id2, tmp_len);
+      if (!client_id2)
+       goto out;
+      
       SILC_LOG_DEBUG(("Old Client ID id(%s)", 
-                     silc_id_render(id, SILC_ID_CLIENT)));
+                     silc_id_render(client_id, SILC_ID_CLIENT)));
       SILC_LOG_DEBUG(("New Client ID id(%s)", 
-                     silc_id_render(id2, SILC_ID_CLIENT)));
+                     silc_id_render(client_id2, SILC_ID_CLIENT)));
 
-      if ((client = silc_idlist_replace_client_id(server->local_list, 
-                                                 id, id2)) == NULL)
-       if (server->server_type == SILC_ROUTER)
-         client = silc_idlist_replace_client_id(server->global_list, id, id2);
-      
-      if (client) {
-       oidp = silc_id_payload_encode(id, SILC_ID_CLIENT);
-       nidp = silc_id_payload_encode(id2, SILC_ID_CLIENT);
+      /* Replace the Client ID */
+      client = silc_idlist_replace_client_id(server->global_list, client_id,
+                                            client_id2);
+      if (!client)
+       client = silc_idlist_replace_client_id(server->local_list, client_id, 
+                                              client_id2);
 
+      if (client) {
        /* The nickname is not valid anymore, set it NULL. This causes that
           the nickname will be queried if someone wants to know it. */
        if (client->nickname)
@@ -374,1673 +339,1116 @@ void silc_server_replace_id(SilcServer server,
           this client is joined to. */
        silc_server_send_notify_on_channels(server, client, 
                                            SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
-                                           oidp->data, oidp->len, 
-                                           nidp->data, nidp->len);
-       
-       silc_buffer_free(nidp);
-       silc_buffer_free(oidp);
+                                           id, tmp_len, 
+                                           id2, tmp_len);
       }
+
+      silc_free(client_id);
+      if (!client)
+       silc_free(client_id2);
       break;
     }
 
-  case SILC_ID_SERVER:
-    SILC_LOG_DEBUG(("Old Server ID id(%s)", 
-                   silc_id_render(id, SILC_ID_SERVER)));
-    SILC_LOG_DEBUG(("New Server ID id(%s)", 
-                   silc_id_render(id2, SILC_ID_SERVER)));
-    if (silc_idlist_replace_server_id(server->local_list, id, id2) == NULL)
-      if (server->server_type == SILC_ROUTER)
-       silc_idlist_replace_server_id(server->global_list, id, id2);
-    break;
+  case SILC_NOTIFY_TYPE_CMODE_CHANGE:
+    /* 
+     * Distribute the notify to local clients on the channel
+     */
+    
+    SILC_LOG_DEBUG(("CMODE CHANGE notify"));
+      
+    channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
+                               packet->dst_id_type);
+    if (!channel_id)
+      goto out;
 
-  case SILC_ID_CHANNEL:
-    SILC_LOG_DEBUG(("Old Channel ID id(%s)", 
-                   silc_id_render(id, SILC_ID_CHANNEL)));
-    SILC_LOG_DEBUG(("New Channel ID id(%s)", 
-                   silc_id_render(id2, SILC_ID_CHANNEL)));
-    if (silc_idlist_replace_channel_id(server->local_list, id, id2) == NULL)
-      silc_idlist_replace_channel_id(server->global_list, id, id2);
-    break;
+    /* Get channel entry */
+    channel = silc_idlist_find_channel_by_id(server->local_list, 
+                                            channel_id, NULL);
+    if (!channel) {
+      channel = silc_idlist_find_channel_by_id(server->global_list, 
+                                              channel_id, NULL);
+      if (!channel) {
+       silc_free(channel_id);
+       goto out;
+      }
+    }
 
-  default:
-    silc_free(id2);
-    break;
-  }
+    /* Send the same notify to the channel */
+    silc_server_packet_send_to_channel(server, sock, channel, packet->type, 
+                                      FALSE, packet->buffer->data, 
+                                      packet->buffer->len, FALSE);
 
- out:
-  if (id)
-    silc_free(id);
-  if (old_id)
-    silc_free(old_id);
-  if (new_id)
-    silc_free(new_id);
-}
+    /* Get the mode */
+    tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+    if (!tmp) {
+      silc_free(channel_id);
+      goto out;
+    }
 
+    SILC_GET32_MSB(mode, tmp);
 
-/* Received New Client packet and processes it.  Creates Client ID for the
-   client. Client becomes registered after calling this functions. */
+    /* Change mode */
+    channel->mode = mode;
+    silc_free(channel_id);
+    break;
 
-SilcClientEntry silc_server_new_client(SilcServer server,
-                                      SilcSocketConnection sock,
-                                      SilcPacketContext *packet)
-{
-  SilcBuffer buffer = packet->buffer;
-  SilcClientEntry client;
-  SilcIDCacheEntry cache;
-  SilcClientID *client_id;
-  SilcBuffer reply;
-  SilcIDListData idata;
-  char *username = NULL, *realname = NULL, *id_string;
-  int ret;
+  case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
+    /* 
+     * Distribute the notify to local clients on the channel
+     */
 
-  SILC_LOG_DEBUG(("Creating new client"));
+    SILC_LOG_DEBUG(("CUMODE CHANGE notify"));
 
-  if (sock->type != SILC_SOCKET_TYPE_CLIENT)
-    return NULL;
+    channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
+                               packet->dst_id_type);
+    if (!channel_id)
+      goto out;
 
-  /* Take client entry */
-  client = (SilcClientEntry)sock->user_data;
-  idata = (SilcIDListData)client;
+    /* Get channel entry */
+    channel = silc_idlist_find_channel_by_id(server->local_list, 
+                                            channel_id, NULL);
+    if (!channel) {
+      channel = silc_idlist_find_channel_by_id(server->global_list, 
+                                              channel_id, NULL);
+      if (!channel) {
+       silc_free(channel_id);
+       goto out;
+      }
+    }
 
-  /* Fetch the old client cache entry so that we can update it. */
-  if (!silc_idcache_find_by_context(server->local_list->clients,
-                                   sock->user_data, &cache)) {
-    SILC_LOG_ERROR(("Lost client's cache entry - bad thing"));
-    return NULL;
-  }
+    /* Get the mode */
+    tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+    if (!tmp) {
+      silc_free(channel_id);
+      goto out;
+    }
+      
+    SILC_GET32_MSB(mode, tmp);
 
-  /* Parse incoming packet */
-  ret = silc_buffer_unformat(buffer,
-                            SILC_STR_UI16_STRING_ALLOC(&username),
-                            SILC_STR_UI16_STRING_ALLOC(&realname),
-                            SILC_STR_END);
-  if (ret == -1) {
-    if (username)
-      silc_free(username);
-    if (realname)
-      silc_free(realname);
-    return NULL;
-  }
+    /* Get target client */
+    tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
+    if (!tmp)
+      goto out;
+    client_id = silc_id_payload_parse_id(tmp, tmp_len);
+    if (!client_id)
+      goto out;
+    
+    /* Get client entry */
+    client = silc_idlist_find_client_by_id(server->global_list, 
+                                          client_id, NULL);
+    if (!client) {
+      client = silc_idlist_find_client_by_id(server->local_list, 
+                                            client_id, NULL);
+      if (!client) {
+       silc_free(client_id);
+       goto out;
+      }
+    }
+    silc_free(client_id);
 
-  if (!username) {
-    silc_free(username);
-    if (realname)
-      silc_free(realname);
-    silc_server_disconnect_remote(server, sock, "Server closed connection: "
-                                  "Incomplete client information");
-    return NULL;
-  }
+    /* Get entry to the channel user list */
+    silc_list_start(channel->user_list);
+    while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
+      if (chl->client == client) {
+       /* Change the mode */
+       chl->mode = mode;
+       break;
+      }
 
-  /* Create Client ID */
-  silc_id_create_client_id(server->id, server->rng, server->md5hash,
-                          username, &client_id);
+    /* Send the same notify to the channel */
+    silc_server_packet_send_to_channel(server, sock, channel, packet->type, 
+                                      FALSE, packet->buffer->data, 
+                                      packet->buffer->len, FALSE);
+    silc_free(channel_id);
+    break;
 
-  /* Update client entry */
-  idata->registered = TRUE;
-  client->nickname = strdup(username);
-  client->username = username;
-  client->userinfo = realname ? realname : strdup("");
-  client->id = client_id;
+  case SILC_NOTIFY_TYPE_INVITE:
+    SILC_LOG_DEBUG(("INVITE notify (not-impl XXX)"));
+    break;
 
-  /* Update the cache entry */
-  cache->id = (void *)client_id;
-  cache->type = SILC_ID_CLIENT;
-  cache->data = username;
-  silc_idcache_sort_by_data(server->local_list->clients);
+  case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
+    SILC_LOG_DEBUG(("CHANNEL CHANGE notify (not-impl XXX)"));
+    break;
 
-  /* Notify our router about new client on the SILC network */
-  if (!server->standalone)
-    silc_server_send_new_id(server, (SilcSocketConnection) 
-                           server->router->connection, 
-                           server->server_type == SILC_ROUTER ? TRUE : FALSE,
-                           client->id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
-  
-  /* Send the new client ID to the client. */
-  id_string = silc_id_id2str(client->id, SILC_ID_CLIENT);
-  reply = silc_buffer_alloc(2 + 2 + SILC_ID_CLIENT_LEN);
-  silc_buffer_pull_tail(reply, SILC_BUFFER_END(reply));
-  silc_buffer_format(reply,
-                    SILC_STR_UI_SHORT(SILC_ID_CLIENT),
-                    SILC_STR_UI_SHORT(SILC_ID_CLIENT_LEN),
-                    SILC_STR_UI_XNSTRING(id_string, SILC_ID_CLIENT_LEN),
-                    SILC_STR_END);
-  silc_server_packet_send(server, sock, SILC_PACKET_NEW_ID, 0, 
-                         reply->data, reply->len, FALSE);
-  silc_free(id_string);
-  silc_buffer_free(reply);
+  case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
+    SILC_LOG_DEBUG(("SERVER SIGNOFF notify (not-impl XXX)"));
+    break;
 
-  /* Send some nice info to the client */
-  SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
-                         ("Welcome to the SILC Network %s@%s",
-                          username, sock->hostname));
-  SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
-                         ("Your host is %s, running version %s",
-                          server->config->server_info->server_name,
-                          server_version));
-  if (server->server_type == SILC_ROUTER) {
-    SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
-                           ("There are %d clients on %d servers in SILC "
-                            "Network", server->stat.clients,
-                            server->stat.servers + 1));
-    SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
-                           ("There are %d clients on %d server in our cell",
-                            server->stat.cell_clients,
-                            server->stat.cell_servers + 1));
-    SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
-                           ("I have %d clients, %d channels, %d servers and "
-                            "%d routers",
-                            server->stat.my_clients, 
-                            server->stat.my_channels,
-                            server->stat.my_servers,
-                            server->stat.my_routers));
-    SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
-                           ("%d server operators and %d router operators "
-                            "online",
-                            server->stat.my_server_ops,
-                            server->stat.my_router_ops));
-  } else {
-    SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
-                           ("I have %d clients and %d channels formed",
-                            server->stat.my_clients,
-                            server->stat.my_channels));
-    SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
-                           ("%d operators online",
-                            server->stat.my_server_ops));
+    /* Ignore rest of the notify types for now */
+  case SILC_NOTIFY_TYPE_NONE:
+  case SILC_NOTIFY_TYPE_MOTD:
+    break;
+  default:
+    break;
   }
-  SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
-                         ("Your connection is secured with %s cipher, "
-                          "key length %d bits",
-                          idata->send_key->cipher->name,
-                          idata->send_key->cipher->key_len));
-  SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
-                         ("Your current nickname is %s",
-                          client->nickname));
-
-  /* Send motd */
-  silc_server_send_motd(server, sock);
 
-  return client;
+ out:
+  silc_notify_payload_free(payload);
 }
 
-/* Create new server. This processes received New Server packet and
-   saves the received Server ID. The server is our locally connected
-   server thus we save all the information and save it to local list. 
-   This funtion can be used by both normal server and router server.
-   If normal server uses this it means that its router has connected
-   to the server. If router uses this it means that one of the cell's
-   servers is connected to the router. */
-
-SilcServerEntry silc_server_new_server(SilcServer server,
-                                      SilcSocketConnection sock,
-                                      SilcPacketContext *packet)
+void silc_server_notify_list(SilcServer server,
+                            SilcSocketConnection sock,
+                            SilcPacketContext *packet)
 {
-  SilcBuffer buffer = packet->buffer;
-  SilcServerEntry new_server;
-  SilcIDCacheEntry cache;
-  SilcServerID *server_id;
-  SilcIDListData idata;
-  unsigned char *server_name, *id_string;
-  unsigned short id_len;
-  int ret;
+  SilcPacketContext *new;
+  SilcBuffer buffer;
+  unsigned short len;
 
-  SILC_LOG_DEBUG(("Creating new server"));
+  SILC_LOG_DEBUG(("Processing New Notify List"));
 
-  if (sock->type != SILC_SOCKET_TYPE_SERVER &&
-      sock->type != SILC_SOCKET_TYPE_ROUTER)
-    return NULL;
+  if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
+      packet->src_id_type != SILC_ID_SERVER)
+    return;
 
-  /* Take server entry */
-  new_server = (SilcServerEntry)sock->user_data;
-  idata = (SilcIDListData)new_server;
-
-  /* Fetch the old server cache entry so that we can update it. */
-  if (!silc_idcache_find_by_context(server->local_list->servers,
-                                   sock->user_data, &cache)) {
-    SILC_LOG_ERROR(("Lost server's cache entry - bad thing"));
-    return NULL;
-  }
-
-  /* Parse the incoming packet */
-  ret = silc_buffer_unformat(buffer,
-                            SILC_STR_UI16_NSTRING_ALLOC(&id_string, &id_len),
-                            SILC_STR_UI16_STRING_ALLOC(&server_name),
-                            SILC_STR_END);
-  if (ret == -1) {
-    if (id_string)
-      silc_free(id_string);
-    if (server_name)
-      silc_free(server_name);
-    return NULL;
-  }
+  /* Make copy of the original packet context, except for the actual
+     data buffer, which we will here now fetch from the original buffer. */
+  new = silc_packet_context_alloc();
+  new->type = SILC_PACKET_NOTIFY;
+  new->flags = packet->flags;
+  new->src_id = packet->src_id;
+  new->src_id_len = packet->src_id_len;
+  new->src_id_type = packet->src_id_type;
+  new->dst_id = packet->dst_id;
+  new->dst_id_len = packet->dst_id_len;
+  new->dst_id_type = packet->dst_id_type;
 
-  if (id_len > buffer->len) {
-    silc_free(id_string);
-    silc_free(server_name);
-    return NULL;
-  }
+  buffer = silc_buffer_alloc(1024);
+  new->buffer = buffer;
 
-  /* Get Server ID */
-  server_id = silc_id_str2id(id_string, id_len, SILC_ID_SERVER);
-  if (!server_id) {
-    silc_free(id_string);
-    silc_free(server_name);
-    return NULL;
-  }
-  silc_free(id_string);
+  while (packet->buffer->len) {
+    SILC_GET16_MSB(len, packet->buffer->data + 2);
+    if (len > packet->buffer->len)
+      break;
 
-  /* Update client entry */
-  idata->registered = TRUE;
-  new_server->server_name = server_name;
-  new_server->id = server_id;
+    if (len > buffer->truelen) {
+      silc_buffer_free(buffer);
+      buffer = silc_buffer_alloc(1024 + len);
+    }
 
-  /* Update the cache entry */
-  cache->id = (void *)server_id;
-  cache->type = SILC_ID_SERVER;
-  cache->data = server_name;
-  silc_idcache_sort_by_data(server->local_list->servers);
+    silc_buffer_pull_tail(buffer, len);
+    silc_buffer_put(buffer, packet->buffer->data, len);
 
-  /* Distribute the information about new server in the SILC network
-     to our router. If we are normal server we won't send anything
-     since this connection must be our router connection. */
-  if (server->server_type == SILC_ROUTER && !server->standalone &&
-      server->router->connection != sock)
-    silc_server_send_new_id(server, server->router->connection,
-                           TRUE, new_server->id, SILC_ID_SERVER, 
-                           SILC_ID_SERVER_LEN);
+    /* Process the Notify */
+    silc_server_notify(server, sock, new);
 
-  if (server->server_type == SILC_ROUTER)
-    server->stat.cell_servers++;
+    silc_buffer_push_tail(buffer, len);
+    silc_buffer_pull(packet->buffer, len);
+  }
 
-  return new_server;
+  silc_buffer_free(buffer);
+  silc_free(new);
 }
 
-/* Processes incoming New ID packet. New ID Payload is used to distribute
-   information about newly registered clients and servers. */
+/* Received private message. This resolves the destination of the message 
+   and sends the packet. This is used by both server and router.  If the
+   destination is our locally connected client this sends the packet to
+   the client. This may also send the message for further routing if
+   the destination is not in our server (or router). */
 
-static void silc_server_new_id_real(SilcServer server, 
-                                   SilcSocketConnection sock,
-                                   SilcPacketContext *packet,
-                                   int broadcast)
+void silc_server_private_message(SilcServer server,
+                                SilcSocketConnection sock,
+                                SilcPacketContext *packet)
 {
-  SilcBuffer buffer = packet->buffer;
-  SilcIDList id_list;
+  SilcClientID *id;
   SilcServerEntry router;
-  SilcSocketConnection router_sock;
-  SilcIDPayload idp;
-  SilcIdType id_type;
-  unsigned char *hash = NULL;
-  void *id;
+  SilcSocketConnection dst_sock;
+  SilcClientEntry client;
+  SilcIDListData idata;
 
-  SILC_LOG_DEBUG(("Processing new ID"));
+  SILC_LOG_DEBUG(("Start"));
 
-  if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
-      server->server_type == SILC_SERVER ||
-      packet->src_id_type != SILC_ID_SERVER)
-    return;
+  if (!packet->dst_id)
+    goto err;
 
-  idp = silc_id_payload_parse(buffer);
-  if (!idp)
-    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"));
+    goto err;
+  }
 
-  id_type = silc_id_payload_get_type(idp);
+  /* 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;
 
-  /* Normal server cannot have other normal server connections */
-  if (id_type == SILC_ID_SERVER && sock->type == SILC_SOCKET_TYPE_SERVER)
-    goto out;
+    /* 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;
 
-  id = silc_id_payload_get_id(idp);
-  if (!id)
-    goto out;
+      silc_server_send_private_message(server, router->connection,
+                                      idata->send_key,
+                                      idata->hmac,
+                                      packet);
+      return;
+    }
 
-  /* If the sender of this packet is server and we are router we need to
-     broadcast this packet to other routers in the network. */
-  if (broadcast && !server->standalone && server->server_type == SILC_ROUTER &&
-      sock->type == SILC_SOCKET_TYPE_SERVER &&
-      !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
-    SILC_LOG_DEBUG(("Broadcasting received New ID packet"));
-    silc_server_packet_send(server, server->router->connection,
-                           packet->type, 
-                           packet->flags | SILC_PACKET_FLAG_BROADCAST,
-                           buffer->data, buffer->len, FALSE);
+    /* 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);
+    return;
   }
 
-  if (sock->type == SILC_SOCKET_TYPE_SERVER)
-    id_list = server->local_list;
-  else
-    id_list = server->global_list;
-
-  router_sock = sock;
-  router = sock->user_data;
-
-  switch(id_type) {
-  case SILC_ID_CLIENT:
-    {
-      SilcClientEntry entry;
+  /* 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;
 
-      SILC_LOG_DEBUG(("New client id(%s) from [%s] %s",
-                     silc_id_render(id, SILC_ID_CLIENT),
-                     sock->type == SILC_SOCKET_TYPE_SERVER ?
-                     "Server" : "Router", sock->hostname));
-    
-      /* As a router we keep information of all global information in our
-        global list. Cell wide information however is kept in the local
-        list. The client is put to global list and we will take the hash
-        value of the Client ID and save it to the ID Cache system for fast
-        searching in the future. */
-      hash = silc_calloc(sizeof(((SilcClientID *)id)->hash), 
-                        sizeof(unsigned char));
-      memcpy(hash, ((SilcClientID *)id)->hash, 
-            sizeof(((SilcClientID *)id)->hash));
-      entry = silc_idlist_add_client(id_list, hash, NULL, NULL, id, 
-                                    router, NULL);
-      entry->nickname = NULL;
+    /* 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);
+    }
+    return;
+  }
 
-      if (sock->type == SILC_SOCKET_TYPE_SERVER)
-       server->stat.cell_clients++;
-      server->stat.clients++;
+  /* 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;
 
-#if 0
-      /* XXX Adding two ID's with same IP number replaces the old entry thus
-        gives wrong route. Thus, now disabled until figured out a better way
-        to do this or when removed the whole thing. This could be removed
-        because entry->router->connection gives always the most optimal route
-        for the ID anyway (unless new routes (faster perhaps) are established
-        after receiving this ID, this we don't know however). */
-      /* Add route cache for this ID */
-      silc_server_route_add(silc_server_route_hash(
-                           ((SilcClientID *)id)->ip.s_addr,
-                           server->id->port), ((SilcClientID *)id)->ip.s_addr,
-                           router);
-#endif
+      /* Get fastest route and send packet. */
+      if (router)
+       silc_server_send_private_message(server, dst_sock, 
+                                        idata->send_key,
+                                        idata->hmac, packet);
+      return;
     }
-    break;
+  }
 
-  case SILC_ID_SERVER:
-    SILC_LOG_DEBUG(("New server id(%s) from [%s] %s",
-                   silc_id_render(id, SILC_ID_SERVER),
-                   sock->type == SILC_SOCKET_TYPE_SERVER ?
-                   "Server" : "Router", sock->hostname));
-    
-    /* As a router we keep information of all global information in our global
-       list. Cell wide information however is kept in the local list. */
-    silc_idlist_add_server(id_list, NULL, 0, id, router, router_sock);
+ err:
+  silc_server_send_error(server, sock, 
+                        "No such nickname: Private message not sent");
+}
 
-    if (sock->type == SILC_SOCKET_TYPE_SERVER)
-      server->stat.cell_servers++;
-    server->stat.servers++;
+/* Processes incoming command reply packet. The command reply packet may
+   be destined to one of our clients or it may directly for us. We will 
+   call the command reply routine after processing the packet. */
 
-#if 0
-    /* Add route cache for this ID */
-    silc_server_route_add(silc_server_route_hash(
-                         ((SilcServerID *)id)->ip.s_addr,
-                         ((SilcServerID *)id)->port), 
-                         ((SilcServerID *)id)->ip.s_addr,
-                         router);
-#endif
-    break;
+void silc_server_command_reply(SilcServer server,
+                              SilcSocketConnection sock,
+                              SilcPacketContext *packet)
+{
+  SilcBuffer buffer = packet->buffer;
+  SilcClientEntry client = NULL;
+  SilcSocketConnection dst_sock;
+  SilcIDListData idata;
+  SilcClientID *id = NULL;
 
-  case SILC_ID_CHANNEL:
-    SILC_LOG_ERROR(("Channel cannot be registered with NEW_ID packet"));
-    break;
+  SILC_LOG_DEBUG(("Start"));
 
-  default:
-    break;
+  /* Source must be server or router */
+  if (packet->src_id_type != SILC_ID_SERVER &&
+      sock->type != SILC_SOCKET_TYPE_ROUTER)
+    return;
+
+  if (packet->dst_id_type == SILC_ID_CHANNEL)
+    return;
+
+  if (packet->dst_id_type == SILC_ID_CLIENT) {
+    /* Destination must be one of ours */
+    id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT);
+    if (!id)
+      return;
+    client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
+    if (!client) {
+      SILC_LOG_ERROR(("Cannot process command reply to unknown client"));
+      silc_free(id);
+      return;
+    }
   }
 
- out:
-  silc_id_payload_free(idp);
-}
+  if (packet->dst_id_type == SILC_ID_SERVER) {
+    /* For now this must be for us */
+    if (SILC_ID_SERVER_COMPARE(packet->dst_id, server->id_string)) {
+      SILC_LOG_ERROR(("Cannot process command reply to unknown server"));
+      return;
+    }
+  }
 
+  /* Execute command reply locally for the command */
+  silc_server_command_reply_process(server, sock, buffer);
 
-/* Processes incoming New ID packet. New ID Payload is used to distribute
-   information about newly registered clients and servers. */
+  if (packet->dst_id_type == SILC_ID_CLIENT && client && id) {
+    /* Relay the packet to the client */
+    
+    dst_sock = (SilcSocketConnection)client->connection;
+    silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len 
+                    + packet->dst_id_len + packet->padlen);
+    
+    silc_packet_send_prepare(dst_sock, 0, 0, buffer->len);
+    silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len);
+    
+    idata = (SilcIDListData)client;
+    
+    /* Encrypt packet */
+    silc_packet_encrypt(idata->send_key, idata->hmac, dst_sock->outbuf, 
+                       buffer->len);
+    
+    /* Send the packet */
+    silc_server_packet_send_real(server, dst_sock, TRUE);
 
-void silc_server_new_id(SilcServer server, SilcSocketConnection sock,
-                       SilcPacketContext *packet)
-{
-  silc_server_new_id_real(server, sock, packet, TRUE);
+    silc_free(id);
+  }
 }
 
-/* Receoved New Id List packet, list of New ID payloads inside one
-   packet. Process the New ID payloads one by one. */
+/* Process received channel message. The message can be originated from
+   client or server. */
 
-void silc_server_new_id_list(SilcServer server, SilcSocketConnection sock,
-                            SilcPacketContext *packet)
+void silc_server_channel_message(SilcServer server,
+                                SilcSocketConnection sock,
+                                SilcPacketContext *packet)
 {
-  SilcPacketContext *new_id;
-  SilcBuffer idp;
-  unsigned short id_len;
-
-  SILC_LOG_DEBUG(("Processing New ID List"));
+  SilcChannelEntry channel = NULL;
+  SilcChannelClientEntry chl;
+  SilcChannelID *id = NULL;
+  void *sender = NULL;
 
-  if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
-      packet->src_id_type != SILC_ID_SERVER)
-    return;
+  SILC_LOG_DEBUG(("Processing channel message"));
 
-  /* If the sender of this packet is server and we are router we need to
-     broadcast this packet to other routers in the network. Broadcast
-     this list packet instead of multiple New ID packets. */
-  if (!server->standalone && server->server_type == SILC_ROUTER &&
-      sock->type == SILC_SOCKET_TYPE_SERVER &&
-      !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
-    SILC_LOG_DEBUG(("Broadcasting received New ID List packet"));
-    silc_server_packet_send(server, server->router->connection,
-                           packet->type, 
-                           packet->flags | SILC_PACKET_FLAG_BROADCAST,
-                           packet->buffer->data, packet->buffer->len, FALSE);
+  /* Sanity checks */
+  if (packet->dst_id_type != SILC_ID_CHANNEL) {
+    SILC_LOG_DEBUG(("Received bad message for channel, dropped"));
+    goto out;
   }
 
-  /* Make copy of the original packet context, except for the actual
-     data buffer, which we will here now fetch from the original buffer. */
-  new_id = silc_packet_context_alloc();
-  new_id->type = SILC_PACKET_NEW_ID;
-  new_id->flags = packet->flags;
-  new_id->src_id = packet->src_id;
-  new_id->src_id_len = packet->src_id_len;
-  new_id->src_id_type = packet->src_id_type;
-  new_id->dst_id = packet->dst_id;
-  new_id->dst_id_len = packet->dst_id_len;
-  new_id->dst_id_type = packet->dst_id_type;
-
-  idp = silc_buffer_alloc(256);
-  new_id->buffer = idp;
-
-  while (packet->buffer->len) {
-    SILC_GET16_MSB(id_len, packet->buffer->data + 2);
-    if ((id_len > packet->buffer->len) ||
-       (id_len > idp->truelen))
-      break;
-
-    silc_buffer_pull_tail(idp, 4 + id_len);
-    silc_buffer_put(idp, packet->buffer->data, 4 + id_len);
-
-    /* Process the New ID */
-    silc_server_new_id_real(server, sock, new_id, FALSE);
+  /* Find channel entry */
+  id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
+  if (!id)
+    goto out;
+  channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
+  if (!channel) {
+    channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
+    if (!channel) {
+      SILC_LOG_DEBUG(("Could not find channel"));
+      goto out;
+    }
+  }
 
-    silc_buffer_push_tail(idp, 4 + id_len);
-    silc_buffer_pull(packet->buffer, 4 + id_len);
+  /* See that this client is on the channel. If the message is coming
+     from router we won't do the check as the message is from client that
+     we don't know about. Also, if the original sender is not client
+     (as it can be server as well) we don't do the check. */
+  sender = silc_id_str2id(packet->src_id, packet->src_id_len, 
+                         packet->src_id_type);
+  if (!sender)
+    goto out;
+  if (sock->type != SILC_SOCKET_TYPE_ROUTER && 
+      packet->src_id_type == SILC_ID_CLIENT) {
+    silc_list_start(channel->user_list);
+    while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
+      if (chl->client && !SILC_ID_CLIENT_COMPARE(chl->client->id, sender))
+       break;
+    }
+    if (chl == SILC_LIST_END) {
+      SILC_LOG_DEBUG(("Client not on channel"));
+      goto out;
+    }
   }
 
-  silc_buffer_free(idp);
-  silc_free(new_id);
+  /* Distribute the packet to our local clients. This will send the
+     packet for further routing as well, if needed. */
+  silc_server_packet_relay_to_channel(server, sock, channel, sender,
+                                     packet->src_id_type,
+                                     packet->buffer->data,
+                                     packet->buffer->len, FALSE);
+
+ out:
+  if (sender)
+    silc_free(sender);
+  if (id)
+    silc_free(id);
 }
 
-/* Received New Channel packet. Information about new channels in the 
-   network are distributed using this packet. Save the information about
-   the new channel. This usually comes from router but also normal server
-   can send this to notify channels it has when it connects to us. */
+/* Received channel key packet. We distribute the key to all of our locally
+   connected clients on the channel. */
 
-void silc_server_new_channel(SilcServer server,
+void silc_server_channel_key(SilcServer server,
                             SilcSocketConnection sock,
                             SilcPacketContext *packet)
 {
-  unsigned char *id;
-  SilcChannelID *channel_id;
-  unsigned short channel_id_len;
-  char *channel_name;
-  int ret;
-
-  SILC_LOG_DEBUG(("Processing New Channel"));
+  SilcBuffer buffer = packet->buffer;
+  SilcChannelEntry channel;
 
-  if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
-      packet->src_id_type != SILC_ID_SERVER ||
-      server->server_type == SILC_SERVER)
+  if (packet->src_id_type != SILC_ID_SERVER)
     return;
 
-  /* Parse payload */
-  ret = silc_buffer_unformat(packet->buffer, 
-                            SILC_STR_UI16_STRING_ALLOC(&channel_name),
-                            SILC_STR_UI16_NSTRING_ALLOC(&id, &channel_id_len),
-                            SILC_STR_END);
-  if (ret == -1) {
-    if (channel_name)
-      silc_free(channel_name);
-    if (id)
-      silc_free(id);
-    return;
-  }
-    
-  /* Decode the channel ID */
-  channel_id = silc_id_str2id(id, channel_id_len, SILC_ID_CHANNEL);
-  if (!channel_id)
+  /* Save the channel key */
+  channel = silc_server_save_channel_key(server, buffer, NULL);
+  if (!channel)
     return;
 
-  if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
-    /* Add the server to global list as it is coming from router. It 
-       cannot be our own channel as it is coming from router. */
+  /* Distribute the key to everybody who is on the channel. If we are router
+     we will also send it to locally connected servers. */
+  silc_server_send_channel_key(server, sock, channel, FALSE);
+}
 
-    SILC_LOG_DEBUG(("New channel id(%s) from [Router] %s",
-                   silc_id_render(channel_id, SILC_ID_CHANNEL), 
-                   sock->hostname));
-    
-    silc_idlist_add_channel(server->global_list, channel_name, 0, channel_id, 
-                           server->router->connection, NULL);
+/* Received New Client packet and processes it.  Creates Client ID for the
+   client. Client becomes registered after calling this functions. */
 
-    server->stat.channels++;
-  } else {
-    /* The channel is coming from our server, thus it is in our cell
-       we will add it to our local list. */
-    SilcChannelEntry channel;
-    SilcBuffer chk;
+SilcClientEntry silc_server_new_client(SilcServer server,
+                                      SilcSocketConnection sock,
+                                      SilcPacketContext *packet)
+{
+  SilcBuffer buffer = packet->buffer;
+  SilcClientEntry client;
+  SilcIDCacheEntry cache;
+  SilcClientID *client_id;
+  SilcBuffer reply;
+  SilcIDListData idata;
+  char *username = NULL, *realname = NULL, *id_string;
+  int ret;
 
-    SILC_LOG_DEBUG(("New channel id(%s) from [Server] %s",
-                   silc_id_render(channel_id, SILC_ID_CHANNEL), 
-                   sock->hostname));
-    
-    /* Check that we don't already have this channel */
-    channel = silc_idlist_find_channel_by_name(server->local_list, 
-                                              channel_name, NULL);
-    if (!channel)
-      channel = silc_idlist_find_channel_by_name(server->global_list, 
-                                                channel_name, NULL);
-
-    /* If the channel does not exist, then create it. We create the channel
-       with the channel ID provided by the server. This creates a new
-       key to the channel as well that we will send to the server. */
-    if (!channel) {
-      channel = silc_server_create_new_channel_with_id(server, NULL,
-                                                      channel_name,
-                                                      channel_id, FALSE);
-      if (!channel)
-       return;
-
-      /* Send the new channel key to the server */
-      chk = silc_channel_key_payload_encode(channel_id_len, id,
-                                           strlen(channel->channel_key->
-                                                  cipher->name),
-                                           channel->channel_key->cipher->name,
-                                           channel->key_len / 8, 
-                                           channel->key);
-      silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0, 
-                             chk->data, chk->len, FALSE);
-      silc_buffer_free(chk);
-
-    } else {
-      /* The channel exist by that name, check whether the ID's match.
-        If they don't then we'll force the server to use the ID we have.
-        We also create a new key for the channel. */
-
-      if (SILC_ID_CHANNEL_COMPARE(channel_id, channel->id)) {
-       /* They don't match, send Replace ID packet to the server to
-          force the ID change. */
-       SILC_LOG_DEBUG(("Forcing the server to change Channel ID"));
-       silc_server_send_replace_id(server, sock, FALSE, 
-                                   channel_id, SILC_ID_CHANNEL,
-                                   SILC_ID_CHANNEL_LEN,
-                                   channel->id, SILC_ID_CHANNEL,
-                                   SILC_ID_CHANNEL_LEN);
-      }
-
-      /* Create new key for the channel and send it to the server and
-        everybody else possibly on the channel. */
-
-      silc_server_create_channel_key(server, channel, 0);
-
-      /* Send to the channel */
-      silc_server_send_channel_key(server, sock, channel, FALSE);
-
-      /* Send to the server */
-      chk = silc_channel_key_payload_encode(channel_id_len, id,
-                                           strlen(channel->channel_key->
-                                                  cipher->name),
-                                           channel->channel_key->cipher->name,
-                                           channel->key_len / 8, 
-                                           channel->key);
-      silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0, 
-                             chk->data, chk->len, FALSE);
-      silc_buffer_free(chk);
-
-      /* Since the channel is coming from server and we also know about it
-        then send the JOIN notify to the server so that it see's our
-        users on the channel "joining" the channel. */
-      /* XXX TODO **/
-    }
-  }
-
-  silc_free(id);
-}
-
-/* Received New Channel List packet, list of New Channel List payloads inside
-   one packet. Process the New Channel payloads one by one. */
-
-void silc_server_new_channel_list(SilcServer server,
-                                 SilcSocketConnection sock,
-                                 SilcPacketContext *packet)
-{
-  SilcPacketContext *new;
-  SilcBuffer buffer;
-  unsigned short len1, len2;
-
-  SILC_LOG_DEBUG(("Processing New Channel List"));
-
-  if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
-      packet->src_id_type != SILC_ID_SERVER ||
-      server->server_type == SILC_SERVER)
-    return;
-
-  /* If the sender of this packet is server and we are router we need to
-     broadcast this packet to other routers in the network. Broadcast
-     this list packet instead of multiple New Channel packets. */
-  if (!server->standalone && server->server_type == SILC_ROUTER &&
-      sock->type == SILC_SOCKET_TYPE_SERVER &&
-      !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
-    SILC_LOG_DEBUG(("Broadcasting received New Channel List packet"));
-    silc_server_packet_send(server, server->router->connection,
-                           packet->type, 
-                           packet->flags | SILC_PACKET_FLAG_BROADCAST,
-                           packet->buffer->data, packet->buffer->len, FALSE);
-  }
-
-  /* Make copy of the original packet context, except for the actual
-     data buffer, which we will here now fetch from the original buffer. */
-  new = silc_packet_context_alloc();
-  new->type = SILC_PACKET_NEW_CHANNEL;
-  new->flags = packet->flags;
-  new->src_id = packet->src_id;
-  new->src_id_len = packet->src_id_len;
-  new->src_id_type = packet->src_id_type;
-  new->dst_id = packet->dst_id;
-  new->dst_id_len = packet->dst_id_len;
-  new->dst_id_type = packet->dst_id_type;
-
-  buffer = silc_buffer_alloc(512);
-  new->buffer = buffer;
-
-  while (packet->buffer->len) {
-    SILC_GET16_MSB(len1, packet->buffer->data);
-    if ((len1 > packet->buffer->len) ||
-       (len1 > buffer->truelen))
-      break;
-
-    SILC_GET16_MSB(len2, packet->buffer->data + 2 + len1);
-    if ((len2 > packet->buffer->len) ||
-       (len2 > buffer->truelen))
-      break;
+  SILC_LOG_DEBUG(("Creating new client"));
 
-    silc_buffer_pull_tail(buffer, 4 + len1 + len2);
-    silc_buffer_put(buffer, packet->buffer->data, 4 + len1 + len2);
+  if (sock->type != SILC_SOCKET_TYPE_CLIENT)
+    return NULL;
 
-    /* Process the New Channel */
-    silc_server_new_channel(server, sock, new);
+  /* Take client entry */
+  client = (SilcClientEntry)sock->user_data;
+  idata = (SilcIDListData)client;
 
-    silc_buffer_push_tail(buffer, 4 + len1 + len2);
-    silc_buffer_pull(packet->buffer, 4 + len1 + len2);
+  /* Fetch the old client cache entry so that we can update it. */
+  if (!silc_idcache_find_by_context(server->local_list->clients,
+                                   sock->user_data, &cache)) {
+    SILC_LOG_ERROR(("Lost client's cache entry - bad thing"));
+    return NULL;
   }
 
-  silc_buffer_free(buffer);
-  silc_free(new);
-}
-
-/* Received new channel user packet. Information about new users on a
-   channel are distributed between routers using this packet.  The
-   router receiving this will redistribute it and also sent JOIN notify
-   to local clients on the same channel. Normal server sends JOIN notify
-   to its local clients on the channel. */
-
-static void silc_server_new_channel_user_real(SilcServer server,
-                                             SilcSocketConnection sock,
-                                             SilcPacketContext *packet,
-                                             int broadcast)
-{
-  unsigned char *tmpid1, *tmpid2;
-  SilcClientID *client_id = NULL;
-  SilcChannelID *channel_id = NULL;
-  unsigned short channel_id_len;
-  unsigned short client_id_len;
-  SilcClientEntry client;
-  SilcChannelEntry channel;
-  SilcChannelClientEntry chl;
-  SilcBuffer clidp;
-  int ret;
-
-  SILC_LOG_DEBUG(("Start"));
-
-  if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
-      server->server_type != SILC_ROUTER ||
-      packet->src_id_type != SILC_ID_SERVER)
-    return;
-
-  /* Parse payload */
-  ret = silc_buffer_unformat(packet->buffer, 
-                            SILC_STR_UI16_NSTRING_ALLOC(&tmpid1, 
-                                                        &channel_id_len),
-                            SILC_STR_UI16_NSTRING_ALLOC(&tmpid2, 
-                                                        &client_id_len),
+  /* Parse incoming packet */
+  ret = silc_buffer_unformat(buffer,
+                            SILC_STR_UI16_STRING_ALLOC(&username),
+                            SILC_STR_UI16_STRING_ALLOC(&realname),
                             SILC_STR_END);
   if (ret == -1) {
-    if (tmpid1)
-      silc_free(tmpid1);
-    if (tmpid2)
-      silc_free(tmpid2);
-    return;
-  }
-
-  /* Decode the channel ID */
-  channel_id = silc_id_str2id(tmpid1, channel_id_len, SILC_ID_CHANNEL);
-  if (!channel_id)
-    goto out;
-
-  /* Decode the client ID */
-  client_id = silc_id_str2id(tmpid2, client_id_len, SILC_ID_CLIENT);
-  if (!client_id)
-    goto out;
-
-  /* If we are router and this packet is not already broadcast packet
-     we will broadcast it. */
-  if (broadcast && !server->standalone && server->server_type == SILC_ROUTER &&
-      !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
-    SILC_LOG_DEBUG(("Broadcasting received New Channel User packet"));
-    silc_server_packet_send(server, server->router->connection, packet->type,
-                           packet->flags | SILC_PACKET_FLAG_BROADCAST, 
-                           packet->buffer->data, packet->buffer->len, FALSE);
-  }
-
-  /* Find the channel */
-  channel = silc_idlist_find_channel_by_id(server->local_list, 
-                                          channel_id, NULL);
-  if (!channel) {
-    channel = silc_idlist_find_channel_by_id(server->global_list, 
-                                            channel_id, NULL);
-    if (!channel)
-      goto out;
+    if (username)
+      silc_free(username);
+    if (realname)
+      silc_free(realname);
+    return NULL;
   }
 
-  /* Get client entry */
-  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)
-      goto out;
+  if (!username) {
+    silc_free(username);
+    if (realname)
+      silc_free(realname);
+    silc_server_disconnect_remote(server, sock, "Server closed connection: "
+                                  "Incomplete client information");
+    return NULL;
   }
 
-  /* Join the client to the channel by adding it to channel's user list.
-     Add also the channel to client entry's channels list for fast cross-
-     referencing. */
-  chl = silc_calloc(1, sizeof(*chl));
-  chl->client = client;
-  chl->channel = channel;
-  silc_list_add(channel->user_list, chl);
-  silc_list_add(client->channels, chl);
+  /* Create Client ID */
+  silc_id_create_client_id(server->id, server->rng, server->md5hash,
+                          username, &client_id);
 
-  server->stat.chanclients++;
+  /* Update client entry */
+  idata->registered = TRUE;
+  client->nickname = strdup(username);
+  client->username = username;
+  client->userinfo = realname ? realname : strdup("");
+  client->id = client_id;
 
-  /* Send JOIN notify to local clients on the channel. As we are router
-     it is assured that this is sent only to our local clients and locally
-     connected servers if needed. */
-  clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
-  silc_server_send_notify_to_channel(server, sock, channel, FALSE,
-                                    SILC_NOTIFY_TYPE_JOIN, 
-                                    1, clidp->data, clidp->len);
-  silc_buffer_free(clidp);
+  /* Update the cache entry */
+  cache->id = (void *)client_id;
+  cache->type = SILC_ID_CLIENT;
+  cache->data = username;
+  silc_idcache_sort_by_data(server->local_list->clients);
 
-  client_id = NULL;
+  /* Notify our router about new client on the SILC network */
+  if (!server->standalone)
+    silc_server_send_new_id(server, (SilcSocketConnection) 
+                           server->router->connection, 
+                           server->server_type == SILC_ROUTER ? TRUE : FALSE,
+                           client->id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
+  
+  /* Send the new client ID to the client. */
+  id_string = silc_id_id2str(client->id, SILC_ID_CLIENT);
+  reply = silc_buffer_alloc(2 + 2 + SILC_ID_CLIENT_LEN);
+  silc_buffer_pull_tail(reply, SILC_BUFFER_END(reply));
+  silc_buffer_format(reply,
+                    SILC_STR_UI_SHORT(SILC_ID_CLIENT),
+                    SILC_STR_UI_SHORT(SILC_ID_CLIENT_LEN),
+                    SILC_STR_UI_XNSTRING(id_string, SILC_ID_CLIENT_LEN),
+                    SILC_STR_END);
+  silc_server_packet_send(server, sock, SILC_PACKET_NEW_ID, 0, 
+                         reply->data, reply->len, FALSE);
+  silc_free(id_string);
+  silc_buffer_free(reply);
 
- out:
-  if (client_id)
-    silc_free(client_id);
-  if (channel_id)
-    silc_free(channel_id);
-  silc_free(tmpid1);
-  silc_free(tmpid2);
-}
+  /* Send some nice info to the client */
+  SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+                         ("Welcome to the SILC Network %s@%s",
+                          username, sock->hostname));
+  SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+                         ("Your host is %s, running version %s",
+                          server->config->server_info->server_name,
+                          server_version));
+  if (server->server_type == SILC_ROUTER) {
+    SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+                           ("There are %d clients on %d servers in SILC "
+                            "Network", server->stat.clients,
+                            server->stat.servers + 1));
+    SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+                           ("There are %d clients on %d server in our cell",
+                            server->stat.cell_clients,
+                            server->stat.cell_servers + 1));
+    SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+                           ("I have %d clients, %d channels, %d servers and "
+                            "%d routers",
+                            server->stat.my_clients, 
+                            server->stat.my_channels,
+                            server->stat.my_servers,
+                            server->stat.my_routers));
+    SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+                           ("%d server operators and %d router operators "
+                            "online",
+                            server->stat.my_server_ops,
+                            server->stat.my_router_ops));
+  } else {
+    SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+                           ("I have %d clients and %d channels formed",
+                            server->stat.my_clients,
+                            server->stat.my_channels));
+    SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+                           ("%d operators online",
+                            server->stat.my_server_ops));
+  }
+  SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+                         ("Your connection is secured with %s cipher, "
+                          "key length %d bits",
+                          idata->send_key->cipher->name,
+                          idata->send_key->cipher->key_len));
+  SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
+                         ("Your current nickname is %s",
+                          client->nickname));
 
-/* Received new channel user packet. Information about new users on a
-   channel are distributed between routers using this packet.  The
-   router receiving this will redistribute it and also sent JOIN notify
-   to local clients on the same channel. Normal server sends JOIN notify
-   to its local clients on the channel. */
+  /* Send motd */
+  silc_server_send_motd(server, sock);
 
-void silc_server_new_channel_user(SilcServer server,
-                                 SilcSocketConnection sock,
-                                 SilcPacketContext *packet)
-{
-  silc_server_new_channel_user_real(server, sock, packet, TRUE);
+  return client;
 }
 
-/* Received New Channel User List packet, list of New Channel User payloads
-   inside one packet.  Process the payloads one by one. */
+/* Create new server. This processes received New Server packet and
+   saves the received Server ID. The server is our locally connected
+   server thus we save all the information and save it to local list. 
+   This funtion can be used by both normal server and router server.
+   If normal server uses this it means that its router has connected
+   to the server. If router uses this it means that one of the cell's
+   servers is connected to the router. */
 
-void silc_server_new_channel_user_list(SilcServer server,
+SilcServerEntry silc_server_new_server(SilcServer server,
                                       SilcSocketConnection sock,
                                       SilcPacketContext *packet)
-{
-  SilcPacketContext *new;
-  SilcBuffer buffer;
-  unsigned short len1, len2;
-
-  SILC_LOG_DEBUG(("Processing New Channel User List"));
-
-  if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
-      packet->src_id_type != SILC_ID_SERVER ||
-      server->server_type == SILC_SERVER)
-    return;
-
-  /* If we are router and this packet is not already broadcast packet
-     we will broadcast it. Brodcast this list packet instead of multiple
-     New Channel User packets. */
-  if (!server->standalone && server->server_type == SILC_ROUTER &&
-      !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
-    SILC_LOG_DEBUG(("Broadcasting received New Channel User List packet"));
-    silc_server_packet_send(server, server->router->connection, packet->type,
-                           packet->flags | SILC_PACKET_FLAG_BROADCAST, 
-                           packet->buffer->data, packet->buffer->len, FALSE);
-  }
-
-  /* Make copy of the original packet context, except for the actual
-     data buffer, which we will here now fetch from the original buffer. */
-  new = silc_packet_context_alloc();
-  new->type = SILC_PACKET_NEW_CHANNEL_USER;
-  new->flags = packet->flags;
-  new->src_id = packet->src_id;
-  new->src_id_len = packet->src_id_len;
-  new->src_id_type = packet->src_id_type;
-  new->dst_id = packet->dst_id;
-  new->dst_id_len = packet->dst_id_len;
-  new->dst_id_type = packet->dst_id_type;
-
-  buffer = silc_buffer_alloc(256);
-  new->buffer = buffer;
-
-  while (packet->buffer->len) {
-    SILC_GET16_MSB(len1, packet->buffer->data);
-    if ((len1 > packet->buffer->len) ||
-       (len1 > buffer->truelen))
-      break;
-
-    SILC_GET16_MSB(len2, packet->buffer->data + 2 + len1);
-    if ((len2 > packet->buffer->len) ||
-       (len2 > buffer->truelen))
-      break;
-
-    silc_buffer_pull_tail(buffer, 4 + len1 + len2);
-    silc_buffer_put(buffer, packet->buffer->data, 4 + len1 + len2);
-
-    /* Process the New Channel User */
-    silc_server_new_channel_user_real(server, sock, new, FALSE);
-
-    silc_buffer_push_tail(buffer, 4 + len1 + len2);
-    silc_buffer_pull(packet->buffer, 4 + len1 + len2);
-  }
-
-  silc_buffer_free(buffer);
-  silc_free(new);
-}
-
-/* Received Remove Channel User packet to remove a user from a channel. 
-   Routers notify other routers that user has left a channel. Client must
-   not send this packet. Normal server may send this packet but must not
-   receive it. */
-
-void silc_server_remove_channel_user(SilcServer server,
-                                    SilcSocketConnection sock,
-                                    SilcPacketContext *packet)
 {
   SilcBuffer buffer = packet->buffer;
-  unsigned char *tmp1 = NULL, *tmp2 = NULL;
-  unsigned short tmp1_len, tmp2_len;
-  SilcClientID *client_id = NULL;
-  SilcChannelID *channel_id = NULL;
-  SilcChannelEntry channel;
-  SilcClientEntry client;
+  SilcServerEntry new_server;
+  SilcIDCacheEntry cache;
+  SilcServerID *server_id;
+  SilcIDListData idata;
+  unsigned char *server_name, *id_string;
+  unsigned short id_len;
   int ret;
 
-  SILC_LOG_DEBUG(("Removing user from channel"));
-
-  if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
-      packet->src_id_type != SILC_ID_SERVER ||
-      server->server_type == SILC_SERVER)
-    return;
+  SILC_LOG_DEBUG(("Creating new server"));
 
-  ret = silc_buffer_unformat(buffer,
-                            SILC_STR_UI16_NSTRING_ALLOC(&tmp1, &tmp1_len),
-                            SILC_STR_UI16_NSTRING_ALLOC(&tmp2, &tmp2_len),
-                            SILC_STR_END);
-  if (ret == -1)
-    goto out;
+  if (sock->type != SILC_SOCKET_TYPE_SERVER &&
+      sock->type != SILC_SOCKET_TYPE_ROUTER)
+    return NULL;
 
-  client_id = silc_id_str2id(tmp1, tmp1_len, SILC_ID_CLIENT);
-  channel_id = silc_id_str2id(tmp2, tmp2_len, SILC_ID_CHANNEL);
-  if (!client_id || !channel_id)
-    goto out;
+  /* Take server entry */
+  new_server = (SilcServerEntry)sock->user_data;
+  idata = (SilcIDListData)new_server;
 
-  /* 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
-     have the broadcast flag set already and we won't do anything. */
-  if (!server->standalone && server->server_type == SILC_ROUTER &&
-      sock->type == SILC_SOCKET_TYPE_SERVER &&
-      !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
-    SILC_LOG_DEBUG(("Broadcasting received Remove Channel User packet"));
-    silc_server_packet_send(server, server->router->connection, packet->type,
-                           packet->flags | SILC_PACKET_FLAG_BROADCAST, 
-                           buffer->data, buffer->len, FALSE);
+  /* Fetch the old server cache entry so that we can update it. */
+  if (!silc_idcache_find_by_context(server->local_list->servers,
+                                   sock->user_data, &cache)) {
+    SILC_LOG_ERROR(("Lost server's cache entry - bad thing"));
+    return NULL;
   }
 
-  /* Get channel entry */
-  channel = silc_idlist_find_channel_by_id(server->local_list, 
-                                          channel_id, NULL);
-  if (!channel) {
-    channel = silc_idlist_find_channel_by_id(server->global_list, 
-                                            channel_id, NULL);
-    if (!channel)
-      goto out;
+  /* Parse the incoming packet */
+  ret = silc_buffer_unformat(buffer,
+                            SILC_STR_UI16_NSTRING_ALLOC(&id_string, &id_len),
+                            SILC_STR_UI16_STRING_ALLOC(&server_name),
+                            SILC_STR_END);
+  if (ret == -1) {
+    if (id_string)
+      silc_free(id_string);
+    if (server_name)
+      silc_free(server_name);
+    return NULL;
   }
 
-  /* Get client entry */
-  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)
-      goto out;
+  if (id_len > buffer->len) {
+    silc_free(id_string);
+    silc_free(server_name);
+    return NULL;
   }
 
-  /* Remove user from channel */
-  silc_server_remove_from_one_channel(server, sock, channel, client, TRUE);
-
- out:
-  if (tmp1)
-    silc_free(tmp1);
-  if (tmp2)
-    silc_free(tmp2);
-  if (client_id)
-    silc_free(client_id);
-  if (channel_id)
-    silc_free(channel_id);
-}
-
-/* Received notify packet. Server can receive notify packets from router. 
-   Server then relays the notify messages to clients if needed. */
-
-void silc_server_notify(SilcServer server,
-                       SilcSocketConnection sock,
-                       SilcPacketContext *packet)
-{
-  SilcNotifyPayload payload;
-  SilcNotifyType type;
-  SilcArgumentPayload args;
-  SilcChannelID *channel_id;
-  SilcClientID *client_id, *client_id2;
-  SilcChannelEntry channel;
-  SilcClientEntry client;
-  SilcChannelClientEntry chl;
-  unsigned int mode;
-  unsigned char *tmp;
-  unsigned int tmp_len;
-
-  SILC_LOG_DEBUG(("Start"));
-
-  if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
-      packet->src_id_type != SILC_ID_SERVER)
-    return;
-
-  /* XXX: For now we expect that the we are normal server and that the
-     sender is router. Server could send (protocol allows it) notify to
-     router but we don't support it yet. */
-  if (server->server_type != SILC_SERVER &&
-      sock->type != SILC_SOCKET_TYPE_ROUTER)
-    return;
-
-  payload = silc_notify_payload_parse(packet->buffer);
-  if (!payload)
-    return;
-
-  type = silc_notify_get_type(payload);
-  args = silc_notify_get_args(payload);
-  if (!args)
-    goto out;
-
-  switch(type) {
-  case SILC_NOTIFY_TYPE_JOIN:
-    /* 
-     * Distribute the notify to local clients on the channel
-     */
-    SILC_LOG_DEBUG(("JOIN notify"));
-
-    channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
-                               packet->dst_id_type);
-    if (!channel_id)
-      goto out;
-
-    /* Get channel entry */
-    channel = silc_idlist_find_channel_by_id(server->local_list, 
-                                            channel_id, NULL);
-    if (!channel) {
-      silc_free(channel_id);
-      goto out;
-    }
-
-    /* Get client ID */
-    tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
-    if (!tmp) {
-      silc_free(channel_id);
-      goto out;
-    }
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
-    if (!client_id) {
-      silc_free(channel_id);
-      goto out;
-    }
-
-    /* Send to channel */
-    silc_server_packet_send_to_channel(server, NULL, channel, packet->type, 
-                                      FALSE, packet->buffer->data, 
-                                      packet->buffer->len, FALSE);
-
-    /* If the the client is not in local list we check global list (ie. the
-       channel will be global channel) and if it does not exist then create
-       entry for the client. */
-    client = silc_idlist_find_client_by_id(server->local_list, 
-                                          client_id, NULL);
-    if (!client) {
-      SilcChannelClientEntry chl;
+  /* Get Server ID */
+  server_id = silc_id_str2id(id_string, id_len, SILC_ID_SERVER);
+  if (!server_id) {
+    silc_free(id_string);
+    silc_free(server_name);
+    return NULL;
+  }
+  silc_free(id_string);
 
-      client = silc_idlist_find_client_by_id(server->global_list, 
-                                            client_id, NULL);
-      if (!client) {
-       client = silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
-                                       client_id, sock->user_data, NULL);
-       if (!client) {
-         silc_free(channel_id);
-         silc_free(client_id);
-         goto out;
-       }
-      }
+  /* Update client entry */
+  idata->registered = TRUE;
+  new_server->server_name = server_name;
+  new_server->id = server_id;
 
-      /* The channel is global now */
-      channel->global_users = TRUE;
+  /* Update the cache entry */
+  cache->id = (void *)server_id;
+  cache->type = SILC_ID_SERVER;
+  cache->data = server_name;
+  silc_idcache_sort_by_data(server->local_list->servers);
 
-      /* Now actually JOIN the global client to the channel */
-      chl = silc_calloc(1, sizeof(*chl));
-      chl->client = client;
-      chl->channel = channel;
-      silc_list_add(channel->user_list, chl);
-      silc_list_add(client->channels, chl);
-    } else {
-      silc_free(client_id);
-    }
-    break;
+  /* Distribute the information about new server in the SILC network
+     to our router. If we are normal server we won't send anything
+     since this connection must be our router connection. */
+  if (server->server_type == SILC_ROUTER && !server->standalone &&
+      server->router->connection != sock)
+    silc_server_send_new_id(server, server->router->connection,
+                           TRUE, new_server->id, SILC_ID_SERVER, 
+                           SILC_ID_SERVER_LEN);
 
-  case SILC_NOTIFY_TYPE_LEAVE:
-    /* 
-     * Distribute the notify to local clients on the channel
-     */
-    SILC_LOG_DEBUG(("LEAVE notify"));
+  if (server->server_type == SILC_ROUTER)
+    server->stat.cell_servers++;
 
-    channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
-                               packet->dst_id_type);
-    if (!channel_id)
-      goto out;
+  return new_server;
+}
 
-    /* Get channel entry */
-    channel = silc_idlist_find_channel_by_id(server->local_list, 
-                                            channel_id, NULL);
-    if (!channel) { 
-      silc_free(channel_id);
-      goto out;
-    }
+/* Processes incoming New ID packet. New ID Payload is used to distribute
+   information about newly registered clients and servers. */
 
-    /* Get client ID */
-    tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
-    if (!tmp) {
-      silc_free(channel_id);
-      goto out;
-    }
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
-    if (!client_id) {
-      silc_free(channel_id);
-      goto out;
-    }
+static void silc_server_new_id_real(SilcServer server, 
+                                   SilcSocketConnection sock,
+                                   SilcPacketContext *packet,
+                                   int broadcast)
+{
+  SilcBuffer buffer = packet->buffer;
+  SilcIDList id_list;
+  SilcServerEntry router;
+  SilcSocketConnection router_sock;
+  SilcIDPayload idp;
+  SilcIdType id_type;
+  unsigned char *hash = NULL;
+  void *id;
 
-    /* Send to channel */
-    silc_server_packet_send_to_channel(server, NULL, channel, packet->type, 
-                                      FALSE, packet->buffer->data, 
-                                      packet->buffer->len, FALSE);
+  SILC_LOG_DEBUG(("Processing new ID"));
 
-    /* Get client entry */
-    client = silc_idlist_find_client_by_id(server->global_list, 
-                                          client_id, NULL);
-    if (!client) {
-      client = silc_idlist_find_client_by_id(server->local_list, 
-                                            client_id, NULL);
-      if (!client) {
-       silc_free(client_id);
-       silc_free(channel_id);
-       goto out;
-      }
-    }
-    silc_free(client_id);
+  if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
+      server->server_type == SILC_SERVER ||
+      packet->src_id_type != SILC_ID_SERVER)
+    return;
 
-    /* Remove the user from channel */
-    silc_server_remove_from_one_channel(server, sock, channel, client, FALSE);
-    break;
+  idp = silc_id_payload_parse(buffer);
+  if (!idp)
+    return;
 
-  case SILC_NOTIFY_TYPE_SIGNOFF:
-    /* 
-     * Distribute the notify to local clients on the channel
-     */
-    SILC_LOG_DEBUG(("SIGNOFF notify"));
+  id_type = silc_id_payload_get_type(idp);
 
-    /* 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;
+  /* Normal server cannot have other normal server connections */
+  if (id_type == SILC_ID_SERVER && sock->type == SILC_SOCKET_TYPE_SERVER)
+    goto out;
 
-    /* Get client entry */
-    client = silc_idlist_find_client_by_id(server->global_list, 
-                                          client_id, NULL);
-    if (!client) {
-      client = silc_idlist_find_client_by_id(server->local_list, 
-                                            client_id, NULL);
-      if (!client) {
-       silc_free(client_id);
-       goto out;
-      }
-    }
-    silc_free(client_id);
+  id = silc_id_payload_get_id(idp);
+  if (!id)
+    goto out;
 
-    /* Remove the client from all channels */
-    silc_server_remove_from_channels(server, NULL, client);
+  /* If the sender of this packet is server and we are router we need to
+     broadcast this packet to other routers in the network. */
+  if (broadcast && !server->standalone && server->server_type == SILC_ROUTER &&
+      sock->type == SILC_SOCKET_TYPE_SERVER &&
+      !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+    SILC_LOG_DEBUG(("Broadcasting received New ID packet"));
+    silc_server_packet_send(server, server->router->connection,
+                           packet->type, 
+                           packet->flags | SILC_PACKET_FLAG_BROADCAST,
+                           buffer->data, buffer->len, FALSE);
+  }
 
-    /* Remove the client entry */
-    silc_idlist_del_client(server->global_list, client);
-    break;
+  if (sock->type == SILC_SOCKET_TYPE_SERVER)
+    id_list = server->local_list;
+  else
+    id_list = server->global_list;
 
-  case SILC_NOTIFY_TYPE_TOPIC_SET:
-    /* 
-     * Distribute the notify to local clients on the channel
-     */
+  router_sock = sock;
+  router = sock->user_data;
 
-    SILC_LOG_DEBUG(("TOPIC SET notify"));
+  switch(id_type) {
+  case SILC_ID_CLIENT:
+    {
+      SilcClientEntry entry;
 
-    channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
-                               packet->dst_id_type);
-    if (!channel_id)
-      goto out;
+      SILC_LOG_DEBUG(("New client id(%s) from [%s] %s",
+                     silc_id_render(id, SILC_ID_CLIENT),
+                     sock->type == SILC_SOCKET_TYPE_SERVER ?
+                     "Server" : "Router", sock->hostname));
+    
+      /* As a router we keep information of all global information in our
+        global list. Cell wide information however is kept in the local
+        list. The client is put to global list and we will take the hash
+        value of the Client ID and save it to the ID Cache system for fast
+        searching in the future. */
+      hash = silc_calloc(sizeof(((SilcClientID *)id)->hash), 
+                        sizeof(unsigned char));
+      memcpy(hash, ((SilcClientID *)id)->hash, 
+            sizeof(((SilcClientID *)id)->hash));
+      entry = silc_idlist_add_client(id_list, hash, NULL, NULL, id, 
+                                    router, NULL);
+      entry->nickname = NULL;
 
-    /* Get channel entry */
-    channel = silc_idlist_find_channel_by_id(server->local_list, 
-                                            channel_id, NULL);
-    if (!channel) {
-      channel = silc_idlist_find_channel_by_id(server->global_list, 
-                                              channel_id, NULL);
-      if (!channel) {
-       silc_free(channel_id);
-       goto out;
-      }
-    }
+      if (sock->type == SILC_SOCKET_TYPE_SERVER)
+       server->stat.cell_clients++;
+      server->stat.clients++;
 
-    /* Get the topic */
-    tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
-    if (!tmp) {
-      silc_free(channel_id);
-      goto out;
+#if 0
+      /* XXX Adding two ID's with same IP number replaces the old entry thus
+        gives wrong route. Thus, now disabled until figured out a better way
+        to do this or when removed the whole thing. This could be removed
+        because entry->router->connection gives always the most optimal route
+        for the ID anyway (unless new routes (faster perhaps) are established
+        after receiving this ID, this we don't know however). */
+      /* Add route cache for this ID */
+      silc_server_route_add(silc_server_route_hash(
+                           ((SilcClientID *)id)->ip.s_addr,
+                           server->id->port), ((SilcClientID *)id)->ip.s_addr,
+                           router);
+#endif
     }
+    break;
 
-    if (channel->topic)
-      silc_free(channel->topic);
-    channel->topic = silc_calloc(tmp_len, sizeof(*channel->topic));
-    memcpy(channel->topic, tmp, tmp_len);
+  case SILC_ID_SERVER:
+    SILC_LOG_DEBUG(("New server id(%s) from [%s] %s",
+                   silc_id_render(id, SILC_ID_SERVER),
+                   sock->type == SILC_SOCKET_TYPE_SERVER ?
+                   "Server" : "Router", sock->hostname));
+    
+    /* As a router we keep information of all global information in our global
+       list. Cell wide information however is kept in the local list. */
+    silc_idlist_add_server(id_list, NULL, 0, id, router, router_sock);
 
-    /* Send the same notify to the channel */
-    silc_server_packet_send_to_channel(server, NULL, channel, packet->type, 
-                                      FALSE, packet->buffer->data, 
-                                      packet->buffer->len, FALSE);
-    silc_free(channel_id);
+    if (sock->type == SILC_SOCKET_TYPE_SERVER)
+      server->stat.cell_servers++;
+    server->stat.servers++;
+
+#if 0
+    /* Add route cache for this ID */
+    silc_server_route_add(silc_server_route_hash(
+                         ((SilcServerID *)id)->ip.s_addr,
+                         ((SilcServerID *)id)->port), 
+                         ((SilcServerID *)id)->ip.s_addr,
+                         router);
+#endif
+    break;
+
+  case SILC_ID_CHANNEL:
+    SILC_LOG_ERROR(("Channel cannot be registered with NEW_ID packet"));
+    break;
+
+  default:
     break;
+  }
 
-  case SILC_NOTIFY_TYPE_NICK_CHANGE:
-    {
-      /* 
-       * Distribute the notify to local clients on the channel
-       */
-      unsigned char *id, *id2;
+ out:
+  silc_id_payload_free(idp);
+}
 
-      SILC_LOG_DEBUG(("NICK CHANGE notify"));
-      
-      /* Get old client ID */
-      id = silc_argument_get_arg_type(args, 1, &tmp_len);
-      if (!id)
-       goto out;
-      client_id = silc_id_payload_parse_id(id, tmp_len);
-      if (!client_id)
-       goto out;
-      
-      /* Get new client ID */
-      id2 = silc_argument_get_arg_type(args, 2, &tmp_len);
-      if (!id2)
-       goto out;
-      client_id2 = silc_id_payload_parse_id(id2, tmp_len);
-      if (!client_id2)
-       goto out;
-      
-      SILC_LOG_DEBUG(("Old Client ID id(%s)", 
-                     silc_id_render(client_id, SILC_ID_CLIENT)));
-      SILC_LOG_DEBUG(("New Client ID id(%s)", 
-                     silc_id_render(client_id2, SILC_ID_CLIENT)));
 
-      /* Replace the Client ID */
-      client = silc_idlist_replace_client_id(server->global_list, client_id,
-                                            client_id2);
-      if (!client)
-       client = silc_idlist_replace_client_id(server->local_list, client_id, 
-                                              client_id2);
+/* Processes incoming New ID packet. New ID Payload is used to distribute
+   information about newly registered clients and servers. */
 
-      if (client)
-       /* 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_NOTIFY_TYPE_NICK_CHANGE, 2,
-                                           id, tmp_len, 
-                                           id2, tmp_len);
+void silc_server_new_id(SilcServer server, SilcSocketConnection sock,
+                       SilcPacketContext *packet)
+{
+  silc_server_new_id_real(server, sock, packet, TRUE);
+}
 
-      silc_free(client_id);
-      if (!client)
-       silc_free(client_id2);
-      break;
-    }
+/* Receoved New Id List packet, list of New ID payloads inside one
+   packet. Process the New ID payloads one by one. */
 
-  case SILC_NOTIFY_TYPE_CMODE_CHANGE:
-    /* 
-     * Distribute the notify to local clients on the channel
-     */
-    
-    SILC_LOG_DEBUG(("CMODE CHANGE notify"));
-      
-    channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
-                               packet->dst_id_type);
-    if (!channel_id)
-      goto out;
+void silc_server_new_id_list(SilcServer server, SilcSocketConnection sock,
+                            SilcPacketContext *packet)
+{
+  SilcPacketContext *new_id;
+  SilcBuffer idp;
+  unsigned short id_len;
 
-    /* Get channel entry */
-    channel = silc_idlist_find_channel_by_id(server->local_list, 
-                                            channel_id, NULL);
-    if (!channel) {
-      channel = silc_idlist_find_channel_by_id(server->global_list, 
-                                              channel_id, NULL);
-      if (!channel) {
-       silc_free(channel_id);
-       goto out;
-      }
-    }
+  SILC_LOG_DEBUG(("Processing New ID List"));
 
-    /* Send the same notify to the channel */
-    silc_server_packet_send_to_channel(server, NULL, channel, packet->type, 
-                                      FALSE, packet->buffer->data, 
-                                      packet->buffer->len, FALSE);
+  if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
+      packet->src_id_type != SILC_ID_SERVER)
+    return;
 
-    /* Get the mode */
-    tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
-    if (!tmp) {
-      silc_free(channel_id);
-      goto out;
-    }
+  /* If the sender of this packet is server and we are router we need to
+     broadcast this packet to other routers in the network. Broadcast
+     this list packet instead of multiple New ID packets. */
+  if (!server->standalone && server->server_type == SILC_ROUTER &&
+      sock->type == SILC_SOCKET_TYPE_SERVER &&
+      !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+    SILC_LOG_DEBUG(("Broadcasting received New ID List packet"));
+    silc_server_packet_send(server, server->router->connection,
+                           packet->type, 
+                           packet->flags | SILC_PACKET_FLAG_BROADCAST,
+                           packet->buffer->data, packet->buffer->len, FALSE);
+  }
 
-    SILC_GET32_MSB(mode, tmp);
+  /* Make copy of the original packet context, except for the actual
+     data buffer, which we will here now fetch from the original buffer. */
+  new_id = silc_packet_context_alloc();
+  new_id->type = SILC_PACKET_NEW_ID;
+  new_id->flags = packet->flags;
+  new_id->src_id = packet->src_id;
+  new_id->src_id_len = packet->src_id_len;
+  new_id->src_id_type = packet->src_id_type;
+  new_id->dst_id = packet->dst_id;
+  new_id->dst_id_len = packet->dst_id_len;
+  new_id->dst_id_type = packet->dst_id_type;
 
-    /* Change mode */
-    channel->mode = mode;
-    silc_free(channel_id);
-    break;
+  idp = silc_buffer_alloc(256);
+  new_id->buffer = idp;
 
-  case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
-    /* 
-     * Distribute the notify to local clients on the channel
-     */
+  while (packet->buffer->len) {
+    SILC_GET16_MSB(id_len, packet->buffer->data + 2);
+    if ((id_len > packet->buffer->len) ||
+       (id_len > idp->truelen))
+      break;
 
-    SILC_LOG_DEBUG(("CUMODE CHANGE notify"));
+    silc_buffer_pull_tail(idp, 4 + id_len);
+    silc_buffer_put(idp, packet->buffer->data, 4 + id_len);
 
-    channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
-                               packet->dst_id_type);
-    if (!channel_id)
-      goto out;
+    /* Process the New ID */
+    silc_server_new_id_real(server, sock, new_id, FALSE);
 
-    /* Get channel entry */
-    channel = silc_idlist_find_channel_by_id(server->local_list, 
-                                            channel_id, NULL);
-    if (!channel) {
-      channel = silc_idlist_find_channel_by_id(server->global_list, 
-                                              channel_id, NULL);
-      if (!channel) {
-       silc_free(channel_id);
-       goto out;
-      }
-    }
+    silc_buffer_push_tail(idp, 4 + id_len);
+    silc_buffer_pull(packet->buffer, 4 + id_len);
+  }
 
-    /* Get the mode */
-    tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
-    if (!tmp) {
-      silc_free(channel_id);
-      goto out;
-    }
-      
-    SILC_GET32_MSB(mode, tmp);
+  silc_buffer_free(idp);
+  silc_free(new_id);
+}
 
-    /* Get target client */
-    tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
-    if (!tmp)
-      goto out;
-    client_id = silc_id_payload_parse_id(tmp, tmp_len);
-    if (!client_id)
-      goto out;
-    
-    /* Get client entry */
-    client = silc_idlist_find_client_by_id(server->global_list, 
-                                          client_id, NULL);
-    if (!client) {
-      client = silc_idlist_find_client_by_id(server->local_list, 
-                                            client_id, NULL);
-      if (!client) {
-       silc_free(client_id);
-       goto out;
-      }
-    }
-    silc_free(client_id);
+/* Received New Channel packet. Information about new channels in the 
+   network are distributed using this packet. Save the information about
+   the new channel. This usually comes from router but also normal server
+   can send this to notify channels it has when it connects to us. */
 
-    /* Get entry to the channel user list */
-    silc_list_start(channel->user_list);
-    while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
-      if (chl->client == client) {
-       /* Change the mode */
-       chl->mode = mode;
-       break;
-      }
+void silc_server_new_channel(SilcServer server,
+                            SilcSocketConnection sock,
+                            SilcPacketContext *packet)
+{
+  unsigned char *id;
+  SilcChannelID *channel_id;
+  unsigned short channel_id_len;
+  char *channel_name;
+  int ret;
 
-    /* Send the same notify to the channel */
-    silc_server_packet_send_to_channel(server, NULL, channel, packet->type, 
-                                      FALSE, packet->buffer->data, 
-                                      packet->buffer->len, FALSE);
-    silc_free(channel_id);
-    break;
+  SILC_LOG_DEBUG(("Processing New Channel"));
 
-  case SILC_NOTIFY_TYPE_INVITE:
-    SILC_LOG_DEBUG(("INVITE notify (not-impl XXX)"));
-    break;
+  if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
+      packet->src_id_type != SILC_ID_SERVER ||
+      server->server_type == SILC_SERVER)
+    return;
 
-    /* Ignore rest notify types for now */
-  case SILC_NOTIFY_TYPE_NONE:
-  case SILC_NOTIFY_TYPE_MOTD:
-    break;
-  default:
-    break;
+  /* Parse payload */
+  ret = silc_buffer_unformat(packet->buffer, 
+                            SILC_STR_UI16_STRING_ALLOC(&channel_name),
+                            SILC_STR_UI16_NSTRING_ALLOC(&id, &channel_id_len),
+                            SILC_STR_END);
+  if (ret == -1) {
+    if (channel_name)
+      silc_free(channel_name);
+    if (id)
+      silc_free(id);
+    return;
   }
+    
+  /* Decode the channel ID */
+  channel_id = silc_id_str2id(id, channel_id_len, SILC_ID_CHANNEL);
+  if (!channel_id)
+    return;
 
- out:
-  silc_notify_payload_free(payload);
-}
+  if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
+    /* Add the server to global list as it is coming from router. It 
+       cannot be our own channel as it is coming from router. */
 
-/* Processes incoming REMOVE_ID packet. The packet is used to notify routers
-   that certain ID should be removed. After that the ID will become invalid. */
+    SILC_LOG_DEBUG(("New channel id(%s) from [Router] %s",
+                   silc_id_render(channel_id, SILC_ID_CHANNEL), 
+                   sock->hostname));
+    
+    silc_idlist_add_channel(server->global_list, channel_name, 0, channel_id, 
+                           server->router->connection, NULL);
 
-void silc_server_remove_id(SilcServer server,
-                          SilcSocketConnection sock,
-                          SilcPacketContext *packet)
-{
-  SilcIDList id_list;
-  SilcIDPayload idp;
-  SilcIdType id_type;
-  void *id, *id_entry;
+    server->stat.channels++;
+  } else {
+    /* The channel is coming from our server, thus it is in our cell
+       we will add it to our local list. */
+    SilcChannelEntry channel;
+    SilcBuffer chk;
 
-  SILC_LOG_DEBUG(("Start"));
+    SILC_LOG_DEBUG(("New channel id(%s) from [Server] %s",
+                   silc_id_render(channel_id, SILC_ID_CHANNEL), 
+                   sock->hostname));
+    
+    /* Check that we don't already have this channel */
+    channel = silc_idlist_find_channel_by_name(server->local_list, 
+                                              channel_name, NULL);
+    if (!channel)
+      channel = silc_idlist_find_channel_by_name(server->global_list, 
+                                                channel_name, NULL);
 
-  if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
-      server->server_type == SILC_SERVER ||
-      packet->src_id_type != SILC_ID_SERVER)
-    return;
+    /* If the channel does not exist, then create it. We create the channel
+       with the channel ID provided by the server. This creates a new
+       key to the channel as well that we will send to the server. */
+    if (!channel) {
+      channel = silc_server_create_new_channel_with_id(server, NULL,
+                                                      channel_name,
+                                                      channel_id, FALSE);
+      if (!channel)
+       return;
 
-  idp = silc_id_payload_parse(packet->buffer);
-  if (!idp)
-    return;
+      /* Send the new channel key to the server */
+      chk = silc_channel_key_payload_encode(channel_id_len, id,
+                                           strlen(channel->channel_key->
+                                                  cipher->name),
+                                           channel->channel_key->cipher->name,
+                                           channel->key_len / 8, 
+                                           channel->key);
+      silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0, 
+                             chk->data, chk->len, FALSE);
+      silc_buffer_free(chk);
 
-  id_type = silc_id_payload_get_type(idp);
+    } else {
+      /* The channel exist by that name, check whether the ID's match.
+        If they don't then we'll force the server to use the ID we have.
+        We also create a new key for the channel. */
 
-  id = silc_id_payload_get_id(idp);
-  if (!id)
-    goto out;
+      if (SILC_ID_CHANNEL_COMPARE(channel_id, channel->id)) {
+       /* They don't match, send CHANNEL_CHANGE notify to the server to
+          force the ID change. */
+       SILC_LOG_DEBUG(("Forcing the server to change Channel ID"));
+       silc_server_send_notify_channel_change(server, sock, FALSE, 
+                                              channel_id,
+                                              channel->id, 
+                                              SILC_ID_CHANNEL_LEN);
+      }
 
-  /* If the sender of this packet is server and we are router we need to
-     broadcast this packet to other routers in the network. */
-  if (!server->standalone && server->server_type == SILC_ROUTER &&
-      sock->type == SILC_SOCKET_TYPE_SERVER &&
-      !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
-    SILC_LOG_DEBUG(("Broadcasting received Remove ID packet"));
-    silc_server_packet_send(server, server->router->connection,
-                           packet->type, 
-                           packet->flags | SILC_PACKET_FLAG_BROADCAST,
-                           packet->buffer->data, packet->buffer->len, FALSE);
-  }
+      /* Create new key for the channel and send it to the server and
+        everybody else possibly on the channel. */
 
-  if (sock->type == SILC_SOCKET_TYPE_SERVER)
-    id_list = server->local_list;
-  else
-    id_list = server->global_list;
+      silc_server_create_channel_key(server, channel, 0);
 
-  /* Remove the ID */
-  switch (id_type) {
-  case SILC_ID_CLIENT:
-    id_entry = silc_idlist_find_client_by_id(id_list, (SilcClientID *)id, 
-                                            NULL);
-    if (id_entry) {
-      /* Remove from channels */
-      silc_server_remove_from_channels(server, NULL, id_entry);
-
-      /* Remove the client entry */
-      silc_idlist_del_client(id_list, (SilcClientEntry)id_entry);
-      server->stat.clients--;
-      if (sock->type == SILC_SOCKET_TYPE_SERVER &&
-          server->server_type == SILC_ROUTER)
-        server->stat.cell_clients--;
-
-      SILC_LOG_DEBUG(("Removed client id(%s) from [%s] %s",
-                     silc_id_render(id, SILC_ID_CLIENT),
-                     sock->type == SILC_SOCKET_TYPE_SERVER ?
-                     "Server" : "Router", sock->hostname));
-    }
-    break;
+      /* Send to the channel */
+      silc_server_send_channel_key(server, sock, channel, FALSE);
 
-  case SILC_ID_SERVER:
-    id_entry = silc_idlist_find_server_by_id(id_list, (SilcServerID *)id,
-                                            NULL);
-    if (id_entry) {
-      silc_idlist_del_server(id_list, (SilcServerEntry)id_entry);
-      server->stat.servers--;
-      if (sock->type == SILC_SOCKET_TYPE_SERVER &&
-          server->server_type == SILC_ROUTER)
-        server->stat.cell_servers--;
-
-      SILC_LOG_DEBUG(("Removed server id(%s) from [%s] %s",
-                     silc_id_render(id, SILC_ID_SERVER),
-                     sock->type == SILC_SOCKET_TYPE_SERVER ?
-                     "Server" : "Router", sock->hostname));
-    }
-    break;
+      /* Send to the server */
+      chk = silc_channel_key_payload_encode(channel_id_len, id,
+                                           strlen(channel->channel_key->
+                                                  cipher->name),
+                                           channel->channel_key->cipher->name,
+                                           channel->key_len / 8, 
+                                           channel->key);
+      silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0, 
+                             chk->data, chk->len, FALSE);
+      silc_buffer_free(chk);
 
-  case SILC_ID_CHANNEL:
-    id_entry = silc_idlist_find_channel_by_id(id_list, (SilcChannelID *)id,
-                                             NULL);
-    if (id_entry) {
-      silc_idlist_del_channel(id_list, (SilcChannelEntry)id_entry);
-      server->stat.channels--;
-      if (sock->type == SILC_SOCKET_TYPE_SERVER &&
-          server->server_type == SILC_ROUTER)
-        server->stat.cell_channels--;
-
-      SILC_LOG_DEBUG(("Removed channel id(%s) from [%s] %s",
-                     silc_id_render(id, SILC_ID_CHANNEL),
-                     sock->type == SILC_SOCKET_TYPE_SERVER ?
-                     "Server" : "Router", sock->hostname));
+      /* Since the channel is coming from server and we also know about it
+        then send the JOIN notify to the server so that it see's our
+        users on the channel "joining" the channel. */
+      /* XXX TODO **/
     }
-    break;
-
-  default:
-    break;
   }
 
- out:
-  silc_id_payload_free(idp);
+  silc_free(id);
 }
 
-/* Processes received SET_MODE packet. The packet is used to distribute
-   the information about changed channel's or client's channel modes. */
+/* Received New Channel List packet, list of New Channel List payloads inside
+   one packet. Process the New Channel payloads one by one. */
 
-void silc_server_set_mode(SilcServer server,
-                         SilcSocketConnection sock,
-                         SilcPacketContext *packet)
+void silc_server_new_channel_list(SilcServer server,
+                                 SilcSocketConnection sock,
+                                 SilcPacketContext *packet)
 {
-  SilcSetModePayload payload = NULL;
-  SilcArgumentPayload args = NULL;
-  unsigned short mode_type;
-  unsigned int mode_mask;
-  unsigned char *tmp, *tmp2;
-  unsigned int tmp_len, tmp_len2;
-  unsigned char mode[4];
-  SilcClientID *client_id;
-  SilcChannelID *channel_id = NULL;
-  SilcClientEntry client;
-  SilcChannelEntry channel;
-  SilcChannelClientEntry chl;
+  SilcPacketContext *new;
+  SilcBuffer buffer;
+  unsigned short len1, len2;
+
+  SILC_LOG_DEBUG(("Processing New Channel List"));
 
   if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
-      packet->src_id_type == SILC_ID_CLIENT)
+      packet->src_id_type != SILC_ID_SERVER ||
+      server->server_type == SILC_SERVER)
     return;
 
-  SILC_LOG_DEBUG(("Start"));
-
-  /* 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
-     have the broadcast flag set already and we won't do anything. */
+  /* If the sender of this packet is server and we are router we need to
+     broadcast this packet to other routers in the network. Broadcast
+     this list packet instead of multiple New Channel packets. */
   if (!server->standalone && server->server_type == SILC_ROUTER &&
       sock->type == SILC_SOCKET_TYPE_SERVER &&
       !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
-    SILC_LOG_DEBUG(("Broadcasting received Set Mode packet"));
-    silc_server_packet_send(server, server->router->connection, packet->type,
-                           packet->flags | SILC_PACKET_FLAG_BROADCAST, 
+    SILC_LOG_DEBUG(("Broadcasting received New Channel List packet"));
+    silc_server_packet_send(server, server->router->connection,
+                           packet->type, 
+                           packet->flags | SILC_PACKET_FLAG_BROADCAST,
                            packet->buffer->data, packet->buffer->len, FALSE);
   }
 
-  /* Parse Set Mode payload */
-  payload = silc_set_mode_payload_parse(packet->buffer);
-  if (!payload)
-    return;
-
-  mode_type = silc_set_mode_get_type(payload);
-  args = silc_set_mode_get_args(payload);
-  if (!args)
-    goto out;
-
-  mode_mask = silc_set_mode_get_mode(payload);
-  SILC_PUT32_MSB(mode_mask, mode);
-
-  switch (mode_type) {
-  case SILC_MODE_TYPE_CHANNEL:
-    /* Get Channel ID */
-    tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
-    if (!tmp)
-      goto out;
-    channel_id = silc_id_payload_parse_id(tmp, tmp_len);
-    if (!channel_id)
-      goto out;
-
-    /* Get channel entry */
-    channel = silc_idlist_find_channel_by_id(server->local_list, 
-                                            channel_id, NULL);
-    if (!channel) {
-      channel = silc_idlist_find_channel_by_id(server->global_list, 
-                                              channel_id, NULL);
-      if (!channel)
-       goto out;
-    }
-
-    /* Get Client ID payload */
-    tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
-    if (!tmp)
-      goto out;
-
-    /* Send CMODE_CHANGE notify to local channel */
-    silc_server_send_notify_to_channel(server, sock, channel, FALSE,
-                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 
-                                      2, tmp, tmp_len,
-                                      mode, sizeof(mode));
-
-    /* Change the mode */
-    channel->mode = mode_mask;
-    break;
-
-  case SILC_MODE_TYPE_UCHANNEL:
-    /* Get Channel ID */
-    tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
-    if (!tmp)
-      goto out;
-    channel_id = silc_id_payload_parse_id(tmp, tmp_len);
-    if (!channel_id)
-      goto out;
-
-    /* Get channel entry */
-    channel = silc_idlist_find_channel_by_id(server->local_list, 
-                                            channel_id, NULL);
-    if (!channel) {
-      channel = silc_idlist_find_channel_by_id(server->global_list, 
-                                              channel_id, NULL);
-      if (!channel)
-       goto out;
-    }
-
-    /* Get Client ID payload */
-    tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
-    if (!tmp)
-      goto out;
+  /* Make copy of the original packet context, except for the actual
+     data buffer, which we will here now fetch from the original buffer. */
+  new = silc_packet_context_alloc();
+  new->type = SILC_PACKET_NEW_CHANNEL;
+  new->flags = packet->flags;
+  new->src_id = packet->src_id;
+  new->src_id_len = packet->src_id_len;
+  new->src_id_type = packet->src_id_type;
+  new->dst_id = packet->dst_id;
+  new->dst_id_len = packet->dst_id_len;
+  new->dst_id_type = packet->dst_id_type;
 
-    /* Get target Client ID */
-    tmp2 = silc_argument_get_arg_type(args, 3, &tmp_len2);
-    if (!tmp2)
-      goto out;
-    client_id = silc_id_payload_parse_id(tmp2, tmp_len2);
-    if (!client_id)
-      goto out;
+  buffer = silc_buffer_alloc(512);
+  new->buffer = buffer;
 
-    /* Get target client entry */
-    client = silc_idlist_find_client_by_id(server->global_list, 
-                                          client_id, NULL);
-    if (!client) {
-      client = silc_idlist_find_client_by_id(server->local_list, 
-                                            client_id, NULL);
-      if (!client) {
-       silc_free(client_id);
-       goto out;
-      }
-    }
-    silc_free(client_id);
+  while (packet->buffer->len) {
+    SILC_GET16_MSB(len1, packet->buffer->data);
+    if ((len1 > packet->buffer->len) ||
+       (len1 > buffer->truelen))
+      break;
 
-    /* Send CUMODE_CHANGE notify to local channel */
-    silc_server_send_notify_to_channel(server, sock, channel, FALSE,
-                                      SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3, 
-                                      tmp, tmp_len,
-                                      mode, sizeof(mode),
-                                      tmp2, tmp_len2);
+    SILC_GET16_MSB(len2, packet->buffer->data + 2 + len1);
+    if ((len2 > packet->buffer->len) ||
+       (len2 > buffer->truelen))
+      break;
 
-    /* Get entry to the channel user list */
-    silc_list_start(channel->user_list);
-    while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
-      if (chl->client == client) {
-       /* Change the mode */
-       chl->mode = mode_mask;
-       break;
-      }
+    silc_buffer_pull_tail(buffer, 4 + len1 + len2);
+    silc_buffer_put(buffer, packet->buffer->data, 4 + len1 + len2);
 
-    break;
+    /* Process the New Channel */
+    silc_server_new_channel(server, sock, new);
 
-  default:
-    break;
+    silc_buffer_push_tail(buffer, 4 + len1 + len2);
+    silc_buffer_pull(packet->buffer, 4 + len1 + len2);
   }
 
- out:
-  if (channel_id)
-    silc_free(channel_id);
-  if (payload)
-    silc_set_mode_payload_free(payload);
+  silc_buffer_free(buffer);
+  silc_free(new);
 }
index 2d0d3f3c91ffd9b9bea6dbb6e46f5c16cfaa7fec..15d6b22f7813ae0cac0041aaa4bd303a9bbef5fb 100644 (file)
 
 /* Prototypes */
 
+void silc_server_notify(SilcServer server,
+                       SilcSocketConnection sock,
+                       SilcPacketContext *packet);
+void silc_server_notify_list(SilcServer server,
+                            SilcSocketConnection sock,
+                            SilcPacketContext *packet);
 void silc_server_private_message(SilcServer server,
                                 SilcSocketConnection sock,
                                 SilcPacketContext *packet);
@@ -35,42 +41,27 @@ void silc_server_channel_message(SilcServer server,
 void silc_server_channel_key(SilcServer server,
                             SilcSocketConnection sock,
                             SilcPacketContext *packet);
-void silc_server_replace_id(SilcServer server,
-                           SilcSocketConnection sock,
-                           SilcPacketContext *packet);
 SilcClientEntry silc_server_new_client(SilcServer server,
                                       SilcSocketConnection sock,
                                       SilcPacketContext *packet);
 SilcServerEntry silc_server_new_server(SilcServer server,
                                       SilcSocketConnection sock,
                                       SilcPacketContext *packet);
-void silc_server_new_id(SilcServer server, SilcSocketConnection sock,
-                       SilcPacketContext *packet);
-void silc_server_new_id_list(SilcServer server, SilcSocketConnection sock,
-                            SilcPacketContext *packet);
-void silc_server_remove_channel_user(SilcServer server,
-                                    SilcSocketConnection sock,
-                                    SilcPacketContext *packet);
 void silc_server_new_channel(SilcServer server,
                             SilcSocketConnection sock,
                             SilcPacketContext *packet);
 void silc_server_new_channel_list(SilcServer server,
                                  SilcSocketConnection sock,
                                  SilcPacketContext *packet);
-void silc_server_new_channel_user(SilcServer server,
-                                 SilcSocketConnection sock,
-                                 SilcPacketContext *packet);
-void silc_server_new_channel_user_list(SilcServer server,
-                                      SilcSocketConnection sock,
-                                      SilcPacketContext *packet);
-void silc_server_notify(SilcServer server,
-                       SilcSocketConnection sock,
+void silc_server_new_id(SilcServer server, SilcSocketConnection sock,
                        SilcPacketContext *packet);
+void silc_server_new_id_list(SilcServer server, SilcSocketConnection sock,
+                            SilcPacketContext *packet);
 void silc_server_remove_id(SilcServer server,
                           SilcSocketConnection sock,
                           SilcPacketContext *packet);
-void silc_server_set_mode(SilcServer server,
-                         SilcSocketConnection sock,
-                         SilcPacketContext *packet);
+void silc_server_remove_id_list(SilcServer server,
+                               SilcSocketConnection sock,
+                               SilcPacketContext *packet);
 
 #endif
index 05f0454e77eaa0984af80b31a95b3b3458449bec..ac8f117c50e9dd3ca7f42bd852030d17698268d2 100644 (file)
@@ -670,7 +670,7 @@ void silc_server_send_motd(SilcServer server,
     if (!motd)
       return;
 
-    silc_server_send_notify(server, sock, SILC_NOTIFY_TYPE_MOTD, 1,
+    silc_server_send_notify(server, sock, FALSE, SILC_NOTIFY_TYPE_MOTD, 1,
                            motd, motd_len);
     silc_free(motd);
   }
@@ -702,6 +702,7 @@ void silc_server_send_error(SilcServer server,
 
 void silc_server_send_notify(SilcServer server,
                             SilcSocketConnection sock,
+                            int broadcast,
                             SilcNotifyType type,
                             unsigned int argc, ...)
 {
@@ -716,10 +717,215 @@ void silc_server_send_notify(SilcServer server,
   silc_buffer_free(packet);
 }
 
+/* Send CHANNEL_CHANGE notify type. This tells the receiver to replace the
+   `old_id' with the `new_id'. */
+
+void silc_server_send_notify_channel_change(SilcServer server,
+                                           SilcSocketConnection sock,
+                                           int broadcast,
+                                           SilcChannelID *old_id,
+                                           SilcChannelID *new_id,
+                                           unsigned int id_len)
+{
+  SilcBuffer idp1, idp2;
+
+  idp1 = silc_id_payload_encode((void *)old_id, SILC_ID_CHANNEL);
+  idp2 = silc_id_payload_encode((void *)new_id, SILC_ID_CHANNEL);
+
+  silc_server_send_notify(server, sock, broadcast,
+                         SILC_NOTIFY_TYPE_CHANNEL_CHANGE,
+                         2, idp1->data, idp1->len, idp2->data, idp2->len);
+  silc_buffer_free(idp1);
+  silc_buffer_free(idp2);
+}
+
+/* Send NICK_CHANGE notify type. This tells the receiver to replace the
+   `old_id' with the `new_id'. */
+
+void silc_server_send_notify_nick_change(SilcServer server,
+                                        SilcSocketConnection sock,
+                                        int broadcast,
+                                        SilcClientID *old_id,
+                                        SilcClientID *new_id,
+                                        unsigned int id_len)
+{
+  SilcBuffer idp1, idp2;
+
+  idp1 = silc_id_payload_encode((void *)old_id, SILC_ID_CLIENT);
+  idp2 = silc_id_payload_encode((void *)new_id, SILC_ID_CLIENT);
+
+  silc_server_send_notify(server, sock, broadcast, 
+                         SILC_NOTIFY_TYPE_NICK_CHANGE,
+                         2, idp1->data, idp1->len, idp2->data, idp2->len);
+  silc_buffer_free(idp1);
+  silc_buffer_free(idp2);
+}
+
+/* Sends JOIN notify type. This tells that new client by `client_id' ID
+   has joined to the `channel'. */
+
+void silc_server_send_notify_join(SilcServer server,
+                                 SilcSocketConnection sock,
+                                 int broadcast,
+                                 SilcChannelEntry channel,
+                                 SilcClientID *client_id,
+                                 unsigned int client_id_len)
+{
+  SilcBuffer idp1, idp2;
+
+  idp1 = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
+  idp2 = silc_id_payload_encode((void *)channel->id, SILC_ID_CHANNEL);
+  silc_server_send_notify(server, sock, broadcast, SILC_NOTIFY_TYPE_JOIN,
+                         2, idp1->data, idp1->len,
+                         idp2->data, idp2->len);
+  silc_buffer_free(idp1);
+  silc_buffer_free(idp2);
+}
+
+/* Sends LEAVE notify type. This tells that `client_id' has left the
+   `channel'. The Notify packet is always destined to the channel. */
+
+void silc_server_send_notify_leave(SilcServer server,
+                                  SilcSocketConnection sock,
+                                  int broadcast,
+                                  SilcChannelEntry channel,
+                                  SilcClientID *client_id,
+                                  unsigned int client_id_len)
+{
+  SilcBuffer idp;
+
+  idp = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
+  silc_server_send_notify_dest(server, sock, broadcast, (void *)channel->id,
+                              SILC_ID_CHANNEL, SILC_NOTIFY_TYPE_LEAVE,
+                              1, idp->data, idp->len);
+  silc_buffer_free(idp);
+}
+
+/* Sends CMODE_CHANGE notify type. This tells that `client_id' changed the
+   `channel' mode to `mode. The Notify packet is always destined to
+   the channel. */
+
+void silc_server_send_notify_cmode(SilcServer server,
+                                  SilcSocketConnection sock,
+                                  int broadcast,
+                                  SilcChannelEntry channel,
+                                  unsigned int mode_mask,
+                                  SilcClientID *client_id,
+                                  unsigned int client_id_len)
+{
+  SilcBuffer idp;
+  unsigned char mode[4];
+
+  idp = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
+  SILC_PUT32_MSB(mode_mask, mode);
+
+  silc_server_send_notify_dest(server, sock, broadcast, (void *)channel->id,
+                              SILC_ID_CHANNEL, SILC_NOTIFY_TYPE_CMODE_CHANGE,
+                              2, idp->data, idp->len,
+                              mode, 4);
+  silc_buffer_free(idp);
+}
+
+/* Sends CUMODE_CHANGE notify type. This tells that `client_id' changed the
+   `target' client's mode on `channel'. The Notify packet is always
+   destined to the channel. */
+
+void silc_server_send_notify_cumode(SilcServer server,
+                                   SilcSocketConnection sock,
+                                   int broadcast,
+                                   SilcChannelEntry channel,
+                                   unsigned int mode_mask,
+                                   SilcClientID *client_id,
+                                   unsigned int client_id_len,
+                                   SilcClientID *target,
+                                   unsigned int target_len)
+{
+  SilcBuffer idp1, idp2;
+  unsigned char mode[4];
+
+  idp1 = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
+  idp2 = silc_id_payload_encode((void *)target, SILC_ID_CLIENT);
+  SILC_PUT32_MSB(mode_mask, mode);
+
+  silc_server_send_notify_dest(server, sock, broadcast, (void *)channel->id,
+                              SILC_ID_CHANNEL, 
+                              SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3, 
+                              idp1->data, idp1->len,
+                              mode, 4,
+                              idp2->data, idp2->len);
+  silc_buffer_free(idp1);
+  silc_buffer_free(idp2);
+}
+
+/* Sends SIGNOFF notify type. This tells that `client_id' client has
+   left SILC network. This function is used only between server and router
+   traffic. This is not used to send the notify to the channel for
+   client. The `message may be NULL. */
+
+void silc_server_send_notify_signoff(SilcServer server,
+                                    SilcSocketConnection sock,
+                                    int broadcast,
+                                    SilcClientID *client_id,
+                                    unsigned int client_id_len,
+                                    char *message)
+{
+  SilcBuffer idp;
+
+  idp = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
+  silc_server_send_notify(server, sock, broadcast,
+                         SILC_NOTIFY_TYPE_SIGNOFF,
+                         message ? 2 : 1, idp->data, idp->len,
+                         message, message ? strlen(message): 0);
+  silc_buffer_free(idp);
+}
+
+/* Sends SERVER_SIGNOFF notify type. This tells that `server_id' server
+   has quit SILC network. */
+
+void silc_server_send_notify_server_signoff(SilcServer server,
+                                           SilcSocketConnection sock,
+                                           int broadcast,
+                                           SilcServerID *server_id,
+                                           unsigned int server_id_len)
+{
+  SilcBuffer idp;
+
+  idp = silc_id_payload_encode((void *)server_id, SILC_ID_SERVER);
+  silc_server_send_notify(server, sock, broadcast,
+                         SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
+                         1, idp->data, idp->len);
+  silc_buffer_free(idp);
+}
+
+/* Sends TOPIC_SET notify type. This tells that `client_id' changed
+   the `channel's topic to `topic'. The Notify packet is always destined
+   to the channel. This function is used to send the topic set notifies
+   between routers. */
+
+void silc_server_send_notify_topic_set(SilcServer server,
+                                      SilcSocketConnection sock,
+                                      int broadcast,
+                                      SilcChannelEntry channel,
+                                      SilcClientID *client_id,
+                                      unsigned int client_id_len,
+                                      char *topic)
+{
+  SilcBuffer idp;
+
+  idp = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
+  silc_server_send_notify(server, sock, broadcast,
+                         SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
+                         topic ? 2 : 1, 
+                         idp->data, idp->len, 
+                         topic, topic ? strlen(topic) : 0);
+  silc_buffer_free(idp);
+}
+
 /* Sends notify message destined to specific entity. */
 
 void silc_server_send_notify_dest(SilcServer server,
                                  SilcSocketConnection sock,
+                                 int broadcast,
                                  void *dest_id,
                                  SilcIdType dest_id_type,
                                  SilcNotifyType type,
@@ -929,96 +1135,6 @@ void silc_server_send_new_id(SilcServer server,
   silc_buffer_free(idp);
 }
 
-/* Sends Replace ID payload to remote end. This is used to replace old
-   ID with new ID sent in the packet.  This is called for example when
-   user changes nickname and we create new ID for the user.  If the 
-   argument `broadcast' is TRUE then the packet is sent as
-   broadcast packet. */
-/* XXX It would be expected that the new id is same type as the old
-   ID. :) */
-
-void silc_server_send_replace_id(SilcServer server,
-                                SilcSocketConnection sock,
-                                int broadcast,
-                                void *old_id, SilcIdType old_id_type,
-                                unsigned int old_id_len,
-                                void *new_id, SilcIdType new_id_type,
-                                unsigned int new_id_len)
-{
-  SilcBuffer packet;
-  unsigned char *oid;
-  unsigned char *nid;
-
-  SILC_LOG_DEBUG(("Start"));
-
-  oid = silc_id_id2str(old_id, old_id_type);
-  if (!oid)
-    return;
-
-  nid = silc_id_id2str(new_id, new_id_type);
-  if (!nid)
-    return;
-
-  packet = silc_buffer_alloc(2 + 2 + 2 + 2 + old_id_len + new_id_len);
-  silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
-  silc_buffer_format(packet,
-                    SILC_STR_UI_SHORT(old_id_type),
-                    SILC_STR_UI_SHORT(old_id_len),
-                    SILC_STR_UI_XNSTRING(oid, old_id_len),
-                    SILC_STR_UI_SHORT(new_id_type),
-                    SILC_STR_UI_SHORT(new_id_len),
-                    SILC_STR_UI_XNSTRING(nid, new_id_len),
-                    SILC_STR_END);
-
-  silc_server_packet_send(server, sock, SILC_PACKET_REPLACE_ID, 
-                         broadcast ? SILC_PACKET_FLAG_BROADCAST : 0, 
-                         packet->data, packet->len, FALSE);
-  silc_free(oid);
-  silc_free(nid);
-  silc_buffer_free(packet);
-}
-
-/* This function is used to send Remove Channel User payload. This may sent
-   by server but is usually used only by router to notify other routers that
-   user has left a channel. Normal server sends this packet to its router
-   to notify that the router should not hold a record about this client
-   on a channel anymore. Router distributes it further to other routers. */
-
-void silc_server_send_remove_channel_user(SilcServer server,
-                                         SilcSocketConnection sock,
-                                         int broadcast,
-                                         void *client_id, void *channel_id)
-{
-  SilcBuffer packet;
-  unsigned char *clid, *chid;
-
-  SILC_LOG_DEBUG(("Start"));
-
-  clid = silc_id_id2str(client_id, SILC_ID_CLIENT);
-  if (!clid)
-    return;
-
-  chid = silc_id_id2str(channel_id, SILC_ID_CHANNEL);
-  if (!chid)
-    return;
-
-  packet = silc_buffer_alloc(2 + 2 + SILC_ID_CLIENT_LEN + SILC_ID_CHANNEL_LEN);
-  silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
-  silc_buffer_format(packet,
-                    SILC_STR_UI_SHORT(SILC_ID_CLIENT_LEN),
-                    SILC_STR_UI_XNSTRING(clid, SILC_ID_CLIENT_LEN),
-                    SILC_STR_UI_SHORT(SILC_ID_CHANNEL_LEN),
-                    SILC_STR_UI_XNSTRING(chid, SILC_ID_CHANNEL_LEN),
-                    SILC_STR_END);
-
-  silc_server_packet_send(server, sock, SILC_PACKET_REMOVE_CHANNEL_USER, 
-                         broadcast ? SILC_PACKET_FLAG_BROADCAST : 0, 
-                         packet->data, packet->len, FALSE);
-  silc_free(clid);
-  silc_free(chid);
-  silc_buffer_free(packet);
-}
-
 /* Send New Channel Payload to notify about newly created channel in the
    SILC network. Normal server nevers sends this packet. Router uses this
    to notify other routers in the network about new channel. This packet
@@ -1059,48 +1175,6 @@ void silc_server_send_new_channel(SilcServer server,
   silc_buffer_free(packet);
 }
 
-/* Send New Channel User payload to notify routers in the network about new
-   user on the channel. The packet is may be broadcasted. Normal server
-   can send this but must not receive. Router can send and receive it. */
-
-void silc_server_send_new_channel_user(SilcServer server,
-                                      SilcSocketConnection sock,
-                                      int broadcast,
-                                      void *channel_id, 
-                                      unsigned int channel_id_len,
-                                      void *client_id,
-                                      unsigned int client_id_len)
-{
-  SilcBuffer packet;
-  unsigned char *clid, *chid;
-
-  SILC_LOG_DEBUG(("Start"));
-
-  chid = silc_id_id2str(channel_id, SILC_ID_CHANNEL);
-  if (!chid)
-    return;
-
-  clid = silc_id_id2str(client_id, SILC_ID_CLIENT);
-  if (!clid)
-    return;
-
-  packet = silc_buffer_alloc(2 + 2 + channel_id_len + client_id_len);
-  silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
-  silc_buffer_format(packet,
-                    SILC_STR_UI_SHORT(channel_id_len),
-                    SILC_STR_UI_XNSTRING(chid, channel_id_len),
-                    SILC_STR_UI_SHORT(client_id_len),
-                    SILC_STR_UI_XNSTRING(clid, client_id_len),
-                    SILC_STR_END);
-
-  silc_server_packet_send(server, sock, SILC_PACKET_NEW_CHANNEL_USER, 
-                         broadcast ? SILC_PACKET_FLAG_BROADCAST : 0, 
-                         packet->data, packet->len, FALSE);
-  silc_free(clid);
-  silc_free(chid);
-  silc_buffer_free(packet);
-}
-
 /* Send Channel Key payload to distribute the new channel key. Normal server
    sends this to router when new client joins to existing channel. Router
    sends this to the local server who sent the join command in case where
@@ -1157,58 +1231,6 @@ void silc_server_send_command(SilcServer server,
   silc_buffer_free(packet);
 }
 
-/* Function used to send REMOVE_ID packet. The packet is used to notify
-   routers that certain ID should be removed. After that the ID will become
-   invalid.  If the argument `broadcast' is TRUE then the packet is sent as
-   broadcast packet. */
-
-void silc_server_send_remove_id(SilcServer server,
-                               SilcSocketConnection sock,
-                               int broadcast,
-                               void *id, unsigned int id_len,
-                               SilcIdType id_type)
-{
-  SilcBuffer idp;
-
-  SILC_LOG_DEBUG(("Start"));
-
-  idp = silc_id_payload_encode(id, id_type);
-  silc_server_packet_send(server, sock, SILC_PACKET_REMOVE_ID, 
-                         broadcast ? SILC_PACKET_FLAG_BROADCAST : 0, 
-                         idp->data, idp->len, FALSE);
-  silc_buffer_free(idp);
-}
-
-/* Function used to send SET_MODE packet. The packet is used to notify routers
-   that channel's or client's channel mode was changed. If the argument
-   `broadcast' is TRUE then the packet is sent as broadcast packet. */
-
-void silc_server_send_set_mode(SilcServer server,
-                              SilcSocketConnection sock,
-                              int broadcast,
-                              int mode_type, unsigned int mode_mask,
-                              unsigned int argc, ...)
-{
-  SilcBuffer packet;
-  va_list ap;
-
-  SILC_LOG_DEBUG(("Start"));
-
-  va_start(ap, argc);
-
-  /* Encode Set Mode payload */
-  packet = silc_set_mode_payload_encode(mode_type, mode_mask, argc, ap);
-  if (!packet)
-    return;
-
-  /* Send the packet */
-  silc_server_packet_send(server, sock, SILC_PACKET_SET_MODE, 
-                         broadcast ? SILC_PACKET_FLAG_BROADCAST : 0, 
-                         packet->data, packet->len, FALSE);
-
-  silc_buffer_free(packet);
-}
-
 /* Send the heartbeat packet. */
 
 void silc_server_send_heartbeat(SilcServer server,
index cfd7937842f568b23d4c9bca8c7d278f4e522c75..827e609c38acde9701c5e4521213a9ae87439a4e 100644 (file)
@@ -83,10 +83,70 @@ void silc_server_send_error(SilcServer server,
                            const char *fmt, ...);
 void silc_server_send_notify(SilcServer server,
                             SilcSocketConnection sock,
+                            int broadcast,
                             SilcNotifyType type,
                             unsigned int argc, ...);
+void silc_server_send_notify_channel_change(SilcServer server,
+                                           SilcSocketConnection sock,
+                                           int broadcast,
+                                           SilcChannelID *old_id,
+                                           SilcChannelID *new_id,
+                                           unsigned int id_len);
+void silc_server_send_notify_nick_change(SilcServer server,
+                                        SilcSocketConnection sock,
+                                        int broadcast,
+                                        SilcClientID *old_id,
+                                        SilcClientID *new_id,
+                                        unsigned int id_len);
+void silc_server_send_notify_join(SilcServer server,
+                                 SilcSocketConnection sock,
+                                 int broadcast,
+                                 SilcChannelEntry channel,
+                                 SilcClientID *client_id,
+                                 unsigned int client_id_len);
+void silc_server_send_notify_leave(SilcServer server,
+                                  SilcSocketConnection sock,
+                                  int broadcast,
+                                  SilcChannelEntry channel,
+                                  SilcClientID *client_id,
+                                  unsigned int client_id_len);
+void silc_server_send_notify_cmode(SilcServer server,
+                                  SilcSocketConnection sock,
+                                  int broadcast,
+                                  SilcChannelEntry channel,
+                                  unsigned int mode_mask,
+                                  SilcClientID *client_id,
+                                  unsigned int client_id_len);
+void silc_server_send_notify_cumode(SilcServer server,
+                                   SilcSocketConnection sock,
+                                   int broadcast,
+                                   SilcChannelEntry channel,
+                                   unsigned int mode_mask,
+                                   SilcClientID *client_id,
+                                   unsigned int client_id_len,
+                                   SilcClientID *target,
+                                   unsigned int target_len);
+void silc_server_send_notify_signoff(SilcServer server,
+                                    SilcSocketConnection sock,
+                                    int broadcast,
+                                    SilcClientID *client_id,
+                                    unsigned int client_id_len,
+                                    char *message);
+void silc_server_send_notify_server_signoff(SilcServer server,
+                                           SilcSocketConnection sock,
+                                           int broadcast,
+                                           SilcServerID *server_id,
+                                           unsigned int server_id_len);
+void silc_server_send_notify_topic_set(SilcServer server,
+                                      SilcSocketConnection sock,
+                                      int broadcast,
+                                      SilcChannelEntry channel,
+                                      SilcClientID *client_id,
+                                      unsigned int client_id_len,
+                                      char *topic);
 void silc_server_send_notify_dest(SilcServer server,
                                  SilcSocketConnection sock,
+                                 int broadcast,
                                  void *dest_id,
                                  SilcIdType dest_id_type,
                                  SilcNotifyType type,
@@ -106,30 +166,12 @@ void silc_server_send_new_id(SilcServer server,
                             int broadcast,
                             void *id, SilcIdType id_type, 
                             unsigned int id_len);
-void silc_server_send_replace_id(SilcServer server,
-                                SilcSocketConnection sock,
-                                int broadcast,
-                                void *old_id, SilcIdType old_id_type,
-                                unsigned int old_id_len,
-                                void *new_id, SilcIdType new_id_type,
-                                unsigned int new_id_len);
-void silc_server_send_remove_channel_user(SilcServer server,
-                                         SilcSocketConnection sock,
-                                         int broadcast,
-                                         void *client_id, void *channel_id);
 void silc_server_send_new_channel(SilcServer server,
                                  SilcSocketConnection sock,
                                  int broadcast,
                                  char *channel_name,
                                  void *channel_id, 
                                  unsigned int channel_id_len);
-void silc_server_send_new_channel_user(SilcServer server,
-                                      SilcSocketConnection sock,
-                                      int broadcast,
-                                      void *channel_id, 
-                                      unsigned int channel_id_len,
-                                      void *client_id,
-                                      unsigned int client_id_len);
 void silc_server_send_channel_key(SilcServer server,
                                  SilcSocketConnection sender,
                                  SilcChannelEntry channel,
@@ -138,16 +180,6 @@ void silc_server_send_command(SilcServer server,
                              SilcSocketConnection sock,
                              SilcCommand command, 
                              unsigned int argc, ...);
-void silc_server_send_remove_id(SilcServer server,
-                               SilcSocketConnection sock,
-                               int broadcast,
-                               void *id, unsigned int id_len,
-                               SilcIdType id_type);
-void silc_server_send_set_mode(SilcServer server,
-                              SilcSocketConnection sock,
-                              int broadcast,
-                              int mode_type, unsigned int mode_mask,
-                              unsigned int argc, ...);
 void silc_server_send_heartbeat(SilcServer server,
                                SilcSocketConnection sock);
 
index e8e51569cedaf5ff02d45dcd137e47e8461a7dd4..e12dfb04a54418d698abf1764f4ee93e74a0f75c 100644 (file)
@@ -1427,6 +1427,8 @@ void silc_server_packet_parse_type(SilcServer server,
   switch(type) {
   case SILC_PACKET_DISCONNECT:
     SILC_LOG_DEBUG(("Disconnect packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
     break;
 
   case SILC_PACKET_SUCCESS:
@@ -1436,6 +1438,8 @@ void silc_server_packet_parse_type(SilcServer server,
      * success message is for whatever protocol is executing currently.
      */
     SILC_LOG_DEBUG(("Success packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
     if (sock->protocol) {
       sock->protocol->execute(server->timeout_queue, 0,
                              sock->protocol, sock->sock, 0, 0);
@@ -1449,6 +1453,8 @@ void silc_server_packet_parse_type(SilcServer server,
      * failure message is for whatever protocol is executing currently.
      */
     SILC_LOG_DEBUG(("Failure packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
     if (sock->protocol) {
       /* XXX Audit the failure type */
       sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
@@ -1459,6 +1465,8 @@ void silc_server_packet_parse_type(SilcServer server,
 
   case SILC_PACKET_REJECT:
     SILC_LOG_DEBUG(("Reject packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
     return;
     break;
 
@@ -1468,7 +1476,10 @@ void silc_server_packet_parse_type(SilcServer server,
      * router. Server then relays the notify messages to clients if needed.
      */
     SILC_LOG_DEBUG(("Notify packet"));
-    silc_server_notify(server, sock, packet);
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      silc_server_notify_list(server, sock, packet);
+    else
+      silc_server_notify(server, sock, packet);
     break;
 
     /* 
@@ -1481,6 +1492,8 @@ void silc_server_packet_parse_type(SilcServer server,
      * specially.
      */
     SILC_LOG_DEBUG(("Channel Message packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
     silc_server_channel_message(server, sock, packet);
     break;
 
@@ -1492,6 +1505,8 @@ void silc_server_packet_parse_type(SilcServer server,
      * never receives this channel and thus is ignored.
      */
     SILC_LOG_DEBUG(("Channel Key packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
     silc_server_channel_key(server, sock, packet);
     break;
 
@@ -1504,6 +1519,8 @@ void silc_server_packet_parse_type(SilcServer server,
      * command context and calls the command.
      */
     SILC_LOG_DEBUG(("Command packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
     silc_server_command_process(server, sock, packet);
     break;
 
@@ -1514,6 +1531,8 @@ void silc_server_packet_parse_type(SilcServer server,
      * that we've routed further.
      */
     SILC_LOG_DEBUG(("Command Reply packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
     silc_server_command_reply(server, sock, packet);
     break;
 
@@ -1526,6 +1545,8 @@ void silc_server_packet_parse_type(SilcServer server,
      * client or server.
      */
     SILC_LOG_DEBUG(("Private Message packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
     silc_server_private_message(server, sock, packet);
     break;
 
@@ -1533,6 +1554,8 @@ void silc_server_packet_parse_type(SilcServer server,
     /*
      * Private message key packet.
      */
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
     break;
 
     /*
@@ -1540,6 +1563,9 @@ void silc_server_packet_parse_type(SilcServer server,
      */
   case SILC_PACKET_KEY_EXCHANGE:
     SILC_LOG_DEBUG(("KE packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
+
     if (sock->protocol && sock->protocol->protocol->type 
        == SILC_PROTOCOL_SERVER_KEY_EXCHANGE) {
 
@@ -1561,6 +1587,9 @@ void silc_server_packet_parse_type(SilcServer server,
 
   case SILC_PACKET_KEY_EXCHANGE_1:
     SILC_LOG_DEBUG(("KE 1 packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
+
     if (sock->protocol && sock->protocol->protocol->type 
        == SILC_PROTOCOL_SERVER_KEY_EXCHANGE) {
 
@@ -1589,6 +1618,9 @@ void silc_server_packet_parse_type(SilcServer server,
 
   case SILC_PACKET_KEY_EXCHANGE_2:
     SILC_LOG_DEBUG(("KE 2 packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
+
     if (sock->protocol && sock->protocol->protocol->type 
        == SILC_PROTOCOL_SERVER_KEY_EXCHANGE) {
 
@@ -1623,6 +1655,8 @@ void silc_server_packet_parse_type(SilcServer server,
      * at any time. 
      */
     SILC_LOG_DEBUG(("Connection authentication request packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
     break;
 
     /*
@@ -1632,6 +1666,9 @@ void silc_server_packet_parse_type(SilcServer server,
     /* Start of the authentication protocol. We receive here the 
        authentication data and will verify it. */
     SILC_LOG_DEBUG(("Connection auth packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
+
     if (sock->protocol && sock->protocol->protocol->type 
        == SILC_PROTOCOL_SERVER_CONNECTION_AUTH) {
 
@@ -1657,16 +1694,10 @@ void silc_server_packet_parse_type(SilcServer server,
      * SILC network.
      */
     SILC_LOG_DEBUG(("New ID packet"));
-    silc_server_new_id(server, sock, packet);
-    break;
-
-  case SILC_PACKET_NEW_ID_LIST:
-    /*
-     * Received list of ID's. This packet is used by servers and routers
-     * to notify their primary router about clients and servers they have.
-     */
-    SILC_LOG_DEBUG(("New ID List packet"));
-    silc_server_new_id_list(server, sock, packet);
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      silc_server_new_id_list(server, sock, packet);
+    else
+      silc_server_new_id(server, sock, packet);
     break;
 
   case SILC_PACKET_NEW_CLIENT:
@@ -1676,6 +1707,8 @@ void silc_server_packet_parse_type(SilcServer server,
      * ID we will send it to the client.
      */
     SILC_LOG_DEBUG(("New Client packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
     silc_server_new_client(server, sock, packet);
     break;
 
@@ -1686,6 +1719,8 @@ void silc_server_packet_parse_type(SilcServer server,
      * connected to us.
      */
     SILC_LOG_DEBUG(("New Server packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
     silc_server_new_server(server, sock, packet);
     break;
 
@@ -1695,74 +1730,10 @@ void silc_server_packet_parse_type(SilcServer server,
      * network are distributed using this packet.
      */
     SILC_LOG_DEBUG(("New Channel packet"));
-    silc_server_new_channel(server, sock, packet);
-    break;
-
-  case SILC_PACKET_NEW_CHANNEL_USER:
-    /*
-     * Received new channel user packet. Information about new users on a
-     * channel are distributed between routers using this packet.  The
-     * router receiving this will redistribute it and also sent JOIN notify
-     * to local clients on the same channel. Normal server sends JOIN notify
-     * to its local clients on the channel.
-     */
-    SILC_LOG_DEBUG(("New Channel User packet"));
-    silc_server_new_channel_user(server, sock, packet);
-    break;
-
-  case SILC_PACKET_NEW_CHANNEL_LIST:
-    /*
-     * List of new channel packets received. This is usually received when
-     * existing server or router connects to us and distributes information
-     * of all channels it has.
-     */
-    SILC_LOG_DEBUG(("New Channel List packet"));
-    silc_server_new_channel_list(server, sock, packet);
-    break;
-
-  case SILC_PACKET_NEW_CHANNEL_USER_LIST:
-    /*
-     * List of new channel user packets received. This is usually received
-     * when existing server or router connects to us and distributes 
-     * information of all channel users it has.
-     */
-    SILC_LOG_DEBUG(("New Channel User List packet"));
-    silc_server_new_channel_user_list(server, sock, packet);
-    break;
-
-  case SILC_PACKET_REPLACE_ID:
-    /*
-     * Received replace ID packet. This sends the old ID that is to be
-     * replaced with the new one included into the packet. Client must not
-     * send this packet.
-     */
-    SILC_LOG_DEBUG(("Replace ID packet"));
-    silc_server_replace_id(server, sock, packet);
-    break;
-
-  case SILC_PACKET_REMOVE_ID:
-    /*
-     * Received remove ID Packet. 
-     */
-    SILC_LOG_DEBUG(("Remove ID packet"));
-    silc_server_remove_id(server, sock, packet);
-    break;
-
-  case SILC_PACKET_REMOVE_CHANNEL_USER:
-    /*
-     * Received packet to remove user from a channel. Routers notify other
-     * routers about a user leaving a channel.
-     */
-    SILC_LOG_DEBUG(("Remove Channel User packet"));
-    silc_server_remove_channel_user(server, sock, packet);
-    break;
-
-  case SILC_PACKET_SET_MODE:
-    /*
-     * Received packet to set the mode of channel or client's channel mode.
-     */
-    SILC_LOG_DEBUG(("Set Mode packet"));
-    silc_server_set_mode(server, sock, packet);
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      silc_server_new_channel_list(server, sock, packet);
+    else
+      silc_server_new_channel(server, sock, packet);
     break;
 
   case SILC_PACKET_HEARTBEAT:
@@ -1770,6 +1741,8 @@ void silc_server_packet_parse_type(SilcServer server,
      * Received heartbeat.
      */
     SILC_LOG_DEBUG(("Heartbeat packet"));
+    if (packet->flags & SILC_PACKET_FLAG_LIST)
+      break;
     break;
 
   default:
@@ -1850,18 +1823,18 @@ void silc_server_free_sock_user_data(SilcServer server,
     {
       SilcClientEntry user_data = (SilcClientEntry)sock->user_data;
 
+      /* Send REMOVE_ID packet to routers. */
+      if (!server->standalone && server->router)
+       silc_server_send_notify_signoff(server, server->router->connection,
+                                       server->server_type == SILC_SERVER ?
+                                       FALSE : TRUE, user_data->id, 
+                                       SILC_ID_CLIENT_LEN, NULL);
+
       /* Remove client from all channels */
       silc_server_remove_from_channels(server, sock, user_data);
 
       /* XXX must take some info to history before freeing */
 
-      /* Send REMOVE_ID packet to routers. */
-      if (!server->standalone && server->router)
-       silc_server_send_remove_id(server, server->router->connection,
-                                  server->server_type == SILC_SERVER ?
-                                  FALSE : TRUE, user_data->id, 
-                                  SILC_ID_CLIENT_LEN, SILC_ID_CLIENT);
-
       /* Free the client entry and everything in it */
       silc_idlist_del_data(user_data);
       silc_idlist_del_client(server->local_list, user_data);
@@ -1878,10 +1851,12 @@ void silc_server_free_sock_user_data(SilcServer server,
 
       /* Send REMOVE_ID packet to routers. */
       if (!server->standalone && server->router)
-       silc_server_send_remove_id(server, server->router->connection,
-                                  server->server_type == SILC_SERVER ?
-                                  FALSE : TRUE, user_data->id, 
-                                  SILC_ID_SERVER_LEN, SILC_ID_SERVER);
+       silc_server_send_notify_server_signoff(server, 
+                                              server->router->connection,
+                                              server->server_type == 
+                                              SILC_SERVER ?
+                                              FALSE : TRUE, user_data->id, 
+                                              SILC_ID_SERVER_LEN);
 
       /* Then also free all client entries that this server owns as
         they will become invalid now as well. */
@@ -2055,6 +2030,12 @@ void silc_server_remove_from_channels(SilcServer server,
     silc_free(chl);
     server->stat.my_chanclients--;
 
+    /* If there is no global users on the channel anymore mark the channel
+       as local channel. */
+    if (server->server_type == SILC_SERVER &&
+       !silc_server_channel_has_global(channel))
+      channel->global_users = FALSE;
+
     /* If there is not at least one local user on the channel then we don't
        need the channel entry anymore, we can remove it safely. */
     if (server->server_type == SILC_SERVER &&
@@ -2502,7 +2483,7 @@ void silc_server_announce_servers(SilcServer server)
 
     /* Send the packet */
     silc_server_packet_send(server, server->router->connection,
-                           SILC_PACKET_NEW_ID_LIST, 0,
+                           SILC_PACKET_NEW_ID, SILC_PACKET_FLAG_LIST,
                            servers->data, servers->len, TRUE);
 
     silc_buffer_free(servers);
@@ -2572,13 +2553,22 @@ void silc_server_announce_clients(SilcServer server)
 
     /* Send the packet */
     silc_server_packet_send(server, server->router->connection,
-                           SILC_PACKET_NEW_ID_LIST, 0,
+                           SILC_PACKET_NEW_ID, SILC_PACKET_FLAG_LIST,
                            clients->data, clients->len, TRUE);
 
     silc_buffer_free(clients);
   }
 }
 
+static SilcBuffer 
+silc_server_announce_encode_join(unsigned int argc, ...)
+{
+  va_list ap;
+
+  va_start(ap, argc);
+  return silc_notify_payload_encode(SILC_NOTIFY_TYPE_JOIN, argc, ap);
+}
+
 /* Returns assembled packets for all channels and users on those channels
    from the given ID List. The packets are in the form dictated by the
    New Channel and New Channel User payloads. */
@@ -2592,6 +2582,7 @@ static void silc_server_announce_get_channels(SilcServer server,
   SilcIDCacheEntry id_cache;
   SilcChannelEntry channel;
   SilcChannelClientEntry chl;
+  SilcBuffer chidp;
   unsigned char *cid;
   unsigned short name_len;
   int len;
@@ -2622,13 +2613,17 @@ static void silc_server_announce_get_channels(SilcServer server,
        silc_buffer_pull(*channels, len);
 
        /* Now find all users on the channel */
+       chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
        silc_list_start(channel->user_list);
        while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
-         unsigned char *clid;
+         SilcBuffer clidp;
+         SilcBuffer tmp;
 
-         clid = silc_id_id2str(chl->client->id, SILC_ID_CLIENT);
-         
-         len = 4 + SILC_ID_CHANNEL_LEN + SILC_ID_CLIENT_LEN;
+         clidp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
+
+         tmp = silc_server_announce_encode_join(2, clidp->data, clidp->len,
+                                                chidp->data, chidp->len);
+         len = tmp->len;
          *channel_users = 
            silc_buffer_realloc(*channel_users, 
                                (*channel_users ? 
@@ -2636,15 +2631,13 @@ static void silc_server_announce_get_channels(SilcServer server,
          silc_buffer_pull_tail(*channel_users, 
                                ((*channel_users)->end - 
                                 (*channel_users)->data));
-         silc_buffer_format(*channel_users,
-                            SILC_STR_UI_SHORT(SILC_ID_CHANNEL_LEN),
-                            SILC_STR_UI_XNSTRING(cid, SILC_ID_CHANNEL_LEN),
-                            SILC_STR_UI_SHORT(SILC_ID_CLIENT_LEN),
-                            SILC_STR_UI_XNSTRING(clid, SILC_ID_CLIENT_LEN),
-                            SILC_STR_END);
+
+         silc_buffer_put(*channel_users, tmp->data, tmp->len);
          silc_buffer_pull(*channel_users, len);
-         silc_free(clid);
+         silc_buffer_free(clidp);
+         silc_buffer_free(tmp);
        }
+       silc_buffer_free(chidp);
 
        silc_free(cid);
 
@@ -2681,7 +2674,7 @@ void silc_server_announce_channels(SilcServer server)
 
     /* Send the packet */
     silc_server_packet_send(server, server->router->connection,
-                           SILC_PACKET_NEW_CHANNEL_LIST, 0,
+                           SILC_PACKET_NEW_CHANNEL, SILC_PACKET_FLAG_LIST,
                            channels->data, channels->len,
                            FALSE);
 
@@ -2695,7 +2688,7 @@ void silc_server_announce_channels(SilcServer server)
 
     /* Send the packet */
     silc_server_packet_send(server, server->router->connection,
-                           SILC_PACKET_NEW_CHANNEL_USER_LIST, 0,
+                           SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
                            channel_users->data, channel_users->len,
                            FALSE);
 
index 13b0dff267259065a0d7308b303a573927d9c707..9b3f64ac514a923c97e02842a7df4e9d5a3d2064 100644 (file)
@@ -68,11 +68,12 @@ typedef struct {
 /* This macro is used to send notify messages with formatted string. The
    string is formatted with arguments and the formatted string is sent as
    argument. */
-#define SILC_SERVER_SEND_NOTIFY(server, sock, type, fmt)                   \
-do {                                                                       \
-  char *__fmt__ = silc_format fmt;                                         \
-  silc_server_send_notify(server, sock, type, 1, __fmt__, strlen(__fmt__)); \
-  silc_free(__fmt__);                                                      \
+#define SILC_SERVER_SEND_NOTIFY(server, sock, type, fmt)       \
+do {                                                           \
+  char *__fmt__ = silc_format fmt;                             \
+  silc_server_send_notify(server, sock, FALSE,                         \
+                         type, 1, __fmt__, strlen(__fmt__));   \
+  silc_free(__fmt__);                                          \
 } while(0);
 
 /* Prototypes */
index a8867c4545f9841cd52a025dd16e5b2027c8e3be..8e0686a801b977b36ed1e4c8505c0dfc1ebb7a4d 100644 (file)
@@ -94,18 +94,9 @@ Table of Contents
       2.3.14 Command Reply Payload .............................. 29
       2.3.15 Connection Auth Request Payload .................... 29
       2.3.16 New ID Payload ..................................... 30
-      2.3.17 New ID List Payload ................................ 31
-      2.3.18 New Client Payload ................................. 31
-      2.3.19 New Server Payload ................................. 32
-      2.3.20 New Channel Payload ................................ 33
-      2.3.21 New Channel User Payload ........................... 34
-      2.3.22 New Channel List Payload ........................... 35
-      2.3.23 New Channel User List Payload ...................... 36
-      2.3.24 Replace ID Payload ................................. 36
-      2.3.25 Remove ID Payload .................................. 37
-      2.3.26 Remove Channel User Payload ........................ 38
-      2.3.27 Set Mode Payload ................................... XXX
-      2.3.28 Set Mode List Payload .............................. XXX
+      2.3.17 New Client Payload ................................. 31
+      2.3.18 New Server Payload ................................. 32
+      2.3.19 New Channel Payload ................................ 33
   2.4 SILC ID Types ............................................. 39
   2.5 Packet Encryption And Decryption .......................... 39
       2.5.1 Normal Packet Encryption And Decryption ............. 39
@@ -117,9 +108,8 @@ Table of Contents
   2.9 Packet Sending ............................................ 43
   2.10 Packet Reception ......................................... 43
   2.11 Packet Routing ........................................... 44
-  2.12 Packet Forwarding ........................................ 44
-  2.13 Packet Broadcasting ...................................... 45
-  2.14 Packet Tunneling ......................................... 45
+  2.12 Packet Broadcasting ...................................... 45
+  2.13 Packet Tunneling ......................................... 45
 3 Security Considerations ....................................... 46
 4 References .................................................... 46
 5 Author's Address .............................................. 47
@@ -147,10 +137,6 @@ Figure 16:  Connection Auth Request Payload
 Figure 17:  New Client Payload
 Figure 18:  New Server Payload
 Figure 19:  New Channel Payload
-Figure 20:  New Channel User Payload
-Figure 21:  Replace ID Payload
-Figure 22:  Remove Channel User Payload
-Figure 23:  Set Mode Payload
 
 
 .ti 0
@@ -302,13 +288,15 @@ o Flags (1 byte) - Indicates flags to be used in packet
        Encryption And Decryption for more information.
 
 
-     Forwarded                 0x02
+     List                      0x02
   
-       Marks the packet to be forwarded.  Some specific
-       packet types may be forwarded.  Receiver of packet
-       with this flag set must not forward the packet any
-       further.  See section 2.12 Packet Forwarding for
-       description of packet forwarding.
+       Indicates that the packet consists of list of
+       packet payloads indicated by the Packet Type field.
+       The payloads are added one after the other.  Note that
+       there are packet types that must not be used as
+       list.  Parsing of list packet is done by calculating
+       the length of each payload and parsing them one by
+       one.
 
 
      Broadcast                 0x04
@@ -405,6 +393,9 @@ List of SILC Packet types are defined as follows.
           the disconnection is sent inside the packet payload.  Client
           usually does not send this packet.
 
+          This packet must not be sent as list and the List flag must
+         not be set.
+
           Payload of the packet:  See section 2.3.3 Disconnect Payload
 
 
@@ -413,6 +404,9 @@ List of SILC Packet types are defined as follows.
           This packet is sent upon successful execution of some protocol.
           The status of the success is sent in the packet.
 
+          This packet must not be sent as list and the List flag must
+         not be set.
+
           Payload of the packet:  See section 2.3.4 Success Payload
 
 
@@ -421,6 +415,9 @@ List of SILC Packet types are defined as follows.
           This packet is sent upon failure of some protocol.  The status
           of the failure is sent in the packet.
 
+          This packet must not be sent as list and the List flag must
+         not be set.
+
           Payload of the packet:  See section 2.3.5 Failure Payload
 
 
@@ -429,6 +426,9 @@ List of SILC Packet types are defined as follows.
           This packet may be sent upon rejection of some protocol.
           The status of the rejection is sent in the packet.
 
+          This packet must not be sent as list and the List flag must
+         not be set.
+
           Payload of the packet:  See section 2.3.6 Reject Payload
 
 
@@ -451,6 +451,9 @@ List of SILC Packet types are defined as follows.
           most likely to take action anyway.  This packet may be sent
           to entity that is indirectly connected to the sender.
 
+          This packet must not be sent as list and the List flag must
+         not be set.
+
           Payload of the packet:  See section 2.3.8 Error Payload.
 
 
@@ -462,6 +465,9 @@ List of SILC Packet types are defined as follows.
           by channel specific keys.  Channel Keys are distributed by
           SILC_PACKET_CHANNEL_KEY packet.
 
+          This packet must not be sent as list and the List flag must
+         not be set.
+
           Payload of the packet:  See section 2.3.9 Channel Message 
                                   Payload
 
@@ -474,6 +480,9 @@ List of SILC Packet types are defined as follows.
           may send this packet.  This packet may be sent to entity
           that is indirectly connected to the sender.
 
+          This packet must not be sent as list and the List flag must
+         not be set.
+
           Payload of the packet:  See section 2.3.10 Channel Key Payload
 
 
@@ -488,6 +497,9 @@ List of SILC Packet types are defined as follows.
           used as well if both of the client knows it, however, it needs 
           to be agreed outside SILC.  See more of this in [SILC1].
 
+          This packet must not be sent as list and the List flag must
+         not be set.
+
           Payload of the packet:  See section 2.3.11 Private Message
                                   Payload
 
@@ -506,6 +518,9 @@ List of SILC Packet types are defined as follows.
           default or to use normal session keys by default, is 
           implementation specific issue.  See more of this in [SILC1].
 
+          This packet must not be sent as list and the List flag must
+         not be set.
+
           Payload of the packet:  See section 2.3.12 Private Message
                                   Key Payload
 
@@ -519,6 +534,9 @@ List of SILC Packet types are defined as follows.
           This packet may be sent to entity that is indirectly connected
           to the sender.
 
+          This packet must not be sent as list and the List flag must
+         not be set.
+
           Payload of the packet:  See section 2.3.13 Command Payload
 
 
@@ -528,6 +546,9 @@ List of SILC Packet types are defined as follows.
           The contents of this packet is command specific.  This packet
           maybe sent to entity that is indirectly connected to the sender.
 
+          This packet must not be sent as list and the List flag must
+         not be set.
+
           Payload of the packet:  See section 2.3.14 Command Reply 
                                   Payload and section 2.3.13 Command
                                   Payload
@@ -538,6 +559,9 @@ List of SILC Packet types are defined as follows.
           This packet is used to start SILC Key Exchange Protocol, 
           described in detail in [SILC3].
 
+          This packet must not be sent as list and the List flag must
+         not be set.
+
           Payload of the packet:  Payload of this packet is described
                                   in the section SILC Key Exchange
                                   Protocol and its sub sections in
@@ -548,6 +572,9 @@ List of SILC Packet types are defined as follows.
 
           This packet is used as part of the SILC Key Exchange Protocol.
 
+          This packet must not be sent as list and the List flag must
+         not be set.
+
           Payload of the packet:  Payload of this packet is described
                                   in the section SILC Key Exchange
                                   Protocol and its sub sections in
@@ -558,6 +585,9 @@ List of SILC Packet types are defined as follows.
 
           This packet is used as part of the SILC Key Exchange Protocol.
 
+          This packet must not be sent as list and the List flag must
+         not be set.
+
           Payload of the packet:  Payload of this packet is described
                                   in the section SILC Key Exchange
                                   Protocol and its sub sections in
@@ -574,6 +604,9 @@ List of SILC Packet types are defined as follows.
           The party receiving this payload must respond with the same
           packet including the mandatory authentication method.
 
+          This packet must not be sent as list and the List flag must
+         not be set.
+
           Payload of the packet:  See section 2.3.15 Connection Auth
                                   Request Payload
 
@@ -585,6 +618,9 @@ List of SILC Packet types are defined as follows.
           the connecting party.  The protocol is described in detail in
           [SILC3].
 
+          This packet must not be sent as list and the List flag must
+         not be set.
+
           Payload of the packet:  Payload of this packet is described
                                   in the section SILC Authentication
                                   Protocol and it sub sections in [SILC].
@@ -602,28 +638,20 @@ List of SILC Packet types are defined as follows.
           Payload of the packet:  See section 2.3.16 New ID Payload
 
 
-     19   SILC_PACKET_NEW_ID_LIST
+     19   SILC_PACKET_NEW_CLIENT
 
-          This packet is used to distribute list of new ID's from
-          server to routers.  This is equivalent to previous packet
-          type except that it may include several ID's.  Client must
-          not send this packet.
-
-          Payload of the packet:  See section 2.3.17 New ID List 
-                                  Payload
-
-
-     20   SILC_PACKET_NEW_CLIENT
-
-          This packet is used by client to register itself to the
-          SILC network.  This is sent after key exchange and 
+          This packet is used by client to register itself to the   
+          SILC network.  This is sent after key exchange and  
           authentication protocols has been completed.  Client sends
           various information about itself in this packet.
 
-          Payload of the packet:  See section 2.3.18 New Client Payload
+          This packet must not be sent as list and the List flag must
+         not be set.
+
+          Payload of the packet:  See section 2.3.19 New Client Payload
 
 
-     21   SILC_PACKET_NEW_SERVER
+     20   SILC_PACKET_NEW_SERVER
 
           This packet is used by server to register itself to the
           SILC network.  This is sent after key exchange and 
@@ -633,10 +661,13 @@ List of SILC Packet types are defined as follows.
           its Server ID and other information in this packet.
           Client must not send or receive this packet.
 
-          Payload of the packet:  See section 2.3.19 New Server Payload
+          This packet must not be sent as list and the List flag must
+         not be set.
 
+          Payload of the packet:  See section 2.3.20 New Server Payload
 
-     22   SILC_PACKET_NEW_CHANNEL
+
+     21   SILC_PACKET_NEW_CHANNEL
 
           This packet is used to notify routers about newly created
           channel.  Channels are always created by the router and it must
@@ -645,108 +676,21 @@ List of SILC Packet types are defined as follows.
           packet.  This packet maybe sent to entity that is indirectly
           connected to the sender.
 
-          Payload of the packet:  See section 2.3.20 New Channel Payload
-
-
-     23   SILC_PACKET_NEW_CHANNEL_USER
-
-          This packet is used to notify routers about new user on channel.
-          The packet is sent after user has joined to the channel.  Server
-          may send this packet to its router and router may send this to
-          its primary router.  Client must not send this packet.  This
-          packet maybe sent to entity that is indirectly connected to
-          the sender.
-
-          When received, the server or router must distribute
-          SILC_NOTIFY_TYPE_JOIN to local clients on the channel.
-
-          Payload of the packet:  See section 2.3.21 New Channel User
-                                  Payload
-
-
-     24   SILC_PACKET_NEW_CHANNEL_LIST
-
-          This packet is used to distribute list of created channels
-          from server to routers.  This is equivalent to the packet
-          SILC_PACKET_NEW_CHANNEL except that it may include several
-          payloads. Client must not send this packet.
-
-          Payload of the packet:  See section 2.3.22 New Channel List
-                                  Payload
+          Payload of the packet:  See section 2.3.21 New Channel Payload
 
 
-     25   SILC_PACKET_NEW_CHANNEL_USER_LIST
-
-          This packet is used to distribute list of users on specific
-          channel from server to routers.  This is equivalent to the
-          packet SILC_PACKET_NEW_CHANNEL_USER except that it may
-          include several payloads.  Client must not send this packet.
-
-          When received, the server or router must distribute
-          SILC_NOTIFY_TYPE_JOIN to local clients on the channel.
-
-          Payload of the packet:  See section 2.3.23 New Channel User
-                                  List Payload
-
-
-     26   SILC_PACKET_REPLACE_ID
-
-          This packet is used to replace old ID with new ID sent in
-          the packet payload.  For example, when client changes its
-          nickname new ID is created and this packet can be used to
-          distribute the new ID and the old ID is removed when it is
-          send in the packet.  Client cannot send or receive this
-          packet.  This packet maybe sent to entity that is indirectly
-          connected to the sender.
-
-          When received and the replaced ID is Client ID the server or
-          router must distribute SILC_NOTIFY_TYPE_NICK_CHANGE to the
-          local clients on the channels (if any) of the client whose
-          ID was changed.  However, the notify type must be sent only
-          once per client.
-
-          Payload of the packet:  See section 2.3.24 Replace ID Payload
-
-
-     27   SILC_PACKET_REMOVE_ID
-
-          This packet is used to removed ID.  For example, when client
-          exits SILC network its ID is removed.  Client must not send
-          this packet.  This packet maybe sent to entity that is
-          indirectly connected to the sender.
-
-          When received and the removed ID is Client ID the server or
-          router must distribute SILC_NOTIFY_TYPE_SIGNOFF to the
-          local clients on the channels (if any) of the client whose
-          ID was removed.  However, the notify type must be sent only
-          once per client.
-
-          Payload of the packet:  See section 2.3.25 Remove ID Payload
-
-
-     28   SILC_PACKET_REMOVE_CHANNEL_USER
-
-          This packet is used to remove user from a channel.  This is
-          used by router to notify other routers in the network that a
-          client has left a channel.  This packet maybe sent to entity
-          that is indirectly connected to the sender.
-
-          When received, the server or router must distribute
-          SILC_NOTIFY_TYPE_LEAVE to local clients on the channel.
-
-          Payload of the packet:  See section 2.3.26 Remove Channel User
-                                  Payload
-
-
-     29   SILC_PACKET_REKEY
+     22   SILC_PACKET_REKEY
 
           This packet is used to indicate that re-key must be performed
           for session keys.  See section Session Key Regeneration in
           [SILC1] for more information.  This packet does not have
           a payload.
 
+          This packet must not be sent as list and the List flag must
+         not be set.
 
-     30   SILC_PACKET_REKEY_DONE
+
+     23   SILC_PACKET_REKEY_DONE
 
           This packet is used to indicate that re-key is performed and
           new keys must be used hereafter.  This is sent only if re-key
@@ -754,38 +698,22 @@ List of SILC Packet types are defined as follows.
           as SILC Key Exchange protocol is executed.  This packet does
           not have a payload.
 
-     
-     31   SILC_PACKET_SET_MODE
-
-          This packet is used by servers and routers to inform each 
-          other about changed modes.  When channel's and client'c channel
-          mode is changed this packet is used to distribute the information
-          to all routers in the network.  Server can send this packet but
-          must not receive it.  Router can send and receive this packet.
-          Client must not send or receive this packet.
-
-          Payload of the packet:  See section 2.3.27 Set Mode Payload
-
-
-     32   SILC_PACKET_SET_MODE_LIST
-
-          This packet is used to distribute list of Set Mode payloads
-          from server to routers.  This is equivalent to the packet
-          SILC_PACKET_SET_MODE except that it may include several
-          payloads.  Client must not send this packet.
-
-          Payload of the packet:  See section 2.3.28 Set Mode List
-                                  Payload
+          This packet must not be sent as list and the List flag must
+         not be set.
 
-     33   SILC_PACKET_HEARTBEAT
+     
+     24   SILC_PACKET_HEARTBEAT
 
           This packet is used by clients, servers and routers to keep the
           connection alive.  It is recommended that all servers implement
           keepalive actions and perform it to both direction in a link.
           This packet does not have a payload.
 
+          This packet must not be sent as list and the List flag must
+         not be set.
+
 
-     34 - 199
+     25 - 199
 
          Currently undefined commands.
 
@@ -1127,25 +1055,24 @@ ID's sent in arguments are sent inside ID Payload.
 
       Sent when client has joined to a channel.  The server must distribute
       this type only to the local clients on the channel and then send
-      SILC_PACKET_NEW_CHANNEL_USER packet to its primary route.  The router
-      or server receiving the packet distributes this type to the local
-      clients on the channel.  See description of SILC_PACKET_NEW_CHANNEL_USER
-      packet for more information.
+      it to its primary router. 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:  1
-          Arguments:  (1) <Client ID>
+      Max Arguments:  2
+          Arguments:  (1) <Client ID>  (2) <Channel ID>
 
-      The <Client ID> is the client that joined to the channel.
+      The <Client ID> is the client that joined to the channel indicated
+      by the <Channel ID>.
 
 
 3     SILC_NOTIFY_TYPE_LEAVE
 
       Sent when client has left a channel.  The server must distribute
       this type only to the local clients on the channel and then send
-      SILC_PACKET_REMOVE_CHANNEL_USER packet to its primary route.  The
-      router or server receiving the packet distributes this type to the
-      local clients on the channel.  See description of 
-      SILC_PACKET_REMOVE_CHANNEL_USER packet for more information.
+      it to its primary router. 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:  1
           Arguments:  (1) <Client ID>
@@ -1155,15 +1082,17 @@ ID's sent in arguments are sent inside ID Payload.
 
 4     SILC_NOTIFY_TYPE_SIGNOFF
 
-      Sent when client signoffs from SILC network.  This type is sent only
-      if the client was joined to any channel.  This type is sent by server
-      or router when SILC_PACKET_REMOVE_ID packet has been received.  See
-      detailed information from description of SILC_PACKET_REMOVE_ID packet.
+      Sent when client signoffs from SILC network.  The server must
+      distribute this type only to the local clients on the channel and
+      then send it to its primary router. 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:  1
-          Arguments:  (1) <Client ID>
+      Max Arguments:  2
+          Arguments:  (1) <Client ID>  (2)  <message>
 
-      The <Client ID> is the client who left SILC network.
+      The <Client ID> is the client who left SILC network.  The <message>
+      is free text string indicating the reason of signoff.
 
 
 5     SILC_NOTIFY_TYPE_TOPIC_SET
@@ -1180,10 +1109,11 @@ ID's sent in arguments are sent inside ID Payload.
 
 6     SILC_NOTIFY_TYPE_NICK_CHANGE
 
-      Sent when client changes nick on a channel.  This type is sent only if
-      the client has joined to any channel.  This type is sent by server or
-      router when SILC_PACKET_REPLACE_ID packet has been received.  See 
-      detailed information from description of SILC_PACKET_REPLACE_ID packet.
+      Sent when client changes nick on a channel.  The server must
+      distribute this type only to the local clients on the channel and
+      then send it to its primary router. 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) <Old Client ID>  (2) <New Client ID>
@@ -1243,6 +1173,17 @@ ID's sent in arguments are sent inside ID Payload.
       The <Old Channel ID> is the channel's old ID and the <New Channel ID>
       is the new one that must replace the old one.
 
+
+11    SILC_NOTIFY_TYPE_SERVER_SIGNOFF
+
+      Sent when server quits SILC network.  Those clients from this server
+      that are on channels must be removed from the channel.
+
+      Max Arguments:  1
+          Arguments:  (1) <Server ID>
+
+      The <Server ID> is the server's ID.
+
 .in 3
 
 Notify types starting from 16384 are reserved for private notify
@@ -1766,29 +1707,6 @@ The packet uses generic ID Payload as New ID Payload.  See section
 2.3.2.1 for generic ID Payload.
 
 
-.ti 0
-2.3.17 New ID List Payload
-
-New ID List Payload is used to distribute list of ID's usually from 
-server to router but also from router to other routers in the network.
-This payload is used, for example, when server is connected to router
-and the server wants to distribute all of its locally connected clients
-and locally created channels to the router.  It is convenient in this
-case to use this payload instead of sending all the information one
-by one using New ID Payload.  Also, when router redistributes the
-packet by broadcasting it, it is convenient to send only one packet.
-
-There is no specific payload for this packet type.  The packet type
-uses same payload as described in previous section.  To form a list
-several payloads is put in the packet each after each.  The payload
-is variable in length but can be calculated by calculating the ID
-Type field, Length field and the ID Data fields together.  This forms
-one New ID Payload in the list.
-
-The list of payloads may only be sent with SILC_PACKET_NEW_ID_LIST
-packet.  They must not be sent in any other packet type.
-
-
 .ti 0
 2.3.18 New Client Payload
 
@@ -1960,334 +1878,6 @@ o Channel ID (variable length) - The created Channel ID.
 .in 3
 
 
-.ti 0
-2.3.21 New Channel User Payload
-
-When client (user) joins to a channel, server must notify routers
-about the new user on the channel.  Normal server sends this packet
-payload to its router which then broadcasts the packet further.
-Router sends this packet always to its primary router.  Client must
-not send this packet payload.  The mode of the user is NONE after 
-user has joined to the channel.
-
-The payload may only be sent with SILC_PACKET_NEW_CHANNEL_USER 
-packet.  It must not be sent in any other packet type.  Following 
-diagram represents the New Channel User 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
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-|       Channel ID Length       |                               |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
-|                                                               |
-~                          Channel ID                           ~
-|                                                               |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-|       Client ID Length        |                               |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
-|                                                               |
-~                           Client ID                           ~
-|                                                               |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-.in 3
-
-.ce
-Figure 20:  New Channel User Payload
-
-
-.in 6
-o Channel ID Length (2 bytes) - Length of the Channel ID.
-
-o Channel ID (variable length) - The Channel ID of the channel
-  to which the client has joined.
-
-o Client ID Length (2 bytes) - Length of the Client ID.
-
-o Client ID (variable length) - The Client ID of the client
-  who has joined the channel.
-.in 3
-
-
-.ti 0
-2.3.22 New Channel List Payload
-
-This payload is used to distribute list of new channels from server
-to routers.  It might be convenient to send list of new channels when
-existing server connects to router, instead of sending them one
-by one.  Also, when router redistributes the packet by broadcasting it,
-it is convenient to send only one packet.
-
-
-There is no specific payload for this packet type.  The packet type
-uses same payload as described in 2.3.19 New Channel Payload.  To form
-a list several payloads is put in the packet each after each.  The
-payload is variable in length but can be calculated by calculating
-the length of the fields together.  This forms one New Channel Payload
-in the list.
-
-The list of payloads may only be sent with SILC_PACKET_NEW_CHANNEL_LIST
-packet.  They must not be sent in any other packet type.
-
-
-.ti 0
-2.3.23 New Channel User List Payload
-
-This payload is used to distribute list of channel users on a channel
-from server to routers.  It might convenient to send list of channel
-users when existing server connects to router, instead of sending them
-one by one.  One list may include users for several different channels.
-Also, when router redistributes the packet by broadcasting it, it is
-convenient to send only one packet.
-
-There is no specific payload for this packet type.  The packet type
-uses same payload as described in 2.3.20 New Channel User Payload.
-To form a list several payloads is put in the packet one after another.
-The payload is variable in length but can be calculated by calculating
-the length of the fields together.  This forms one New Channel User
-Payload in the list.
-
-The list of payloads may only be sent with packet
-SILC_PACKET_NEW_CHANNEL_USER_LIST. They must not be sent in any other
-packet type.
-
-
-.ti 0
-2.3.24 Replace ID Payload
-
-This payload is used to replace old ID with new ID sent in the payload.
-When ID changes for some entity and the new ID is wanted to replace the
-old one this payload must be used.  Client cannot send or receive this
-payload.  Normal server and router server may send and receive this
-payload.  After this packet has been sent the old ID must not be used
-anymore.
-
-The payload may only be sent with SILC_PACKET_REPLACE_ID packet.  It must
-not be sent in any other packet type.  Following diagram represents the 
-Replace Payload 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
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-|          Old ID Type          |         Old ID Length         |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-|                                                               |
-~                         Old ID Data                           ~
-|                                                               |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-|          New ID Type          |         New ID Length         |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-|                                                               |
-~                         New ID Data                           ~
-|                                                               |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-.in 3
-
-.ce
-Figure 21:  Replace ID Payload
-
-
-.in 6
-o Old ID Type (2 bytes) - Indicates the type of the old ID.  See 
-  section 2.4 SILC ID Types for list of defined ID types.
-
-o Old ID Length (2 bytes) - Length of the old ID Data area not 
-  including the length of any other fields in the payload.
-
-o Old ID Data (variable length) - The actual old ID data.
-
-o New ID Type (2 bytes) - Indicates the type of the new ID.  See 
-  section 2.4 SILC ID Types for list of defined ID types.
-
-o New ID Length (2 bytes) - Length of the new ID Data area not 
-  including the length of any other fields in the payload.
-
-o New ID Data (variable length) - The actual new ID data.
-.in 3
-
-
-.ti 0
-2.3.25 Remove ID Payload
-
-Remove ID payload is used to remove ID from SILC network.  This is used
-when client, server, router or channel is removed from the SILC network.
-After this payload has been send the old ID must not be used anymore.
-Client must not send or receive this payload.
-
-The packet uses generic ID Payload as New ID Payload.  See section
-2.3.2.1 for generic ID Payload.
-
-
-.ti 0
-2.3.26 Remove Channel User Payload
-
-Remove Channel User payload is used to remove a user from a channel network
-wide.  This is used by routers to notify other routers that a user has
-left a channel.  As routers keep information about users on channels a
-user leaving channel must be removed from all routers.  Normal server may
-send this payload as well.  Client must not send this payload.
-
-The payload may only be sent with SILC_PACKET_REMOVE_CHANNEL USER packet.
-It must not be sent in any other packet type.  Following diagram
-represents the Remove Payload 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
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-|      Client ID Length         |                               |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
-|                                                               |
-~                        Client ID Data                         ~
-|                                                               |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-|      Channel ID Length        |                               |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
-|                                                               |
-~                        Channel ID Data                        ~
-|                                                               |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-.in 3
-
-.ce
-Figure 22:  Remove Channel User Payload
-
-
-.in 6
-o Client ID Length (2 bytes) - Length of the Client ID Data area
-  not including the length of any other fields in the payload.
-
-o Client ID Data (variable length) - The Client ID of the user
-  that has left the channel.
-
-o Channel ID Length (2 bytes) - Length of the Channel ID Data area
-  not including the length of any other fields in the payload.
-
-o Channel ID Data (variable length) - The Channel ID of the channel
-  the user has left.
-.in 3
-
-
-.ti 0
-2.3.27 Set Mode Payload
-
-Set Mode Payload is used by servers and routers to distribute to each 
-other the information about changed modes in the SILC network.  The 
-payload is sent when channel's or client's channel mode is changed.  
-Server can send this to router which will broadcast it further to other
-routers.  However, normal server must not reiceve this payload.  Client
-must not send or receive this payload.
-
-The payload may only be sent with SILC_PACKET_SET_MODE packet.
-It must not be sent in any other packet type.  Following diagram
-represents the Set Mode Payload.
-
-
-
-.in 5
-.nf
-.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
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-|           Mode Type           |        Payload Length         |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-|                           Mode Mask                           |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-| Argument Nums |
-+-+-+-+-+-+-+-+-+
-.in 3
-
-.ce
-Figure 23:  Set Mode Payload
-
-
-.in 6
-o Mode type (2 bytes) - Indicates the type of the mode that was
-  changed.  Every type has arguments associated to the type which
-  are defined below.  The following types are defined:
-
-  0        SILC_MODE_TYPE_CHANNEL
-
-           Max Arguments:  2
-               Arguments:  (1) <Channel ID>  (2) <Client ID>
-
-           The <Channel ID> is the channel which mode was set and the
-           <Client ID> is the client who set it.
-
-
-  1        SILC_MODE_TYPE_UCHANNEL
-
-           Max Arguments:  3
-               Arguments:  (1) <Channel ID>        (2) <Client ID>  
-                           (3) <Target Client ID>
-
-           The <Channel ID> is the channel where the <Client ID> and
-           the <Target Client ID> is on.  The <Client ID> is the client
-           who set the <Target Client ID> mode.
-
-
-  2 -      RESERVED
-
-           Reserved types.
-
-
-  32768 -  Private range
-
-           Rest of the types are reserved for private use.
-
-o Payload Length (2 bytes) - Length of the entire Set Mode Payload
-  including any associated Argument Payloads.
-
-o Mode Mask (4 bytes) - Indicates the set mode mask.  This is
-  specified by the mode type.  See definitions of SILC_COMMAND_UMODE
-  for client modes, SILC_COMMAND_CMODE for channel modes and
-  SILC_COMMAND_CUMODE for client's channel modes in [SILC1].
-
-o Argument Nums (2 bytes) - Indicates the number of Argument
-  Payloads associated to this payload.  Mode types may define
-  arguments to be send along this payload.
-.in 3
-
-
-.ti 0
-2.3.28 Set Mode List Payload
-
-This paylaod is used to distribute list of Set Mode payloads inside
-one packet.  When server announces channels and client's on those 
-channels to its primary router when it connects to it, it is convenient
-to send list of Set Mode payloads to set the modes for the channel
-and clients on those channel.  One list may include several mode
-types.  Also, when router redistributes the packet by broadcasting it,
-it is convenient to send only one packet.
-
-There is no specific payload for this packet type.  The packet type
-uses same payload as described in 2.3.27 Set Mode Payload.  To form a
-list several payloads are put in the packet one after another.  The
-payload is variable in length but can be calculated by calculating the
-length of the fields together.  This forms one Set Mode payload in the
-list.
-
-The list of payloads may only be sent with packet SILC_PACKET_SET_MODE_LIST.
-They must not be sent in any other packet type.
-
-
 .ti 0
 2.4 SILC ID Types
 
@@ -2579,35 +2169,7 @@ directly connected to the server.
 
 
 .ti 0
-2.12 Packet Forwarding
-
-Currently SILC command packets may be forwarded from one entity to another.
-Any other packet currently cannot be forwarded but support for more packet
-types may be added if needed.  Forwarding is usually used by server to
-forward some command request coming from client to the router as the server
-may be incapable to handle the request.  Forwarding may be only one hop
-long; the receiver of the packet with Forwarded flag set in the SILC   
-Packet header must not forward the packet any further.
-
-The normal scenario is that client sends JOIN command to the server which
-is not able to create the channel as there are no local clients on the
-channel.  Channels are created always by the router of the cell thus the
-packet must be forwarded to the router.  The server forwards the original
-packet coming from client to the router after it has set the Forwarded
-flag to the SILC Packet header.
-
-Router receiving the packet knows that the packet has to be processed
-specially by checking the flags and the Forwarded flag in the SILC Packet
-header.  After router has joined the client to the channel (and perhaps
-created a new channel) it sends normal command reply packet to the
-client.  However, as the router doesn't have direct connection to the
-client the packet is sent through the server.  Server detects that 
-the command reply packet is destined to the client and sends it to
-the client.
-
-
-.ti 0
-2.13 Packet Broadcasting
+2.12 Packet Broadcasting
 
 SILC packets may be broadcasted in SILC network.  However, only router
 server may send or receive broadcast packets.  Client and normal server
@@ -2634,7 +2196,7 @@ routers may keep these informations up to date.
 
 
 .ti 0
-2.14 Packet Tunneling
+2.13 Packet Tunneling
 
 Tunneling is a feature that is available in SILC protocol.  Tunneling
 means that extra SILC Packet Header is applied to the original packet
index 00b37a35976f958525f20c43ad08da5957c0f12c..949cef5841c478e9957073c595eb3f59095a2f16 100644 (file)
@@ -1175,7 +1175,15 @@ rsa        RSA  (mandatory)
 dss        DSS  (optional)
 .in 3
 
-Both of the algorithms are described in [Scheneir] and [Menezes].
+DSS is described in [Menezes].  The RSA must be implemented according
+PKCS #1 [PKCS1].  The mandatory PKCS #1 implementation in SILC must be
+compliant to either PKCS #1 version 1.5 or newer with the following
+notes: The signature encoding is always in same format as the encryption
+encoding regardles of the PKCS #1 version.  The signature with appendix
+(with hash algorithm OID in the data) must not be used in the SILC.  The
+rationale for this is that there is no binding between the PKCS #1 OIDs
+and the hash algorithms used in the SILC protocol.  Hence, the encoding
+is always in PKCS #1 version 1.5 format.
 
 Additional public key algorithms may be defined to be used in SILC.
 
index 928d4c188cf72c41b2e7f989c06a98bc11f1e6cd..81cf7e020650031db21904c42c722a7242836e94 100644 (file)
@@ -1426,11 +1426,16 @@ void silc_client_notify_by_server(SilcClient client,
       goto out;
     }
 
-    /* Get channel entry */
-    channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
-                               SILC_ID_CHANNEL);
+    /* Get Channel ID */
+    tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+    if (!tmp)
+      goto out;
+
+    channel_id = silc_id_payload_parse_id(tmp, tmp_len);
     if (!channel_id)
       goto out;
+
+    /* Get channel entry */
     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
                                     SILC_ID_CHANNEL, &id_cache))
       break;
index fb03c6a6806d3d739a441f746cc640b17130a32d..b22ae26401b7803d7b10d5b4a0e986fbac2687e0 100644 (file)
@@ -30,7 +30,6 @@ libsilccore_a_SOURCES = \
        silcsockconn.c \
        silcpayload.c \
        silcnotify.c \
-       silcmode.c \
        silcauth.c
 
 EXTRA_DIST = *.h
index c531badce4cbe89208264f17be522a0a0371a42c..51e69badd0f189a7242095ed408d569ae28c4d3d 100644 (file)
@@ -131,3 +131,12 @@ unsigned int silc_id_get_len(SilcIdType type)
 
   return 0;
 }
+
+/* Duplicate ID data */
+
+void *silc_id_dup(void *id, SilcIdType type)
+{
+  int len = silc_id_get_len(type);
+  void *new = silc_calloc(1, len);
+  memcpy(new, id, len);
+}
index 2cb84f00e730f3db0a89bb6ae802d0b17228dbe6..d4c813c4e012b95ab92349448feee8f3a68d4b91 100644 (file)
@@ -116,5 +116,6 @@ typedef struct {
 unsigned char *silc_id_id2str(void *id, SilcIdType type);
 void *silc_id_str2id(unsigned char *id, unsigned int id_len, SilcIdType type);
 unsigned int silc_id_get_len(SilcIdType type);
+void *silc_id_dup(void *id, SilcIdType type);
 
 #endif
diff --git a/lib/silccore/silcmode.c b/lib/silccore/silcmode.c
deleted file mode 100644 (file)
index d0f4f4d..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
-
-  silcmode.c
-
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
-
-  Copyright (C) 2001 Pekka Riikonen
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-*/
-/* $Id$ */
-
-#include "silcincludes.h"
-#include "silcmode.h"
-
-/******************************************************************************
-
-                               Set Mode Payload
-
-******************************************************************************/
-
-struct SilcSetModePayloadStruct {
-  unsigned short mode_type;
-  unsigned int mode_mask;
-  unsigned char argc;
-  SilcArgumentPayload args;
-};
-
-/* Parse Set Mode payload buffer and return data into payload structure */
-
-SilcSetModePayload silc_set_mode_payload_parse(SilcBuffer buffer)
-{
-  SilcSetModePayload new;
-  unsigned short len;
-  int ret;
-
-  SILC_LOG_DEBUG(("Parsing Set Mode payload"));
-
-  new = silc_calloc(1, sizeof(*new));
-
-  ret = silc_buffer_unformat(buffer,
-                            SILC_STR_UI_SHORT(&new->mode_type),
-                            SILC_STR_UI_SHORT(&len),
-                            SILC_STR_UI_INT(&new->mode_mask),
-                            SILC_STR_UI_CHAR(&new->argc),
-                            SILC_STR_END);
-  if (ret == -1)
-    goto err;
-
-  if (len > buffer->len)
-    goto err;
-
-  if (new->argc) {
-    silc_buffer_pull(buffer, 9);
-    new->args = silc_argument_payload_parse(buffer, new->argc);
-    silc_buffer_push(buffer, 9);
-  }
-
-  return new;
-
- err:
-  silc_free(new);
-  return NULL;
-}
-
-/* Encode Set Mode payload with variable argument list. If `argc' is > 0
-   argument payloads will be associated to the Set Mode payload. Variable
-   arguments must be {usigned char *, unsigned int (len)}. */
-
-SilcBuffer silc_set_mode_payload_encode(unsigned short mode_type, 
-                                       unsigned int mode_mask,
-                                       unsigned int argc, 
-                                       va_list ap)
-{
-  SilcBuffer buffer;
-  SilcBuffer args = NULL;
-  unsigned char **argv;
-  unsigned int *argv_lens = NULL, *argv_types = NULL;
-  unsigned char *x;
-  unsigned int x_len;
-  int i, len = 0;
-
-  if (argc) {
-    argv = silc_calloc(argc, sizeof(unsigned char *));
-    argv_lens = silc_calloc(argc, sizeof(unsigned int));
-    argv_types = silc_calloc(argc, sizeof(unsigned int));
-    
-    for (i = 0; i < argc; i++) {
-      x = va_arg(ap, unsigned char *);
-      x_len = va_arg(ap, unsigned int);
-      
-      argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
-      memcpy(argv[i], x, x_len);
-      argv_lens[i] = x_len;
-      argv_types[i] = i + 1;
-    }
-
-    args = silc_argument_payload_encode(argc, argv, argv_lens, argv_types);
-    len = args->len;
-
-    for (i = 0; i < argc; i++)
-      silc_free(argv[i]);
-    silc_free(argv);
-    silc_free(argv_lens);
-    silc_free(argv_types);
-  }
-
-  len += 9;
-  buffer = silc_buffer_alloc(len);
-  silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
-  silc_buffer_format(buffer,
-                    SILC_STR_UI_SHORT(mode_type),
-                    SILC_STR_UI_SHORT(len),
-                    SILC_STR_UI_INT(mode_mask),
-                    SILC_STR_UI_CHAR((unsigned char)argc),
-                    SILC_STR_END);
-
-  if (argc) {
-    silc_buffer_pull(buffer, 9);
-    silc_buffer_format(buffer,
-                      SILC_STR_UI_XNSTRING(args->data, args->len),
-                      SILC_STR_END);
-    silc_buffer_push(buffer, 9);
-    silc_buffer_free(args);
-  }
-
-  return buffer;
-}
-
-/* Free's Set Mode payload */
-
-void silc_set_mode_payload_free(SilcSetModePayload payload)
-{
-  if (payload) {
-    silc_argument_payload_free(payload->args);
-    silc_free(payload);
-  }
-}
-
-/* Return mode type */
-
-unsigned short silc_set_mode_get_type(SilcSetModePayload payload)
-{
-  return payload->mode_type;
-}
-
-/* Return mode mask */
-
-unsigned int silc_set_mode_get_mode(SilcSetModePayload payload)
-{
-  return payload->mode_mask;
-}
-
-/* Return argument nums */
-
-unsigned int silc_set_mode_get_arg_num(SilcSetModePayload payload)
-{
-  return payload->argc;
-}
-
-/* Return argument payload */
-
-SilcArgumentPayload silc_set_mode_get_args(SilcSetModePayload payload)
-{
-  return payload->args;
-}
index 2659206a81133fd8fd19b277ebf85e37d8227b1c..26b45c748e85e4e443620e79a0ab39041d009c7e 100644 (file)
 #ifndef SILCMODE_H
 #define SILCMODE_H
 
-/* Forward declarations */
-typedef struct SilcSetModePayloadStruct *SilcSetModePayload;
-
-/* Mode types defined for Set Mode payload */
-#define SILC_MODE_TYPE_CHANNEL        0
-#define SILC_MODE_TYPE_UCHANNEL       1
-#define SILC_MODE_RESERVED            2      /* RESERVED */
-#define SILC_MODE_PRIVATE             32768  /* RESERVED */
-
 /* Channel modes */
 #define SILC_CHANNEL_MODE_NONE        0x0000
 #define SILC_CHANNEL_MODE_PRIVATE     0x0001 /* private channel */
@@ -48,16 +39,4 @@ typedef struct SilcSetModePayloadStruct *SilcSetModePayload;
 #define SILC_CHANNEL_UMODE_CHANFO     0x0001 /* channel founder */
 #define SILC_CHANNEL_UMODE_CHANOP     0x0002 /* channel operator */
 
-/* Prototypes */
-SilcSetModePayload silc_set_mode_payload_parse(SilcBuffer buffer);
-SilcBuffer silc_set_mode_payload_encode(unsigned short mode_type, 
-                                       unsigned int mode_mask,
-                                       unsigned int argc, 
-                                       va_list ap);
-void silc_set_mode_payload_free(SilcSetModePayload payload);
-unsigned short silc_set_mode_get_type(SilcSetModePayload payload);
-unsigned int silc_set_mode_get_mode(SilcSetModePayload payload);
-unsigned int silc_set_mode_get_arg_num(SilcSetModePayload payload);
-SilcArgumentPayload silc_set_mode_get_args(SilcSetModePayload payload);
-
 #endif
index 3c85ed2a3a4a90244fda86eda37c60454c1d3684..2cf198f5590c72d5b82bed4e08f1ac72eea67b46 100644 (file)
@@ -41,6 +41,7 @@ typedef unsigned short SilcNotifyType;
 #define SILC_NOTIFY_TYPE_CUMODE_CHANGE   8 /* "has change mode" */
 #define SILC_NOTIFY_TYPE_MOTD            9 /* message of the day */
 #define SILC_NOTIFY_TYPE_CHANNEL_CHANGE  10 /* Channel's ID has changed */
+#define SILC_NOTIFY_TYPE_SERVER_SIGNOFF  11 /* Server quitting SILC */
 
 /* Prototypes */
 SilcNotifyPayload silc_notify_payload_parse(SilcBuffer buffer);
index 17edad0237dccf60a4e5b03593e32f7dba0fcb1d..1d63e9cd25115eeadfa451ea475268b7989da54c 100644 (file)
@@ -59,10 +59,10 @@ typedef unsigned char SilcPacketFlags;
 /* All defined packet flags */
 #define SILC_PACKET_FLAG_NONE             0x00
 #define SILC_PACKET_FLAG_PRIVMSG_KEY      0x01
-#define SILC_PACKET_FLAG_BROADCAST        0x02
-#define SILC_PACKET_FLAG_TUNNELED         0x04
+#define SILC_PACKET_FLAG_LIST             0x04
+#define SILC_PACKET_FLAG_BROADCAST        0x04
+#define SILC_PACKET_FLAG_TUNNELED         0x08
 /* Rest of flags still available
-#define SILC_PACKET_FLAG_XXX              0x08
 #define SILC_PACKET_FLAG_XXX              0x10
 #define SILC_PACKET_FLAG_XXX              0x20
 #define SILC_PACKET_FLAG_XXX              0x40
@@ -210,22 +210,15 @@ typedef void (*SilcPacketParserCallback)(SilcPacketParserContext
 #define SILC_PACKET_CONNECTION_AUTH_REQUEST 16   /* Request of auth meth */
 #define SILC_PACKET_CONNECTION_AUTH      17      /* Connectinon auth */
 #define SILC_PACKET_NEW_ID               18      /* Sending new ID */
-#define SILC_PACKET_NEW_ID_LIST          19      /* Sending list of them */
-#define SILC_PACKET_NEW_CLIENT           20      /* Registering client */
-#define SILC_PACKET_NEW_SERVER           21      /* Registering server */
-#define SILC_PACKET_NEW_CHANNEL          22      /* Registering channel */
-#define SILC_PACKET_NEW_CHANNEL_USER     23      /*   "" user on channel */
-#define SILC_PACKET_NEW_CHANNEL_LIST     24      /* List of new channels */
-#define SILC_PACKET_NEW_CHANNEL_USER_LIST 25     /* List of users on "" */
-#define SILC_PACKET_REPLACE_ID           26      /* To replace old ID */
-#define SILC_PACKET_REMOVE_ID            27      /* To remove ID */
-#define SILC_PACKET_REMOVE_CHANNEL_USER  28      /* Remove user from channel */
-#define SILC_PACKET_REKEY                29
-#define SILC_PACKET_REKEY_DONE           30
-#define SILC_PACKET_SET_MODE             31      /* Set mode */
-#define SILC_PACKET_SET_MODE_LIST        32      /* List of Set Mode's */
-#define SILC_PACKET_HEARTBEAT            33      /* Heartbeat */
-/* #define SILC_PACKET_MAX               255 */
+#define SILC_PACKET_NEW_CLIENT           19      /* Client registering */
+#define SILC_PACKET_NEW_SERVER           20      /* Server registering */
+#define SILC_PACKET_NEW_CHANNEL          21      /* Channel registering */
+#define SILC_PACKET_REKEY                22      /* Re-key start */
+#define SILC_PACKET_REKEY_DONE           23      /* Re-key done */
+#define SILC_PACKET_HEARTBEAT            24      /* Heartbeat */
+
+#define SILC_PACKET_PRIVATE              200     /* Private range start  */
+#define SILC_PACKET_MAX                  255     /* RESERVED */
 
 /* Macros */
 
index c24ce8fe72eedd167c468e3a2bde8fa042a76deb..d53921698cbba75f7daa7e7b79006774816db243 100644 (file)
@@ -167,7 +167,9 @@ SilcBuffer silc_id_payload_encode(void *id, SilcIdType type)
   unsigned char *id_data;
   unsigned int len;
 
-  SILC_LOG_DEBUG(("Parsing ID payload"));
+  SILC_LOG_DEBUG(("Encoding %s ID payload",
+                 type == SILC_ID_CLIENT ? "Client" :
+                 type == SILC_ID_SERVER ? "Server" : "Channel"));
 
   id_data = silc_id_id2str(id, type);
   len = silc_id_get_len(type);
index c25e99ec9329253eb2f535e862145253059b92bf..a5475074da39e44019dfed00817f881d2b29f873 100644 (file)
@@ -30,7 +30,6 @@
 SilcPKCSObject silc_pkcs_list[] =
 {
   /* RSA with PKCS #1 (Uses directly routines from Raw RSA operations) */
-  /*
   { "rsa", &silc_rsa_data_context, 
     silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
     silc_rsa_get_private_key, silc_rsa_set_public_key,
@@ -38,10 +37,9 @@ SilcPKCSObject silc_pkcs_list[] =
     silc_rsa_data_context_len, silc_rsa_set_arg,
     silc_pkcs1_encrypt, silc_pkcs1_decrypt,
     silc_pkcs1_sign, silc_pkcs1_verify },
-  */
 
   /* Raw RSA operations */
-  { "rsa", &silc_rsa_data_context, 
+  { "rsa-raw", &silc_rsa_data_context, 
     silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
     silc_rsa_get_private_key, silc_rsa_set_public_key,
     silc_rsa_set_private_key, silc_rsa_context_len,