updates.
[silc.git] / apps / silcd / command.c
index b018eaa12f22e6fc742ecc87b6687ae86eaf1479..188c04cac8c0421383229208c4436e3085dd7706 100644 (file)
@@ -152,7 +152,7 @@ void silc_server_command_process(SilcServer server,
      command routine receiving it. */
   ctx = silc_server_command_alloc();
   ctx->server = server;
-  ctx->sock = sock;
+  ctx->sock = silc_socket_dup(sock);
   ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
   
   /* Parse the command payload in the packet */
@@ -161,6 +161,7 @@ void silc_server_command_process(SilcServer server,
     SILC_LOG_ERROR(("Bad command payload, packet dropped"));
     silc_buffer_free(packet->buffer);
     silc_packet_context_free(packet);
+    silc_socket_free(ctx->sock);
     silc_free(ctx);
     return;
   }
@@ -209,6 +210,8 @@ void silc_server_command_free(SilcServerCommandContext ctx)
       silc_command_free_payload(ctx->payload);
     if (ctx->packet)
       silc_packet_context_free(ctx->packet);
+    if (ctx->sock)
+      silc_socket_free(ctx->sock); /* Decrease reference counter */
     silc_free(ctx);
   }
 }
@@ -566,7 +569,7 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
   }
 }
 
-static void
+static int
 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
@@ -575,7 +578,7 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
   SilcClientEntry *clients = NULL, entry;
   SilcClientID **client_id = NULL;
   unsigned int client_id_count = 0;
-  int i;
+  int i, ret = 0;
 
   /* Protocol dictates that we must always send the received WHOIS request
      to our router if we are normal server, so let's do it now unless we
@@ -607,6 +610,7 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
     silc_command_set_ident(cmd->payload, old_ident);
 
     silc_buffer_free(tmpbuf);
+    ret = -1;
     goto out;
   }
 
@@ -617,7 +621,7 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
                                       &nick, &server_name, &count,
                                       SILC_COMMAND_WHOIS))
-    return;
+    return 0;
 
   /* Get all clients matching that ID or nickname from local list */
   if (client_id_count) {
@@ -678,8 +682,10 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
      mandatory fields that WHOIS command reply requires. Check for these and
      make query from the server who owns the client if some fields are 
      missing. */
-  if (!silc_server_command_whois_check(cmd, clients, clients_count))
+  if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
+    ret = -1;
     goto out;
+  }
 
   /* Send the command reply to the client */
   silc_server_command_whois_send_reply(cmd, clients, clients_count);
@@ -696,9 +702,11 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
     silc_free(nick);
   if (server_name)
     silc_free(server_name);
+
+  return ret;
 }
 
-static void
+static int
 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
@@ -707,13 +715,13 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
   SilcClientEntry *clients = NULL, entry;
   SilcClientID **client_id = NULL;
   unsigned int client_id_count = 0;
-  int i;
+  int i, ret = 0;
 
   /* Parse the whois request */
   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
                                       &nick, &server_name, &count,
                                       SILC_COMMAND_WHOIS))
-    return;
+    return 0;
 
   /* Process the command request. Let's search for the requested client and
      send reply to the requesting server. */
@@ -784,8 +792,10 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
      mandatory fields that WHOIS command reply requires. Check for these and
      make query from the server who owns the client if some fields are 
      missing. */
-  if (!silc_server_command_whois_check(cmd, clients, clients_count))
+  if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
+    ret = -1;
     goto out;
+  }
 
   /* Send the command reply to the client */
   silc_server_command_whois_send_reply(cmd, clients, clients_count);
@@ -802,6 +812,8 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
     silc_free(nick);
   if (server_name)
     silc_free(server_name);
+
+  return ret;
 }
 
 /* Server side of command WHOIS. Processes user's query and sends found 
@@ -810,15 +822,18 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
 SILC_SERVER_CMD_FUNC(whois)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  int ret = 0;
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
 
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
-    silc_server_command_whois_from_client(cmd);
-  else
-    silc_server_command_whois_from_server(cmd);
+    ret = silc_server_command_whois_from_client(cmd);
+  else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
+          (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
+    ret = silc_server_command_whois_from_server(cmd);
 
-  silc_server_command_free(cmd);
+  if (!ret)
+    silc_server_command_free(cmd);
 }
 
 SILC_SERVER_CMD_FUNC(whowas)
@@ -966,7 +981,7 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
   }
 }
 
-static void
+static int
 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
@@ -975,7 +990,7 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
   SilcClientEntry *clients = NULL, entry;
   SilcClientID **client_id = NULL;
   unsigned int client_id_count = 0;
-  int i;
+  int i, ret = 0;
 
   /* Protocol dictates that we must always send the received IDENTIFY request
      to our router if we are normal server, so let's do it now unless we
@@ -1007,6 +1022,7 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
     silc_command_set_ident(cmd->payload, old_ident);
 
     silc_buffer_free(tmpbuf);
+    ret = -1;
     goto out;
   }
 
@@ -1017,7 +1033,7 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
                                       &nick, &server_name, &count,
                                       SILC_COMMAND_IDENTIFY))
-    return;
+    return 0;
 
   /* Get all clients matching that ID or nickname from local list */
   if (client_id_count) { 
@@ -1075,8 +1091,10 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
 
   /* Check that all mandatory fields are present and request those data
      from the server who owns the client if necessary. */
-  if (!silc_server_command_identify_check(cmd, clients, clients_count))
+  if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
+    ret = -1;
     goto out;
+  }
 
   /* Send the command reply to the client */
   silc_server_command_identify_send_reply(cmd, clients, clients_count);
