Code auditing weekend results and fixes committing.
[silc.git] / lib / silcclient / client.c
1 /*
2
3   client.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 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; either version 2 of the License, or
12   (at your option) any later version.
13   
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.
18
19 */
20 /* $Id$ */
21
22 #include "clientlibincludes.h"
23
24 /* Static task callback prototypes */
25 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
26 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
27 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
28 SILC_TASK_CALLBACK(silc_client_packet_process);
29 SILC_TASK_CALLBACK(silc_client_packet_parse_real);
30
31 static void silc_client_packet_parse(SilcPacketParserContext *parser_context);
32 static void silc_client_packet_parse_type(SilcClient client, 
33                                           SilcSocketConnection sock,
34                                           SilcPacketContext *packet);
35
36 /* Allocates new client object. This has to be done before client may
37    work. After calling this one must call silc_client_init to initialize
38    the client. The `application' is application specific user data pointer
39    and caller must free it. */
40
41 SilcClient silc_client_alloc(SilcClientOperations *ops, void *application)
42 {
43   SilcClient new_client;
44
45   new_client = silc_calloc(1, sizeof(*new_client));
46   new_client->application = application;
47   new_client->ops = ops;
48
49   return new_client;
50 }
51
52 /* Free's client object */
53
54 void silc_client_free(SilcClient client)
55 {
56   if (client) {
57     silc_free(client);
58   }
59 }
60
61 /* Initializes the client. This makes all the necessary steps to make
62    the client ready to be run. One must call silc_client_run to run the
63    client. */
64
65 int silc_client_init(SilcClient client)
66 {
67   SILC_LOG_DEBUG(("Initializing client"));
68
69   /* Initialize hash functions for client to use */
70   silc_hash_alloc("md5", &client->md5hash);
71   silc_hash_alloc("sha1", &client->sha1hash);
72
73   /* Initialize none cipher */
74   silc_cipher_alloc("none", &client->none_cipher);
75
76   /* Initialize random number generator */
77   client->rng = silc_rng_alloc();
78   silc_rng_init(client->rng);
79   silc_math_primegen_init(); /* XXX */
80
81   /* Register protocols */
82   silc_client_protocols_register();
83
84   /* Initialize the scheduler */
85   silc_schedule_init(&client->io_queue, &client->timeout_queue, 
86                      &client->generic_queue, 5000);
87
88   return TRUE;
89 }
90
91 /* Stops the client. This is called to stop the client and thus to stop
92    the program. */
93
94 void silc_client_stop(SilcClient client)
95 {
96   SILC_LOG_DEBUG(("Stopping client"));
97
98   /* Stop the scheduler, although it might be already stopped. This
99      doesn't hurt anyone. This removes all the tasks and task queues,
100      as well. */
101   silc_schedule_stop();
102   silc_schedule_uninit();
103
104   silc_client_protocols_unregister();
105
106   SILC_LOG_DEBUG(("Client stopped"));
107 }
108
109 /* Runs the client. */
110
111 void silc_client_run(SilcClient client)
112 {
113   SILC_LOG_DEBUG(("Running client"));
114
115   /* Start the scheduler, the heart of the SILC client. When this returns
116      the program will be terminated. */
117   silc_schedule();
118 }
119
120 /* Allocates and adds new connection to the client. This adds the allocated
121    connection to the connection table and returns a pointer to it. A client
122    can have multiple connections to multiple servers. Every connection must
123    be added to the client using this function. User data `context' may
124    be sent as argument. */
125
126 SilcClientConnection silc_client_add_connection(SilcClient client,
127                                                 char *hostname,
128                                                 int port,
129                                                 void *context)
130 {
131   SilcClientConnection conn;
132   int i;
133
134   conn = silc_calloc(1, sizeof(*conn));
135
136   /* Initialize ID caches */
137   conn->client_cache = silc_idcache_alloc(0);
138   conn->channel_cache = silc_idcache_alloc(0);
139   conn->server_cache = silc_idcache_alloc(0);
140   conn->client = client;
141   conn->remote_host = strdup(hostname);
142   conn->remote_port = port;
143   conn->context = context;
144   conn->pending_commands = silc_dlist_init();
145
146   /* Add the connection to connections table */
147   for (i = 0; i < client->conns_count; i++)
148     if (client->conns && !client->conns[i]) {
149       client->conns[i] = conn;
150       return conn;
151     }
152
153   client->conns = silc_realloc(client->conns, sizeof(*client->conns)
154                                * (client->conns_count + 1));
155   client->conns[client->conns_count] = conn;
156   client->conns_count++;
157
158   return conn;
159 }
160
161 /* Removes connection from client. */
162
163 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
164 {
165   int i;
166
167   for (i = 0; i < client->conns_count; i++)
168     if (client->conns[i] == conn) {
169       if (conn->pending_commands)
170         silc_dlist_uninit(conn->pending_commands);
171       silc_free(conn);
172       client->conns[i] = NULL;
173     }
174 }
175
176 /* Internal context for connection process. This is needed as we
177    doing asynchronous connecting. */
178 typedef struct {
179   SilcClient client;
180   SilcClientConnection conn;
181   SilcTask task;
182   int sock;
183   char *host;
184   int port;
185   int tries;
186 } SilcClientInternalConnectContext;
187
188 static int 
189 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
190 {
191   int sock;
192
193   /* XXX In the future we should give up this non-blocking connect all
194      together and use threads instead. */
195   /* Create connection to server asynchronously */
196   sock = silc_net_create_connection_async(ctx->port, ctx->host);
197   if (sock < 0)
198     return -1;
199
200   /* Register task that will receive the async connect and will
201      read the result. */
202   ctx->task = silc_task_register(ctx->client->io_queue, sock, 
203                                  silc_client_connect_to_server_start,
204                                  (void *)ctx, 0, 0, 
205                                  SILC_TASK_FD,
206                                  SILC_TASK_PRI_NORMAL);
207   silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
208   silc_schedule_set_listen_fd(sock, ctx->task->iomask);
209
210   ctx->sock = sock;
211
212   return sock;
213 }
214
215 /* Connects to remote server. This is the main routine used to connect
216    to SILC server. Returns -1 on error and the created socket otherwise. 
217    The `context' is user context that is saved into the SilcClientConnection
218    that is created after the connection is created. */
219
220 int silc_client_connect_to_server(SilcClient client, int port,
221                                   char *host, void *context)
222 {
223   SilcClientInternalConnectContext *ctx;
224   SilcClientConnection conn;
225   int sock;
226
227   SILC_LOG_DEBUG(("Connecting to port %d of server %s",
228                   port, host));
229
230   conn = silc_client_add_connection(client, host, port, context);
231
232   client->ops->say(client, conn, 
233                    "Connecting to port %d of server %s", port, host);
234
235   /* Allocate internal context for connection process. This is
236      needed as we are doing async connecting. */
237   ctx = silc_calloc(1, sizeof(*ctx));
238   ctx->client = client;
239   ctx->conn = conn;
240   ctx->host = strdup(host);
241   ctx->port = port;
242   ctx->tries = 0;
243
244   /* Do the actual connecting process */
245   sock = silc_client_connect_to_server_internal(ctx);
246   if (sock == -1)
247     silc_client_del_connection(client, conn);
248   return sock;
249 }
250
251 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
252    key material between client and server.  This function can be called
253    directly if application is performing its own connecting and does not
254    use the connecting provided by this library. */
255
256 int silc_client_start_key_exchange(SilcClient client,
257                                    SilcClientConnection conn,
258                                    int fd)
259 {
260   SilcProtocol protocol;
261   SilcClientKEInternalContext *proto_ctx;
262   void *context;
263
264   /* Allocate new socket connection object */
265   silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
266   if (conn->sock == NULL) {
267     client->ops->say(client, conn, 
268                      "Error: Could not allocate connection socket");
269     return FALSE;
270   }
271
272   conn->nickname = strdup(client->username);
273   conn->sock->hostname = conn->remote_host;
274   conn->sock->port = conn->remote_port;
275
276   /* Allocate internal Key Exchange context. This is sent to the
277      protocol as context. */
278   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
279   proto_ctx->client = (void *)client;
280   proto_ctx->sock = conn->sock;
281   proto_ctx->rng = client->rng;
282   proto_ctx->responder = FALSE;
283
284   /* Perform key exchange protocol. silc_client_connect_to_server_final
285      will be called after the protocol is finished. */
286   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
287                       &protocol, (void *)proto_ctx,
288                       silc_client_connect_to_server_second);
289   if (!protocol) {
290     client->ops->say(client, conn, 
291                      "Error: Could not start authentication protocol");
292     return FALSE;
293   }
294   conn->sock->protocol = protocol;
295
296   /* Register the connection for network input and output. This sets
297      that scheduler will listen for incoming packets for this connection 
298      and sets that outgoing packets may be sent to this connection as well.
299      However, this doesn't set the scheduler for outgoing traffic, it will 
300      be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
301      later when outgoing data is available. */
302   context = (void *)client;
303   SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
304
305   /* Execute the protocol */
306   protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
307   return TRUE;
308 }
309
310 /* Start of the connection to the remote server. This is called after
311    succesful TCP/IP connection has been established to the remote host. */
312
313 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
314 {
315   SilcClientInternalConnectContext *ctx =
316     (SilcClientInternalConnectContext *)context;
317   SilcClient client = ctx->client;
318   SilcClientConnection conn = ctx->conn;
319   int opt, opt_len = sizeof(opt);
320
321   SILC_LOG_DEBUG(("Start"));
322
323   /* Check the socket status as it might be in error */
324   getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
325   if (opt != 0) {
326     if (ctx->tries < 2) {
327       /* Connection failed but lets try again */
328       client->ops->say(client, conn, "Could not connect to server %s: %s",
329                        ctx->host, strerror(opt));
330       client->ops->say(client, conn, 
331                        "Connecting to port %d of server %s resumed", 
332                        ctx->port, ctx->host);
333
334       /* Unregister old connection try */
335       silc_schedule_unset_listen_fd(fd);
336       silc_net_close_connection(fd);
337       silc_task_unregister(client->io_queue, ctx->task);
338
339       /* Try again */
340       silc_client_connect_to_server_internal(ctx);
341       ctx->tries++;
342     } else {
343       /* Connection failed and we won't try anymore */
344       client->ops->say(client, conn, "Could not connect to server %s: %s",
345                        ctx->host, strerror(opt));
346       silc_schedule_unset_listen_fd(fd);
347       silc_net_close_connection(fd);
348       silc_task_unregister(client->io_queue, ctx->task);
349       silc_free(ctx);
350
351       /* Notify application of failure */
352       client->ops->connect(client, conn, FALSE);
353       silc_client_del_connection(client, conn);
354     }
355     return;
356   }
357
358   silc_schedule_unset_listen_fd(fd);
359   silc_task_unregister(client->io_queue, ctx->task);
360   silc_free(ctx);
361
362   if (!silc_client_start_key_exchange(client, conn, fd)) {
363     silc_net_close_connection(fd);
364     client->ops->connect(client, conn, FALSE);
365   }
366 }
367
368 /* Second part of the connecting to the server. This executed 
369    authentication protocol. */
370
371 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
372 {
373   SilcProtocol protocol = (SilcProtocol)context;
374   SilcClientKEInternalContext *ctx = 
375     (SilcClientKEInternalContext *)protocol->context;
376   SilcClient client = (SilcClient)ctx->client;
377   SilcSocketConnection sock = NULL;
378   SilcClientConnAuthInternalContext *proto_ctx;
379
380   SILC_LOG_DEBUG(("Start"));
381
382   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
383       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
384     /* Error occured during protocol */
385     SILC_LOG_DEBUG(("Error during KE protocol"));
386     silc_protocol_free(protocol);
387     if (ctx->ske)
388       silc_ske_free(ctx->ske);
389     if (ctx->dest_id)
390       silc_free(ctx->dest_id);
391     ctx->sock->protocol = NULL;
392
393     /* Notify application of failure */
394     client->ops->connect(client, ctx->sock->user_data, FALSE);
395     silc_free(ctx);
396     return;
397   }
398
399   /* Allocate internal context for the authentication protocol. This
400      is sent as context for the protocol. */
401   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
402   proto_ctx->client = (void *)client;
403   proto_ctx->sock = sock = ctx->sock;
404   proto_ctx->ske = ctx->ske;    /* Save SKE object from previous protocol */
405   proto_ctx->dest_id_type = ctx->dest_id_type;
406   proto_ctx->dest_id = ctx->dest_id;
407
408   /* Resolve the authentication method to be used in this connection */
409   if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
410                                     sock->port, &proto_ctx->auth_meth,
411                                     &proto_ctx->auth_data, 
412                                     &proto_ctx->auth_data_len))
413     {
414       /* XXX do AUTH_REQUEST resolcing with server */
415       proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
416     }
417
418   /* Free old protocol as it is finished now */
419   silc_protocol_free(protocol);
420   if (ctx->packet)
421     silc_packet_context_free(ctx->packet);
422   silc_free(ctx);
423   /* silc_free(ctx->keymat....); */
424   sock->protocol = NULL;
425
426   /* Allocate the authentication protocol. This is allocated here
427      but we won't start it yet. We will be receiving party of this
428      protocol thus we will wait that connecting party will make
429      their first move. */
430   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
431                       &sock->protocol, (void *)proto_ctx, 
432                       silc_client_connect_to_server_final);
433
434   /* Execute the protocol */
435   sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
436 }
437
438 /* Finalizes the connection to the remote SILC server. This is called
439    after authentication protocol has been completed. This send our
440    user information to the server to receive our client ID from
441    server. */
442
443 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
444 {
445   SilcProtocol protocol = (SilcProtocol)context;
446   SilcClientConnAuthInternalContext *ctx = 
447     (SilcClientConnAuthInternalContext *)protocol->context;
448   SilcClient client = (SilcClient)ctx->client;
449   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
450   SilcBuffer packet;
451
452   SILC_LOG_DEBUG(("Start"));
453
454   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
455       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
456     /* Error occured during protocol */
457     SILC_LOG_DEBUG(("Error during authentication protocol"));
458     silc_protocol_free(protocol);
459     if (ctx->auth_data)
460       silc_free(ctx->auth_data);
461     if (ctx->ske)
462       silc_ske_free(ctx->ske);
463     if (ctx->dest_id)
464       silc_free(ctx->dest_id);
465     conn->sock->protocol = NULL;
466
467     /* Notify application of failure */
468     client->ops->connect(client, ctx->sock->user_data, FALSE);
469     silc_free(ctx);
470     return;
471   }
472
473   /* Send NEW_CLIENT packet to the server. We will become registered
474      to the SILC network after sending this packet and we will receive
475      client ID from the server. */
476   packet = silc_buffer_alloc(2 + 2 + strlen(client->username) + 
477                              strlen(client->realname));
478   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
479   silc_buffer_format(packet,
480                      SILC_STR_UI_SHORT(strlen(client->username)),
481                      SILC_STR_UI_XNSTRING(client->username,
482                                           strlen(client->username)),
483                      SILC_STR_UI_SHORT(strlen(client->realname)),
484                      SILC_STR_UI_XNSTRING(client->realname,
485                                           strlen(client->realname)),
486                      SILC_STR_END);
487
488   /* Send the packet */
489   silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
490                           NULL, 0, NULL, NULL, 
491                           packet->data, packet->len, TRUE);
492   silc_buffer_free(packet);
493
494   /* Save remote ID. */
495   conn->remote_id = ctx->dest_id;
496   conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
497   conn->remote_id_data_len = SILC_ID_SERVER_LEN;
498
499   /* Notify application of successful connection */
500   client->ops->connect(client, conn, TRUE);
501
502   silc_protocol_free(protocol);
503   if (ctx->auth_data)
504     silc_free(ctx->auth_data);
505   if (ctx->ske)
506     silc_ske_free(ctx->ske);
507   silc_free(ctx);
508   conn->sock->protocol = NULL;
509 }
510
511 /* Internal routine that sends packet or marks packet to be sent. This
512    is used directly only in special cases. Normal cases should use
513    silc_server_packet_send. Returns < 0 on error. */
514
515 static int silc_client_packet_send_real(SilcClient client,
516                                         SilcSocketConnection sock,
517                                         int force_send)
518 {
519   int ret;
520
521   /* Send the packet */
522   ret = silc_packet_send(sock, force_send);
523   if (ret != -2)
524     return ret;
525
526   /* Mark that there is some outgoing data available for this connection. 
527      This call sets the connection both for input and output (the input
528      is set always and this call keeps the input setting, actually). 
529      Actual data sending is performed by silc_client_packet_process. */
530   SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
531
532   /* Mark to socket that data is pending in outgoing buffer. This flag
533      is needed if new data is added to the buffer before the earlier
534      put data is sent to the network. */
535   SILC_SET_OUTBUF_PENDING(sock);
536
537   return 0;
538 }
539
540 /* Packet processing callback. This is used to send and receive packets
541    from network. This is generic task. */
542
543 SILC_TASK_CALLBACK(silc_client_packet_process)
544 {
545   SilcClient client = (SilcClient)context;
546   SilcSocketConnection sock = NULL;
547   SilcClientConnection conn;
548   int ret;
549
550   SILC_LOG_DEBUG(("Processing packet"));
551
552   SILC_CLIENT_GET_SOCK(client, fd, sock);
553   if (sock == NULL)
554     return;
555
556   conn = (SilcClientConnection)sock->user_data;
557
558   /* Packet sending */
559   if (type == SILC_TASK_WRITE) {
560     SILC_LOG_DEBUG(("Writing data to connection"));
561
562     if (sock->outbuf->data - sock->outbuf->head)
563       silc_buffer_push(sock->outbuf, 
564                        sock->outbuf->data - sock->outbuf->head);
565
566     ret = silc_client_packet_send_real(client, sock, TRUE);
567
568     /* If returned -2 could not write to connection now, will do
569        it later. */
570     if (ret == -2)
571       return;
572     
573     /* The packet has been sent and now it is time to set the connection
574        back to only for input. When there is again some outgoing data 
575        available for this connection it will be set for output as well. 
576        This call clears the output setting and sets it only for input. */
577     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
578     SILC_UNSET_OUTBUF_PENDING(sock);
579
580     silc_buffer_clear(sock->outbuf);
581     return;
582   }
583
584   /* Packet receiving */
585   if (type == SILC_TASK_READ) {
586     SILC_LOG_DEBUG(("Reading data from connection"));
587
588     /* Read data from network */
589     ret = silc_packet_receive(sock);
590     if (ret < 0)
591       return;
592     
593     /* EOF */
594     if (ret == 0) {
595       SILC_LOG_DEBUG(("Read EOF"));
596
597       /* If connection is disconnecting already we will finally
598          close the connection */
599       if (SILC_IS_DISCONNECTING(sock)) {
600         client->ops->disconnect(client, conn);
601         silc_client_close_connection(client, sock);
602         return;
603       }
604       
605       client->ops->say(client, conn, "Connection closed: premature EOF");
606       SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
607       client->ops->disconnect(client, conn);
608       silc_client_close_connection(client, sock);
609       return;
610     }
611
612     /* Process the packet. This will call the parser that will then
613        decrypt and parse the packet. */
614     silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
615                                 silc_client_packet_parse, client);
616   }
617 }
618
619 /* Parses whole packet, received earlier. */
620
621 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
622 {
623   SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
624   SilcClient client = (SilcClient)parse_ctx->context;
625   SilcPacketContext *packet = parse_ctx->packet;
626   SilcBuffer buffer = packet->buffer;
627   SilcSocketConnection sock = parse_ctx->sock;
628   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
629   int ret;
630
631   SILC_LOG_DEBUG(("Start"));
632
633   /* Decrypt the received packet */
634   ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet);
635   if (ret < 0)
636     goto out;
637
638   if (ret == 0) {
639     /* Parse the packet. Packet type is returned. */
640     ret = silc_packet_parse(packet);
641   } else {
642     /* Parse the packet header in special way as this is "special"
643        packet type. */
644     ret = silc_packet_parse_special(packet);
645   }
646
647   if (ret == SILC_PACKET_NONE)
648     goto out;
649
650   /* Parse the incoming packet type */
651   silc_client_packet_parse_type(client, sock, packet);
652
653  out:
654   silc_buffer_clear(sock->inbuf);
655   silc_packet_context_free(packet);
656   silc_free(parse_ctx);
657 }
658
659 /* Parser callback called by silc_packet_receive_process. Thie merely
660    registers timeout that will handle the actual parsing when appropriate. */
661
662 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
663 {
664   SilcClient client = (SilcClient)parser_context->context;
665
666   /* Parse the packet */
667   silc_task_register(client->timeout_queue, parser_context->sock->sock, 
668                      silc_client_packet_parse_real,
669                      (void *)parser_context, 0, 1, 
670                      SILC_TASK_TIMEOUT,
671                      SILC_TASK_PRI_NORMAL);
672 }
673   
674 /* Parses the packet type and calls what ever routines the packet type
675    requires. This is done for all incoming packets. */
676
677 void silc_client_packet_parse_type(SilcClient client, 
678                                    SilcSocketConnection sock,
679                                    SilcPacketContext *packet)
680 {
681   SilcBuffer buffer = packet->buffer;
682   SilcPacketType type = packet->type;
683
684   SILC_LOG_DEBUG(("Parsing packet type %d", type));
685
686   /* Parse the packet type */
687   switch(type) {
688   case SILC_PACKET_DISCONNECT:
689     silc_client_disconnected_by_server(client, sock, buffer);
690     break;
691   case SILC_PACKET_SUCCESS:
692     /*
693      * Success received for something. For now we can have only
694      * one protocol for connection executing at once hence this
695      * success message is for whatever protocol is executing currently.
696      */
697     if (sock->protocol) {
698       sock->protocol->execute(client->timeout_queue, 0,
699                               sock->protocol, sock->sock, 0, 0);
700     }
701     break;
702   case SILC_PACKET_FAILURE:
703     /*
704      * Failure received for some protocol. Set the protocol state to 
705      * error and call the protocol callback. This fill cause error on
706      * protocol and it will call the final callback.
707      */
708     if (sock->protocol) {
709       sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
710       sock->protocol->execute(client->timeout_queue, 0,
711                               sock->protocol, sock->sock, 0, 0);
712
713       /* XXX We have only two protocols currently thus we know what this
714          failure indication is. */
715       if (buffer->len >= 4) {
716         unsigned int failure;
717
718         SILC_GET32_MSB(failure, buffer->data);
719
720         /* Notify application */
721         client->ops->failure(client, sock->user_data, sock->protocol,
722                              (void *)failure);
723       }
724     }
725     break;
726   case SILC_PACKET_REJECT:
727     break;
728
729   case SILC_PACKET_NOTIFY:
730     /*
731      * Received notify message 
732      */
733     silc_client_notify_by_server(client, sock, packet);
734     break;
735
736   case SILC_PACKET_ERROR:
737     /*
738      * Received error message
739      */
740     silc_client_error_by_server(client, sock, buffer);
741     break;
742
743   case SILC_PACKET_CHANNEL_MESSAGE:
744     /*
745      * Received message to (from, actually) a channel
746      */
747     silc_client_channel_message(client, sock, packet);
748     break;
749   case SILC_PACKET_CHANNEL_KEY:
750     /*
751      * Received key for a channel. By receiving this key the client will be
752      * able to talk to the channel it has just joined. This can also be
753      * a new key for existing channel as keys expire peridiocally.
754      */
755     silc_client_receive_channel_key(client, sock, buffer);
756     break;
757
758   case SILC_PACKET_PRIVATE_MESSAGE:
759     /*
760      * Received private message
761      */
762     silc_client_private_message(client, sock, packet);
763     break;
764   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
765     /*
766      * Received private message key
767      */
768     break;
769
770   case SILC_PACKET_COMMAND_REPLY:
771     /*
772      * Recived reply for a command
773      */
774     silc_client_command_reply_process(client, sock, packet);
775     break;
776
777   case SILC_PACKET_KEY_EXCHANGE:
778     if (sock->protocol) {
779       SilcClientKEInternalContext *proto_ctx = 
780         (SilcClientKEInternalContext *)sock->protocol->context;
781
782       proto_ctx->packet = silc_packet_context_dup(packet);
783       proto_ctx->dest_id_type = packet->src_id_type;
784       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
785                                           packet->src_id_type);
786       if (!proto_ctx->dest_id)
787         break;
788
789       /* Let the protocol handle the packet */
790       sock->protocol->execute(client->timeout_queue, 0,
791                               sock->protocol, sock->sock, 0, 0);
792     } else {
793       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
794                       "protocol active, packet dropped."));
795
796       /* XXX Trigger KE protocol?? Rekey actually! */
797     }
798     break;
799
800   case SILC_PACKET_KEY_EXCHANGE_1:
801     if (sock->protocol) {
802
803     } else {
804       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
805                       "protocol active, packet dropped."));
806     }
807     break;
808   case SILC_PACKET_KEY_EXCHANGE_2:
809     if (sock->protocol) {
810       SilcClientKEInternalContext *proto_ctx = 
811         (SilcClientKEInternalContext *)sock->protocol->context;
812
813       if (proto_ctx->packet)
814         silc_packet_context_free(proto_ctx->packet);
815
816       proto_ctx->packet = silc_packet_context_dup(packet);
817       proto_ctx->dest_id_type = packet->src_id_type;
818       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
819                                           packet->src_id_type);
820       if (!proto_ctx->dest_id)
821         break;
822
823       /* Let the protocol handle the packet */
824       sock->protocol->execute(client->timeout_queue, 0,
825                               sock->protocol, sock->sock, 0, 0);
826     } else {
827       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
828                       "protocol active, packet dropped."));
829     }
830     break;
831
832   case SILC_PACKET_NEW_ID:
833     {
834       /*
835        * Received new ID from server. This packet is received at
836        * the connection to the server.  New ID is also received when 
837        * user changes nickname but in that case the new ID is received
838        * as command reply and not as this packet type.
839        */
840       SilcIDPayload idp;
841
842       idp = silc_id_payload_parse(buffer);
843       if (!idp)
844         break;
845       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
846         break;
847
848       silc_client_receive_new_id(client, sock, idp);
849       silc_id_payload_free(idp);
850       break;
851     }
852
853   default:
854     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
855     break;
856   }
857 }
858
859 /* Sends packet. This doesn't actually send the packet instead it assembles
860    it and marks it to be sent. However, if force_send is TRUE the packet
861    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
862    will be derived from sock argument. Otherwise the valid arguments sent
863    are used. */
864
865 void silc_client_packet_send(SilcClient client, 
866                              SilcSocketConnection sock,
867                              SilcPacketType type, 
868                              void *dst_id,
869                              SilcIdType dst_id_type,
870                              SilcCipher cipher,
871                              SilcHmac hmac,
872                              unsigned char *data, 
873                              unsigned int data_len, 
874                              int force_send)
875 {
876   SilcPacketContext packetdata;
877
878   SILC_LOG_DEBUG(("Sending packet, type %d", type));
879
880   /* Get data used in the packet sending, keys and stuff */
881   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
882     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
883       cipher = ((SilcClientConnection)sock->user_data)->send_key;
884
885     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
886       hmac = ((SilcClientConnection)sock->user_data)->hmac;
887
888     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
889       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
890       dst_id_type = SILC_ID_SERVER;
891     }
892   }
893
894   /* Set the packet context pointers */
895   packetdata.flags = 0;
896   packetdata.type = type;
897   if (((SilcClientConnection)sock->user_data)->local_id_data)
898     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
899   else 
900     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
901   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
902   packetdata.src_id_type = SILC_ID_CLIENT;
903   if (dst_id) {
904     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
905     packetdata.dst_id_len = silc_id_get_len(dst_id_type);
906     packetdata.dst_id_type = dst_id_type;
907   } else {
908     packetdata.dst_id = NULL;
909     packetdata.dst_id_len = 0;
910     packetdata.dst_id_type = SILC_ID_NONE;
911   }
912   packetdata.rng = client->rng;
913   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
914     packetdata.src_id_len + packetdata.dst_id_len;
915   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
916
917   /* Prepare outgoing data buffer for packet sending */
918   silc_packet_send_prepare(sock, 
919                            SILC_PACKET_HEADER_LEN +
920                            packetdata.src_id_len + 
921                            packetdata.dst_id_len,
922                            packetdata.padlen,
923                            data_len);
924
925   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
926
927   packetdata.buffer = sock->outbuf;
928
929   /* Put the data to the buffer */
930   if (data && data_len)
931     silc_buffer_put(sock->outbuf, data, data_len);
932
933   /* Create the outgoing packet */
934   silc_packet_assemble(&packetdata);
935
936   /* Encrypt the packet */
937   if (cipher)
938     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
939
940   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
941                    sock->outbuf->data, sock->outbuf->len);
942
943   /* Now actually send the packet */
944   silc_client_packet_send_real(client, sock, force_send);
945 }
946
947 /* Sends packet to a channel. Packet to channel is always encrypted
948    differently from "normal" packets. SILC header of the packet is 
949    encrypted with the next receiver's key and the rest of the packet is
950    encrypted with the channel specific key. Padding and HMAC is computed
951    with the next receiver's key. */
952
953 void silc_client_packet_send_to_channel(SilcClient client, 
954                                         SilcSocketConnection sock,
955                                         SilcChannelEntry channel,
956                                         unsigned char *data, 
957                                         unsigned int data_len, 
958                                         int force_send)
959 {
960   int i;
961   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
962   SilcBuffer payload;
963   SilcPacketContext packetdata;
964   SilcCipher cipher;
965   SilcHmac hmac;
966   unsigned char *id_string;
967
968   SILC_LOG_DEBUG(("Sending packet to channel"));
969
970   if (!channel || !channel->key) {
971     client->ops->say(client, conn, 
972                      "Cannot talk to channel: key does not exist");
973     return;
974   }
975
976   /* Generate IV */
977   if (!channel->iv)
978     for (i = 0; i < 16; i++) channel->iv[i] = silc_rng_get_byte(client->rng);
979   else
980     silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
981
982   /* Encode the channel payload */
983   payload = silc_channel_payload_encode(data_len, data, 16, channel->iv, 
984                                         client->rng);
985   if (!payload) {
986     client->ops->say(client, conn, 
987                      "Error: Could not create packet to be sent to channel");
988     return;
989   }
990
991   /* Get data used in packet header encryption, keys and stuff. Rest
992      of the packet (the payload) is, however, encrypted with the 
993      specified channel key. */
994   cipher = conn->send_key;
995   hmac = conn->hmac;
996   id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
997
998   /* Set the packet context pointers. The destination ID is always
999      the Channel ID of the channel. Server and router will handle the
1000      distribution of the packet. */
1001   packetdata.flags = 0;
1002   packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
1003   packetdata.src_id = conn->local_id_data;
1004   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1005   packetdata.src_id_type = SILC_ID_CLIENT;
1006   packetdata.dst_id = id_string;
1007   packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1008   packetdata.dst_id_type = SILC_ID_CHANNEL;
1009   packetdata.rng = client->rng;
1010   packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN + 
1011     packetdata.src_id_len + packetdata.dst_id_len;
1012   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1013                                           packetdata.src_id_len +
1014                                           packetdata.dst_id_len));
1015
1016   /* Prepare outgoing data buffer for packet sending */
1017   silc_packet_send_prepare(sock, 
1018                            SILC_PACKET_HEADER_LEN +
1019                            packetdata.src_id_len + 
1020                            packetdata.dst_id_len,
1021                            packetdata.padlen,
1022                            payload->len);
1023
1024   packetdata.buffer = sock->outbuf;
1025
1026   /* Encrypt payload of the packet. This is encrypted with the channel key. */
1027   channel->channel_key->cipher->encrypt(channel->channel_key->context,
1028                                         payload->data, payload->data,
1029                                         payload->len - 16, /* -IV_LEN */
1030                                         channel->iv);
1031
1032   /* Put the actual encrypted payload data into the buffer. */
1033   silc_buffer_put(sock->outbuf, payload->data, payload->len);
1034
1035   /* Create the outgoing packet */
1036   silc_packet_assemble(&packetdata);
1037
1038   /* Encrypt the header and padding of the packet. This is encrypted 
1039      with normal session key shared with our server. */
1040   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1041                       packetdata.src_id_len + packetdata.dst_id_len +
1042                       packetdata.padlen);
1043
1044   SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1045                    sock->outbuf->data, sock->outbuf->len);
1046
1047   /* Now actually send the packet */
1048   silc_client_packet_send_real(client, sock, force_send);
1049   silc_buffer_free(payload);
1050   silc_free(id_string);
1051 }
1052
1053 /* Sends private message to remote client. If private message key has
1054    not been set with this client then the message will be encrypted using
1055    normal session keys. Private messages are special packets in SILC
1056    network hence we need this own function for them. This is similiar
1057    to silc_client_packet_send_to_channel except that we send private
1058    message. */
1059
1060 void silc_client_packet_send_private_message(SilcClient client,
1061                                              SilcSocketConnection sock,
1062                                              SilcClientEntry client_entry,
1063                                              unsigned char *data, 
1064                                              unsigned int data_len, 
1065                                              int force_send)
1066 {
1067   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1068   SilcBuffer buffer;
1069   SilcPacketContext packetdata;
1070   unsigned int nick_len;
1071   SilcCipher cipher;
1072   SilcHmac hmac;
1073
1074   SILC_LOG_DEBUG(("Sending private message"));
1075
1076   /* Create private message payload */
1077   nick_len = strlen(conn->nickname);
1078   buffer = silc_buffer_alloc(2 + nick_len + data_len);
1079   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1080   silc_buffer_format(buffer,
1081                      SILC_STR_UI_SHORT(nick_len),
1082                      SILC_STR_UI_XNSTRING(conn->nickname,
1083                                           nick_len),
1084                      SILC_STR_UI_XNSTRING(data, data_len),
1085                      SILC_STR_END);
1086
1087   /* If we don't have private message specific key then private messages
1088      are just as any normal packet thus call normal packet sending.  If
1089      the key exist then the encryption process is a bit different and
1090      will be done in the rest of this function. */
1091   if (!client_entry->send_key) {
1092     silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1093                             client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1094                             buffer->data, buffer->len, force_send);
1095     goto out;
1096   }
1097
1098   /* We have private message specific key */
1099
1100   /* Get data used in the encryption */
1101   cipher = client_entry->send_key;
1102   hmac = conn->hmac;
1103
1104   /* Set the packet context pointers. */
1105   packetdata.flags = 0;
1106   packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1107   packetdata.src_id = conn->local_id_data;
1108   packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1109   packetdata.src_id_type = SILC_ID_CLIENT;
1110   if (client_entry)
1111     packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1112   else
1113     packetdata.dst_id = conn->local_id_data;
1114   packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1115   packetdata.dst_id_type = SILC_ID_CLIENT;
1116   packetdata.rng = client->rng;
1117   packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN + 
1118     packetdata.src_id_len + packetdata.dst_id_len;
1119   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1120                                           packetdata.src_id_len +
1121                                           packetdata.dst_id_len));
1122
1123   /* Prepare outgoing data buffer for packet sending */
1124   silc_packet_send_prepare(sock, 
1125                            SILC_PACKET_HEADER_LEN +
1126                            packetdata.src_id_len + 
1127                            packetdata.dst_id_len,
1128                            packetdata.padlen,
1129                            buffer->len);
1130   
1131   packetdata.buffer = sock->outbuf;
1132
1133   /* Encrypt payload of the packet. Encrypt with private message specific
1134      key if it exist, otherwise with session key. */
1135   cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1136                           buffer->len, cipher->iv);
1137       
1138   /* Put the actual encrypted payload data into the buffer. */
1139   silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1140
1141   /* Create the outgoing packet */
1142   silc_packet_assemble(&packetdata);
1143
1144   /* Encrypt the header and padding of the packet. */
1145   silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN + 
1146                       packetdata.src_id_len + packetdata.dst_id_len +
1147                       packetdata.padlen);
1148
1149   SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1150                    sock->outbuf->data, sock->outbuf->len);
1151
1152   /* Now actually send the packet */
1153   silc_client_packet_send_real(client, sock, force_send);
1154   silc_free(packetdata.dst_id);
1155
1156  out:
1157   silc_free(buffer);
1158 }     
1159
1160 /* Closes connection to remote end. Free's all allocated data except
1161    for some information such as nickname etc. that are valid at all time. */
1162
1163 void silc_client_close_connection(SilcClient client,
1164                                   SilcSocketConnection sock)
1165 {
1166   SilcClientConnection conn;
1167
1168   /* We won't listen for this connection anymore */
1169   silc_schedule_unset_listen_fd(sock->sock);
1170
1171   /* Unregister all tasks */
1172   silc_task_unregister_by_fd(client->io_queue, sock->sock);
1173   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1174
1175   /* Close the actual connection */
1176   silc_net_close_connection(sock->sock);
1177
1178   client->ops->say(client, sock->user_data,
1179                    "Closed connection to host %s", sock->hostname ?
1180                    sock->hostname : sock->ip);
1181
1182   /* Free everything */
1183   if (sock->user_data) {
1184     conn = (SilcClientConnection)sock->user_data;
1185
1186     /* XXX Free all client entries and channel entries. */
1187
1188     /* Clear ID caches */
1189     silc_idcache_del_all(conn->client_cache);
1190     silc_idcache_del_all(conn->channel_cache);
1191
1192     /* Free data */
1193     if (conn->remote_host)
1194       silc_free(conn->remote_host);
1195     if (conn->local_id)
1196       silc_free(conn->local_id);
1197     if (conn->local_id_data)
1198       silc_free(conn->local_id_data);
1199     if (conn->send_key)
1200       silc_cipher_free(conn->send_key);
1201     if (conn->receive_key)
1202       silc_cipher_free(conn->receive_key);
1203     if (conn->hmac)
1204       silc_hmac_free(conn->hmac);
1205     if (conn->hmac_key) {
1206       memset(conn->hmac_key, 0, conn->hmac_key_len);
1207       silc_free(conn->hmac_key);
1208     }
1209     if (conn->pending_commands)
1210       silc_dlist_uninit(conn->pending_commands);
1211
1212     conn->sock = NULL;
1213     conn->remote_port = 0;
1214     conn->remote_type = 0;
1215     conn->send_key = NULL;
1216     conn->receive_key = NULL;
1217     conn->hmac = NULL;
1218     conn->hmac_key = NULL;
1219     conn->hmac_key_len = 0;
1220     conn->local_id = NULL;
1221     conn->local_id_data = NULL;
1222     conn->remote_host = NULL;
1223     conn->current_channel = NULL;
1224     conn->pending_commands = NULL;
1225
1226     silc_client_del_connection(client, conn);
1227   }
1228
1229   if (sock->protocol) {
1230     silc_protocol_free(sock->protocol);
1231     sock->protocol = NULL;
1232   }
1233   silc_socket_free(sock);
1234 }
1235
1236 /* Called when we receive disconnection packet from server. This 
1237    closes our end properly and displays the reason of the disconnection
1238    on the screen. */
1239
1240 void silc_client_disconnected_by_server(SilcClient client,
1241                                         SilcSocketConnection sock,
1242                                         SilcBuffer message)
1243 {
1244   char *msg;
1245
1246   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1247
1248   msg = silc_calloc(message->len + 1, sizeof(char));
1249   memcpy(msg, message->data, message->len);
1250   client->ops->say(client, sock->user_data, msg);
1251   silc_free(msg);
1252
1253   SILC_SET_DISCONNECTED(sock);
1254   silc_client_close_connection(client, sock);
1255 }
1256
1257 /* Received error message from server. Display it on the screen. 
1258    We don't take any action what so ever of the error message. */
1259
1260 void silc_client_error_by_server(SilcClient client,
1261                                  SilcSocketConnection sock,
1262                                  SilcBuffer message)
1263 {
1264   char *msg;
1265
1266   msg = silc_calloc(message->len + 1, sizeof(char));
1267   memcpy(msg, message->data, message->len);
1268   client->ops->say(client, sock->user_data, msg);
1269   silc_free(msg);
1270 }
1271
1272 /* Called when notify is received and some async operation (such as command)
1273    is required before processing the notify message. This calls again the
1274    silc_client_notify_by_server and reprocesses the original notify packet. */
1275
1276 static void silc_client_notify_by_server_pending(void *context)
1277 {
1278   SilcPacketContext *p = (SilcPacketContext *)context;
1279   silc_client_notify_by_server(p->context, p->sock, p);
1280   silc_packet_context_free(p);
1281 }
1282
1283 /* Received notify message from server */
1284
1285 void silc_client_notify_by_server(SilcClient client,
1286                                   SilcSocketConnection sock,
1287                                   SilcPacketContext *packet)
1288 {
1289   SilcBuffer buffer = packet->buffer;
1290   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1291   SilcNotifyPayload payload;
1292   SilcNotifyType type;
1293   SilcArgumentPayload args;
1294
1295   SilcClientID *client_id = NULL;
1296   SilcChannelID *channel_id = NULL;
1297   SilcClientEntry client_entry;
1298   SilcClientEntry client_entry2;
1299   SilcChannelEntry channel;
1300   SilcChannelUser chu;
1301   SilcIDCacheEntry id_cache = NULL;
1302   unsigned char *tmp;
1303   unsigned int tmp_len, mode;
1304
1305   payload = silc_notify_payload_parse(buffer);
1306   if (!payload)
1307     goto out;
1308
1309   type = silc_notify_get_type(payload);
1310   args = silc_notify_get_args(payload);
1311   if (!args)
1312     goto out;
1313
1314   switch(type) {
1315   case SILC_NOTIFY_TYPE_NONE:
1316     /* Notify application */
1317     client->ops->notify(client, conn, type, 
1318                         silc_argument_get_arg_type(args, 1, NULL));
1319     break;
1320
1321   case SILC_NOTIFY_TYPE_INVITE:
1322     /* 
1323      * Someone invited me to a channel. Find Client and Channel entries
1324      * for the application.
1325      */
1326     
1327     /* Get Client ID */
1328     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1329     if (!tmp)
1330       goto out;
1331
1332     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1333     if (!client_id)
1334       goto out;
1335
1336     /* Find Client entry and if not found query it */
1337     client_entry = silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
1338     if (!client_entry) {
1339       SilcPacketContext *p = silc_packet_context_dup(packet);
1340       p->context = (void *)client;
1341       p->sock = sock;
1342       silc_client_command_pending(conn, SILC_COMMAND_WHOIS, SILC_IDLIST_IDENT,
1343                                   silc_client_notify_by_server_pending, p);
1344       goto out;
1345     }
1346
1347     /* Get Channel ID */
1348     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1349     if (!tmp)
1350       goto out;
1351
1352     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1353     if (!channel_id)
1354       goto out;
1355
1356     /* XXX Will ALWAYS fail because currently we don't have way to resolve
1357        channel information for channel that we're not joined to. */
1358     /* XXX ways to fix: use (extended) LIST command, or define the channel
1359        name to the notfy type when name resolving is not mandatory. */
1360     /* Find channel entry */
1361     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1362                                      SILC_ID_CHANNEL, &id_cache))
1363       goto out;
1364
1365     channel = (SilcChannelEntry)id_cache->context;
1366
1367     /* Notify application */
1368     client->ops->notify(client, conn, type, client_entry, channel);
1369     break;
1370
1371   case SILC_NOTIFY_TYPE_JOIN:
1372     /*
1373      * Someone has joined to a channel. Get their ID and nickname and
1374      * cache them for later use.
1375      */
1376
1377     /* Get Client ID */
1378     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1379     if (!tmp)
1380       goto out;
1381
1382     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1383     if (!client_id)
1384       goto out;
1385
1386     /* Find Client entry and if not found query it */
1387     client_entry = silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
1388     if (!client_entry) {
1389       SilcPacketContext *p = silc_packet_context_dup(packet);
1390       p->context = (void *)client;
1391       p->sock = sock;
1392       silc_client_command_pending(conn, SILC_COMMAND_WHOIS, SILC_IDLIST_IDENT, 
1393                                   silc_client_notify_by_server_pending, p);
1394       goto out;
1395     }
1396
1397     /* Get channel entry */
1398     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1399                                 SILC_ID_CHANNEL);
1400     if (!channel_id)
1401       goto out;
1402     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1403                                      SILC_ID_CHANNEL, &id_cache))
1404       break;
1405
1406     channel = (SilcChannelEntry)id_cache->context;
1407
1408     /* Add client to channel */
1409     chu = silc_calloc(1, sizeof(*chu));
1410     chu->client = client_entry;
1411     silc_list_add(channel->clients, chu);
1412
1413     /* XXX add support for multiple same nicks on same channel. Check
1414        for them here */
1415
1416     /* Notify application. The channel entry is sent last as this notify
1417        is for channel but application don't know it from the arguments
1418        sent by server. */
1419     client->ops->notify(client, conn, type, client_entry, channel);
1420     break;
1421
1422   case SILC_NOTIFY_TYPE_LEAVE:
1423     /*
1424      * Someone has left a channel. We will remove it from the channel but
1425      * we'll keep it in the cache in case we'll need it later.
1426      */
1427     
1428     /* Get Client ID */
1429     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1430     if (!tmp)
1431       goto out;
1432
1433     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1434     if (!client_id)
1435       goto out;
1436
1437     /* Find Client entry */
1438     client_entry = 
1439       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1440     if (!client_entry)
1441       goto out;
1442
1443     /* Get channel entry */
1444     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1445                                 SILC_ID_CHANNEL);
1446     if (!channel_id)
1447       goto out;
1448     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1449                                      SILC_ID_CHANNEL, &id_cache))
1450       break;
1451
1452     channel = (SilcChannelEntry)id_cache->context;
1453
1454     /* Remove client from channel */
1455     silc_list_start(channel->clients);
1456     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1457       if (chu->client == client_entry) {
1458         silc_list_del(channel->clients, chu);
1459         silc_free(chu);
1460         break;
1461       }
1462     }
1463
1464     /* Notify application. The channel entry is sent last as this notify
1465        is for channel but application don't know it from the arguments
1466        sent by server. */
1467     client->ops->notify(client, conn, type, client_entry, channel);
1468     break;
1469
1470   case SILC_NOTIFY_TYPE_SIGNOFF:
1471     /*
1472      * Someone left SILC. We'll remove it from all channels and from cache.
1473      */
1474
1475     /* Get Client ID */
1476     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1477     if (!tmp)
1478       goto out;
1479
1480     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1481     if (!client_id)
1482       goto out;
1483
1484     /* Find Client entry */
1485     client_entry = 
1486       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1487     if (!client_entry)
1488       goto out;
1489
1490     /* Remove from all channels */
1491     silc_client_remove_from_channels(client, conn, client_entry);
1492
1493     /* Remove from cache */
1494     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1495                            client_entry->id);
1496
1497     /* Notify application */
1498     client->ops->notify(client, conn, type, client_entry);
1499
1500     /* Free data */
1501     if (client_entry->nickname)
1502       silc_free(client_entry->nickname);
1503     if (client_entry->server)
1504       silc_free(client_entry->server);
1505     if (client_entry->id)
1506       silc_free(client_entry->id);
1507     if (client_entry->send_key)
1508       silc_cipher_free(client_entry->send_key);
1509     if (client_entry->receive_key)
1510       silc_cipher_free(client_entry->receive_key);
1511     break;
1512
1513   case SILC_NOTIFY_TYPE_TOPIC_SET:
1514     /*
1515      * Someone set the topic on a channel.
1516      */
1517
1518     /* Get Client ID */
1519     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1520     if (!tmp)
1521       goto out;
1522
1523     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1524     if (!client_id)
1525       goto out;
1526
1527     /* Find Client entry */
1528     client_entry = 
1529       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1530     if (!client_entry)
1531       goto out;
1532
1533     /* Get topic */
1534     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1535     if (!tmp)
1536       goto out;
1537
1538     /* Get channel entry */
1539     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1540                                 SILC_ID_CHANNEL);
1541     if (!channel_id)
1542       goto out;
1543     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1544                                      SILC_ID_CHANNEL, &id_cache))
1545       break;
1546
1547     channel = (SilcChannelEntry)id_cache->context;
1548
1549     /* Notify application. The channel entry is sent last as this notify
1550        is for channel but application don't know it from the arguments
1551        sent by server. */
1552     client->ops->notify(client, conn, type, client_entry, tmp, channel);
1553     break;
1554
1555   case SILC_NOTIFY_TYPE_NICK_CHANGE:
1556     /*
1557      * Someone changed their nickname. If we don't have entry for the new
1558      * ID we will query it and return here after it's done. After we've
1559      * returned we fetch the old entry and free it and notify the 
1560      * application.
1561      */
1562
1563     /* Get new Client ID */
1564     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1565     if (!tmp)
1566       goto out;
1567
1568     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1569     if (!client_id)
1570       goto out;
1571
1572     /* Ignore my ID */
1573     if (!SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
1574       break;
1575
1576     /* Find Client entry and if not found query it */
1577     client_entry2 = 
1578       silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
1579     if (!client_entry2) {
1580       SilcPacketContext *p = silc_packet_context_dup(packet);
1581       p->context = (void *)client;
1582       p->sock = sock;
1583       silc_client_command_pending(conn, SILC_COMMAND_WHOIS, SILC_IDLIST_IDENT,
1584                                   silc_client_notify_by_server_pending, p);
1585       goto out;
1586     }
1587
1588     /* Get old Client ID */
1589     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1590     if (!tmp)
1591       goto out;
1592
1593     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1594     if (!client_id)
1595       goto out;
1596
1597     /* Find old Client entry */
1598     client_entry = 
1599       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1600     if (!client_entry)
1601       goto out;
1602
1603     /* Remove the old from cache */
1604     silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
1605                            client_entry->id);
1606
1607     /* Replace old ID entry with new one on all channels. */
1608     silc_client_replace_from_channels(client, conn, client_entry,
1609                                       client_entry2);
1610
1611     /* Notify application */
1612     client->ops->notify(client, conn, type, client_entry, client_entry2);
1613
1614     /* Free data */
1615     if (client_entry->nickname)
1616       silc_free(client_entry->nickname);
1617     if (client_entry->server)
1618       silc_free(client_entry->server);
1619     if (client_entry->id)
1620       silc_free(client_entry->id);
1621     if (client_entry->send_key)
1622       silc_cipher_free(client_entry->send_key);
1623     if (client_entry->receive_key)
1624       silc_cipher_free(client_entry->receive_key);
1625     break;
1626
1627   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
1628     /*
1629      * Someone changed a channel mode
1630      */
1631
1632     /* Get Client ID */
1633     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1634     if (!tmp)
1635       goto out;
1636
1637     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1638     if (!client_id)
1639       goto out;
1640
1641     /* Find Client entry */
1642     client_entry = 
1643       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1644     if (!client_entry)
1645       goto out;
1646
1647     /* Get the mode */
1648     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1649     if (!tmp)
1650       goto out;
1651
1652     SILC_GET32_MSB(mode, tmp);
1653
1654     /* Get channel entry */
1655     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1656                                 SILC_ID_CHANNEL);
1657     if (!channel_id)
1658       goto out;
1659     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1660                                      SILC_ID_CHANNEL, &id_cache))
1661       break;
1662
1663     channel = (SilcChannelEntry)id_cache->context;
1664
1665     /* Save the new mode */
1666     channel->mode = mode;
1667
1668     /* Notify application. The channel entry is sent last as this notify
1669        is for channel but application don't know it from the arguments
1670        sent by server. */
1671     client->ops->notify(client, conn, type, client_entry, mode, channel);
1672     break;
1673
1674   case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1675     /*
1676      * Someone changed user's mode on a channel
1677      */
1678
1679     /* Get Client ID */
1680     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1681     if (!tmp)
1682       goto out;
1683
1684     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1685     if (!client_id)
1686       goto out;
1687
1688     /* Find Client entry */
1689     client_entry = 
1690       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1691     if (!client_entry)
1692       goto out;
1693
1694     /* Get the mode */
1695     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1696     if (!tmp)
1697       goto out;
1698
1699     SILC_GET32_MSB(mode, tmp);
1700
1701     /* Get target Client ID */
1702     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1703     if (!tmp)
1704       goto out;
1705
1706     silc_free(client_id);
1707     client_id = silc_id_payload_parse_id(tmp, tmp_len);
1708     if (!client_id)
1709       goto out;
1710
1711     /* Find target Client entry */
1712     client_entry2 = 
1713       silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1714     if (!client_entry2)
1715       goto out;
1716
1717     /* Get channel entry */
1718     channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1719                                 SILC_ID_CHANNEL);
1720     if (!channel_id)
1721       goto out;
1722     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1723                                      SILC_ID_CHANNEL, &id_cache))
1724       break;
1725
1726     channel = (SilcChannelEntry)id_cache->context;
1727
1728     /* Save the mode */
1729     silc_list_start(channel->clients);
1730     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1731       if (chu->client == client_entry) {
1732         chu->mode = mode;
1733         break;
1734       }
1735     }
1736
1737     /* Notify application. The channel entry is sent last as this notify
1738        is for channel but application don't know it from the arguments
1739        sent by server. */
1740     client->ops->notify(client, conn, type, client_entry, mode, 
1741                         client_entry2, channel);
1742     break;
1743
1744   case SILC_NOTIFY_TYPE_MOTD:
1745     /*
1746      * Received Message of the day
1747      */
1748
1749     /* Get motd */
1750     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1751     if (!tmp)
1752       goto out;
1753     
1754     /* Notify application */
1755     client->ops->notify(client, conn, type, tmp);
1756     break;
1757     
1758   default:
1759     break;
1760   }
1761
1762  out:
1763   silc_notify_payload_free(payload);
1764   if (client_id)
1765     silc_free(client_id);
1766   if (channel_id)
1767     silc_free(channel_id);
1768 }
1769
1770 /* Processes the received new Client ID from server. Old Client ID is
1771    deleted from cache and new one is added. */
1772
1773 void silc_client_receive_new_id(SilcClient client,
1774                                 SilcSocketConnection sock,
1775                                 SilcIDPayload idp)
1776 {
1777   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1778
1779   /* Delete old ID from ID cache */
1780   silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1781   
1782   /* Save the new ID */
1783   if (conn->local_id)
1784     silc_free(conn->local_id);
1785   if (conn->local_id_data)
1786     silc_free(conn->local_id_data);
1787
1788   conn->local_id = silc_id_payload_get_id(idp);
1789   conn->local_id_data = silc_id_payload_get_data(idp);
1790   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1791
1792   if (!conn->local_entry)
1793     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1794
1795   conn->local_entry->nickname = conn->nickname;
1796   if (!conn->local_entry->username) {
1797     conn->local_entry->username = 
1798       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1799                   sizeof(conn->local_entry->username));
1800     sprintf(conn->local_entry->username, "%s@%s", client->username,
1801             client->hostname);
1802   }
1803   conn->local_entry->server = strdup(conn->remote_host);
1804   conn->local_entry->id = conn->local_id;
1805   
1806   /* Put it to the ID cache */
1807   silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1808                    conn->local_id, (void *)conn->local_entry, TRUE);
1809 }
1810
1811 /* Processed received Channel ID for a channel. This is called when client
1812    joins to channel and server replies with channel ID. The ID is cached. */
1813
1814 void silc_client_new_channel_id(SilcClient client,
1815                                 SilcSocketConnection sock,
1816                                 char *channel_name,
1817                                 unsigned int mode, SilcIDPayload idp)
1818 {
1819   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1820   SilcChannelEntry channel;
1821
1822   SILC_LOG_DEBUG(("New channel ID"));
1823
1824   channel = silc_calloc(1, sizeof(*channel));
1825   channel->channel_name = channel_name;
1826   channel->id = silc_id_payload_get_id(idp);
1827   channel->mode = mode;
1828   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1829
1830   conn->current_channel = channel;
1831
1832   /* Put it to the ID cache */
1833   silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1834                    (void *)channel->id, (void *)channel, TRUE);
1835 }
1836
1837 /* Saves channel key from encoded `key_payload'. This is used when we
1838    receive Channel Key Payload and when we are processing JOIN command 
1839    reply. */
1840
1841 void silc_client_save_channel_key(SilcClientConnection conn,
1842                                   SilcBuffer key_payload, 
1843                                   SilcChannelEntry channel)
1844 {
1845   unsigned char *id_string, *key, *cipher;
1846   unsigned int tmp_len;
1847   SilcChannelID *id;
1848   SilcIDCacheEntry id_cache = NULL;
1849   SilcChannelKeyPayload payload;
1850
1851   payload = silc_channel_key_payload_parse(key_payload);
1852   if (!payload)
1853     return;
1854
1855   id_string = silc_channel_key_get_id(payload, &tmp_len);
1856   if (!id_string) {
1857     silc_channel_key_payload_free(payload);
1858     return;
1859   }
1860
1861   id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
1862   if (!id) {
1863     silc_channel_key_payload_free(payload);
1864     return;
1865   }
1866
1867   /* Find channel. */
1868   if (!channel) {
1869     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1870                                      SILC_ID_CHANNEL, &id_cache))
1871       goto out;
1872     
1873     /* Get channel entry */
1874     channel = (SilcChannelEntry)id_cache->context;
1875   }
1876
1877   /* Save the key */
1878   key = silc_channel_key_get_key(payload, &tmp_len);
1879   cipher = silc_channel_key_get_cipher(payload, NULL);
1880   channel->key_len = tmp_len;
1881   channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
1882   memcpy(channel->key, key, tmp_len);
1883
1884   if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
1885     conn->client->ops->say(conn->client, conn,
1886                      "Cannot talk to channel: unsupported cipher %s", cipher);
1887     goto out;
1888   }
1889   channel->channel_key->cipher->set_key(channel->channel_key->context, 
1890                                         key, tmp_len);
1891
1892   /* Client is now joined to the channel */
1893   channel->on_channel = TRUE;
1894
1895  out:
1896   silc_free(id);
1897   silc_channel_key_payload_free(payload);
1898 }
1899
1900 /* Processes received key for channel. The received key will be used
1901    to protect the traffic on the channel for now on. Client must receive
1902    the key to the channel before talking on the channel is possible. 
1903    This is the key that server has generated, this is not the channel
1904    private key, it is entirely local setting. */
1905
1906 void silc_client_receive_channel_key(SilcClient client,
1907                                      SilcSocketConnection sock,
1908                                      SilcBuffer packet)
1909 {
1910   SILC_LOG_DEBUG(("Received key for channel"));
1911
1912   /* Save the key */
1913   silc_client_save_channel_key(sock->user_data, packet, NULL);
1914 }
1915
1916 /* Process received message to a channel (or from a channel, really). This
1917    decrypts the channel message with channel specific key and parses the
1918    channel payload. Finally it displays the message on the screen. */
1919
1920 void silc_client_channel_message(SilcClient client, 
1921                                  SilcSocketConnection sock, 
1922                                  SilcPacketContext *packet)
1923 {
1924   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1925   SilcBuffer buffer = packet->buffer;
1926   SilcChannelPayload payload = NULL;
1927   SilcChannelID *id = NULL;
1928   SilcChannelEntry channel;
1929   SilcChannelUser chu;
1930   SilcIDCacheEntry id_cache = NULL;
1931   SilcClientID *client_id = NULL;
1932   char *nickname;
1933
1934   /* Sanity checks */
1935   if (packet->dst_id_type != SILC_ID_CHANNEL)
1936     goto out;
1937
1938   client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1939                              SILC_ID_CLIENT);
1940   if (!client_id)
1941     goto out;
1942   id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
1943   if (!id)
1944     goto out;
1945
1946   /* Find the channel entry from channels on this connection */
1947   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1948                                    SILC_ID_CHANNEL, &id_cache))
1949     goto out;
1950
1951   channel = (SilcChannelEntry)id_cache->context;
1952
1953   /* Decrypt the channel message payload. Push the IV out of the way,
1954      since it is not encrypted (after pushing buffer->tail has the IV). */
1955   silc_buffer_push_tail(buffer, 16);
1956   channel->channel_key->cipher->decrypt(channel->channel_key->context,
1957                                         buffer->data, buffer->data,
1958                                         buffer->len, buffer->tail);
1959   silc_buffer_pull_tail(buffer, 16);
1960
1961   /* Parse the channel message payload */
1962   payload = silc_channel_payload_parse(buffer);
1963   if (!payload)
1964     goto out;
1965
1966   /* Find nickname */
1967   nickname = "[unknown]";
1968   silc_list_start(channel->clients);
1969   while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1970     if (!SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
1971       nickname = chu->client->nickname;
1972       break;
1973     }
1974   }
1975
1976   /* Pass the message to application */
1977   client->ops->channel_message(client, conn, nickname,
1978                                channel->channel_name,
1979                                silc_channel_get_data(payload, NULL));
1980
1981  out:
1982   if (id)
1983     silc_free(id);
1984   if (client_id)
1985     silc_free(client_id);
1986   if (payload)
1987     silc_channel_payload_free(payload);
1988 }
1989
1990 /* Private message received. This processes the private message and
1991    finally displays it on the screen. */
1992
1993 void silc_client_private_message(SilcClient client, 
1994                                  SilcSocketConnection sock, 
1995                                  SilcPacketContext *packet)
1996 {
1997   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1998   SilcBuffer buffer = packet->buffer;
1999   unsigned short nick_len;
2000   unsigned char *nickname, *message;
2001   int ret;
2002
2003   /* Get nickname */
2004   ret = silc_buffer_unformat(buffer, 
2005                              SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
2006                              SILC_STR_END);
2007   if (ret == -1)
2008     return;
2009
2010   silc_buffer_pull(buffer, 2 + nick_len);
2011
2012   message = silc_calloc(buffer->len + 1, sizeof(char));
2013   memcpy(message, buffer->data, buffer->len);
2014
2015   /* Pass the private message to application */
2016   client->ops->private_message(client, conn, nickname, message);
2017
2018   /* See if we are away (gone). If we are away we will reply to the
2019      sender with the set away message. */
2020   if (conn->away && conn->away->away) {
2021     SilcClientID *remote_id;
2022     SilcClientEntry remote_client;
2023     SilcIDCacheEntry id_cache;
2024
2025     if (packet->src_id_type != SILC_ID_CLIENT)
2026       goto out;
2027
2028     remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
2029                                SILC_ID_CLIENT);
2030     if (!remote_id)
2031       goto out;
2032
2033     /* If it's me, ignore */
2034     if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
2035       goto out;
2036
2037     /* Check whether we know this client already */
2038     if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
2039                                      SILC_ID_CLIENT, &id_cache))
2040       {
2041         /* Allocate client entry */
2042         remote_client = silc_calloc(1, sizeof(*remote_client));
2043         remote_client->id = remote_id;
2044         silc_parse_nickname(nickname, &remote_client->nickname, 
2045                             &remote_client->server, &remote_client->num);
2046
2047         /* Save the client to cache */
2048         silc_idcache_add(conn->client_cache, remote_client->nickname,
2049                          SILC_ID_CLIENT, remote_client->id, remote_client, 
2050                          TRUE);
2051       } else {
2052         silc_free(remote_id);
2053         remote_client = (SilcClientEntry)id_cache->context;
2054       }
2055
2056     /* Send the away message */
2057     silc_client_packet_send_private_message(client, sock, remote_client,
2058                                             conn->away->away,
2059                                             strlen(conn->away->away), TRUE);
2060   }
2061
2062  out:
2063   memset(message, 0, buffer->len);
2064   silc_free(message);
2065   silc_free(nickname);
2066 }
2067
2068 /* Removes a client entry from all channel it has joined. This really is
2069    a performance killer (client_entry should have pointers to channel 
2070    entry list). */
2071
2072 void silc_client_remove_from_channels(SilcClient client,
2073                                       SilcClientConnection conn,
2074                                       SilcClientEntry client_entry)
2075 {
2076   SilcIDCacheEntry id_cache;
2077   SilcIDCacheList list;
2078   SilcChannelEntry channel;
2079   SilcChannelUser chu;
2080
2081   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2082                                SILC_ID_CHANNEL, &list))
2083     return;
2084
2085   silc_idcache_list_first(list, &id_cache);
2086   channel = (SilcChannelEntry)id_cache->context;
2087   
2088   while (channel) {
2089     
2090     /* Remove client from channel */
2091     silc_list_start(channel->clients);
2092     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2093       if (chu->client == client_entry) {
2094         silc_list_del(channel->clients, chu);
2095         silc_free(chu);
2096         break;
2097       }
2098     }
2099
2100     if (!silc_idcache_list_next(list, &id_cache))
2101       break;
2102     
2103     channel = (SilcChannelEntry)id_cache->context;
2104   }
2105
2106   silc_idcache_list_free(list);
2107 }
2108
2109 /* Replaces `old' client entries from all channels to `new' client entry.
2110    This can be called for example when nickname changes and old ID entry
2111    is replaced from ID cache with the new one. If the old ID entry is only
2112    updated, then this fucntion needs not to be called. */
2113
2114 void silc_client_replace_from_channels(SilcClient client, 
2115                                        SilcClientConnection conn,
2116                                        SilcClientEntry old,
2117                                        SilcClientEntry new)
2118 {
2119   SilcIDCacheEntry id_cache;
2120   SilcIDCacheList list;
2121   SilcChannelEntry channel;
2122   SilcChannelUser chu;
2123
2124   if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2125                                SILC_ID_CHANNEL, &list))
2126     return;
2127
2128   silc_idcache_list_first(list, &id_cache);
2129   channel = (SilcChannelEntry)id_cache->context;
2130   
2131   while (channel) {
2132     
2133     /* Replace client entry */
2134     silc_list_start(channel->clients);
2135     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2136       if (chu->client == old) {
2137         chu->client = new;
2138         break;
2139       }
2140     }
2141
2142     if (!silc_idcache_list_next(list, &id_cache))
2143       break;
2144     
2145     channel = (SilcChannelEntry)id_cache->context;
2146   }
2147
2148   silc_idcache_list_free(list);
2149 }
2150
2151 /* Parses mode mask and returns the mode as string. */
2152
2153 char *silc_client_chmode(unsigned int mode)
2154 {
2155   char string[20];
2156
2157   if (!mode)
2158     return NULL;
2159
2160   memset(string, 0, sizeof(string));
2161
2162   if (mode & SILC_CHANNEL_MODE_PRIVATE)
2163     strncat(string, "p", 1);
2164
2165   if (mode & SILC_CHANNEL_MODE_SECRET)
2166     strncat(string, "s", 1);
2167
2168   if (mode & SILC_CHANNEL_MODE_PRIVKEY)
2169     strncat(string, "k", 1);
2170
2171   if (mode & SILC_CHANNEL_MODE_INVITE)
2172     strncat(string, "i", 1);
2173
2174   if (mode & SILC_CHANNEL_MODE_TOPIC)
2175     strncat(string, "t", 1);
2176
2177   if (mode & SILC_CHANNEL_MODE_ULIMIT)
2178     strncat(string, "l", 1);
2179
2180   if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
2181     strncat(string, "a", 1);
2182
2183   /* Rest of mode is ignored */
2184
2185   return strdup(string);
2186 }
2187
2188 /* Parses channel user mode mask and returns te mode as string */
2189
2190 char *silc_client_chumode(unsigned int mode)
2191 {
2192   char string[4];
2193
2194   if (!mode)
2195     return NULL;
2196
2197   memset(string, 0, sizeof(string));
2198
2199   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2200     strncat(string, "f", 1);
2201
2202   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2203     strncat(string, "o", 1);
2204
2205   return strdup(string);
2206 }
2207
2208 /* Parses channel user mode and returns it as special mode character. */
2209
2210 char *silc_client_chumode_char(unsigned int mode)
2211 {
2212   char string[4];
2213
2214   if (!mode)
2215     return NULL;
2216
2217   memset(string, 0, sizeof(string));
2218
2219   if (mode & SILC_CHANNEL_UMODE_CHANFO)
2220     strncat(string, "*", 1);
2221
2222   if (mode & SILC_CHANNEL_UMODE_CHANOP)
2223     strncat(string, "@", 1);
2224
2225   return strdup(string);
2226 }