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.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
37 unsigned int arg_type,
39 unsigned int arg_len);
40 static void silc_server_command_free(SilcServerCommandContext cmd);
42 /* Server command list. */
43 SilcServerCommand silc_command_list[] =
45 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
46 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
47 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
48 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
49 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
54 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(connect, CONNECT,
56 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
59 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
60 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
63 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(restart, RESTART,
65 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
66 SILC_SERVER_CMD(close, CLOSE,
67 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
68 SILC_SERVER_CMD(die, DIE, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
69 SILC_SERVER_CMD(silcoper, SILCOPER,
70 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
71 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
72 SILC_SERVER_CMD(names, NAMES, SILC_CF_LAG | SILC_CF_REG),
77 /* List of pending commands. */
78 SilcServerCommandPending *silc_command_pending = NULL;
80 /* Returns TRUE if the connection is registered. Unregistered connections
81 usually cannot send commands hence the check. */
83 static int silc_server_is_registered(SilcServer server,
84 SilcSocketConnection sock,
85 SilcServerCommandContext cmd,
89 case SILC_SOCKET_TYPE_CLIENT:
91 SilcClientEntry client = (SilcClientEntry)sock->user_data;
92 if (client->registered)
96 case SILC_SOCKET_TYPE_SERVER:
97 case SILC_SOCKET_TYPE_ROUTER:
99 SilcServerEntry serv = (SilcServerEntry)sock->user_data;
100 if (serv->registered)
108 silc_server_command_send_status_reply(cmd, command,
109 SILC_STATUS_ERR_NOT_REGISTERED);
110 silc_server_command_free(cmd);
114 /* Processes received command packet. */
116 void silc_server_command_process(SilcServer server,
117 SilcSocketConnection sock,
118 SilcPacketContext *packet)
120 SilcServerCommandContext ctx;
121 SilcServerCommand *cmd;
123 /* Check whether it is allowed for this connection to execute any
125 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
127 SilcClientEntry client = (SilcClientEntry)sock->user_data;
132 /* Allow only one command executed in 2 seconds. */
133 curtime = time(NULL);
134 if (client->last_command && (curtime - client->last_command) < 2)
137 /* Update access time */
138 client->last_command = curtime;
141 /* Allocate command context. This must be free'd by the
142 command routine receiving it. */
143 ctx = silc_calloc(1, sizeof(*ctx));
144 ctx->server = server;
146 ctx->packet = packet; /* Save original packet */
148 /* Parse the command payload in the packet */
149 ctx->payload = silc_command_parse_payload(packet->buffer);
151 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
152 silc_buffer_free(packet->buffer);
157 /* Execute command. If this fails the packet is dropped. */
158 for (cmd = silc_command_list; cmd->cb; cmd++)
159 if (cmd->cmd == silc_command_get(ctx->payload)) {
161 if (!(cmd->flags & SILC_CF_REG)) {
166 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
173 SILC_LOG_ERROR(("Unknown command, packet dropped"));
179 silc_buffer_free(packet->buffer);
182 /* Add new pending command to the list of pending commands. Currently
183 pending commands are executed from command replies, thus we can
184 execute any command after receiving some specific command reply.
186 The argument `reply_cmd' is the command reply from where the callback
187 function is to be called, thus, it IS NOT the command to be executed. */
189 void silc_server_command_pending(SilcCommand reply_cmd,
190 SilcCommandCb callback,
193 SilcServerCommandPending *reply, *r;
195 reply = silc_calloc(1, sizeof(*reply));
196 reply->reply_cmd = reply_cmd;
197 reply->context = context;
198 reply->callback = callback;
200 if (silc_command_pending == NULL) {
201 silc_command_pending = reply;
205 for (r = silc_command_pending; r; r = r->next) {
206 if (r->next == NULL) {
213 /* Deletes pending command by reply command type. */
215 void silc_server_command_pending_del(SilcCommand reply_cmd)
217 SilcServerCommandPending *r, *tmp;
219 if (silc_command_pending) {
220 if (silc_command_pending->reply_cmd == reply_cmd) {
221 silc_free(silc_command_pending);
222 silc_command_pending = NULL;
226 for (r = silc_command_pending; r; r = r->next) {
227 if (r->next && r->next->reply_cmd == reply_cmd) {
229 r->next = r->next->next;
237 /* Free's the command context allocated before executing the command */
239 static void silc_server_command_free(SilcServerCommandContext cmd)
242 silc_command_free_payload(cmd->payload);
247 /* Sends simple status message as command reply packet */
250 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
252 SilcCommandStatus status)
256 SILC_LOG_DEBUG(("Sending command status %d", status));
258 buffer = silc_command_encode_reply_payload_va(command, status, 0);
259 silc_server_packet_send(cmd->server, cmd->sock,
260 SILC_PACKET_COMMAND_REPLY, 0,
261 buffer->data, buffer->len, FALSE);
262 silc_buffer_free(buffer);
265 /* Sends command status reply with one extra argument. The argument
266 type must be sent as argument. */
269 silc_server_command_send_status_data(SilcServerCommandContext cmd,
271 SilcCommandStatus status,
272 unsigned int arg_type,
274 unsigned int arg_len)
278 SILC_LOG_DEBUG(("Sending command status %d", status));
280 buffer = silc_command_encode_reply_payload_va(command, status, 1,
281 arg_type, arg, arg_len);
282 silc_server_packet_send(cmd->server, cmd->sock,
283 SILC_PACKET_COMMAND_REPLY, 0,
284 buffer->data, buffer->len, FALSE);
285 silc_buffer_free(buffer);
288 /* Server side of command WHOIS. Processes user's query and sends found
289 results as command replies back to the client. */
291 SILC_SERVER_CMD_FUNC(whois)
293 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
294 SilcServer server = cmd->server;
295 char *tmp, *nick = NULL, *server_name = NULL;
296 unsigned int argc, count = 0, len;
297 SilcClientEntry entry;
299 unsigned char *id_string;
301 SILC_LOG_DEBUG(("Start"));
303 argc = silc_command_get_arg_num(cmd->payload);
305 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
306 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
311 SILC_STATUS_ERR_TOO_MANY_PARAMS);
315 /* Get the nickname@server string and parse it. */
316 tmp = silc_command_get_first_arg(cmd->payload, NULL);
318 if (strchr(tmp, '@')) {
319 len = strcspn(tmp, "@");
320 nick = silc_calloc(len + 1, sizeof(char));
321 memcpy(nick, tmp, len);
322 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
323 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
329 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
333 /* Get the max count of reply messages allowed */
335 tmp = silc_command_get_next_arg(cmd->payload, NULL);
337 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
338 SILC_STATUS_ERR_TOO_MANY_PARAMS);
342 silc_free(server_name);
348 /* Then, make the query from our local client list */
349 entry = silc_idlist_find_client_by_nickname(server->local_list,
353 /* If we are normal server and are connected to a router we will
354 make global query from the router. */
355 if (server->server_type == SILC_SERVER && !server->standalone) {
360 /* If we are router then we will check our global list as well. */
361 if (server->server_type == SILC_ROUTER) {
363 silc_idlist_find_client_by_nickname(server->global_list,
366 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
367 SILC_STATUS_ERR_NO_SUCH_NICK,
368 3, tmp, strlen(tmp));
374 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
375 SILC_STATUS_ERR_NO_SUCH_NICK,
376 3, tmp, strlen(tmp));
381 /* XXX, works only for local server info */
383 /* Send WHOIS reply */
384 id_string = silc_id_id2str(entry->id, SILC_ID_CLIENT);
385 tmp = silc_command_get_first_arg(cmd->payload, NULL);
388 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
389 char nh[256], uh[256];
390 unsigned char idle[4];
391 SilcSocketConnection hsock;
393 memset(uh, 0, sizeof(uh));
394 memset(nh, 0, sizeof(nh));
396 strncat(nh, entry->nickname, strlen(entry->nickname));
398 len = entry->router ? strlen(entry->router->server_name) :
399 strlen(server->server_name);
400 strncat(nh, entry->router ? entry->router->server_name :
401 server->server_name, len);
403 strncat(uh, entry->username, strlen(entry->username));
405 hsock = (SilcSocketConnection)entry->connection;
406 len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
407 strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
409 SILC_PUT32_MSB((time(NULL) - entry->last_receive), idle);
414 silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS,
416 2, id_string, SILC_ID_CLIENT_LEN,
420 strlen(entry->userinfo),
424 silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS,
426 2, id_string, SILC_ID_CLIENT_LEN,
434 silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS,
436 2, id_string, SILC_ID_CLIENT_LEN,
438 strlen(entry->nickname),
439 4, tmp, strlen(tmp)); /* XXX */
441 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
442 0, packet->data, packet->len, FALSE);
444 silc_free(id_string);
445 silc_buffer_free(packet);
448 silc_server_command_free(cmd);
451 SILC_SERVER_CMD_FUNC(whowas)
455 SILC_SERVER_CMD_FUNC(identify)
457 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
458 SilcServer server = cmd->server;
459 char *tmp, *nick = NULL, *server_name = NULL;
460 unsigned int argc, count = 0, len;
461 SilcClientEntry entry;
463 unsigned char *id_string;
465 SILC_LOG_DEBUG(("Start"));
467 argc = silc_command_get_arg_num(cmd->payload);
469 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
470 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
474 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
475 SILC_STATUS_ERR_TOO_MANY_PARAMS);
479 /* Get the nickname@server string and parse it. */
480 tmp = silc_command_get_first_arg(cmd->payload, NULL);
482 if (strchr(tmp, '@')) {
483 len = strcspn(tmp, "@");
484 nick = silc_calloc(len + 1, sizeof(char));
485 memcpy(nick, tmp, len);
486 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
487 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
492 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
493 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
497 /* Get the max count of reply messages allowed */
499 tmp = silc_command_get_next_arg(cmd->payload, NULL);
501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
502 SILC_STATUS_ERR_TOO_MANY_PARAMS);
509 entry = silc_idlist_find_client_by_nickname(server->local_list,
512 entry = silc_idlist_find_client_by_hash(server->global_list,
513 nick, server->md5hash);
515 /* If client was not found and if we are normal server and are connected
516 to a router we will make global query from the router. */
517 if (!entry && server->server_type == SILC_SERVER && !server->standalone &&
519 SilcBuffer buffer = cmd->packet->buffer;
521 SILC_LOG_DEBUG(("Requesting identify from router"));
523 /* Send IDENTIFY command to our router */
524 silc_buffer_push(buffer, buffer->data - buffer->head);
525 silc_server_packet_forward(server, (SilcSocketConnection)
526 server->id_entry->router->connection,
527 buffer->data, buffer->len, TRUE);
531 /* If we are router we have checked our local list by nickname and our
532 global list by hash so far. It is possible that the client is still not
533 found and we'll check it from local list by hash. */
534 if (!entry && server->server_type == SILC_ROUTER)
535 entry = silc_idlist_find_client_by_hash(server->local_list,
536 nick, server->md5hash);
539 /* The client definitely does not exist */
540 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
541 SILC_STATUS_ERR_NO_SUCH_NICK,
542 3, tmp, strlen(tmp));
546 /* Send IDENTIFY reply */
547 id_string = silc_id_id2str(entry->id, SILC_ID_CLIENT);
548 tmp = silc_command_get_first_arg(cmd->payload, NULL);
549 packet = silc_command_encode_reply_payload_va(SILC_COMMAND_IDENTIFY,
553 3, nick, strlen(nick));
554 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
555 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
556 silc_server_packet_send_dest(server, cmd->sock,
557 SILC_PACKET_COMMAND_REPLY, 0,
558 id, cmd->packet->src_id_type,
559 packet->data, packet->len, FALSE);
562 silc_server_packet_send(server, cmd->sock,
563 SILC_PACKET_COMMAND_REPLY, 0,
564 packet->data, packet->len, FALSE);
567 silc_free(id_string);
568 silc_buffer_free(packet);
574 silc_free(server_name);
575 silc_server_command_free(cmd);
578 /* Checks string for bad characters and returns TRUE if they are found. */
580 static int silc_server_command_bad_chars(char *nick)
582 if (strchr(nick, '\\')) return TRUE;
583 if (strchr(nick, '\"')) return TRUE;
584 if (strchr(nick, '´')) return TRUE;
585 if (strchr(nick, '`')) return TRUE;
586 if (strchr(nick, '\'')) return TRUE;
587 if (strchr(nick, '*')) return TRUE;
588 if (strchr(nick, '/')) return TRUE;
589 if (strchr(nick, '@')) return TRUE;
594 /* Server side of command NICK. Sets nickname for user. Setting
595 nickname causes generation of a new client ID for the client. The
596 new client ID is sent to the client after changing the nickname. */
598 SILC_SERVER_CMD_FUNC(nick)
600 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
601 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
602 SilcServer server = cmd->server;
604 SilcClientID *new_id;
608 SILC_LOG_DEBUG(("Start"));
610 /* Check number of arguments */
611 if (silc_command_get_arg_num(cmd->payload) < 1) {
612 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
613 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
618 nick = silc_command_get_arg_type(cmd->payload, 1, NULL);
619 if (silc_server_command_bad_chars(nick) == TRUE) {
620 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
621 SILC_STATUS_ERR_BAD_NICKNAME);
625 /* Create new Client ID */
626 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
627 cmd->server->md5hash, nick,
630 /* Send notify about nickname change to our router. We send the new
631 ID and ask to replace it with the old one. */
632 if (cmd->server->server_type == SILC_SERVER && !cmd->server->standalone)
633 silc_server_send_replace_id(server, server->id_entry->router->connection,
635 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
636 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
638 /* If we are router we have to distribute the new Client ID to all
640 if (cmd->server->server_type == SILC_ROUTER && !cmd->server->standalone)
641 silc_server_send_replace_id(server, server->id_entry->router->connection,
643 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
644 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
646 /* Remove old cache entry */
647 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
652 memset(id_entry->id, 0, SILC_ID_CLIENT_LEN);
653 silc_free(id_entry->id);
656 /* Save the nickname as this client is our local client */
657 if (id_entry->nickname)
658 silc_free(id_entry->nickname);
660 id_entry->nickname = strdup(nick);
661 id_entry->id = new_id;
663 /* Update client cache */
664 silc_idcache_add(server->local_list->clients, id_entry->nickname,
665 SILC_ID_CLIENT, id_entry->id, (void *)id_entry, TRUE);
667 /* Send the new Client ID as reply command back to client */
668 id_string = silc_id_id2str(id_entry->id, SILC_ID_CLIENT);
669 packet = silc_command_encode_reply_payload_va(SILC_COMMAND_NICK,
673 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
674 0, packet->data, packet->len, FALSE);
676 silc_free(id_string);
677 silc_buffer_free(packet);
680 silc_server_command_free(cmd);
683 SILC_SERVER_CMD_FUNC(list)
687 /* Server side of TOPIC command. Sets topic for channel and/or returns
688 current topic to client. */
690 SILC_SERVER_CMD_FUNC(topic)
692 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
693 SilcServer server = cmd->server;
694 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
695 SilcChannelID *channel_id;
696 SilcChannelEntry channel;
700 /* Check number of arguments */
701 argc = silc_command_get_arg_num(cmd->payload);
703 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
704 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
708 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
709 SILC_STATUS_ERR_TOO_MANY_PARAMS);
714 tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
716 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
717 SILC_STATUS_ERR_NO_CHANNEL_ID);
720 channel_id = silc_id_str2id(tmp, SILC_ID_CHANNEL);
724 tmp = silc_command_get_arg_type(cmd->payload, 2, NULL);
726 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
727 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
731 /* Check whether the channel exists */
732 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
734 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
735 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
739 /* Set the topic for channel */
740 channel->topic = strdup(tmp);
742 /* Send notify about topic change to all clients on the channel */
743 silc_server_send_notify_to_channel(server, channel,
744 SILC_NOTIFY_TYPE_TOPIC_SET,
745 "%s@%s set topic: %s",
747 cmd->sock->hostname ?
748 cmd->sock->hostname : cmd->sock->ip,
752 /* Send the topic to client as reply packet */
753 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
755 2, tmp, strlen(tmp));
758 silc_server_command_free(cmd);
761 /* Server side of INVITE command. Invites some client to join some channel. */
763 SILC_SERVER_CMD_FUNC(invite)
765 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
766 SilcServer server = cmd->server;
767 SilcSocketConnection sock = cmd->sock, dest_sock;
768 SilcClientEntry sender, dest;
769 SilcClientID *dest_id;
770 SilcChannelEntry channel;
771 SilcChannelID *channel_id;
772 unsigned int argc, len;
773 unsigned char *id_string;
775 /* Check number of arguments */
776 argc = silc_command_get_arg_num(cmd->payload);
778 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
779 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
784 SILC_STATUS_ERR_TOO_MANY_PARAMS);
788 /* Get destination ID */
789 id_string = silc_command_get_arg_type(cmd->payload, 1, &len);
791 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
792 SILC_STATUS_ERR_NO_CLIENT_ID);
795 dest_id = silc_id_str2id(id_string, SILC_ID_CLIENT);
798 id_string = silc_command_get_arg_type(cmd->payload, 2, &len);
800 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
801 SILC_STATUS_ERR_NO_CHANNEL_ID);
804 channel_id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
806 /* Check whether the channel exists */
807 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
809 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
810 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
814 /* Check whether the sender of this command is on the channel. */
815 sender = (SilcClientEntry )sock->user_data;
816 if (!silc_server_client_on_channel(sender, channel)) {
817 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
818 SILC_STATUS_ERR_NOT_ON_CHANNEL);
822 /* Check whether the channel is invite-only channel. If yes then the
823 sender of this command must be at least channel operator. */
826 /* Find the connection data for the destination. If it is local we will
827 send it directly otherwise we will send it to router for routing. */
828 dest = silc_idlist_find_client_by_id(server->local_list, dest_id);
830 dest_sock = (SilcSocketConnection)dest->connection;
832 dest_sock = silc_server_get_route(server, dest_id, SILC_ID_CLIENT);
834 /* Check whether the requested client is already on the channel. */
835 /* XXX if we are normal server we don't know about global clients on
836 the channel thus we must request it (NAMES command), check from
837 local cache as well. */
838 if (silc_server_client_on_channel(dest, channel)) {
839 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
840 SILC_STATUS_ERR_USER_ON_CHANNEL);
844 /* Send notify to the client that is invited to the channel */
845 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
846 SILC_NOTIFY_TYPE_INVITE,
847 "%s invites you to channel %s",
848 sender->nickname, channel->channel_name);
850 /* Send command reply */
851 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
855 silc_server_command_free(cmd);
858 /* Quits connection to client. This gets called if client won't
859 close the connection even when it has issued QUIT command. */
861 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
863 SilcServer server = (SilcServer)context;
864 SilcSocketConnection sock = server->sockets[fd];
866 /* Free all client specific data, such as client entry and entires
867 on channels this client may be on. */
868 silc_server_free_sock_user_data(server, sock);
870 /* Close the connection on our side */
871 silc_server_close_connection(server, sock);
874 /* Quits SILC session. This is the normal way to disconnect client. */
876 SILC_SERVER_CMD_FUNC(quit)
878 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
879 SilcServer server = cmd->server;
880 SilcSocketConnection sock = cmd->sock;
882 SILC_LOG_DEBUG(("Start"));
884 /* We quit the connection with little timeout */
885 silc_task_register(server->timeout_queue, sock->sock,
886 silc_server_command_quit_cb, server,
887 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
889 silc_server_command_free(cmd);
892 SILC_SERVER_CMD_FUNC(kill)
896 /* Server side of command INFO. This sends information about us to
897 the client. If client requested specific server we will send the
898 command to that server. */
900 SILC_SERVER_CMD_FUNC(info)
902 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
903 SilcServer server = cmd->server;
906 unsigned char *id_string;
907 char info_string[256], *dest_server;
909 argc = silc_command_get_arg_num(cmd->payload);
911 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
912 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
916 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
917 SILC_STATUS_ERR_TOO_MANY_PARAMS);
921 /* Get server name */
922 dest_server = silc_command_get_arg_type(cmd->payload, 1, NULL);
924 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
925 SILC_STATUS_ERR_NO_SUCH_SERVER);
929 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
931 memset(info_string, 0, sizeof(info_string));
932 snprintf(info_string, sizeof(info_string),
933 "location: %s server: %s admin: %s <%s>",
934 server->config->admin_info->location,
935 server->config->admin_info->server_type,
936 server->config->admin_info->admin_name,
937 server->config->admin_info->admin_email);
939 id_string = silc_id_id2str(server->id, SILC_ID_SERVER);
942 silc_command_encode_reply_payload_va(SILC_COMMAND_INFO,
944 2, id_string, SILC_ID_SERVER_LEN,
946 strlen(info_string));
947 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
948 packet->data, packet->len, FALSE);
950 silc_free(id_string);
951 silc_buffer_free(packet);
953 /* Send this command to the requested server */
955 if (server->server_type == SILC_SERVER && !server->standalone) {
959 if (server->server_type == SILC_ROUTER) {
965 silc_server_command_free(cmd);
968 SILC_SERVER_CMD_FUNC(connect)
972 /* Server side of command PING. This just replies to the ping. */
974 SILC_SERVER_CMD_FUNC(ping)
976 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
977 SilcServer server = cmd->server;
980 unsigned char *id_string;
982 argc = silc_command_get_arg_num(cmd->payload);
984 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
985 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
989 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
990 SILC_STATUS_ERR_TOO_MANY_PARAMS);
995 id_string = silc_command_get_arg_type(cmd->payload, 1, NULL);
997 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
998 SILC_STATUS_ERR_NO_SERVER_ID);
1001 id = silc_id_str2id(id_string, SILC_ID_SERVER);
1003 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1004 /* Send our reply */
1005 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1008 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1009 SILC_STATUS_ERR_NO_SUCH_SERVER);
1016 silc_server_command_free(cmd);
1019 SILC_SERVER_CMD_FUNC(oper)
1028 SilcChannelEntry channel;
1030 } JoinInternalContext;
1032 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1034 JoinInternalContext *ctx = (JoinInternalContext *)context;
1036 if (ctx->channel->key && ctx->channel->key_len) {
1037 silc_server_send_notify_to_channel(ctx->server, ctx->channel,
1038 SILC_NOTIFY_TYPE_JOIN,
1039 "%s (%s@%s) has joined channel %s",
1040 ctx->nickname, ctx->username,
1041 ctx->hostname, ctx->channel_name);
1044 silc_task_register(ctx->server->timeout_queue, fd,
1045 silc_server_command_join_notify, context,
1046 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1050 /* Assembles NAMES command and executes it. This is called when client
1051 joins to a channel and we wan't to send NAMES command reply to the
1054 void silc_server_command_send_names(SilcServer server,
1055 SilcSocketConnection sock,
1056 SilcChannelEntry channel)
1058 SilcServerCommandContext cmd;
1060 unsigned char *id_string;
1062 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1063 buffer = silc_command_encode_payload_va(SILC_COMMAND_NAMES, 1,
1064 1, id_string, SILC_ID_CHANNEL_LEN);
1066 cmd = silc_calloc(1, sizeof(*cmd));
1067 cmd->payload = silc_command_parse_payload(buffer);
1068 cmd->server = server;
1070 cmd->pending = FALSE;
1072 silc_server_command_names((void *)cmd);
1073 silc_free(id_string);
1077 /* Server side of command JOIN. Joins client into requested channel. If
1078 the channel does not exist it will be created. */
1080 SILC_SERVER_CMD_FUNC(join)
1082 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1083 SilcServer server = cmd->server;
1084 SilcSocketConnection sock = cmd->sock;
1085 SilcBuffer buffer = cmd->packet->buffer;
1086 int argc, i, tmp_len;
1087 char *tmp, *channel_name = NULL, *cipher = NULL, *id_string = NULL;
1088 unsigned char *passphrase, mode[4];
1089 SilcChannelEntry channel;
1090 SilcServerID *router_id;
1092 SilcClientEntry client;
1094 SILC_LOG_DEBUG(("Start"));
1096 /* Check number of parameters */
1097 argc = silc_command_get_arg_num(cmd->payload);
1099 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1100 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1104 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1105 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1109 /* Get channel name */
1110 tmp = silc_command_get_arg_type(cmd->payload, 1, &tmp_len);
1111 channel_name = silc_calloc(tmp_len + 1, sizeof(*channel_name));
1112 memcpy(channel_name, tmp, tmp_len);
1113 if (silc_server_command_bad_chars(tmp) == TRUE) {
1114 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1115 SILC_STATUS_ERR_BAD_CHANNEL);
1116 silc_free(channel_name);
1120 /* Get passphrase */
1121 tmp = silc_command_get_arg_type(cmd->payload, 2, &tmp_len);
1123 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1124 memcpy(passphrase, tmp, tmp_len);
1127 /* Get cipher name */
1128 cipher = silc_command_get_arg_type(cmd->payload, 3, NULL);
1130 /* See if the channel exists */
1132 silc_idlist_find_channel_by_name(server->local_list, channel_name);
1134 /* Channel not found */
1136 /* If we are standalone server we don't have a router, we just create
1137 the channel by ourselves. */
1138 if (server->standalone) {
1139 router_id = server->id;
1140 channel = silc_server_new_channel(server, router_id,
1141 cipher, channel_name);
1148 /* No channel ID found, the channel does not exist on our server.
1149 We send JOIN command to our router which will handle the joining
1150 procedure (either creates the channel if it doesn't exist or
1151 joins the client to it) - if we are normal server. */
1152 if (server->server_type == SILC_SERVER) {
1154 /* Forward the original JOIN command to the router */
1155 silc_buffer_push(buffer, buffer->data - buffer->head);
1156 silc_server_packet_forward(server, (SilcSocketConnection)
1157 server->id_entry->router->connection,
1158 buffer->data, buffer->len, TRUE);
1160 /* Add the command to be pending. It will be re-executed after
1161 router has replied back to us. */
1162 cmd->pending = TRUE;
1163 silc_server_command_pending(SILC_COMMAND_JOIN,
1164 silc_server_command_join, context);
1169 /* If we are router and the channel does not exist we will check our
1170 global list for the channel. */
1171 if (!channel && server->server_type == SILC_ROUTER) {
1173 /* Notify all routers about the new channel in SILC network. */
1174 if (!server->standalone) {
1176 silc_server_send_new_id(server, server->id_entry->router->connection,
1178 xxx, SILC_ID_CHANNEL, SILC_ID_CHANNEL_LEN);
1186 /* If the JOIN request was forwarded to us we will make a bit slower
1187 query to get the client pointer. Otherwise, we get the client pointer
1189 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1190 client = (SilcClientEntry)sock->user_data;
1192 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1193 client = silc_idlist_find_client_by_id(server->local_list, id);
1201 /* Check whether the client already is on the channel */
1202 if (silc_server_client_on_channel(client, channel)) {
1203 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1204 SILC_STATUS_ERR_USER_ON_CHANNEL);
1205 silc_free(channel_name);
1209 /* Join the client to the channel */
1210 i = channel->user_list_count;
1211 channel->user_list = silc_realloc(channel->user_list,
1212 sizeof(*channel->user_list) * (i + 1));
1213 channel->user_list[i].mode = SILC_CHANNEL_UMODE_NONE;
1214 channel->user_list[i].client = client;
1215 channel->user_list_count++;
1217 /* Add the channel to client's channel list */
1218 i = client->channel_count;
1219 client->channel = silc_realloc(client->channel,
1220 sizeof(*client->channel) * (i + 1));
1221 client->channel[i] = channel;
1222 client->channel_count++;
1224 /* Notify router about new user on channel. If we are normal server
1225 we send it to our router, if we are router we send it to our
1227 if (!server->standalone) {
1231 /* Send command reply to the client. Client receives the Channe ID,
1232 channel mode and possibly other information in this reply packet. */
1233 if (!cmd->pending) {
1234 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1235 SILC_PUT32_MSB(channel->mode, mode);
1237 if (!channel->topic)
1239 silc_command_encode_reply_payload_va(SILC_COMMAND_JOIN,
1242 strlen(channel_name),
1243 3, id_string, SILC_ID_CHANNEL_LEN,
1247 silc_command_encode_reply_payload_va(SILC_COMMAND_JOIN,
1250 strlen(channel_name),
1251 3, id_string, SILC_ID_CHANNEL_LEN,
1254 strlen(channel->topic));
1256 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1257 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1258 silc_server_packet_send_dest(cmd->server, cmd->sock,
1259 SILC_PACKET_COMMAND_REPLY, 0,
1260 id, cmd->packet->src_id_type,
1261 packet->data, packet->len, FALSE);
1264 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1265 packet->data, packet->len, FALSE);
1267 silc_buffer_free(packet);
1270 /* Send channel key to the client. Client cannot start transmitting
1271 to the channel until we have sent the key. */
1272 if (!cmd->pending) {
1273 tmp_len = strlen(channel->channel_key->cipher->name);
1275 silc_channel_key_encode_payload(SILC_ID_CHANNEL_LEN,
1277 channel->channel_key->cipher->name,
1278 channel->key_len / 8, channel->key);
1280 silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
1281 packet->data, packet->len, FALSE);
1282 silc_buffer_free(packet);
1286 silc_free(id_string);
1288 /* Finally, send notify message to all clients on the channel about
1289 new user on the channel. */
1290 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1291 if (!cmd->pending) {
1292 silc_server_send_notify_to_channel(server, channel,
1293 SILC_NOTIFY_TYPE_JOIN,
1294 "%s (%s@%s) has joined channel %s",
1295 client->nickname, client->username,
1296 sock->hostname ? sock->hostname :
1297 sock->ip, channel_name);
1299 /* This is pending command request. Send the notify after we have
1300 received the key for the channel from the router. */
1301 JoinInternalContext *ctx = silc_calloc(1, sizeof(*ctx));
1302 ctx->channel_name = channel_name;
1303 ctx->nickname = client->nickname;
1304 ctx->username = client->username;
1305 ctx->hostname = sock->hostname ? sock->hostname : sock->ip;
1306 ctx->channel = channel;
1307 ctx->server = server;
1308 silc_task_register(server->timeout_queue, sock->sock,
1309 silc_server_command_join_notify, ctx,
1310 0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1314 /* Send NAMES command reply to the joined channel so the user sees who
1315 is currently on the channel. */
1316 silc_server_command_send_names(server, sock, channel);
1319 silc_server_command_free(cmd);
1322 /* Server side of command MOTD. Sends server's current "message of the
1323 day" to the client. */
1325 SILC_SERVER_CMD_FUNC(motd)
1328 SILC_LOG_DEBUG(("Start"));
1332 SILC_SERVER_CMD_FUNC(umode)
1336 SILC_SERVER_CMD_FUNC(cmode)
1340 SILC_SERVER_CMD_FUNC(kick)
1344 SILC_SERVER_CMD_FUNC(restart)
1348 SILC_SERVER_CMD_FUNC(close)
1352 SILC_SERVER_CMD_FUNC(die)
1356 SILC_SERVER_CMD_FUNC(silcoper)
1360 /* Server side command of LEAVE. Removes client from a channel. */
1362 SILC_SERVER_CMD_FUNC(leave)
1364 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1365 SilcServer server = cmd->server;
1366 SilcSocketConnection sock = cmd->sock;
1367 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
1369 SilcChannelEntry channel;
1371 unsigned int i, argc, key_len;
1372 unsigned char *tmp, channel_key[32];
1374 SILC_LOG_DEBUG(("Start"));
1376 argc = silc_command_get_arg_num(cmd->payload);
1378 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1379 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1384 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1388 /* Get Channel ID */
1389 tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
1391 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1392 SILC_STATUS_ERR_NO_CHANNEL_ID);
1395 id = silc_id_str2id(tmp, SILC_ID_CHANNEL);
1397 /* Get channel entry */
1398 channel = silc_idlist_find_channel_by_id(server->local_list, id);
1400 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1401 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1405 /* Check whether this client is on the channel */
1406 if (!silc_server_client_on_channel(id_entry, channel)) {
1407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1408 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1412 /* Notify routers that they should remove this client from their list
1413 of clients on the channel. */
1414 if (!server->standalone)
1415 silc_server_send_remove_channel_user(server,
1416 server->id_entry->router->connection,
1417 server->server_type == SILC_ROUTER ?
1418 TRUE : FALSE, id_entry->id, id);
1420 /* Remove client from channel */
1421 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
1423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1426 /* If the channel does not exist anymore we won't send anything */
1430 /* Re-generate channel key */
1431 key_len = channel->key_len / 8;
1432 for (i = 0; i < key_len; i++)
1433 channel_key[i] = silc_rng_get_byte(server->rng);
1434 channel->channel_key->cipher->set_key(channel->channel_key->context,
1435 channel_key, key_len);
1436 memset(channel->key, 0, key_len);
1437 silc_free(channel->key);
1438 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1439 memcpy(channel->key, channel_key, key_len);
1440 memset(channel_key, 0, sizeof(channel_key));
1442 /* Encode channel key payload to be distributed on the channel */
1444 silc_channel_key_encode_payload(SILC_ID_CHANNEL_LEN, tmp,
1445 strlen(channel->channel_key->cipher->name),
1446 channel->channel_key->cipher->name,
1447 key_len, channel->key);
1449 /* If we are normal server then we will send it to our router. If we
1450 are router we will send it to all local servers that has clients on
1452 if (server->server_type == SILC_SERVER) {
1453 if (!server->standalone)
1454 silc_server_packet_send(server,
1455 cmd->server->id_entry->router->connection,
1456 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1462 /* Send to locally connected clients on the channel */
1463 silc_server_packet_send_local_channel(server, channel,
1464 SILC_PACKET_CHANNEL_KEY, 0,
1465 packet->data, packet->len, FALSE);
1467 silc_buffer_free(packet);
1471 silc_server_command_free(cmd);
1474 /* Server side of command NAMES. Resolves clients and their names currently
1475 joined on the requested channel. The name list is sent back to the
1478 SILC_SERVER_CMD_FUNC(names)
1480 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1481 SilcServer server = cmd->server;
1482 SilcChannelEntry channel;
1485 unsigned int i, len, len2, argc;
1487 char *name_list = NULL, *n;
1488 SilcBuffer client_id_list;
1490 SILC_LOG_DEBUG(("Start"));
1492 argc = silc_command_get_arg_num(cmd->payload);
1494 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
1495 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
1500 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1504 /* Get Channel ID */
1505 tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
1507 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1508 SILC_STATUS_ERR_NO_CHANNEL_ID);
1511 id = silc_id_str2id(tmp, SILC_ID_CHANNEL);
1513 /* Check whether the channel exists. If we are normal server and the
1514 channel does not exist we will send this same command to our router
1515 which will know if the channel exists. */
1516 channel = silc_idlist_find_channel_by_id(server->local_list, id);
1518 if (server->server_type == SILC_SERVER && !server->standalone) {
1519 /* XXX Send names command */
1521 cmd->pending = TRUE;
1522 silc_server_command_pending(SILC_COMMAND_NAMES,
1523 silc_server_command_names, context);
1527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1528 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1532 /* Assemble the name list now */
1535 for (i = 0; i < channel->user_list_count; i++) {
1536 if (!channel->user_list[i].client)
1539 n = channel->user_list[i].client->nickname;
1543 name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
1544 memcpy(name_list + (len - len2), n, len2);
1547 if (i == channel->user_list_count - 1)
1549 memcpy(name_list + len, ",", 1);
1556 /* Assemble the Client ID list now */
1557 client_id_list = silc_buffer_alloc(SILC_ID_CLIENT_LEN *
1558 channel->user_list_count);
1559 silc_buffer_pull_tail(client_id_list, (SILC_ID_CLIENT_LEN *
1560 channel->user_list_count));
1561 for (i = 0; i < channel->user_list_count; i++) {
1562 unsigned char *id_string;
1564 if (!channel->user_list[i].client)
1567 id_string = silc_id_id2str(channel->user_list[i].client->id,
1569 silc_buffer_format(client_id_list,
1570 SILC_STR_UI_XNSTRING(id_string, SILC_ID_CLIENT_LEN),
1572 silc_buffer_pull(client_id_list, SILC_ID_CLIENT_LEN);
1573 silc_free(id_string);
1575 silc_buffer_push(client_id_list,
1576 client_id_list->data - client_id_list->head);
1579 packet = silc_command_encode_reply_payload_va(SILC_COMMAND_NAMES,
1581 2, tmp, SILC_ID_CHANNEL_LEN,
1584 4, client_id_list->data,
1585 client_id_list->len);
1586 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1587 packet->data, packet->len, FALSE);
1589 silc_buffer_free(packet);
1590 silc_free(name_list);
1591 silc_buffer_free(client_id_list);
1595 silc_server_command_free(cmd);