@@ -1093,9 +1111,11 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
     silc_free(nick);
   if (server_name)
     silc_free(server_name);
+
+  return ret;
 }
 
-static void
+static int
 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
@@ -1104,13 +1124,13 @@ silc_server_command_identify_from_server(SilcServerCommandContext cmd)
   SilcClientEntry *clients = NULL, entry;
   SilcClientID **client_id = NULL;
   unsigned int client_id_count = 0;
-  int i;
+  int i, ret = 0;
 
   /* Parse the IDENTIFY request */
   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
                                       &nick, &server_name, &count,
                                       SILC_COMMAND_IDENTIFY))
-    return;
+    return 0;
 
   /* Process the command request. Let's search for the requested client and
      send reply to the requesting server. */
@@ -1178,8 +1198,10 @@ silc_server_command_identify_from_server(SilcServerCommandContext cmd)
 
   /* Check that all mandatory fields are present and request those data
      from the server who owns the client if necessary. */
-  if (!silc_server_command_identify_check(cmd, clients, clients_count))
+  if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
+    ret = -1;
     goto out;
+  }
 
   /* Send the command reply */
   silc_server_command_identify_send_reply(cmd, clients, clients_count);
@@ -1196,20 +1218,25 @@ silc_server_command_identify_from_server(SilcServerCommandContext cmd)
     silc_free(nick);
   if (server_name)
     silc_free(server_name);
+
+  return ret;
 }
 
 SILC_SERVER_CMD_FUNC(identify)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  int ret = 0;
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
 
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
-    silc_server_command_identify_from_client(cmd);
-  else
-    silc_server_command_identify_from_server(cmd);
+    ret = silc_server_command_identify_from_client(cmd);
+  else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
+          (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
+    ret = silc_server_command_identify_from_server(cmd);
 
-  silc_server_command_free(cmd);
+  if (!ret)
+    silc_server_command_free(cmd);
 }
 
 /* Checks string for bad characters and returns TRUE if they are found. */
@@ -1258,13 +1285,12 @@ SILC_SERVER_CMD_FUNC(nick)
 
   /* Send notify about nickname change to our router. We send the new
      ID and ask to replace it with the old one. If we are router the
-     packet is broadcasted. */
+     packet is broadcasted. Send NICK_CHANGE notify. */
   if (!server->standalone)
-    silc_server_send_replace_id(server, server->router->connection, 
-                               server->server_type == SILC_SERVER ? 
-                               FALSE : TRUE, client->id,
-                               SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
-                               new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
+    silc_server_send_notify_nick_change(server, server->router->connection, 
+                                       server->server_type == SILC_SERVER ? 
+                                       FALSE : TRUE, client->id,
+                                       new_id, SILC_ID_CLIENT_LEN);
 
   /* Remove old cache entry */
   silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT, 
@@ -1291,7 +1317,7 @@ SILC_SERVER_CMD_FUNC(nick)
 
   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
-  /* Send NICK_CHANGE notify */
+  /* Send NICK_CHANGE notify to the client's channels */
   silc_server_send_notify_on_channels(server, client, 
                                      SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
                                      oidp->data, oidp->len, 
@@ -1375,15 +1401,15 @@ SILC_SERVER_CMD_FUNC(topic)
 
     /* See whether has rights to change topic */
     silc_list_start(channel->user_list);
-    while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
-      if (chl->client == client) {
-       if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
-         silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
-                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
-         goto out;
-       } else {
-         break;
-       }
+    while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
+      if (chl->client == client)
+       break;
+
+    if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
+      if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
+       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
+                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV);
+       goto out;
       }
     }
 
@@ -1392,6 +1418,13 @@ SILC_SERVER_CMD_FUNC(topic)
       silc_free(channel->topic);
     channel->topic = strdup(tmp);
 
+    /* Send TOPIC_SET notify type to the network */
+    if (!server->standalone)
+      silc_server_send_notify_topic_set(server, server->router->connection,
+                                       server->server_type == SILC_ROUTER ?
+                                       TRUE : FALSE, channel, client->id,
+                                       SILC_ID_CLIENT_LEN, channel->topic);
+
     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
     /* Send notify about topic change to all clients on the channel */
