5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
23 * Revision 1.14 2000/09/29 07:13:04 priikone
24 * Added support for notify type sending in notify payload.
25 * Removed Log headers from the file.
26 * Enabled debug messages by default for server.
28 * Revision 1.13 2000/08/21 14:21:21 priikone
29 * Fixed channel joining and channel message sending inside a
30 * SILC cell. Added silc_server_send_remove_channel_user and
31 * silc_server_remove_channel_user functions.
33 * Revision 1.12 2000/07/26 07:05:11 priikone
34 * Fixed the server to server (server to router actually) connections
35 * and made the private message work inside a cell. Added functin
36 * silc_server_replace_id.
38 * Revision 1.11 2000/07/19 07:08:09 priikone
39 * Added version detection support to SKE.
41 * Revision 1.10 2000/07/17 11:47:30 priikone
42 * Added command lagging support. Added idle counting support.
44 * Revision 1.9 2000/07/12 05:59:41 priikone
45 * Major rewrite of ID Cache system. Support added for the new
46 * ID cache system. Major rewrite of ID List stuff on server. All
47 * SilcXXXList's are now called SilcXXXEntry's and they are pointers
48 * by default. A lot rewritten ID list functions.
50 * Revision 1.8 2000/07/10 05:42:59 priikone
51 * Removed command packet processing from server.c and added it to
53 * Implemented INFO command. Added support for testing that
54 * connections are registered before executing commands.
56 * Revision 1.7 2000/07/07 06:55:24 priikone
57 * Do not allow client to join twice on same channel.
59 * Revision 1.6 2000/07/06 10:20:59 priikone
60 * Cipher name in joining is not mandatory, removed check.
62 * Revision 1.5 2000/07/06 07:16:43 priikone
63 * Fixed a wrong way of sending command replies. The fixed way
64 * does comply with the protocol.
66 * Revision 1.4 2000/07/05 06:13:38 priikone
67 * Added PING, INVITE and NAMES command.
69 * Revision 1.3 2000/07/03 05:52:22 priikone
70 * Implemented LEAVE command.
72 * Revision 1.2 2000/06/28 05:06:38 priikone
73 * Shorter timeout for channel joining notify.
75 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
76 * Imported from internal CVS/Added Log headers.
81 #include "serverincludes.h"
82 #include "server_internal.h"
84 static int silc_server_is_registered(SilcServer server,
85 SilcSocketConnection sock,
86 SilcServerCommandContext cmd,
89 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
91 SilcCommandStatus status);
93 silc_server_command_send_status_data(SilcServerCommandContext cmd,
95 SilcCommandStatus status,
96 unsigned int arg_type,
98 unsigned int arg_len);
99 static void silc_server_command_free(SilcServerCommandContext cmd);
101 /* Server command list. */
102 SilcServerCommand silc_command_list[] =
104 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
105 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
106 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
107 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
108 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
109 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
110 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
111 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
112 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
113 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
114 SILC_SERVER_CMD(connect, CONNECT,
115 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
116 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
117 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
118 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
119 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
120 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
121 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
122 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
123 SILC_SERVER_CMD(restart, RESTART,
124 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
125 SILC_SERVER_CMD(close, CLOSE,
126 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
127 SILC_SERVER_CMD(die, DIE, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
128 SILC_SERVER_CMD(silcoper, SILCOPER,
129 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
130 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
131 SILC_SERVER_CMD(names, NAMES, SILC_CF_LAG | SILC_CF_REG),
136 /* List of pending commands. */
137 SilcServerCommandPending *silc_command_pending = NULL;
139 /* Returns TRUE if the connection is registered. Unregistered connections
140 usually cannot send commands hence the check. */
142 static int silc_server_is_registered(SilcServer server,
143 SilcSocketConnection sock,
144 SilcServerCommandContext cmd,
148 case SILC_SOCKET_TYPE_CLIENT:
150 SilcClientEntry client = (SilcClientEntry)sock->user_data;
151 if (client->registered)
155 case SILC_SOCKET_TYPE_SERVER:
156 case SILC_SOCKET_TYPE_ROUTER:
158 SilcServerEntry serv = (SilcServerEntry)sock->user_data;
159 if (serv->registered)
167 silc_server_command_send_status_reply(cmd, command,
168 SILC_STATUS_ERR_NOT_REGISTERED);
169 silc_server_command_free(cmd);
173 /* Processes received command packet. */
175 void silc_server_command_process(SilcServer server,
176 SilcSocketConnection sock,
177 SilcPacketContext *packet)
179 SilcServerCommandContext ctx;
180 SilcServerCommand *cmd;
182 /* Check whether it is allowed for this connection to execute any
184 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
186 SilcClientEntry client = (SilcClientEntry)sock->user_data;
191 /* Allow only one command executed in 2 seconds. */
192 curtime = time(NULL);
193 if (client->last_command && (curtime - client->last_command) < 2)
196 /* Update access time */
197 client->last_command = curtime;
200 /* Allocate command context. This must be free'd by the
201 command routine receiving it. */
202 ctx = silc_calloc(1, sizeof(*ctx));
203 ctx->server = server;
205 ctx->packet = packet; /* Save original packet */
207 /* Parse the command payload in the packet */
208 ctx->payload = silc_command_parse_payload(packet->buffer);
210 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
211 silc_buffer_free(packet->buffer);
216 /* Execute command. If this fails the packet is dropped. */
217 for (cmd = silc_command_list; cmd->cb; cmd++)
218 if (cmd->cmd == silc_command_get(ctx->payload)) {
220 if (!(cmd->flags & SILC_CF_REG)) {
225 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
232 SILC_LOG_ERROR(("Unknown command, packet dropped"));
238 silc_buffer_free(packet->buffer);
241 /* Add new pending command to the list of pending commands. Currently
242 pending commands are executed from command replies, thus we can
243 execute any command after receiving some specific command reply.
245 The argument `reply_cmd' is the command reply from where the callback
246 function is to be called, thus, it IS NOT the command to be executed. */
248 void silc_server_command_pending(SilcCommand reply_cmd,
249 SilcCommandCb callback,
252 SilcServerCommandPending *reply, *r;
254 reply = silc_calloc(1, sizeof(*reply));
255 reply->reply_cmd = reply_cmd;
256 reply->context = context;
257 reply->callback = callback;
259 if (silc_command_pending == NULL) {
260 silc_command_pending = reply;
264 for (r = silc_command_pending; r; r = r->next) {
265 if (r->next == NULL) {
272 /* Deletes pending command by reply command type. */
274 void silc_server_command_pending_del(SilcCommand reply_cmd)
276 SilcServerCommandPending *r, *tmp;
278 if (silc_command_pending) {
279 if (silc_command_pending->reply_cmd == reply_cmd) {
280 silc_free(silc_command_pending);
281 silc_command_pending = NULL;
285 for (r = silc_command_pending; r; r = r->next) {
286 if (r->next && r->next->reply_cmd == reply_cmd) {
288 r->next = r->next->next;
296 /* Free's the command context allocated before executing the command */
298 static void silc_server_command_free(SilcServerCommandContext cmd)
301 silc_command_free_payload(cmd->payload);
306 #define SILC_COMMAND_STATUS_DATA(x) \
309 /* Sends simple status message as command reply packet */
312 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
314 SilcCommandStatus status)
318 SILC_LOG_DEBUG(("Sending command status %d", status));
320 buffer = silc_command_encode_reply_payload_va(command, status, 0);
321 silc_server_packet_send(cmd->server, cmd->sock,
322 SILC_PACKET_COMMAND_REPLY, 0,
323 buffer->data, buffer->len, FALSE);
324 silc_buffer_free(buffer);
327 /* Sends command status reply with one extra argument. The argument
328 type must be sent as argument. */
331 silc_server_command_send_status_data(SilcServerCommandContext cmd,
333 SilcCommandStatus status,
334 unsigned int arg_type,
336 unsigned int arg_len)
340 SILC_LOG_DEBUG(("Sending command status %d", status));
342 buffer = silc_command_encode_reply_payload_va(command, status, 1,
343 arg_type, arg, arg_len);
344 silc_server_packet_send(cmd->server, cmd->sock,
345 SILC_PACKET_COMMAND_REPLY, 0,
346 buffer->data, buffer->len, FALSE);
347 silc_buffer_free(buffer);
350 /* Server side of command WHOIS. Processes user's query and sends found
351 results as command replies back to the client. */
353 SILC_SERVER_CMD_FUNC(whois)
355 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
356 SilcServer server = cmd->server;
357 char *tmp, *nick = NULL, *server_name = NULL;
358 unsigned int argc, count = 0, len;
359 SilcClientEntry entry;
361 unsigned char *id_string;
363 SILC_LOG_DEBUG(("Start"));
365 argc = silc_command_get_arg_num(cmd->payload);
367 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
368 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
372 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
373 SILC_STATUS_ERR_TOO_MANY_PARAMS);
377 /* Get the nickname@server string and parse it. */
378 tmp = silc_command_get_first_arg(cmd->payload, NULL);
380 if (strchr(tmp, '@')) {
381 len = strcspn(tmp, "@");
382 nick = silc_calloc(len + 1, sizeof(char));
383 memcpy(nick, tmp, len);
384 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
385 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
390 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
391 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
395 /* Get the max count of reply messages allowed */
397 tmp = silc_command_get_next_arg(cmd->payload, NULL);
399 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
400 SILC_STATUS_ERR_TOO_MANY_PARAMS);
404 silc_free(server_name);
410 /* Then, make the query from our local client list */
411 entry = silc_idlist_find_client_by_nickname(server->local_list,
415 /* If we are normal server and are connected to a router we will
416 make global query from the router. */
417 if (server->server_type == SILC_SERVER && !server->standalone) {
422 /* If we are router then we will check our global list as well. */
423 if (server->server_type == SILC_ROUTER) {
425 silc_idlist_find_client_by_nickname(server->global_list,
428 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
429 SILC_STATUS_ERR_NO_SUCH_NICK,
430 3, tmp, strlen(tmp));
436 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
437 SILC_STATUS_ERR_NO_SUCH_NICK,
438 3, tmp, strlen(tmp));
443 /* XXX, works only for local server info */
445 /* Send WHOIS reply */
446 id_string = silc_id_id2str(entry->id, SILC_ID_CLIENT);
447 tmp = silc_command_get_first_arg(cmd->payload, NULL);
450 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
451 char nh[256], uh[256];
452 unsigned char idle[4];
453 SilcSocketConnection hsock;
455 memset(uh, 0, sizeof(uh));
456 memset(nh, 0, sizeof(nh));
458 strncat(nh, entry->nickname, strlen(entry->nickname));
460 len = entry->router ? strlen(entry->router->server_name) :
461 strlen(server->server_name);
462 strncat(nh, entry->router ? entry->router->server_name :
463 server->server_name, len);
465 strncat(uh, entry->username, strlen(entry->username));
467 hsock = (SilcSocketConnection)entry->connection;
468 len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
469 strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
471 SILC_PUT32_MSB((time(NULL) - entry->last_receive), idle);
476 silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS,
478 2, id_string, SILC_ID_CLIENT_LEN,
482 strlen(entry->userinfo),
486 silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS,
488 2, id_string, SILC_ID_CLIENT_LEN,
496 silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS,
498 2, id_string, SILC_ID_CLIENT_LEN,
500 strlen(entry->nickname),
501 4, tmp, strlen(tmp)); /* XXX */
503 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
504 0, packet->data, packet->len, FALSE);
506 silc_free(id_string);
507 silc_buffer_free(packet);
510 silc_server_command_free(cmd);
513 SILC_SERVER_CMD_FUNC(whowas)
517 SILC_SERVER_CMD_FUNC(identify)
519 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
520 SilcServer server = cmd->server;
521 char *tmp, *nick = NULL, *server_name = NULL;
522 unsigned int argc, count = 0, len;
523 SilcClientEntry entry;
525 unsigned char *id_string;
527 SILC_LOG_DEBUG(("Start"));
529 argc = silc_command_get_arg_num(cmd->payload);
531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
532 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
536 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
537 SILC_STATUS_ERR_TOO_MANY_PARAMS);
541 /* Get the nickname@server string and parse it. */
542 tmp = silc_command_get_first_arg(cmd->payload, NULL);
544 if (strchr(tmp, '@')) {
545 len = strcspn(tmp, "@");
546 nick = silc_calloc(len + 1, sizeof(char));
547 memcpy(nick, tmp, len);
548 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
549 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
554 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
555 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
559 /* Get the max count of reply messages allowed */
561 tmp = silc_command_get_next_arg(cmd->payload, NULL);
563 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
564 SILC_STATUS_ERR_TOO_MANY_PARAMS);
571 entry = silc_idlist_find_client_by_nickname(server->local_list,
574 entry = silc_idlist_find_client_by_hash(server->global_list,
575 nick, server->md5hash);
577 /* If client was not found and if we are normal server and are connected
578 to a router we will make global query from the router. */
579 if (!entry && server->server_type == SILC_SERVER && !server->standalone &&
581 SilcBuffer buffer = cmd->packet->buffer;
583 SILC_LOG_DEBUG(("Requesting identify from router"));
585 /* Send IDENTIFY command to our router */
586 silc_buffer_push(buffer, buffer->data - buffer->head);
587 silc_server_packet_forward(server, (SilcSocketConnection)
588 server->id_entry->router->connection,
589 buffer->data, buffer->len, TRUE);
593 /* If we are router we have checked our local list by nickname and our
594 global list by hash so far. It is possible that the client is still not
595 found and we'll check it from local list by hash. */
596 if (!entry && server->server_type == SILC_ROUTER)
597 entry = silc_idlist_find_client_by_hash(server->local_list,
598 nick, server->md5hash);
601 /* The client definitely does not exist */
602 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
603 SILC_STATUS_ERR_NO_SUCH_NICK,
604 3, tmp, strlen(tmp));
608 /* Send IDENTIFY reply */
609 id_string = silc_id_id2str(entry->id, SILC_ID_CLIENT);
610 tmp = silc_command_get_first_arg(cmd->payload, NULL);
611 packet = silc_command_encode_reply_payload_va(SILC_COMMAND_IDENTIFY,
615 3, nick, strlen(nick));
616 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
617 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
618 silc_server_packet_send_dest(server, cmd->sock,
619 SILC_PACKET_COMMAND_REPLY, 0,
620 id, cmd->packet->src_id_type,
621 packet->data, packet->len, FALSE);
624 silc_server_packet_send(server, cmd->sock,
625 SILC_PACKET_COMMAND_REPLY, 0,
626 packet->data, packet->len, FALSE);
629 silc_free(id_string);
630 silc_buffer_free(packet);
636 silc_free(server_name);
637 silc_server_command_free(cmd);
640 /* Checks string for bad characters and returns TRUE if they are found. */
642 static int silc_server_command_bad_chars(char *nick)
644 if (strchr(nick, '\\')) return TRUE;
645 if (strchr(nick, '\"')) return TRUE;
646 if (strchr(nick, '´')) return TRUE;
647 if (strchr(nick, '`')) return TRUE;
648 if (strchr(nick, '\'')) return TRUE;
649 if (strchr(nick, '*')) return TRUE;
650 if (strchr(nick, '/')) return TRUE;
651 if (strchr(nick, '@')) return TRUE;
656 /* Server side of command NICK. Sets nickname for user. Setting
657 nickname causes generation of a new client ID for the client. The
658 new client ID is sent to the client after changing the nickname. */
660 SILC_SERVER_CMD_FUNC(nick)
662 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
663 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
664 SilcServer server = cmd->server;
666 SilcClientID *new_id;
670 SILC_LOG_DEBUG(("Start"));
672 /* Check number of arguments */
673 if (silc_command_get_arg_num(cmd->payload) < 1) {
674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
675 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
680 nick = silc_command_get_arg_type(cmd->payload, 1, NULL);
681 if (silc_server_command_bad_chars(nick) == TRUE) {
682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
683 SILC_STATUS_ERR_BAD_NICKNAME);
687 /* Create new Client ID */
688 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
689 cmd->server->md5hash, nick,
692 /* Send notify about nickname change to our router. We send the new
693 ID and ask to replace it with the old one. */
694 if (cmd->server->server_type == SILC_SERVER && !cmd->server->standalone)
695 silc_server_send_replace_id(server, server->id_entry->router->connection,
697 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
698 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
700 /* If we are router we have to distribute the new Client ID to all
702 if (cmd->server->server_type == SILC_ROUTER && !cmd->server->standalone)
703 silc_server_send_replace_id(server, server->id_entry->router->connection,
705 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
706 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
708 /* Remove old cache entry */
709 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
714 memset(id_entry->id, 0, SILC_ID_CLIENT_LEN);
715 silc_free(id_entry->id);
718 /* Save the nickname as this client is our local client */
719 if (id_entry->nickname)
720 silc_free(id_entry->nickname);
722 id_entry->nickname = strdup(nick);
723 id_entry->id = new_id;
725 /* Update client cache */
726 silc_idcache_add(server->local_list->clients, id_entry->nickname,
727 SILC_ID_CLIENT, id_entry->id, (void *)id_entry, TRUE);
729 /* Send the new Client ID as reply command back to client */
730 id_string = silc_id_id2str(id_entry->id, SILC_ID_CLIENT);
731 packet = silc_command_encode_reply_payload_va(SILC_COMMAND_NICK,
735 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
736 0, packet->data, packet->len, FALSE);
738 silc_free(id_string);
739 silc_buffer_free(packet);
742 silc_server_command_free(cmd);
745 SILC_SERVER_CMD_FUNC(list)
749 SILC_SERVER_CMD_FUNC(topic)
753 /* Server side of INVITE command. Invites some client to join some channel. */
755 SILC_SERVER_CMD_FUNC(invite)
757 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
758 SilcServer server = cmd->server;
759 SilcSocketConnection sock = cmd->sock, dest_sock;
760 SilcClientEntry sender, dest;
761 SilcClientID *dest_id;
762 SilcChannelEntry channel;
763 SilcChannelID *channel_id;
764 unsigned int argc, len;
765 unsigned char *id_string;
767 /* Check number of arguments */
768 argc = silc_command_get_arg_num(cmd->payload);
770 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
771 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
775 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
776 SILC_STATUS_ERR_TOO_MANY_PARAMS);
780 /* Get destination ID */
781 id_string = silc_command_get_arg_type(cmd->payload, 1, &len);
783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
784 SILC_STATUS_ERR_NO_CLIENT_ID);
787 dest_id = silc_id_str2id(id_string, SILC_ID_CLIENT);
790 id_string = silc_command_get_arg_type(cmd->payload, 2, &len);
792 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
793 SILC_STATUS_ERR_NO_CHANNEL_ID);
796 channel_id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
798 /* Check whether the channel exists */
799 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
801 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
802 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
806 /* Check whether the sender of this command is on the channel. */
807 sender = (SilcClientEntry )sock->user_data;
808 if (!silc_server_client_on_channel(sender, channel)) {
809 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
810 SILC_STATUS_ERR_NOT_ON_CHANNEL);
814 /* Check whether the channel is invite-only channel. If yes then the
815 sender of this command must be at least channel operator. */
818 /* Find the connection data for the destination. If it is local we will
819 send it directly otherwise we will send it to router for routing. */
820 dest = silc_idlist_find_client_by_id(server->local_list, dest_id);
822 dest_sock = (SilcSocketConnection)dest->connection;
824 dest_sock = silc_server_get_route(server, dest_id, SILC_ID_CLIENT);
826 /* Check whether the requested client is already on the channel. */
827 /* XXX if we are normal server we don't know about global clients on
828 the channel thus we must request it (NAMES command), check from
829 local cache as well. */
830 if (silc_server_client_on_channel(dest, channel)) {
831 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
832 SILC_STATUS_ERR_USER_ON_CHANNEL);
836 /* Send notify to the client that is invited to the channel */
837 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
838 SILC_NOTIFY_TYPE_INVITE,
839 "%s invites you to channel %s",
840 sender->nickname, channel->channel_name);
842 /* Send command reply */
843 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
847 silc_server_command_free(cmd);
850 /* Quits connection to client. This gets called if client won't
851 close the connection even when it has issued QUIT command. */
853 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
855 SilcServer server = (SilcServer)context;
856 SilcSocketConnection sock = server->sockets[fd];
858 /* Free all client specific data, such as client entry and entires
859 on channels this client may be on. */
860 silc_server_free_sock_user_data(server, sock);
862 /* Close the connection on our side */
863 silc_server_close_connection(server, sock);
866 /* Quits SILC session. This is the normal way to disconnect client. */
868 SILC_SERVER_CMD_FUNC(quit)
870 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
871 SilcServer server = cmd->server;
872 SilcSocketConnection sock = cmd->sock;
874 SILC_LOG_DEBUG(("Start"));
876 /* We quit the connection with little timeout */
877 silc_task_register(server->timeout_queue, sock->sock,
878 silc_server_command_quit_cb, server,
879 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
881 silc_server_command_free(cmd);
884 SILC_SERVER_CMD_FUNC(kill)
888 /* Server side of command INFO. This sends information about us to
889 the client. If client requested specific server we will send the
890 command to that server. */
892 SILC_SERVER_CMD_FUNC(info)
894 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
895 SilcServer server = cmd->server;
898 unsigned char *id_string;
899 char info_string[256], *dest_server;
901 argc = silc_command_get_arg_num(cmd->payload);
903 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
904 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
908 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
909 SILC_STATUS_ERR_TOO_MANY_PARAMS);
913 /* Get server name */
914 dest_server = silc_command_get_arg_type(cmd->payload, 1, NULL);
916 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
917 SILC_STATUS_ERR_NO_SUCH_SERVER);
921 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
923 memset(info_string, 0, sizeof(info_string));
924 snprintf(info_string, sizeof(info_string),
925 "location: %s server: %s admin: %s <%s>",
926 server->config->admin_info->location,
927 server->config->admin_info->server_type,
928 server->config->admin_info->admin_name,
929 server->config->admin_info->admin_email);
931 id_string = silc_id_id2str(server->id, SILC_ID_SERVER);
934 silc_command_encode_reply_payload_va(SILC_COMMAND_INFO,
936 2, id_string, SILC_ID_SERVER_LEN,
938 strlen(info_string));
939 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
940 packet->data, packet->len, FALSE);
942 silc_free(id_string);
943 silc_buffer_free(packet);
945 /* Send this command to the requested server */
947 if (server->server_type == SILC_SERVER && !server->standalone) {
951 if (server->server_type == SILC_ROUTER) {
957 silc_server_command_free(cmd);
960 SILC_SERVER_CMD_FUNC(connect)
964 /* Server side of command PING. This just replies to the ping. */
966 SILC_SERVER_CMD_FUNC(ping)
968 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
969 SilcServer server = cmd->server;
972 unsigned char *id_string;
974 argc = silc_command_get_arg_num(cmd->payload);
976 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
977 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
982 SILC_STATUS_ERR_TOO_MANY_PARAMS);
987 id_string = silc_command_get_arg_type(cmd->payload, 1, NULL);
989 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
990 SILC_STATUS_ERR_NO_SERVER_ID);
993 id = silc_id_str2id(id_string, SILC_ID_SERVER);
995 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
997 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1000 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1001 SILC_STATUS_ERR_NO_SUCH_SERVER);
1008 silc_server_command_free(cmd);
1011 SILC_SERVER_CMD_FUNC(oper)
1020 SilcChannelEntry channel;
1022 } JoinInternalContext;
1024 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1026 JoinInternalContext *ctx = (JoinInternalContext *)context;
1028 if (ctx->channel->key && ctx->channel->key_len) {
1029 silc_server_send_notify_to_channel(ctx->server, ctx->channel,
1030 SILC_NOTIFY_TYPE_JOIN,
1031 "%s (%s@%s) has joined channel %s",
1032 ctx->nickname, ctx->username,
1033 ctx->hostname, ctx->channel_name);
1036 silc_task_register(ctx->server->timeout_queue, fd,
1037 silc_server_command_join_notify, context,
1038 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1042 /* Assembles NAMES command and executes it. This is called when client
1043 joins to a channel and we wan't to send NAMES command reply to the
1046 void silc_server_command_send_names(SilcServer server,
1047 SilcSocketConnection sock,
1048 SilcChannelEntry channel)
1050 SilcServerCommandContext cmd;
1052 unsigned char *id_string;
1054 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1055 buffer = silc_command_encode_payload_va(SILC_COMMAND_NAMES, 1,
1056 1, id_string, SILC_ID_CHANNEL_LEN);
1058 cmd = silc_calloc(1, sizeof(*cmd));
1059 cmd->payload = silc_command_parse_payload(buffer);
1060 cmd->server = server;
1062 cmd->pending = FALSE;
1064 silc_server_command_names((void *)cmd);
1065 silc_free(id_string);
1069 /* Server side of command JOIN. Joins client into requested channel. If
1070 the channel does not exist it will be created. */
1072 SILC_SERVER_CMD_FUNC(join)
1074 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1075 SilcServer server = cmd->server;
1076 SilcSocketConnection sock = cmd->sock;
1077 SilcBuffer buffer = cmd->packet->buffer;
1078 int argc, i, tmp_len;
1079 char *tmp, *channel_name = NULL, *cipher = NULL, *id_string = NULL;
1080 unsigned char *passphrase, mode[4];
1081 SilcChannelEntry channel;
1082 SilcServerID *router_id;
1084 SilcClientEntry client;
1086 SILC_LOG_DEBUG(("Start"));
1088 /* Check number of parameters */
1089 argc = silc_command_get_arg_num(cmd->payload);
1091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1092 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1096 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1097 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1101 /* Get channel name */
1102 tmp = silc_command_get_arg_type(cmd->payload, 1, &tmp_len);
1103 channel_name = silc_calloc(tmp_len + 1, sizeof(*channel_name));
1104 memcpy(channel_name, tmp, tmp_len);
1105 if (silc_server_command_bad_chars(tmp) == TRUE) {
1106 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1107 SILC_STATUS_ERR_BAD_CHANNEL);
1108 silc_free(channel_name);
1112 /* Get passphrase */
1113 tmp = silc_command_get_arg_type(cmd->payload, 2, &tmp_len);
1115 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1116 memcpy(passphrase, tmp, tmp_len);
1119 /* Get cipher name */
1120 cipher = silc_command_get_arg_type(cmd->payload, 3, NULL);
1122 /* See if the channel exists */
1124 silc_idlist_find_channel_by_name(server->local_list, channel_name);
1126 /* Channel not found */
1128 /* If we are standalone server we don't have a router, we just create
1129 the channel by ourselves. */
1130 if (server->standalone) {
1131 router_id = server->id;
1132 channel = silc_server_new_channel(server, router_id,
1133 cipher, channel_name);
1140 /* No channel ID found, the channel does not exist on our server.
1141 We send JOIN command to our router which will handle the joining
1142 procedure (either creates the channel if it doesn't exist or
1143 joins the client to it) - if we are normal server. */
1144 if (server->server_type == SILC_SERVER) {
1146 /* Forward the original JOIN command to the router */
1147 silc_buffer_push(buffer, buffer->data - buffer->head);
1148 silc_server_packet_forward(server, (SilcSocketConnection)
1149 server->id_entry->router->connection,
1150 buffer->data, buffer->len, TRUE);
1152 /* Add the command to be pending. It will be re-executed after
1153 router has replied back to us. */
1154 cmd->pending = TRUE;
1155 silc_server_command_pending(SILC_COMMAND_JOIN,
1156 silc_server_command_join, context);
1161 /* If we are router and the channel does not exist we will check our
1162 global list for the channel. */
1163 if (!channel && server->server_type == SILC_ROUTER) {
1165 /* Notify all routers about the new channel in SILC network. */
1166 if (!server->standalone) {
1168 silc_server_send_new_id(server, server->id_entry->router->connection,
1170 xxx, SILC_ID_CHANNEL, SILC_ID_CHANNEL_LEN);
1178 /* If the JOIN request was forwarded to us we will make a bit slower
1179 query to get the client pointer. Otherwise, we get the client pointer
1181 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1182 client = (SilcClientEntry)sock->user_data;
1184 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1185 client = silc_idlist_find_client_by_id(server->local_list, id);
1193 /* Check whether the client already is on the channel */
1194 if (silc_server_client_on_channel(client, channel)) {
1195 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1196 SILC_STATUS_ERR_USER_ON_CHANNEL);
1197 silc_free(channel_name);
1201 /* Join the client to the channel */
1202 i = channel->user_list_count;
1203 channel->user_list = silc_realloc(channel->user_list,
1204 sizeof(*channel->user_list) * (i + 1));
1205 channel->user_list[i].mode = SILC_CHANNEL_UMODE_NONE;
1206 channel->user_list[i].client = client;
1207 channel->user_list_count++;
1209 /* Add the channel to client's channel list */
1210 i = client->channel_count;
1211 client->channel = silc_realloc(client->channel,
1212 sizeof(*client->channel) * (i + 1));
1213 client->channel[i] = channel;
1214 client->channel_count++;
1216 /* Notify router about new user on channel. If we are normal server
1217 we send it to our router, if we are router we send it to our
1219 if (!server->standalone) {
1223 /* Send command reply to the client. Client receives the Channe ID,
1224 channel mode and possibly other information in this reply packet. */
1225 if (!cmd->pending) {
1226 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1227 SILC_PUT32_MSB(channel->mode, mode);
1229 if (!channel->topic)
1231 silc_command_encode_reply_payload_va(SILC_COMMAND_JOIN,
1234 strlen(channel_name),
1235 3, id_string, SILC_ID_CHANNEL_LEN,
1239 silc_command_encode_reply_payload_va(SILC_COMMAND_JOIN,
1242 strlen(channel_name),
1243 3, id_string, SILC_ID_CHANNEL_LEN,
1246 strlen(channel->topic));
1248 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1249 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1250 silc_server_packet_send_dest(cmd->server, cmd->sock,
1251 SILC_PACKET_COMMAND_REPLY, 0,
1252 id, cmd->packet->src_id_type,
1253 packet->data, packet->len, FALSE);
1256 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1257 packet->data, packet->len, FALSE);
1259 silc_buffer_free(packet);
1262 /* Send channel key to the client. Client cannot start transmitting
1263 to the channel until we have sent the key. */
1264 if (!cmd->pending) {
1265 tmp_len = strlen(channel->channel_key->cipher->name);
1267 silc_channel_key_encode_payload(SILC_ID_CHANNEL_LEN,
1269 channel->channel_key->cipher->name,
1270 channel->key_len / 8, channel->key);
1272 silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
1273 packet->data, packet->len, FALSE);
1274 silc_buffer_free(packet);
1278 silc_free(id_string);
1280 /* Finally, send notify message to all clients on the channel about
1281 new user on the channel. */
1282 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1283 if (!cmd->pending) {
1284 silc_server_send_notify_to_channel(server, channel,
1285 SILC_NOTIFY_TYPE_JOIN,
1286 "%s (%s@%s) has joined channel %s",
1287 client->nickname, client->username,
1288 sock->hostname ? sock->hostname :
1289 sock->ip, channel_name);
1291 /* This is pending command request. Send the notify after we have
1292 received the key for the channel from the router. */
1293 JoinInternalContext *ctx = silc_calloc(1, sizeof(*ctx));
1294 ctx->channel_name = channel_name;
1295 ctx->nickname = client->nickname;
1296 ctx->username = client->username;
1297 ctx->hostname = sock->hostname ? sock->hostname : sock->ip;
1298 ctx->channel = channel;
1299 ctx->server = server;
1300 silc_task_register(server->timeout_queue, sock->sock,
1301 silc_server_command_join_notify, ctx,
1302 0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1306 /* Send NAMES command reply to the joined channel so the user sees who
1307 is currently on the channel. */
1308 silc_server_command_send_names(server, sock, channel);
1311 silc_server_command_free(cmd);
1314 /* Server side of command MOTD. Sends servers current "message of the
1315 day" to the client. */
1317 SILC_SERVER_CMD_FUNC(motd)
1320 SILC_LOG_DEBUG(("Start"));
1324 SILC_SERVER_CMD_FUNC(umode)
1328 SILC_SERVER_CMD_FUNC(cmode)
1332 SILC_SERVER_CMD_FUNC(kick)
1336 SILC_SERVER_CMD_FUNC(restart)
1340 SILC_SERVER_CMD_FUNC(close)
1344 SILC_SERVER_CMD_FUNC(die)
1348 SILC_SERVER_CMD_FUNC(silcoper)
1352 /* Server side command of LEAVE. Removes client from a channel. */
1354 SILC_SERVER_CMD_FUNC(leave)
1356 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1357 SilcServer server = cmd->server;
1358 SilcSocketConnection sock = cmd->sock;
1359 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
1361 SilcChannelEntry channel;
1363 unsigned int i, argc, key_len;
1364 unsigned char *tmp, channel_key[32];
1366 SILC_LOG_DEBUG(("Start"));
1368 argc = silc_command_get_arg_num(cmd->payload);
1370 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1371 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1375 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1376 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1380 /* Get Channel ID */
1381 tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
1383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1384 SILC_STATUS_ERR_NO_CHANNEL_ID);
1387 id = silc_id_str2id(tmp, SILC_ID_CHANNEL);
1389 /* Get channel entry */
1390 channel = silc_idlist_find_channel_by_id(server->local_list, id);
1392 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1393 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1397 /* Check whether this client is on the channel */
1398 if (!silc_server_client_on_channel(id_entry, channel)) {
1399 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1400 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1404 /* Notify routers that they should remove this client from their list
1405 of clients on the channel. */
1406 if (!server->standalone)
1407 silc_server_send_remove_channel_user(server,
1408 server->id_entry->router->connection,
1409 server->server_type == SILC_ROUTER ?
1410 TRUE : FALSE, id_entry->id, id);
1412 /* Remove client from channel */
1413 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
1415 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1418 /* If the channel does not exist anymore we won't send anything */
1422 /* Re-generate channel key */
1423 key_len = channel->key_len / 8;
1424 for (i = 0; i < key_len; i++)
1425 channel_key[i] = silc_rng_get_byte(server->rng);
1426 channel->channel_key->cipher->set_key(channel->channel_key->context,
1427 channel_key, key_len);
1428 memset(channel->key, 0, key_len);
1429 silc_free(channel->key);
1430 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1431 memcpy(channel->key, channel_key, key_len);
1432 memset(channel_key, 0, sizeof(channel_key));
1434 /* Encode channel key payload to be distributed on the channel */
1436 silc_channel_key_encode_payload(SILC_ID_CHANNEL_LEN, tmp,
1437 strlen(channel->channel_key->cipher->name),
1438 channel->channel_key->cipher->name,
1439 key_len, channel->key);
1441 /* If we are normal server then we will send it to our router. If we
1442 are router we will send it to all local servers that has clients on
1444 if (server->server_type == SILC_SERVER) {
1445 if (!server->standalone)
1446 silc_server_packet_send(server,
1447 cmd->server->id_entry->router->connection,
1448 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1454 /* Send to locally connected clients on the channel */
1455 silc_server_packet_send_local_channel(server, channel,
1456 SILC_PACKET_CHANNEL_KEY, 0,
1457 packet->data, packet->len, FALSE);
1459 silc_buffer_free(packet);
1463 silc_server_command_free(cmd);
1466 /* Server side of command NAMES. Resolves clients and their names currently
1467 joined on the requested channel. The name list is sent back to the
1470 SILC_SERVER_CMD_FUNC(names)
1472 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1473 SilcServer server = cmd->server;
1474 SilcChannelEntry channel;
1477 unsigned int i, len, len2, argc;
1479 char *name_list = NULL, *n;
1480 SilcBuffer client_id_list;
1482 SILC_LOG_DEBUG(("Start"));
1484 argc = silc_command_get_arg_num(cmd->payload);
1486 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
1487 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1491 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
1492 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1496 /* Get Channel ID */
1497 tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
1499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1500 SILC_STATUS_ERR_NO_CHANNEL_ID);
1503 id = silc_id_str2id(tmp, SILC_ID_CHANNEL);
1505 /* Check whether the channel exists. If we are normal server and the
1506 channel does not exist we will send this same command to our router
1507 which will know if the channel exists. */
1508 channel = silc_idlist_find_channel_by_id(server->local_list, id);
1510 if (server->server_type == SILC_SERVER && !server->standalone) {
1511 /* XXX Send names command */
1513 cmd->pending = TRUE;
1514 silc_server_command_pending(SILC_COMMAND_NAMES,
1515 silc_server_command_names, context);
1519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1520 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1524 /* Assemble the name list now */
1527 for (i = 0; i < channel->user_list_count; i++) {
1528 if (!channel->user_list[i].client)
1531 n = channel->user_list[i].client->nickname;
1535 name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
1536 memcpy(name_list + (len - len2), n, len2);
1539 if (i == channel->user_list_count - 1)
1541 memcpy(name_list + len, ",", 1);
1548 /* Assemble the Client ID list now */
1549 client_id_list = silc_buffer_alloc(SILC_ID_CLIENT_LEN *
1550 channel->user_list_count);
1551 silc_buffer_pull_tail(client_id_list, (SILC_ID_CLIENT_LEN *
1552 channel->user_list_count));
1553 for (i = 0; i < channel->user_list_count; i++) {
1554 unsigned char *id_string;
1556 if (!channel->user_list[i].client)
1559 id_string = silc_id_id2str(channel->user_list[i].client->id,
1561 silc_buffer_format(client_id_list,
1562 SILC_STR_UI_XNSTRING(id_string, SILC_ID_CLIENT_LEN),
1564 silc_buffer_pull(client_id_list, SILC_ID_CLIENT_LEN);
1565 silc_free(id_string);
1567 silc_buffer_push(client_id_list,
1568 client_id_list->data - client_id_list->head);
1571 packet = silc_command_encode_reply_payload_va(SILC_COMMAND_NAMES,
1573 2, tmp, SILC_ID_CHANNEL_LEN,
1576 4, client_id_list->data,
1577 client_id_list->len);
1578 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1579 packet->data, packet->len, FALSE);
1581 silc_buffer_free(packet);
1582 silc_free(name_list);
1583 silc_buffer_free(client_id_list);
1587 silc_server_command_free(cmd);