Fix double free in silcd.
[silc.git] / apps / silcd / command.c
index 82bc2f6ee035a5af7853e0b511cfaa9b37af9b7d..d8d105c535a76a72de9518fe9c1853fe17c48765 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2005 Pekka Riikonen
+  Copyright (C) 1997 - 2008 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
 
   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
@@ -22,7 +22,7 @@
 #include "server_internal.h"
 
 static int silc_server_is_registered(SilcServer server,
 #include "server_internal.h"
 
 static int silc_server_is_registered(SilcServer server,
-                                    SilcSocketConnection sock,
+                                    SilcPacketStream sock,
                                     SilcServerCommandContext cmd,
                                     SilcCommand command);
 static void
                                     SilcServerCommandContext cmd,
                                     SilcCommand command);
 static void
@@ -126,11 +126,11 @@ do {                                                                           \
    usually cannot send commands hence the check. */
 
 static int silc_server_is_registered(SilcServer server,
    usually cannot send commands hence the check. */
 
 static int silc_server_is_registered(SilcServer server,
-                                    SilcSocketConnection sock,
+                                    SilcPacketStream sock,
                                     SilcServerCommandContext cmd,
                                     SilcCommand command)
 {
                                     SilcServerCommandContext cmd,
                                     SilcCommand command)
 {
-  SilcIDListData idata = (SilcIDListData)sock->user_data;
+  SilcIDListData idata = silc_packet_get_context(sock);
 
   if (!idata)
     return FALSE;
 
   if (!idata)
     return FALSE;
@@ -155,7 +155,7 @@ typedef struct {
 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
 {
   SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
 {
   SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
-  SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
+  SilcClientEntry client = silc_packet_get_context(timeout->ctx->sock);
 
   if (!client) {
     SILC_LOG_DEBUG(("Client entry is invalid"));
 
   if (!client) {
     SILC_LOG_DEBUG(("Client entry is invalid"));
@@ -189,32 +189,32 @@ SILC_TASK_CALLBACK(silc_server_command_process_timeout)
 /* Processes received command packet. */
 
 void silc_server_command_process(SilcServer server,
 /* Processes received command packet. */
 
 void silc_server_command_process(SilcServer server,
-                                SilcSocketConnection sock,
-                                SilcPacketContext *packet)
+                                SilcPacketStream sock,
+                                SilcPacket packet)
 {
 {
+  SilcIDListData idata = silc_packet_get_context(sock);
   SilcServerCommandContext ctx;
   SilcServerCommand *cmd;
   SilcCommand command;
 
   SilcServerCommandContext ctx;
   SilcServerCommand *cmd;
   SilcCommand command;
 
+  if (!idata)
+    return;
+
   /* Allocate command context. This must be free'd by the
      command routine receiving it. */
   ctx = silc_server_command_alloc();
   ctx->server = server;
   /* Allocate command context. This must be free'd by the
      command routine receiving it. */
   ctx = silc_server_command_alloc();
   ctx->server = server;
-  ctx->sock = silc_socket_dup(sock);
-  ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
+  ctx->sock = sock;
+  ctx->packet = packet; /* Save original packet */
+  silc_packet_stream_ref(sock);
 
   /* Parse the command payload in the packet */
 
   /* Parse the command payload in the packet */
-  ctx->payload = silc_command_payload_parse(packet->buffer->data,
-                                           packet->buffer->len);
+  ctx->payload = silc_command_payload_parse(packet->buffer.data,
+                                           silc_buffer_len(&packet->buffer));
   if (!ctx->payload) {
   if (!ctx->payload) {
-    SILC_LOG_ERROR(("Bad command payload, dropped (%s:%d [%s])",
-                  sock->hostname, sock->port,
-                  (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
-                   sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
-                   sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
-                   "Router")));
-    silc_packet_context_free(packet);
-    silc_socket_free(ctx->sock);
+    SILC_LOG_ERROR(("Bad command payload"));
+    silc_packet_free(packet);
+    silc_packet_stream_unref(ctx->sock);
     silc_free(ctx);
     return;
   }
     silc_free(ctx);
     return;
   }
@@ -230,7 +230,9 @@ void silc_server_command_process(SilcServer server,
     SILC_LOG_DEBUG(("Unknown command %d", command));
     silc_server_command_send_status_reply(ctx, command,
                                          SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
     SILC_LOG_DEBUG(("Unknown command %d", command));
     silc_server_command_send_status_reply(ctx, command,
                                          SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
-    silc_server_command_free(ctx);
+    silc_packet_free(packet);
+    silc_packet_stream_unref(ctx->sock);
+    silc_free(ctx);
     return;
   }
 
     return;
   }
 
@@ -238,17 +240,11 @@ void silc_server_command_process(SilcServer server,
      executed with zero (0) timeout but if client is sending command more
      frequently than once in 2 seconds, then the timeout may be 0 to 2
      seconds. */
      executed with zero (0) timeout but if client is sending command more
      frequently than once in 2 seconds, then the timeout may be 0 to 2
      seconds. */
-  if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
-    SilcClientEntry client = (SilcClientEntry)sock->user_data;
+  if (idata->conn_type == SILC_CONN_CLIENT) {
+    SilcClientEntry client = silc_packet_get_context(sock);
     SilcServerCommandTimeout timeout;
     int fast;
 
     SilcServerCommandTimeout timeout;
     int fast;
 
-    if (!client) {
-      SILC_LOG_DEBUG(("Client entry is invalid"));
-      silc_server_command_free(ctx);
-      return;
-    }
-
     timeout = silc_calloc(1, sizeof(*timeout));
     timeout->ctx = ctx;
     timeout->cmd = cmd;
     timeout = silc_calloc(1, sizeof(*timeout));
     timeout->ctx = ctx;
     timeout->cmd = cmd;
@@ -266,16 +262,16 @@ void silc_server_command_process(SilcServer server,
 
     if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
                  (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
 
     if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
                  (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
-      silc_schedule_task_add(server->schedule, sock->sock,
-                            silc_server_command_process_timeout, timeout,
-                            (client->fast_command < 3 ? 0 :
-                             2 - (time(NULL) - client->last_command)),
-                            (client->fast_command < 3 ? 200000 : 0),
-                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+      silc_schedule_task_add_timeout(
+                           server->schedule,
+                           silc_server_command_process_timeout, timeout,
+                           (client->fast_command < 3 ? 0 :
+                            2 - (time(NULL) - client->last_command)),
+                           (client->fast_command < 3 ? 200000 : 0));
     else
     else
-      silc_schedule_task_add(server->schedule, sock->sock,
-                            silc_server_command_process_timeout, timeout,
-                            0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+      silc_schedule_task_add_timeout(server->schedule,
+                                    silc_server_command_process_timeout,
+                                    timeout, 0, 0);
     return;
   }
 
     return;
   }
 
@@ -313,9 +309,9 @@ void silc_server_command_free(SilcServerCommandContext ctx)
     if (ctx->payload)
       silc_command_payload_free(ctx->payload);
     if (ctx->packet)
     if (ctx->payload)
       silc_command_payload_free(ctx->payload);
     if (ctx->packet)
-      silc_packet_context_free(ctx->packet);
+      silc_packet_free(ctx->packet);
     if (ctx->sock)
     if (ctx->sock)
-      silc_socket_free(ctx->sock); /* Decrease reference counter */
+      silc_packet_stream_unref(ctx->sock);
     silc_free(ctx);
   }
 }
     silc_free(ctx);
   }
 }
@@ -361,7 +357,8 @@ SILC_TASK_CALLBACK(silc_server_command_pending_timeout)
                                         SILC_COMMAND_RESERVED,
                                         SILC_STATUS_ERR_TIMEDOUT, 0,
                                         reply->ident, 0);
                                         SILC_COMMAND_RESERVED,
                                         SILC_STATUS_ERR_TIMEDOUT, 0,
                                         reply->ident, 0);
-  cmdr->payload = silc_command_payload_parse(tmpreply->data, tmpreply->len);
+  cmdr->payload = silc_command_payload_parse(tmpreply->data,
+                                            silc_buffer_len(tmpreply));
   silc_buffer_free(tmpreply);
 
   /* Call all callbacks. Same as SILC_SERVER_PENDING_EXEC macro. */
   silc_buffer_free(tmpreply);
 
   /* Call all callbacks. Same as SILC_SERVER_PENDING_EXEC macro. */
@@ -382,7 +379,7 @@ SILC_TASK_CALLBACK(silc_server_command_pending_timeout)
    specified command, ident, callback and context this function has no
    effect. */
 
    specified command, ident, callback and context this function has no
    effect. */
 
-bool silc_server_command_pending(SilcServer server,
+SilcBool silc_server_command_pending(SilcServer server,
                                 SilcCommand reply_cmd,
                                 SilcUInt16 ident,
                                 SilcCommandCb callback,
                                 SilcCommand reply_cmd,
                                 SilcUInt16 ident,
                                 SilcCommandCb callback,
@@ -395,7 +392,7 @@ bool silc_server_command_pending(SilcServer server,
 /* Same as silc_server_command_pending with specific timeout for pending
    commands.  If the `timeout' is zero default timeout is used. */
 
 /* Same as silc_server_command_pending with specific timeout for pending
    commands.  If the `timeout' is zero default timeout is used. */
 
-bool silc_server_command_pending_timed(SilcServer server,
+SilcBool silc_server_command_pending_timed(SilcServer server,
                                       SilcCommand reply_cmd,
                                       SilcUInt16 ident,
                                       SilcCommandCb callback,
                                       SilcCommand reply_cmd,
                                       SilcUInt16 ident,
                                       SilcCommandCb callback,
@@ -420,10 +417,9 @@ bool silc_server_command_pending_timed(SilcServer server,
   reply->context = context;
   reply->callback = callback;
   reply->timeout =
   reply->context = context;
   reply->callback = callback;
   reply->timeout =
-    silc_schedule_task_add(server->schedule, 0,
-                          silc_server_command_pending_timeout, reply,
-                          timeout ? timeout : 12, 0,
-                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+    silc_schedule_task_add_timeout(server->schedule,
+                                  silc_server_command_pending_timeout, reply,
+                                  timeout ? timeout : 12, 0);
   silc_dlist_add(server->pending_commands, reply);
 
   return TRUE;
   silc_dlist_add(server->pending_commands, reply);
 
   return TRUE;
@@ -500,7 +496,7 @@ silc_server_command_send_status_reply(SilcServerCommandContext cmd,
                                         0);
   silc_server_packet_send(cmd->server, cmd->sock,
                          SILC_PACKET_COMMAND_REPLY, 0,
                                         0);
   silc_server_packet_send(cmd->server, cmd->sock,
                          SILC_PACKET_COMMAND_REPLY, 0,
-                         buffer->data, buffer->len, FALSE);
+                         buffer->data, silc_buffer_len(buffer));
   silc_buffer_free(buffer);
 }
 
   silc_buffer_free(buffer);
 }
 
@@ -529,7 +525,7 @@ silc_server_command_send_status_data(SilcServerCommandContext cmd,
                                         1, arg_type, arg, arg_len);
   silc_server_packet_send(cmd->server, cmd->sock,
                          SILC_PACKET_COMMAND_REPLY, 0,
                                         1, arg_type, arg, arg_len);
   silc_server_packet_send(cmd->server, cmd->sock,
                          SILC_PACKET_COMMAND_REPLY, 0,
-                         buffer->data, buffer->len, FALSE);
+                         buffer->data, silc_buffer_len(buffer));
   silc_buffer_free(buffer);
 }
 
   silc_buffer_free(buffer);
 }
 
@@ -559,7 +555,7 @@ silc_server_command_send_status_data2(SilcServerCommandContext cmd,
                                         arg_type2, arg2, arg_len2);
   silc_server_packet_send(cmd->server, cmd->sock,
                          SILC_PACKET_COMMAND_REPLY, 0,
                                         arg_type2, arg2, arg_len2);
   silc_server_packet_send(cmd->server, cmd->sock,
                          SILC_PACKET_COMMAND_REPLY, 0,
-                         buffer->data, buffer->len, FALSE);
+                         buffer->data, silc_buffer_len(buffer));
   silc_buffer_free(buffer);
 }
 
   silc_buffer_free(buffer);
 }
 
@@ -589,7 +585,7 @@ silc_server_command_pending_error_check(SilcServerCommandContext cmd,
     buffer = silc_command_payload_encode_payload(cmdr->payload);
     silc_server_packet_send(cmd->server, cmd->sock,
                            SILC_PACKET_COMMAND_REPLY, 0,
     buffer = silc_command_payload_encode_payload(cmdr->payload);
     silc_server_packet_send(cmd->server, cmd->sock,
                            SILC_PACKET_COMMAND_REPLY, 0,
-                           buffer->data, buffer->len, FALSE);
+                           buffer->data, silc_buffer_len(buffer));
     silc_buffer_free(buffer);
     return TRUE;
   }
     silc_buffer_free(buffer);
     return TRUE;
   }
@@ -603,7 +599,7 @@ SILC_SERVER_CMD_FUNC(whois)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 256);
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 256);
-  silc_server_query_command(cmd->server, SILC_COMMAND_WHOIS, cmd);
+  silc_server_query_command(cmd->server, SILC_COMMAND_WHOIS, cmd, NULL);
   silc_server_command_free(cmd);
 }
 
   silc_server_command_free(cmd);
 }
 
@@ -613,7 +609,7 @@ SILC_SERVER_CMD_FUNC(whowas)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
-  silc_server_query_command(cmd->server, SILC_COMMAND_WHOWAS, cmd);
+  silc_server_query_command(cmd->server, SILC_COMMAND_WHOWAS, cmd, NULL);
   silc_server_command_free(cmd);
 }
 
   silc_server_command_free(cmd);
 }
 
@@ -623,7 +619,7 @@ SILC_SERVER_CMD_FUNC(identify)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 256);
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 256);
-  silc_server_query_command(cmd->server, SILC_COMMAND_IDENTIFY, cmd);
+  silc_server_query_command(cmd->server, SILC_COMMAND_IDENTIFY, cmd, NULL);
   silc_server_command_free(cmd);
 }
 
   silc_server_command_free(cmd);
 }
 
@@ -634,7 +630,7 @@ SILC_SERVER_CMD_FUNC(identify)
 SILC_SERVER_CMD_FUNC(nick)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
 SILC_SERVER_CMD_FUNC(nick)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcClientEntry client = silc_packet_get_context(cmd->sock);
   SilcServer server = cmd->server;
   SilcBuffer nidp, oidp = NULL;
   SilcClientID *new_id;
   SilcServer server = cmd->server;
   SilcBuffer nidp, oidp = NULL;
   SilcClientID *new_id;
@@ -642,7 +638,7 @@ SILC_SERVER_CMD_FUNC(nick)
   unsigned char *nick, *nickc = NULL;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
 
   unsigned char *nick, *nickc = NULL;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+  if (client->data.conn_type != SILC_CONN_CLIENT || !client)
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
@@ -657,8 +653,8 @@ SILC_SERVER_CMD_FUNC(nick)
 
   /* Truncate over long nicks */
   if (nick_len > 128) {
 
   /* Truncate over long nicks */
   if (nick_len > 128) {
-    nick[128] = '\0';
     nick_len = 128;
     nick_len = 128;
+    nick[nick_len - 1] = '\0';
   }
 
   /* Check for valid nickname string.  This is cached, original is saved
   }
 
   /* Check for valid nickname string.  This is cached, original is saved
@@ -703,26 +699,20 @@ SILC_SERVER_CMD_FUNC(nick)
 
   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
 
   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
-  /* Remove old cache entry */
-  silc_idcache_del_by_context(server->local_list->clients, client);
-
-  silc_free(client->id);
-  client->id = new_id;
-
+  /* Update client entry */
+  silc_idcache_update_by_context(server->local_list->clients, client,
+                                new_id, nickc, TRUE);
+  silc_free(new_id);
   silc_free(client->nickname);
   client->nickname = strdup(nick);
 
   silc_free(client->nickname);
   client->nickname = strdup(nick);
 
-  /* Update client cache */
-  silc_idcache_add(server->local_list->clients, nickc,
-                  client->id, (void *)client, 0, NULL);
-
   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
   /* Send NICK_CHANGE notify to the client's channels */
   silc_server_send_notify_on_channels(server, NULL, client,
                                      SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
   /* Send NICK_CHANGE notify to the client's channels */
   silc_server_send_notify_on_channels(server, NULL, client,
                                      SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
-                                     oidp->data, oidp->len,
-                                     nidp->data, nidp->len,
+                                     oidp->data, silc_buffer_len(oidp),
+                                     nidp->data, silc_buffer_len(nidp),
                                      client->nickname,
                                      strlen(client->nickname));
 
                                      client->nickname,
                                      strlen(client->nickname));
 
@@ -736,7 +726,7 @@ SILC_SERVER_CMD_FUNC(nick)
   silc_server_send_command_reply(cmd->server, cmd->sock,
                                 SILC_COMMAND_NICK,
                                 SILC_STATUS_OK, 0, ident, 2,
   silc_server_send_command_reply(cmd->server, cmd->sock,
                                 SILC_COMMAND_NICK,
                                 SILC_STATUS_OK, 0, ident, 2,
-                                2, nidp->data, nidp->len,
+                                2, nidp->data, silc_buffer_len(nidp),
                                 3, nick, nick_len);
   silc_buffer_free(nidp);
   if (oidp)
                                 3, nick, nick_len);
   silc_buffer_free(nidp);
   if (oidp)
@@ -813,7 +803,7 @@ silc_server_command_list_send_reply(SilcServerCommandContext cmd,
     /* Send the reply */
     silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_LIST,
                                   status, 0, ident, 4,
     /* Send the reply */
     silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_LIST,
                                   status, 0, ident, 4,
-                                  2, idp->data, idp->len,
+                                  2, idp->data, silc_buffer_len(idp),
                                   3, entry->channel_name,
                                   strlen(entry->channel_name),
                                   4, topic, topic ? strlen(topic) : 0,
                                   3, entry->channel_name,
                                   strlen(entry->channel_name),
                                   4, topic, topic ? strlen(topic) : 0,
@@ -847,7 +837,7 @@ silc_server_command_list_send_reply(SilcServerCommandContext cmd,
     /* Send the reply */
     silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_LIST,
                                   status, 0, ident, 4,
     /* Send the reply */
     silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_LIST,
                                   status, 0, ident, 4,
-                                  2, idp->data, idp->len,
+                                  2, idp->data, silc_buffer_len(idp),
                                   3, entry->channel_name,
                                   strlen(entry->channel_name),
                                   4, topic, topic ? strlen(topic) : 0,
                                   3, entry->channel_name,
                                   strlen(entry->channel_name),
                                   4, topic, topic ? strlen(topic) : 0,
@@ -864,9 +854,8 @@ SILC_SERVER_CMD_FUNC(list)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
+  SilcID id;
   SilcChannelID *channel_id = NULL;
   SilcChannelID *channel_id = NULL;
-  unsigned char *tmp;
-  SilcUInt32 tmp_len;
   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
   SilcUInt32 lch_count = 0, gch_count = 0;
 
   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
   SilcUInt32 lch_count = 0, gch_count = 0;
 
@@ -887,7 +876,7 @@ SILC_SERVER_CMD_FUNC(list)
     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                            SILC_PACKET_COMMAND, cmd->packet->flags,
     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                            SILC_PACKET_COMMAND, cmd->packet->flags,
-                           tmpbuf->data, tmpbuf->len, TRUE);
+                           tmpbuf->data, silc_buffer_len(tmpbuf));
 
     /* Reprocess this packet after received reply from router */
     silc_server_command_pending(server, SILC_COMMAND_LIST,
 
     /* Reprocess this packet after received reply from router */
     silc_server_command_pending(server, SILC_COMMAND_LIST,
@@ -901,15 +890,8 @@ SILC_SERVER_CMD_FUNC(list)
   }
 
   /* Get Channel ID */
   }
 
   /* Get Channel ID */
-  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
-  if (tmp) {
-    channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
-    if (!channel_id) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
-                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
-      goto out;
-    }
-  }
+  if (silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL))
+    channel_id = SILC_ID_GET_ID(id);
 
   /* Get the channels from local list */
   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
 
   /* Get the channels from local list */
   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
