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 i, argc, count = 0, len, clients_count;
297 SilcClientEntry entry;
299 unsigned char *id_string;
300 SilcClientEntry *clients;
301 SilcCommandStatus status;
303 SILC_LOG_DEBUG(("Start"));
305 argc = silc_command_get_arg_num(cmd->payload);
307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
308 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
313 SILC_STATUS_ERR_TOO_MANY_PARAMS);
317 /* Get the nickname@server string and parse it. */
318 tmp = silc_command_get_first_arg(cmd->payload, NULL);
320 if (strchr(tmp, '@')) {
321 len = strcspn(tmp, "@");
322 nick = silc_calloc(len + 1, sizeof(char));
323 memcpy(nick, tmp, len);
324 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
325 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
330 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
331 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
335 /* Get the max count of reply messages allowed */
337 tmp = silc_command_get_next_arg(cmd->payload, NULL);
339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
340 SILC_STATUS_ERR_TOO_MANY_PARAMS);
344 silc_free(server_name);
350 /* Get all clients matching that nickname */
351 clients = silc_idlist_get_clients_by_nickname(server->local_list,
356 /* If we are normal server and are connected to a router we will
357 make global query from the router. */
358 if (server->server_type == SILC_SERVER && !server->standalone) {
363 /* If we are router then we will check our global list as well. */
364 if (server->server_type == SILC_ROUTER) {
366 silc_idlist_find_client_by_nickname(server->global_list,
369 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
370 SILC_STATUS_ERR_NO_SUCH_NICK,
371 3, tmp, strlen(tmp));
377 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
378 SILC_STATUS_ERR_NO_SUCH_NICK,
379 3, tmp, strlen(tmp));
384 /* XXX, works only for local server info */
387 status = SILC_STATUS_OK;
388 if (clients_count > 1)
389 status = SILC_STATUS_LIST_START;
391 for (i = 0; i < clients_count; i++) {
394 if (count && i - 1 == count)
397 if (clients_count > 2)
398 status = SILC_STATUS_LIST_ITEM;
400 if (clients_count > 1 && i == clients_count - 1)
401 status = SILC_STATUS_LIST_END;
403 /* Send WHOIS reply */
404 id_string = silc_id_id2str(entry->id, SILC_ID_CLIENT);
405 tmp = silc_command_get_first_arg(cmd->payload, NULL);
408 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
409 char nh[256], uh[256];
410 unsigned char idle[4];
411 SilcSocketConnection hsock;
413 memset(uh, 0, sizeof(uh));
414 memset(nh, 0, sizeof(nh));
416 strncat(nh, entry->nickname, strlen(entry->nickname));
418 len = entry->router ? strlen(entry->router->server_name) :
419 strlen(server->server_name);
420 strncat(nh, entry->router ? entry->router->server_name :
421 server->server_name, len);
423 strncat(uh, entry->username, strlen(entry->username));
425 hsock = (SilcSocketConnection)entry->connection;
426 len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
427 strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
429 SILC_PUT32_MSB((time(NULL) - entry->last_receive), idle);
434 silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS,
436 2, id_string, SILC_ID_CLIENT_LEN,
440 strlen(entry->userinfo),
444 silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS,
446 2, id_string, SILC_ID_CLIENT_LEN,
454 silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS,
456 2, id_string, SILC_ID_CLIENT_LEN,
458 strlen(entry->nickname),
459 4, tmp, strlen(tmp)); /* XXX */
461 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
462 0, packet->data, packet->len, FALSE);
464 silc_free(id_string);
465 silc_buffer_free(packet);
469 silc_server_command_free(cmd);
472 SILC_SERVER_CMD_FUNC(whowas)
476 SILC_SERVER_CMD_FUNC(identify)
478 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
479 SilcServer server = cmd->server;
480 char *tmp, *nick = NULL, *server_name = NULL;
481 unsigned int argc, count = 0, len;
482 SilcClientEntry entry;
484 unsigned char *id_string;
486 SILC_LOG_DEBUG(("Start"));
488 argc = silc_command_get_arg_num(cmd->payload);
490 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
491 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
496 SILC_STATUS_ERR_TOO_MANY_PARAMS);
500 /* Get the nickname@server string and parse it. */
501 tmp = silc_command_get_first_arg(cmd->payload, NULL);
503 if (strchr(tmp, '@')) {
504 len = strcspn(tmp, "@");
505 nick = silc_calloc(len + 1, sizeof(char));
506 memcpy(nick, tmp, len);
507 server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
508 memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
513 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
514 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
518 /* Get the max count of reply messages allowed */
520 tmp = silc_command_get_next_arg(cmd->payload, NULL);
522 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
523 SILC_STATUS_ERR_TOO_MANY_PARAMS);
530 entry = silc_idlist_find_client_by_nickname(server->local_list,
533 entry = silc_idlist_find_client_by_hash(server->global_list,
534 nick, server->md5hash);
536 /* If client was not found and if we are normal server and are connected
537 to a router we will make global query from the router. */
538 if (!entry && server->server_type == SILC_SERVER && !server->standalone &&
540 SilcBuffer buffer = cmd->packet->buffer;
542 SILC_LOG_DEBUG(("Requesting identify from router"));
544 /* Send IDENTIFY command to our router */
545 silc_buffer_push(buffer, buffer->data - buffer->head);
546 silc_server_packet_forward(server, (SilcSocketConnection)
547 server->id_entry->router->connection,
548 buffer->data, buffer->len, TRUE);
552 /* If we are router we have checked our local list by nickname and our
553 global list by hash so far. It is possible that the client is still not
554 found and we'll check it from local list by hash. */
555 if (!entry && server->server_type == SILC_ROUTER)
556 entry = silc_idlist_find_client_by_hash(server->local_list,
557 nick, server->md5hash);
560 /* The client definitely does not exist */
561 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
562 SILC_STATUS_ERR_NO_SUCH_NICK,
563 3, tmp, strlen(tmp));
567 /* Send IDENTIFY reply */
568 id_string = silc_id_id2str(entry->id, SILC_ID_CLIENT);
569 tmp = silc_command_get_first_arg(cmd->payload, NULL);
570 packet = silc_command_encode_reply_payload_va(SILC_COMMAND_IDENTIFY,
574 3, nick, strlen(nick));
575 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
576 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
577 silc_server_packet_send_dest(server, cmd->sock,
578 SILC_PACKET_COMMAND_REPLY, 0,
579 id, cmd->packet->src_id_type,
580 packet->data, packet->len, FALSE);
583 silc_server_packet_send(server, cmd->sock,
584 SILC_PACKET_COMMAND_REPLY, 0,
585 packet->data, packet->len, FALSE);
588 silc_free(id_string);
589 silc_buffer_free(packet);
595 silc_free(server_name);
596 silc_server_command_free(cmd);
599 /* Checks string for bad characters and returns TRUE if they are found. */
601 static int silc_server_command_bad_chars(char *nick)
603 if (strchr(nick, '\\')) return TRUE;
604 if (strchr(nick, '\"')) return TRUE;
605 if (strchr(nick, '´')) return TRUE;
606 if (strchr(nick, '`')) return TRUE;
607 if (strchr(nick, '\'')) return TRUE;
608 if (strchr(nick, '*')) return TRUE;
609 if (strchr(nick, '/')) return TRUE;
610 if (strchr(nick, '@')) return TRUE;
615 /* Server side of command NICK. Sets nickname for user. Setting
616 nickname causes generation of a new client ID for the client. The
617 new client ID is sent to the client after changing the nickname. */
619 SILC_SERVER_CMD_FUNC(nick)
621 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
622 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
623 SilcServer server = cmd->server;
625 SilcClientID *new_id;
629 SILC_LOG_DEBUG(("Start"));
631 /* Check number of arguments */
632 if (silc_command_get_arg_num(cmd->payload) < 1) {
633 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
634 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
639 nick = silc_command_get_arg_type(cmd->payload, 1, NULL);
640 if (silc_server_command_bad_chars(nick) == TRUE) {
641 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
642 SILC_STATUS_ERR_BAD_NICKNAME);
646 /* Create new Client ID */
647 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
648 cmd->server->md5hash, nick,
651 /* Send notify about nickname change to our router. We send the new
652 ID and ask to replace it with the old one. */
653 if (cmd->server->server_type == SILC_SERVER && !cmd->server->standalone)
654 silc_server_send_replace_id(server, server->id_entry->router->connection,
656 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
657 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
659 /* If we are router we have to distribute the new Client ID to all
661 if (cmd->server->server_type == SILC_ROUTER && !cmd->server->standalone)
662 silc_server_send_replace_id(server, server->id_entry->router->connection,
664 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
665 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
667 /* Remove old cache entry */
668 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
673 memset(id_entry->id, 0, SILC_ID_CLIENT_LEN);
674 silc_free(id_entry->id);
677 /* Save the nickname as this client is our local client */
678 if (id_entry->nickname)
679 silc_free(id_entry->nickname);
681 id_entry->nickname = strdup(nick);
682 id_entry->id = new_id;
684 /* Update client cache */
685 silc_idcache_add(server->local_list->clients, id_entry->nickname,
686 SILC_ID_CLIENT, id_entry->id, (void *)id_entry, TRUE);
688 /* Send the new Client ID as reply command back to client */
689 id_string = silc_id_id2str(id_entry->id, SILC_ID_CLIENT);
690 packet = silc_command_encode_reply_payload_va(SILC_COMMAND_NICK,
694 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
695 0, packet->data, packet->len, FALSE);
697 silc_free(id_string);
698 silc_buffer_free(packet);
701 silc_server_command_free(cmd);
704 SILC_SERVER_CMD_FUNC(list)
708 /* Server side of TOPIC command. Sets topic for channel and/or returns
709 current topic to client. */
711 SILC_SERVER_CMD_FUNC(topic)
713 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
714 SilcServer server = cmd->server;
715 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
716 SilcChannelID *channel_id;
717 SilcChannelEntry channel;
719 unsigned char *tmp, *id_string;
722 /* Check number of arguments */
723 argc = silc_command_get_arg_num(cmd->payload);
725 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
726 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
730 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
731 SILC_STATUS_ERR_TOO_MANY_PARAMS);
736 tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
738 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
739 SILC_STATUS_ERR_NO_CHANNEL_ID);
742 channel_id = silc_id_str2id(tmp, SILC_ID_CHANNEL);
744 /* Check whether the channel exists */
745 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
747 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
748 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
754 tmp = silc_command_get_arg_type(cmd->payload, 2, NULL);
756 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
757 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
761 if (strlen(tmp) > 256) {
762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
763 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
767 /* Set the topic for channel */
769 silc_free(channel->topic);
770 channel->topic = strdup(tmp);
772 /* Send notify about topic change to all clients on the channel */
773 silc_server_send_notify_to_channel(server, channel,
774 SILC_NOTIFY_TYPE_TOPIC_SET,
775 "%s@%s set topic: %s",
777 cmd->sock->hostname ?
778 cmd->sock->hostname : cmd->sock->ip,
782 /* Send the topic to client as reply packet */
783 id_string = silc_id_id2str(channel_id, SILC_ID_CHANNEL);
785 packet = silc_command_encode_reply_payload_va(SILC_COMMAND_TOPIC,
790 strlen(channel->topic));
792 packet = silc_command_encode_reply_payload_va(SILC_COMMAND_TOPIC,
795 SILC_ID_CHANNEL_LEN);
796 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
797 0, packet->data, packet->len, FALSE);
799 silc_free(id_string);
800 silc_buffer_free(packet);
801 silc_free(channel_id);
804 silc_server_command_free(cmd);
807 /* Server side of INVITE command. Invites some client to join some channel. */
809 SILC_SERVER_CMD_FUNC(invite)
811 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
812 SilcServer server = cmd->server;
813 SilcSocketConnection sock = cmd->sock, dest_sock;
814 SilcClientEntry sender, dest;
815 SilcClientID *dest_id;
816 SilcChannelEntry channel;
817 SilcChannelID *channel_id;
818 unsigned int argc, len;
819 unsigned char *id_string;
821 /* Check number of arguments */
822 argc = silc_command_get_arg_num(cmd->payload);
824 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
825 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
829 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
830 SILC_STATUS_ERR_TOO_MANY_PARAMS);
834 /* Get destination ID */
835 id_string = silc_command_get_arg_type(cmd->payload, 1, &len);
837 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
838 SILC_STATUS_ERR_NO_CLIENT_ID);
841 dest_id = silc_id_str2id(id_string, SILC_ID_CLIENT);
844 id_string = silc_command_get_arg_type(cmd->payload, 2, &len);
846 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
847 SILC_STATUS_ERR_NO_CHANNEL_ID);
850 channel_id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
852 /* Check whether the channel exists */
853 channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
855 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
856 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
860 /* Check whether the sender of this command is on the channel. */
861 sender = (SilcClientEntry )sock->user_data;
862 if (!silc_server_client_on_channel(sender, channel)) {
863 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
864 SILC_STATUS_ERR_NOT_ON_CHANNEL);
868 /* Check whether the channel is invite-only channel. If yes then the
869 sender of this command must be at least channel operator. */
872 /* Find the connection data for the destination. If it is local we will
873 send it directly otherwise we will send it to router for routing. */
874 dest = silc_idlist_find_client_by_id(server->local_list, dest_id);
876 dest_sock = (SilcSocketConnection)dest->connection;
878 dest_sock = silc_server_get_route(server, dest_id, SILC_ID_CLIENT);
880 /* Check whether the requested client is already on the channel. */
881 /* XXX if we are normal server we don't know about global clients on
882 the channel thus we must request it (NAMES command), check from
883 local cache as well. */
884 if (silc_server_client_on_channel(dest, channel)) {
885 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
886 SILC_STATUS_ERR_USER_ON_CHANNEL);
890 /* Send notify to the client that is invited to the channel */
891 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
892 SILC_NOTIFY_TYPE_INVITE,
893 "%s invites you to channel %s",
894 sender->nickname, channel->channel_name);
896 /* Send command reply */
897 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
901 silc_server_command_free(cmd);
904 /* Quits connection to client. This gets called if client won't
905 close the connection even when it has issued QUIT command. */
907 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
909 SilcServer server = (SilcServer)context;
910 SilcSocketConnection sock = server->sockets[fd];
912 /* Free all client specific data, such as client entry and entires
913 on channels this client may be on. */
914 silc_server_free_sock_user_data(server, sock);
916 /* Close the connection on our side */
917 silc_server_close_connection(server, sock);
920 /* Quits SILC session. This is the normal way to disconnect client. */
922 SILC_SERVER_CMD_FUNC(quit)
924 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
925 SilcServer server = cmd->server;
926 SilcSocketConnection sock = cmd->sock;
928 SILC_LOG_DEBUG(("Start"));
930 /* We quit the connection with little timeout */
931 silc_task_register(server->timeout_queue, sock->sock,
932 silc_server_command_quit_cb, server,
933 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
935 silc_server_command_free(cmd);
938 SILC_SERVER_CMD_FUNC(kill)
942 /* Server side of command INFO. This sends information about us to
943 the client. If client requested specific server we will send the
944 command to that server. */
946 SILC_SERVER_CMD_FUNC(info)
948 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
949 SilcServer server = cmd->server;
952 unsigned char *id_string;
953 char info_string[256], *dest_server;
955 argc = silc_command_get_arg_num(cmd->payload);
957 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
958 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
962 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
963 SILC_STATUS_ERR_TOO_MANY_PARAMS);
967 /* Get server name */
968 dest_server = silc_command_get_arg_type(cmd->payload, 1, NULL);
970 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
971 SILC_STATUS_ERR_NO_SUCH_SERVER);
975 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
977 memset(info_string, 0, sizeof(info_string));
978 snprintf(info_string, sizeof(info_string),
979 "location: %s server: %s admin: %s <%s>",
980 server->config->admin_info->location,
981 server->config->admin_info->server_type,
982 server->config->admin_info->admin_name,
983 server->config->admin_info->admin_email);
985 id_string = silc_id_id2str(server->id, SILC_ID_SERVER);
988 silc_command_encode_reply_payload_va(SILC_COMMAND_INFO,
990 2, id_string, SILC_ID_SERVER_LEN,
992 strlen(info_string));
993 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
994 packet->data, packet->len, FALSE);
996 silc_free(id_string);
997 silc_buffer_free(packet);
999 /* Send this command to the requested server */
1001 if (server->server_type == SILC_SERVER && !server->standalone) {
1005 if (server->server_type == SILC_ROUTER) {
1011 silc_server_command_free(cmd);
1014 SILC_SERVER_CMD_FUNC(connect)
1018 /* Server side of command PING. This just replies to the ping. */
1020 SILC_SERVER_CMD_FUNC(ping)
1022 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1023 SilcServer server = cmd->server;
1026 unsigned char *id_string;
1028 argc = silc_command_get_arg_num(cmd->payload);
1030 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1031 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1035 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1036 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1041 id_string = silc_command_get_arg_type(cmd->payload, 1, NULL);
1043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1044 SILC_STATUS_ERR_NO_SERVER_ID);
1047 id = silc_id_str2id(id_string, SILC_ID_SERVER);
1049 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1050 /* Send our reply */
1051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1054 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1055 SILC_STATUS_ERR_NO_SUCH_SERVER);
1062 silc_server_command_free(cmd);
1065 SILC_SERVER_CMD_FUNC(oper)
1074 SilcChannelEntry channel;
1076 } JoinInternalContext;
1078 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1080 JoinInternalContext *ctx = (JoinInternalContext *)context;
1082 if (ctx->channel->key && ctx->channel->key_len) {
1083 silc_server_send_notify_to_channel(ctx->server, ctx->channel,
1084 SILC_NOTIFY_TYPE_JOIN,
1085 "%s (%s@%s) has joined channel %s",
1086 ctx->nickname, ctx->username,
1087 ctx->hostname, ctx->channel_name);
1090 silc_task_register(ctx->server->timeout_queue, fd,
1091 silc_server_command_join_notify, context,
1092 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1096 /* Assembles NAMES command and executes it. This is called when client
1097 joins to a channel and we wan't to send NAMES command reply to the
1100 void silc_server_command_send_names(SilcServer server,
1101 SilcSocketConnection sock,
1102 SilcChannelEntry channel)
1104 SilcServerCommandContext cmd;
1106 unsigned char *id_string;
1108 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1109 buffer = silc_command_encode_payload_va(SILC_COMMAND_NAMES, 1,
1110 1, id_string, SILC_ID_CHANNEL_LEN);
1112 cmd = silc_calloc(1, sizeof(*cmd));
1113 cmd->payload = silc_command_parse_payload(buffer);
1114 cmd->server = server;
1116 cmd->pending = FALSE;
1118 silc_server_command_names((void *)cmd);
1119 silc_free(id_string);
1123 /* Server side of command JOIN. Joins client into requested channel. If
1124 the channel does not exist it will be created. */
1126 SILC_SERVER_CMD_FUNC(join)
1128 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1129 SilcServer server = cmd->server;
1130 SilcSocketConnection sock = cmd->sock;
1131 SilcBuffer buffer = cmd->packet->buffer;
1132 int argc, i, tmp_len;
1133 char *tmp, *channel_name = NULL, *cipher = NULL, *id_string = NULL;
1134 unsigned char *passphrase, mode[4];
1135 SilcChannelEntry channel;
1136 SilcServerID *router_id;
1138 SilcClientEntry client;
1140 SILC_LOG_DEBUG(("Start"));
1142 /* Check number of parameters */
1143 argc = silc_command_get_arg_num(cmd->payload);
1145 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1146 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1150 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1151 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1155 /* Get channel name */
1156 tmp = silc_command_get_arg_type(cmd->payload, 1, &tmp_len);
1157 channel_name = silc_calloc(tmp_len + 1, sizeof(*channel_name));
1158 memcpy(channel_name, tmp, tmp_len);
1159 if (silc_server_command_bad_chars(tmp) == TRUE) {
1160 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1161 SILC_STATUS_ERR_BAD_CHANNEL);
1162 silc_free(channel_name);
1166 /* Get passphrase */
1167 tmp = silc_command_get_arg_type(cmd->payload, 2, &tmp_len);
1169 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1170 memcpy(passphrase, tmp, tmp_len);
1173 /* Get cipher name */
1174 cipher = silc_command_get_arg_type(cmd->payload, 3, NULL);
1176 /* See if the channel exists */
1178 silc_idlist_find_channel_by_name(server->local_list, channel_name);
1180 /* Channel not found */
1182 /* If we are standalone server we don't have a router, we just create
1183 the channel by ourselves. */
1184 if (server->standalone) {
1185 router_id = server->id;
1186 channel = silc_server_new_channel(server, router_id,
1187 cipher, channel_name);
1194 /* No channel ID found, the channel does not exist on our server.
1195 We send JOIN command to our router which will handle the joining
1196 procedure (either creates the channel if it doesn't exist or
1197 joins the client to it) - if we are normal server. */
1198 if (server->server_type == SILC_SERVER) {
1200 /* Forward the original JOIN command to the router */
1201 silc_buffer_push(buffer, buffer->data - buffer->head);
1202 silc_server_packet_forward(server, (SilcSocketConnection)
1203 server->id_entry->router->connection,
1204 buffer->data, buffer->len, TRUE);
1206 /* Add the command to be pending. It will be re-executed after
1207 router has replied back to us. */
1208 cmd->pending = TRUE;
1209 silc_server_command_pending(SILC_COMMAND_JOIN,
1210 silc_server_command_join, context);
1215 /* If we are router and the channel does not exist we will check our
1216 global list for the channel. */
1217 if (!channel && server->server_type == SILC_ROUTER) {
1219 /* Notify all routers about the new channel in SILC network. */
1220 if (!server->standalone) {
1222 silc_server_send_new_id(server, server->id_entry->router->connection,
1224 xxx, SILC_ID_CHANNEL, SILC_ID_CHANNEL_LEN);
1232 /* If the JOIN request was forwarded to us we will make a bit slower
1233 query to get the client pointer. Otherwise, we get the client pointer
1235 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1236 client = (SilcClientEntry)sock->user_data;
1238 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1239 client = silc_idlist_find_client_by_id(server->local_list, id);
1247 /* Check whether the client already is on the channel */
1248 if (silc_server_client_on_channel(client, channel)) {
1249 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1250 SILC_STATUS_ERR_USER_ON_CHANNEL);
1251 silc_free(channel_name);
1255 /* Join the client to the channel */
1256 i = channel->user_list_count;
1257 channel->user_list = silc_realloc(channel->user_list,
1258 sizeof(*channel->user_list) * (i + 1));
1259 channel->user_list[i].mode = SILC_CHANNEL_UMODE_NONE;
1260 channel->user_list[i].client = client;
1261 channel->user_list_count++;
1263 /* Add the channel to client's channel list */
1264 i = client->channel_count;
1265 client->channel = silc_realloc(client->channel,
1266 sizeof(*client->channel) * (i + 1));
1267 client->channel[i] = channel;
1268 client->channel_count++;
1270 /* Notify router about new user on channel. If we are normal server
1271 we send it to our router, if we are router we send it to our
1273 if (!server->standalone) {
1277 /* Send command reply to the client. Client receives the Channe ID,
1278 channel mode and possibly other information in this reply packet. */
1279 if (!cmd->pending) {
1280 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1281 SILC_PUT32_MSB(channel->mode, mode);
1283 if (!channel->topic)
1285 silc_command_encode_reply_payload_va(SILC_COMMAND_JOIN,
1288 strlen(channel_name),
1289 3, id_string, SILC_ID_CHANNEL_LEN,
1293 silc_command_encode_reply_payload_va(SILC_COMMAND_JOIN,
1296 strlen(channel_name),
1297 3, id_string, SILC_ID_CHANNEL_LEN,
1300 strlen(channel->topic));
1302 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1303 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1304 silc_server_packet_send_dest(cmd->server, cmd->sock,
1305 SILC_PACKET_COMMAND_REPLY, 0,
1306 id, cmd->packet->src_id_type,
1307 packet->data, packet->len, FALSE);
1310 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1311 packet->data, packet->len, FALSE);
1313 silc_buffer_free(packet);
1316 /* Send channel key to the client. Client cannot start transmitting
1317 to the channel until we have sent the key. */
1318 if (!cmd->pending) {
1319 tmp_len = strlen(channel->channel_key->cipher->name);
1321 silc_channel_key_encode_payload(SILC_ID_CHANNEL_LEN,
1323 channel->channel_key->cipher->name,
1324 channel->key_len / 8, channel->key);
1326 silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0,
1327 packet->data, packet->len, FALSE);
1328 silc_buffer_free(packet);
1332 silc_free(id_string);
1334 /* Finally, send notify message to all clients on the channel about
1335 new user on the channel. */
1336 if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1337 if (!cmd->pending) {
1338 silc_server_send_notify_to_channel(server, channel,
1339 SILC_NOTIFY_TYPE_JOIN,
1340 "%s (%s@%s) has joined channel %s",
1341 client->nickname, client->username,
1342 sock->hostname ? sock->hostname :
1343 sock->ip, channel_name);
1345 /* This is pending command request. Send the notify after we have
1346 received the key for the channel from the router. */
1347 JoinInternalContext *ctx = silc_calloc(1, sizeof(*ctx));
1348 ctx->channel_name = channel_name;
1349 ctx->nickname = client->nickname;
1350 ctx->username = client->username;
1351 ctx->hostname = sock->hostname ? sock->hostname : sock->ip;
1352 ctx->channel = channel;
1353 ctx->server = server;
1354 silc_task_register(server->timeout_queue, sock->sock,
1355 silc_server_command_join_notify, ctx,
1356 0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1360 /* Send NAMES command reply to the joined channel so the user sees who
1361 is currently on the channel. */
1362 silc_server_command_send_names(server, sock, channel);
1365 silc_server_command_free(cmd);
1368 /* Server side of command MOTD. Sends server's current "message of the
1369 day" to the client. */
1371 SILC_SERVER_CMD_FUNC(motd)
1373 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1374 SilcServer server = cmd->server;
1375 SilcSocketConnection sock = cmd->sock;
1380 SILC_LOG_DEBUG(("Start"));
1382 argc = silc_command_get_arg_num(cmd->payload);
1384 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1385 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1389 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1390 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1394 /* XXX show currently only our motd */
1396 if (server->config && server->config->motd &&
1397 server->config->motd->motd_file) {
1400 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
1405 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
1411 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
1416 silc_server_command_free(cmd);
1419 SILC_SERVER_CMD_FUNC(umode)
1423 SILC_SERVER_CMD_FUNC(cmode)
1427 SILC_SERVER_CMD_FUNC(kick)
1431 SILC_SERVER_CMD_FUNC(restart)
1435 SILC_SERVER_CMD_FUNC(close)
1439 SILC_SERVER_CMD_FUNC(die)
1443 SILC_SERVER_CMD_FUNC(silcoper)
1447 /* Server side command of LEAVE. Removes client from a channel. */
1449 SILC_SERVER_CMD_FUNC(leave)
1451 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1452 SilcServer server = cmd->server;
1453 SilcSocketConnection sock = cmd->sock;
1454 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
1456 SilcChannelEntry channel;
1458 unsigned int i, argc, key_len;
1459 unsigned char *tmp, channel_key[32];
1461 SILC_LOG_DEBUG(("Start"));
1463 argc = silc_command_get_arg_num(cmd->payload);
1465 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1466 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1470 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1471 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1475 /* Get Channel ID */
1476 tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
1478 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1479 SILC_STATUS_ERR_NO_CHANNEL_ID);
1482 id = silc_id_str2id(tmp, SILC_ID_CHANNEL);
1484 /* Get channel entry */
1485 channel = silc_idlist_find_channel_by_id(server->local_list, id);
1487 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1488 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1492 /* Check whether this client is on the channel */
1493 if (!silc_server_client_on_channel(id_entry, channel)) {
1494 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1495 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1499 /* Notify routers that they should remove this client from their list
1500 of clients on the channel. */
1501 if (!server->standalone)
1502 silc_server_send_remove_channel_user(server,
1503 server->id_entry->router->connection,
1504 server->server_type == SILC_ROUTER ?
1505 TRUE : FALSE, id_entry->id, id);
1507 /* Remove client from channel */
1508 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
1510 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1513 /* If the channel does not exist anymore we won't send anything */
1517 /* Re-generate channel key */
1518 key_len = channel->key_len / 8;
1519 for (i = 0; i < key_len; i++)
1520 channel_key[i] = silc_rng_get_byte(server->rng);
1521 channel->channel_key->cipher->set_key(channel->channel_key->context,
1522 channel_key, key_len);
1523 memset(channel->key, 0, key_len);
1524 silc_free(channel->key);
1525 channel->key = silc_calloc(key_len, sizeof(*channel->key));
1526 memcpy(channel->key, channel_key, key_len);
1527 memset(channel_key, 0, sizeof(channel_key));
1529 /* Encode channel key payload to be distributed on the channel */
1531 silc_channel_key_encode_payload(SILC_ID_CHANNEL_LEN, tmp,
1532 strlen(channel->channel_key->cipher->name),
1533 channel->channel_key->cipher->name,
1534 key_len, channel->key);
1536 /* If we are normal server then we will send it to our router. If we
1537 are router we will send it to all local servers that has clients on
1539 if (server->server_type == SILC_SERVER) {
1540 if (!server->standalone)
1541 silc_server_packet_send(server,
1542 cmd->server->id_entry->router->connection,
1543 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1549 /* Send to locally connected clients on the channel */
1550 silc_server_packet_send_local_channel(server, channel,
1551 SILC_PACKET_CHANNEL_KEY, 0,
1552 packet->data, packet->len, FALSE);
1554 silc_buffer_free(packet);
1558 silc_server_command_free(cmd);
1561 /* Server side of command NAMES. Resolves clients and their names currently
1562 joined on the requested channel. The name list is sent back to the
1565 SILC_SERVER_CMD_FUNC(names)
1567 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1568 SilcServer server = cmd->server;
1569 SilcChannelEntry channel;
1572 unsigned int i, len, len2, argc;
1574 char *name_list = NULL, *n;
1575 SilcBuffer client_id_list;
1577 SILC_LOG_DEBUG(("Start"));
1579 argc = silc_command_get_arg_num(cmd->payload);
1581 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
1582 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1586 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
1587 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1591 /* Get Channel ID */
1592 tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
1594 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1595 SILC_STATUS_ERR_NO_CHANNEL_ID);
1598 id = silc_id_str2id(tmp, SILC_ID_CHANNEL);
1600 /* Check whether the channel exists. If we are normal server and the
1601 channel does not exist we will send this same command to our router
1602 which will know if the channel exists. */
1603 channel = silc_idlist_find_channel_by_id(server->local_list, id);
1605 if (server->server_type == SILC_SERVER && !server->standalone) {
1606 /* XXX Send names command */
1608 cmd->pending = TRUE;
1609 silc_server_command_pending(SILC_COMMAND_NAMES,
1610 silc_server_command_names, context);
1614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1615 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1619 /* Assemble the name list now */
1622 for (i = 0; i < channel->user_list_count; i++) {
1623 if (!channel->user_list[i].client)
1626 n = channel->user_list[i].client->nickname;
1630 name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
1631 memcpy(name_list + (len - len2), n, len2);
1634 if (i == channel->user_list_count - 1)
1636 memcpy(name_list + len, ",", 1);
1643 /* Assemble the Client ID list now */
1644 client_id_list = silc_buffer_alloc(SILC_ID_CLIENT_LEN *
1645 channel->user_list_count);
1646 silc_buffer_pull_tail(client_id_list, (SILC_ID_CLIENT_LEN *
1647 channel->user_list_count));
1648 for (i = 0; i < channel->user_list_count; i++) {
1649 unsigned char *id_string;
1651 if (!channel->user_list[i].client)
1654 id_string = silc_id_id2str(channel->user_list[i].client->id,
1656 silc_buffer_format(client_id_list,
1657 SILC_STR_UI_XNSTRING(id_string, SILC_ID_CLIENT_LEN),
1659 silc_buffer_pull(client_id_list, SILC_ID_CLIENT_LEN);
1660 silc_free(id_string);
1662 silc_buffer_push(client_id_list,
1663 client_id_list->data - client_id_list->head);
1666 packet = silc_command_encode_reply_payload_va(SILC_COMMAND_NAMES,
1668 2, tmp, SILC_ID_CHANNEL_LEN,
1671 4, client_id_list->data,
1672 client_id_list->len);
1673 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1674 packet->data, packet->len, FALSE);
1676 silc_buffer_free(packet);
1677 silc_free(name_list);
1678 silc_buffer_free(client_id_list);
1682 silc_server_command_free(cmd);