@@ -1525,7 +1558,8 @@ SILC_SERVER_CMD_FUNC(invite)
   sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
 
   /* Send notify to the client that is invited to the channel */
-  silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
+  silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
+                              SILC_ID_CLIENT,
                               SILC_NOTIFY_TYPE_INVITE, 2, 
                               sidp->data, sidp->len, tmp, len);
 
@@ -1539,20 +1573,30 @@ SILC_SERVER_CMD_FUNC(invite)
   silc_server_command_free(cmd);
 }
 
+typedef struct {
+  SilcServer server;
+  SilcSocketConnection sock;
+  char *signoff;
+} *QuitInternal;
+
 /* Quits connection to client. This gets called if client won't
    close the connection even when it has issued QUIT command. */
 
 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
 {
-  SilcServer server = (SilcServer)context;
-  SilcSocketConnection sock = server->sockets[fd];
+  QuitInternal q = (QuitInternal)context;
 
   /* Free all client specific data, such as client entry and entires
      on channels this client may be on. */
-  silc_server_free_sock_user_data(server, sock);
+  silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
+                              q->signoff);
+  q->sock->user_data = NULL;
 
   /* Close the connection on our side */
-  silc_server_close_connection(server, sock);
+  silc_server_close_connection(q->server, q->sock);
+
+  silc_free(q->signoff);
+  silc_free(q);
 }
 
 /* Quits SILC session. This is the normal way to disconnect client. */
@@ -1562,13 +1606,26 @@ SILC_SERVER_CMD_FUNC(quit)
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
   SilcSocketConnection sock = cmd->sock;
+  QuitInternal q;
+  unsigned char *tmp = NULL;
+  unsigned int len = 0;
 
-  SILC_LOG_DEBUG(("Start"));
+  SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
+
+  /* Get destination ID */
+  tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
+  if (len > 128)
+    tmp = NULL;
+
+  q = silc_calloc(1, sizeof(*q));
+  q->server = server;
+  q->sock = sock;
+  q->signoff = tmp ? strdup(tmp) : NULL;
 
   /* We quit the connection with little timeout */
   silc_task_register(server->timeout_queue, sock->sock,
-                    silc_server_command_quit_cb, server,
-                    0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+                    silc_server_command_quit_cb, (void *)q,
+                    0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
 
   silc_server_command_free(cmd);
 }
@@ -1718,7 +1775,7 @@ void silc_server_command_send_users(SilcServer server,
   }
   cmd->args = silc_command_get_args(cmd->payload);
   cmd->server = server;
-  cmd->sock = sock;
+  cmd->sock = silc_socket_dup(sock);
   cmd->packet = silc_packet_context_dup(packet);
   cmd->pending = FALSE;
 
@@ -1726,19 +1783,18 @@ void silc_server_command_send_users(SilcServer server,
     /* If this function was called from pending command then instead of
        processing the command now, register a pending command callback which
        will process it after we've received the automatic USERS command 
-       reply. */
-    silc_server_command_pending(server, SILC_COMMAND_USERS, 0,
-                               silc_server_command_destructor,
-                               silc_server_command_users,
-                               silc_server_command_dup(cmd));
+       reply which server will send in JOIN. */
+    silc_server_command_pending(server, SILC_COMMAND_USERS, 0, NULL,
+                               silc_server_command_users, cmd);
     cmd->pending = TRUE;
-    goto out;
+    silc_buffer_free(buffer);
+    silc_buffer_free(idp);
+    return;
   }
 
   /* Process USERS command. */
   silc_server_command_users((void *)cmd);
 
- out:
   silc_buffer_free(buffer);
   silc_buffer_free(idp);
   silc_packet_context_free(packet);
@@ -1907,16 +1963,16 @@ static void silc_server_command_join_channel(SilcServer server,
   if (!cmd->pending) {
     /* Send JOIN notify to locally connected clients on the channel */
     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
-                                      SILC_NOTIFY_TYPE_JOIN, 1,
-                                      clidp->data, clidp->len);
+                                      SILC_NOTIFY_TYPE_JOIN, 2,
+                                      clidp->data, clidp->len,
+                                      chidp->data, chidp->len);
 
-    /* Send NEW_CHANNEL_USER packet to our primary router */
+    /* Send JOIN notify packet to our primary router */
     if (!server->standalone)