@@ -937,8 +919,8 @@ SILC_SERVER_CMD_FUNC(topic)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
-  SilcChannelID *channel_id;
+  SilcClientEntry client = silc_packet_get_context(cmd->sock);
+  SilcID id;
   SilcChannelEntry channel;
   SilcChannelClientEntry chl;
   SilcBuffer idp;
   SilcChannelEntry channel;
   SilcChannelClientEntry chl;
   SilcBuffer idp;
@@ -946,7 +928,7 @@ SILC_SERVER_CMD_FUNC(topic)
   SilcUInt32 argc, tmp_len;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
 
   SilcUInt32 argc, tmp_len;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+  if (client->data.conn_type != SILC_CONN_CLIENT || !client)
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
@@ -954,14 +936,7 @@ SILC_SERVER_CMD_FUNC(topic)
   argc = silc_argument_get_arg_num(cmd->args);
 
   /* Get Channel ID */
   argc = silc_argument_get_arg_num(cmd->args);
 
   /* Get Channel ID */
-  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
-  if (!tmp) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
-                                         SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
-    goto out;
-  }
-  channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
-  if (!channel_id) {
+  if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
     goto out;
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
     goto out;
@@ -969,11 +944,12 @@ SILC_SERVER_CMD_FUNC(topic)
 
   /* Check whether the channel exists */
   channel = silc_idlist_find_channel_by_id(server->local_list,
 
   /* Check whether the channel exists */
   channel = silc_idlist_find_channel_by_id(server->local_list,
-                                          channel_id, NULL);
+                                          SILC_ID_GET_ID(id), NULL);
   if (!channel) {
     channel = silc_idlist_find_channel_by_id(server->global_list,
   if (!channel) {
     channel = silc_idlist_find_channel_by_id(server->global_list,
-                                            channel_id, NULL);
+                                            SILC_ID_GET_ID(id), NULL);
     if (!channel) {
     if (!channel) {
+      tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
                                           0, 2, tmp, tmp_len);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
                                           0, 2, tmp, tmp_len);
@@ -983,22 +959,19 @@ SILC_SERVER_CMD_FUNC(topic)
 
   if (argc > 1) {
     /* Get the topic */
 
   if (argc > 1) {
     /* Get the topic */
-    tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
+    tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
     if (!tmp) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
                                            SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
                                            0);
       goto out;
     }
     if (!tmp) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
                                            SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
                                            0);
       goto out;
     }
-
-    if (strlen(tmp) > 256) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
-                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
-                                           0);
-      goto out;
+    if (tmp_len > 256) {
+      tmp_len = 256;
+      tmp[tmp_len - 1] = '\0';
     }
 
     }
 
-    if (!silc_utf8_valid(tmp, strlen(tmp))) {
+    if (!silc_utf8_valid(tmp, tmp_len)) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
                                            SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
                                            0);
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
                                            SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
                                            0);
@@ -1039,7 +1012,7 @@ SILC_SERVER_CMD_FUNC(topic)
       idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
                                         SILC_NOTIFY_TYPE_TOPIC_SET, 2,
       idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
                                         SILC_NOTIFY_TYPE_TOPIC_SET, 2,
-                                        idp->data, idp->len,
+                                        idp->data, silc_buffer_len(idp),
                                         channel->topic,
                                         strlen(channel->topic));
       silc_buffer_free(idp);
                                         channel->topic,
                                         strlen(channel->topic));
       silc_buffer_free(idp);
@@ -1047,15 +1020,14 @@ SILC_SERVER_CMD_FUNC(topic)
   }
 
   /* Send the topic to client as reply packet */
   }
 
   /* Send the topic to client as reply packet */
-  idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
+  idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
   silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_TOPIC,
                                 SILC_STATUS_OK, 0, ident, 2,
   silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_TOPIC,
                                 SILC_STATUS_OK, 0, ident, 2,
-                                2, idp->data, idp->len,
+                                2, idp->data, silc_buffer_len(idp),
                                 3, channel->topic,
                                 channel->topic ?
                                 strlen(channel->topic) : 0);
   silc_buffer_free(idp);
                                 3, channel->topic,
                                 channel->topic ?
                                 strlen(channel->topic) : 0);
   silc_buffer_free(idp);
-  silc_free(channel_id);
 
  out:
   silc_server_command_free(cmd);
 
  out:
   silc_server_command_free(cmd);
@@ -1068,32 +1040,25 @@ SILC_SERVER_CMD_FUNC(invite)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcSocketConnection sock = cmd->sock, dest_sock;
+  SilcPacketStream sock = cmd->sock, dest_sock;
   SilcChannelClientEntry chl;
   SilcClientEntry sender, dest;
   SilcChannelClientEntry chl;
   SilcClientEntry sender, dest;
-  SilcClientID *dest_id = NULL;
   SilcChannelEntry channel;
   SilcChannelEntry channel;
-  SilcChannelID *channel_id = NULL;
+  SilcID id, id2;
   SilcIDListData idata;
   SilcArgumentPayload args;
   SilcHashTableList htl;
   SilcBuffer list, tmp2;
   SilcBufferStruct alist;
   unsigned char *tmp, *atype = NULL;
   SilcIDListData idata;
   SilcArgumentPayload args;
   SilcHashTableList htl;
   SilcBuffer list, tmp2;
   SilcBufferStruct alist;
   unsigned char *tmp, *atype = NULL;
-  SilcUInt32 len, type, len2;
+  SilcUInt32 len, len2, ttype;
+  void *type;
   SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
 
   /* Get Channel ID */
   SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
 
   /* Get Channel ID */
-  tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
-  if (!tmp) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
-                                         SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
-    goto out;
-  }
-  channel_id = silc_id_payload_parse_id(tmp, len, NULL);
-  if (!channel_id) {
+  if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
     goto out;
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
     goto out;
@@ -1101,11 +1066,12 @@ SILC_SERVER_CMD_FUNC(invite)
 
   /* Get the channel entry */
   channel = silc_idlist_find_channel_by_id(server->local_list,
 
   /* Get the channel entry */
   channel = silc_idlist_find_channel_by_id(server->local_list,
-                                          channel_id, NULL);
+                                          SILC_ID_GET_ID(id), NULL);
   if (!channel) {
     channel = silc_idlist_find_channel_by_id(server->global_list,
   if (!channel) {
     channel = silc_idlist_find_channel_by_id(server->global_list,
-                                            channel_id, NULL);
+                                            SILC_ID_GET_ID(id), NULL);
     if (!channel) {
     if (!channel) {
+      tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
                                           0, 2, tmp, len);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
                                           0, 2, tmp, len);
@@ -1114,8 +1080,9 @@ SILC_SERVER_CMD_FUNC(invite)
   }
 
   /* Check whether the sender of this command is on the channel. */
   }
 
   /* Check whether the sender of this command is on the channel. */
-  sender = (SilcClientEntry)sock->user_data;
+  sender = silc_packet_get_context(sock);
   if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
   if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
+    tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
                                         SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
                                         2, tmp, len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
                                         SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
                                         2, tmp, len);
@@ -1127,6 +1094,7 @@ SILC_SERVER_CMD_FUNC(invite)
   if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
       !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
   if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
       !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
+    tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV,
                                         0, 2, tmp, len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV,
                                         0, 2, tmp, len);
@@ -1134,21 +1102,15 @@ SILC_SERVER_CMD_FUNC(invite)
   }
 
   /* Get destination client ID */
   }
 
   /* Get destination client ID */
-  tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
-  if (tmp) {
-    bool resolve;
-
-    dest_id = silc_id_payload_parse_id(tmp, len, NULL);
-    if (!dest_id) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
-                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
-      goto out;
-    }
+  if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id2, NULL)) {
+    SilcBool resolve;
 
     /* Get the client entry */
 
     /* Get the client entry */
-    dest = silc_server_query_client(server, dest_id, FALSE, &resolve);
+    dest = silc_server_query_client(server, SILC_ID_GET_ID(id2),
+                                   FALSE, &resolve);
     if (!dest) {
       if (server->server_type != SILC_SERVER || !resolve || cmd->pending) {
     if (!dest) {
       if (server->server_type != SILC_SERVER || !resolve || cmd->pending) {
+       tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
        silc_server_command_send_status_data(
                                        cmd, SILC_COMMAND_INVITE,
                                        SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
        silc_server_command_send_status_data(
                                        cmd, SILC_COMMAND_INVITE,
                                        SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
@@ -1168,6 +1130,7 @@ SILC_SERVER_CMD_FUNC(invite)
 
     /* Check whether the requested client is already on the channel. */
     if (silc_server_client_on_channel(dest, channel, NULL)) {
 
     /* Check whether the requested client is already on the channel. */
     if (silc_server_client_on_channel(dest, channel, NULL)) {
+      tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
       atype = silc_argument_get_arg_type(cmd->args, 1, &len2);
       silc_server_command_send_status_data2(cmd, SILC_COMMAND_INVITE,
                                            SILC_STATUS_ERR_USER_ON_CHANNEL,
       atype = silc_argument_get_arg_type(cmd->args, 1, &len2);
       silc_server_command_send_status_data2(cmd, SILC_COMMAND_INVITE,
                                            SILC_STATUS_ERR_USER_ON_CHANNEL,
@@ -1177,9 +1140,11 @@ SILC_SERVER_CMD_FUNC(invite)
     }
 
     /* Get route to the client */
     }
 
     /* Get route to the client */
-    dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
+    dest_sock = silc_server_get_client_route(server, NULL, 0,
+                                            SILC_ID_GET_ID(id2),
                                             &idata, NULL);
     if (!dest_sock) {
                                             &idata, NULL);
     if (!dest_sock) {
+      tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
                                           0, 2, tmp, len);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
                                           0, 2, tmp, len);
@@ -1196,9 +1161,10 @@ SILC_SERVER_CMD_FUNC(invite)
                              silc_server_inviteban_destruct, channel, TRUE);
 
     /* Check if the ID is in the list already */
                              silc_server_inviteban_destruct, channel, TRUE);
 
     /* Check if the ID is in the list already */
+    tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
     silc_hash_table_list(channel->invite_list, &htl);
     while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
     silc_hash_table_list(channel->invite_list, &htl);
     while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
-      if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
+      if (SILC_PTR_TO_32(type) == 3 && !memcmp(tmp2->data, tmp, len)) {
        tmp = NULL;
        break;
       }
        tmp = NULL;
        break;
       }
@@ -1215,15 +1181,15 @@ SILC_SERVER_CMD_FUNC(invite)
     if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
       /* Send notify to the client that is invited to the channel */
       SilcBuffer idp, idp2;
     if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
       /* Send notify to the client that is invited to the channel */
       SilcBuffer idp, idp2;
-      idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
+      idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
       idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
       idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
-      silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
-                                  SILC_ID_CLIENT,
+      silc_server_send_notify_dest(server, dest_sock, FALSE,
+                                  SILC_ID_GET_ID(id2), SILC_ID_CLIENT,
                                   SILC_NOTIFY_TYPE_INVITE, 3,
                                   SILC_NOTIFY_TYPE_INVITE, 3,
-                                  idp->data, idp->len,
+                                  idp->data, silc_buffer_len(idp),
                                   channel->channel_name,
                                   strlen(channel->channel_name),
                                   channel->channel_name,
                                   strlen(channel->channel_name),
-                                  idp2->data, idp2->len);
+                                  idp2->data, silc_buffer_len(idp2));
       silc_buffer_free(idp);
       silc_buffer_free(idp2);
     }
       silc_buffer_free(idp);
       silc_buffer_free(idp2);
     }
@@ -1286,8 +1252,9 @@ SILC_SERVER_CMD_FUNC(invite)
                       SILC_STR_END);
     silc_hash_table_list(channel->invite_list, &htl);
     while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
                       SILC_STR_END);
     silc_hash_table_list(channel->invite_list, &htl);
     while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
-      list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
-                                             type);
+      list = silc_argument_payload_encode_one(list, tmp2->data,
+                                             silc_buffer_len(tmp2),
+                                             SILC_PTR_TO_32(type));
     silc_hash_table_list_reset(&htl);
   }
 
     silc_hash_table_list_reset(&htl);
   }
 
@@ -1298,17 +1265,17 @@ SILC_SERVER_CMD_FUNC(invite)
     /* Send to local servers if we are router */
     if (server->server_type == SILC_ROUTER) {
       SilcBuffer idp, idp2;
     /* Send to local servers if we are router */
     if (server->server_type == SILC_ROUTER) {
       SilcBuffer idp, idp2;
-      idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
+      idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
       idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
                                          SILC_NOTIFY_TYPE_INVITE, 5,
       idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
                                          SILC_NOTIFY_TYPE_INVITE, 5,
-                                        idp->data, idp->len,
+                                        idp->data, silc_buffer_len(idp),
                                         channel->channel_name,
                                         strlen(channel->channel_name),
                                         channel->channel_name,
                                         strlen(channel->channel_name),
-                                        idp2->data, idp2->len,
+                                        idp2->data, silc_buffer_len(idp2),
                                         atype, 1,
                                         tmp ? alist.data : NULL,
                                         atype, 1,
                                         tmp ? alist.data : NULL,
-                                        tmp ? alist.len : 0);
+                                        tmp ? silc_buffer_len(&alist) : 0);
       silc_buffer_free(idp);
       silc_buffer_free(idp2);
     }
       silc_buffer_free(idp);
       silc_buffer_free(idp2);
     }
@@ -1322,31 +1289,29 @@ SILC_SERVER_CMD_FUNC(invite)
 
   /* Send invite list back only if the list was modified, or no arguments
      was given. */
 
   /* Send invite list back only if the list was modified, or no arguments
      was given. */
-  type = 0;
+  ttype = 0;
   argc = silc_argument_get_arg_num(cmd->args);
   if (argc == 1)
   argc = silc_argument_get_arg_num(cmd->args);
   if (argc == 1)
-    type = 1;
+    ttype = 1;
   if (silc_argument_get_arg_type(cmd->args, 3, &len))
   if (silc_argument_get_arg_type(cmd->args, 3, &len))
-    type = 1;
+    ttype = 1;
 
   /* Send command reply */
   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_INVITE,
                                 SILC_STATUS_OK, 0, ident, 2,
                                 2, tmp, len,
 
   /* Send command reply */
   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_INVITE,
                                 SILC_STATUS_OK, 0, ident, 2,
                                 2, tmp, len,
-                                3, type && list ?
+                                3, ttype && list ?
                                 list->data : NULL,
                                 list->data : NULL,
-                                type && list ? list->len : 0);
+                                ttype && list ? silc_buffer_len(list) : 0);
   silc_buffer_free(list);
 
  out:
   silc_buffer_free(list);
 
  out:
-  silc_free(dest_id);
-  silc_free(channel_id);
   silc_server_command_free(cmd);
 }
 
 typedef struct {
   silc_server_command_free(cmd);
 }
 
 typedef struct {
-  SilcSocketConnection sock;
+  SilcPacketStream sock;
   char *signoff;
 } *QuitInternal;
 
   char *signoff;
 } *QuitInternal;
 
@@ -1357,20 +1322,16 @@ SILC_TASK_CALLBACK(silc_server_command_quit_cb)
 {
   SilcServer server = app_context;
   QuitInternal q = (QuitInternal)context;
 {
   SilcServer server = app_context;
   QuitInternal q = (QuitInternal)context;
+  SilcClientEntry client = silc_packet_get_context(q->sock);
 
 
-  if (q->sock->user_data) {
+  if (client) {
     /* Free all client specific data, such as client entry and entires
        on channels this client may be on. */
     /* Free all client specific data, such as client entry and entires
        on channels this client may be on. */
-    silc_server_free_client_data(server, q->sock, q->sock->user_data,
-                                TRUE, q->signoff);
-    q->sock->user_data = NULL;
-  }
-
-  if (!SILC_IS_DISCONNECTED(q->sock))
-    /* Close the connection on our side */
+    silc_server_free_sock_user_data(server, q->sock, q->signoff);
     silc_server_close_connection(server, q->sock);
     silc_server_close_connection(server, q->sock);
+  }
 
 
-  silc_socket_free(q->sock);
+  silc_packet_stream_unref(q->sock);
   silc_free(q->signoff);
   silc_free(q);
 }
   silc_free(q->signoff);
   silc_free(q);
 }
@@ -1381,14 +1342,15 @@ SILC_SERVER_CMD_FUNC(quit)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcSocketConnection sock = cmd->sock;
+  SilcPacketStream sock = cmd->sock;
+  SilcClientEntry client = silc_packet_get_context(sock);
   QuitInternal q;
   unsigned char *tmp = NULL;
   SilcUInt32 len = 0;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
 
   QuitInternal q;
   unsigned char *tmp = NULL;
   SilcUInt32 len = 0;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+  if (client->data.conn_type != SILC_CONN_CLIENT)
     goto out;
 
   /* Get message */
     goto out;
 
   /* Get message */
@@ -1397,13 +1359,14 @@ SILC_SERVER_CMD_FUNC(quit)
     tmp = NULL;
 
   q = silc_calloc(1, sizeof(*q));
     tmp = NULL;
 
   q = silc_calloc(1, sizeof(*q));
-  q->sock = silc_socket_dup(sock);
+  q->sock = sock;
   q->signoff = tmp ? strdup(tmp) : NULL;
   q->signoff = tmp ? strdup(tmp) : NULL;
+  silc_packet_stream_ref(q->sock);
 
   /* We quit the connection with little timeout */
 
   /* We quit the connection with little timeout */
-  silc_schedule_task_add(server->schedule, sock->sock,
-                        silc_server_command_quit_cb, (void *)q,
-                        0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+  silc_schedule_task_add_timeout(server->schedule,
+                                silc_server_command_quit_cb, (void *)q,
+                                0, 200000);
 
  out:
   silc_server_command_free(cmd);
 
  out:
   silc_server_command_free(cmd);
@@ -1416,15 +1379,15 @@ SILC_SERVER_CMD_FUNC(kill)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcClientEntry client = silc_packet_get_context(cmd->sock);
   SilcClientEntry remote_client;
   SilcClientEntry remote_client;
-  SilcClientID *client_id = NULL;
+  SilcID id;
   unsigned char *tmp, *comment, *auth;
   SilcUInt32 tmp_len, tmp_len2, auth_len;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 3);
 
   unsigned char *tmp, *comment, *auth;
   SilcUInt32 tmp_len, tmp_len2, auth_len;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 3);
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+  if (client->data.conn_type != SILC_CONN_CLIENT || !client)
     goto out;
 
   /* Get authentication payload if present */
     goto out;
 
   /* Get authentication payload if present */
