updates.
[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 - 2001 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 #include "client_internal.h"
24
25 /* Static task callback prototypes */
26 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
27 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
28 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
29 SILC_TASK_CALLBACK(silc_client_packet_parse_real);
30 SILC_TASK_CALLBACK(silc_client_rekey_callback);
31 SILC_TASK_CALLBACK(silc_client_rekey_final);
32
33 static void silc_client_packet_parse(SilcPacketParserContext *parser_context);
34 static void silc_client_packet_parse_type(SilcClient client, 
35                                           SilcSocketConnection sock,
36                                           SilcPacketContext *packet);
37
38 /* Allocates new client object. This has to be done before client may
39    work. After calling this one must call silc_client_init to initialize
40    the client. The `application' is application specific user data pointer
41    and caller must free it. */
42
43 SilcClient silc_client_alloc(SilcClientOperations *ops, void *application)
44 {
45   SilcClient new_client;
46
47   new_client = silc_calloc(1, sizeof(*new_client));
48   new_client->application = application;
49   new_client->ops = ops;
50
51   return new_client;
52 }
53
54 /* Frees client object and its internals. */
55
56 void silc_client_free(SilcClient client)
57 {
58   if (client) {
59     if (client->rng)
60       silc_rng_free(client->rng);
61
62     silc_free(client);
63   }
64 }
65
66 /* Initializes the client. This makes all the necessary steps to make
67    the client ready to be run. One must call silc_client_run to run the
68    client. Returns FALSE if error occured, TRUE otherwise. */
69
70 int silc_client_init(SilcClient client)
71 {
72   SILC_LOG_DEBUG(("Initializing client"));
73
74   /* Initialize hash functions for client to use */
75   silc_hash_alloc("md5", &client->md5hash);
76   silc_hash_alloc("sha1", &client->sha1hash);
77
78   /* Initialize none cipher */
79   silc_cipher_alloc("none", &client->none_cipher);
80
81   /* Initialize random number generator */
82   client->rng = silc_rng_alloc();
83   silc_rng_init(client->rng);
84   silc_rng_global_init(client->rng);
85
86   /* Register protocols */
87   silc_client_protocols_register();
88
89   /* Initialize the scheduler */
90   silc_schedule_init(&client->io_queue, &client->timeout_queue, 
91                      &client->generic_queue, 5000);
92
93   return TRUE;
94 }
95
96 /* Stops the client. This is called to stop the client and thus to stop
97    the program. */
98
99 void silc_client_stop(SilcClient client)
100 {
101   SILC_LOG_DEBUG(("Stopping client"));
102
103   /* Stop the scheduler, although it might be already stopped. This
104      doesn't hurt anyone. This removes all the tasks and task queues,
105      as well. */
106   silc_schedule_stop();
107   silc_schedule_uninit();
108
109   silc_client_protocols_unregister();
110
111   SILC_LOG_DEBUG(("Client stopped"));
112 }
113
114 /* Runs the client. This starts the scheduler from the utility library.
115    When this functions returns the execution of the appliation is over. */
116
117 void silc_client_run(SilcClient client)
118 {
119   SILC_LOG_DEBUG(("Running client"));
120
121   /* Start the scheduler, the heart of the SILC client. When this returns
122      the program will be terminated. */
123   silc_schedule();
124 }
125
126 /* Allocates and adds new connection to the client. This adds the allocated
127    connection to the connection table and returns a pointer to it. A client
128    can have multiple connections to multiple servers. Every connection must
129    be added to the client using this function. User data `context' may
130    be sent as argument. This function is normally used only if the 
131    application performed the connecting outside the library. The library
132    however may use this internally. */
133
134 SilcClientConnection silc_client_add_connection(SilcClient client,
135                                                 char *hostname,
136                                                 int port,
137                                                 void *context)
138 {
139   SilcClientConnection conn;
140   int i;
141
142   conn = silc_calloc(1, sizeof(*conn));
143
144   /* Initialize ID caches */
145   conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT, NULL);
146   conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
147   conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
148   conn->client = client;
149   conn->remote_host = strdup(hostname);
150   conn->remote_port = port;
151   conn->context = context;
152   conn->pending_commands = silc_dlist_init();
153
154   /* Add the connection to connections table */
155   for (i = 0; i < client->conns_count; i++)
156     if (client->conns && !client->conns[i]) {
157       client->conns[i] = conn;
158       return conn;
159     }
160
161   client->conns = silc_realloc(client->conns, sizeof(*client->conns)
162                                * (client->conns_count + 1));
163   client->conns[client->conns_count] = conn;
164   client->conns_count++;
165
166   return conn;
167 }
168
169 /* Removes connection from client. Frees all memory. */
170
171 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
172 {
173   int i;
174
175   for (i = 0; i < client->conns_count; i++)
176     if (client->conns[i] == conn) {
177       if (conn->pending_commands)
178         silc_dlist_uninit(conn->pending_commands);
179       silc_free(conn);
180       client->conns[i] = NULL;
181     }
182 }
183
184 /* Adds listener socket to the listener sockets table. This function is
185    used to add socket objects that are listeners to the client.  This should
186    not be used to add other connection objects. */
187
188 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
189 {
190   int i;
191
192   if (!client->sockets) {
193     client->sockets = silc_calloc(1, sizeof(*client->sockets));
194     client->sockets[0] = silc_socket_dup(sock);
195     client->sockets_count = 1;
196     return;
197   }
198
199   for (i = 0; i < client->sockets_count; i++) {
200     if (client->sockets[i] == NULL) {
201       client->sockets[i] = silc_socket_dup(sock);
202       return;
203     }
204   }
205
206   client->sockets = silc_realloc(client->sockets, sizeof(*client->sockets) *
207                                  (client->sockets_count + 1));
208   client->sockets[client->sockets_count] = silc_socket_dup(sock);
209   client->sockets_count++;
210 }
211
212 /* Deletes listener socket from the listener sockets table. */
213
214 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
215 {
216   int i;
217
218   if (!client->sockets)
219     return;
220
221   for (i = 0; i < client->sockets_count; i++) {
222     if (client->sockets[i] == sock) {
223       silc_socket_free(sock);
224       client->sockets[i] = NULL;
225       return;
226     }
227   }
228 }
229
230 static int 
231 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
232 {
233   int sock;
234
235   /* XXX In the future we should give up this non-blocking connect all
236      together and use threads instead. */
237   /* Create connection to server asynchronously */
238   sock = silc_net_create_connection_async(ctx->port, ctx->host);
239   if (sock < 0)
240     return -1;
241
242   /* Register task that will receive the async connect and will
243      read the result. */
244   ctx->task = silc_task_register(ctx->client->io_queue, sock, 
245                                  silc_client_connect_to_server_start,
246                                  (void *)ctx, 0, 0, 
247                                  SILC_TASK_FD,
248                                  SILC_TASK_PRI_NORMAL);
249   silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
250   silc_schedule_set_listen_fd(sock, ctx->task->iomask);
251
252   ctx->sock = sock;
253
254   return sock;
255 }
256
257 /* Connects to remote server. This is the main routine used to connect
258    to SILC server. Returns -1 on error and the created socket otherwise. 
259    The `context' is user context that is saved into the SilcClientConnection
260    that is created after the connection is created. Note that application
261    may handle the connecting process outside the library. If this is the
262    case then this function is not used at all. When the connecting is
263    done the `connect' client operation is called. */
264
265 int silc_client_connect_to_server(SilcClient client, int port,
266                                   char *host, void *context)
267 {
268   SilcClientInternalConnectContext *ctx;
269   SilcClientConnection conn;
270   int sock;
271
272   SILC_LOG_DEBUG(("Connecting to port %d of server %s",
273                   port, host));
274
275   conn = silc_client_add_connection(client, host, port, context);
276
277   client->ops->say(client, conn, 
278                    "Connecting to port %d of server %s", port, host);
279
280   /* Allocate internal context for connection process. This is
281      needed as we are doing async connecting. */
282   ctx = silc_calloc(1, sizeof(*ctx));
283   ctx->client = client;
284   ctx->conn = conn;
285   ctx->host = strdup(host);
286   ctx->port = port;
287   ctx->tries = 0;
288
289   /* Do the actual connecting process */
290   sock = silc_client_connect_to_server_internal(ctx);
291   if (sock == -1)
292     silc_client_del_connection(client, conn);
293   return sock;
294 }
295
296 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
297    key material between client and server.  This function can be called
298    directly if application is performing its own connecting and does not
299    use the connecting provided by this library. This function is normally
300    used only if the application performed the connecting outside the library.
301    The library however may use this internally. */
302
303 int silc_client_start_key_exchange(SilcClient client,
304                                    SilcClientConnection conn,
305                                    int fd)
306 {
307   SilcProtocol protocol;
308   SilcClientKEInternalContext *proto_ctx;
309   void *context;
310
311   /* Allocate new socket connection object */
312   silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
313
314   conn->nickname = strdup(client->username);
315   conn->sock->hostname = conn->remote_host;
316   conn->sock->ip = strdup(conn->remote_host);
317   conn->sock->port = conn->remote_port;
318
319   /* Allocate internal Key Exchange context. This is sent to the
320      protocol as context. */
321   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
322   proto_ctx->client = (void *)client;
323   proto_ctx->sock = silc_socket_dup(conn->sock);
324   proto_ctx->rng = client->rng;
325   proto_ctx->responder = FALSE;
326   proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
327   proto_ctx->verify = silc_client_protocol_ke_verify_key;
328
329   /* Perform key exchange protocol. silc_client_connect_to_server_final
330      will be called after the protocol is finished. */
331   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
332                       &protocol, (void *)proto_ctx,
333                       silc_client_connect_to_server_second);
334   if (!protocol) {
335     client->ops->say(client, conn, 
336                      "Error: Could not start authentication protocol");
337     return FALSE;
338   }
339   conn->sock->protocol = protocol;
340
341   /* Register the connection for network input and output. This sets
342      that scheduler will listen for incoming packets for this connection 
343      and sets that outgoing packets may be sent to this connection as well.
344      However, this doesn't set the scheduler for outgoing traffic, it will 
345      be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
346      later when outgoing data is available. */
347   context = (void *)client;
348   SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
349
350   /* Execute the protocol */
351   silc_protocol_execute(protocol, client->timeout_queue, 0, 0);
352   return TRUE;
353 }
354
355 /* Start of the connection to the remote server. This is called after
356    succesful TCP/IP connection has been established to the remote host. */
357
358 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
359 {
360   SilcClientInternalConnectContext *ctx =
361     (SilcClientInternalConnectContext *)context;
362   SilcClient client = ctx->client;
363   SilcClientConnection conn = ctx->conn;
364   int opt, opt_len = sizeof(opt);
365
366   SILC_LOG_DEBUG(("Start"));
367
368   /* Check the socket status as it might be in error */
369   getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
370   if (opt != 0) {
371     if (ctx->tries < 2) {
372       /* Connection failed but lets try again */
373       client->ops->say(client, conn, "Could not connect to server %s: %s",
374                        ctx->host, strerror(opt));
375       client->ops->say(client, conn, 
376                        "Connecting to port %d of server %s resumed", 
377                        ctx->port, ctx->host);
378
379       /* Unregister old connection try */
380       silc_schedule_unset_listen_fd(fd);
381       silc_net_close_connection(fd);
382       silc_task_unregister(client->io_queue, ctx->task);
383
384       /* Try again */
385       silc_client_connect_to_server_internal(ctx);
386       ctx->tries++;
387     } else {
388       /* Connection failed and we won't try anymore */
389       client->ops->say(client, conn, "Could not connect to server %s: %s",
390                        ctx->host, strerror(opt));
391       silc_schedule_unset_listen_fd(fd);
392       silc_net_close_connection(fd);
393       silc_task_unregister(client->io_queue, ctx->task);
394       silc_free(ctx);
395
396       /* Notify application of failure */
397       client->ops->connect(client, conn, FALSE);
398       silc_client_del_connection(client, conn);
399     }
400     return;
401   }
402
403   silc_schedule_unset_listen_fd(fd);
404   silc_task_unregister(client->io_queue, ctx->task);
405   silc_free(ctx);
406
407   if (!silc_client_start_key_exchange(client, conn, fd)) {
408     silc_net_close_connection(fd);
409     client->ops->connect(client, conn, FALSE);
410   }
411 }
412
413 /* Second part of the connecting to the server. This executed 
414    authentication protocol. */
415
416 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
417 {
418   SilcProtocol protocol = (SilcProtocol)context;
419   SilcClientKEInternalContext *ctx = 
420     (SilcClientKEInternalContext *)protocol->context;
421   SilcClient client = (SilcClient)ctx->client;
422   SilcSocketConnection sock = NULL;
423   SilcClientConnAuthInternalContext *proto_ctx;
424
425   SILC_LOG_DEBUG(("Start"));
426
427   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
428       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
429     /* Error occured during protocol */
430     SILC_LOG_DEBUG(("Error during KE protocol"));
431     silc_protocol_free(protocol);
432     silc_ske_free_key_material(ctx->keymat);
433     if (ctx->ske)
434       silc_ske_free(ctx->ske);
435     if (ctx->dest_id)
436       silc_free(ctx->dest_id);
437     ctx->sock->protocol = NULL;
438     silc_socket_free(ctx->sock);
439
440     /* Notify application of failure */
441     client->ops->connect(client, ctx->sock->user_data, FALSE);
442     silc_free(ctx);
443     return;
444   }
445
446   /* We now have the key material as the result of the key exchange
447      protocol. Take the key material into use. Free the raw key material
448      as soon as we've set them into use. */
449   silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
450                                    ctx->ske->prop->cipher,
451                                    ctx->ske->prop->pkcs,
452                                    ctx->ske->prop->hash,
453                                    ctx->ske->prop->hmac,
454                                    ctx->ske->prop->group);
455   silc_ske_free_key_material(ctx->keymat);
456
457   /* Allocate internal context for the authentication protocol. This
458      is sent as context for the protocol. */
459   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
460   proto_ctx->client = (void *)client;
461   proto_ctx->sock = sock = ctx->sock;
462   proto_ctx->ske = ctx->ske;    /* Save SKE object from previous protocol */
463   proto_ctx->dest_id_type = ctx->dest_id_type;
464   proto_ctx->dest_id = ctx->dest_id;
465
466   /* Resolve the authentication method to be used in this connection */
467   if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
468                                     sock->port, &proto_ctx->auth_meth,
469                                     &proto_ctx->auth_data, 
470                                     &proto_ctx->auth_data_len))
471     proto_ctx->auth_meth = SILC_AUTH_NONE;
472
473   /* Free old protocol as it is finished now */
474   silc_protocol_free(protocol);
475   if (ctx->packet)
476     silc_packet_context_free(ctx->packet);
477   silc_free(ctx);
478   sock->protocol = NULL;
479
480   /* Allocate the authenteication protocol and execute it. */
481   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
482                       &sock->protocol, (void *)proto_ctx, 
483                       silc_client_connect_to_server_final);
484
485   /* Execute the protocol */
486   silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
487 }
488
489 /* Finalizes the connection to the remote SILC server. This is called
490    after authentication protocol has been completed. This send our
491    user information to the server to receive our client ID from
492    server. */
493
494 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
495 {
496   SilcProtocol protocol = (SilcProtocol)context;
497   SilcClientConnAuthInternalContext *ctx = 
498     (SilcClientConnAuthInternalContext *)protocol->context;
499   SilcClient client = (SilcClient)ctx->client;
500   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
501   SilcBuffer packet;
502
503   SILC_LOG_DEBUG(("Start"));
504
505   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
506       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
507     /* Error occured during protocol */
508     SILC_LOG_DEBUG(("Error during authentication protocol"));
509     silc_protocol_free(protocol);
510     if (ctx->auth_data)
511       silc_free(ctx->auth_data);
512     if (ctx->ske)
513       silc_ske_free(ctx->ske);
514     if (ctx->dest_id)
515       silc_free(ctx->dest_id);
516     conn->sock->protocol = NULL;
517     silc_socket_free(ctx->sock);
518
519     /* Notify application of failure */
520     client->ops->connect(client, ctx->sock->user_data, FALSE);
521     silc_free(ctx);
522     return;
523   }
524
525   /* Send NEW_CLIENT packet to the server. We will become registered
526      to the SILC network after sending this packet and we will receive
527      client ID from the server. */
528   packet = silc_buffer_alloc(2 + 2 + strlen(client->username) + 
529                              strlen(client->realname));
530   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
531   silc_buffer_format(packet,
532                      SILC_STR_UI_SHORT(strlen(client->username)),
533                      SILC_STR_UI_XNSTRING(client->username,
534                                           strlen(client->username)),
535                      SILC_STR_UI_SHORT(strlen(client->realname)),
536                      SILC_STR_UI_XNSTRING(client->realname,
537                                           strlen(client->realname)),
538                      SILC_STR_END);
539
540   /* Send the packet */
541   silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
542                           NULL, 0, NULL, NULL, 
543                           packet->data, packet->len, TRUE);
544   silc_buffer_free(packet);
545
546   /* Save remote ID. */
547   conn->remote_id = ctx->dest_id;
548   conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
549   conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
550
551   /* Register re-key timeout */
552   conn->rekey->timeout = 3600; /* XXX hardcoded */
553   conn->rekey->context = (void *)client;
554   silc_task_register(client->timeout_queue, conn->sock->sock, 
555                      silc_client_rekey_callback,
556                      (void *)conn->sock, conn->rekey->timeout, 0,
557                      SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
558
559   silc_protocol_free(protocol);
560   if (ctx->auth_data)
561     silc_free(ctx->auth_data);
562   if (ctx->ske)
563     silc_ske_free(ctx->ske);
564   silc_socket_free(ctx->sock);
565   silc_free(ctx);
566   conn->sock->protocol = NULL;
567 }
568
569 /* Internal routine that sends packet or marks packet to be sent. This
570    is used directly only in special cases. Normal cases should use
571    silc_server_packet_send. Returns < 0 on error. */
572
573 int silc_client_packet_send_real(SilcClient client,
574                                  SilcSocketConnection sock,
575                                  bool force_send,
576                                  bool flush)
577 {
578   int ret;
579
580   /* If rekey protocol is active we must assure that all packets are
581      sent through packet queue. */
582   if (flush == FALSE && SILC_CLIENT_IS_REKEY(sock))
583     force_send = FALSE;
584
585   /* Send the packet */
586   ret = silc_packet_send(sock, force_send);
587   if (ret != -2)
588     return ret;
589
590   /* Mark that there is some outgoing data available for this connection. 
591      This call sets the connection both for input and output (the input
592      is set always and this call keeps the input setting, actually). 
593      Actual data sending is performed by silc_client_packet_process. */
594   SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
595
596   /* Mark to socket that data is pending in outgoing buffer. This flag
597      is needed if new data is added to the buffer before the earlier
598      put data is sent to the network. */
599   SILC_SET_OUTBUF_PENDING(sock);
600
601   return 0;
602 }
603
604 /* Packet processing callback. This is used to send and receive packets
605    from network. This is generic task. */
606
607 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
608 {
609   SilcClient client = (SilcClient)context;
610   SilcSocketConnection sock = NULL;
611   SilcClientConnection conn;
612   int ret;
613
614   SILC_LOG_DEBUG(("Processing packet"));
615
616   SILC_CLIENT_GET_SOCK(client, fd, sock);
617   if (sock == NULL)
618     return;
619
620   conn = (SilcClientConnection)sock->user_data;
621
622   /* Packet sending */
623   if (type == SILC_TASK_WRITE) {
624     SILC_LOG_DEBUG(("Writing data to connection"));
625
626     if (sock->outbuf->data - sock->outbuf->head)
627       silc_buffer_push(sock->outbuf, 
628                        sock->outbuf->data - sock->outbuf->head);
629
630     ret = silc_client_packet_send_real(client, sock, TRUE, TRUE);
631
632     /* If returned -2 could not write to connection now, will do
633        it later. */
634     if (ret == -2)
635       return;
636     
637     /* The packet has been sent and now it is time to set the connection
638        back to only for input. When there is again some outgoing data 
639        available for this connection it will be set for output as well. 
640        This call clears the output setting and sets it only for input. */
641     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
642     SILC_UNSET_OUTBUF_PENDING(sock);
643
644     silc_buffer_clear(sock->outbuf);
645     return;
646   }
647
648   /* Packet receiving */
649   if (type == SILC_TASK_READ) {
650     SILC_LOG_DEBUG(("Reading data from connection"));
651
652     /* Read data from network */
653     ret = silc_packet_receive(sock);
654     if (ret < 0)
655       return;
656     
657     /* EOF */
658     if (ret == 0) {
659       SILC_LOG_DEBUG(("Read EOF"));
660
661       /* If connection is disconnecting already we will finally
662          close the connection */
663       if (SILC_IS_DISCONNECTING(sock)) {
664         if (sock == conn->sock)
665           client->ops->disconnect(client, conn);
666         silc_client_close_connection(client, sock, conn);
667         return;
668       }
669       
670       SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
671       if (sock == conn->sock)
672         client->ops->disconnect(client, conn);
673       silc_client_close_connection(client, sock, conn);
674       return;
675     }
676
677     /* Process the packet. This will call the parser that will then
678        decrypt and parse the packet. */
679     if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
680       silc_packet_receive_process(sock, conn->receive_key, conn->hmac_receive,
681                                   silc_client_packet_parse, client);
682     else
683       silc_packet_receive_process(sock, NULL, NULL,
684                                   silc_client_packet_parse, client);
685   }
686 }
687
688 /* Callback function that the silc_packet_decrypt will call to make the
689    decision whether the packet is normal or special packet. We will 
690    return TRUE if it is normal and FALSE if it is special */
691
692 static int silc_client_packet_decrypt_check(SilcPacketType packet_type,
693                                             SilcBuffer buffer,
694                                             SilcPacketContext *packet,
695                                             void *context)
696 {
697
698   /* Packet is normal packet, if: 
699
700      1) packet is private message packet and does not have private key set
701      2) is other packet than channel message packet
702
703      all other packets are special packets 
704   */
705
706   if (packet_type == SILC_PACKET_PRIVATE_MESSAGE &&
707       (buffer->data[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
708     return FALSE;
709
710   if (packet_type != SILC_PACKET_CHANNEL_MESSAGE)
711     return TRUE;
712
713   return FALSE;
714 }
715
716 /* Parses whole packet, received earlier. */
717
718 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
719 {
720   SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
721   SilcClient client = (SilcClient)parse_ctx->context;
722   SilcPacketContext *packet = parse_ctx->packet;
723   SilcBuffer buffer = packet->buffer;
724   SilcSocketConnection sock = parse_ctx->sock;
725   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
726   int ret;
727
728   SILC_LOG_DEBUG(("Start"));
729
730   /* Decrypt the received packet */
731   if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
732     ret = silc_packet_decrypt(conn->receive_key, conn->hmac_receive, 
733                               buffer, packet,
734                               silc_client_packet_decrypt_check, parse_ctx);
735   else
736     ret = silc_packet_decrypt(NULL, NULL, buffer, packet,
737                               silc_client_packet_decrypt_check, parse_ctx);
738
739   if (ret < 0)
740     goto out;
741
742   if (ret == 0) {
743     /* Parse the packet. Packet type is returned. */
744     ret = silc_packet_parse(packet);
745   } else {
746     /* Parse the packet header in special way as this is "special"
747        packet type. */
748     ret = silc_packet_parse_special(packet);
749   }
750
751   if (ret == SILC_PACKET_NONE)
752     goto out;
753
754   /* Parse the incoming packet type */
755   silc_client_packet_parse_type(client, sock, packet);
756
757  out:
758   /*  silc_buffer_clear(sock->inbuf); */
759   silc_packet_context_free(packet);
760   silc_free(parse_ctx);
761 }
762
763 /* Parser callback called by silc_packet_receive_process. Thie merely
764    registers timeout that will handle the actual parsing when appropriate. */
765
766 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
767 {
768   SilcClient client = (SilcClient)parser_context->context;
769
770   /* Parse the packet */
771   silc_task_register(client->timeout_queue, parser_context->sock->sock, 
772                      silc_client_packet_parse_real,
773                      (void *)parser_context, 0, 1, 
774                      SILC_TASK_TIMEOUT,
775                      SILC_TASK_PRI_NORMAL);
776 }
777
778 /* Parses the packet type and calls what ever routines the packet type
779    requires. This is done for all incoming packets. */
780
781 void silc_client_packet_parse_type(SilcClient client, 
782                                    SilcSocketConnection sock,
783                                    SilcPacketContext *packet)
784 {
785   SilcBuffer buffer = packet->buffer;
786   SilcPacketType type = packet->type;
787
788   SILC_LOG_DEBUG(("Parsing packet type %d", type));
789
790   /* Parse the packet type */
791   switch(type) {
792   case SILC_PACKET_DISCONNECT:
793     silc_client_disconnected_by_server(client, sock, buffer);
794     break;
795   case SILC_PACKET_SUCCESS:
796     /*
797      * Success received for something. For now we can have only
798      * one protocol for connection executing at once hence this
799      * success message is for whatever protocol is executing currently.
800      */
801     if (sock->protocol)
802       silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
803     break;
804   case SILC_PACKET_FAILURE:
805     /*
806      * Failure received for some protocol. Set the protocol state to 
807      * error and call the protocol callback. This fill cause error on
808      * protocol and it will call the final callback.
809      */
810     silc_client_process_failure(client, sock, packet);
811     break;
812   case SILC_PACKET_REJECT:
813     break;
814
815   case SILC_PACKET_NOTIFY:
816     /*
817      * Received notify message 
818      */
819     silc_client_notify_by_server(client, sock, packet);
820     break;
821
822   case SILC_PACKET_ERROR:
823     /*
824      * Received error message
825      */
826     silc_client_error_by_server(client, sock, buffer);
827     break;
828
829   case SILC_PACKET_CHANNEL_MESSAGE:
830     /*
831      * Received message to (from, actually) a channel
832      */
833     silc_client_channel_message(client, sock, packet);
834     break;
835   case SILC_PACKET_CHANNEL_KEY:
836     /*
837      * Received key for a channel. By receiving this key the client will be
838      * able to talk to the channel it has just joined. This can also be
839      * a new key for existing channel as keys expire peridiocally.
840      */
841     silc_client_receive_channel_key(client, sock, buffer);
842     break;
843
844   case SILC_PACKET_PRIVATE_MESSAGE:
845     /*
846      * Received private message
847      */
848     silc_client_private_message(client, sock, packet);
849     break;
850   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
851     /*
852      * Received private message key
853      */
854     break;
855
856   case SILC_PACKET_COMMAND_REPLY:
857     /*
858      * Recived reply for a command
859      */
860     silc_client_command_reply_process(client, sock, packet);
861     break;
862
863   case SILC_PACKET_KEY_EXCHANGE:
864     if (sock->protocol && sock->protocol->protocol && 
865         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
866       SilcClientKEInternalContext *proto_ctx = 
867         (SilcClientKEInternalContext *)sock->protocol->context;
868
869       proto_ctx->packet = silc_packet_context_dup(packet);
870       proto_ctx->dest_id_type = packet->src_id_type;
871       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
872                                           packet->src_id_type);
873       if (!proto_ctx->dest_id)
874         break;
875
876       /* Let the protocol handle the packet */
877       silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
878     } else {
879       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
880                       "protocol active, packet dropped."));
881     }
882     break;
883
884   case SILC_PACKET_KEY_EXCHANGE_1:
885     if (sock->protocol && sock->protocol->protocol && 
886         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
887          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
888
889       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
890         SilcClientRekeyInternalContext *proto_ctx = 
891           (SilcClientRekeyInternalContext *)sock->protocol->context;
892         
893         if (proto_ctx->packet)
894           silc_packet_context_free(proto_ctx->packet);
895         
896         proto_ctx->packet = silc_packet_context_dup(packet);
897
898         /* Let the protocol handle the packet */
899         silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
900       } else {
901         SilcClientKEInternalContext *proto_ctx = 
902           (SilcClientKEInternalContext *)sock->protocol->context;
903         
904         if (proto_ctx->packet)
905           silc_packet_context_free(proto_ctx->packet);
906         
907         proto_ctx->packet = silc_packet_context_dup(packet);
908         proto_ctx->dest_id_type = packet->src_id_type;
909         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
910                                             packet->src_id_type);
911         if (!proto_ctx->dest_id)
912           break;
913         
914         /* Let the protocol handle the packet */
915         silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
916       }
917     } else {
918       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
919                       "protocol active, packet dropped."));
920     }
921     break;
922   case SILC_PACKET_KEY_EXCHANGE_2:
923     if (sock->protocol && sock->protocol->protocol && 
924         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
925          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
926
927       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
928         SilcClientRekeyInternalContext *proto_ctx = 
929           (SilcClientRekeyInternalContext *)sock->protocol->context;
930         
931         if (proto_ctx->packet)
932           silc_packet_context_free(proto_ctx->packet);
933         
934         proto_ctx->packet = silc_packet_context_dup(packet);
935
936         /* Let the protocol handle the packet */
937         silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
938       } else {
939         SilcClientKEInternalContext *proto_ctx = 
940           (SilcClientKEInternalContext *)sock->protocol->context;
941         
942         if (proto_ctx->packet)
943           silc_packet_context_free(proto_ctx->packet);
944         
945         proto_ctx->packet = silc_packet_context_dup(packet);
946         proto_ctx->dest_id_type = packet->src_id_type;
947         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
948                                             packet->src_id_type);
949         if (!proto_ctx->dest_id)
950           break;
951         
952         /* Let the protocol handle the packet */
953         silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
954       }
955     } else {
956       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
957                       "protocol active, packet dropped."));
958     }
959     break;
960
961   case SILC_PACKET_NEW_ID:
962     {
963       /*
964        * Received new ID from server. This packet is received at
965        * the connection to the server.  New ID is also received when 
966        * user changes nickname but in that case the new ID is received
967        * as command reply and not as this packet type.
968        */
969       SilcIDPayload idp;
970
971       idp = silc_id_payload_parse(buffer);
972       if (!idp)
973         break;
974       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
975         break;
976
977       silc_client_receive_new_id(client, sock, idp);
978       silc_id_payload_free(idp);
979       break;
980     }
981
982   case SILC_PACKET_HEARTBEAT:
983     /*
984      * Received heartbeat packet
985      */
986     SILC_LOG_DEBUG(("Heartbeat packet"));
987     break;
988
989   case SILC_PACKET_KEY_AGREEMENT:
990     /*
991      * Received key agreement packet
992      */
993     SILC_LOG_DEBUG(("Key agreement packet"));
994     silc_client_key_agreement(client, sock, packet);
995     break;
996
997   case SILC_PACKET_REKEY:
998     SILC_LOG_DEBUG(("Re-key packet"));
999     /* We ignore this for now */
1000     break;
1001
1002   case SILC_PACKET_REKEY_DONE:
1003     SILC_LOG_DEBUG(("Re-key done packet"));
1004
1005     if (sock->protocol && sock->protocol->protocol && 
1006         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1007
1008       SilcClientRekeyInternalContext *proto_ctx = 
1009         (SilcClientRekeyInternalContext *)sock->protocol->context;
1010       
1011       if (proto_ctx->packet)
1012         silc_packet_context_free(proto_ctx->packet);
1013       
1014       proto_ctx->packet = silc_packet_context_dup(packet);
1015
1016       /* Let the protocol handle the packet */
1017       if (proto_ctx->responder == FALSE)
1018         silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
1019       else
1020         /* Let the protocol handle the packet */
1021         silc_protocol_execute(sock->protocol, client->timeout_queue, 
1022                               0, 100000);
1023     } else {
1024       SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1025                       "protocol active, packet dropped."));
1026     }
1027     break;
1028
1029   default:
1030     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1031     break;
1032   }
1033 }
1034
1035 /* Sends packet. This doesn't actually send the packet instead it assembles
1036    it and marks it to be sent. However, if force_send is TRUE the packet
1037    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1038    will be derived from sock argument. Otherwise the valid arguments sent
1039    are used. */
1040
1041 void silc_client_packet_send(SilcClient client, 
1042                              SilcSocketConnection sock,
1043                              SilcPacketType type, 
1044                              void *dst_id,
1045                              SilcIdType dst_id_type,
1046                              SilcCipher cipher,
1047                              SilcHmac hmac,
1048                              unsigned char *data, 
1049                              uint32 data_len, 
1050                              int force_send)
1051 {
1052   SilcPacketContext packetdata;
1053
1054   SILC_LOG_DEBUG(("Sending packet, type %d", type));
1055
1056   /* Get data used in the packet sending, keys and stuff */
1057   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1058     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1059       cipher = ((SilcClientConnection)sock->user_data)->send_key;
1060
1061     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1062       hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1063
1064     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1065       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1066       dst_id_type = SILC_ID_SERVER;
1067     }
1068   }
1069
1070   /* Set the packet context pointers */
1071   packetdata.flags = 0;
1072   packetdata.type = type;
1073   if (sock->user_data && 
1074       ((SilcClientConnection)sock->user_data)->local_id_data) {
1075     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1076     packetdata.src_id_len = 
1077       silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1078                       SILC_ID_CLIENT);
1079   } else { 
1080     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1081     packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1082   }
1083   packetdata.src_id_type = SILC_ID_CLIENT;
1084   if (dst_id) {
1085     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1086     packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1087     packetdata.dst_id_type = dst_id_type;
1088   } else {
1089     packetdata.dst_id = NULL;
1090     packetdata.dst_id_len = 0;
1091     packetdata.dst_id_type = SILC_ID_NONE;
1092   }
1093   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
1094     packetdata.src_id_len + packetdata.dst_id_len;
1095   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
1096
1097   /* Prepare outgoing data buffer for packet sending */
1098   silc_packet_send_prepare(sock, 
1099                            SILC_PACKET_HEADER_LEN +
1100                            packetdata.src_id_len + 
1101                            packetdata.dst_id_len,
1102                            packetdata.padlen,
1103                            data_len);
1104
1105   SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
1106
1107   packetdata.buffer = sock->outbuf;
1108
1109   /* Put the data to the buffer */
1110   if (data && data_len)
1111     silc_buffer_put(sock->outbuf, data, data_len);
1112
1113   /* Create the outgoing packet */
1114   silc_packet_assemble(&packetdata);
1115
1116   /* Encrypt the packet */
1117   if (cipher)
1118     silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
1119
1120   SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
1121                    sock->outbuf->data, sock->outbuf->len);
1122
1123   /* Now actually send the packet */
1124   silc_client_packet_send_real(client, sock, force_send, FALSE);
1125 }
1126
1127 /* Closes connection to remote end. Free's all allocated data except
1128    for some information such as nickname etc. that are valid at all time. 
1129    If the `sock' is NULL then the conn->sock will be used.  If `sock' is
1130    provided it will be checked whether the sock and `conn->sock' are the
1131    same (they can be different, ie. a socket can use `conn' as its
1132    connection but `conn->sock' might be actually a different connection
1133    than the `sock'). */
1134
1135 void silc_client_close_connection(SilcClient client,
1136                                   SilcSocketConnection sock,
1137                                   SilcClientConnection conn)
1138 {
1139   int del = FALSE;
1140
1141   if (!sock || (sock && conn->sock == sock))
1142     del = TRUE;
1143   if (!sock)
1144     sock = conn->sock;
1145
1146   /* We won't listen for this connection anymore */
1147   silc_schedule_unset_listen_fd(sock->sock);
1148
1149   /* Unregister all tasks */
1150   silc_task_unregister_by_fd(client->io_queue, sock->sock);
1151   silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1152
1153   /* Close the actual connection */
1154   silc_net_close_connection(sock->sock);
1155
1156   /* Free everything */
1157   if (del && sock->user_data) {
1158     /* XXX Free all client entries and channel entries. */
1159
1160     client->ops->say(client, sock->user_data,
1161                      "Closed connection to host %s", sock->hostname);
1162
1163     /* Clear ID caches */
1164     silc_idcache_del_all(conn->client_cache);
1165     silc_idcache_del_all(conn->channel_cache);
1166
1167     /* Free data */
1168     if (conn->remote_host)
1169       silc_free(conn->remote_host);
1170     if (conn->local_id)
1171       silc_free(conn->local_id);
1172     if (conn->local_id_data)
1173       silc_free(conn->local_id_data);
1174     if (conn->send_key)
1175       silc_cipher_free(conn->send_key);
1176     if (conn->receive_key)
1177       silc_cipher_free(conn->receive_key);
1178     if (conn->hmac_send)        /* conn->hmac_receive is same */
1179       silc_hmac_free(conn->hmac_send);
1180     if (conn->pending_commands)
1181       silc_dlist_uninit(conn->pending_commands);
1182     if (conn->rekey)
1183       silc_free(conn->rekey);
1184
1185     conn->sock = NULL;
1186     conn->remote_port = 0;
1187     conn->remote_type = 0;
1188     conn->send_key = NULL;
1189     conn->receive_key = NULL;
1190     conn->hmac_send = NULL;
1191     conn->hmac_receive = NULL;
1192     conn->local_id = NULL;
1193     conn->local_id_data = NULL;
1194     conn->remote_host = NULL;
1195     conn->current_channel = NULL;
1196     conn->pending_commands = NULL;
1197     conn->rekey = NULL;
1198
1199     silc_client_del_connection(client, conn);
1200   }
1201
1202   if (sock->protocol) {
1203     silc_protocol_free(sock->protocol);
1204     sock->protocol = NULL;
1205   }
1206   silc_socket_free(sock);
1207 }
1208
1209 /* Called when we receive disconnection packet from server. This 
1210    closes our end properly and displays the reason of the disconnection
1211    on the screen. */
1212
1213 void silc_client_disconnected_by_server(SilcClient client,
1214                                         SilcSocketConnection sock,
1215                                         SilcBuffer message)
1216 {
1217   char *msg;
1218
1219   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1220
1221   msg = silc_calloc(message->len + 1, sizeof(char));
1222   memcpy(msg, message->data, message->len);
1223   client->ops->say(client, sock->user_data, msg);
1224   silc_free(msg);
1225
1226   SILC_SET_DISCONNECTED(sock);
1227   silc_client_close_connection(client, sock, sock->user_data);
1228 }
1229
1230 /* Received error message from server. Display it on the screen. 
1231    We don't take any action what so ever of the error message. */
1232
1233 void silc_client_error_by_server(SilcClient client,
1234                                  SilcSocketConnection sock,
1235                                  SilcBuffer message)
1236 {
1237   char *msg;
1238
1239   msg = silc_calloc(message->len + 1, sizeof(char));
1240   memcpy(msg, message->data, message->len);
1241   client->ops->say(client, sock->user_data, msg);
1242   silc_free(msg);
1243 }
1244
1245 /* Processes the received new Client ID from server. Old Client ID is
1246    deleted from cache and new one is added. */
1247
1248 void silc_client_receive_new_id(SilcClient client,
1249                                 SilcSocketConnection sock,
1250                                 SilcIDPayload idp)
1251 {
1252   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1253   int connecting = FALSE;
1254
1255   if (!conn->local_entry)
1256     connecting = TRUE;
1257
1258   /* Delete old ID from ID cache */
1259   if (conn->local_id) {
1260     silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1261     silc_free(conn->local_id);
1262   }
1263   
1264   /* Save the new ID */
1265
1266   if (conn->local_id_data)
1267     silc_free(conn->local_id_data);
1268
1269   conn->local_id = silc_id_payload_get_id(idp);
1270   conn->local_id_data = silc_id_payload_get_data(idp);
1271   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1272
1273   if (!conn->local_entry)
1274     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1275
1276   conn->local_entry->nickname = conn->nickname;
1277   if (!conn->local_entry->username) {
1278     conn->local_entry->username = 
1279       silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1280                   sizeof(conn->local_entry->username));
1281     sprintf(conn->local_entry->username, "%s@%s", client->username,
1282             client->hostname);
1283   }
1284   conn->local_entry->server = strdup(conn->remote_host);
1285   conn->local_entry->id = conn->local_id;
1286   
1287   /* Put it to the ID cache */
1288   silc_idcache_add(conn->client_cache, conn->nickname, conn->local_id, 
1289                    (void *)conn->local_entry, FALSE);
1290
1291   /* Notify application of successful connection. We do it here now that
1292      we've received the Client ID and are allowed to send traffic. */
1293   if (connecting)
1294     client->ops->connect(client, conn, TRUE);
1295 }
1296
1297 /* Processed received Channel ID for a channel. This is called when client
1298    joins to channel and server replies with channel ID. The ID is cached. 
1299    Returns the created channel entry. */
1300
1301 SilcChannelEntry silc_client_new_channel_id(SilcClient client,
1302                                             SilcSocketConnection sock,
1303                                             char *channel_name,
1304                                             uint32 mode, 
1305                                             SilcIDPayload idp)
1306 {
1307   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1308   SilcChannelEntry channel;
1309
1310   SILC_LOG_DEBUG(("New channel ID"));
1311
1312   channel = silc_calloc(1, sizeof(*channel));
1313   channel->channel_name = channel_name;
1314   channel->id = silc_id_payload_get_id(idp);
1315   channel->mode = mode;
1316   silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1317
1318   conn->current_channel = channel;
1319
1320   /* Put it to the ID cache */
1321   silc_idcache_add(conn->channel_cache, channel_name, (void *)channel->id, 
1322                    (void *)channel, FALSE);
1323
1324   return channel;
1325 }
1326
1327 /* Removes a client entry from all channel it has joined. This really is
1328    a performance killer (client_entry should have pointers to channel 
1329    entry list). */
1330
1331 void silc_client_remove_from_channels(SilcClient client,
1332                                       SilcClientConnection conn,
1333                                       SilcClientEntry client_entry)
1334 {
1335   SilcIDCacheEntry id_cache;
1336   SilcIDCacheList list;
1337   SilcChannelEntry channel;
1338   SilcChannelUser chu;
1339
1340   if (!silc_idcache_get_all(conn->channel_cache, &list))
1341     return;
1342
1343   silc_idcache_list_first(list, &id_cache);
1344   channel = (SilcChannelEntry)id_cache->context;
1345   
1346   while (channel) {
1347     
1348     /* Remove client from channel */
1349     silc_list_start(channel->clients);
1350     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1351       if (chu->client == client_entry) {
1352         silc_list_del(channel->clients, chu);
1353         silc_free(chu);
1354         break;
1355       }
1356     }
1357
1358     if (!silc_idcache_list_next(list, &id_cache))
1359       break;
1360     
1361     channel = (SilcChannelEntry)id_cache->context;
1362   }
1363
1364   silc_idcache_list_free(list);
1365 }
1366
1367 /* Replaces `old' client entries from all channels to `new' client entry.
1368    This can be called for example when nickname changes and old ID entry
1369    is replaced from ID cache with the new one. If the old ID entry is only
1370    updated, then this fucntion needs not to be called. */
1371
1372 void silc_client_replace_from_channels(SilcClient client, 
1373                                        SilcClientConnection conn,
1374                                        SilcClientEntry old,
1375                                        SilcClientEntry new)
1376 {
1377   SilcIDCacheEntry id_cache;
1378   SilcIDCacheList list;
1379   SilcChannelEntry channel;
1380   SilcChannelUser chu;
1381
1382   if (!silc_idcache_get_all(conn->channel_cache, &list))
1383     return;
1384
1385   silc_idcache_list_first(list, &id_cache);
1386   channel = (SilcChannelEntry)id_cache->context;
1387   
1388   while (channel) {
1389     
1390     /* Replace client entry */
1391     silc_list_start(channel->clients);
1392     while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1393       if (chu->client == old) {
1394         chu->client = new;
1395         break;
1396       }
1397     }
1398
1399     if (!silc_idcache_list_next(list, &id_cache))
1400       break;
1401     
1402     channel = (SilcChannelEntry)id_cache->context;
1403   }
1404
1405   silc_idcache_list_free(list);
1406 }
1407
1408 /* Parses mode mask and returns the mode as string. */
1409
1410 char *silc_client_chmode(uint32 mode, SilcChannelEntry channel)
1411 {
1412   char string[100];
1413
1414   if (!mode)
1415     return NULL;
1416
1417   memset(string, 0, sizeof(string));
1418
1419   if (mode & SILC_CHANNEL_MODE_PRIVATE)
1420     strncat(string, "p", 1);
1421
1422   if (mode & SILC_CHANNEL_MODE_SECRET)
1423     strncat(string, "s", 1);
1424
1425   if (mode & SILC_CHANNEL_MODE_PRIVKEY)
1426     strncat(string, "k", 1);
1427
1428   if (mode & SILC_CHANNEL_MODE_INVITE)
1429     strncat(string, "i", 1);
1430
1431   if (mode & SILC_CHANNEL_MODE_TOPIC)
1432     strncat(string, "t", 1);
1433
1434   if (mode & SILC_CHANNEL_MODE_ULIMIT)
1435     strncat(string, "l", 1);
1436
1437   if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
1438     strncat(string, "a", 1);
1439
1440   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
1441     strncat(string, "f", 1);
1442
1443   if (mode & SILC_CHANNEL_MODE_CIPHER) {
1444     char cipher[30];
1445     memset(cipher, 0, sizeof(cipher));
1446     snprintf(cipher, sizeof(cipher), " c (%s)", 
1447              channel->channel_key->cipher->name);
1448     strncat(string, cipher, strlen(cipher));
1449   }
1450
1451   if (mode & SILC_CHANNEL_MODE_HMAC) {
1452     char hmac[30];
1453     memset(hmac, 0, sizeof(hmac));
1454     snprintf(hmac, sizeof(hmac), " h (%s)", 
1455              channel->hmac->hmac->name);
1456     strncat(string, hmac, strlen(hmac));
1457   }
1458
1459   /* Rest of mode is ignored */
1460
1461   return strdup(string);
1462 }
1463
1464 /* Parses channel user mode mask and returns te mode as string */
1465
1466 char *silc_client_chumode(uint32 mode)
1467 {
1468   char string[4];
1469
1470   if (!mode)
1471     return NULL;
1472
1473   memset(string, 0, sizeof(string));
1474
1475   if (mode & SILC_CHANNEL_UMODE_CHANFO)
1476     strncat(string, "f", 1);
1477
1478   if (mode & SILC_CHANNEL_UMODE_CHANOP)
1479     strncat(string, "o", 1);
1480
1481   return strdup(string);
1482 }
1483
1484 /* Parses channel user mode and returns it as special mode character. */
1485
1486 char *silc_client_chumode_char(uint32 mode)
1487 {
1488   char string[4];
1489
1490   if (!mode)
1491     return NULL;
1492
1493   memset(string, 0, sizeof(string));
1494
1495   if (mode & SILC_CHANNEL_UMODE_CHANFO)
1496     strncat(string, "*", 1);
1497
1498   if (mode & SILC_CHANNEL_UMODE_CHANOP)
1499     strncat(string, "@", 1);
1500
1501   return strdup(string);
1502 }
1503
1504 /* Registers failure timeout to process the received failure packet
1505    with timeout. */
1506
1507 void silc_client_process_failure(SilcClient client,
1508                                  SilcSocketConnection sock,
1509                                  SilcPacketContext *packet)
1510 {
1511   uint32 failure = 0;
1512
1513   if (sock->protocol) {
1514     if (packet->buffer->len >= 4)
1515       SILC_GET32_MSB(failure, packet->buffer->data);
1516
1517     /* Notify application */
1518     client->ops->failure(client, sock->user_data, sock->protocol,
1519                          (void *)failure);
1520   }
1521 }
1522
1523 /* A timeout callback for the re-key. We will be the initiator of the
1524    re-key protocol. */
1525
1526 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1527 {
1528   SilcSocketConnection sock = (SilcSocketConnection)context;
1529   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1530   SilcClient client = (SilcClient)conn->rekey->context;
1531   SilcProtocol protocol;
1532   SilcClientRekeyInternalContext *proto_ctx;
1533
1534   SILC_LOG_DEBUG(("Start"));
1535
1536   /* Allocate internal protocol context. This is sent as context
1537      to the protocol. */
1538   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1539   proto_ctx->client = (void *)client;
1540   proto_ctx->sock = silc_socket_dup(sock);
1541   proto_ctx->responder = FALSE;
1542   proto_ctx->pfs = conn->rekey->pfs;
1543       
1544   /* Perform rekey protocol. Will call the final callback after the
1545      protocol is over. */
1546   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY, 
1547                       &protocol, proto_ctx, silc_client_rekey_final);
1548   sock->protocol = protocol;
1549       
1550   /* Run the protocol */
1551   silc_protocol_execute(protocol, client->timeout_queue, 0, 0);
1552
1553   /* Re-register re-key timeout */
1554   silc_task_register(client->timeout_queue, sock->sock, 
1555                      silc_client_rekey_callback,
1556                      context, conn->rekey->timeout, 0,
1557                      SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1558 }
1559
1560 /* The final callback for the REKEY protocol. This will actually take the
1561    new key material into use. */
1562
1563 SILC_TASK_CALLBACK(silc_client_rekey_final)
1564 {
1565   SilcProtocol protocol = (SilcProtocol)context;
1566   SilcClientRekeyInternalContext *ctx =
1567     (SilcClientRekeyInternalContext *)protocol->context;
1568   SilcClient client = (SilcClient)ctx->client;
1569   SilcSocketConnection sock = ctx->sock;
1570
1571   SILC_LOG_DEBUG(("Start"));
1572
1573   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1574       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1575     /* Error occured during protocol */
1576     silc_protocol_cancel(protocol, client->timeout_queue);
1577     silc_protocol_free(protocol);
1578     sock->protocol = NULL;
1579     if (ctx->packet)
1580       silc_packet_context_free(ctx->packet);
1581     if (ctx->ske)
1582       silc_ske_free(ctx->ske);
1583     silc_socket_free(ctx->sock);
1584     silc_free(ctx);
1585     return;
1586   }
1587
1588   /* Cleanup */
1589   silc_protocol_free(protocol);
1590   sock->protocol = NULL;
1591   if (ctx->packet)
1592     silc_packet_context_free(ctx->packet);
1593   if (ctx->ske)
1594     silc_ske_free(ctx->ske);
1595   silc_socket_free(ctx->sock);
1596   silc_free(ctx);
1597 }