-      silc_server_send_new_channel_user(server, server->router->connection,
-                                       server->server_type == SILC_SERVER ?
-                                       FALSE : TRUE,
-                                       channel->id, SILC_ID_CHANNEL_LEN,
-                                       client->id, SILC_ID_CLIENT_LEN);
+      silc_server_send_notify_join(server, server->router->connection,
+                                  server->server_type == SILC_ROUTER ?
+                                  TRUE : FALSE, channel, client->id,
+                                  SILC_ID_CLIENT_LEN);
   }
 
   /* Send USERS command reply to the joined channel so the user sees who
@@ -2036,7 +2092,7 @@ SILC_SERVER_CMD_FUNC(join)
                                      silc_server_command_join,
                                      silc_server_command_dup(cmd));
          cmd->pending = TRUE;
-         goto out;
+         return;
        }
        
        /* We are router and the channel does not seem exist so we will check
@@ -2539,11 +2595,17 @@ SILC_SERVER_CMD_FUNC(cmode)
 
   /* Send CMODE_CHANGE notify */
   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
-  silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
+  silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
                                     SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
                                     cidp->data, cidp->len, 
                                     tmp_mask, tmp_len);
-  silc_free(cidp);
+
+  /* Set CMODE notify type to network */
+  if (!server->standalone)
+    silc_server_send_notify_cmode(server, server->router->connection,
+                                 server->server_type == SILC_ROUTER ? 
+                                 TRUE : FALSE, channel,
+                                 mode_mask, client->id, SILC_ID_CLIENT_LEN);
 
   /* Send command reply to sender */
   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
@@ -2554,6 +2616,7 @@ SILC_SERVER_CMD_FUNC(cmode)
     
   silc_buffer_free(packet);
   silc_free(channel_id);
+  silc_free(cidp);
 
  out:
   silc_server_command_free(cmd);
@@ -2572,20 +2635,20 @@ SILC_SERVER_CMD_FUNC(cumode)
   SilcClientEntry target_client;
   SilcChannelClientEntry chl;
   SilcBuffer packet, idp;
-  unsigned char *tmp_id, *tmp_mask;
-  unsigned int target_mask, sender_mask, tmp_len;
+  unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
+  unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
   int notify = FALSE;
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
 
   /* Get Channel ID */
-  tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
-  if (!tmp_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);
     goto out;
   }
-  channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
+  channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
   if (!channel_id) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID);
@@ -2651,7 +2714,8 @@ SILC_SERVER_CMD_FUNC(cumode)
   target_client = silc_idlist_find_client_by_id(server->local_list, 
                                                client_id, NULL);
   if (!target_client) {
-    /* XXX If target client is not one of mine send to primary route */
+    target_client = silc_idlist_find_client_by_id(server->global_list, 
+                                                 client_id, NULL);
   }
 
   /* Check whether target client is on the channel */
@@ -2712,14 +2776,25 @@ SILC_SERVER_CMD_FUNC(cumode)
     }
   }
 
+  idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+
   /* Send notify to channel, notify only if mode was actually changed. */
   if (notify) {
-    idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
-    silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
+    silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
                                       SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
                                       idp->data, idp->len,
-                                      tmp_mask, 4, tmp_id, tmp_len);
-    silc_buffer_free(idp);
+                                      tmp_mask, 4, 
+                                      tmp_id, tmp_len);
+
+    /* Set CUMODE notify type to network */
+    if (!server->standalone)
+      silc_server_send_notify_cumode(server, server->router->connection,
+                                    server->server_type == SILC_ROUTER ? 
+                                    TRUE : FALSE, channel,
+                                    target_mask, client->id, 
+                                    SILC_ID_CLIENT_LEN,
+                                    target_client->id, 
+                                    SILC_ID_CLIENT_LEN);
   }
 
   /* Send command reply to sender */
@@ -2733,6 +2808,7 @@ SILC_SERVER_CMD_FUNC(cumode)
   silc_buffer_free(packet);
   silc_free(channel_id);
   silc_free(client_id);
+  silc_buffer_free(idp);
 
  out:
   silc_server_command_free(cmd);
@@ -2806,12 +2882,12 @@ SILC_SERVER_CMD_FUNC(leave)
   }
 
   /* Notify routers that they should remove this client from their list
-     of clients on the channel. */
+     of clients on the channel. Send LEAVE notify type. */
   if (!server->standalone)
-    silc_server_send_remove_channel_user(server, 
-                                        server->router->connection,
-                                        server->server_type == SILC_ROUTER ?
-                                        TRUE : FALSE, id_entry->id, id);
+    silc_server_send_notify_leave(server, server->router->connection,
+                                 server->server_type == SILC_ROUTER ?
+                                 TRUE : FALSE, channel, id_entry->id,
+                                 SILC_ID_CLIENT_LEN);
 
   /* Remove client from channel */
   i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
@@ -2923,7 +2999,7 @@ SILC_SERVER_CMD_FUNC(users)
       
       silc_buffer_free(tmpbuf);
       silc_free(id);
-      goto out;
+      return;
     }
 
     /* We are router and we will check the global list as well. */