@@ -1449,28 +1412,22 @@ SILC_SERVER_CMD_FUNC(kill)
   }
 
   /* Get the client ID */
   }
 
   /* Get the client ID */
-  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
-  if (!tmp) {
+  if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
-                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
-                                         0);
-    goto out;
-  }
-  client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
-  if (!client_id) {
-    silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
-                                        SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
-                                        0, 2, tmp, tmp_len);
+                                         SILC_STATUS_ERR_NO_CLIENT_ID, 0);
     goto out;
   }
 
   /* Get the client entry */
   remote_client = silc_idlist_find_client_by_id(server->local_list,
     goto out;
   }
 
   /* Get the client entry */
   remote_client = silc_idlist_find_client_by_id(server->local_list,
-                                               client_id, TRUE, NULL);
+                                               SILC_ID_GET_ID(id),
+                                               TRUE, NULL);
   if (!remote_client) {
     remote_client = silc_idlist_find_client_by_id(server->global_list,
   if (!remote_client) {
     remote_client = silc_idlist_find_client_by_id(server->global_list,
-                                                 client_id, TRUE, NULL);
+                                                 SILC_ID_GET_ID(id),
+                                                 TRUE, NULL);
     if (!remote_client) {
     if (!remote_client) {
+      tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
                                           0, 2, tmp, tmp_len);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
                                           0, 2, tmp, tmp_len);
@@ -1482,13 +1439,13 @@ SILC_SERVER_CMD_FUNC(kill)
   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
   if (comment && tmp_len2 > 128) {
     tmp_len2 = 128;
   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
   if (comment && tmp_len2 > 128) {
     tmp_len2 = 128;
-    comment[127] = '\0';
+    comment[tmp_len2 - 1] = '\0';
   }
 
   /* If authentication data is provided then verify that killing is
      actually allowed */
   if (auth && auth_len) {
   }
 
   /* If authentication data is provided then verify that killing is
      actually allowed */
   if (auth && auth_len) {
-    SilcSocketConnection sock;
+    SilcPacketStream sock;
 
     if (!SILC_IS_LOCAL(remote_client) || !remote_client->data.public_key) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
 
     if (!SILC_IS_LOCAL(remote_client) || !remote_client->data.public_key) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
@@ -1508,23 +1465,31 @@ SILC_SERVER_CMD_FUNC(kill)
     }
 
     /* Send reply to the sender */
     }
 
     /* Send reply to the sender */
+    tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
                                         SILC_STATUS_OK, 0,
                                         2, tmp, tmp_len);
 
     /* Do normal signoff for the destination client */
     sock = remote_client->connection;
     silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
                                         SILC_STATUS_OK, 0,
                                         2, tmp, tmp_len);
 
     /* Do normal signoff for the destination client */
     sock = remote_client->connection;
+
+    if (sock)
+      silc_packet_stream_ref(sock);
+
     silc_server_remove_from_channels(server, NULL, remote_client,
                                     TRUE, (char *)"Killed", TRUE, TRUE);
     silc_server_remove_from_channels(server, NULL, remote_client,
                                     TRUE, (char *)"Killed", TRUE, TRUE);
-    silc_server_free_client_data(server, NULL, remote_client, TRUE,
-                                comment ? comment :
-                                (unsigned char *)"Killed");
-    if (sock)
+    silc_server_free_sock_user_data(server, sock, comment ? comment :
+                                   (unsigned char *)"Killed");
+    if (sock) {
+      silc_packet_set_context(sock, NULL);
       silc_server_close_connection(server, sock);
       silc_server_close_connection(server, sock);
+      silc_packet_stream_unref(sock);
+    }
   } else {
     /* Router operator killing */
 
     /* Send reply to the sender */
   } else {
     /* Router operator killing */
 
     /* Send reply to the sender */
+    tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
                                         SILC_STATUS_OK, 0,
                                         2, tmp, tmp_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
                                         SILC_STATUS_OK, 0,
                                         2, tmp, tmp_len);
@@ -1540,7 +1505,6 @@ SILC_SERVER_CMD_FUNC(kill)
   }
 
  out:
   }
 
  out:
-  silc_free(client_id);
   silc_server_command_free(cmd);
 }
 
   silc_server_command_free(cmd);
 }
 
@@ -1558,7 +1522,7 @@ SILC_SERVER_CMD_FUNC(info)
   char *dest_server = NULL, *server_info = NULL, *server_name;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   SilcServerEntry entry = NULL;
   char *dest_server = NULL, *server_info = NULL, *server_name;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   SilcServerEntry entry = NULL;
-  SilcServerID *server_id = NULL;
+  SilcID id;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
 
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
 
@@ -1576,24 +1540,15 @@ SILC_SERVER_CMD_FUNC(info)
   }
 
   /* Get Server ID */
   }
 
   /* Get Server ID */
-  tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
-  if (tmp) {
-    server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
-    if (!server_id) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
-                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
-      goto out;
-    }
-  }
-
-  if (server_id) {
+  if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL)) {
     /* Check whether we have this server cached */
     entry = silc_idlist_find_server_by_id(server->local_list,
     /* Check whether we have this server cached */
     entry = silc_idlist_find_server_by_id(server->local_list,
-                                         server_id, TRUE, NULL);
+                                         SILC_ID_GET_ID(id), TRUE, NULL);
     if (!entry) {
       entry = silc_idlist_find_server_by_id(server->global_list,
     if (!entry) {
       entry = silc_idlist_find_server_by_id(server->global_list,
-                                           server_id, TRUE, NULL);
+                                           SILC_ID_GET_ID(id), TRUE, NULL);
       if (!entry && server->server_type != SILC_SERVER) {
       if (!entry && server->server_type != SILC_SERVER) {
+       tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
        silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
                                             0, 2, tmp, tmp_len);
        silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
                                             0, 2, tmp, tmp_len);
@@ -1602,12 +1557,7 @@ SILC_SERVER_CMD_FUNC(info)
     }
   }
 
     }
   }
 
-  /* Some buggy servers has sent request to router about themselves. */
-  if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
-    goto out;
-
-  if ((!dest_server && !server_id && !entry) || (entry &&
-                                                entry == server->id_entry) ||
+  if ((!dest_server && !entry) || (entry && entry == server->id_entry) ||
       (dest_server && !cmd->pending &&
        !memcmp(dest_server, server->server_name, strlen(dest_server)))) {
     /* Send our reply */
       (dest_server && !cmd->pending &&
        !memcmp(dest_server, server->server_name, strlen(dest_server)))) {
     /* Send our reply */
@@ -1649,7 +1599,7 @@ SILC_SERVER_CMD_FUNC(info)
 
       silc_server_packet_send(server, entry->connection,
                              SILC_PACKET_COMMAND, cmd->packet->flags,
 
       silc_server_packet_send(server, entry->connection,
                              SILC_PACKET_COMMAND, cmd->packet->flags,
-                             tmpbuf->data, tmpbuf->len, TRUE);
+                             tmpbuf->data, silc_buffer_len(tmpbuf));
 
       /* Reprocess this packet after received reply from router */
       silc_server_command_pending(server, SILC_COMMAND_INFO,
 
       /* Reprocess this packet after received reply from router */
       silc_server_command_pending(server, SILC_COMMAND_INFO,
@@ -1676,7 +1626,7 @@ SILC_SERVER_CMD_FUNC(info)
 
       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                              SILC_PACKET_COMMAND, cmd->packet->flags,
 
       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                              SILC_PACKET_COMMAND, cmd->packet->flags,
-                             tmpbuf->data, tmpbuf->len, TRUE);
+                             tmpbuf->data, silc_buffer_len(tmpbuf));
 
       /* Reprocess this packet after received reply from router */
       silc_server_command_pending(server, SILC_COMMAND_INFO,
 
       /* Reprocess this packet after received reply from router */
       silc_server_command_pending(server, SILC_COMMAND_INFO,
@@ -1690,8 +1640,6 @@ SILC_SERVER_CMD_FUNC(info)
     }
   }
 
     }
   }
 
-  silc_free(server_id);
-
   if (!entry) {
     if (dest_server) {
       silc_free(dest_server);
   if (!entry) {
     if (dest_server) {
       silc_free(dest_server);
@@ -1713,7 +1661,7 @@ SILC_SERVER_CMD_FUNC(info)
   /* Send the reply */
   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_INFO,
                                 SILC_STATUS_OK, 0, ident, 3,
   /* Send the reply */
   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_INFO,
                                 SILC_STATUS_OK, 0, ident, 3,
-                                2, idp->data, idp->len,
+                                2, idp->data, silc_buffer_len(idp),
                                 3, server_name,
                                 strlen(server_name),
                                 4, server_info,
                                 3, server_name,
                                 strlen(server_name),
                                 4, server_info,
@@ -1734,27 +1682,24 @@ SILC_SERVER_CMD_FUNC(ping)
   SilcServer server = cmd->server;
   SilcUInt32 tmp_len;
   unsigned char *tmp;
   SilcServer server = cmd->server;
   SilcUInt32 tmp_len;
   unsigned char *tmp;
-  SilcServerID *server_id = NULL;
+  SilcID id;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PING, cmd, 1, 1);
 
   /* Get Server ID */
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PING, cmd, 1, 1);
 
   /* Get Server ID */
-  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
-  if (!tmp) {
+  if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
                                          0);
     goto out;
   }
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
                                          0);
     goto out;
   }
-  server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
-  if (!server_id)
-    goto out;
 
 
-  if (SILC_ID_SERVER_COMPARE(server_id, server->id)) {
+  if (SILC_ID_SERVER_COMPARE(SILC_ID_GET_ID(id), server->id)) {
     /* Send our reply */
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
                                          SILC_STATUS_OK, 0);
   } else {
     /* Send our reply */
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
                                          SILC_STATUS_OK, 0);
   } else {
+    tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_PING,
                                         SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
                                         2, tmp, tmp_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_PING,
                                         SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
                                         2, tmp, tmp_len);
@@ -1762,7 +1707,6 @@ SILC_SERVER_CMD_FUNC(ping)
   }
 
  out:
   }
 
  out:
-  silc_free(server_id);
   silc_server_command_free(cmd);
 }
 
   silc_server_command_free(cmd);
 }
 
@@ -1772,7 +1716,7 @@ SILC_SERVER_CMD_FUNC(stats)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcServerID *server_id;
+  SilcID id;
   unsigned char *tmp;
   SilcUInt32 tmp_len;
   SilcBuffer packet, stats;
   unsigned char *tmp;
   SilcUInt32 tmp_len;
   SilcBuffer packet, stats;
@@ -1782,25 +1726,23 @@ SILC_SERVER_CMD_FUNC(stats)
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
 
   /* Get Server ID */
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
 
   /* Get Server ID */
-  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
-  if (!tmp) {
+  if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_STATS,
                                          SILC_STATUS_ERR_NO_SERVER_ID, 0);
     goto out;
   }
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_STATS,
                                          SILC_STATUS_ERR_NO_SERVER_ID, 0);
     goto out;
   }
-  server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
-  if (!server_id)
-    goto out;
+
+  SILC_LOG_DEBUG(("id %s", silc_id_render(SILC_ID_GET_ID(id),
+                                         id.type)));
 
   /* The ID must be ours */
 
   /* The ID must be ours */
-  if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
+  if (!SILC_ID_SERVER_COMPARE(server->id, SILC_ID_GET_ID(id))) {
+    tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_STATS,
                                         SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
                                         2, tmp, tmp_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_STATS,
                                         SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
                                         2, tmp, tmp_len);
-    silc_free(server_id);
     goto out;
   }
     goto out;
   }
-  silc_free(server_id);
 
   /* If we are router then just send everything we got. If we are normal
      server then we'll send this to our router to get all the latest
 
   /* If we are router then just send everything we got. If we are normal
      server then we'll send this to our router to get all the latest
@@ -1817,10 +1759,11 @@ SILC_SERVER_CMD_FUNC(stats)
                                 SILC_ID_SERVER);
     packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
                                            ++server->cmd_ident, 1,
                                 SILC_ID_SERVER);
     packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
                                            ++server->cmd_ident, 1,
-                                           1, idp->data, idp->len);
+                                           1, idp->data,
+                                           silc_buffer_len(idp));
     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                            SILC_PACKET_COMMAND, 0, packet->data,
     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                            SILC_PACKET_COMMAND, 0, packet->data,
-                           packet->len, FALSE);
+                           silc_buffer_len(packet));
 
     /* Reprocess this packet after received reply from router */
     silc_server_command_pending(server, SILC_COMMAND_STATS,
 
     /* Reprocess this packet after received reply from router */
     silc_server_command_pending(server, SILC_COMMAND_STATS,
@@ -1855,10 +1798,11 @@ SILC_SERVER_CMD_FUNC(stats)
                     SILC_STR_UI_INT(server->stat.router_ops),
                     SILC_STR_END);
 
                     SILC_STR_UI_INT(server->stat.router_ops),
                     SILC_STR_END);
 
+  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_STATS,
                                 SILC_STATUS_OK, 0, ident, 2,
                                 2, tmp, tmp_len,
   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_STATS,
                                 SILC_STATUS_OK, 0, ident, 2,
                                 2, tmp, tmp_len,
-                                3, stats->data, stats->len);
+                                3, stats->data, silc_buffer_len(stats));
   silc_buffer_free(stats);
 
  out:
   silc_buffer_free(stats);
 
  out:
@@ -1873,15 +1817,16 @@ static void silc_server_command_join_channel(SilcServer server,
                                             SilcServerCommandContext cmd,
                                             SilcChannelEntry channel,
                                             SilcClientID *client_id,
                                             SilcServerCommandContext cmd,
                                             SilcChannelEntry channel,
                                             SilcClientID *client_id,
-                                            bool created,
-                                            bool create_key,
+                                            SilcBool created,
+                                            SilcBool create_key,
                                             SilcUInt32 umode,
                                             const unsigned char *auth,
                                             SilcUInt32 auth_len,
                                             const unsigned char *cauth,
                                             SilcUInt32 cauth_len)
 {
                                             SilcUInt32 umode,
                                             const unsigned char *auth,
                                             SilcUInt32 auth_len,
                                             const unsigned char *cauth,
                                             SilcUInt32 cauth_len)
 {
-  SilcSocketConnection sock = cmd->sock;
+  SilcPacketStream sock = cmd->sock;
+  SilcIDListData idata = silc_packet_get_context(sock);
   unsigned char *tmp;
   SilcUInt32 tmp_len, user_count;
   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4], ulimit[4];
   unsigned char *tmp;
   SilcUInt32 tmp_len, user_count;
   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4], ulimit[4];
@@ -1891,19 +1836,23 @@ static void silc_server_command_join_channel(SilcServer server,
   SilcBuffer user_list, mode_list, invite_list, ban_list;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   char check[512], check2[512];
   SilcBuffer user_list, mode_list, invite_list, ban_list;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   char check[512], check2[512];
-  bool founder = FALSE;
-  bool resolve;
+  void *plen;
+  SilcBool founder = FALSE;
+  SilcBool resolve;
   SilcBuffer fkey = NULL, chpklist = NULL;
   SilcBuffer fkey = NULL, chpklist = NULL;
-  const char *cipher;
+  const char *cipher, *hostname, *ip;
 
   SILC_LOG_DEBUG(("Joining client to channel"));
 
   if (!channel)
     return;
 
 
   SILC_LOG_DEBUG(("Joining client to channel"));
 
   if (!channel)
     return;
 
+  silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
+                             NULL, &hostname, &ip, NULL);
+
   /* Get the client entry */
   /* Get the client entry */
-  if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
-    client = (SilcClientEntry)sock->user_data;
+  if (idata->conn_type == SILC_CONN_CLIENT) {
+    client = (SilcClientEntry)idata;
     if (!client)
       return;
   } else {
     if (!client)
       return;
   } else {
@@ -1940,7 +1889,7 @@ static void silc_server_command_join_channel(SilcServer server,
       clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
       silc_server_send_command(server, cmd->sock,
                               SILC_COMMAND_GETKEY, ++server->cmd_ident,
       clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
       silc_server_send_command(server, cmd->sock,
                               SILC_COMMAND_GETKEY, ++server->cmd_ident,
-                              1, 1, clidp->data, clidp->len);
+                              1, 1, clidp->data, silc_buffer_len(clidp));
       silc_buffer_free(clidp);
       silc_server_command_pending(server, SILC_COMMAND_GETKEY,
                                  server->cmd_ident,
       silc_buffer_free(clidp);
       silc_server_command_pending(server, SILC_COMMAND_GETKEY,
                                  server->cmd_ident,
@@ -2004,7 +1953,7 @@ static void silc_server_command_join_channel(SilcServer server,
     if (!strchr(client->username, '@')) {
       silc_strncat(check, sizeof(check), "@", 1);
       silc_strncat(check, sizeof(check),
     if (!strchr(client->username, '@')) {
       silc_strncat(check, sizeof(check), "@", 1);
       silc_strncat(check, sizeof(check),
-                  cmd->sock->hostname, strlen(cmd->sock->hostname));
+                  hostname, strlen(hostname));
     }
 
     silc_strncat(check2, sizeof(check2),
     }
 
     silc_strncat(check2, sizeof(check2),
@@ -2023,7 +1972,7 @@ static void silc_server_command_join_channel(SilcServer server,
     if (!strchr(client->username, '@')) {
       silc_strncat(check2, sizeof(check2), "@", 1);
       silc_strncat(check2, sizeof(check2),
     if (!strchr(client->username, '@')) {
       silc_strncat(check2, sizeof(check2), "@", 1);
       silc_strncat(check2, sizeof(check2),
-                  cmd->sock->hostname, strlen(cmd->sock->hostname));
+                  hostname, strlen(hostname));
     }
 
     /* Check invite list if channel is invite-only channel */
     }
 
     /* Check invite list if channel is invite-only channel */
@@ -2043,7 +1992,8 @@ static void silc_server_command_join_channel(SilcServer server,
        chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
        silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
                                             SILC_STATUS_ERR_NOT_INVITED, 0,
        chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
        silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
                                             SILC_STATUS_ERR_NOT_INVITED, 0,
-                                            2, chidp->data, chidp->len);
+                                            2, chidp->data,
+                                            silc_buffer_len(chidp));
        silc_buffer_free(chidp);
        goto out;
       }
        silc_buffer_free(chidp);
        goto out;
       }
@@ -2067,7 +2017,8 @@ static void silc_server_command_join_channel(SilcServer server,
        silc_server_command_send_status_data(
                                      cmd, SILC_COMMAND_JOIN,
                                      SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0,
        silc_server_command_send_status_data(
                                      cmd, SILC_COMMAND_JOIN,
                                      SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0,
-                                     2, chidp->data, chidp->len);
+                                     2, chidp->data,
+                                     silc_buffer_len(chidp));
        silc_buffer_free(chidp);
        goto out;
       }
        silc_buffer_free(chidp);
        goto out;
       }
@@ -2080,7 +2031,8 @@ static void silc_server_command_join_channel(SilcServer server,
        chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
        silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
                                             SILC_STATUS_ERR_CHANNEL_IS_FULL,
        chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
        silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
                                             SILC_STATUS_ERR_CHANNEL_IS_FULL,
-                                            0, 2, chidp->data, chidp->len);
+                                            0, 2, chidp->data,
+                                            silc_buffer_len(chidp));
        silc_buffer_free(chidp);
        goto out;
       }
        silc_buffer_free(chidp);
        goto out;
       }
@@ -2100,7 +2052,8 @@ static void silc_server_command_join_channel(SilcServer server,
       chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
                                           SILC_STATUS_ERR_BAD_PASSWORD, 0,
       chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
                                           SILC_STATUS_ERR_BAD_PASSWORD, 0,
-                                          2, chidp->data, chidp->len);
+                                          2, chidp->data,
+                                          silc_buffer_len(chidp));
       silc_buffer_free(chidp);
       goto out;
     }
       silc_buffer_free(chidp);
       goto out;
     }
