Added debug logs for updating stat.clients value
[silc.git] / apps / silcd / command_reply.c
1 /*
2
3   command_reply.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2009 Pekka Riikonen
8
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; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id$ */
20
21 #include "serverincludes.h"
22 #include "server_internal.h"
23 #include "command_reply.h"
24
25 /* All functions that call the COMMAND_CHECK_STATUS macros must have
26    out: and err: goto labels. */
27
28 #define COMMAND_CHECK_STATUS                                            \
29 do {                                                                    \
30   SILC_LOG_DEBUG(("Start"));                                            \
31   if (!silc_command_get_status(cmd->payload, &status, &error)) {        \
32     if (SILC_STATUS_IS_ERROR(status))                                   \
33       goto out;                                                         \
34     if (status == SILC_STATUS_LIST_END)                                 \
35       goto out;                                                         \
36     goto err;                                                           \
37   }                                                                     \
38 } while(0)
39
40 /* Server command reply list. Not all commands have reply function as
41    they are never sent by server. More maybe added later if need appears. */
42 SilcServerCommandReply silc_command_reply_list[] =
43 {
44   SILC_SERVER_CMD_REPLY(whois, WHOIS),
45   SILC_SERVER_CMD_REPLY(whowas, WHOWAS),
46   SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
47   SILC_SERVER_CMD_REPLY(info, INFO),
48   SILC_SERVER_CMD_REPLY(motd, MOTD),
49   SILC_SERVER_CMD_REPLY(join, JOIN),
50   SILC_SERVER_CMD_REPLY(stats, STATS),
51   SILC_SERVER_CMD_REPLY(users, USERS),
52   SILC_SERVER_CMD_REPLY(getkey, GETKEY),
53   SILC_SERVER_CMD_REPLY(list, LIST),
54   SILC_SERVER_CMD_REPLY(watch, WATCH),
55   SILC_SERVER_CMD_REPLY(ping, PING),
56
57   { NULL, 0 },
58 };
59
60 /* Process received command reply. */
61
62 void silc_server_command_reply_process(SilcServer server,
63                                        SilcPacketStream sock,
64                                        SilcBuffer buffer)
65 {
66   SilcIDListData idata = silc_packet_get_context(sock);
67   SilcServerCommandReply *cmd;
68   SilcServerCommandReplyContext ctx;
69   SilcCommandPayload payload;
70   SilcCommand command;
71
72   SILC_LOG_DEBUG(("Start"));
73
74   /* Get command reply payload from packet */
75   payload = silc_command_payload_parse(buffer->data, silc_buffer_len(buffer));
76   if (!payload) {
77     /* Silently ignore bad reply packet */
78     SILC_LOG_DEBUG(("Bad command reply packet"));
79     return;
80   }
81
82   /* Allocate command reply context. This must be free'd by the
83      command reply routine receiving it. */
84   ctx = silc_calloc(1, sizeof(*ctx));
85   ctx->server = server;
86   ctx->sock = sock;
87   ctx->payload = payload;
88   ctx->args = silc_command_get_args(ctx->payload);
89   ctx->ident = silc_command_get_ident(ctx->payload);
90   command = silc_command_get(ctx->payload);
91   silc_packet_stream_ref(sock);
92
93   /* Client is not allowed to send reply to all commands */
94   if (idata->conn_type == SILC_CONN_CLIENT &&
95       command != SILC_COMMAND_WHOIS) {
96     silc_server_command_reply_free(ctx);
97     return;
98   }
99
100   /* Check for pending commands and mark to be exeucted */
101   ctx->callbacks =
102     silc_server_command_pending_check(server, command,
103                                       ctx->ident, &ctx->callbacks_count);
104
105   /* Execute command reply */
106   for (cmd = silc_command_reply_list; cmd->cb; cmd++)
107     if (cmd->cmd == command)
108       break;
109
110   if (cmd == NULL || !cmd->cb) {
111     silc_server_command_reply_free(ctx);
112     return;
113   }
114
115   cmd->cb(ctx, NULL);
116 }
117
118 /* Free command reply context and its internals. */
119
120 void silc_server_command_reply_free(SilcServerCommandReplyContext cmd)
121 {
122   if (cmd) {
123     silc_command_payload_free(cmd->payload);
124     if (cmd->sock)
125       silc_packet_stream_unref(cmd->sock);
126     silc_free(cmd->callbacks);
127     silc_free(cmd);
128   }
129 }
130
131 static void
132 silc_server_command_process_error(SilcServerCommandReplyContext cmd,
133                                   SilcStatus error)
134 {
135   SilcServer server = cmd->server;
136   SilcIDListData idata = silc_packet_get_context(cmd->sock);
137
138   /* If we received notify for invalid ID we'll remove the ID if we
139      have it cached. */
140   if (error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
141       idata->conn_type == SILC_CONN_ROUTER) {
142     SilcClientEntry client;
143     SilcID id;
144     if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id,
145                                   NULL)) {
146       SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
147                       "the entry from cache"));
148       client = silc_idlist_find_client_by_id(server->global_list,
149                                              SILC_ID_GET_ID(id), FALSE, NULL);
150       if (!client)
151         return;
152
153       silc_server_remove_from_channels(server, NULL, client, TRUE,
154                                        NULL, TRUE, FALSE);
155       silc_dlist_del(server->expired_clients, client);
156       silc_idlist_del_data(client);
157       silc_idlist_del_client(server->global_list, client);
158     }
159   }
160 }
161
162 /* Caches the received WHOIS information. */
163
164 static char
165 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
166 {
167   SilcServer server = cmd->server;
168   unsigned char *id_data, *umodes;
169   char *nickname, *username, *realname, *tmp;
170   unsigned char *fingerprint;
171   SilcID id;
172   SilcClientEntry client;
173   char global = FALSE;
174   char nick[128 + 1], servername[256 + 1], uname[128 + 1];
175   SilcUInt32 mode = 0, len, len2, id_len, flen;
176   const char *hostname, *ip;
177
178   silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
179                               NULL, &hostname, &ip, NULL);
180
181   id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
182   nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
183   username = silc_argument_get_arg_type(cmd->args, 4, &len);
184   realname = silc_argument_get_arg_type(cmd->args, 5, &len);
185   if (!id_data || !nickname || !username || !realname)
186     return FALSE;
187
188   tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
189   if (tmp)
190     SILC_GET32_MSB(mode, tmp);
191
192   if (!silc_id_payload_parse_id(id_data, id_len, &id))
193     return FALSE;
194
195   fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
196
197   /* Check if we have this client cached already. */
198
199   client = silc_idlist_find_client_by_id(server->local_list,
200                                          SILC_ID_GET_ID(id),
201                                          FALSE, NULL);
202   if (!client) {
203     client = silc_idlist_find_client_by_id(server->global_list,
204                                            SILC_ID_GET_ID(id),
205                                            FALSE, NULL);
206     global = TRUE;
207   }
208
209   if (!client) {
210     /* If router did not find such Client ID in its lists then this must
211        be bogus client or some router in the net is buggy. */
212     if (server->server_type != SILC_SERVER)
213       return FALSE;
214
215     /* Take hostname out of nick string if it includes it. */
216     silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
217                         sizeof(servername));
218
219     /* We don't have that client anywhere, add it. The client is added
220        to global list since server didn't have it in the lists so it must be
221        global. This will check for valid nickname and username strings. */
222     client = silc_idlist_add_client(server->global_list,
223                                     strdup(nick), username,
224                                     strdup(realname),
225                                     silc_id_dup(SILC_ID_GET_ID(id),
226                                                 SILC_ID_CLIENT),
227                                     silc_packet_get_context(cmd->sock),
228                                     NULL);
229     if (!client) {
230       SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
231       return FALSE;
232     }
233
234     client->data.status |=
235       (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_RESOLVED);
236     client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
237     client->mode = mode;
238     client->servername = servername[0] ? strdup(servername) : NULL;
239   } else {
240     /* We have the client already, update the data */
241
242     SILC_LOG_DEBUG(("Updating client data"));
243
244     /* Check nickname */
245     silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
246                         sizeof(servername));
247     nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
248                                      128, NULL);
249     if (!nickname) {
250       SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOIS reply "
251                       "from %s",
252                       hostname ? hostname : "", nick));
253       return FALSE;
254     }
255
256     /* Check username */
257     silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
258     if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128)) {
259       SILC_LOG_ERROR(("Malformed username '%s' received in WHOIS reply "
260                       "from %s",
261                       hostname ? hostname : "", tmp));
262       return FALSE;
263     }
264
265     /* Update entry */
266     silc_idcache_update_by_context(global ? server->global_list->clients :
267                                    server->local_list->clients, client, NULL,
268                                    nickname, TRUE);
269
270     silc_free(client->nickname);
271     silc_free(client->username);
272     silc_free(client->userinfo);
273     silc_free(client->servername);
274
275     client->nickname = strdup(nick);
276     client->username = strdup(username);
277     client->userinfo = strdup(realname);
278     client->servername = servername[0] ? strdup(servername) : NULL;
279     client->mode = mode;
280     client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
281     client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
282   }
283
284   /* Save channel list if it was sent to us */
285   if (server->server_type == SILC_SERVER) {
286     tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
287     umodes = silc_argument_get_arg_type(cmd->args, 10, &len2);
288     if (tmp && umodes) {
289       SilcBufferStruct channels_buf, umodes_buf;
290       silc_buffer_set(&channels_buf, tmp, len);
291       silc_buffer_set(&umodes_buf, umodes, len2);
292       silc_server_save_user_channels(server, cmd->sock, client, &channels_buf,
293                                      &umodes_buf);
294     } else {
295       silc_server_save_user_channels(server, cmd->sock, client, NULL, NULL);
296     }
297   }
298
299   if (fingerprint && flen == sizeof(client->data.fingerprint))
300     memcpy(client->data.fingerprint, fingerprint, flen);
301
302   /* Take Requested Attributes if set. */
303   tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
304   if (tmp) {
305     silc_free(client->attrs);
306     client->attrs = silc_memdup(tmp, len);
307     client->attrs_len = len;
308
309     /* Try to take public key from attributes if present and we don't have
310        the key already.  Do this only on normal server.  Routers do GETKEY
311        for all clients anyway. */
312     if (server->server_type != SILC_ROUTER && !client->data.public_key) {
313       SilcAttributePayload attr;
314       SilcAttributeObjPk pk;
315       unsigned char f[SILC_HASH_MAXLEN];
316       SilcDList attrs = silc_attribute_payload_parse(tmp, len);
317
318       SILC_LOG_DEBUG(("Take client public key from attributes"));
319
320       if (attrs) {
321         silc_dlist_start(attrs);
322         while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
323           if (silc_attribute_get_attribute(attr) ==
324               SILC_ATTRIBUTE_USER_PUBLIC_KEY) {
325
326             if (!silc_attribute_get_object(attr, &pk, sizeof(pk)))
327               continue;
328
329             /* Take only SILC public keys */
330             if (strcmp(pk.type, "silc-rsa")) {
331               silc_free(pk.type);
332               silc_free(pk.data);
333               continue;
334             }
335
336             /* Verify that the server provided fingerprint matches the key */
337             silc_hash_make(server->sha1hash, pk.data, pk.data_len, f);
338             if (memcmp(f, client->data.fingerprint, sizeof(f))) {
339               silc_free(pk.type);
340               silc_free(pk.data);
341               continue;
342             }
343
344             /* Save the public key. */
345             if (!silc_pkcs_public_key_alloc(SILC_PKCS_SILC,
346                                             pk.data, pk.data_len,
347                                             &client->data.public_key)) {
348               silc_free(pk.type);
349               silc_free(pk.data);
350               continue;
351             }
352
353             SILC_LOG_DEBUG(("Saved client public key from attributes"));
354
355             /* Add client's public key to repository */
356             if (!silc_server_get_public_key_by_client(server, client, NULL))
357               silc_skr_add_public_key_simple(server->repository,
358                                              client->data.public_key,
359                                              SILC_SKR_USAGE_IDENTIFICATION,
360                                              client, NULL);
361
362             silc_free(pk.type);
363             silc_free(pk.data);
364             break;
365           }
366         }
367
368         silc_attribute_payload_list_free(attrs);
369       }
370     }
371   }
372
373   return TRUE;
374 }
375
376 /* Handle requested attributes reply in WHOIS from client */
377
378 static char
379 silc_server_command_reply_whois_save_client(SilcServerCommandReplyContext cmd)
380 {
381   unsigned char *tmp;
382   SilcUInt32 len;
383   SilcClientEntry client = silc_packet_get_context(cmd->sock);
384
385   /* Take Requested Attributes if set. */
386   tmp = silc_argument_get_arg_type(cmd->args, 11, &len);
387   if (tmp && client) {
388     silc_free(client->attrs);
389     client->attrs = silc_memdup(tmp, len);
390     client->attrs_len = len;
391   }
392
393   client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
394
395   return TRUE;
396 }
397
398 /* Reiceved reply for WHOIS command. We sent the whois request to our
399    primary router, if we are normal server, and thus has now received reply
400    to the command. We will figure out what client originally sent us the
401    command and will send the reply to it.  If we are router we will figure
402    out who server sent us the command and send reply to that one. */
403
404 SILC_SERVER_CMD_REPLY_FUNC(whois)
405 {
406   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
407   SilcIDListData idata = silc_packet_get_context(cmd->sock);
408   SilcStatus status, error;
409
410   COMMAND_CHECK_STATUS;
411
412   if (idata->conn_type != SILC_CONN_CLIENT) {
413     if (!silc_server_command_reply_whois_save(cmd))
414       goto out;
415   } else {
416     if (!silc_server_command_reply_whois_save_client(cmd))
417       goto out;
418   }
419
420   /* Pending callbacks are not executed if this was an list entry */
421   if (status != SILC_STATUS_OK &&
422       status != SILC_STATUS_LIST_END) {
423     silc_server_command_reply_free(cmd);
424     return;
425   }
426
427  out:
428   silc_server_command_process_error(cmd, error);
429   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
430   silc_server_command_reply_free(cmd);
431   return;
432
433  err:
434   silc_server_command_process_error(cmd, error);
435   silc_server_command_reply_free(cmd);
436 }
437
438 /* Caches the received WHOWAS information for a short period of time. */
439
440 static char
441 silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
442 {
443   SilcServer server = cmd->server;
444   SilcUInt32 len, id_len;
445   unsigned char *id_data;
446   char *nickname, *username, *realname;
447   SilcID id;
448   SilcClientEntry client;
449   SilcIDCacheEntry cache = NULL;
450   char nick[128 + 1], servername[256 + 1], uname[128 + 1];
451   int global = FALSE;
452   const char *hostname, *ip;
453
454   silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
455                               NULL, &hostname, &ip, NULL);
456
457   id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
458   nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
459   username = silc_argument_get_arg_type(cmd->args, 4, &len);
460   if (!id_data || !nickname || !username)
461     return FALSE;
462
463   realname = silc_argument_get_arg_type(cmd->args, 5, &len);
464
465   if (!silc_id_payload_parse_id(id_data, id_len, &id))
466     return FALSE;
467
468   /* Check if we have this client cached already. */
469
470   client = silc_idlist_find_client_by_id(server->local_list,
471                                          SILC_ID_GET_ID(id),
472                                          FALSE, &cache);
473   if (!client) {
474     client = silc_idlist_find_client_by_id(server->global_list,
475                                            SILC_ID_GET_ID(id),
476                                            FALSE, &cache);
477     global = TRUE;
478   }
479
480   if (!client) {
481     /* If router did not find such Client ID in its lists then this must
482        be bogus client or some router in the net is buggy. */
483     if (server->server_type != SILC_SERVER)
484       return FALSE;
485
486     /* Take hostname out of nick string if it includes it. */
487     silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
488                         sizeof(servername));
489
490     /* We don't have that client anywhere, add it. The client is added
491        to global list since server didn't have it in the lists so it must be
492        global. */
493     client = silc_idlist_add_client(server->global_list,
494                                     strdup(nick), username,
495                                     strdup(realname),
496                                     silc_id_dup(SILC_ID_GET_ID(id),
497                                                 SILC_ID_CLIENT),
498                                     silc_packet_get_context(cmd->sock), NULL);
499     if (!client) {
500       SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
501       return FALSE;
502     }
503
504     client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
505     client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
506     client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
507     client->servername = servername[0] ? strdup(servername) : NULL;
508   } else {
509     /* We have the client already, update the data */
510
511     /* Check nickname */
512     silc_parse_userfqdn(nickname, nick, sizeof(nick), servername,
513                         sizeof(servername));
514     nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
515                                      128, NULL);
516     if (!nickname) {
517       SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOWAS reply "
518                       "from %s",
519                       nick, hostname ? hostname : ""));
520       return FALSE;
521     }
522
523     /* Check username */
524     silc_parse_userfqdn(username, uname, sizeof(uname), NULL, 0);
525     if (!silc_identifier_verify(uname, strlen(uname), SILC_STRING_UTF8, 128))
526       return FALSE;
527
528     silc_free(client->nickname);
529     silc_free(client->username);
530     silc_free(client->servername);
531
532     client->nickname = strdup(nick);
533     client->username = strdup(username);
534     client->servername = servername[0] ? strdup(servername) : NULL;
535     client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
536     client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
537     client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
538
539     /* Update cache entry */
540     silc_idcache_update_by_context(global ? server->global_list->clients :
541                                    server->local_list->clients, client, NULL,
542                                    nickname, TRUE);
543   }
544
545   /* If client is global and is not on any channel then add that we'll
546      expire the entry after a while. */
547   if (global) {
548     client = silc_idlist_find_client_by_id(server->global_list, client->id,
549                                            FALSE, &cache);
550     if (client && !silc_hash_table_count(client->channels)) {
551       client->data.created = silc_time();
552       silc_dlist_del(server->expired_clients, client);
553       silc_dlist_add(server->expired_clients, client);
554     }
555   }
556
557   return TRUE;
558 }
559
560 /* Received reply for WHOWAS command. Cache the client information only for
561    a short period of time. */
562
563 SILC_SERVER_CMD_REPLY_FUNC(whowas)
564 {
565   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
566   SilcStatus status, error;
567
568   COMMAND_CHECK_STATUS;
569
570   if (!silc_server_command_reply_whowas_save(cmd))
571     goto out;
572
573   /* Pending callbacks are not executed if this was an list entry */
574   if (status != SILC_STATUS_OK &&
575       status != SILC_STATUS_LIST_END) {
576     silc_server_command_reply_free(cmd);
577     return;
578   }
579
580  out:
581   silc_server_command_process_error(cmd, error);
582   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
583   silc_server_command_reply_free(cmd);
584   return;
585
586  err:
587   silc_server_command_process_error(cmd, error);
588   silc_server_command_reply_free(cmd);
589 }
590
591 /* Caches the received IDENTIFY information. */
592
593 static char
594 silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
595 {
596   SilcServer server = cmd->server;
597   SilcUInt32 len, id_len;
598   unsigned char *id_data;
599   char *name, *info;
600   SilcClientID client_id;
601   SilcServerID server_id;
602   SilcChannelID*channel_id;
603   SilcClientEntry client;
604   SilcServerEntry server_entry;
605   SilcChannelEntry channel;
606   char global = FALSE;
607   char nick[128 + 1];
608   SilcIDPayload idp = NULL;
609   SilcIdType id_type;
610
611   id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
612   if (!id_data)
613     return FALSE;
614   idp = silc_id_payload_parse(id_data, id_len);
615   if (!idp)
616     return FALSE;
617
618   name = silc_argument_get_arg_type(cmd->args, 3, &len);
619   info = silc_argument_get_arg_type(cmd->args, 4, &len);
620
621   id_type = silc_id_payload_get_type(idp);
622
623   switch (id_type) {
624   case SILC_ID_CLIENT:
625     if (!silc_id_payload_get_id(idp, &client_id, sizeof(client_id)))
626       goto error;
627
628     SILC_LOG_DEBUG(("Received client information"));
629
630     client = silc_idlist_find_client_by_id(server->local_list,
631                                            &client_id, FALSE, NULL);
632     if (!client) {
633       client = silc_idlist_find_client_by_id(server->global_list, &client_id,
634                                              FALSE, NULL);
635       global = TRUE;
636     }
637     if (!client) {
638       /* If router did not find such Client ID in its lists then this must
639          be bogus client or some router in the net is buggy. */
640       if (server->server_type != SILC_SERVER)
641         goto error;
642
643       /* Take nickname */
644       if (name)
645         silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
646
647       /* We don't have that client anywhere, add it. The client is added
648          to global list since server didn't have it in the lists so it must be
649          global. */
650       client = silc_idlist_add_client(server->global_list,
651                                       nick[0] ? nick : NULL, info, NULL,
652                                       silc_id_dup(&client_id, SILC_ID_CLIENT),
653                                       silc_packet_get_context(cmd->sock),
654                                       NULL);
655       if (!client) {
656         SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
657         goto error;
658       }
659
660       client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
661       client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
662       client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
663     } else {
664       /* We have the client already, update the data */
665
666       SILC_LOG_DEBUG(("Updating client data"));
667
668       /* Take nickname */
669       if (name) {
670         silc_parse_userfqdn(name, nick, sizeof(nick), NULL, 0);
671
672         /* Check nickname */
673         name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
674                                      128, NULL);
675         if (!name) {
676           SILC_LOG_ERROR(("Malformed nickname '%s' received in IDENTIFY "
677                           "reply ", nick));
678           return FALSE;
679         }
680
681         silc_free(client->nickname);
682         client->nickname = strdup(nick);
683
684         /* Update the context */
685         silc_idcache_update_by_context(global ? server->global_list->clients :
686                                        server->local_list->clients, client,
687                                        NULL, name, TRUE);
688       }
689
690       if (info) {
691         silc_free(client->username);
692         client->username = strdup(info);
693       }
694
695       client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
696       client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
697     }
698
699     break;
700
701   case SILC_ID_SERVER:
702     if (!name)
703       goto error;
704
705     if (!silc_id_payload_get_id(idp, &server_id, sizeof(server_id)))
706       goto error;
707
708     SILC_LOG_DEBUG(("Received server information"));
709
710     server_entry = silc_idlist_find_server_by_id(server->local_list,
711                                                  &server_id, FALSE, NULL);
712     if (!server_entry)
713       server_entry = silc_idlist_find_server_by_id(server->global_list,
714                                                    &server_id, FALSE, NULL);
715     if (!server_entry) {
716       /* If router did not find such Server ID in its lists then this must
717          be bogus server or some router in the net is buggy. */
718       if (server->server_type != SILC_SERVER)
719         goto error;
720
721       /* We don't have that server anywhere, add it. */
722       server_entry = silc_idlist_add_server(server->global_list,
723                                             strdup(name), 0,
724                                             silc_id_dup(&server_id,
725                                                         SILC_ID_SERVER),
726                                             server->router,
727                                             SILC_PRIMARY_ROUTE(server));
728       if (!server_entry)
729         goto error;
730
731       server_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
732       server_entry->data.status |= SILC_IDLIST_STATUS_RESOLVED;
733       server_entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
734     }
735
736     break;
737
738   case SILC_ID_CHANNEL:
739     if (!name)
740       goto error;
741
742     if (!silc_id_payload_get_id(idp, &channel_id, sizeof(channel_id)))
743       goto error;
744
745     SILC_LOG_DEBUG(("Received channel information"));
746
747     /* Check channel name */
748     info = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
749                                    256, NULL);
750     if (!info)
751       goto error;
752
753     channel = silc_idlist_find_channel_by_name(server->local_list,
754                                                info, NULL);
755     if (!channel)
756       channel = silc_idlist_find_channel_by_name(server->global_list,
757                                                  info, NULL);
758     if (!channel) {
759       /* If router did not find such Channel ID in its lists then this must
760          be bogus channel or some router in the net is buggy. */
761       if (server->server_type != SILC_SERVER) {
762         silc_free(info);
763         goto error;
764       }
765
766       /* We don't have that channel anywhere, add it. */
767       channel = silc_idlist_add_channel(server->global_list, strdup(name),
768                                         SILC_CHANNEL_MODE_NONE,
769                                         silc_id_dup(&channel_id,
770                                                     SILC_ID_CHANNEL),
771                                         server->router, NULL, NULL, 0);
772       if (!channel) {
773         silc_free(info);
774         goto error;
775       }
776       silc_free(info);
777     }
778
779     break;
780   }
781
782   silc_id_payload_free(idp);
783   return TRUE;
784
785  error:
786   silc_id_payload_free(idp);
787   return FALSE;
788 }
789
790 /* Received reply for forwarded IDENTIFY command. We have received the
791    requested identify information now and we will cache it. After this we
792    will call the pending command so that the requestee gets the information
793    after all. */
794
795 SILC_SERVER_CMD_REPLY_FUNC(identify)
796 {
797   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
798   SilcStatus status, error;
799
800   COMMAND_CHECK_STATUS;
801
802   if (!silc_server_command_reply_identify_save(cmd))
803     goto out;
804
805   /* Pending callbacks are not executed if this was an list entry */
806   if (status != SILC_STATUS_OK &&
807       status != SILC_STATUS_LIST_END) {
808     silc_server_command_reply_free(cmd);
809     return;
810   }
811
812  out:
813   silc_server_command_process_error(cmd, error);
814   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
815   silc_server_command_reply_free(cmd);
816   return;
817
818  err:
819   silc_server_command_process_error(cmd, error);
820   silc_server_command_reply_free(cmd);
821 }
822
823 /* Received reply fro INFO command. Cache the server and its information */
824
825 SILC_SERVER_CMD_REPLY_FUNC(info)
826 {
827   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
828   SilcServer server = cmd->server;
829   SilcStatus status, error;
830   SilcServerEntry entry;
831   SilcID id;
832   SilcUInt32 tmp_len;
833   unsigned char *tmp, *name;
834
835   COMMAND_CHECK_STATUS;
836
837   /* Get Server ID */
838   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
839     goto out;
840
841   /* Get the name */
842   name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
843   if (!name)
844     goto out;
845
846   entry = silc_idlist_find_server_by_id(server->local_list,
847                                         SILC_ID_GET_ID(id),
848                                         FALSE, NULL);
849   if (!entry) {
850     entry = silc_idlist_find_server_by_id(server->global_list,
851                                           SILC_ID_GET_ID(id),
852                                           FALSE, NULL);
853     if (!entry) {
854       /* Add the server to global list */
855       entry = silc_idlist_add_server(server->global_list, strdup(name), 0,
856                                      silc_id_dup(SILC_ID_GET_ID(id),
857                                                  SILC_ID_SERVER),
858                                      silc_packet_get_context(cmd->sock),
859                                      cmd->sock);
860       if (!entry)
861         goto out;
862
863       entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
864     }
865   }
866
867   /* Get the info string */
868   tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
869   if (tmp_len > 256)
870     tmp = NULL;
871
872   entry->server_info = tmp ? strdup(tmp) : NULL;
873
874  out:
875   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
876  err:
877   silc_server_command_reply_free(cmd);
878 }
879
880 /* Received reply fro MOTD command. */
881
882 SILC_SERVER_CMD_REPLY_FUNC(motd)
883 {
884   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
885   SilcServer server = cmd->server;
886   SilcStatus status, error;
887   SilcServerEntry entry = NULL;
888   SilcID id;
889   SilcUInt32 tmp_len;
890   unsigned char *tmp;
891
892   COMMAND_CHECK_STATUS;
893
894   /* Get Server ID */
895   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
896     goto out;
897
898   entry = silc_idlist_find_server_by_id(server->local_list,
899                                         SILC_ID_GET_ID(id),
900                                         TRUE, NULL);
901   if (!entry) {
902     entry = silc_idlist_find_server_by_id(server->global_list,
903                                           SILC_ID_GET_ID(id),
904                                           TRUE, NULL);
905     if (!entry) {
906       SilcBuffer buffer;
907
908       /* If router did not find such Server ID in its lists then this must
909          be bogus client or some router in the net is buggy. */
910       if (server->server_type != SILC_SERVER)
911         goto out;
912
913       /* Statistics */
914       cmd->server->stat.commands_sent++;
915
916       /* entry isn't known so we IDENTIFY it. otherwise the
917          silc_server_command_motd won't know about it and tell
918          the client that there is no such server */
919       tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
920       buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
921                                               ++server->cmd_ident, 5,
922                                               1, NULL, 0, 2, NULL, 0,
923                                               3, NULL, 0, 4, NULL, 0,
924                                               5, tmp, tmp_len);
925       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
926                               SILC_PACKET_COMMAND, 0, buffer->data,
927                               silc_buffer_len(buffer));
928       silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
929                                   server->cmd_ident,
930                                   silc_server_command_reply_motd,
931                                   cmd);
932       silc_buffer_free(buffer);
933       return;
934     }
935   }
936
937   /* Get the motd */
938   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
939   if (tmp_len > 256)
940     tmp = NULL;
941
942   entry->motd = tmp;
943
944  out:
945   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_MOTD);
946  err:
947   silc_server_command_reply_free(cmd);
948
949   if (entry)
950     entry->motd = NULL;
951 }
952
953 /* Received reply for forwarded JOIN command. Router has created or joined
954    the client to the channel. We save some channel information locally
955    for future use. */
956
957 SILC_SERVER_CMD_REPLY_FUNC(join)
958 {
959   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
960   SilcServer server = cmd->server;
961   SilcIDCacheEntry cache = NULL;
962   SilcStatus status, error;
963   SilcID id, id2;
964   SilcChannelEntry entry;
965   SilcHmac hmac = NULL;
966   SilcUInt32 len, list_count;
967   char *channel_name, *channel_namec = NULL, *tmp;
968   SilcUInt32 mode, created;
969   SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
970   SilcPublicKey founder_key = NULL;
971
972   COMMAND_CHECK_STATUS;
973
974   /* Get channel name */
975   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
976   if (!channel_name)
977     goto out;
978
979   /* Get channel ID */
980   if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id, NULL))
981     goto out;
982
983   /* Get client ID */
984   if (!silc_argument_get_decoded(cmd->args, 4, SILC_ARGUMENT_ID, &id2, NULL))
985     goto out;
986
987   /* Get mode mask */
988   tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
989   if (!tmp)
990     goto out;
991   SILC_GET32_MSB(mode, tmp);
992
993   /* Get created boolean value */
994   tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
995   if (!tmp)
996     goto out;
997   SILC_GET32_MSB(created, tmp);
998   if (created != 0 && created != 1)
999     goto out;
1000
1001   /* Get channel key */
1002   tmp = silc_argument_get_arg_type(cmd->args, 7, &len);
1003   if (tmp) {
1004     keyp = silc_buffer_alloc(len);
1005     silc_buffer_pull_tail(keyp, silc_buffer_truelen(keyp));
1006     silc_buffer_put(keyp, tmp, len);
1007   }
1008
1009   /* Get hmac */
1010   tmp = silc_argument_get_arg_type(cmd->args, 11, NULL);
1011   if (tmp) {
1012     if (!silc_hmac_alloc(tmp, NULL, &hmac))
1013       goto out;
1014   }
1015
1016   /* Get the list count */
1017   tmp = silc_argument_get_arg_type(cmd->args, 12, &len);
1018   if (!tmp)
1019     goto out;
1020   SILC_GET32_MSB(list_count, tmp);
1021
1022   /* Get Client ID list */
1023   tmp = silc_argument_get_arg_type(cmd->args, 13, &len);
1024   if (!tmp)
1025     goto out;
1026
1027   client_id_list = silc_buffer_alloc(len);
1028   silc_buffer_pull_tail(client_id_list, len);
1029   silc_buffer_put(client_id_list, tmp, len);
1030
1031   /* Get client mode list */
1032   tmp = silc_argument_get_arg_type(cmd->args, 14, &len);
1033   if (!tmp)
1034     goto out;
1035
1036   client_mode_list = silc_buffer_alloc(len);
1037   silc_buffer_pull_tail(client_mode_list, len);
1038   silc_buffer_put(client_mode_list, tmp, len);
1039
1040   /* Get founder key */
1041   tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
1042   if (tmp)
1043     silc_public_key_payload_decode(tmp, len, &founder_key);
1044
1045   /* See whether we already have the channel. */
1046   channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
1047                                           SILC_STRING_UTF8, 256, NULL);
1048   if (!channel_namec)
1049     goto out;
1050   entry = silc_idlist_find_channel_by_name(server->local_list,
1051                                            channel_namec, &cache);
1052   if (!entry) {
1053     /* Add new channel */
1054
1055     SILC_LOG_DEBUG(("Adding new [%s] channel %s id(%s)",
1056                     (created == 0 ? "existing" : "created"), channel_name,
1057                     silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL)));
1058
1059     /* If the channel is found from global list we must move it to the
1060        local list. */
1061     entry = silc_idlist_find_channel_by_name(server->global_list,
1062                                              channel_namec, &cache);
1063     if (entry)
1064       silc_idlist_del_channel(server->global_list, entry);
1065
1066     /* Add the channel to our local list. */
1067     entry = silc_idlist_add_channel(server->local_list, strdup(channel_name),
1068                                     SILC_CHANNEL_MODE_NONE,
1069                                     silc_id_dup(SILC_ID_GET_ID(id),
1070                                                 SILC_ID_CHANNEL),
1071                                     server->router, NULL, NULL, hmac);
1072     if (!entry)
1073       goto out;
1074
1075     hmac = NULL;
1076     server->stat.my_channels++;
1077     server->stat.channels++;
1078   } else {
1079     /* The entry exists. */
1080
1081     /* If ID has changed, then update it to the cache too. */
1082     if (!SILC_ID_CHANNEL_COMPARE(entry->id, SILC_ID_GET_ID(id)))
1083       silc_idlist_replace_channel_id(server->local_list, entry->id,
1084                                      SILC_ID_GET_ID(id));
1085
1086     entry->disabled = FALSE;
1087
1088     /* Remove the founder auth data if the mode is not set but we have
1089        them in the entry */
1090     if (!(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && entry->founder_key) {
1091       silc_pkcs_public_key_free(entry->founder_key);
1092       entry->founder_key = NULL;
1093     }
1094   }
1095
1096   if (founder_key) {
1097     if (entry->founder_key)
1098       silc_pkcs_public_key_free(entry->founder_key);
1099     entry->founder_key = founder_key;
1100     founder_key = NULL;
1101   }
1102
1103   if (entry->hmac_name && (hmac || (!hmac && entry->hmac))) {
1104     silc_free(entry->hmac_name);
1105     entry->hmac_name = strdup(silc_hmac_get_name(hmac ? hmac : entry->hmac));
1106   }
1107
1108   /* Get the ban list */
1109   tmp = silc_argument_get_arg_type(cmd->args, 8, &len);
1110   if (tmp && len > 2) {
1111     SilcArgumentPayload iargs;
1112     SilcUInt16 iargc;
1113     SILC_GET16_MSB(iargc, tmp);
1114     iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1115     if (iargs) {
1116       /* Delete old ban list */
1117       if (entry->ban_list)
1118         silc_hash_table_free(entry->ban_list);
1119       entry->ban_list =
1120         silc_hash_table_alloc(0, silc_hash_ptr,
1121                               NULL, NULL, NULL,
1122                               silc_server_inviteban_destruct, entry, TRUE);
1123
1124       /* Add new ban list */
1125       silc_server_inviteban_process(server, entry->ban_list, 0, iargs);
1126       silc_argument_payload_free(iargs);
1127     }
1128   }
1129
1130   /* Get the invite list */
1131   tmp = silc_argument_get_arg_type(cmd->args, 9, &len);
1132   if (tmp && len > 2) {
1133     SilcArgumentPayload iargs;
1134     SilcUInt16 iargc;
1135     SILC_GET16_MSB(iargc, tmp);
1136     iargs = silc_argument_payload_parse(tmp + 2, len - 2, iargc);
1137     if (iargs) {
1138       /* Delete old invite list */
1139       if (entry->invite_list)
1140         silc_hash_table_free(entry->invite_list);
1141       entry->invite_list =
1142         silc_hash_table_alloc(0, silc_hash_ptr,
1143                               NULL, NULL, NULL,
1144                               silc_server_inviteban_destruct, entry, TRUE);
1145
1146       /* Add new invite list */
1147       silc_server_inviteban_process(server, entry->invite_list, 0, iargs);
1148       silc_argument_payload_free(iargs);
1149     }
1150   }
1151
1152   /* Get the topic */
1153   tmp = silc_argument_get_arg_type(cmd->args, 10, &len);
1154   if (tmp) {
1155     silc_free(entry->topic);
1156     entry->topic = strdup(tmp);
1157   }
1158
1159   /* Get channel public key list */
1160   tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
1161   if (tmp && server->server_type != SILC_ROUTER)
1162     silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
1163
1164   /* The the user limit */
1165   tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
1166   if (tmp && len == 4)
1167     SILC_GET32_MSB(entry->user_limit, tmp);
1168
1169   /* If channel was not created we know there is global users on the
1170      channel. */
1171   entry->global_users = (created == 0 ? TRUE : FALSE);
1172
1173   /* If channel was just created the mask must be zero */
1174   if (!entry->global_users && mode)
1175     mode = 0;
1176
1177   /* Save channel mode */
1178   entry->mode = mode;
1179
1180   /* Save channel key */
1181   if (keyp) {
1182     if (!(entry->mode & SILC_CHANNEL_MODE_PRIVKEY))
1183       silc_server_save_channel_key(server, keyp, entry);
1184     silc_buffer_free(keyp);
1185   }
1186
1187   /* Save the users to the channel */
1188   silc_server_save_users_on_channel(server, cmd->sock, entry,
1189                                     SILC_ID_GET_ID(id2), client_id_list,
1190                                     client_mode_list, list_count);
1191   entry->users_resolved = TRUE;
1192
1193  out:
1194   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
1195  err:
1196   silc_free(channel_namec);
1197   if (hmac)
1198     silc_hmac_free(hmac);
1199   silc_server_command_reply_free(cmd);
1200
1201   if (founder_key)
1202     silc_pkcs_public_key_free(founder_key);
1203   if (client_id_list)
1204     silc_buffer_free(client_id_list);
1205   if (client_mode_list)
1206     silc_buffer_free(client_mode_list);
1207 }
1208
1209 /* Received reply to STATS command.  */
1210
1211 SILC_SERVER_CMD_REPLY_FUNC(stats)
1212 {
1213   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1214   SilcServer server = cmd->server;
1215   SilcStatus status, error;
1216   unsigned char *tmp;
1217   SilcUInt32 tmp_len;
1218   SilcBufferStruct buf;
1219
1220   COMMAND_CHECK_STATUS;
1221
1222   /* Get statistics structure */
1223   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1224   if (server->server_type != SILC_ROUTER && tmp) {
1225     silc_buffer_set(&buf, tmp, tmp_len);
1226     silc_buffer_unformat(&buf,
1227                          SILC_STR_UI_INT(NULL),
1228                          SILC_STR_UI_INT(NULL),
1229                          SILC_STR_UI_INT(NULL),
1230                          SILC_STR_UI_INT(NULL),
1231                          SILC_STR_UI_INT(NULL),
1232                          SILC_STR_UI_INT(NULL),
1233                          SILC_STR_UI_INT(&server->stat.cell_clients),
1234                          SILC_STR_UI_INT(&server->stat.cell_channels),
1235                          SILC_STR_UI_INT(&server->stat.cell_servers),
1236                          SILC_STR_UI_INT(&server->stat.clients),
1237                          SILC_STR_UI_INT(&server->stat.channels),
1238                          SILC_STR_UI_INT(&server->stat.servers),
1239                          SILC_STR_UI_INT(&server->stat.routers),
1240                          SILC_STR_UI_INT(&server->stat.server_ops),
1241                          SILC_STR_UI_INT(&server->stat.router_ops),
1242                          SILC_STR_END);
1243   }
1244
1245   SILC_LOG_DEBUG(("stat.clients = %d\n", server->stat.clients));
1246
1247  out:
1248   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
1249  err:
1250   silc_server_command_reply_free(cmd);
1251 }
1252
1253 SILC_SERVER_CMD_REPLY_FUNC(users)
1254 {
1255   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1256   SilcServer server = cmd->server;
1257   SilcStatus status, error;
1258   SilcChannelEntry channel;
1259   SilcID id;
1260   SilcBuffer client_id_list;
1261   SilcBuffer client_mode_list;
1262   unsigned char *tmp;
1263   SilcUInt32 tmp_len;
1264   SilcUInt32 list_count;
1265
1266   COMMAND_CHECK_STATUS;
1267
1268   /* Get channel ID */
1269   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1270     goto out;
1271
1272   /* Get channel entry */
1273   channel = silc_idlist_find_channel_by_id(server->local_list,
1274                                            SILC_ID_GET_ID(id), NULL);
1275   if (!channel) {
1276     channel = silc_idlist_find_channel_by_id(server->global_list,
1277                                              SILC_ID_GET_ID(id), NULL);
1278     if (!channel) {
1279       SilcBuffer idp;
1280
1281       if (server->server_type != SILC_SERVER)
1282         goto out;
1283
1284       idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1285       silc_server_send_command(server, SILC_PRIMARY_ROUTE(server),
1286                                SILC_COMMAND_IDENTIFY, ++server->cmd_ident,
1287                                1, 5, idp->data, silc_buffer_len(idp));
1288       silc_buffer_free(idp);
1289
1290       /* Register pending command callback. After we've received the channel
1291          information we will reprocess this command reply by re-calling this
1292          USERS command reply callback. */
1293       silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1294                                   server->cmd_ident,
1295                                   silc_server_command_reply_users, cmd);
1296       return;
1297     }
1298   }
1299
1300   /* Get the list count */
1301   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1302   if (!tmp)
1303     goto out;
1304   SILC_GET32_MSB(list_count, tmp);
1305
1306   /* Get Client ID list */
1307   tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
1308   if (!tmp)
1309     goto out;
1310
1311   client_id_list = silc_buffer_alloc(tmp_len);
1312   silc_buffer_pull_tail(client_id_list, tmp_len);
1313   silc_buffer_put(client_id_list, tmp, tmp_len);
1314
1315   /* Get client mode list */
1316   tmp = silc_argument_get_arg_type(cmd->args, 5, &tmp_len);
1317   if (!tmp)
1318     goto out;
1319
1320   client_mode_list = silc_buffer_alloc(tmp_len);
1321   silc_buffer_pull_tail(client_mode_list, tmp_len);
1322   silc_buffer_put(client_mode_list, tmp, tmp_len);
1323
1324   /* Save the users to the channel */
1325   silc_server_save_users_on_channel(server, cmd->sock, channel, NULL,
1326                                     client_id_list, client_mode_list,
1327                                     list_count);
1328
1329   channel->global_users = silc_server_channel_has_global(channel);
1330   channel->users_resolved = TRUE;
1331
1332   silc_buffer_free(client_id_list);
1333   silc_buffer_free(client_mode_list);
1334
1335  out:
1336   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
1337  err:
1338   silc_server_command_reply_free(cmd);
1339 }
1340
1341 SILC_SERVER_CMD_REPLY_FUNC(getkey)
1342 {
1343   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1344   SilcServer server = cmd->server;
1345   SilcStatus status, error;
1346   SilcClientEntry client = NULL;
1347   SilcServerEntry server_entry = NULL;
1348   SilcClientID client_id;
1349   SilcServerID server_id;
1350   unsigned char *tmp;
1351   SilcUInt32 len;
1352   SilcIDPayload idp = NULL;
1353   SilcIdType id_type;
1354   SilcPublicKey public_key = NULL;
1355
1356   COMMAND_CHECK_STATUS;
1357
1358   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1359   if (!tmp)
1360     goto out;
1361   idp = silc_id_payload_parse(tmp, len);
1362   if (!idp)
1363     goto out;
1364
1365   /* Get the public key payload */
1366   tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
1367   if (!tmp)
1368     goto out;
1369
1370   /* Decode the public key payload */
1371   if (!silc_public_key_payload_decode(tmp, len, &public_key))
1372     goto out;
1373
1374   id_type = silc_id_payload_get_type(idp);
1375   if (id_type == SILC_ID_CLIENT) {
1376     silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
1377
1378     client = silc_idlist_find_client_by_id(server->local_list, &client_id,
1379                                            TRUE, NULL);
1380     if (!client) {
1381       client = silc_idlist_find_client_by_id(server->global_list,
1382                                              &client_id, TRUE, NULL);
1383       if (!client)
1384         goto out;
1385     }
1386
1387     if (!client->data.public_key) {
1388       /* Add client's public key to repository */
1389       if (!silc_server_get_public_key_by_client(server, client, NULL))
1390         silc_skr_add_public_key_simple(server->repository,
1391                                        public_key,
1392                                        SILC_SKR_USAGE_IDENTIFICATION,
1393                                        client, NULL);
1394       client->data.public_key = public_key;
1395       public_key = NULL;
1396     }
1397   } else if (id_type == SILC_ID_SERVER) {
1398     silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
1399
1400     server_entry = silc_idlist_find_server_by_id(server->local_list,
1401                                                  &server_id, TRUE, NULL);
1402     if (!server_entry) {
1403       server_entry = silc_idlist_find_server_by_id(server->global_list,
1404                                                    &server_id, TRUE, NULL);
1405       if (!server_entry)
1406         goto out;
1407     }
1408
1409     server_entry->data.public_key = public_key;
1410     public_key = NULL;
1411   } else {
1412     goto out;
1413   }
1414
1415  out:
1416   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_GETKEY);
1417   if (idp)
1418     silc_id_payload_free(idp);
1419   if (public_key)
1420     silc_pkcs_public_key_free(public_key);
1421  err:
1422   silc_server_command_reply_free(cmd);
1423 }
1424
1425 SILC_SERVER_CMD_REPLY_FUNC(list)
1426 {
1427   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1428   SilcServer server = cmd->server;
1429   SilcStatus status, error;
1430   SilcID id;
1431   SilcChannelEntry channel;
1432   SilcIDCacheEntry cache;
1433   unsigned char *tmp, *name, *namec = NULL, *topic;
1434   SilcUInt32 usercount = 0;
1435   SilcBool global_list = FALSE;
1436
1437   COMMAND_CHECK_STATUS;
1438
1439   if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL))
1440     goto out;
1441
1442   name = silc_argument_get_arg_type(cmd->args, 3, NULL);
1443   topic = silc_argument_get_arg_type(cmd->args, 4, NULL);
1444   tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1445   if (tmp)
1446     SILC_GET32_MSB(usercount, tmp);
1447
1448   namec = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
1449                                   256, NULL);
1450   if (!namec)
1451     goto out;
1452
1453   /* Add the channel entry if we do not have it already */
1454   channel = silc_idlist_find_channel_by_name(server->local_list,
1455                                              namec, &cache);
1456   if (!channel) {
1457     channel = silc_idlist_find_channel_by_name(server->global_list,
1458                                                namec, &cache);
1459     global_list = TRUE;
1460   }
1461   if (!channel) {
1462     /* If router did not find such channel in its lists then this must
1463        be bogus channel or some router in the net is buggy. */
1464     if (server->server_type != SILC_SERVER)
1465       goto out;
1466
1467     channel = silc_idlist_add_channel(server->global_list, strdup(name),
1468                                       SILC_CHANNEL_MODE_NONE,
1469                                       silc_id_dup(SILC_ID_GET_ID(id),
1470                                                   SILC_ID_CHANNEL),
1471                                       server->router, NULL, NULL, NULL);
1472     if (!channel)
1473       goto out;
1474   }
1475
1476   channel->user_count = usercount;
1477
1478   if (topic) {
1479     silc_free(channel->topic);
1480     channel->topic = strdup(topic);
1481   }
1482
1483   /* Pending callbacks are not executed if this was an list entry */
1484   if (status != SILC_STATUS_OK &&
1485       status != SILC_STATUS_LIST_END) {
1486     silc_server_command_reply_free(cmd);
1487     return;
1488   }
1489
1490  out:
1491   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
1492  err:
1493   silc_free(namec);
1494   silc_server_command_reply_free(cmd);
1495 }
1496
1497 SILC_SERVER_CMD_REPLY_FUNC(watch)
1498 {
1499   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1500   SilcStatus status, error;
1501
1502   COMMAND_CHECK_STATUS;
1503
1504  out:
1505   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WATCH);
1506  err:
1507   silc_server_command_reply_free(cmd);
1508 }
1509
1510 SILC_SERVER_CMD_REPLY_FUNC(ping)
1511 {
1512   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
1513   SilcStatus status, error;
1514
1515   COMMAND_CHECK_STATUS;
1516
1517  out:
1518   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_PING);
1519  err:
1520   silc_server_command_reply_free(cmd);
1521 }