Fixed a bug in disconnecting in irssi.
[silc.git] / lib / silcclient / client.c
1 /*
2
3   client.c 
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2002 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id$ */
20
21 #include "silcincludes.h"
22 #include "silcclient.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_rekey_callback);
30 SILC_TASK_CALLBACK(silc_client_rekey_final);
31
32 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
33                                      void *context);
34 static void silc_client_packet_parse_type(SilcClient client, 
35                                           SilcSocketConnection sock,
36                                           SilcPacketContext *packet);
37 void silc_client_resolve_auth_method(bool success,
38                                      SilcProtocolAuthMeth auth_meth,
39                                      const unsigned char *auth_data,
40                                      SilcUInt32 auth_data_len, void *context);
41
42 /* Allocates new client object. This has to be done before client may
43    work. After calling this one must call silc_client_init to initialize
44    the client. The `application' is application specific user data pointer
45    and caller must free it. */
46
47 SilcClient silc_client_alloc(SilcClientOperations *ops, 
48                              SilcClientParams *params,
49                              void *application,
50                              const char *silc_version)
51 {
52   SilcClient new_client;
53
54   new_client = silc_calloc(1, sizeof(*new_client));
55   new_client->application = application;
56
57   new_client->internal = silc_calloc(1, sizeof(*new_client->internal));
58   new_client->internal->ops = ops;
59   new_client->internal->params = 
60     silc_calloc(1, sizeof(*new_client->internal->params));
61   new_client->internal->silc_client_version = strdup(silc_version);
62
63   if (params)
64     memcpy(new_client->internal->params, params, sizeof(*params));
65
66   if (!new_client->internal->params->task_max)
67     new_client->internal->params->task_max = 200;
68
69   if (!new_client->internal->params->rekey_secs)
70     new_client->internal->params->rekey_secs = 3600;
71
72   if (!new_client->internal->params->connauth_request_secs)
73     new_client->internal->params->connauth_request_secs = 2;
74
75   new_client->internal->params->
76     nickname_format[sizeof(new_client->internal->
77                            params->nickname_format) - 1] = 0;
78
79   return new_client;
80 }
81
82 /* Frees client object and its internals. */
83
84 void silc_client_free(SilcClient client)
85 {
86   if (client) {
87     if (client->rng)
88       silc_rng_free(client->rng);
89
90     silc_free(client->internal->params);
91     silc_free(client->internal->silc_client_version);
92     silc_free(client->internal);
93     silc_free(client);
94   }
95 }
96
97 /* Initializes the client. This makes all the necessary steps to make
98    the client ready to be run. One must call silc_client_run to run the
99    client. Returns FALSE if error occured, TRUE otherwise. */
100
101 int silc_client_init(SilcClient client)
102 {
103   SILC_LOG_DEBUG(("Initializing client"));
104
105   /* Initialize hash functions for client to use */
106   silc_hash_alloc("md5", &client->internal->md5hash);
107   silc_hash_alloc("sha1", &client->internal->sha1hash);
108
109   /* Initialize none cipher */
110   silc_cipher_alloc("none", &client->internal->none_cipher);
111
112   /* Initialize random number generator */
113   client->rng = silc_rng_alloc();
114   silc_rng_init(client->rng);
115   silc_rng_global_init(client->rng);
116
117   /* Register protocols */
118   silc_client_protocols_register();
119
120   /* Initialize the scheduler */
121   client->schedule = 
122     silc_schedule_init(client->internal->params->task_max ?
123                        client->internal->params->task_max : 200);
124   if (!client->schedule)
125     return FALSE;
126
127   /* Register commands */
128   silc_client_commands_register(client);
129
130   return TRUE;
131 }
132
133 /* Stops the client. This is called to stop the client and thus to stop
134    the program. */
135
136 void silc_client_stop(SilcClient client)
137 {
138   SILC_LOG_DEBUG(("Stopping client"));
139
140   silc_schedule_stop(client->schedule);
141   silc_schedule_uninit(client->schedule);
142
143   silc_client_protocols_unregister();
144   silc_client_commands_unregister(client);
145
146   SILC_LOG_DEBUG(("Client stopped"));
147 }
148
149 /* Runs the client. This starts the scheduler from the utility library.
150    When this functions returns the execution of the appliation is over. */
151
152 void silc_client_run(SilcClient client)
153 {
154   SILC_LOG_DEBUG(("Running client"));
155
156   /* Start the scheduler, the heart of the SILC client. When this returns
157      the program will be terminated. */
158   silc_schedule(client->schedule);
159 }
160
161 /* Runs the client and returns immeadiately. This function is used when
162    the SILC Client object indicated by the `client' is run under some
163    other scheduler, or event loop or main loop.  On GUI applications,
164    for example this may be desired to use to run the client under the
165    GUI application's main loop.  Typically the GUI application would
166    register an idle task that calls this function multiple times in
167    a second to quickly process the SILC specific data. */
168
169 void silc_client_run_one(SilcClient client)
170 {
171   /* Run the scheduler once. */
172   silc_schedule_one(client->schedule, 0);
173 }
174
175 static void silc_client_entry_destructor(SilcIDCache cache,
176                                          SilcIDCacheEntry entry)
177 {
178   silc_free(entry->name);
179 }
180
181 /* Allocates and adds new connection to the client. This adds the allocated
182    connection to the connection table and returns a pointer to it. A client
183    can have multiple connections to multiple servers. Every connection must
184    be added to the client using this function. User data `context' may
185    be sent as argument. This function is normally used only if the 
186    application performed the connecting outside the library. The library
187    however may use this internally. */
188
189 SilcClientConnection
190 silc_client_add_connection(SilcClient client,
191                            SilcClientConnectionParams *params,
192                            char *hostname, int port, void *context)
193 {
194   SilcClientConnection conn;
195   int i;
196
197   SILC_LOG_DEBUG(("Adding new connection to %s:%d", hostname, port));
198
199   conn = silc_calloc(1, sizeof(*conn));
200
201   /* Initialize ID caches */
202   conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT, 
203                                           silc_client_entry_destructor);
204   conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
205   conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
206   conn->client = client;
207   conn->remote_host = strdup(hostname);
208   conn->remote_port = port;
209   conn->context = context;
210   conn->pending_commands = silc_dlist_init();
211   conn->ftp_sessions = silc_dlist_init();
212
213   if (params) {
214     if (params->detach_data)
215       conn->params.detach_data = silc_memdup(params->detach_data,
216                                              params->detach_data_len);
217     conn->params.detach_data_len = params->detach_data_len;
218   }
219
220   /* Add the connection to connections table */
221   for (i = 0; i < client->internal->conns_count; i++)
222     if (client->internal->conns && !client->internal->conns[i]) {
223       client->internal->conns[i] = conn;
224       return conn;
225     }
226
227   client->internal->conns = 
228     silc_realloc(client->internal->conns, sizeof(*client->internal->conns)
229                  * (client->internal->conns_count + 1));
230   client->internal->conns[client->internal->conns_count] = conn;
231   client->internal->conns_count++;
232
233   return conn;
234 }
235
236 /* Removes connection from client. Frees all memory. */
237
238 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
239 {
240   int i;
241
242   SILC_LOG_DEBUG(("Deleting connection %s%d", conn->remote_host,
243                   conn->remote_port));
244
245   for (i = 0; i < client->internal->conns_count; i++)
246     if (client->internal->conns[i] == conn) {
247
248       silc_idcache_free(conn->client_cache);
249       silc_idcache_free(conn->channel_cache);
250       silc_idcache_free(conn->server_cache);
251       if (conn->pending_commands)
252         silc_dlist_uninit(conn->pending_commands);
253       silc_free(conn->remote_host);
254       silc_dlist_uninit(conn->ftp_sessions);
255       silc_free(conn);
256
257       client->internal->conns[i] = NULL;
258     }
259 }
260
261 /* Adds listener socket to the listener sockets table. This function is
262    used to add socket objects that are listeners to the client.  This should
263    not be used to add other connection objects. */
264
265 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
266 {
267   int i;
268
269   if (!client->internal->sockets) {
270     client->internal->sockets = 
271       silc_calloc(1, sizeof(*client->internal->sockets));
272     client->internal->sockets[0] = silc_socket_dup(sock);
273     client->internal->sockets_count = 1;
274     return;
275   }
276
277   for (i = 0; i < client->internal->sockets_count; i++) {
278     if (client->internal->sockets[i] == NULL) {
279       client->internal->sockets[i] = silc_socket_dup(sock);
280       return;
281     }
282   }
283
284   client->internal->sockets = 
285     silc_realloc(client->internal->sockets, 
286                  sizeof(*client->internal->sockets) *
287                  (client->internal->sockets_count + 1));
288   client->internal->sockets[client->internal->sockets_count] = 
289     silc_socket_dup(sock);
290   client->internal->sockets_count++;
291 }
292
293 /* Deletes listener socket from the listener sockets table. */
294
295 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
296 {
297   int i;
298
299   if (!client->internal->sockets)
300     return;
301
302   for (i = 0; i < client->internal->sockets_count; i++) {
303     if (client->internal->sockets[i] == sock) {
304       silc_socket_free(sock);
305       client->internal->sockets[i] = NULL;
306       return;
307     }
308   }
309 }
310
311 static int 
312 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
313 {
314   int sock;
315
316   /* XXX In the future we should give up this non-blocking connect all
317      together and use threads instead. */
318   /* Create connection to server asynchronously */
319   sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
320   if (sock < 0)
321     return -1;
322
323   /* Register task that will receive the async connect and will
324      read the result. */
325   ctx->task = silc_schedule_task_add(ctx->client->schedule, sock, 
326                                      silc_client_connect_to_server_start,
327                                      (void *)ctx, 0, 0, 
328                                      SILC_TASK_FD,
329                                      SILC_TASK_PRI_NORMAL);
330   silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE);
331
332   ctx->sock = sock;
333
334   return sock;
335 }
336
337 /* Connects to remote server. This is the main routine used to connect
338    to SILC server. Returns -1 on error and the created socket otherwise. 
339    The `context' is user context that is saved into the SilcClientConnection
340    that is created after the connection is created. Note that application
341    may handle the connecting process outside the library. If this is the
342    case then this function is not used at all. When the connecting is
343    done the `connect' client operation is called. */
344
345 int silc_client_connect_to_server(SilcClient client,
346                                   SilcClientConnectionParams *params,
347                                   int port, char *host, void *context)
348 {
349   SilcClientInternalConnectContext *ctx;
350   SilcClientConnection conn;
351   int sock;
352
353   SILC_LOG_DEBUG(("Connecting to port %d of server %s",
354                   port, host));
355
356   conn = silc_client_add_connection(client, params, host, port, context);
357
358   client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
359                              "Connecting to port %d of server %s", port, host);
360
361   /* Allocate internal context for connection process. This is
362      needed as we are doing async connecting. */
363   ctx = silc_calloc(1, sizeof(*ctx));
364   ctx->client = client;
365   ctx->conn = conn;
366   ctx->host = strdup(host);
367   ctx->port = port;
368   ctx->tries = 0;
369
370   /* Do the actual connecting process */
371   sock = silc_client_connect_to_server_internal(ctx);
372   if (sock == -1)
373     silc_client_del_connection(client, conn);
374   return sock;
375 }
376
377 /* Socket hostname and IP lookup callback that is called before actually
378    starting the key exchange.  The lookup is called from the function
379    silc_client_start_key_exchange. */
380
381 static void silc_client_start_key_exchange_cb(SilcSocketConnection sock,
382                                               void *context)
383 {
384   SilcClientConnection conn = (SilcClientConnection)context;
385   SilcClient client = conn->client;
386   SilcProtocol protocol;
387   SilcClientKEInternalContext *proto_ctx;
388
389   SILC_LOG_DEBUG(("Start"));
390
391   /* XXX We should most likely use the resolved host name instead of the
392      one user provided for us. */
393   silc_free(conn->sock->hostname);
394   conn->sock->hostname = strdup(conn->remote_host);
395   if (!conn->sock->ip)
396     conn->sock->ip = strdup(conn->remote_host);
397   conn->sock->port = conn->remote_port;
398
399   /* Allocate internal Key Exchange context. This is sent to the
400      protocol as context. */
401   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
402   proto_ctx->client = (void *)client;
403   proto_ctx->sock = silc_socket_dup(conn->sock);
404   proto_ctx->rng = client->rng;
405   proto_ctx->responder = FALSE;
406   proto_ctx->send_packet = silc_client_protocol_ke_send_packet;
407   proto_ctx->verify = silc_client_protocol_ke_verify_key;
408
409   /* Perform key exchange protocol. silc_client_connect_to_server_final
410      will be called after the protocol is finished. */
411   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
412                       &protocol, (void *)proto_ctx,
413                       silc_client_connect_to_server_second);
414   if (!protocol) {
415     client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
416                                "Error: Could not start key exchange protocol");
417     silc_net_close_connection(conn->sock->sock);
418     client->internal->ops->connect(client, conn, SILC_CLIENT_CONN_ERROR);
419     return;
420   }
421   conn->sock->protocol = protocol;
422
423   /* Register the connection for network input and output. This sets
424      that scheduler will listen for incoming packets for this connection 
425      and sets that outgoing packets may be sent to this connection as well.
426      However, this doesn't set the scheduler for outgoing traffic, it will 
427      be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
428      later when outgoing data is available. */
429   context = (void *)client;
430   SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(conn->sock->sock);
431
432   /* Execute the protocol */
433   silc_protocol_execute(protocol, client->schedule, 0, 0);
434 }
435
436 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
437    key material between client and server.  This function can be called
438    directly if application is performing its own connecting and does not
439    use the connecting provided by this library. This function is normally
440    used only if the application performed the connecting outside the library.
441    The library however may use this internally. */
442
443 void silc_client_start_key_exchange(SilcClient client,
444                                     SilcClientConnection conn,
445                                     int fd)
446 {
447   /* Allocate new socket connection object */
448   silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
449
450   /* Sometimes when doing quick reconnects the new socket may be same as
451      the old one and there might be pending stuff for the old socket. 
452      If new one is same then those pending sutff might cause problems.
453      Make sure they do not do that. */
454   silc_schedule_task_del_by_fd(client->schedule, fd);
455
456   conn->nickname = (client->nickname ? strdup(client->nickname) :
457                     strdup(client->username));
458
459   /* Resolve the remote hostname and IP address for our socket connection */
460   silc_socket_host_lookup(conn->sock, FALSE, silc_client_start_key_exchange_cb,
461                           conn, client->schedule);
462 }
463
464 /* Callback called when error has occurred during connecting to the server.
465    The `connect' client operation will be called. */
466
467 SILC_TASK_CALLBACK(silc_client_connect_failure)
468 {
469   SilcClientKEInternalContext *ctx = 
470     (SilcClientKEInternalContext *)context;
471   SilcClient client = (SilcClient)ctx->client;
472
473   client->internal->ops->connect(client, ctx->sock->user_data, 
474                                  SILC_CLIENT_CONN_ERROR);
475   if (ctx->packet)
476     silc_packet_context_free(ctx->packet);
477   silc_free(ctx);
478 }
479
480 /* Start of the connection to the remote server. This is called after
481    succesful TCP/IP connection has been established to the remote host. */
482
483 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
484 {
485   SilcClientInternalConnectContext *ctx =
486     (SilcClientInternalConnectContext *)context;
487   SilcClient client = ctx->client;
488   SilcClientConnection conn = ctx->conn;
489   int opt, opt_len = sizeof(opt);
490
491   SILC_LOG_DEBUG(("Start"));
492
493   /* Check the socket status as it might be in error */
494   silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
495   if (opt != 0) {
496     if (ctx->tries < 2) {
497       /* Connection failed but lets try again */
498       client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
499                                  "Could not connect to server %s: %s",
500                                  ctx->host, strerror(opt));
501       client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
502                                  "Connecting to port %d of server %s resumed", 
503                                  ctx->port, ctx->host);
504
505       /* Unregister old connection try */
506       silc_schedule_unset_listen_fd(client->schedule, fd);
507       silc_net_close_connection(fd);
508       silc_schedule_task_del(client->schedule, ctx->task);
509
510       /* Try again */
511       silc_client_connect_to_server_internal(ctx);
512       ctx->tries++;
513     } else {
514       /* Connection failed and we won't try anymore */
515       client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
516                                  "Could not connect to server %s: %s",
517                                  ctx->host, strerror(opt));
518       silc_schedule_unset_listen_fd(client->schedule, fd);
519       silc_net_close_connection(fd);
520       silc_schedule_task_del(client->schedule, ctx->task);
521       silc_free(ctx);
522
523       /* Notify application of failure */
524       client->internal->ops->connect(client, conn, SILC_CLIENT_CONN_ERROR);
525       silc_client_del_connection(client, conn);
526     }
527     return;
528   }
529
530   silc_schedule_unset_listen_fd(client->schedule, fd);
531   silc_schedule_task_del(client->schedule, ctx->task);
532   silc_free(ctx);
533
534   silc_client_start_key_exchange(client, conn, fd);
535 }
536
537 /* Second part of the connecting to the server. This executed 
538    authentication protocol. */
539
540 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
541 {
542   SilcProtocol protocol = (SilcProtocol)context;
543   SilcClientKEInternalContext *ctx = 
544     (SilcClientKEInternalContext *)protocol->context;
545   SilcClient client = (SilcClient)ctx->client;
546   SilcSocketConnection sock = NULL;
547   SilcClientConnAuthInternalContext *proto_ctx;
548
549   SILC_LOG_DEBUG(("Start"));
550
551   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
552       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
553     /* Error occured during protocol */
554     SILC_LOG_DEBUG(("Error during KE protocol"));
555     silc_protocol_free(protocol);
556     silc_ske_free_key_material(ctx->keymat);
557     if (ctx->ske)
558       silc_ske_free(ctx->ske);
559     if (ctx->dest_id)
560       silc_free(ctx->dest_id);
561     ctx->sock->protocol = NULL;
562     silc_socket_free(ctx->sock);
563
564     /* Notify application of failure */
565     silc_schedule_task_add(client->schedule, ctx->sock->sock,
566                            silc_client_connect_failure, ctx,
567                            0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
568     return;
569   }
570
571   /* We now have the key material as the result of the key exchange
572      protocol. Take the key material into use. Free the raw key material
573      as soon as we've set them into use. */
574   silc_client_protocol_ke_set_keys(ctx->ske, ctx->sock, ctx->keymat,
575                                    ctx->ske->prop->cipher,
576                                    ctx->ske->prop->pkcs,
577                                    ctx->ske->prop->hash,
578                                    ctx->ske->prop->hmac,
579                                    ctx->ske->prop->group,
580                                    ctx->responder);
581   silc_ske_free_key_material(ctx->keymat);
582
583   /* Allocate internal context for the authentication protocol. This
584      is sent as context for the protocol. */
585   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
586   proto_ctx->client = (void *)client;
587   proto_ctx->sock = sock = ctx->sock;
588   proto_ctx->ske = ctx->ske;    /* Save SKE object from previous protocol */
589   proto_ctx->dest_id_type = ctx->dest_id_type;
590   proto_ctx->dest_id = ctx->dest_id;
591
592   /* Free old protocol as it is finished now */
593   silc_protocol_free(protocol);
594   if (ctx->packet)
595     silc_packet_context_free(ctx->packet);
596   silc_free(ctx);
597   sock->protocol = NULL;
598
599   /* Resolve the authentication method to be used in this connection. The
600      completion callback is called after the application has resolved
601      the authentication method. */
602   client->internal->ops->get_auth_method(client, sock->user_data, 
603                                          sock->hostname,
604                                          sock->port, 
605                                          silc_client_resolve_auth_method,
606                                          proto_ctx);
607 }
608
609 /* Authentication method resolving callback. Application calls this function
610    after we've called the client->internal->ops->get_auth_method 
611    client operation to resolve the authentication method. We will continue
612    the executiong of the protocol in this function. */
613
614 void silc_client_resolve_auth_method(bool success,
615                                      SilcProtocolAuthMeth auth_meth,
616                                      const unsigned char *auth_data,
617                                      SilcUInt32 auth_data_len, void *context)
618 {
619   SilcClientConnAuthInternalContext *proto_ctx =
620     (SilcClientConnAuthInternalContext *)context;
621   SilcClient client = (SilcClient)proto_ctx->client;
622
623   if (!success)
624     auth_meth = SILC_AUTH_NONE;
625
626   proto_ctx->auth_meth = auth_meth;
627
628   if (auth_data && auth_data_len) {
629     proto_ctx->auth_data = silc_memdup(auth_data, auth_data_len);
630     proto_ctx->auth_data_len = auth_data_len;
631   }
632
633   /* Allocate the authenteication protocol and execute it. */
634   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
635                       &proto_ctx->sock->protocol, (void *)proto_ctx, 
636                       silc_client_connect_to_server_final);
637
638   /* Execute the protocol */
639   silc_protocol_execute(proto_ctx->sock->protocol, client->schedule, 0, 0);
640 }
641
642 /* Finalizes the connection to the remote SILC server. This is called
643    after authentication protocol has been completed. This send our
644    user information to the server to receive our client ID from
645    server. */
646
647 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
648 {
649   SilcProtocol protocol = (SilcProtocol)context;
650   SilcClientConnAuthInternalContext *ctx = 
651     (SilcClientConnAuthInternalContext *)protocol->context;
652   SilcClient client = (SilcClient)ctx->client;
653   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
654   SilcBuffer packet;
655
656   SILC_LOG_DEBUG(("Start"));
657
658   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
659       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
660     /* Error occured during protocol */
661     SILC_LOG_DEBUG(("Error during authentication protocol"));
662     goto err;
663   }
664
665   if (conn->params.detach_data) {
666     /* Send RESUME_CLIENT packet to the server, which is used to resume
667        old detached session back. */
668     SilcBuffer auth;
669     SilcClientID *old_client_id;
670     unsigned char *old_id;
671     SilcUInt16 old_id_len;
672
673     if (!silc_client_process_detach_data(client, conn, &old_id, &old_id_len))
674       goto err;
675
676     old_client_id = silc_id_str2id(old_id, old_id_len, SILC_ID_CLIENT);
677     if (!old_client_id) {
678       silc_free(old_id);
679       goto err;
680     }
681
682     /* Generate authentication data that server will verify */
683     auth = silc_auth_public_key_auth_generate(client->public_key,
684                                               client->private_key,
685                                               client->rng, conn->hash,
686                                               old_client_id, SILC_ID_CLIENT);
687     if (!auth) {
688       silc_free(old_client_id);
689       silc_free(old_id);
690       goto err;
691     }
692
693     packet = silc_buffer_alloc_size(2 + old_id_len + auth->len);
694     silc_buffer_format(packet,
695                        SILC_STR_UI_SHORT(old_id_len),
696                        SILC_STR_UI_XNSTRING(old_id, old_id_len),
697                        SILC_STR_UI_XNSTRING(auth->data, auth->len),
698                        SILC_STR_END);
699
700     /* Send the packet */
701     silc_client_packet_send(client, ctx->sock, SILC_PACKET_RESUME_CLIENT,
702                             NULL, 0, NULL, NULL, 
703                             packet->data, packet->len, TRUE);
704     silc_buffer_free(packet);
705     silc_buffer_free(auth);
706     silc_free(old_client_id);
707     silc_free(old_id);
708   } else {
709     /* Send NEW_CLIENT packet to the server. We will become registered
710        to the SILC network after sending this packet and we will receive
711        client ID from the server. */
712     packet = silc_buffer_alloc(2 + 2 + strlen(client->username) + 
713                                strlen(client->realname));
714     silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
715     silc_buffer_format(packet,
716                        SILC_STR_UI_SHORT(strlen(client->username)),
717                        SILC_STR_UI_XNSTRING(client->username,
718                                             strlen(client->username)),
719                        SILC_STR_UI_SHORT(strlen(client->realname)),
720                        SILC_STR_UI_XNSTRING(client->realname,
721                                             strlen(client->realname)),
722                        SILC_STR_END);
723
724     /* Send the packet */
725     silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
726                             NULL, 0, NULL, NULL, 
727                             packet->data, packet->len, TRUE);
728     silc_buffer_free(packet);
729   }
730
731   /* Save remote ID. */
732   conn->remote_id = ctx->dest_id;
733   conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
734   conn->remote_id_data_len = silc_id_get_len(ctx->dest_id, SILC_ID_SERVER);
735
736   /* Register re-key timeout */
737   conn->rekey->timeout = client->internal->params->rekey_secs;
738   conn->rekey->context = (void *)client;
739   silc_schedule_task_add(client->schedule, conn->sock->sock, 
740                          silc_client_rekey_callback,
741                          (void *)conn->sock, conn->rekey->timeout, 0,
742                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
743
744   silc_protocol_free(protocol);
745   silc_free(ctx->auth_data);
746   if (ctx->ske)
747     silc_ske_free(ctx->ske);
748   silc_socket_free(ctx->sock);
749   silc_free(ctx);
750   conn->sock->protocol = NULL;
751   return;
752
753  err:
754   silc_protocol_free(protocol);
755   silc_free(ctx->auth_data);
756   silc_free(ctx->dest_id);
757   if (ctx->ske)
758     silc_ske_free(ctx->ske);
759   conn->sock->protocol = NULL;
760   silc_socket_free(ctx->sock);
761
762   /* Notify application of failure */
763   silc_schedule_task_add(client->schedule, ctx->sock->sock,
764                          silc_client_connect_failure, ctx,
765                          0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
766 }
767
768 /* Internal routine that sends packet or marks packet to be sent. This
769    is used directly only in special cases. Normal cases should use
770    silc_server_packet_send. Returns < 0 on error. */
771
772 int silc_client_packet_send_real(SilcClient client,
773                                  SilcSocketConnection sock,
774                                  bool force_send)
775 {
776   int ret;
777
778   /* If rekey protocol is active we must assure that all packets are
779      sent through packet queue. */
780   if (SILC_CLIENT_IS_REKEY(sock))
781     force_send = FALSE;
782
783   /* If outbound data is already pending do not force send */
784   if (SILC_IS_OUTBUF_PENDING(sock))
785     force_send = FALSE;
786
787   /* Send the packet */
788   ret = silc_packet_send(sock, force_send);
789   if (ret != -2)
790     return ret;
791
792   /* Mark that there is some outgoing data available for this connection. 
793      This call sets the connection both for input and output (the input
794      is set always and this call keeps the input setting, actually). 
795      Actual data sending is performed by silc_client_packet_process. */
796   SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
797
798   /* Mark to socket that data is pending in outgoing buffer. This flag
799      is needed if new data is added to the buffer before the earlier
800      put data is sent to the network. */
801   SILC_SET_OUTBUF_PENDING(sock);
802
803   return 0;
804 }
805
806 /* Packet processing callback. This is used to send and receive packets
807    from network. This is generic task. */
808
809 SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
810 {
811   SilcClient client = (SilcClient)context;
812   SilcSocketConnection sock = NULL;
813   SilcClientConnection conn;
814   int ret;
815
816   SILC_LOG_DEBUG(("Processing packet"));
817
818   SILC_CLIENT_GET_SOCK(client, fd, sock);
819   if (sock == NULL)
820     return;
821
822   conn = (SilcClientConnection)sock->user_data;
823
824   /* Packet sending */
825   if (type == SILC_TASK_WRITE) {
826     /* Do not send data to disconnected connection */
827     if (SILC_IS_DISCONNECTED(sock))
828       return;
829
830     ret = silc_packet_send(sock, TRUE);
831
832     /* If returned -2 could not write to connection now, will do
833        it later. */
834     if (ret == -2)
835       return;
836
837     /* Error */
838     if (ret == -1)
839       return;
840     
841     /* The packet has been sent and now it is time to set the connection
842        back to only for input. When there is again some outgoing data 
843        available for this connection it will be set for output as well. 
844        This call clears the output setting and sets it only for input. */
845     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
846     SILC_UNSET_OUTBUF_PENDING(sock);
847
848     silc_buffer_clear(sock->outbuf);
849     return;
850   }
851
852   /* Packet receiving */
853   if (type == SILC_TASK_READ) {
854     /* Read data from network */
855     ret = silc_packet_receive(sock);
856     if (ret < 0)
857       return;
858     
859     /* EOF */
860     if (ret == 0) {
861       SILC_LOG_DEBUG(("Read EOF"));
862
863       /* If connection is disconnecting already we will finally
864          close the connection */
865       if (SILC_IS_DISCONNECTING(sock)) {
866         if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
867           client->internal->ops->disconnect(client, conn);
868         silc_client_close_connection_real(client, sock, conn);
869         return;
870       }
871       
872       SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
873       if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
874         client->internal->ops->disconnect(client, conn);
875       silc_client_close_connection_real(client, sock, conn);
876       return;
877     }
878
879     /* Process the packet. This will call the parser that will then
880        decrypt and parse the packet. */
881     if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
882       silc_packet_receive_process(sock, FALSE, conn->receive_key, 
883                                   conn->hmac_receive, conn->psn_receive,
884                                   silc_client_packet_parse, client);
885     else
886       silc_packet_receive_process(sock, FALSE, NULL, NULL, 0, 
887                                   silc_client_packet_parse, client);
888   }
889 }
890
891 /* Parser callback called by silc_packet_receive_process. Thie merely
892    registers timeout that will handle the actual parsing when appropriate. */
893
894 static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
895                                      void *context)
896 {
897   SilcClient client = (SilcClient)context;
898   SilcSocketConnection sock = parser_context->sock;
899   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
900   SilcPacketContext *packet = parser_context->packet;
901   SilcPacketType ret;
902
903   if (conn && conn->hmac_receive && conn->sock == sock)
904     conn->psn_receive = parser_context->packet->sequence + 1;
905
906   /* Parse the packet immediately */
907   if (parser_context->normal)
908     ret = silc_packet_parse(packet, conn->receive_key);
909   else
910     ret = silc_packet_parse_special(packet, conn->receive_key);
911
912   if (ret == SILC_PACKET_NONE) {
913     silc_packet_context_free(packet);
914     silc_free(parser_context);
915     return FALSE;
916   }
917   
918   /* If protocol for this connection is key exchange or rekey then we'll
919      process all packets synchronously, since there might be packets in
920      queue that we are not able to decrypt without first processing the
921      packets before them. */
922   if ((ret == SILC_PACKET_REKEY || ret == SILC_PACKET_REKEY_DONE) ||
923       (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     /* Parse the incoming packet type */
928     silc_client_packet_parse_type(client, sock, packet);
929     silc_packet_context_free(packet);
930     silc_free(parser_context);
931
932     /* Reprocess the buffer since we'll return FALSE. This is because
933        the `conn->receive_key' might have become valid by processing
934        the previous packet */
935     if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
936       silc_packet_receive_process(sock, FALSE, conn->receive_key, 
937                                   conn->hmac_receive, conn->psn_receive,
938                                   silc_client_packet_parse, client);
939     else
940       silc_packet_receive_process(sock, FALSE, NULL, NULL, 0, 
941                                   silc_client_packet_parse, client);
942     
943     return FALSE;
944   }
945
946   /* Parse the incoming packet type */
947   silc_client_packet_parse_type(client, sock, packet);
948   silc_packet_context_free(packet);
949   silc_free(parser_context);
950   return TRUE;
951 }
952
953 /* Parses the packet type and calls what ever routines the packet type
954    requires. This is done for all incoming packets. */
955
956 void silc_client_packet_parse_type(SilcClient client, 
957                                    SilcSocketConnection sock,
958                                    SilcPacketContext *packet)
959 {
960   SilcBuffer buffer = packet->buffer;
961   SilcPacketType type = packet->type;
962
963   SILC_LOG_DEBUG(("Parsing packet type %d", type));
964
965   /* Parse the packet type */
966   switch(type) {
967   case SILC_PACKET_DISCONNECT:
968     silc_client_disconnected_by_server(client, sock, buffer);
969     break;
970   case SILC_PACKET_SUCCESS:
971     /*
972      * Success received for something. For now we can have only
973      * one protocol for connection executing at once hence this
974      * success message is for whatever protocol is executing currently.
975      */
976     if (sock->protocol)
977       silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
978     break;
979   case SILC_PACKET_FAILURE:
980     /*
981      * Failure received for some protocol. Set the protocol state to 
982      * error and call the protocol callback. This fill cause error on
983      * protocol and it will call the final callback.
984      */
985     silc_client_process_failure(client, sock, packet);
986     break;
987   case SILC_PACKET_REJECT:
988     break;
989
990   case SILC_PACKET_NOTIFY:
991     /*
992      * Received notify message 
993      */
994     silc_client_notify_by_server(client, sock, packet);
995     break;
996
997   case SILC_PACKET_ERROR:
998     /*
999      * Received error message
1000      */
1001     silc_client_error_by_server(client, sock, buffer);
1002     break;
1003
1004   case SILC_PACKET_CHANNEL_MESSAGE:
1005     /*
1006      * Received message to (from, actually) a channel
1007      */
1008     silc_client_channel_message(client, sock, packet);
1009     break;
1010   case SILC_PACKET_CHANNEL_KEY:
1011     /*
1012      * Received key for a channel. By receiving this key the client will be
1013      * able to talk to the channel it has just joined. This can also be
1014      * a new key for existing channel as keys expire peridiocally.
1015      */
1016     silc_client_receive_channel_key(client, sock, buffer);
1017     break;
1018
1019   case SILC_PACKET_PRIVATE_MESSAGE:
1020     /*
1021      * Received private message
1022      */
1023     silc_client_private_message(client, sock, packet);
1024     break;
1025   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
1026     /*
1027      * Received private message key
1028      */
1029     break;
1030
1031   case SILC_PACKET_COMMAND_REPLY:
1032     /*
1033      * Recived reply for a command
1034      */
1035     silc_client_command_reply_process(client, sock, packet);
1036     break;
1037
1038   case SILC_PACKET_KEY_EXCHANGE:
1039     if (sock->protocol && sock->protocol->protocol && 
1040         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
1041       SilcClientKEInternalContext *proto_ctx = 
1042         (SilcClientKEInternalContext *)sock->protocol->context;
1043
1044       proto_ctx->packet = silc_packet_context_dup(packet);
1045       proto_ctx->dest_id_type = packet->src_id_type;
1046       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1047                                           packet->src_id_type);
1048       if (!proto_ctx->dest_id)
1049         break;
1050
1051       /* Let the protocol handle the packet */
1052       silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1053     } else {
1054       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
1055                       "protocol active, packet dropped."));
1056     }
1057     break;
1058
1059   case SILC_PACKET_KEY_EXCHANGE_1:
1060     if (sock->protocol && sock->protocol->protocol && 
1061         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1062          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1063
1064       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1065         SilcClientRekeyInternalContext *proto_ctx = 
1066           (SilcClientRekeyInternalContext *)sock->protocol->context;
1067         
1068         if (proto_ctx->packet)
1069           silc_packet_context_free(proto_ctx->packet);
1070         
1071         proto_ctx->packet = silc_packet_context_dup(packet);
1072
1073         /* Let the protocol handle the packet */
1074         silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1075       } else {
1076         SilcClientKEInternalContext *proto_ctx = 
1077           (SilcClientKEInternalContext *)sock->protocol->context;
1078         
1079         if (proto_ctx->packet)
1080           silc_packet_context_free(proto_ctx->packet);
1081         
1082         proto_ctx->packet = silc_packet_context_dup(packet);
1083         proto_ctx->dest_id_type = packet->src_id_type;
1084         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1085                                             packet->src_id_type);
1086         if (!proto_ctx->dest_id)
1087           break;
1088         
1089         /* Let the protocol handle the packet */
1090         silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1091       }
1092     } else {
1093       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
1094                       "protocol active, packet dropped."));
1095     }
1096     break;
1097   case SILC_PACKET_KEY_EXCHANGE_2:
1098     if (sock->protocol && sock->protocol->protocol && 
1099         (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1100          sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
1101
1102       if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1103         SilcClientRekeyInternalContext *proto_ctx = 
1104           (SilcClientRekeyInternalContext *)sock->protocol->context;
1105         
1106         if (proto_ctx->packet)
1107           silc_packet_context_free(proto_ctx->packet);
1108         
1109         proto_ctx->packet = silc_packet_context_dup(packet);
1110
1111         /* Let the protocol handle the packet */
1112         silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1113       } else {
1114         SilcClientKEInternalContext *proto_ctx = 
1115           (SilcClientKEInternalContext *)sock->protocol->context;
1116         
1117         if (proto_ctx->packet)
1118           silc_packet_context_free(proto_ctx->packet);
1119         if (proto_ctx->dest_id)
1120           silc_free(proto_ctx->dest_id);
1121         proto_ctx->packet = silc_packet_context_dup(packet);
1122         proto_ctx->dest_id_type = packet->src_id_type;
1123         proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
1124                                             packet->src_id_type);
1125         if (!proto_ctx->dest_id)
1126           break;
1127         
1128         /* Let the protocol handle the packet */
1129         silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1130       }
1131     } else {
1132       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
1133                       "protocol active, packet dropped."));
1134     }
1135     break;
1136
1137   case SILC_PACKET_NEW_ID:
1138     {
1139       /*
1140        * Received new ID from server. This packet is received at
1141        * the connection to the server.  New ID is also received when 
1142        * user changes nickname but in that case the new ID is received
1143        * as command reply and not as this packet type.
1144        */
1145       SilcIDPayload idp;
1146
1147       idp = silc_id_payload_parse(buffer->data, buffer->len);
1148       if (!idp)
1149         break;
1150       if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
1151         break;
1152
1153       silc_client_receive_new_id(client, sock, idp);
1154       silc_id_payload_free(idp);
1155       break;
1156     }
1157
1158   case SILC_PACKET_HEARTBEAT:
1159     /*
1160      * Received heartbeat packet
1161      */
1162     SILC_LOG_DEBUG(("Heartbeat packet"));
1163     break;
1164
1165   case SILC_PACKET_KEY_AGREEMENT:
1166     /*
1167      * Received key agreement packet
1168      */
1169     SILC_LOG_DEBUG(("Key agreement packet"));
1170     silc_client_key_agreement(client, sock, packet);
1171     break;
1172
1173   case SILC_PACKET_REKEY:
1174     SILC_LOG_DEBUG(("Re-key packet"));
1175     /* We ignore this for now */
1176     break;
1177
1178   case SILC_PACKET_REKEY_DONE:
1179     SILC_LOG_DEBUG(("Re-key done packet"));
1180
1181     if (sock->protocol && sock->protocol->protocol && 
1182         sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
1183
1184       SilcClientRekeyInternalContext *proto_ctx = 
1185         (SilcClientRekeyInternalContext *)sock->protocol->context;
1186       
1187       if (proto_ctx->packet)
1188         silc_packet_context_free(proto_ctx->packet);
1189       
1190       proto_ctx->packet = silc_packet_context_dup(packet);
1191
1192       /* Let the protocol handle the packet */
1193       if (proto_ctx->responder == FALSE)
1194         silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
1195       else
1196         /* Let the protocol handle the packet */
1197         silc_protocol_execute(sock->protocol, client->schedule, 
1198                               0, 100000);
1199     } else {
1200       SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
1201                       "protocol active, packet dropped."));
1202     }
1203     break;
1204
1205   case SILC_PACKET_CONNECTION_AUTH_REQUEST:
1206     /*
1207      * Reveived reply to our connection authentication method request
1208      * packet. This is used to resolve the authentication method for the
1209      * current session from the server if the client does not know it.
1210      */
1211     silc_client_connection_auth_request(client, sock, packet);
1212     break;
1213
1214   case SILC_PACKET_FTP:
1215     /* Received file transfer packet. */
1216     silc_client_ftp(client, sock, packet);
1217     break;
1218
1219   default:
1220     SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
1221     break;
1222   }
1223 }
1224
1225 /* Sends packet. This doesn't actually send the packet instead it assembles
1226    it and marks it to be sent. However, if force_send is TRUE the packet
1227    is sent immediately. if dst_id, cipher and hmac are NULL those parameters
1228    will be derived from sock argument. Otherwise the valid arguments sent
1229    are used. */
1230
1231 void silc_client_packet_send(SilcClient client, 
1232                              SilcSocketConnection sock,
1233                              SilcPacketType type, 
1234                              void *dst_id,
1235                              SilcIdType dst_id_type,
1236                              SilcCipher cipher,
1237                              SilcHmac hmac,
1238                              unsigned char *data, 
1239                              SilcUInt32 data_len, 
1240                              int force_send)
1241 {
1242   SilcPacketContext packetdata;
1243   const SilcBufferStruct packet;
1244   int block_len;
1245   SilcUInt32 sequence = 0;
1246
1247   if (!sock)
1248     return;
1249
1250   SILC_LOG_DEBUG(("Sending packet, type %d", type));
1251
1252   /* Get data used in the packet sending, keys and stuff */
1253   if ((!cipher || !hmac || !dst_id) && sock->user_data) {
1254     if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
1255       cipher = ((SilcClientConnection)sock->user_data)->send_key;
1256
1257     if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
1258       hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
1259
1260     if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
1261       dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
1262       dst_id_type = SILC_ID_SERVER;
1263     }
1264
1265     if (hmac)
1266       sequence = ((SilcClientConnection)sock->user_data)->psn_send++;
1267   }
1268
1269   block_len = cipher ? silc_cipher_get_block_len(cipher) : 0;
1270
1271   /* Set the packet context pointers */
1272   packetdata.flags = 0;
1273   packetdata.type = type;
1274   if (sock->user_data && 
1275       ((SilcClientConnection)sock->user_data)->local_id_data) {
1276     packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
1277     packetdata.src_id_len = 
1278       silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
1279                       SILC_ID_CLIENT);
1280   } else { 
1281     packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
1282     packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1283   }
1284   packetdata.src_id_type = SILC_ID_CLIENT;
1285   if (dst_id) {
1286     packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
1287     packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
1288     packetdata.dst_id_type = dst_id_type;
1289   } else {
1290     packetdata.dst_id = NULL;
1291     packetdata.dst_id_len = 0;
1292     packetdata.dst_id_type = SILC_ID_NONE;
1293   }
1294   data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1295                                             packetdata.src_id_len + 
1296                                             packetdata.dst_id_len));
1297   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
1298     packetdata.src_id_len + packetdata.dst_id_len;
1299   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
1300
1301   /* Create the outgoing packet */
1302   if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock, 
1303                             data, data_len, (const SilcBuffer)&packet)) {
1304     SILC_LOG_ERROR(("Error assembling packet"));
1305     return;
1306   }
1307
1308   /* Encrypt the packet */
1309   if (cipher)
1310     silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet, 
1311                         packet.len);
1312
1313   SILC_LOG_HEXDUMP(("Packet (%d), len %d", sequence, packet.len),
1314                    packet.data, packet.len);
1315
1316   /* Now actually send the packet */
1317   silc_client_packet_send_real(client, sock, force_send);
1318 }
1319
1320 void silc_client_packet_queue_purge(SilcClient client,
1321                                     SilcSocketConnection sock)
1322 {
1323   if (sock && SILC_IS_OUTBUF_PENDING(sock) && 
1324       (SILC_IS_DISCONNECTED(sock) == FALSE)) {
1325     silc_packet_send(sock, TRUE);
1326     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
1327     SILC_UNSET_OUTBUF_PENDING(sock);
1328     silc_buffer_clear(sock->outbuf);
1329   }
1330 }
1331
1332 /* Closes connection to remote end. Free's all allocated data except
1333    for some information such as nickname etc. that are valid at all time. 
1334    If the `sock' is NULL then the conn->sock will be used.  If `sock' is
1335    provided it will be checked whether the sock and `conn->sock' are the
1336    same (they can be different, ie. a socket can use `conn' as its
1337    connection but `conn->sock' might be actually a different connection
1338    than the `sock'). */
1339
1340 void silc_client_close_connection_real(SilcClient client,
1341                                        SilcSocketConnection sock,
1342                                        SilcClientConnection conn)
1343 {
1344   int del = FALSE;
1345
1346   SILC_LOG_DEBUG(("Start"));
1347
1348   if (!sock && !conn)
1349     return;
1350
1351   if (!sock || (sock && conn->sock == sock))
1352     del = TRUE;
1353   if (!sock)
1354     sock = conn->sock;
1355
1356   /* We won't listen for this connection anymore */
1357   silc_schedule_unset_listen_fd(client->schedule, sock->sock);
1358
1359   /* Unregister all tasks */
1360   silc_schedule_task_del_by_fd(client->schedule, sock->sock);
1361
1362   /* Close the actual connection */
1363   silc_net_close_connection(sock->sock);
1364
1365   /* Cancel any active protocol */
1366   if (sock->protocol) {
1367     if (sock->protocol->protocol->type == 
1368         SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
1369         sock->protocol->protocol->type == 
1370         SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
1371       sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1372       silc_protocol_execute_final(sock->protocol, client->schedule);
1373       /* The application will recall this function with these protocols
1374          (the ops->connect client operation). */
1375       return;
1376     } else {
1377       sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
1378       silc_protocol_execute_final(sock->protocol, client->schedule);
1379       sock->protocol = NULL;
1380     }
1381   }
1382
1383   /* Free everything */
1384   if (del && sock->user_data) {
1385     /* Free all cache entries */
1386     SilcIDCacheList list;
1387     SilcIDCacheEntry entry;
1388     SilcClientCommandPending *r;
1389     bool ret;
1390
1391     if (silc_idcache_get_all(conn->client_cache, &list)) {
1392       ret = silc_idcache_list_first(list, &entry);
1393       while (ret) {
1394         silc_client_del_client(client, conn, entry->context);
1395         ret = silc_idcache_list_next(list, &entry);
1396       }
1397       silc_idcache_list_free(list);
1398     }
1399
1400     if (silc_idcache_get_all(conn->channel_cache, &list)) {
1401       ret = silc_idcache_list_first(list, &entry);
1402       while (ret) {
1403         silc_client_del_channel(client, conn, entry->context);
1404         ret = silc_idcache_list_next(list, &entry);
1405       }
1406       silc_idcache_list_free(list);
1407     }
1408
1409     if (silc_idcache_get_all(conn->server_cache, &list)) {
1410       ret = silc_idcache_list_first(list, &entry);
1411       while (ret) {
1412         silc_client_del_server(client, conn, entry->context);
1413         ret = silc_idcache_list_next(list, &entry);
1414       }
1415       silc_idcache_list_free(list);
1416     }
1417
1418     /* Clear ID caches */
1419     if (conn->client_cache)
1420       silc_idcache_free(conn->client_cache);
1421     if (conn->channel_cache)
1422       silc_idcache_free(conn->channel_cache);
1423     if (conn->server_cache)
1424       silc_idcache_free(conn->server_cache);
1425
1426     /* Free data (my ID is freed in above silc_client_del_client).
1427        conn->nickname is freed when freeing the local_entry->nickname. */
1428     if (conn->remote_host)
1429       silc_free(conn->remote_host);
1430     if (conn->local_id_data)
1431       silc_free(conn->local_id_data);
1432     if (conn->send_key)
1433       silc_cipher_free(conn->send_key);
1434     if (conn->receive_key)
1435       silc_cipher_free(conn->receive_key);
1436     if (conn->hmac_send)
1437       silc_hmac_free(conn->hmac_send);
1438     if (conn->hmac_receive)
1439       silc_hmac_free(conn->hmac_receive);
1440     if (conn->rekey)
1441       silc_free(conn->rekey);
1442
1443     if (conn->active_session) {
1444       sock->user_data = NULL;
1445       silc_client_ftp_session_free(conn->active_session);
1446       conn->active_session = NULL;
1447     }
1448
1449     silc_client_ftp_free_sessions(client, conn);
1450
1451     silc_dlist_start(conn->pending_commands);
1452     while ((r = silc_dlist_get(conn->pending_commands)) != SILC_LIST_END)
1453       silc_dlist_del(conn->pending_commands, r);
1454     if (conn->pending_commands)
1455       silc_dlist_uninit(conn->pending_commands);
1456
1457     memset(conn, 0, sizeof(*conn));
1458     silc_client_del_connection(client, conn);
1459   }
1460
1461   silc_socket_free(sock);
1462 }
1463
1464 /* Closes the connection to the remote end */
1465
1466 void silc_client_close_connection(SilcClient client,
1467                                   SilcClientConnection conn)
1468 {
1469   silc_client_close_connection_real(client, NULL, conn);
1470 }
1471
1472 /* Called when we receive disconnection packet from server. This 
1473    closes our end properly and displays the reason of the disconnection
1474    on the screen. */
1475
1476 SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later)
1477 {
1478   SilcClient client = (SilcClient)context;
1479   SilcClientConnection conn;
1480   SilcSocketConnection sock;
1481
1482   SILC_CLIENT_GET_SOCK(client, fd, sock);
1483   if (sock == NULL)
1484     return;
1485
1486   conn = (SilcClientConnection)sock->user_data;
1487   if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1488     client->internal->ops->disconnect(client, conn);
1489
1490   silc_client_close_connection_real(client, sock, sock->user_data);
1491 }
1492
1493 /* Called when we receive disconnection packet from server. This 
1494    closes our end properly and displays the reason of the disconnection
1495    on the screen. */
1496
1497 void silc_client_disconnected_by_server(SilcClient client,
1498                                         SilcSocketConnection sock,
1499                                         SilcBuffer packet)
1500 {
1501   SilcStatus status;
1502   char *message = NULL;
1503
1504   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1505
1506   if (packet->len < 1)
1507     return;
1508
1509   status = (SilcStatus)packet->data[0];
1510
1511   if (packet->len > 1 &&
1512       silc_utf8_valid(packet->data + 1, packet->len - 1))
1513     message = silc_memdup(packet->data + 1, packet->len - 1);
1514
1515   client->internal->ops->say(client, sock->user_data, 
1516                              SILC_CLIENT_MESSAGE_AUDIT, 
1517                              "Server closed connection: %s (%d) %s",
1518                              silc_get_status_message(status), status,
1519                              message ? message : "");
1520   silc_free(message);
1521
1522   SILC_SET_DISCONNECTED(sock);
1523
1524   /* Close connection through scheduler. */
1525   silc_schedule_task_add(client->schedule, sock->sock, 
1526                          silc_client_disconnected_by_server_later,
1527                          client, 0, 1, SILC_TASK_TIMEOUT, 
1528                          SILC_TASK_PRI_NORMAL);
1529 }
1530
1531 /* Received error message from server. Display it on the screen. 
1532    We don't take any action what so ever of the error message. */
1533
1534 void silc_client_error_by_server(SilcClient client,
1535                                  SilcSocketConnection sock,
1536                                  SilcBuffer message)
1537 {
1538   char *msg;
1539
1540   msg = silc_memdup(message->data, message->len);
1541   client->internal->ops->say(client, sock->user_data, 
1542                              SILC_CLIENT_MESSAGE_AUDIT, msg);
1543   silc_free(msg);
1544 }
1545
1546 /* Auto-nicking callback to send NICK command to server. */
1547
1548 SILC_TASK_CALLBACK(silc_client_send_auto_nick)
1549 {
1550   SilcClientConnection conn = (SilcClientConnection)context;
1551   SilcClient client = conn->client;
1552
1553   silc_client_command_send(client, conn, SILC_COMMAND_NICK, 
1554                            ++conn->cmd_ident, 1, 1, 
1555                            client->nickname, strlen(client->nickname));
1556 }
1557
1558 /* Client session resuming callback.  If the session was resumed
1559    this callback is called after the resuming is completed.  This
1560    will call the `connect' client operation to the application
1561    since it has not been called yet. */
1562
1563 static void silc_client_resume_session_cb(SilcClient client,
1564                                           SilcClientConnection conn,
1565                                           bool success,
1566                                           void *context)
1567 {
1568   SilcBuffer sidp;
1569
1570   /* Notify application that connection is created to server */
1571   client->internal->ops->connect(client, conn, success ?
1572                                  SILC_CLIENT_CONN_SUCCESS_RESUME :
1573                                  SILC_CLIENT_CONN_ERROR);
1574
1575   if (success) {
1576     /* Issue INFO command to fetch the real server name and server
1577        information and other stuff. */
1578     silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1579                                  silc_client_command_reply_info_i, 0, 
1580                                  ++conn->cmd_ident);
1581     sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1582     silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1583                              conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1584     silc_buffer_free(sidp);
1585   }
1586 }
1587
1588 /* Processes the received new Client ID from server. Old Client ID is
1589    deleted from cache and new one is added. */
1590
1591 void silc_client_receive_new_id(SilcClient client,
1592                                 SilcSocketConnection sock,
1593                                 SilcIDPayload idp)
1594 {
1595   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1596   int connecting = FALSE;
1597   SilcClientID *client_id = silc_id_payload_get_id(idp);
1598
1599   if (!conn->local_entry)
1600     connecting = TRUE;
1601
1602   /* Delete old ID from ID cache */
1603   if (conn->local_id) {
1604     /* Check whether they are different */
1605     if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) {
1606       silc_free(client_id);
1607       return;
1608     }
1609
1610     silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1611     silc_free(conn->local_id);
1612   }
1613   
1614   /* Save the new ID */
1615
1616   if (conn->local_id_data)
1617     silc_free(conn->local_id_data);
1618
1619   conn->local_id = client_id;
1620   conn->local_id_data = silc_id_payload_get_data(idp);
1621   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1622
1623   if (!conn->local_entry)
1624     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1625
1626   conn->local_entry->nickname = conn->nickname;
1627   if (!conn->local_entry->username)
1628     conn->local_entry->username = strdup(client->username);
1629   if (!conn->local_entry->hostname)
1630     conn->local_entry->hostname = strdup(client->hostname);
1631   if (!conn->local_entry->server)
1632     conn->local_entry->server = strdup(conn->remote_host);
1633   conn->local_entry->id = conn->local_id;
1634   conn->local_entry->valid = TRUE;
1635   if (!conn->local_entry->channels)
1636     conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr, 
1637                                                         NULL, NULL,
1638                                                         NULL, NULL, NULL, 
1639                                                         TRUE);
1640
1641   /* Put it to the ID cache */
1642   silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id, 
1643                    (void *)conn->local_entry, 0, NULL);
1644
1645   if (connecting) {
1646     if (!conn->params.detach_data) {
1647       SilcBuffer sidp;
1648
1649       /* Send NICK command if the nickname was set by the application (and is
1650          not same as the username). Send this with little timeout. */
1651       if (client->nickname && strcmp(client->nickname, client->username))
1652         silc_schedule_task_add(client->schedule, 0,
1653                                silc_client_send_auto_nick, conn,
1654                                1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1655
1656       /* Notify application of successful connection. We do it here now that
1657          we've received the Client ID and are allowed to send traffic. */
1658       client->internal->ops->connect(client, conn, SILC_CLIENT_CONN_SUCCESS);
1659
1660       /* Issue INFO command to fetch the real server name and server
1661          information and other stuff. */
1662       silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1663                                    silc_client_command_reply_info_i, 0, 
1664                                    ++conn->cmd_ident);
1665       sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1666       silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1667                                conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1668       silc_buffer_free(sidp);
1669     } else {
1670       /* We are resuming session.  Start resolving informations from the
1671          server we need to set the client libary in the state before
1672          detaching the session.  The connect client operation is called
1673          after this is successfully completed */
1674       silc_client_resume_session(client, conn, silc_client_resume_session_cb,
1675                                  NULL);
1676     }
1677   }
1678 }
1679
1680 /* Removes a client entry from all channels it has joined. */
1681
1682 void silc_client_remove_from_channels(SilcClient client,
1683                                       SilcClientConnection conn,
1684                                       SilcClientEntry client_entry)
1685 {
1686   SilcHashTableList htl;
1687   SilcChannelUser chu;
1688
1689   silc_hash_table_list(client_entry->channels, &htl);
1690   while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
1691     silc_hash_table_del(chu->client->channels, chu->channel);
1692     silc_hash_table_del(chu->channel->user_list, chu->client);
1693     silc_free(chu);
1694   }
1695
1696   silc_hash_table_list_reset(&htl);
1697 }
1698
1699 /* Replaces `old' client entries from all channels to `new' client entry.
1700    This can be called for example when nickname changes and old ID entry
1701    is replaced from ID cache with the new one. If the old ID entry is only
1702    updated, then this fucntion needs not to be called. */
1703
1704 void silc_client_replace_from_channels(SilcClient client, 
1705                                        SilcClientConnection conn,
1706                                        SilcClientEntry old,
1707                                        SilcClientEntry new)
1708 {
1709   SilcHashTableList htl;
1710   SilcChannelUser chu;
1711
1712   silc_hash_table_list(old->channels, &htl);
1713   while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
1714     /* Replace client entry */
1715     silc_hash_table_del(chu->client->channels, chu->channel);
1716     silc_hash_table_del(chu->channel->user_list, chu->client);
1717     
1718     chu->client = new;
1719     silc_hash_table_add(chu->channel->user_list, chu->client, chu);
1720     silc_hash_table_add(chu->client->channels, chu->channel, chu);
1721   }
1722   silc_hash_table_list_reset(&htl);
1723 }
1724
1725 /* Registers failure timeout to process the received failure packet
1726    with timeout. */
1727
1728 void silc_client_process_failure(SilcClient client,
1729                                  SilcSocketConnection sock,
1730                                  SilcPacketContext *packet)
1731 {
1732   SilcUInt32 failure = 0;
1733
1734   if (sock->protocol) {
1735     if (packet->buffer->len >= 4)
1736       SILC_GET32_MSB(failure, packet->buffer->data);
1737
1738     /* Notify application */
1739     client->internal->ops->failure(client, sock->user_data, sock->protocol,
1740                                    (void *)failure);
1741   }
1742 }
1743
1744 /* A timeout callback for the re-key. We will be the initiator of the
1745    re-key protocol. */
1746
1747 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1748 {
1749   SilcSocketConnection sock = (SilcSocketConnection)context;
1750   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1751   SilcClient client = (SilcClient)conn->rekey->context;
1752   SilcProtocol protocol;
1753   SilcClientRekeyInternalContext *proto_ctx;
1754
1755   SILC_LOG_DEBUG(("Start"));
1756
1757   /* Allocate internal protocol context. This is sent as context
1758      to the protocol. */
1759   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1760   proto_ctx->client = (void *)client;
1761   proto_ctx->sock = silc_socket_dup(sock);
1762   proto_ctx->responder = FALSE;
1763   proto_ctx->pfs = conn->rekey->pfs;
1764       
1765   /* Perform rekey protocol. Will call the final callback after the
1766      protocol is over. */
1767   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY, 
1768                       &protocol, proto_ctx, silc_client_rekey_final);
1769   sock->protocol = protocol;
1770       
1771   /* Run the protocol */
1772   silc_protocol_execute(protocol, client->schedule, 0, 0);
1773
1774   /* Re-register re-key timeout */
1775   silc_schedule_task_add(client->schedule, sock->sock, 
1776                          silc_client_rekey_callback,
1777                          context, conn->rekey->timeout, 0,
1778                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1779 }
1780
1781 /* The final callback for the REKEY protocol. This will actually take the
1782    new key material into use. */
1783
1784 SILC_TASK_CALLBACK(silc_client_rekey_final)
1785 {
1786   SilcProtocol protocol = (SilcProtocol)context;
1787   SilcClientRekeyInternalContext *ctx =
1788     (SilcClientRekeyInternalContext *)protocol->context;
1789   SilcClient client = (SilcClient)ctx->client;
1790   SilcSocketConnection sock = ctx->sock;
1791
1792   SILC_LOG_DEBUG(("Start"));
1793
1794   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1795       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1796     /* Error occured during protocol */
1797     silc_protocol_cancel(protocol, client->schedule);
1798     silc_protocol_free(protocol);
1799     sock->protocol = NULL;
1800     if (ctx->packet)
1801       silc_packet_context_free(ctx->packet);
1802     if (ctx->ske)
1803       silc_ske_free(ctx->ske);
1804     silc_socket_free(ctx->sock);
1805     silc_free(ctx);
1806     return;
1807   }
1808
1809   /* Purge the outgoing data queue to assure that all rekey packets really
1810      go to the network before we quit the protocol. */
1811   silc_client_packet_queue_purge(client, sock);
1812
1813   /* Cleanup */
1814   silc_protocol_free(protocol);
1815   sock->protocol = NULL;
1816   if (ctx->packet)
1817     silc_packet_context_free(ctx->packet);
1818   if (ctx->ske)
1819     silc_ske_free(ctx->ske);
1820   silc_socket_free(ctx->sock);
1821   silc_free(ctx);
1822 }
1823
1824 /* Processes incoming connection authentication method request packet.
1825    It is a reply to our previously sent request. The packet can be used
1826    to resolve the authentication method for the current session if the
1827    client does not know it beforehand. */
1828
1829 void silc_client_connection_auth_request(SilcClient client,
1830                                          SilcSocketConnection sock,
1831                                          SilcPacketContext *packet)
1832 {
1833   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1834   SilcUInt16 conn_type, auth_meth;
1835   int ret;
1836
1837   /* If we haven't send our request then ignore this one. */
1838   if (!conn->connauth)
1839     return;
1840
1841   /* Parse the payload */
1842   ret = silc_buffer_unformat(packet->buffer,
1843                              SILC_STR_UI_SHORT(&conn_type),
1844                              SILC_STR_UI_SHORT(&auth_meth),
1845                              SILC_STR_END);
1846   if (ret == -1)
1847     auth_meth = SILC_AUTH_NONE;
1848
1849   /* Call the request callback to notify application for received 
1850      authentication method information. */
1851   if (conn->connauth->callback)
1852     (*conn->connauth->callback)(client, conn, auth_meth,
1853                                 conn->connauth->context);
1854
1855   silc_schedule_task_del(client->schedule, conn->connauth->timeout);
1856
1857   silc_free(conn->connauth);
1858   conn->connauth = NULL;
1859 }
1860
1861 /* Timeout task callback called if the server does not reply to our 
1862    connection authentication method request in the specified time interval. */
1863
1864 SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
1865 {
1866   SilcClientConnection conn = (SilcClientConnection)context;
1867   SilcClient client = conn->client;
1868
1869   if (!conn->connauth)
1870     return;
1871
1872   /* Call the request callback to notify application */
1873   if (conn->connauth->callback)
1874     (*conn->connauth->callback)(client, conn, SILC_AUTH_NONE,
1875                                 conn->connauth->context);
1876
1877   silc_free(conn->connauth);
1878   conn->connauth = NULL;
1879 }
1880
1881 /* This function can be used to request the current authentication method
1882    from the server. This may be called when connecting to the server
1883    and the client library requests the authentication data from the
1884    application. If the application does not know the current authentication
1885    method it can request it from the server using this function.
1886    The `callback' with `context' will be called after the server has
1887    replied back with the current authentication method. */
1888
1889 void 
1890 silc_client_request_authentication_method(SilcClient client,
1891                                           SilcClientConnection conn,
1892                                           SilcConnectionAuthRequest callback,
1893                                           void *context)
1894 {
1895   SilcClientConnAuthRequest connauth;
1896   SilcBuffer packet;
1897
1898   connauth = silc_calloc(1, sizeof(*connauth));
1899   connauth->callback = callback;
1900   connauth->context = context;
1901
1902   if (conn->connauth)
1903     silc_free(conn->connauth);
1904
1905   conn->connauth = connauth;
1906
1907   /* Assemble the request packet and send it to the server */
1908   packet = silc_buffer_alloc(4);
1909   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1910   silc_buffer_format(packet,
1911                      SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
1912                      SILC_STR_UI_SHORT(SILC_AUTH_NONE),
1913                      SILC_STR_END);
1914   silc_client_packet_send(client, conn->sock, 
1915                           SILC_PACKET_CONNECTION_AUTH_REQUEST,
1916                           NULL, 0, NULL, NULL, 
1917                           packet->data, packet->len, FALSE);
1918   silc_buffer_free(packet);
1919
1920   /* Register a timeout in case server does not reply anything back. */
1921   connauth->timeout =
1922     silc_schedule_task_add(client->schedule, conn->sock->sock, 
1923                            silc_client_request_authentication_method_timeout,
1924                            conn, 
1925                            client->internal->params->connauth_request_secs, 0,
1926                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1927 }