@@ -2126,8 +2079,10 @@ static void silc_server_command_join_channel(SilcServer server,
     chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
     silc_server_command_send_status_data2(cmd, SILC_COMMAND_JOIN,
                                          SILC_STATUS_ERR_USER_ON_CHANNEL, 0,
     chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
     silc_server_command_send_status_data2(cmd, SILC_COMMAND_JOIN,
                                          SILC_STATUS_ERR_USER_ON_CHANNEL, 0,
-                                         2, clidp->data, clidp->len,
-                                         3, chidp->data, chidp->len);
+                                         2, clidp->data,
+                                         silc_buffer_len(clidp),
+                                         3, chidp->data,
+                                         silc_buffer_len(chidp));
     silc_buffer_free(clidp);
     silc_buffer_free(chidp);
     goto out;
     silc_buffer_free(clidp);
     silc_buffer_free(chidp);
     goto out;
@@ -2174,18 +2129,17 @@ static void silc_server_command_join_channel(SilcServer server,
     SILC_PUT32_MSB(channel->user_limit, ulimit);
 
   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
     SILC_PUT32_MSB(channel->user_limit, ulimit);
 
   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
-    tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
-    cipher = silc_cipher_get_name(channel->channel_key);
-    keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
-                                                          SILC_ID_CHANNEL),
-                                          tmp,
+    unsigned char cid[32];
+    SilcUInt32 cid_len;
+    silc_id_id2str(channel->id, SILC_ID_CHANNEL, cid, sizeof(cid), &cid_len);
+    cipher = silc_cipher_get_name(channel->send_key);
+    keyp = silc_channel_key_payload_encode(cid_len, cid,
                                           strlen(cipher), cipher,
                                           channel->key_len / 8, channel->key);
                                           strlen(cipher), cipher,
                                           channel->key_len / 8, channel->key);
-    silc_free(tmp);
   }
 
   if (channel->founder_key)
   }
 
   if (channel->founder_key)
-    fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
+    fkey = silc_public_key_payload_encode(channel->founder_key);
 
   /* Encode invite list */
   invite_list = NULL;
 
   /* Encode invite list */
   invite_list = NULL;
@@ -2199,10 +2153,11 @@ static void silc_server_command_join_channel(SilcServer server,
                       SILC_STR_END);
 
     silc_hash_table_list(channel->invite_list, &htl);
                       SILC_STR_END);
 
     silc_hash_table_list(channel->invite_list, &htl);
-    while (silc_hash_table_get(&htl, (void *)&tmp_len, (void *)&reply))
+    while (silc_hash_table_get(&htl, (void *)&plen, (void *)&reply))
       invite_list = silc_argument_payload_encode_one(invite_list,
                                                     reply->data,
       invite_list = silc_argument_payload_encode_one(invite_list,
                                                     reply->data,
-                                                    reply->len, tmp_len);
+                                                    silc_buffer_len(reply),
+                                                    SILC_PTR_TO_32(plen));
     silc_hash_table_list_reset(&htl);
   }
 
     silc_hash_table_list_reset(&htl);
   }
 
@@ -2218,10 +2173,11 @@ static void silc_server_command_join_channel(SilcServer server,
                       SILC_STR_END);
 
     silc_hash_table_list(channel->ban_list, &htl);
                       SILC_STR_END);
 
     silc_hash_table_list(channel->ban_list, &htl);
-    while (silc_hash_table_get(&htl, (void *)&tmp_len, (void *)&reply))
+    while (silc_hash_table_get(&htl, (void *)&plen, (void *)&reply))
       ban_list = silc_argument_payload_encode_one(ban_list,
                                                  reply->data,
       ban_list = silc_argument_payload_encode_one(ban_list,
                                                  reply->data,
-                                                 reply->len, tmp_len);
+                                                 silc_buffer_len(reply),
+                                                 SILC_PTR_TO_32(plen));
     silc_hash_table_list_reset(&htl);
   }
 
     silc_hash_table_list_reset(&htl);
   }
 
@@ -2233,17 +2189,21 @@ static void silc_server_command_join_channel(SilcServer server,
                                         SILC_STATUS_OK, 0, ident, 16,
                                         2, channel->channel_name,
                                         strlen(channel->channel_name),
                                         SILC_STATUS_OK, 0, ident, 16,
                                         2, channel->channel_name,
                                         strlen(channel->channel_name),
-                                        3, chidp->data, chidp->len,
-                                        4, clidp->data, clidp->len,
+                                        3, chidp->data,
+                                        silc_buffer_len(chidp),
+                                        4, clidp->data,
+                                        silc_buffer_len(clidp),
                                         5, mode, 4,
                                         6, tmp2, 4,
                                         7, keyp ? keyp->data : NULL,
                                         5, mode, 4,
                                         6, tmp2, 4,
                                         7, keyp ? keyp->data : NULL,
-                                        keyp ? keyp->len : 0,
+                                        keyp ? silc_buffer_len(keyp) : 0,
                                         8, ban_list ? ban_list->data : NULL,
                                         8, ban_list ? ban_list->data : NULL,
-                                        ban_list ? ban_list->len : 0,
+                                        ban_list ?
+                                        silc_buffer_len(ban_list): 0,
                                         9, invite_list ? invite_list->data :
                                         NULL,
                                         9, invite_list ? invite_list->data :
                                         NULL,
-                                        invite_list ? invite_list->len : 0,
+                                        invite_list ?
+                                        silc_buffer_len(invite_list) : 0,
                                         10, channel->topic,
                                         channel->topic ?
                                         strlen(channel->topic) : 0,
                                         10, channel->topic,
                                         channel->topic ?
                                         strlen(channel->topic) : 0,
@@ -2251,13 +2211,14 @@ static void silc_server_command_join_channel(SilcServer server,
                                         strlen(silc_hmac_get_name(channel->
                                                                   hmac)),
                                         12, tmp3, 4,
                                         strlen(silc_hmac_get_name(channel->
                                                                   hmac)),
                                         12, tmp3, 4,
-                                        13, user_list->data, user_list->len,
+                                        13, user_list->data,
+                                        silc_buffer_len(user_list),
                                         14, mode_list->data,
                                         14, mode_list->data,
-                                        mode_list->len,
+                                        silc_buffer_len(mode_list),
                                         15, fkey ? fkey->data : NULL,
                                         15, fkey ? fkey->data : NULL,
-                                        fkey ? fkey->len : 0,
+                                        fkey ? silc_buffer_len(fkey) : 0,
                                         16, chpklist ? chpklist->data : NULL,
                                         16, chpklist ? chpklist->data : NULL,
-                                        chpklist ? chpklist->len : 0,
+                                        chpklist ? silc_buffer_len(chpklist) : 0,
                                         17, (channel->mode &
                                              SILC_CHANNEL_MODE_ULIMIT ?
                                              ulimit : NULL),
                                         17, (channel->mode &
                                              SILC_CHANNEL_MODE_ULIMIT ?
                                              ulimit : NULL),
@@ -2267,7 +2228,7 @@ static void silc_server_command_join_channel(SilcServer server,
 
   /* Send command reply */
   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
 
   /* Send command reply */
   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
-                         reply->data, reply->len, FALSE);
+                         reply->data, silc_buffer_len(reply));
 
   /* Statistics */
   cmd->server->stat.commands_sent++;
 
   /* Statistics */
   cmd->server->stat.commands_sent++;
@@ -2281,8 +2242,8 @@ static void silc_server_command_join_channel(SilcServer server,
   SILC_LOG_DEBUG(("Send JOIN notify to channel"));
   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
                                     SILC_NOTIFY_TYPE_JOIN, 2,
   SILC_LOG_DEBUG(("Send JOIN notify to channel"));
   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
                                     SILC_NOTIFY_TYPE_JOIN, 2,
-                                    clidp->data, clidp->len,
-                                    chidp->data, chidp->len);
+                                    clidp->data, silc_buffer_len(clidp),
+                                    chidp->data, silc_buffer_len(chidp));
 
   /* Update statistics */
   server->stat.my_chanclients++;
 
   /* Update statistics */
   server->stat.my_chanclients++;
@@ -2299,7 +2260,7 @@ static void silc_server_command_join_channel(SilcServer server,
     if (keyp)
       /* Distribute the channel key to all backup routers. */
       silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
     if (keyp)
       /* Distribute the channel key to all backup routers. */
       silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
-                             keyp->data, keyp->len, FALSE, TRUE);
+                             keyp->data, silc_buffer_len(keyp), FALSE, TRUE);
 
     /* If client became founder by providing correct founder auth data
        notify the mode change to the channel. */
 
     /* If client became founder by providing correct founder auth data
        notify the mode change to the channel. */
@@ -2308,10 +2269,12 @@ static void silc_server_command_join_channel(SilcServer server,
       SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
                                         SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
       SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
                                         SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
-                                        clidp->data, clidp->len,
-                                        mode, 4, clidp->data, clidp->len,
+                                        clidp->data,
+                                        silc_buffer_len(clidp),
+                                        mode, 4, clidp->data,
+                                        silc_buffer_len(clidp),
                                         fkey ? fkey->data : NULL,
                                         fkey ? fkey->data : NULL,
-                                        fkey ? fkey->len : 0);
+                                        fkey ? silc_buffer_len(fkey) : 0);
     }
   }
 
     }
   }
 
@@ -2342,17 +2305,51 @@ static void silc_server_command_join_channel(SilcServer server,
 /* Server side of command JOIN. Joins client into requested channel. If
    the channel does not exist it will be created. */
 
 /* Server side of command JOIN. Joins client into requested channel. If
    the channel does not exist it will be created. */
 
+void silc_server_command_join_connected(SilcServer server,
+                                       SilcServerEntry server_entry,
+                                       void *context)
+{
+  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+
+  if (!server_entry) {
+    SilcUInt32 tmp_len;
+    unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+    char serv[256 + 1];
+
+    SILC_LOG_DEBUG(("Connecting to router failed"));
+    silc_parse_userfqdn(tmp, NULL, 0, serv, sizeof(serv));
+
+    if (serv[0]) {
+      silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
+                                          SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
+                                          2, serv, strlen(serv));
+    } else {
+      silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
+                                          SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
+                                          2, tmp, tmp_len);
+    }
+    silc_server_command_free(cmd);
+    return;
+  }
+
+  /* Reprocess command */
+  SILC_LOG_DEBUG(("Reprocess JOIN after connecting to router"));
+  silc_server_command_join(cmd, NULL);
+}
+
 SILC_SERVER_CMD_FUNC(join)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 SILC_SERVER_CMD_FUNC(join)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
+  SilcIDListData idata = silc_packet_get_context(cmd->sock);
   unsigned char *auth, *cauth;
   SilcUInt32 tmp_len, auth_len, cauth_len;
   char *tmp, *channel_name, *channel_namec = NULL, *cipher, *hmac;
   unsigned char *auth, *cauth;
   SilcUInt32 tmp_len, auth_len, cauth_len;
   char *tmp, *channel_name, *channel_namec = NULL, *cipher, *hmac;
+  char parsed[256 + 1], serv[256 + 1];
   SilcChannelEntry channel;
   SilcUInt32 umode = 0;
   SilcChannelEntry channel;
   SilcUInt32 umode = 0;
-  bool created = FALSE, create_key = TRUE;
-  SilcClientID *client_id;
+  SilcBool created = FALSE, create_key = TRUE;
+  SilcID id;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 7);
 
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 7);
 
@@ -2367,15 +2364,61 @@ SILC_SERVER_CMD_FUNC(join)
 
   /* Truncate over long channel names */
   if (tmp_len > 256) {
 
   /* Truncate over long channel names */
   if (tmp_len > 256) {
-    tmp[256] = '\0';
     tmp_len = 256;
     tmp_len = 256;
+    tmp[tmp_len - 1] = '\0';
+  }
+
+  /* Parse server name from the channel name */
+  silc_parse_userfqdn(tmp, parsed, sizeof(parsed), serv,
+                     sizeof(serv));
+  channel_name = parsed;
+
+  if (server->config->dynamic_server) {
+    /* If server name is not specified but local channels is FALSE then the
+       channel will be global, based on our router name. */
+    if (!serv[0] && !server->config->local_channels) {
+      if (!server->standalone) {
+       silc_snprintf(serv, sizeof(serv), server->router->server_name);
+      } else {
+       SilcServerConfigRouter *router;
+       router = silc_server_config_get_primary_router(server);
+       if (router) {
+         /* Create connection to primary router */
+         SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d",
+                         router->host, router->port));
+         silc_server_create_connection(server, FALSE, TRUE,
+                                       router->host, router->port,
+                                       silc_server_command_join_connected,
+                                       cmd);
+         return;
+       }
+      }
+    }
+
+    /* If server name is ours, ignore it. */
+    if (serv[0] && silc_utf8_strcasecmp(serv, server->server_name))
+      memset(serv, 0, sizeof(serv));
+
+    /* Create connection */
+    if (serv[0] && server->standalone) {
+      SilcServerConfigRouter *router;
+      router = silc_server_config_get_primary_router(server);
+      if (router) {
+       /* Create connection to primary router */
+       SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d",
+                       router->host, router->port));
+       silc_server_create_connection(server, FALSE, TRUE,
+                                     router->host, router->port,
+                                     silc_server_command_join_connected, cmd);
+       return;
+      }
+    }
   }
   }
-  channel_name = tmp;
 
   /* Check for valid channel name.  This is cached, the original is saved
      in the channel context. */
 
   /* Check for valid channel name.  This is cached, the original is saved
      in the channel context. */
-  channel_namec = silc_channel_name_check(tmp, tmp_len, SILC_STRING_UTF8, 256,
-                                         NULL);
+  channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
+                                         SILC_STRING_UTF8, 256, NULL);
   if (!channel_namec) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
                                          SILC_STATUS_ERR_BAD_CHANNEL, 0);
   if (!channel_namec) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
                                          SILC_STATUS_ERR_BAD_CHANNEL, 0);
@@ -2383,20 +2426,13 @@ SILC_SERVER_CMD_FUNC(join)
   }
 
   /* Get Client ID of the client who is joining to the channel */
   }
 
   /* Get Client ID of the client who is joining to the channel */
-  tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
-  if (!tmp) {
+  if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
                                          SILC_STATUS_ERR_NO_CLIENT_ID,
                                          0);
     goto out;
   }
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
                                          SILC_STATUS_ERR_NO_CLIENT_ID,
                                          0);
     goto out;
   }
-  client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
-  if (!client_id) {
-    silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
-                                        SILC_STATUS_ERR_BAD_CLIENT_ID, 0,
-                                        2, tmp, tmp_len);
-    goto out;
-  }
+  tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
 
   /* Get cipher, hmac name and auth payload */
   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
 
   /* Get cipher, hmac name and auth payload */
   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
@@ -2408,8 +2444,8 @@ SILC_SERVER_CMD_FUNC(join)
   channel = silc_idlist_find_channel_by_name(server->local_list,
                                             channel_namec, NULL);
 
   channel = silc_idlist_find_channel_by_name(server->local_list,
                                             channel_namec, NULL);
 
-  if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
-    SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
+  if (idata->conn_type == SILC_CONN_CLIENT) {
+    SilcClientEntry entry = (SilcClientEntry)idata;
     if (!entry) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
                                            SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
     if (!entry) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
                                            SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
@@ -2429,9 +2465,6 @@ SILC_SERVER_CMD_FUNC(join)
     }
 #endif /* SILC_DIST_INPLACE */
 
     }
 #endif /* SILC_DIST_INPLACE */
 
-    silc_free(client_id);
-    client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
-
     if (!channel ||
        (channel->disabled && server->server_type != SILC_ROUTER)) {
       /* Channel not found or not valid */
     if (!channel ||
        (channel->disabled && server->server_type != SILC_ROUTER)) {
       /* Channel not found or not valid */
@@ -2443,11 +2476,22 @@ SILC_SERVER_CMD_FUNC(join)
          channel = silc_server_create_new_channel(server, server->id, cipher,
                                                   hmac, channel_name, TRUE);
          if (!channel) {
          channel = silc_server_create_new_channel(server, server->id, cipher,
                                                   hmac, channel_name, TRUE);
          if (!channel) {
-           silc_server_command_send_status_data(
-                                 cmd, SILC_COMMAND_JOIN,
-                                 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
-                                 0, 2, cipher, strlen(cipher));
-           silc_free(client_id);
+           if (cipher) {
+             silc_server_command_send_status_data(
+                               cmd, SILC_COMMAND_JOIN,
+                               SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
+                               0, 2, cipher, strlen(cipher));
+           } else if (hmac) {
+             silc_server_command_send_status_data(
+                               cmd, SILC_COMMAND_JOIN,
+                               SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
+                               0, 2, hmac, strlen(hmac));
+           } else {
+             silc_server_command_send_status_reply(
+                               cmd, SILC_COMMAND_JOIN,
+                               SILC_STATUS_ERR_RESOURCE_LIMIT,
+                               0);
+           }
            goto out;
          }
 
            goto out;
          }
 
@@ -2468,10 +2512,8 @@ SILC_SERVER_CMD_FUNC(join)
          /* If this is pending command callback then we've resolved
             it and it didn't work, return since we've notified the
             client already in the command reply callback. */
          /* If this is pending command callback then we've resolved
             it and it didn't work, return since we've notified the
             client already in the command reply callback. */
-         if (cmd->pending) {
-           silc_free(client_id);
+         if (cmd->pending)
            goto out;
            goto out;
-         }
 
          /* Statistics */
          cmd->server->stat.commands_sent++;
 
          /* Statistics */
          cmd->server->stat.commands_sent++;
@@ -2481,10 +2523,9 @@ SILC_SERVER_CMD_FUNC(join)
          tmpbuf = silc_command_payload_encode_payload(cmd->payload);
 
          /* Send JOIN command to our router */
          tmpbuf = silc_command_payload_encode_payload(cmd->payload);
 
          /* Send JOIN command to our router */
-         silc_server_packet_send(server, (SilcSocketConnection)
-                                 SILC_PRIMARY_ROUTE(server),
+         silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                                  SILC_PACKET_COMMAND, cmd->packet->flags,
                                  SILC_PACKET_COMMAND, cmd->packet->flags,
-                                 tmpbuf->data, tmpbuf->len, TRUE);
+                                 tmpbuf->data, silc_buffer_len(tmpbuf));
 
          /* Reprocess this packet after received reply from router */
          silc_server_command_pending(server, SILC_COMMAND_JOIN,
 
          /* Reprocess this packet after received reply from router */
          silc_server_command_pending(server, SILC_COMMAND_JOIN,
@@ -2494,7 +2535,6 @@ SILC_SERVER_CMD_FUNC(join)
          cmd->pending = TRUE;
           silc_command_set_ident(cmd->payload, old_ident);
          silc_buffer_free(tmpbuf);
          cmd->pending = TRUE;
           silc_command_set_ident(cmd->payload, old_ident);
          silc_buffer_free(tmpbuf);
-         silc_free(client_id);
          goto out;
        }
 
          goto out;
        }
 
@@ -2507,11 +2547,22 @@ SILC_SERVER_CMD_FUNC(join)
          channel = silc_server_create_new_channel(server, server->id, cipher,
                                                   hmac, channel_name, TRUE);
          if (!channel) {
          channel = silc_server_create_new_channel(server, server->id, cipher,
                                                   hmac, channel_name, TRUE);
          if (!channel) {
-           silc_server_command_send_status_data(
-                                      cmd, SILC_COMMAND_JOIN,
-                                      SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
-                                      2, cipher, strlen(cipher));
-           silc_free(client_id);
+           if (cipher) {
+             silc_server_command_send_status_data(
+                                     cmd, SILC_COMMAND_JOIN,
+                                     SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
+                                     0, 2, cipher, strlen(cipher));
+           } else if (hmac) {
+             silc_server_command_send_status_data(
+                                     cmd, SILC_COMMAND_JOIN,
+                                     SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
+                                     0, 2, hmac, strlen(hmac));
+           } else {
+             silc_server_command_send_status_reply(
+                                     cmd, SILC_COMMAND_JOIN,
+                                     SILC_STATUS_ERR_RESOURCE_LIMIT,
+                                     0);
+           }
            goto out;
          }
 
            goto out;
          }
 
@@ -2528,11 +2579,9 @@ SILC_SERVER_CMD_FUNC(join)
       /* If the command came from router and we are normal server then
         something went wrong with the joining as the channel was not found.
         We can't do anything else but ignore this. */
       /* If the command came from router and we are normal server then
         something went wrong with the joining as the channel was not found.
         We can't do anything else but ignore this. */
-      if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
-         server->server_type != SILC_ROUTER) {
-       silc_free(client_id);
+      if (idata->conn_type == SILC_CONN_ROUTER ||
+         server->server_type != SILC_ROUTER)
        goto out;
        goto out;
-      }
 
       /* We are router and the channel does not seem exist so we will check
         our global list as well for the channel. */
 
       /* We are router and the channel does not seem exist so we will check
         our global list as well for the channel. */
