Use resovled hostname as remote server name instead of one
[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, client);
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   for (i = 0; i < client->internal->conns_count; i++)
243     if (client->internal->conns[i] == conn) {
244
245       silc_idcache_free(conn->client_cache);
246       silc_idcache_free(conn->channel_cache);
247       silc_idcache_free(conn->server_cache);
248       if (conn->pending_commands)
249         silc_dlist_uninit(conn->pending_commands);
250       silc_free(conn->remote_host);
251       if (conn->ftp_sessions)
252         silc_dlist_uninit(conn->ftp_sessions);
253       silc_free(conn);
254
255       client->internal->conns[i] = NULL;
256     }
257 }
258
259 /* Adds listener socket to the listener sockets table. This function is
260    used to add socket objects that are listeners to the client.  This should
261    not be used to add other connection objects. */
262
263 void silc_client_add_socket(SilcClient client, SilcSocketConnection sock)
264 {
265   int i;
266
267   if (!client->internal->sockets) {
268     client->internal->sockets = 
269       silc_calloc(1, sizeof(*client->internal->sockets));
270     client->internal->sockets[0] = silc_socket_dup(sock);
271     client->internal->sockets_count = 1;
272     return;
273   }
274
275   for (i = 0; i < client->internal->sockets_count; i++) {
276     if (client->internal->sockets[i] == NULL) {
277       client->internal->sockets[i] = silc_socket_dup(sock);
278       return;
279     }
280   }
281
282   client->internal->sockets = 
283     silc_realloc(client->internal->sockets, 
284                  sizeof(*client->internal->sockets) *
285                  (client->internal->sockets_count + 1));
286   client->internal->sockets[client->internal->sockets_count] = 
287     silc_socket_dup(sock);
288   client->internal->sockets_count++;
289 }
290
291 /* Deletes listener socket from the listener sockets table. */
292
293 void silc_client_del_socket(SilcClient client, SilcSocketConnection sock)
294 {
295   int i;
296
297   if (!client->internal->sockets)
298     return;
299
300   for (i = 0; i < client->internal->sockets_count; i++) {
301     if (client->internal->sockets[i] == sock) {
302       silc_socket_free(sock);
303       client->internal->sockets[i] = NULL;
304       return;
305     }
306   }
307 }
308
309 static int 
310 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
311 {
312   int sock;
313
314   /* XXX In the future we should give up this non-blocking connect all
315      together and use threads instead. */
316   /* Create connection to server asynchronously */
317   sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
318   if (sock < 0)
319     return -1;
320
321   /* Register task that will receive the async connect and will
322      read the result. */
323   ctx->task = silc_schedule_task_add(ctx->client->schedule, sock, 
324                                      silc_client_connect_to_server_start,
325                                      (void *)ctx, 0, 0, 
326                                      SILC_TASK_FD,
327                                      SILC_TASK_PRI_NORMAL);
328   silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE);
329
330   ctx->sock = sock;
331
332   return sock;
333 }
334
335 /* Connects to remote server. This is the main routine used to connect
336    to SILC server. Returns -1 on error and the created socket otherwise. 
337    The `context' is user context that is saved into the SilcClientConnection
338    that is created after the connection is created. Note that application
339    may handle the connecting process outside the library. If this is the
340    case then this function is not used at all. When the connecting is
341    done the `connect' client operation is called. */
342
343 int silc_client_connect_to_server(SilcClient client,
344                                   SilcClientConnectionParams *params,
345                                   int port, char *host, void *context)
346 {
347   SilcClientInternalConnectContext *ctx;
348   SilcClientConnection conn;
349   int sock;
350
351   SILC_LOG_DEBUG(("Connecting to port %d of server %s",
352                   port, host));
353
354   conn = silc_client_add_connection(client, params, host, port, context);
355
356   client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
357                              "Connecting to port %d of server %s", port, host);
358
359   /* Allocate internal context for connection process. This is
360      needed as we are doing async connecting. */
361   ctx = silc_calloc(1, sizeof(*ctx));
362   ctx->client = client;
363   ctx->conn = conn;
364   ctx->host = strdup(host);
365   ctx->port = port;
366   ctx->tries = 0;
367
368   /* Do the actual connecting process */
369   sock = silc_client_connect_to_server_internal(ctx);
370   if (sock == -1)
371     silc_client_del_connection(client, conn);
372   return sock;
373 }
374
375 /* Socket hostname and IP lookup callback that is called before actually
376    starting the key exchange.  The lookup is called from the function
377    silc_client_start_key_exchange. */
378
379 static void silc_client_start_key_exchange_cb(SilcSocketConnection sock,
380                                               void *context)
381 {
382   SilcClientConnection conn = (SilcClientConnection)context;
383   SilcClient client = conn->client;
384   SilcProtocol protocol;
385   SilcClientKEInternalContext *proto_ctx;
386
387   SILC_LOG_DEBUG(("Start"));
388
389   if (conn->sock->hostname) {
390     silc_free(conn->remote_host);
391     conn->remote_host = strdup(conn->sock->hostname);
392   } else {
393     conn->sock->hostname = strdup(conn->remote_host);
394   }
395   if (!conn->sock->ip)
396     conn->sock->ip = strdup(conn->sock->hostname);
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, 0, NULL);
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, 0, NULL);
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   SilcSocketConnection sock;
1480
1481   SILC_CLIENT_GET_SOCK(client, fd, sock);
1482   if (sock == NULL)
1483     return;
1484
1485   silc_client_close_connection_real(client, sock, sock->user_data);
1486 }
1487
1488 /* Called when we receive disconnection packet from server. This 
1489    closes our end properly and displays the reason of the disconnection
1490    on the screen. */
1491
1492 void silc_client_disconnected_by_server(SilcClient client,
1493                                         SilcSocketConnection sock,
1494                                         SilcBuffer packet)
1495 {
1496   SilcClientConnection conn;
1497   SilcStatus status;
1498   char *message = NULL;
1499
1500   SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1501
1502   if (packet->len < 1)
1503     return;
1504
1505   status = (SilcStatus)packet->data[0];
1506
1507   if (packet->len > 1 &&
1508       silc_utf8_valid(packet->data + 1, packet->len - 1))
1509     message = silc_memdup(packet->data + 1, packet->len - 1);
1510
1511   conn = (SilcClientConnection)sock->user_data;
1512   if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
1513     client->internal->ops->disconnect(client, conn, status, message);
1514
1515   silc_free(message);
1516
1517   SILC_SET_DISCONNECTED(sock);
1518
1519   /* Close connection through scheduler. */
1520   silc_schedule_task_add(client->schedule, sock->sock, 
1521                          silc_client_disconnected_by_server_later,
1522                          client, 0, 1, SILC_TASK_TIMEOUT, 
1523                          SILC_TASK_PRI_NORMAL);
1524 }
1525
1526 /* Received error message from server. Display it on the screen. 
1527    We don't take any action what so ever of the error message. */
1528
1529 void silc_client_error_by_server(SilcClient client,
1530                                  SilcSocketConnection sock,
1531                                  SilcBuffer message)
1532 {
1533   char *msg;
1534
1535   msg = silc_memdup(message->data, message->len);
1536   client->internal->ops->say(client, sock->user_data, 
1537                              SILC_CLIENT_MESSAGE_AUDIT, msg);
1538   silc_free(msg);
1539 }
1540
1541 /* Auto-nicking callback to send NICK command to server. */
1542
1543 SILC_TASK_CALLBACK(silc_client_send_auto_nick)
1544 {
1545   SilcClientConnection conn = (SilcClientConnection)context;
1546   SilcClient client = conn->client;
1547
1548   silc_client_command_send(client, conn, SILC_COMMAND_NICK, 
1549                            ++conn->cmd_ident, 1, 1, 
1550                            client->nickname, strlen(client->nickname));
1551 }
1552
1553 /* Client session resuming callback.  If the session was resumed
1554    this callback is called after the resuming is completed.  This
1555    will call the `connect' client operation to the application
1556    since it has not been called yet. */
1557
1558 static void silc_client_resume_session_cb(SilcClient client,
1559                                           SilcClientConnection conn,
1560                                           bool success,
1561                                           void *context)
1562 {
1563   SilcBuffer sidp;
1564
1565   /* Notify application that connection is created to server */
1566   client->internal->ops->connect(client, conn, success ?
1567                                  SILC_CLIENT_CONN_SUCCESS_RESUME :
1568                                  SILC_CLIENT_CONN_ERROR);
1569
1570   if (success) {
1571     /* Issue INFO command to fetch the real server name and server
1572        information and other stuff. */
1573     silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1574                                  silc_client_command_reply_info_i, 0, 
1575                                  ++conn->cmd_ident);
1576     sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1577     silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1578                              conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1579     silc_buffer_free(sidp);
1580   }
1581 }
1582
1583 /* Processes the received new Client ID from server. Old Client ID is
1584    deleted from cache and new one is added. */
1585
1586 void silc_client_receive_new_id(SilcClient client,
1587                                 SilcSocketConnection sock,
1588                                 SilcIDPayload idp)
1589 {
1590   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1591   int connecting = FALSE;
1592   SilcClientID *client_id = silc_id_payload_get_id(idp);
1593
1594   if (!conn->local_entry)
1595     connecting = TRUE;
1596
1597   /* Delete old ID from ID cache */
1598   if (conn->local_id) {
1599     /* Check whether they are different */
1600     if (SILC_ID_CLIENT_COMPARE(conn->local_id, client_id)) {
1601       silc_free(client_id);
1602       return;
1603     }
1604
1605     silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
1606     silc_free(conn->local_id);
1607   }
1608   
1609   /* Save the new ID */
1610
1611   if (conn->local_id_data)
1612     silc_free(conn->local_id_data);
1613
1614   conn->local_id = client_id;
1615   conn->local_id_data = silc_id_payload_get_data(idp);
1616   conn->local_id_data_len = silc_id_payload_get_len(idp);;
1617
1618   if (!conn->local_entry)
1619     conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1620
1621   conn->local_entry->nickname = conn->nickname;
1622   if (!conn->local_entry->username)
1623     conn->local_entry->username = strdup(client->username);
1624   if (!conn->local_entry->server)
1625     conn->local_entry->server = strdup(conn->remote_host);
1626   conn->local_entry->id = conn->local_id;
1627   conn->local_entry->valid = TRUE;
1628   if (!conn->local_entry->channels)
1629     conn->local_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr, 
1630                                                         NULL, NULL,
1631                                                         NULL, NULL, NULL, 
1632                                                         TRUE);
1633
1634   /* Put it to the ID cache */
1635   silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id, 
1636                    (void *)conn->local_entry, 0, NULL);
1637
1638   if (connecting) {
1639     SilcBuffer sidp;
1640
1641     /* Issue IDENTIFY command for itself to get resolved hostname
1642        correctly from server. */
1643     silc_client_command_register(client, SILC_COMMAND_IDENTIFY, NULL, NULL,
1644                                  silc_client_command_reply_identify_i, 0, 
1645                                  ++conn->cmd_ident);
1646     sidp = silc_id_payload_encode(conn->local_entry->id, SILC_ID_CLIENT);
1647     silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
1648                              conn->cmd_ident, 1, 5, sidp->data, sidp->len);
1649     silc_buffer_free(sidp);
1650
1651     if (!conn->params.detach_data) {
1652       /* Send NICK command if the nickname was set by the application (and is
1653          not same as the username). Send this with little timeout. */
1654       if (client->nickname && strcmp(client->nickname, client->username))
1655         silc_schedule_task_add(client->schedule, 0,
1656                                silc_client_send_auto_nick, conn,
1657                                1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1658
1659       /* Notify application of successful connection. We do it here now that
1660          we've received the Client ID and are allowed to send traffic. */
1661       client->internal->ops->connect(client, conn, SILC_CLIENT_CONN_SUCCESS);
1662
1663       /* Issue INFO command to fetch the real server name and server
1664          information and other stuff. */
1665       silc_client_command_register(client, SILC_COMMAND_INFO, NULL, NULL,
1666                                    silc_client_command_reply_info_i, 0, 
1667                                    ++conn->cmd_ident);
1668       sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
1669       silc_client_command_send(client, conn, SILC_COMMAND_INFO,
1670                                conn->cmd_ident, 1, 2, sidp->data, sidp->len);
1671       silc_buffer_free(sidp);
1672     } else {
1673       /* We are resuming session.  Start resolving informations from the
1674          server we need to set the client libary in the state before
1675          detaching the session.  The connect client operation is called
1676          after this is successfully completed */
1677       silc_client_resume_session(client, conn, silc_client_resume_session_cb,
1678                                  NULL);
1679     }
1680   }
1681 }
1682
1683 /* Removes a client entry from all channels it has joined. */
1684
1685 void silc_client_remove_from_channels(SilcClient client,
1686                                       SilcClientConnection conn,
1687                                       SilcClientEntry client_entry)
1688 {
1689   SilcHashTableList htl;
1690   SilcChannelUser chu;
1691
1692   silc_hash_table_list(client_entry->channels, &htl);
1693   while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
1694     silc_hash_table_del(chu->client->channels, chu->channel);
1695     silc_hash_table_del(chu->channel->user_list, chu->client);
1696     silc_free(chu);
1697   }
1698
1699   silc_hash_table_list_reset(&htl);
1700 }
1701
1702 /* Replaces `old' client entries from all channels to `new' client entry.
1703    This can be called for example when nickname changes and old ID entry
1704    is replaced from ID cache with the new one. If the old ID entry is only
1705    updated, then this fucntion needs not to be called. */
1706
1707 void silc_client_replace_from_channels(SilcClient client, 
1708                                        SilcClientConnection conn,
1709                                        SilcClientEntry old,
1710                                        SilcClientEntry new)
1711 {
1712   SilcHashTableList htl;
1713   SilcChannelUser chu;
1714
1715   silc_hash_table_list(old->channels, &htl);
1716   while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
1717     /* Replace client entry */
1718     silc_hash_table_del(chu->client->channels, chu->channel);
1719     silc_hash_table_del(chu->channel->user_list, chu->client);
1720     
1721     chu->client = new;
1722     silc_hash_table_add(chu->channel->user_list, chu->client, chu);
1723     silc_hash_table_add(chu->client->channels, chu->channel, chu);
1724   }
1725   silc_hash_table_list_reset(&htl);
1726 }
1727
1728 /* Registers failure timeout to process the received failure packet
1729    with timeout. */
1730
1731 void silc_client_process_failure(SilcClient client,
1732                                  SilcSocketConnection sock,
1733                                  SilcPacketContext *packet)
1734 {
1735   SilcUInt32 failure = 0;
1736
1737   if (sock->protocol) {
1738     if (packet->buffer->len >= 4)
1739       SILC_GET32_MSB(failure, packet->buffer->data);
1740
1741     /* Notify application */
1742     client->internal->ops->failure(client, sock->user_data, sock->protocol,
1743                                    (void *)failure);
1744   }
1745 }
1746
1747 /* A timeout callback for the re-key. We will be the initiator of the
1748    re-key protocol. */
1749
1750 SILC_TASK_CALLBACK(silc_client_rekey_callback)
1751 {
1752   SilcSocketConnection sock = (SilcSocketConnection)context;
1753   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1754   SilcClient client = (SilcClient)conn->rekey->context;
1755   SilcProtocol protocol;
1756   SilcClientRekeyInternalContext *proto_ctx;
1757
1758   SILC_LOG_DEBUG(("Start"));
1759
1760   /* Allocate internal protocol context. This is sent as context
1761      to the protocol. */
1762   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
1763   proto_ctx->client = (void *)client;
1764   proto_ctx->sock = silc_socket_dup(sock);
1765   proto_ctx->responder = FALSE;
1766   proto_ctx->pfs = conn->rekey->pfs;
1767       
1768   /* Perform rekey protocol. Will call the final callback after the
1769      protocol is over. */
1770   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_REKEY, 
1771                       &protocol, proto_ctx, silc_client_rekey_final);
1772   sock->protocol = protocol;
1773       
1774   /* Run the protocol */
1775   silc_protocol_execute(protocol, client->schedule, 0, 0);
1776
1777   /* Re-register re-key timeout */
1778   silc_schedule_task_add(client->schedule, sock->sock, 
1779                          silc_client_rekey_callback,
1780                          context, conn->rekey->timeout, 0,
1781                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1782 }
1783
1784 /* The final callback for the REKEY protocol. This will actually take the
1785    new key material into use. */
1786
1787 SILC_TASK_CALLBACK(silc_client_rekey_final)
1788 {
1789   SilcProtocol protocol = (SilcProtocol)context;
1790   SilcClientRekeyInternalContext *ctx =
1791     (SilcClientRekeyInternalContext *)protocol->context;
1792   SilcClient client = (SilcClient)ctx->client;
1793   SilcSocketConnection sock = ctx->sock;
1794
1795   SILC_LOG_DEBUG(("Start"));
1796
1797   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
1798       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
1799     /* Error occured during protocol */
1800     silc_protocol_cancel(protocol, client->schedule);
1801     silc_protocol_free(protocol);
1802     sock->protocol = NULL;
1803     if (ctx->packet)
1804       silc_packet_context_free(ctx->packet);
1805     if (ctx->ske)
1806       silc_ske_free(ctx->ske);
1807     silc_socket_free(ctx->sock);
1808     silc_free(ctx);
1809     return;
1810   }
1811
1812   /* Purge the outgoing data queue to assure that all rekey packets really
1813      go to the network before we quit the protocol. */
1814   silc_client_packet_queue_purge(client, sock);
1815
1816   /* Cleanup */
1817   silc_protocol_free(protocol);
1818   sock->protocol = NULL;
1819   if (ctx->packet)
1820     silc_packet_context_free(ctx->packet);
1821   if (ctx->ske)
1822     silc_ske_free(ctx->ske);
1823   silc_socket_free(ctx->sock);
1824   silc_free(ctx);
1825 }
1826
1827 /* Processes incoming connection authentication method request packet.
1828    It is a reply to our previously sent request. The packet can be used
1829    to resolve the authentication method for the current session if the
1830    client does not know it beforehand. */
1831
1832 void silc_client_connection_auth_request(SilcClient client,
1833                                          SilcSocketConnection sock,
1834                                          SilcPacketContext *packet)
1835 {
1836   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1837   SilcUInt16 conn_type, auth_meth;
1838   int ret;
1839
1840   /* If we haven't send our request then ignore this one. */
1841   if (!conn->connauth)
1842     return;
1843
1844   /* Parse the payload */
1845   ret = silc_buffer_unformat(packet->buffer,
1846                              SILC_STR_UI_SHORT(&conn_type),
1847                              SILC_STR_UI_SHORT(&auth_meth),
1848                              SILC_STR_END);
1849   if (ret == -1)
1850     auth_meth = SILC_AUTH_NONE;
1851
1852   /* Call the request callback to notify application for received 
1853      authentication method information. */
1854   if (conn->connauth->callback)
1855     (*conn->connauth->callback)(client, conn, auth_meth,
1856                                 conn->connauth->context);
1857
1858   silc_schedule_task_del(client->schedule, conn->connauth->timeout);
1859
1860   silc_free(conn->connauth);
1861   conn->connauth = NULL;
1862 }
1863
1864 /* Timeout task callback called if the server does not reply to our 
1865    connection authentication method request in the specified time interval. */
1866
1867 SILC_TASK_CALLBACK(silc_client_request_authentication_method_timeout)
1868 {
1869   SilcClientConnection conn = (SilcClientConnection)context;
1870   SilcClient client = conn->client;
1871
1872   if (!conn->connauth)
1873     return;
1874
1875   /* Call the request callback to notify application */
1876   if (conn->connauth->callback)
1877     (*conn->connauth->callback)(client, conn, SILC_AUTH_NONE,
1878                                 conn->connauth->context);
1879
1880   silc_free(conn->connauth);
1881   conn->connauth = NULL;
1882 }
1883
1884 /* This function can be used to request the current authentication method
1885    from the server. This may be called when connecting to the server
1886    and the client library requests the authentication data from the
1887    application. If the application does not know the current authentication
1888    method it can request it from the server using this function.
1889    The `callback' with `context' will be called after the server has
1890    replied back with the current authentication method. */
1891
1892 void 
1893 silc_client_request_authentication_method(SilcClient client,
1894                                           SilcClientConnection conn,
1895                                           SilcConnectionAuthRequest callback,
1896                                           void *context)
1897 {
1898   SilcClientConnAuthRequest connauth;
1899   SilcBuffer packet;
1900
1901   connauth = silc_calloc(1, sizeof(*connauth));
1902   connauth->callback = callback;
1903   connauth->context = context;
1904
1905   if (conn->connauth)
1906     silc_free(conn->connauth);
1907
1908   conn->connauth = connauth;
1909
1910   /* Assemble the request packet and send it to the server */
1911   packet = silc_buffer_alloc(4);
1912   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
1913   silc_buffer_format(packet,
1914                      SILC_STR_UI_SHORT(SILC_SOCKET_TYPE_CLIENT),
1915                      SILC_STR_UI_SHORT(SILC_AUTH_NONE),
1916                      SILC_STR_END);
1917   silc_client_packet_send(client, conn->sock, 
1918                           SILC_PACKET_CONNECTION_AUTH_REQUEST,
1919                           NULL, 0, NULL, NULL, 
1920                           packet->data, packet->len, FALSE);
1921   silc_buffer_free(packet);
1922
1923   /* Register a timeout in case server does not reply anything back. */
1924   connauth->timeout =
1925     silc_schedule_task_add(client->schedule, conn->sock->sock, 
1926                            silc_client_request_authentication_method_timeout,
1927                            conn, 
1928                            client->internal->params->connauth_request_secs, 0,
1929                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
1930 }