@@ -2543,11 +2592,22 @@ SILC_SERVER_CMD_FUNC(join)
        channel = silc_server_create_new_channel(server, server->id, cipher,
                                                 hmac, channel_name, TRUE);
        if (!channel) {
        channel = silc_server_create_new_channel(server, server->id, cipher,
                                                 hmac, channel_name, TRUE);
        if (!channel) {
-         silc_server_command_send_status_data(
-                                      cmd, SILC_COMMAND_JOIN,
-                                      SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
-                                      2, cipher, strlen(cipher));
-         silc_free(client_id);
+         if (cipher) {
+           silc_server_command_send_status_data(
+                                     cmd, SILC_COMMAND_JOIN,
+                                     SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
+                                     0, 2, cipher, strlen(cipher));
+         } else if (hmac) {
+           silc_server_command_send_status_data(
+                                     cmd, SILC_COMMAND_JOIN,
+                                     SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
+                                     0, 2, hmac, strlen(hmac));
+         } else {
+           silc_server_command_send_status_reply(
+                                     cmd, SILC_COMMAND_JOIN,
+                                     SILC_STATUS_ERR_RESOURCE_LIMIT,
+                                     0);
+         }
          goto out;
        }
 
          goto out;
        }
 
@@ -2593,12 +2653,10 @@ SILC_SERVER_CMD_FUNC(join)
     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
 
   /* Join to the channel */
     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
 
   /* Join to the channel */
-  silc_server_command_join_channel(server, cmd, channel, client_id,
+  silc_server_command_join_channel(server, cmd, channel, SILC_ID_GET_ID(id),
                                   created, create_key, umode,
                                   auth, auth_len, cauth, cauth_len);
 
                                   created, create_key, umode,
                                   auth, auth_len, cauth, cauth_len);
 
-  silc_free(client_id);
-
  out:
   silc_free(channel_namec);
   silc_server_command_free(cmd);
  out:
   silc_free(channel_namec);
   silc_server_command_free(cmd);
@@ -2651,20 +2709,20 @@ SILC_SERVER_CMD_FUNC(motd)
        /* No motd */
        silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
                                       SILC_STATUS_OK, 0, ident, 1,
        /* No motd */
        silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
                                       SILC_STATUS_OK, 0, ident, 1,
-                                      2, idp->data, idp->len);
+                                      2, idp->data, silc_buffer_len(idp));
        goto out;
       }
 
       motd[motd_len] = 0;
       silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
                                     SILC_STATUS_OK, 0, ident, 2,
        goto out;
       }
 
       motd[motd_len] = 0;
       silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
                                     SILC_STATUS_OK, 0, ident, 2,
-                                    2, idp->data, idp->len,
+                                    2, idp->data, silc_buffer_len(idp),
                                     3, motd, motd_len);
     } else {
       /* No motd */
       silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
                                     SILC_STATUS_OK, 0, ident, 1,
                                     3, motd, motd_len);
     } else {
       /* No motd */
       silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
                                     SILC_STATUS_OK, 0, ident, 1,
-                                    2, idp->data, idp->len);
+                                    2, idp->data, silc_buffer_len(idp));
     }
     silc_buffer_free(idp);
   } else {
     }
     silc_buffer_free(idp);
   } else {
@@ -2693,7 +2751,7 @@ SILC_SERVER_CMD_FUNC(motd)
 
       silc_server_packet_send(server, entry->connection,
                              SILC_PACKET_COMMAND, cmd->packet->flags,
 
       silc_server_packet_send(server, entry->connection,
                              SILC_PACKET_COMMAND, cmd->packet->flags,
-                             tmpbuf->data, tmpbuf->len, TRUE);
+                             tmpbuf->data, silc_buffer_len(tmpbuf));
 
       /* Reprocess this packet after received reply from router */
       silc_server_command_pending(server, SILC_COMMAND_MOTD,
 
       /* Reprocess this packet after received reply from router */
       silc_server_command_pending(server, SILC_COMMAND_MOTD,
@@ -2723,7 +2781,7 @@ SILC_SERVER_CMD_FUNC(motd)
 
       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                              SILC_PACKET_COMMAND, cmd->packet->flags,
 
       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                              SILC_PACKET_COMMAND, cmd->packet->flags,
-                             tmpbuf->data, tmpbuf->len, TRUE);
+                             tmpbuf->data, silc_buffer_len(tmpbuf));
 
       /* Reprocess this packet after received reply from router */
       silc_server_command_pending(server, SILC_COMMAND_MOTD,
 
       /* Reprocess this packet after received reply from router */
       silc_server_command_pending(server, SILC_COMMAND_MOTD,
@@ -2750,7 +2808,7 @@ SILC_SERVER_CMD_FUNC(motd)
     idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
     silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
                                   SILC_STATUS_OK, 0, ident, 2,
     idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
     silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
                                   SILC_STATUS_OK, 0, ident, 2,
-                                  2, idp->data, idp->len,
+                                  2, idp->data, silc_buffer_len(idp),
                                   3, entry->motd,
                                   entry->motd ?
                                   strlen(entry->motd) : 0);
                                   3, entry->motd,
                                   entry->motd ?
                                   strlen(entry->motd) : 0);
@@ -2770,13 +2828,13 @@ SILC_SERVER_CMD_FUNC(umode)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcClientEntry client = silc_packet_get_context(cmd->sock);
   unsigned char *tmp_mask, m[4];
   SilcUInt32 mask = 0;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   unsigned char *tmp_mask, m[4];
   SilcUInt32 mask = 0;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
-  bool set_mask = FALSE;
+  SilcBool set_mask = FALSE;
 
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+  if (client->data.conn_type != SILC_CONN_CLIENT || !client)
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
@@ -2847,9 +2905,9 @@ SILC_SERVER_CMD_FUNC(cmode)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcClientEntry client = silc_packet_get_context(cmd->sock);
   SilcIDListData idata = (SilcIDListData)client;
   SilcIDListData idata = (SilcIDListData)client;
-  SilcChannelID *channel_id = NULL;
+  SilcID id;
   SilcChannelEntry channel;
   SilcChannelClientEntry chl;
   SilcBuffer cidp;
   SilcChannelEntry channel;
   SilcChannelClientEntry chl;
   SilcBuffer cidp;
@@ -2857,7 +2915,7 @@ SILC_SERVER_CMD_FUNC(cmode)
   char *cipher = NULL, *hmac = NULL, *passphrase = NULL, ulimit[4];
   SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2, chpklen;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   char *cipher = NULL, *hmac = NULL, *passphrase = NULL, ulimit[4];
   SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2, chpklen;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
-  bool set_mask = FALSE, set_chpk = FALSE;
+  SilcBool set_mask = FALSE, set_chpk = FALSE;
   SilcPublicKey founder_key = NULL;
   SilcBuffer fkey = NULL, chpklist = NULL;
   SilcBufferStruct chpk;
   SilcPublicKey founder_key = NULL;
   SilcBuffer fkey = NULL, chpklist = NULL;
   SilcBufferStruct chpk;
@@ -2870,15 +2928,7 @@ SILC_SERVER_CMD_FUNC(cmode)
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 9);
 
   /* Get Channel ID */
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 9);
 
   /* Get Channel ID */
-  tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
-  if (!tmp_id) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
-                                         SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
-    silc_server_command_free(cmd);
-    return;
-  }
-  channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
-  if (!channel_id) {
+  if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
     silc_server_command_free(cmd);
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
     silc_server_command_free(cmd);
@@ -2887,15 +2937,15 @@ SILC_SERVER_CMD_FUNC(cmode)
 
   /* Get channel entry */
   channel = silc_idlist_find_channel_by_id(server->local_list,
 
   /* Get channel entry */
   channel = silc_idlist_find_channel_by_id(server->local_list,
-                                          channel_id, NULL);
+                                          SILC_ID_GET_ID(id), NULL);
   if (!channel) {
     channel = silc_idlist_find_channel_by_id(server->global_list,
   if (!channel) {
     channel = silc_idlist_find_channel_by_id(server->global_list,
-                                            channel_id, NULL);
+                                            SILC_ID_GET_ID(id), NULL);
     if (!channel) {
     if (!channel) {
+      tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
                                           0, 2, tmp_id, tmp_len2);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
                                           0, 2, tmp_id, tmp_len2);
-      silc_free(channel_id);
       silc_server_command_free(cmd);
       return;
     }
       silc_server_command_free(cmd);
       return;
     }
@@ -2911,6 +2961,7 @@ SILC_SERVER_CMD_FUNC(cmode)
 
   /* Check whether this client is on the channel */
   if (!silc_server_client_on_channel(client, channel, &chl)) {
 
   /* Check whether this client is on the channel */
   if (!silc_server_client_on_channel(client, channel, &chl)) {
+    tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
                                         SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
                                         2, tmp_id, tmp_len2);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
                                         SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
                                         2, tmp_id, tmp_len2);
@@ -2921,6 +2972,7 @@ SILC_SERVER_CMD_FUNC(cmode)
   if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
                                                  mode_mask)) {
     SILC_LOG_DEBUG(("Client does not have rights to change mode"));
   if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
                                                  mode_mask)) {
     SILC_LOG_DEBUG(("Client does not have rights to change mode"));
+    tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
     silc_server_command_send_status_data(
                             cmd, SILC_COMMAND_CMODE,
                             (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
     silc_server_command_send_status_data(
                             cmd, SILC_COMMAND_CMODE,
                             (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
@@ -2936,18 +2988,19 @@ SILC_SERVER_CMD_FUNC(cmode)
     unsigned char m[4];
     SILC_PUT32_MSB(channel->mode, m);
     if (channel->founder_key)
     unsigned char m[4];
     SILC_PUT32_MSB(channel->mode, m);
     if (channel->founder_key)
-      fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
+      fkey = silc_public_key_payload_encode(channel->founder_key);
     if (channel->channel_pubkeys)
       chpklist = silc_server_get_channel_pk_list(server, channel,
                                                 FALSE, FALSE);
     if (channel->channel_pubkeys)
       chpklist = silc_server_get_channel_pk_list(server, channel,
                                                 FALSE, FALSE);
+    tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
     silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
                                   SILC_STATUS_OK, 0, ident, 4,
                                   2, tmp_id, tmp_len2,
                                   3, m, sizeof(m),
                                   4, fkey ? fkey->data : NULL,
     silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
                                   SILC_STATUS_OK, 0, ident, 4,
                                   2, tmp_id, tmp_len2,
                                   3, m, sizeof(m),
                                   4, fkey ? fkey->data : NULL,
-                                  fkey ? fkey->len : 0,
+                                  fkey ? silc_buffer_len(fkey) : 0,
                                   5, chpklist ? chpklist->data : NULL,
                                   5, chpklist ? chpklist->data : NULL,
-                                  chpklist ? chpklist->len : 0);
+                                  chpklist ? silc_buffer_len(chpklist) : 0);
     goto out;
   }
 
     goto out;
   }
 
@@ -2966,6 +3019,10 @@ SILC_SERVER_CMD_FUNC(cmode)
         new channel key. Clients are not using private channel keys
         anymore after this. */
 
         new channel key. Clients are not using private channel keys
         anymore after this. */
 
+      /* if we don't remove the flag from the mode
+       * silc_server_create_channel_key won't create a new key */
+      channel->mode &= ~SILC_CHANNEL_MODE_PRIVKEY;
+
       /* Re-generate channel key */
       if (!silc_server_create_channel_key(server, channel, 0))
        goto out;
       /* Re-generate channel key */
       if (!silc_server_create_channel_key(server, channel, 0))
        goto out;
@@ -2976,7 +3033,7 @@ SILC_SERVER_CMD_FUNC(cmode)
                                   server->server_type == SILC_ROUTER ?
                                   FALSE : !server->standalone);
 
                                   server->server_type == SILC_ROUTER ?
                                   FALSE : !server->standalone);
 
-      cipher = (char *)silc_cipher_get_name(channel->channel_key);
+      cipher = (char *)silc_cipher_get_name(channel->send_key);
       hmac = (char *)silc_hmac_get_name(channel->hmac);
     }
   }
       hmac = (char *)silc_hmac_get_name(channel->hmac);
     }
   }
@@ -3029,7 +3086,7 @@ SILC_SERVER_CMD_FUNC(cmode)
   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
       /* Cipher to use protect the traffic */
   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
       /* Cipher to use protect the traffic */
-      SilcCipher newkey, oldkey;
+      SilcCipher send_key, receive_key, olds, oldr;
 
       /* Get cipher */
       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
 
       /* Get cipher */
       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
@@ -3040,7 +3097,14 @@ SILC_SERVER_CMD_FUNC(cmode)
       }
 
       /* Delete old cipher and allocate the new one */
       }
 
       /* Delete old cipher and allocate the new one */
-      if (!silc_cipher_alloc(cipher, &newkey)) {
+      if (!silc_cipher_alloc(cipher, &send_key)) {
+       silc_server_command_send_status_data(
+                                        cmd, SILC_COMMAND_CMODE,
+                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
+                                        2, cipher, strlen(cipher));
+       goto out;
+      }
+      if (!silc_cipher_alloc(cipher, &receive_key)) {
        silc_server_command_send_status_data(
                                         cmd, SILC_COMMAND_CMODE,
                                         SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
        silc_server_command_send_status_data(
                                         cmd, SILC_COMMAND_CMODE,
                                         SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
@@ -3048,18 +3112,22 @@ SILC_SERVER_CMD_FUNC(cmode)
        goto out;
       }
 
        goto out;
       }
 
-      oldkey = channel->channel_key;
-      channel->channel_key = newkey;
+      olds = channel->send_key;
+      oldr = channel->receive_key;
+      channel->send_key = send_key;
+      channel->receive_key = receive_key;
 
       /* Re-generate channel key */
       if (!silc_server_create_channel_key(server, channel, 0)) {
        /* We don't have new key, revert to old one */
 
       /* Re-generate channel key */
       if (!silc_server_create_channel_key(server, channel, 0)) {
        /* We don't have new key, revert to old one */
-       channel->channel_key = oldkey;
+       channel->send_key = olds;
+       channel->receive_key = oldr;
        goto out;
       }
 
       /* Remove old channel key for good */
        goto out;
       }
 
       /* Remove old channel key for good */
-      silc_cipher_free(oldkey);
+      silc_cipher_free(olds);
+      silc_cipher_free(oldr);
 
       /* Send the channel key. This sends it to our local clients and if
         we are normal server to our router as well. */
 
       /* Send the channel key. This sends it to our local clients and if
         we are normal server to our router as well. */
@@ -3071,11 +3139,20 @@ SILC_SERVER_CMD_FUNC(cmode)
     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
       /* Cipher mode is unset. Remove the cipher and revert back to
         default cipher */
     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
       /* Cipher mode is unset. Remove the cipher and revert back to
         default cipher */
-      SilcCipher newkey, oldkey;
+      SilcCipher send_key, receive_key, olds, oldr;
       cipher = channel->cipher;
 
       /* Delete old cipher and allocate default one */
       cipher = channel->cipher;
 
       /* Delete old cipher and allocate default one */
-      if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
+      if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER,
+                            &send_key)) {
+       silc_server_command_send_status_data(
+                                     cmd, SILC_COMMAND_CMODE,
+                                     SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
+                                     2, cipher, strlen(cipher));
+       goto out;
+      }
+      if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER,
+                            &receive_key)) {
        silc_server_command_send_status_data(
                                      cmd, SILC_COMMAND_CMODE,
                                      SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
        silc_server_command_send_status_data(
                                      cmd, SILC_COMMAND_CMODE,
                                      SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
@@ -3083,18 +3160,22 @@ SILC_SERVER_CMD_FUNC(cmode)
        goto out;
       }
 
        goto out;
       }
 
-      oldkey = channel->channel_key;
-      channel->channel_key = newkey;
+      olds = channel->send_key;
+      oldr = channel->receive_key;
+      channel->send_key = send_key;
+      channel->receive_key = receive_key;
 
       /* Re-generate channel key */
       if (!silc_server_create_channel_key(server, channel, 0)) {
        /* We don't have new key, revert to old one */
 
       /* Re-generate channel key */
       if (!silc_server_create_channel_key(server, channel, 0)) {
        /* We don't have new key, revert to old one */
-       channel->channel_key = oldkey;
+       channel->send_key = olds;
+       channel->receive_key = oldr;
        goto out;
       }
 
       /* Remove old channel key for good */
        goto out;
       }
 
       /* Remove old channel key for good */
-      silc_cipher_free(oldkey);
+      silc_cipher_free(olds);
+      silc_cipher_free(oldr);
 
       /* Send the channel key. This sends it to our local clients and if
         we are normal server to our router as well. */
 
       /* Send the channel key. This sends it to our local clients and if
         we are normal server to our router as well. */
@@ -3107,7 +3188,7 @@ SILC_SERVER_CMD_FUNC(cmode)
   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
       /* HMAC to use protect the traffic */
   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
       /* HMAC to use protect the traffic */
-      unsigned char hash[32];
+      unsigned char hash[SILC_HASH_MAXLEN];
       SilcHmac newhmac;
 
       /* Get hmac */
       SilcHmac newhmac;
 
       /* Get hmac */
@@ -3143,7 +3224,7 @@ SILC_SERVER_CMD_FUNC(cmode)
       /* Hmac mode is unset. Remove the hmac and revert back to
         default hmac */
       SilcHmac newhmac;
       /* Hmac mode is unset. Remove the hmac and revert back to
         default hmac */
       SilcHmac newhmac;
-      unsigned char hash[32];
+      unsigned char hash[SILC_HASH_MAXLEN];
       hmac = channel->hmac_name;
 
       /* Delete old hmac and allocate default one */
       hmac = channel->hmac_name;
 
       /* Delete old hmac and allocate default one */
@@ -3175,7 +3256,7 @@ SILC_SERVER_CMD_FUNC(cmode)
       founder_key = idata->public_key;
       tmp = silc_argument_get_arg_type(cmd->args, 8, &tmp_len);
       if (tmp) {
       founder_key = idata->public_key;
       tmp = silc_argument_get_arg_type(cmd->args, 8, &tmp_len);
       if (tmp) {
-       if (!silc_pkcs_public_key_payload_decode(tmp, tmp_len, &founder_key)) {
+       if (!silc_public_key_payload_decode(tmp, tmp_len, &founder_key)) {
          silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
                                                SILC_STATUS_ERR_AUTH_FAILED,
                                                0);
          silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
                                                SILC_STATUS_ERR_AUTH_FAILED,
                                                0);
@@ -3221,7 +3302,7 @@ SILC_SERVER_CMD_FUNC(cmode)
        goto out;
       }
 
        goto out;
       }
 
-      fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
+      fkey = silc_public_key_payload_encode(channel->founder_key);
       if (!fkey) {
        silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
                                              SILC_STATUS_ERR_AUTH_FAILED,
       if (!fkey) {
        silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
                                              SILC_STATUS_ERR_AUTH_FAILED,
@@ -3282,14 +3363,14 @@ SILC_SERVER_CMD_FUNC(cmode)
     SILC_PUT32_MSB(channel->user_limit, ulimit);
   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
                                     SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
     SILC_PUT32_MSB(channel->user_limit, ulimit);
   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
                                     SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
-                                    cidp->data, cidp->len,
+                                    cidp->data, silc_buffer_len(cidp),
                                     tmp_mask, 4,
                                     cipher, cipher ? strlen(cipher) : 0,
                                     hmac, hmac ? strlen(hmac) : 0,
                                     passphrase, passphrase ?
                                     strlen(passphrase) : 0,
                                     fkey ? fkey->data : NULL,
                                     tmp_mask, 4,
                                     cipher, cipher ? strlen(cipher) : 0,
                                     hmac, hmac ? strlen(hmac) : 0,
                                     passphrase, passphrase ?
                                     strlen(passphrase) : 0,
                                     fkey ? fkey->data : NULL,
-                                    fkey ? fkey->len : 0,
+                                    fkey ? silc_buffer_len(fkey) : 0,
                                     chpkdata ? chpkdata : NULL,
                                     chpkdata ? chpklen : 0,
                                     mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
                                     chpkdata ? chpkdata : NULL,
                                     chpkdata ? chpklen : 0,
                                     mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
@@ -3310,14 +3391,15 @@ SILC_SERVER_CMD_FUNC(cmode)
     chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
 
   /* Send command reply to sender */
     chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
 
   /* Send command reply to sender */
+  tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
                                 SILC_STATUS_OK, 0, ident, 5,
                                 2, tmp_id, tmp_len2,
                                 3, tmp_mask, 4,
                                 4, fkey ? fkey->data : NULL,
   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
                                 SILC_STATUS_OK, 0, ident, 5,
                                 2, tmp_id, tmp_len2,
                                 3, tmp_mask, 4,
                                 4, fkey ? fkey->data : NULL,
-                                fkey ? fkey->len : 0,
+                                fkey ? silc_buffer_len(fkey) : 0,
                                 5, chpklist ? chpklist->data :
                                 5, chpklist ? chpklist->data :
-                                NULL, chpklist ? chpklist->len
+                                NULL, chpklist ? silc_buffer_len(chpklist)
                                 : 0,
                                 6, (mode_mask &
                                     SILC_CHANNEL_MODE_ULIMIT ?
                                 : 0,
                                 6, (mode_mask &
                                     SILC_CHANNEL_MODE_ULIMIT ?
@@ -3331,7 +3413,6 @@ SILC_SERVER_CMD_FUNC(cmode)
   channel->mode = old_mask;
   silc_buffer_free(chpklist);
   silc_buffer_free(fkey);
   channel->mode = old_mask;
   silc_buffer_free(chpklist);
   silc_buffer_free(fkey);
-  silc_free(channel_id);
   silc_server_command_free(cmd);
 }
 
   silc_server_command_free(cmd);
 }
 
@@ -3341,9 +3422,8 @@ SILC_SERVER_CMD_FUNC(cumode)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
-  SilcChannelID *channel_id = NULL;
-  SilcClientID *client_id = NULL;
+  SilcClientEntry client = silc_packet_get_context(cmd->sock);
+  SilcID id, id2;
   SilcChannelEntry channel;
   SilcClientEntry target_client;
   SilcChannelClientEntry chl;
   SilcChannelEntry channel;
   SilcClientEntry target_client;
   SilcChannelClientEntry chl;
@@ -3361,14 +3441,7 @@ SILC_SERVER_CMD_FUNC(cumode)
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
 
   /* Get Channel ID */
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
 
   /* Get Channel ID */
-  tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
-  if (!tmp_ch_id) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
-                                         SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
-    goto out;
-  }
-  channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
-  if (!channel_id) {
+  if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
     goto out;
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
     goto out;
@@ -3376,11 +3449,12 @@ SILC_SERVER_CMD_FUNC(cumode)
 
   /* Get channel entry */
   channel = silc_idlist_find_channel_by_id(server->local_list,
 
   /* Get channel entry */
   channel = silc_idlist_find_channel_by_id(server->local_list,
-                                          channel_id, NULL);
+                                          SILC_ID_GET_ID(id), NULL);
   if (!channel) {
     channel = silc_idlist_find_channel_by_id(server->global_list,
   if (!channel) {
     channel = silc_idlist_find_channel_by_id(server->global_list,
-                                            channel_id, NULL);
+                                            SILC_ID_GET_ID(id), NULL);
     if (!channel) {
     if (!channel) {
+      tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
                                           0, 2, tmp_ch_id, tmp_ch_len);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
                                           0, 2, tmp_ch_id, tmp_ch_len);
@@ -3390,6 +3464,7 @@ SILC_SERVER_CMD_FUNC(cumode)
 
   /* Check whether sender is on the channel */
   if (!silc_server_client_on_channel(client, channel, &chl)) {
 
   /* Check whether sender is on the channel */
   if (!silc_server_client_on_channel(client, channel, &chl)) {
+    tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
                                         SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
                                         2, tmp_ch_id, tmp_ch_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
                                         SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
                                         2, tmp_ch_id, tmp_ch_len);
@@ -3408,14 +3483,7 @@ SILC_SERVER_CMD_FUNC(cumode)
   SILC_GET32_MSB(target_mask, tmp_mask);
 
   /* Get target Client ID */
   SILC_GET32_MSB(target_mask, tmp_mask);
 
   /* Get target Client ID */
-  tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
-  if (!tmp_id) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
-                                         SILC_STATUS_ERR_NO_CLIENT_ID, 0);
-    goto out;
-  }
-  client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
-  if (!client_id) {
+  if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id2, NULL)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
                                          SILC_STATUS_ERR_NO_CLIENT_ID, 0);
     goto out;
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
                                          SILC_STATUS_ERR_NO_CLIENT_ID, 0);
     goto out;
@@ -3423,14 +3491,17 @@ SILC_SERVER_CMD_FUNC(cumode)
 
   /* Get target client's entry */
   target_client = silc_idlist_find_client_by_id(server->local_list,
 
   /* Get target client's entry */
   target_client = silc_idlist_find_client_by_id(server->local_list,
-                                               client_id, TRUE, NULL);
+                                               SILC_ID_GET_ID(id2),
+                                               TRUE, NULL);
   if (!target_client)
     target_client = silc_idlist_find_client_by_id(server->global_list,
   if (!target_client)
     target_client = silc_idlist_find_client_by_id(server->global_list,
-                                                 client_id, TRUE, NULL);
+                                                 SILC_ID_GET_ID(id2),
+                                                 TRUE, NULL);
 
   if (target_client != client &&
       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
 
   if (target_client != client &&
       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
+    tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
                                         SILC_STATUS_ERR_NOT_YOU, 0,
                                         2, tmp_ch_id, tmp_ch_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
                                         SILC_STATUS_ERR_NOT_YOU, 0,
                                         2, tmp_ch_id, tmp_ch_len);
@@ -3440,6 +3511,8 @@ SILC_SERVER_CMD_FUNC(cumode)
   /* Check whether target client is on the channel */
   if (target_client != client) {
     if (!silc_server_client_on_channel(target_client, channel, &chl)) {
   /* Check whether target client is on the channel */
   if (target_client != client) {
     if (!silc_server_client_on_channel(target_client, channel, &chl)) {
+      tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
+      tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
       silc_server_command_send_status_data2(
                                  cmd, SILC_COMMAND_CUMODE,
                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0,
       silc_server_command_send_status_data2(
                                  cmd, SILC_COMMAND_CUMODE,
                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0,
@@ -3456,6 +3529,7 @@ SILC_SERVER_CMD_FUNC(cumode)
   /* If the target client is founder, no one else can change their mode
      but themselves. */
   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
   /* If the target client is founder, no one else can change their mode
      but themselves. */
   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
+    tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
                                         SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
                                         0, 2, tmp_ch_id, tmp_ch_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
                                         SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
                                         0, 2, tmp_ch_id, tmp_ch_len);
@@ -3502,7 +3576,7 @@ SILC_SERVER_CMD_FUNC(cumode)
 
       notify = TRUE;
       founder_key = channel->founder_key;
 
       notify = TRUE;
       founder_key = channel->founder_key;
-      fkey = silc_pkcs_public_key_payload_encode(founder_key);
+      fkey = silc_public_key_payload_encode(founder_key);
       if (!fkey) {
        silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
                                              SILC_STATUS_ERR_AUTH_FAILED, 0);
       if (!fkey) {
        silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
                                              SILC_STATUS_ERR_AUTH_FAILED, 0);
@@ -3549,6 +3623,7 @@ SILC_SERVER_CMD_FUNC(cumode)
     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
+       tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
         silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV,
                                             0, 2, tmp_ch_id, tmp_ch_len);
         silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV,
                                             0, 2, tmp_ch_id, tmp_ch_len);
@@ -3562,6 +3637,7 @@ SILC_SERVER_CMD_FUNC(cumode)
     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
+       tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
         silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV,
                                             0, 2, tmp_ch_id, tmp_ch_len);
         silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV,
                                             0, 2, tmp_ch_id, tmp_ch_len);
@@ -3670,16 +3746,17 @@ SILC_SERVER_CMD_FUNC(cumode)
 
   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
 
   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
+  tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
 
   /* Send notify to channel, notify only if mode was actually changed. */
   if (notify) {
     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
                                       SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
 
   /* Send notify to channel, notify only if mode was actually changed. */
   if (notify) {
     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
                                       SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
-                                      idp->data, idp->len,
+                                      idp->data, silc_buffer_len(idp),
                                       tmp_mask, 4,
                                       tmp_id, tmp_len,
                                       fkey ? fkey->data : NULL,
                                       tmp_mask, 4,
                                       tmp_id, tmp_len,
                                       fkey ? fkey->data : NULL,
-                                      fkey ? fkey->len : 0);
+                                      fkey ? silc_buffer_len(fkey) : 0);
 
     /* Set CUMODE notify type to network */
     silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
 
     /* Set CUMODE notify type to network */
     silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
@@ -3697,8 +3774,6 @@ SILC_SERVER_CMD_FUNC(cumode)
   silc_buffer_free(idp);
 
  out:
   silc_buffer_free(idp);
 
  out:
-  silc_free(channel_id);
-  silc_free(client_id);
   silc_buffer_free(fkey);
   silc_server_command_free(cmd);
 }
   silc_buffer_free(fkey);
   silc_server_command_free(cmd);
 }
@@ -3709,10 +3784,9 @@ SILC_SERVER_CMD_FUNC(kick)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcClientEntry client = silc_packet_get_context(cmd->sock);
   SilcClientEntry target_client;
   SilcClientEntry target_client;
-  SilcChannelID *channel_id;
-  SilcClientID *client_id;
+  SilcID id, id2;
   SilcChannelEntry channel;
   SilcChannelClientEntry chl;
   SilcBuffer idp;
   SilcChannelEntry channel;
   SilcChannelClientEntry chl;
   SilcBuffer idp;
@@ -3726,27 +3800,20 @@ SILC_SERVER_CMD_FUNC(kick)
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
 
   /* Get Channel ID */
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
 
   /* Get Channel ID */
-  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
-  if (!tmp) {
+  if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
     goto out;
   }
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
     goto out;
   }
-  channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
-  if (!channel_id) {
-    silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
-                                        SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
-                                         2, tmp, tmp_len);
-    goto out;
-  }
 
   /* Get channel entry */
   channel = silc_idlist_find_channel_by_id(server->local_list,
 
   /* Get channel entry */
   channel = silc_idlist_find_channel_by_id(server->local_list,
-                                          channel_id, NULL);
+                                          SILC_ID_GET_ID(id), NULL);
   if (!channel) {
     channel = silc_idlist_find_channel_by_id(server->local_list,
   if (!channel) {
     channel = silc_idlist_find_channel_by_id(server->local_list,
-                                            channel_id, NULL);
+                                            SILC_ID_GET_ID(id), NULL);
     if (!channel) {
     if (!channel) {
+      tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
                                           0, 2, tmp, tmp_len);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
                                           0, 2, tmp, tmp_len);
@@ -3756,6 +3823,7 @@ SILC_SERVER_CMD_FUNC(kick)
 
   /* Check whether sender is on the channel */
   if (!silc_server_client_on_channel(client, channel, &chl)) {
 
   /* Check whether sender is on the channel */
   if (!silc_server_client_on_channel(client, channel, &chl)) {
+    tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
                                         SILC_STATUS_ERR_NOT_ON_CHANNEL,
                                         0, 2, tmp, tmp_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
                                         SILC_STATUS_ERR_NOT_ON_CHANNEL,
                                         0, 2, tmp, tmp_len);
@@ -3765,6 +3833,7 @@ SILC_SERVER_CMD_FUNC(kick)
   /* Check that the kicker is channel operator or channel founder */
   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
   /* Check that the kicker is channel operator or channel founder */
   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
+    tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV,
                                         0, 2, tmp, tmp_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV,
                                         0, 2, tmp, tmp_len);
@@ -3772,30 +3841,25 @@ SILC_SERVER_CMD_FUNC(kick)
   }
 
   /* Get target Client ID */
   }
 
   /* Get target Client ID */
-  target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
-  if (!target_idp) {
+  if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id2, NULL)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
                                          SILC_STATUS_ERR_NO_CLIENT_ID, 0);
     goto out;
   }
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
                                          SILC_STATUS_ERR_NO_CLIENT_ID, 0);
     goto out;
   }
-  client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
-  if (!client_id) {
-    silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
-                                        SILC_STATUS_ERR_BAD_CLIENT_ID,
-                                        0, 2, target_idp, target_idp_len);
-    goto out;
-  }
 
   /* Get target client's entry */
   target_client = silc_idlist_find_client_by_id(server->local_list,
 
   /* Get target client's entry */
   target_client = silc_idlist_find_client_by_id(server->local_list,
-                                               client_id, TRUE, NULL);
-  if (!target_client) {
+                                               SILC_ID_GET_ID(id2),
+                                               TRUE, NULL);
+  if (!target_client)
     target_client = silc_idlist_find_client_by_id(server->global_list,
     target_client = silc_idlist_find_client_by_id(server->global_list,
-                                                 client_id, TRUE, NULL);
-  }
+                                                 SILC_ID_GET_ID(id2),
+                                                 TRUE, NULL);
 
   /* Check whether target client is on the channel */
   if (!silc_server_client_on_channel(target_client, channel, &chl)) {
 
   /* Check whether target client is on the channel */
   if (!silc_server_client_on_channel(target_client, channel, &chl)) {
+    tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+    target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
     silc_server_command_send_status_data2(cmd, SILC_COMMAND_KICK,
                                          SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
                                          0, 2, target_idp, target_idp_len,
     silc_server_command_send_status_data2(cmd, SILC_COMMAND_KICK,
                                          SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
                                          0, 2, target_idp, target_idp_len,
@@ -3806,6 +3870,7 @@ SILC_SERVER_CMD_FUNC(kick)
   /* Check that the target client is not channel founder. Channel founder
      cannot be kicked from the channel. */
   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
   /* Check that the target client is not channel founder. Channel founder
      cannot be kicked from the channel. */
   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
+    tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
                                         SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
                                         0, 2, tmp, tmp_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
                                         SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
                                         0, 2, tmp, tmp_len);
@@ -3817,8 +3882,9 @@ SILC_SERVER_CMD_FUNC(kick)
   if (clen > 128)
     comment = NULL;
 
   if (clen > 128)
     comment = NULL;
 
-
   /* Send the reply back to the client */
   /* Send the reply back to the client */
+  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+  target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_KICK,
                                 SILC_STATUS_OK, 0, ident, 2,
                                 2, tmp, tmp_len,
   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_KICK,
                                 SILC_STATUS_OK, 0, ident, 2,
                                 2, tmp, tmp_len,
@@ -3830,7 +3896,7 @@ SILC_SERVER_CMD_FUNC(kick)
                                     SILC_NOTIFY_TYPE_KICKED, 3,
                                     target_idp, target_idp_len,
                                     comment, comment ? strlen(comment) : 0,
                                     SILC_NOTIFY_TYPE_KICKED, 3,
                                     target_idp, target_idp_len,
                                     comment, comment ? strlen(comment) : 0,
-                                    idp->data, idp->len);
+                                    idp->data, silc_buffer_len(idp));
   silc_buffer_free(idp);
 
   /* Send KICKED notify to primary route */
   silc_buffer_free(idp);
 
   /* Send KICKED notify to primary route */
@@ -3843,7 +3909,7 @@ SILC_SERVER_CMD_FUNC(kick)
     SilcBuffer ab =
       silc_argument_payload_encode_one(NULL, target_idp, target_idp_len, 3);
     SilcArgumentPayload args =
     SilcBuffer ab =
       silc_argument_payload_encode_one(NULL, target_idp, target_idp_len, 3);
     SilcArgumentPayload args =
-      silc_argument_payload_parse(ab->data, ab->len, 1);
+      silc_argument_payload_parse(ab->data, silc_buffer_len(ab), 1);
 
     silc_server_inviteban_process(server, channel->invite_list, 1, args);
     silc_buffer_free(ab);
 
     silc_server_inviteban_process(server, channel->invite_list, 1, args);
     silc_buffer_free(ab);
@@ -3880,19 +3946,23 @@ SILC_SERVER_CMD_FUNC(oper)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcClientEntry client = silc_packet_get_context(cmd->sock);
   unsigned char *username = NULL, *auth;
   SilcUInt32 tmp_len;
   SilcServerConfigAdmin *admin;
   SilcIDListData idata = (SilcIDListData)client;
   unsigned char *username = NULL, *auth;
   SilcUInt32 tmp_len;
   SilcServerConfigAdmin *admin;
   SilcIDListData idata = (SilcIDListData)client;
-  bool result = FALSE;
+  SilcBool result = FALSE;
   SilcPublicKey cached_key;
   SilcPublicKey cached_key;
+  const char *hostname, *ip;
 
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+  if (client->data.conn_type != SILC_CONN_CLIENT || !client)
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
 
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
 
+  silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
+                             NULL, &hostname, &ip, NULL);
+
   /* Get the username */
   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
   if (!username) {
   /* Get the username */
   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
   if (!username) {
@@ -3913,10 +3983,10 @@ SILC_SERVER_CMD_FUNC(oper)
   }
 
   /* Get the admin configuration */
   }
 
   /* Get the admin configuration */
-  admin = silc_server_config_find_admin(server, cmd->sock->ip,
+  admin = silc_server_config_find_admin(server, (char *)ip,
                                        username, client->nickname);
   if (!admin) {
                                        username, client->nickname);
   if (!admin) {
-    admin = silc_server_config_find_admin(server, cmd->sock->hostname,
+    admin = silc_server_config_find_admin(server, (char *)hostname,
                                          username, client->nickname);
     if (!admin) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
                                          username, client->nickname);
     if (!admin) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
@@ -3924,7 +3994,7 @@ SILC_SERVER_CMD_FUNC(oper)
                                            0);
       SILC_LOG_INFO(("OPER authentication failed for username '%s' by "
                     "nickname '%s' from %s", username,
                                            0);
       SILC_LOG_INFO(("OPER authentication failed for username '%s' by "
                     "nickname '%s' from %s", username,
-                    client->nickname, cmd->sock->hostname));
+                    client->nickname, hostname));
       goto out;
     }
   }
       goto out;
     }
   }
@@ -3945,7 +4015,9 @@ SILC_SERVER_CMD_FUNC(oper)
                                   admin->passphrase, admin->passphrase_len,
                                   idata->hash, client->id, SILC_ID_CLIENT);
   if (!result && admin->publickeys) {
                                   admin->passphrase, admin->passphrase_len,
                                   idata->hash, client->id, SILC_ID_CLIENT);
   if (!result && admin->publickeys) {
-    cached_key = silc_server_get_public_key(server, admin->publickeys);
+    cached_key =
+      silc_server_get_public_key(server,
+                                SILC_SKR_USAGE_SERVICE_AUTHORIZATION, admin);
     if (!cached_key)
       goto out;
     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
     if (!cached_key)
       goto out;
     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
@@ -3994,21 +4066,16 @@ SILC_TASK_CALLBACK(silc_server_command_detach_cb)
   QuitInternal q = (QuitInternal)context;
   SilcClientID *client_id = (SilcClientID *)q->sock;
   SilcClientEntry client;
   QuitInternal q = (QuitInternal)context;
   SilcClientID *client_id = (SilcClientID *)q->sock;
   SilcClientEntry client;
-  SilcSocketConnection sock;
+  SilcPacketStream sock;
 
   client = silc_idlist_find_client_by_id(server->local_list, client_id,
                                         TRUE, NULL);
   if (client && client->connection) {
     sock = client->connection;
 
 
   client = silc_idlist_find_client_by_id(server->local_list, client_id,
                                         TRUE, NULL);
   if (client && client->connection) {
     sock = client->connection;
 
-    /* If there is pending outgoing data for the client then purge it
-       to the network before closing connection. */
-    silc_server_packet_queue_purge(server, sock);
-
     /* Close the connection on our side */
     client->router = NULL;
     client->connection = NULL;
     /* Close the connection on our side */
     client->router = NULL;
     client->connection = NULL;
-    sock->user_data = NULL;
     silc_server_close_connection(server, sock);
   }
 
     silc_server_close_connection(server, sock);
   }
 
@@ -4042,7 +4109,7 @@ SILC_SERVER_CMD_FUNC(detach)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcClientEntry client = silc_packet_get_context(cmd->sock);
   QuitInternal q;
 
   if (server->config->detach_disabled) {
   QuitInternal q;
 
   if (server->config->detach_disabled) {
@@ -4052,7 +4119,7 @@ SILC_SERVER_CMD_FUNC(detach)
     goto out;
   }
 
     goto out;
   }
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+  if (client->data.conn_type != SILC_CONN_CLIENT || !client)
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
@@ -4080,16 +4147,16 @@ SILC_SERVER_CMD_FUNC(detach)
 
   q = silc_calloc(1, sizeof(*q));
   q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
 
   q = silc_calloc(1, sizeof(*q));
   q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
-  silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
-                        q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+  silc_schedule_task_add_timeout(server->schedule,
+                                silc_server_command_detach_cb,
+                                q, 0, 200000);
 
   if (server->config->detach_timeout) {
     q = silc_calloc(1, sizeof(*q));
     q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
 
   if (server->config->detach_timeout) {
     q = silc_calloc(1, sizeof(*q));
     q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
-    silc_schedule_task_add(server->schedule, 0,
-                          silc_server_command_detach_timeout,
-                          q, server->config->detach_timeout * 60,
-                          0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+    silc_schedule_task_add_timeout(server->schedule,
+                                  silc_server_command_detach_timeout,
+                                  q, server->config->detach_timeout * 60, 0);
   }
 
   /* Send reply to the sender */
   }
 
   /* Send reply to the sender */
@@ -4108,9 +4175,9 @@ SILC_SERVER_CMD_FUNC(watch)
   SilcServer server = cmd->server;
   char *add_nick, *del_nick;
   SilcUInt32 add_nick_len, del_nick_len, tmp_len, pk_len;
   SilcServer server = cmd->server;
   char *add_nick, *del_nick;
   SilcUInt32 add_nick_len, del_nick_len, tmp_len, pk_len;
-  unsigned char hash[16], *tmp,  *pk, *nick;
+  unsigned char hash[SILC_HASH_MAXLEN], *tmp,  *pk, *nick;
   SilcClientEntry client;
   SilcClientEntry client;
-  SilcClientID *client_id = NULL;
+  SilcID id;
   SilcUInt16 old_ident;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
   SilcUInt16 old_ident;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
@@ -4136,7 +4203,7 @@ SILC_SERVER_CMD_FUNC(watch)
 
       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                              SILC_PACKET_COMMAND, cmd->packet->flags,
 
       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                              SILC_PACKET_COMMAND, cmd->packet->flags,
-                             tmpbuf->data, tmpbuf->len, TRUE);
+                             tmpbuf->data, silc_buffer_len(tmpbuf));
 
       /* Reprocess this packet after received reply from router */
       silc_server_command_pending(server, SILC_COMMAND_WATCH,
 
       /* Reprocess this packet after received reply from router */
       silc_server_command_pending(server, SILC_COMMAND_WATCH,
@@ -4172,30 +4239,23 @@ SILC_SERVER_CMD_FUNC(watch)
  process_watch:
 
   /* Get the client ID */
  process_watch:
 
   /* Get the client ID */
-  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
-  if (!tmp) {
+  if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
                                          0);
     goto out;
   }
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
                                          0);
     goto out;
   }
-  client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
-  if (!client_id) {
-    silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
-                                        SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
-                                        0, 2, tmp, tmp_len);
-    goto out;
-  }
 
   /* Get the client entry which must be in local list */
   client = silc_idlist_find_client_by_id(server->local_list,
 
   /* Get the client entry which must be in local list */
   client = silc_idlist_find_client_by_id(server->local_list,
-                                        client_id, TRUE, NULL);
+                                        SILC_ID_GET_ID(id), TRUE, NULL);
   if (!client) {
     /* Backup checks global list also */
     if (server->server_type == SILC_BACKUP_ROUTER)
       client = silc_idlist_find_client_by_id(server->global_list,
   if (!client) {
     /* Backup checks global list also */
     if (server->server_type == SILC_BACKUP_ROUTER)
       client = silc_idlist_find_client_by_id(server->global_list,
-                                            client_id, TRUE, NULL);
+                                            SILC_ID_GET_ID(id), TRUE, NULL);
     if (!client) {
     if (!client) {
+      tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
                                           0, 2, tmp, tmp_len);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
                                           0, 2, tmp, tmp_len);
@@ -4217,12 +4277,12 @@ SILC_SERVER_CMD_FUNC(watch)
   }
 
   if (add_nick && add_nick_len > 128) {
   }
 
   if (add_nick && add_nick_len > 128) {
-    add_nick[128] = '\0';
     add_nick_len = 128;
     add_nick_len = 128;
+    add_nick[add_nick_len - 1] = '\0';
   }
   if (del_nick && del_nick_len > 128) {
   }
   if (del_nick && del_nick_len > 128) {
-    del_nick[128] = '\0';
     del_nick_len = 128;
     del_nick_len = 128;
+    del_nick[del_nick_len - 1] = '\0';
   }
 
   /* Add new nickname to be watched in our cell */
   }
 
   /* Add new nickname to be watched in our cell */
@@ -4321,8 +4381,10 @@ SILC_SERVER_CMD_FUNC(watch)
 
     pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
     while (pk) {
 
     pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
     while (pk) {
-      if (!silc_pkcs_public_key_payload_decode(pk, pk_len, &public_key))
+      if (!silc_public_key_payload_decode(pk, pk_len, &public_key)) {
+        pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
        continue;
        continue;
+      }
       if (type == 0x03)
         type = 0x00;
 
       if (type == 0x03)
         type = 0x00;
 
@@ -4395,15 +4457,16 @@ SILC_SERVER_CMD_FUNC(watch)
     old_ident = silc_command_get_ident(cmd->payload);
     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
     old_ident = silc_command_get_ident(cmd->payload);
     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
-    silc_server_backup_send(server, cmd->sock->user_data, SILC_PACKET_COMMAND,
-                           cmd->packet->flags, tmpbuf->data, tmpbuf->len,
+    silc_server_backup_send(server, silc_packet_get_context(cmd->sock),
+                           SILC_PACKET_COMMAND,
+                           cmd->packet->flags, tmpbuf->data,
+                           silc_buffer_len(tmpbuf),
                            FALSE, TRUE);
     silc_command_set_ident(cmd->payload, old_ident);
     silc_buffer_free(tmpbuf);
   }
 
  out:
                            FALSE, TRUE);
     silc_command_set_ident(cmd->payload, old_ident);
     silc_buffer_free(tmpbuf);
   }
 
  out:
-  silc_free(client_id);
   silc_server_command_free(cmd);
 }
 
   silc_server_command_free(cmd);
 }
 
@@ -4414,19 +4477,23 @@ SILC_SERVER_CMD_FUNC(silcoper)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcClientEntry client = silc_packet_get_context(cmd->sock);
   unsigned char *username = NULL, *auth;
   SilcUInt32 tmp_len;
   SilcServerConfigAdmin *admin;
   SilcIDListData idata = (SilcIDListData)client;
   unsigned char *username = NULL, *auth;
   SilcUInt32 tmp_len;
   SilcServerConfigAdmin *admin;
   SilcIDListData idata = (SilcIDListData)client;
-  bool result = FALSE;
+  SilcBool result = FALSE;
   SilcPublicKey cached_key;
   SilcPublicKey cached_key;
+  const char *hostname, *ip;
 
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+  if (client->data.conn_type != SILC_CONN_CLIENT || !client)
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
 
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
 
+  silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
+                             NULL, &hostname, &ip, NULL);
+
   if (server->server_type != SILC_ROUTER) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
                                          SILC_STATUS_ERR_AUTH_FAILED, 0);
   if (server->server_type != SILC_ROUTER) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
                                          SILC_STATUS_ERR_AUTH_FAILED, 0);
@@ -4446,24 +4513,24 @@ SILC_SERVER_CMD_FUNC(silcoper)
   username = silc_identifier_check(username, tmp_len, SILC_STRING_UTF8, 128,
                                   &tmp_len);
   if (!username) {
   username = silc_identifier_check(username, tmp_len, SILC_STRING_UTF8, 128,
                                   &tmp_len);
   if (!username) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
                                          SILC_STATUS_ERR_BAD_USERNAME,
                                          0);
     goto out;
   }
 
   /* Get the admin configuration */
                                          SILC_STATUS_ERR_BAD_USERNAME,
                                          0);
     goto out;
   }
 
   /* Get the admin configuration */
-  admin = silc_server_config_find_admin(server, cmd->sock->ip,
+  admin = silc_server_config_find_admin(server, (char *)ip,
                                        username, client->nickname);
   if (!admin) {
                                        username, client->nickname);
   if (!admin) {
-    admin = silc_server_config_find_admin(server, cmd->sock->hostname,
+    admin = silc_server_config_find_admin(server, (char *)hostname,
                                          username, client->nickname);
     if (!admin) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
                                            SILC_STATUS_ERR_AUTH_FAILED, 0);
       SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by "
                     "nickname '%s' from %s", username,
                                          username, client->nickname);
     if (!admin) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
                                            SILC_STATUS_ERR_AUTH_FAILED, 0);
       SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by "
                     "nickname '%s' from %s", username,
-                    client->nickname, cmd->sock->hostname));
+                    client->nickname, hostname));
       goto out;
     }
   }
       goto out;
     }
   }
@@ -4484,7 +4551,9 @@ SILC_SERVER_CMD_FUNC(silcoper)
                                   admin->passphrase, admin->passphrase_len,
                                   idata->hash, client->id, SILC_ID_CLIENT);
   if (!result && admin->publickeys) {
                                   admin->passphrase, admin->passphrase_len,
                                   idata->hash, client->id, SILC_ID_CLIENT);
   if (!result && admin->publickeys) {
-    cached_key = silc_server_get_public_key(server, admin->publickeys);
+    cached_key =
+      silc_server_get_public_key(server,
+                                SILC_SKR_USAGE_SERVICE_AUTHORIZATION, admin);
     if (!cached_key)
       goto out;
     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
     if (!cached_key)
       goto out;
     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
@@ -4493,7 +4562,7 @@ SILC_SERVER_CMD_FUNC(silcoper)
   }
   if (!result) {
     /* Authentication failed */
   }
   if (!result) {
     /* Authentication failed */
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
                                          SILC_STATUS_ERR_AUTH_FAILED, 0);
     goto out;
   }
                                          SILC_STATUS_ERR_AUTH_FAILED, 0);
     goto out;
   }
@@ -4533,63 +4602,63 @@ SILC_SERVER_CMD_FUNC(ban)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcClientEntry client = silc_packet_get_context(cmd->sock);
   SilcBuffer list, tmp2;
   SilcChannelEntry channel;
   SilcChannelClientEntry chl;
   SilcBuffer list, tmp2;
   SilcChannelEntry channel;
   SilcChannelClientEntry chl;
-  SilcChannelID *channel_id = NULL;
-  unsigned char *id, *tmp, *atype = NULL;
+  SilcID id;
+  unsigned char *tmp_id, *tmp, *atype = NULL;
   SilcUInt32 id_len, len, len2;
   SilcArgumentPayload args;
   SilcHashTableList htl;
   SilcUInt32 id_len, len, len2;
   SilcArgumentPayload args;
   SilcHashTableList htl;
-  SilcUInt32 type;
+  void *type;
   SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
   SilcBufferStruct blist;
 
   SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
   SilcBufferStruct blist;
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+  if (client->data.conn_type != SILC_CONN_CLIENT || !client)
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
 
   /* Get Channel ID */
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
 
   /* Get Channel ID */
-  id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
-  if (id) {
-    channel_id = silc_id_payload_parse_id(id, id_len, NULL);
-    if (!channel_id) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
-                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
-      goto out;
-    }
+  if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+                                         SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
+    goto out;
   }
 
   /* Get channel entry. The server must know about the channel since the
      client is expected to be on the channel. */
   channel = silc_idlist_find_channel_by_id(server->local_list,
   }
 
   /* Get channel entry. The server must know about the channel since the
      client is expected to be on the channel. */
   channel = silc_idlist_find_channel_by_id(server->local_list,
-                                          channel_id, NULL);
+                                          SILC_ID_GET_ID(id), NULL);
   if (!channel) {
     channel = silc_idlist_find_channel_by_id(server->global_list,
   if (!channel) {
     channel = silc_idlist_find_channel_by_id(server->global_list,
-                                            channel_id, NULL);
+                                            SILC_ID_GET_ID(id), NULL);
     if (!channel) {
     if (!channel) {
-      silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
+      tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
+      silc_server_command_send_status_data(
+                                          cmd, SILC_COMMAND_BAN,
                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
-                                          0, 2, id, id_len);
+                                          0, 2, tmp_id, id_len);
       goto out;
     }
   }
 
   /* Check whether this client is on the channel */
   if (!silc_server_client_on_channel(client, channel, &chl)) {
       goto out;
     }
   }
 
   /* Check whether this client is on the channel */
   if (!silc_server_client_on_channel(client, channel, &chl)) {
+    tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
                                         SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
     silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
                                         SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
-                                        2, id, id_len);
+                                        2, tmp_id, id_len);
     goto out;
   }
 
   /* The client must be at least channel operator. */
   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
     goto out;
   }
 
   /* The client must be at least channel operator. */
   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
+    tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0,
     silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0,
-                                        2, id, id_len);
+                                        2, tmp_id, id_len);
     goto out;
   }
 
     goto out;
   }
 
@@ -4650,11 +4719,14 @@ SILC_SERVER_CMD_FUNC(ban)
                       SILC_STR_END);
     silc_hash_table_list(channel->ban_list, &htl);
     while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
                       SILC_STR_END);
     silc_hash_table_list(channel->ban_list, &htl);
     while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
-      list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
-                                             type);
+      list = silc_argument_payload_encode_one(list, tmp2->data,
+                                             silc_buffer_len(tmp2),
+                                             SILC_PTR_TO_32(type));
     silc_hash_table_list_reset(&htl);
   }
 
     silc_hash_table_list_reset(&htl);
   }
 
+  tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
+
   /* Send BAN notify type to local servers (but not clients) and to
      network. */
   if (atype && tmp && len2) {
   /* Send BAN notify type to local servers (but not clients) and to
      network. */
   if (atype && tmp && len2) {
@@ -4664,10 +4736,10 @@ SILC_SERVER_CMD_FUNC(ban)
     if (server->server_type == SILC_ROUTER)
       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
                                          SILC_NOTIFY_TYPE_BAN, 3,
     if (server->server_type == SILC_ROUTER)
       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
                                          SILC_NOTIFY_TYPE_BAN, 3,
-                                        id, id_len,
+                                        tmp_id, id_len,
                                         atype, 1,
                                         tmp ? blist.data : NULL,
                                         atype, 1,
                                         tmp ? blist.data : NULL,
-                                        tmp ? blist.len : 0);
+                                        tmp ? silc_buffer_len(&blist) : 0);
 
     /* Send to network. */
     silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
 
     /* Send to network. */
     silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
@@ -4678,13 +4750,12 @@ SILC_SERVER_CMD_FUNC(ban)
   /* Send the reply back to the client */
   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_BAN,
                                 SILC_STATUS_OK, 0, ident, 2,
   /* Send the reply back to the client */
   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_BAN,
                                 SILC_STATUS_OK, 0, ident, 2,
-                                2, id, id_len,
+                                2, tmp_id, id_len,
                                 3, list ? list->data : NULL,
                                 3, list ? list->data : NULL,
-                                list ? list->len : 0);
+                                list ? silc_buffer_len(list) : 0);
   silc_buffer_free(list);
 
  out:
   silc_buffer_free(list);
 
  out:
-  silc_free(channel_id);
   silc_server_command_free(cmd);
 }
 
   silc_server_command_free(cmd);
 }
 
@@ -4694,37 +4765,33 @@ SILC_SERVER_CMD_FUNC(leave)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcSocketConnection sock = cmd->sock;
-  SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
-  SilcChannelID *id = NULL;
+  SilcPacketStream sock = cmd->sock;
+  SilcClientEntry id_entry = silc_packet_get_context(cmd->sock);
+  SilcID id;
   SilcChannelEntry channel;
   SilcUInt32 len;
   unsigned char *tmp;
 
   SilcChannelEntry channel;
   SilcUInt32 len;
   unsigned char *tmp;
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
+  if (id_entry->data.conn_type != SILC_CONN_CLIENT || !id_entry)
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
 
   /* Get Channel ID */
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
 
   /* Get Channel ID */
-  tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
-  if (!tmp) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
-                                         SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
-    goto out;
-  }
-  id = silc_id_payload_parse_id(tmp, len, NULL);
-  if (!id) {
+  if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
     goto out;
   }
 
   /* Get channel entry */
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
     goto out;
   }
 
   /* Get channel entry */
-  channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
+  channel = silc_idlist_find_channel_by_id(server->local_list,
+                                          SILC_ID_GET_ID(id), NULL);
   if (!channel) {
   if (!channel) {
-    channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
+    channel = silc_idlist_find_channel_by_id(server->global_list,
+                                            SILC_ID_GET_ID(id), NULL);
     if (!channel) {
     if (!channel) {
+      tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
                                           0, 2, tmp, len);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
                                           0, 2, tmp, len);
@@ -4734,6 +4801,7 @@ SILC_SERVER_CMD_FUNC(leave)
 
   /* Check whether this client is on the channel */
   if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
 
   /* Check whether this client is on the channel */
   if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
+    tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
                                         SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
                                         2, tmp, len);
     silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
                                         SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
                                         2, tmp, len);
@@ -4745,6 +4813,7 @@ SILC_SERVER_CMD_FUNC(leave)
   silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
                                SILC_BROADCAST(server), channel, id_entry->id);
 
   silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
                                SILC_BROADCAST(server), channel, id_entry->id);
 
+  tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
   silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
                                       SILC_STATUS_OK, 0, 2, tmp, len);
 
   silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
                                       SILC_STATUS_OK, 0, 2, tmp, len);
 
@@ -4766,7 +4835,6 @@ SILC_SERVER_CMD_FUNC(leave)
   }
 
  out:
   }
 
  out:
-  silc_free(id);
   silc_server_command_free(cmd);
 }
 
   silc_server_command_free(cmd);
 }
 
@@ -4778,8 +4846,9 @@ SILC_SERVER_CMD_FUNC(users)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
+  SilcIDListData idata = silc_packet_get_context(cmd->sock);
   SilcChannelEntry channel;
   SilcChannelEntry channel;
-  SilcChannelID *id = NULL;
+  SilcID id;
   SilcBuffer idp;
   unsigned char *channel_id;
   SilcUInt32 channel_id_len;
   SilcBuffer idp;
   unsigned char *channel_id;
   SilcUInt32 channel_id_len;
@@ -4817,8 +4886,7 @@ SILC_SERVER_CMD_FUNC(users)
 
   /* Check Channel ID */
   if (channel_id) {
 
   /* Check Channel ID */
   if (channel_id) {
-    id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
-    if (!id) {
+    if (!silc_id_payload_parse_id(channel_id, channel_id_len, &id)) {
       silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
                                           SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
                                           2, channel_id, channel_id_len);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
                                           SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
                                           2, channel_id, channel_id_len);
@@ -4829,8 +4897,9 @@ SILC_SERVER_CMD_FUNC(users)
   /* If we are server and we don't know about this channel we will send
      the command to our router. If we know about the channel then we also
      have the list of users already. */
   /* If we are server and we don't know about this channel we will send
      the command to our router. If we know about the channel then we also
      have the list of users already. */
-  if (id)
-    channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
+  if (channel_id)
+    channel = silc_idlist_find_channel_by_id(server->local_list,
+                                            SILC_ID_GET_ID(id), NULL);
   else
     channel = silc_idlist_find_channel_by_name(server->local_list,
                                               channel_namec, NULL);
   else
     channel = silc_idlist_find_channel_by_name(server->local_list,
                                               channel_namec, NULL);
@@ -4850,7 +4919,7 @@ SILC_SERVER_CMD_FUNC(users)
       /* Send USERS command */
       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                              SILC_PACKET_COMMAND, cmd->packet->flags,
       /* Send USERS command */
       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                              SILC_PACKET_COMMAND, cmd->packet->flags,
-                             tmpbuf->data, tmpbuf->len, TRUE);
+                             tmpbuf->data, silc_buffer_len(tmpbuf));
 
       /* Reprocess this packet after received reply */
       silc_server_command_pending(server, SILC_COMMAND_USERS,
 
       /* Reprocess this packet after received reply */
       silc_server_command_pending(server, SILC_COMMAND_USERS,
@@ -4860,19 +4929,19 @@ SILC_SERVER_CMD_FUNC(users)
       cmd->pending = TRUE;
       silc_command_set_ident(cmd->payload, ident);
       silc_buffer_free(tmpbuf);
       cmd->pending = TRUE;
       silc_command_set_ident(cmd->payload, ident);
       silc_buffer_free(tmpbuf);
-      silc_free(id);
       goto out;
     }
 
     /* Check the global list as well. */
       goto out;
     }
 
     /* Check the global list as well. */
-    if (id)
-      channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
+    if (channel_id)
+      channel = silc_idlist_find_channel_by_id(server->global_list,
+                                              SILC_ID_GET_ID(id), NULL);
     else
       channel = silc_idlist_find_channel_by_name(server->global_list,
                                                 channel_namec, NULL);
     if (!channel) {
       /* Channel really does not exist */
     else
       channel = silc_idlist_find_channel_by_name(server->global_list,
                                                 channel_namec, NULL);
     if (!channel) {
       /* Channel really does not exist */
-      if (id)
+      if (channel_id)
        silc_server_command_send_status_data(
                                    cmd, SILC_COMMAND_USERS,
                                    SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID, 0,
        silc_server_command_send_status_data(
                                    cmd, SILC_COMMAND_USERS,
                                    SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID, 0,
@@ -4888,9 +4957,9 @@ SILC_SERVER_CMD_FUNC(users)
 
   /* If the channel is private or secret do not send anything, unless the
      user requesting this command is on the channel or is server */
 
   /* If the channel is private or secret do not send anything, unless the
      user requesting this command is on the channel or is server */
-  if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
+  if (idata->conn_type == SILC_CONN_CLIENT) {
     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
-       && !silc_server_client_on_channel(cmd->sock->user_data, channel,
+       && !silc_server_client_on_channel((SilcClientEntry)idata, channel,
                                          NULL)) {
       silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
                                          NULL)) {
       silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
@@ -4915,22 +4984,21 @@ SILC_SERVER_CMD_FUNC(users)
   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_USERS,
                                 SILC_STATUS_OK, 0, ident, 4,
   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
   silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_USERS,
                                 SILC_STATUS_OK, 0, ident, 4,
-                                2, idp->data, idp->len,
+                                2, idp->data, silc_buffer_len(idp),
                                 3, lc, 4,
                                 4, client_id_list ?
                                 client_id_list->data : NULL,
                                 client_id_list ?
                                 3, lc, 4,
                                 4, client_id_list ?
                                 client_id_list->data : NULL,
                                 client_id_list ?
-                                client_id_list->len : 0,
+                                silc_buffer_len(client_id_list) : 0,
                                 5, client_mode_list ?
                                 client_mode_list->data : NULL,
                                 client_mode_list ?
                                 5, client_mode_list ?
                                 client_mode_list->data : NULL,
                                 client_mode_list ?
-                                client_mode_list->len : 0);
+                                silc_buffer_len(client_mode_list) : 0);
   silc_buffer_free(idp);
   if (client_id_list)
     silc_buffer_free(client_id_list);
   if (client_mode_list)
     silc_buffer_free(client_mode_list);
   silc_buffer_free(idp);
   if (client_id_list)
     silc_buffer_free(client_id_list);
   if (client_mode_list)
     silc_buffer_free(client_mode_list);
-  silc_free(id);
 
  out:
   silc_free(channel_namec);
 
  out:
   silc_free(channel_namec);
@@ -4946,8 +5014,8 @@ SILC_SERVER_CMD_FUNC(getkey)
   SilcServer server = cmd->server;
   SilcClientEntry client;
   SilcServerEntry server_entry;
   SilcServer server = cmd->server;
   SilcClientEntry client;
   SilcServerEntry server_entry;
-  SilcClientID *client_id = NULL;
-  SilcServerID *server_id = NULL;
+  SilcClientID client_id;
+  SilcServerID server_id;
   SilcIDPayload idp = NULL;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   unsigned char *tmp;
   SilcIDPayload idp = NULL;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   unsigned char *tmp;
@@ -4973,15 +5041,15 @@ SILC_SERVER_CMD_FUNC(getkey)
 
   id_type = silc_id_payload_get_type(idp);
   if (id_type == SILC_ID_CLIENT) {
 
   id_type = silc_id_payload_get_type(idp);
   if (id_type == SILC_ID_CLIENT) {
-    client_id = silc_id_payload_get_id(idp);
+    silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
 
     /* If the client is not found from local list there is no chance it
        would be locally connected client so send the command further. */
     client = silc_idlist_find_client_by_id(server->local_list,
 
     /* If the client is not found from local list there is no chance it
        would be locally connected client so send the command further. */
     client = silc_idlist_find_client_by_id(server->local_list,
-                                          client_id, TRUE, NULL);
+                                          &client_id, TRUE, NULL);
     if (!client)
       client = silc_idlist_find_client_by_id(server->global_list,
     if (!client)
       client = silc_idlist_find_client_by_id(server->global_list,
-                                            client_id, TRUE, NULL);
+                                            &client_id, TRUE, NULL);
 
     if ((!client && !cmd->pending && !server->standalone) ||
        (client && !client->connection && !cmd->pending &&
 
     if ((!client && !cmd->pending && !server->standalone) ||
        (client && !client->connection && !cmd->pending &&
@@ -4989,10 +5057,10 @@ SILC_SERVER_CMD_FUNC(getkey)
        (client && !client->data.public_key && !cmd->pending)) {
       SilcBuffer tmpbuf;
       SilcUInt16 old_ident;
        (client && !client->data.public_key && !cmd->pending)) {
       SilcBuffer tmpbuf;
       SilcUInt16 old_ident;
-      SilcSocketConnection dest_sock;
+      SilcPacketStream dest_sock;
 
       dest_sock = silc_server_get_client_route(server, NULL, 0,
 
       dest_sock = silc_server_get_client_route(server, NULL, 0,
-                                              client_id, NULL, NULL);
+                                              &client_id, NULL, NULL);
       if (!dest_sock)
        goto out;
 
       if (!dest_sock)
        goto out;
 
@@ -5005,7 +5073,7 @@ SILC_SERVER_CMD_FUNC(getkey)
 
       silc_server_packet_send(server, dest_sock,
                              SILC_PACKET_COMMAND, cmd->packet->flags,
 
       silc_server_packet_send(server, dest_sock,
                              SILC_PACKET_COMMAND, cmd->packet->flags,
-                             tmpbuf->data, tmpbuf->len, TRUE);
+                             tmpbuf->data, silc_buffer_len(tmpbuf));
 
       /* Reprocess this packet after received reply from router */
       silc_server_command_pending(server, SILC_COMMAND_GETKEY,
 
       /* Reprocess this packet after received reply from router */
       silc_server_command_pending(server, SILC_COMMAND_GETKEY,
@@ -5030,17 +5098,17 @@ SILC_SERVER_CMD_FUNC(getkey)
        send just OK reply */
     public_key = client->data.public_key;
     if (public_key)
        send just OK reply */
     public_key = client->data.public_key;
     if (public_key)
-      pk = silc_pkcs_public_key_payload_encode(public_key);
+      pk = silc_public_key_payload_encode(public_key);
   } else if (id_type == SILC_ID_SERVER) {
   } else if (id_type == SILC_ID_SERVER) {
-    server_id = silc_id_payload_get_id(idp);
+    silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
 
     /* If the server is not found from local list there is no chance it
        would be locally connected server so send the command further. */
     server_entry = silc_idlist_find_server_by_id(server->local_list,
 
     /* If the server is not found from local list there is no chance it
        would be locally connected server so send the command further. */
     server_entry = silc_idlist_find_server_by_id(server->local_list,
-                                                server_id, TRUE, NULL);
+                                                &server_id, TRUE, NULL);
     if (!server_entry)
       server_entry = silc_idlist_find_server_by_id(server->global_list,
     if (!server_entry)
       server_entry = silc_idlist_find_server_by_id(server->global_list,
-                                                  server_id, TRUE, NULL);
+                                                  &server_id, TRUE, NULL);
 
     if (server_entry != server->id_entry &&
        ((!server_entry && !cmd->pending && !server->standalone) ||
 
     if (server_entry != server->id_entry &&
        ((!server_entry && !cmd->pending && !server->standalone) ||
@@ -5060,7 +5128,7 @@ SILC_SERVER_CMD_FUNC(getkey)
 
       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                              SILC_PACKET_COMMAND, cmd->packet->flags,
 
       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                              SILC_PACKET_COMMAND, cmd->packet->flags,
-                             tmpbuf->data, tmpbuf->len, TRUE);
+                             tmpbuf->data, silc_buffer_len(tmpbuf));
 
       /* Reprocess this packet after received reply from router */
       silc_server_command_pending(server, SILC_COMMAND_GETKEY,
 
       /* Reprocess this packet after received reply from router */
       silc_server_command_pending(server, SILC_COMMAND_GETKEY,
@@ -5085,7 +5153,7 @@ SILC_SERVER_CMD_FUNC(getkey)
                  (server_entry == server->id_entry ? server->public_key :
                   NULL) : server_entry->data.public_key);
     if (public_key)
                  (server_entry == server->id_entry ? server->public_key :
                   NULL) : server_entry->data.public_key);
     if (public_key)
-      pk = silc_pkcs_public_key_payload_encode(public_key);
+      pk = silc_public_key_payload_encode(public_key);
   } else {
     goto out;
   }
   } else {
     goto out;
   }
@@ -5095,14 +5163,12 @@ SILC_SERVER_CMD_FUNC(getkey)
                                 SILC_STATUS_OK, 0, ident, 2,
                                 2, tmp, tmp_len,
                                 3, pk ? pk->data : NULL,
                                 SILC_STATUS_OK, 0, ident, 2,
                                 2, tmp, tmp_len,
                                 3, pk ? pk->data : NULL,
-                                pk ? pk->len : 0);
+                                pk ? silc_buffer_len(pk) : 0);
 
  out:
   if (idp)
     silc_id_payload_free(idp);
   silc_buffer_free(pk);
 
  out:
   if (idp)
     silc_id_payload_free(idp);
   silc_buffer_free(pk);
-  silc_free(client_id);
-  silc_free(server_id);
   silc_server_command_free(cmd);
 }
 
   silc_server_command_free(cmd);
 }
 
@@ -5115,7 +5181,7 @@ SILC_SERVER_CMD_FUNC(service)
   SilcServer server = cmd->server;
   SilcUInt32 tmp_len, auth_len;
   unsigned char *service_name, *auth;
   SilcServer server = cmd->server;
   SilcUInt32 tmp_len, auth_len;
   unsigned char *service_name, *auth;
-  bool send_list = FALSE;
+  SilcBool send_list = FALSE;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SERVICE, cmd, 0, 256);
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SERVICE, cmd, 0, 256);
@@ -5160,12 +5226,12 @@ SILC_SERVER_CMD_FUNC(connect)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcClientEntry client = silc_packet_get_context(cmd->sock);
   unsigned char *tmp, *host;
   SilcUInt32 tmp_len;
   SilcUInt32 port = SILC_PORT;
 
   unsigned char *tmp, *host;
   SilcUInt32 tmp_len;
   SilcUInt32 port = SILC_PORT;
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+  if (client->data.conn_type != SILC_CONN_CLIENT || !client)
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
@@ -5200,7 +5266,7 @@ SILC_SERVER_CMD_FUNC(connect)
     SILC_GET32_MSB(port, tmp);
 
   /* Create the connection. It is done with timeout and is async. */
     SILC_GET32_MSB(port, tmp);
 
   /* Create the connection. It is done with timeout and is async. */
-  silc_server_create_connection(server, host, port);
+  silc_server_create_connection(server, FALSE, FALSE, host, port, NULL, NULL);
 
   /* Send reply to the sender */
   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
 
   /* Send reply to the sender */
   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
@@ -5216,15 +5282,15 @@ SILC_SERVER_CMD_FUNC(close)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcClientEntry client = silc_packet_get_context(cmd->sock);
   SilcServerEntry server_entry;
   SilcServerEntry server_entry;
-  SilcSocketConnection sock;
+  SilcPacketStream sock;
   unsigned char *tmp;
   SilcUInt32 tmp_len;
   unsigned char *name;
   SilcUInt32 port = SILC_PORT;
 
   unsigned char *tmp;
   SilcUInt32 tmp_len;
   unsigned char *name;
   SilcUInt32 port = SILC_PORT;
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+  if (client->data.conn_type != SILC_CONN_CLIENT || !client)
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
@@ -5274,7 +5340,7 @@ SILC_SERVER_CMD_FUNC(close)
                                        SILC_STATUS_OK, 0);
 
   /* Close the connection to the server */
                                        SILC_STATUS_OK, 0);
 
   /* Close the connection to the server */
-  sock = (SilcSocketConnection)server_entry->connection;
+  sock = server_entry->connection;
 
   if (server_entry->server_type == SILC_BACKUP_ROUTER) {
     server->backup_closed = TRUE;
 
   if (server_entry->server_type == SILC_BACKUP_ROUTER) {
     server->backup_closed = TRUE;
@@ -5290,8 +5356,7 @@ SILC_SERVER_CMD_FUNC(close)
   silc_server_disconnect_remote(server, sock,
                                SILC_STATUS_ERR_BANNED_FROM_SERVER,
                                "Closed by administrator");
   silc_server_disconnect_remote(server, sock,
                                SILC_STATUS_ERR_BANNED_FROM_SERVER,
                                "Closed by administrator");
-  if (sock->user_data)
-    silc_server_free_sock_user_data(server, sock, NULL);
+  silc_server_free_sock_user_data(server, sock, NULL);
   server->backup_noswitch = FALSE;
 
  out:
   server->backup_noswitch = FALSE;
 
  out:
@@ -5305,9 +5370,9 @@ SILC_SERVER_CMD_FUNC(shutdown)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcClientEntry client = silc_packet_get_context(cmd->sock);
 
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
+  if (client->data.conn_type != SILC_CONN_CLIENT || !client)
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);