5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "clientlibincludes.h"
24 /* Static task callback prototypes */
25 SILC_TASK_CALLBACK(silc_client_connect_to_server_start);
26 SILC_TASK_CALLBACK(silc_client_connect_to_server_second);
27 SILC_TASK_CALLBACK(silc_client_connect_to_server_final);
28 SILC_TASK_CALLBACK(silc_client_packet_process);
29 SILC_TASK_CALLBACK(silc_client_packet_parse_real);
31 static void silc_client_packet_parse(SilcPacketParserContext *parser_context);
32 static void silc_client_packet_parse_type(SilcClient client,
33 SilcSocketConnection sock,
34 SilcPacketContext *packet);
36 /* Allocates new client object. This has to be done before client may
37 work. After calling this one must call silc_client_init to initialize
38 the client. The `application' is application specific user data pointer
39 and caller must free it. */
41 SilcClient silc_client_alloc(SilcClientOperations *ops, void *application)
43 SilcClient new_client;
45 new_client = silc_calloc(1, sizeof(*new_client));
46 new_client->application = application;
47 new_client->ops = ops;
52 /* Free's client object */
54 void silc_client_free(SilcClient client)
58 silc_rng_free(client->rng);
64 /* Initializes the client. This makes all the necessary steps to make
65 the client ready to be run. One must call silc_client_run to run the
68 int silc_client_init(SilcClient client)
70 SILC_LOG_DEBUG(("Initializing client"));
72 /* Initialize hash functions for client to use */
73 silc_hash_alloc("md5", &client->md5hash);
74 silc_hash_alloc("sha1", &client->sha1hash);
76 /* Initialize none cipher */
77 silc_cipher_alloc("none", &client->none_cipher);
79 /* Initialize random number generator */
80 client->rng = silc_rng_alloc();
81 silc_rng_init(client->rng);
82 silc_rng_global_init(client->rng);
84 /* Register protocols */
85 silc_client_protocols_register();
87 /* Initialize the scheduler */
88 silc_schedule_init(&client->io_queue, &client->timeout_queue,
89 &client->generic_queue, 5000);
94 /* Stops the client. This is called to stop the client and thus to stop
97 void silc_client_stop(SilcClient client)
99 SILC_LOG_DEBUG(("Stopping client"));
101 /* Stop the scheduler, although it might be already stopped. This
102 doesn't hurt anyone. This removes all the tasks and task queues,
104 silc_schedule_stop();
105 silc_schedule_uninit();
107 silc_client_protocols_unregister();
109 SILC_LOG_DEBUG(("Client stopped"));
112 /* Runs the client. */
114 void silc_client_run(SilcClient client)
116 SILC_LOG_DEBUG(("Running client"));
118 /* Start the scheduler, the heart of the SILC client. When this returns
119 the program will be terminated. */
123 /* Allocates and adds new connection to the client. This adds the allocated
124 connection to the connection table and returns a pointer to it. A client
125 can have multiple connections to multiple servers. Every connection must
126 be added to the client using this function. User data `context' may
127 be sent as argument. */
129 SilcClientConnection silc_client_add_connection(SilcClient client,
134 SilcClientConnection conn;
137 conn = silc_calloc(1, sizeof(*conn));
139 /* Initialize ID caches */
140 conn->client_cache = silc_idcache_alloc(0);
141 conn->channel_cache = silc_idcache_alloc(0);
142 conn->server_cache = silc_idcache_alloc(0);
143 conn->client = client;
144 conn->remote_host = strdup(hostname);
145 conn->remote_port = port;
146 conn->context = context;
147 conn->pending_commands = silc_dlist_init();
149 /* Add the connection to connections table */
150 for (i = 0; i < client->conns_count; i++)
151 if (client->conns && !client->conns[i]) {
152 client->conns[i] = conn;
156 client->conns = silc_realloc(client->conns, sizeof(*client->conns)
157 * (client->conns_count + 1));
158 client->conns[client->conns_count] = conn;
159 client->conns_count++;
164 /* Removes connection from client. */
166 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
170 for (i = 0; i < client->conns_count; i++)
171 if (client->conns[i] == conn) {
172 if (conn->pending_commands)
173 silc_dlist_uninit(conn->pending_commands);
175 client->conns[i] = NULL;
179 /* Internal context for connection process. This is needed as we
180 doing asynchronous connecting. */
183 SilcClientConnection conn;
189 } SilcClientInternalConnectContext;
192 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
196 /* XXX In the future we should give up this non-blocking connect all
197 together and use threads instead. */
198 /* Create connection to server asynchronously */
199 sock = silc_net_create_connection_async(ctx->port, ctx->host);
203 /* Register task that will receive the async connect and will
205 ctx->task = silc_task_register(ctx->client->io_queue, sock,
206 silc_client_connect_to_server_start,
209 SILC_TASK_PRI_NORMAL);
210 silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
211 silc_schedule_set_listen_fd(sock, ctx->task->iomask);
218 /* Connects to remote server. This is the main routine used to connect
219 to SILC server. Returns -1 on error and the created socket otherwise.
220 The `context' is user context that is saved into the SilcClientConnection
221 that is created after the connection is created. */
223 int silc_client_connect_to_server(SilcClient client, int port,
224 char *host, void *context)
226 SilcClientInternalConnectContext *ctx;
227 SilcClientConnection conn;
230 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
233 conn = silc_client_add_connection(client, host, port, context);
235 client->ops->say(client, conn,
236 "Connecting to port %d of server %s", port, host);
238 /* Allocate internal context for connection process. This is
239 needed as we are doing async connecting. */
240 ctx = silc_calloc(1, sizeof(*ctx));
241 ctx->client = client;
243 ctx->host = strdup(host);
247 /* Do the actual connecting process */
248 sock = silc_client_connect_to_server_internal(ctx);
250 silc_client_del_connection(client, conn);
254 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
255 key material between client and server. This function can be called
256 directly if application is performing its own connecting and does not
257 use the connecting provided by this library. */
259 int silc_client_start_key_exchange(SilcClient client,
260 SilcClientConnection conn,
263 SilcProtocol protocol;
264 SilcClientKEInternalContext *proto_ctx;
267 /* Allocate new socket connection object */
268 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
269 if (conn->sock == NULL) {
270 client->ops->say(client, conn,
271 "Error: Could not allocate connection socket");
275 conn->nickname = strdup(client->username);
276 conn->sock->hostname = conn->remote_host;
277 conn->sock->ip = strdup(conn->remote_host);
278 conn->sock->port = conn->remote_port;
280 /* Allocate internal Key Exchange context. This is sent to the
281 protocol as context. */
282 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
283 proto_ctx->client = (void *)client;
284 proto_ctx->sock = conn->sock;
285 proto_ctx->rng = client->rng;
286 proto_ctx->responder = FALSE;
288 /* Perform key exchange protocol. silc_client_connect_to_server_final
289 will be called after the protocol is finished. */
290 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
291 &protocol, (void *)proto_ctx,
292 silc_client_connect_to_server_second);
294 client->ops->say(client, conn,
295 "Error: Could not start authentication protocol");
298 conn->sock->protocol = protocol;
300 /* Register the connection for network input and output. This sets
301 that scheduler will listen for incoming packets for this connection
302 and sets that outgoing packets may be sent to this connection as well.
303 However, this doesn't set the scheduler for outgoing traffic, it will
304 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
305 later when outgoing data is available. */
306 context = (void *)client;
307 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
309 /* Execute the protocol */
310 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
314 /* Start of the connection to the remote server. This is called after
315 succesful TCP/IP connection has been established to the remote host. */
317 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
319 SilcClientInternalConnectContext *ctx =
320 (SilcClientInternalConnectContext *)context;
321 SilcClient client = ctx->client;
322 SilcClientConnection conn = ctx->conn;
323 int opt, opt_len = sizeof(opt);
325 SILC_LOG_DEBUG(("Start"));
327 /* Check the socket status as it might be in error */
328 getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
330 if (ctx->tries < 2) {
331 /* Connection failed but lets try again */
332 client->ops->say(client, conn, "Could not connect to server %s: %s",
333 ctx->host, strerror(opt));
334 client->ops->say(client, conn,
335 "Connecting to port %d of server %s resumed",
336 ctx->port, ctx->host);
338 /* Unregister old connection try */
339 silc_schedule_unset_listen_fd(fd);
340 silc_net_close_connection(fd);
341 silc_task_unregister(client->io_queue, ctx->task);
344 silc_client_connect_to_server_internal(ctx);
347 /* Connection failed and we won't try anymore */
348 client->ops->say(client, conn, "Could not connect to server %s: %s",
349 ctx->host, strerror(opt));
350 silc_schedule_unset_listen_fd(fd);
351 silc_net_close_connection(fd);
352 silc_task_unregister(client->io_queue, ctx->task);
355 /* Notify application of failure */
356 client->ops->connect(client, conn, FALSE);
357 silc_client_del_connection(client, conn);
362 silc_schedule_unset_listen_fd(fd);
363 silc_task_unregister(client->io_queue, ctx->task);
366 if (!silc_client_start_key_exchange(client, conn, fd)) {
367 silc_net_close_connection(fd);
368 client->ops->connect(client, conn, FALSE);
372 /* Second part of the connecting to the server. This executed
373 authentication protocol. */
375 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
377 SilcProtocol protocol = (SilcProtocol)context;
378 SilcClientKEInternalContext *ctx =
379 (SilcClientKEInternalContext *)protocol->context;
380 SilcClient client = (SilcClient)ctx->client;
381 SilcSocketConnection sock = NULL;
382 SilcClientConnAuthInternalContext *proto_ctx;
384 SILC_LOG_DEBUG(("Start"));
386 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
387 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
388 /* Error occured during protocol */
389 SILC_LOG_DEBUG(("Error during KE protocol"));
390 silc_protocol_free(protocol);
392 silc_ske_free(ctx->ske);
394 silc_free(ctx->dest_id);
395 ctx->sock->protocol = NULL;
397 /* Notify application of failure */
398 client->ops->connect(client, ctx->sock->user_data, FALSE);
403 /* Allocate internal context for the authentication protocol. This
404 is sent as context for the protocol. */
405 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
406 proto_ctx->client = (void *)client;
407 proto_ctx->sock = sock = ctx->sock;
408 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
409 proto_ctx->dest_id_type = ctx->dest_id_type;
410 proto_ctx->dest_id = ctx->dest_id;
412 /* Resolve the authentication method to be used in this connection */
413 if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
414 sock->port, &proto_ctx->auth_meth,
415 &proto_ctx->auth_data,
416 &proto_ctx->auth_data_len))
418 /* XXX do AUTH_REQUEST resolcing with server */
419 proto_ctx->auth_meth = SILC_AUTH_NONE;
422 /* Free old protocol as it is finished now */
423 silc_protocol_free(protocol);
425 silc_packet_context_free(ctx->packet);
427 /* silc_free(ctx->keymat....); */
428 sock->protocol = NULL;
430 /* Allocate the authentication protocol. This is allocated here
431 but we won't start it yet. We will be receiving party of this
432 protocol thus we will wait that connecting party will make
434 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
435 &sock->protocol, (void *)proto_ctx,
436 silc_client_connect_to_server_final);
438 /* Execute the protocol */
439 sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
442 /* Finalizes the connection to the remote SILC server. This is called
443 after authentication protocol has been completed. This send our
444 user information to the server to receive our client ID from
447 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
449 SilcProtocol protocol = (SilcProtocol)context;
450 SilcClientConnAuthInternalContext *ctx =
451 (SilcClientConnAuthInternalContext *)protocol->context;
452 SilcClient client = (SilcClient)ctx->client;
453 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
456 SILC_LOG_DEBUG(("Start"));
458 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
459 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
460 /* Error occured during protocol */
461 SILC_LOG_DEBUG(("Error during authentication protocol"));
462 silc_protocol_free(protocol);
464 silc_free(ctx->auth_data);
466 silc_ske_free(ctx->ske);
468 silc_free(ctx->dest_id);
469 conn->sock->protocol = NULL;
471 /* Notify application of failure */
472 client->ops->connect(client, ctx->sock->user_data, FALSE);
477 /* Send NEW_CLIENT packet to the server. We will become registered
478 to the SILC network after sending this packet and we will receive
479 client ID from the server. */
480 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
481 strlen(client->realname));
482 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
483 silc_buffer_format(packet,
484 SILC_STR_UI_SHORT(strlen(client->username)),
485 SILC_STR_UI_XNSTRING(client->username,
486 strlen(client->username)),
487 SILC_STR_UI_SHORT(strlen(client->realname)),
488 SILC_STR_UI_XNSTRING(client->realname,
489 strlen(client->realname)),
492 /* Send the packet */
493 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
495 packet->data, packet->len, TRUE);
496 silc_buffer_free(packet);
498 /* Save remote ID. */
499 conn->remote_id = ctx->dest_id;
500 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
501 conn->remote_id_data_len = SILC_ID_SERVER_LEN;
503 silc_protocol_free(protocol);
505 silc_free(ctx->auth_data);
507 silc_ske_free(ctx->ske);
509 conn->sock->protocol = NULL;
512 /* Internal routine that sends packet or marks packet to be sent. This
513 is used directly only in special cases. Normal cases should use
514 silc_server_packet_send. Returns < 0 on error. */
516 static int silc_client_packet_send_real(SilcClient client,
517 SilcSocketConnection sock,
522 /* Send the packet */
523 ret = silc_packet_send(sock, force_send);
527 /* Mark that there is some outgoing data available for this connection.
528 This call sets the connection both for input and output (the input
529 is set always and this call keeps the input setting, actually).
530 Actual data sending is performed by silc_client_packet_process. */
531 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
533 /* Mark to socket that data is pending in outgoing buffer. This flag
534 is needed if new data is added to the buffer before the earlier
535 put data is sent to the network. */
536 SILC_SET_OUTBUF_PENDING(sock);
541 /* Packet processing callback. This is used to send and receive packets
542 from network. This is generic task. */
544 SILC_TASK_CALLBACK(silc_client_packet_process)
546 SilcClient client = (SilcClient)context;
547 SilcSocketConnection sock = NULL;
548 SilcClientConnection conn;
551 SILC_LOG_DEBUG(("Processing packet"));
553 SILC_CLIENT_GET_SOCK(client, fd, sock);
557 conn = (SilcClientConnection)sock->user_data;
560 if (type == SILC_TASK_WRITE) {
561 SILC_LOG_DEBUG(("Writing data to connection"));
563 if (sock->outbuf->data - sock->outbuf->head)
564 silc_buffer_push(sock->outbuf,
565 sock->outbuf->data - sock->outbuf->head);
567 ret = silc_client_packet_send_real(client, sock, TRUE);
569 /* If returned -2 could not write to connection now, will do
574 /* The packet has been sent and now it is time to set the connection
575 back to only for input. When there is again some outgoing data
576 available for this connection it will be set for output as well.
577 This call clears the output setting and sets it only for input. */
578 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
579 SILC_UNSET_OUTBUF_PENDING(sock);
581 silc_buffer_clear(sock->outbuf);
585 /* Packet receiving */
586 if (type == SILC_TASK_READ) {
587 SILC_LOG_DEBUG(("Reading data from connection"));
589 /* Read data from network */
590 ret = silc_packet_receive(sock);
596 SILC_LOG_DEBUG(("Read EOF"));
598 /* If connection is disconnecting already we will finally
599 close the connection */
600 if (SILC_IS_DISCONNECTING(sock)) {
601 client->ops->disconnect(client, conn);
602 silc_client_close_connection(client, sock);
606 SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
607 client->ops->disconnect(client, conn);
608 silc_client_close_connection(client, sock);
612 /* Process the packet. This will call the parser that will then
613 decrypt and parse the packet. */
614 silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
615 silc_client_packet_parse, client);
619 /* Parses whole packet, received earlier. */
621 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
623 SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
624 SilcClient client = (SilcClient)parse_ctx->context;
625 SilcPacketContext *packet = parse_ctx->packet;
626 SilcBuffer buffer = packet->buffer;
627 SilcSocketConnection sock = parse_ctx->sock;
628 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
631 SILC_LOG_DEBUG(("Start"));
633 /* Decrypt the received packet */
634 ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet);
639 /* Parse the packet. Packet type is returned. */
640 ret = silc_packet_parse(packet);
642 /* Parse the packet header in special way as this is "special"
644 ret = silc_packet_parse_special(packet);
647 if (ret == SILC_PACKET_NONE)
650 /* Parse the incoming packet type */
651 silc_client_packet_parse_type(client, sock, packet);
654 silc_buffer_clear(sock->inbuf);
655 silc_packet_context_free(packet);
656 silc_free(parse_ctx);
659 /* Parser callback called by silc_packet_receive_process. Thie merely
660 registers timeout that will handle the actual parsing when appropriate. */
662 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
664 SilcClient client = (SilcClient)parser_context->context;
666 /* Parse the packet */
667 silc_task_register(client->timeout_queue, parser_context->sock->sock,
668 silc_client_packet_parse_real,
669 (void *)parser_context, 0, 1,
671 SILC_TASK_PRI_NORMAL);
674 /* Parses the packet type and calls what ever routines the packet type
675 requires. This is done for all incoming packets. */
677 void silc_client_packet_parse_type(SilcClient client,
678 SilcSocketConnection sock,
679 SilcPacketContext *packet)
681 SilcBuffer buffer = packet->buffer;
682 SilcPacketType type = packet->type;
684 SILC_LOG_DEBUG(("Parsing packet type %d", type));
686 /* Parse the packet type */
688 case SILC_PACKET_DISCONNECT:
689 silc_client_disconnected_by_server(client, sock, buffer);
691 case SILC_PACKET_SUCCESS:
693 * Success received for something. For now we can have only
694 * one protocol for connection executing at once hence this
695 * success message is for whatever protocol is executing currently.
697 if (sock->protocol) {
698 sock->protocol->execute(client->timeout_queue, 0,
699 sock->protocol, sock->sock, 0, 0);
702 case SILC_PACKET_FAILURE:
704 * Failure received for some protocol. Set the protocol state to
705 * error and call the protocol callback. This fill cause error on
706 * protocol and it will call the final callback.
708 if (sock->protocol) {
709 sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
710 sock->protocol->execute(client->timeout_queue, 0,
711 sock->protocol, sock->sock, 0, 0);
713 /* XXX We have only two protocols currently thus we know what this
714 failure indication is. */
715 if (buffer->len >= 4) {
716 unsigned int failure;
718 SILC_GET32_MSB(failure, buffer->data);
720 /* Notify application */
721 client->ops->failure(client, sock->user_data, sock->protocol,
726 case SILC_PACKET_REJECT:
729 case SILC_PACKET_NOTIFY:
731 * Received notify message
733 silc_client_notify_by_server(client, sock, packet);
736 case SILC_PACKET_ERROR:
738 * Received error message
740 silc_client_error_by_server(client, sock, buffer);
743 case SILC_PACKET_CHANNEL_MESSAGE:
745 * Received message to (from, actually) a channel
747 silc_client_channel_message(client, sock, packet);
749 case SILC_PACKET_CHANNEL_KEY:
751 * Received key for a channel. By receiving this key the client will be
752 * able to talk to the channel it has just joined. This can also be
753 * a new key for existing channel as keys expire peridiocally.
755 silc_client_receive_channel_key(client, sock, buffer);
758 case SILC_PACKET_PRIVATE_MESSAGE:
760 * Received private message
762 silc_client_private_message(client, sock, packet);
764 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
766 * Received private message key
770 case SILC_PACKET_COMMAND_REPLY:
772 * Recived reply for a command
774 silc_client_command_reply_process(client, sock, packet);
777 case SILC_PACKET_KEY_EXCHANGE:
778 if (sock->protocol) {
779 SilcClientKEInternalContext *proto_ctx =
780 (SilcClientKEInternalContext *)sock->protocol->context;
782 proto_ctx->packet = silc_packet_context_dup(packet);
783 proto_ctx->dest_id_type = packet->src_id_type;
784 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
785 packet->src_id_type);
786 if (!proto_ctx->dest_id)
789 /* Let the protocol handle the packet */
790 sock->protocol->execute(client->timeout_queue, 0,
791 sock->protocol, sock->sock, 0, 0);
793 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
794 "protocol active, packet dropped."));
796 /* XXX Trigger KE protocol?? Rekey actually! */
800 case SILC_PACKET_KEY_EXCHANGE_1:
801 if (sock->protocol) {
804 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
805 "protocol active, packet dropped."));
808 case SILC_PACKET_KEY_EXCHANGE_2:
809 if (sock->protocol) {
810 SilcClientKEInternalContext *proto_ctx =
811 (SilcClientKEInternalContext *)sock->protocol->context;
813 if (proto_ctx->packet)
814 silc_packet_context_free(proto_ctx->packet);
816 proto_ctx->packet = silc_packet_context_dup(packet);
817 proto_ctx->dest_id_type = packet->src_id_type;
818 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
819 packet->src_id_type);
820 if (!proto_ctx->dest_id)
823 /* Let the protocol handle the packet */
824 sock->protocol->execute(client->timeout_queue, 0,
825 sock->protocol, sock->sock, 0, 0);
827 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
828 "protocol active, packet dropped."));
832 case SILC_PACKET_NEW_ID:
835 * Received new ID from server. This packet is received at
836 * the connection to the server. New ID is also received when
837 * user changes nickname but in that case the new ID is received
838 * as command reply and not as this packet type.
842 idp = silc_id_payload_parse(buffer);
845 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
848 silc_client_receive_new_id(client, sock, idp);
849 silc_id_payload_free(idp);
853 case SILC_PACKET_HEARTBEAT:
855 * Received heartbeat packet
857 SILC_LOG_DEBUG(("Heartbeat packet"));
861 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
866 /* Sends packet. This doesn't actually send the packet instead it assembles
867 it and marks it to be sent. However, if force_send is TRUE the packet
868 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
869 will be derived from sock argument. Otherwise the valid arguments sent
872 void silc_client_packet_send(SilcClient client,
873 SilcSocketConnection sock,
876 SilcIdType dst_id_type,
880 unsigned int data_len,
883 SilcPacketContext packetdata;
885 SILC_LOG_DEBUG(("Sending packet, type %d", type));
887 /* Get data used in the packet sending, keys and stuff */
888 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
889 if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
890 cipher = ((SilcClientConnection)sock->user_data)->send_key;
892 if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
893 hmac = ((SilcClientConnection)sock->user_data)->hmac;
895 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
896 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
897 dst_id_type = SILC_ID_SERVER;
901 /* Set the packet context pointers */
902 packetdata.flags = 0;
903 packetdata.type = type;
904 if (((SilcClientConnection)sock->user_data)->local_id_data)
905 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
907 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
908 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
909 packetdata.src_id_type = SILC_ID_CLIENT;
911 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
912 packetdata.dst_id_len = silc_id_get_len(dst_id_type);
913 packetdata.dst_id_type = dst_id_type;
915 packetdata.dst_id = NULL;
916 packetdata.dst_id_len = 0;
917 packetdata.dst_id_type = SILC_ID_NONE;
919 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
920 packetdata.src_id_len + packetdata.dst_id_len;
921 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
923 /* Prepare outgoing data buffer for packet sending */
924 silc_packet_send_prepare(sock,
925 SILC_PACKET_HEADER_LEN +
926 packetdata.src_id_len +
927 packetdata.dst_id_len,
931 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
933 packetdata.buffer = sock->outbuf;
935 /* Put the data to the buffer */
936 if (data && data_len)
937 silc_buffer_put(sock->outbuf, data, data_len);
939 /* Create the outgoing packet */
940 silc_packet_assemble(&packetdata);
942 /* Encrypt the packet */
944 silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
946 SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
947 sock->outbuf->data, sock->outbuf->len);
949 /* Now actually send the packet */
950 silc_client_packet_send_real(client, sock, force_send);
953 /* Sends packet to a channel. Packet to channel is always encrypted
954 differently from "normal" packets. SILC header of the packet is
955 encrypted with the next receiver's key and the rest of the packet is
956 encrypted with the channel specific key. Padding and HMAC is computed
957 with the next receiver's key. */
959 void silc_client_packet_send_to_channel(SilcClient client,
960 SilcSocketConnection sock,
961 SilcChannelEntry channel,
963 unsigned int data_len,
967 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
969 SilcPacketContext packetdata;
972 unsigned char *id_string;
974 SILC_LOG_DEBUG(("Sending packet to channel"));
976 if (!channel || !channel->key) {
977 client->ops->say(client, conn,
978 "Cannot talk to channel: key does not exist");
983 if (channel->iv[0] == '\0')
984 for (i = 0; i < 16; i++) channel->iv[i] = silc_rng_get_byte(client->rng);
986 silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
988 /* Encode the channel payload */
989 payload = silc_channel_payload_encode(data_len, data, 16, channel->iv,
992 client->ops->say(client, conn,
993 "Error: Could not create packet to be sent to channel");
997 /* Get data used in packet header encryption, keys and stuff. Rest
998 of the packet (the payload) is, however, encrypted with the
999 specified channel key. */
1000 cipher = conn->send_key;
1002 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1004 /* Set the packet context pointers. The destination ID is always
1005 the Channel ID of the channel. Server and router will handle the
1006 distribution of the packet. */
1007 packetdata.flags = 0;
1008 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
1009 packetdata.src_id = conn->local_id_data;
1010 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1011 packetdata.src_id_type = SILC_ID_CLIENT;
1012 packetdata.dst_id = id_string;
1013 packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1014 packetdata.dst_id_type = SILC_ID_CHANNEL;
1015 packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN +
1016 packetdata.src_id_len + packetdata.dst_id_len;
1017 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1018 packetdata.src_id_len +
1019 packetdata.dst_id_len));
1021 /* Prepare outgoing data buffer for packet sending */
1022 silc_packet_send_prepare(sock,
1023 SILC_PACKET_HEADER_LEN +
1024 packetdata.src_id_len +
1025 packetdata.dst_id_len,
1029 packetdata.buffer = sock->outbuf;
1031 SILC_LOG_HEXDUMP(("IV"), channel->iv, 16);
1032 SILC_LOG_HEXDUMP(("channel key"), channel->key, channel->key_len/8);
1034 /* Encrypt payload of the packet. This is encrypted with the channel key. */
1035 channel->channel_key->cipher->encrypt(channel->channel_key->context,
1036 payload->data, payload->data,
1037 payload->len - 16, /* -IV_LEN */
1040 /* Put the actual encrypted payload data into the buffer. */
1041 silc_buffer_put(sock->outbuf, payload->data, payload->len);
1043 /* Create the outgoing packet */
1044 silc_packet_assemble(&packetdata);
1046 /* Encrypt the header and padding of the packet. This is encrypted
1047 with normal session key shared with our server. */
1048 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1049 packetdata.src_id_len + packetdata.dst_id_len +
1052 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1053 sock->outbuf->data, sock->outbuf->len);
1055 /* Now actually send the packet */
1056 silc_client_packet_send_real(client, sock, force_send);
1057 silc_buffer_free(payload);
1058 silc_free(id_string);
1061 /* Sends private message to remote client. If private message key has
1062 not been set with this client then the message will be encrypted using
1063 normal session keys. Private messages are special packets in SILC
1064 network hence we need this own function for them. This is similiar
1065 to silc_client_packet_send_to_channel except that we send private
1068 void silc_client_packet_send_private_message(SilcClient client,
1069 SilcSocketConnection sock,
1070 SilcClientEntry client_entry,
1071 unsigned char *data,
1072 unsigned int data_len,
1075 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1077 SilcPacketContext packetdata;
1078 unsigned int nick_len;
1082 SILC_LOG_DEBUG(("Sending private message"));
1084 /* Create private message payload */
1085 nick_len = strlen(conn->nickname);
1086 buffer = silc_buffer_alloc(2 + nick_len + data_len);
1087 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1088 silc_buffer_format(buffer,
1089 SILC_STR_UI_SHORT(nick_len),
1090 SILC_STR_UI_XNSTRING(conn->nickname,
1092 SILC_STR_UI_XNSTRING(data, data_len),
1095 /* If we don't have private message specific key then private messages
1096 are just as any normal packet thus call normal packet sending. If
1097 the key exist then the encryption process is a bit different and
1098 will be done in the rest of this function. */
1099 if (!client_entry->send_key) {
1100 silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1101 client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1102 buffer->data, buffer->len, force_send);
1106 /* We have private message specific key */
1108 /* Get data used in the encryption */
1109 cipher = client_entry->send_key;
1112 /* Set the packet context pointers. */
1113 packetdata.flags = 0;
1114 packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1115 packetdata.src_id = conn->local_id_data;
1116 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1117 packetdata.src_id_type = SILC_ID_CLIENT;
1119 packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1121 packetdata.dst_id = conn->local_id_data;
1122 packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1123 packetdata.dst_id_type = SILC_ID_CLIENT;
1124 packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN +
1125 packetdata.src_id_len + packetdata.dst_id_len;
1126 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1127 packetdata.src_id_len +
1128 packetdata.dst_id_len));
1130 /* Prepare outgoing data buffer for packet sending */
1131 silc_packet_send_prepare(sock,
1132 SILC_PACKET_HEADER_LEN +
1133 packetdata.src_id_len +
1134 packetdata.dst_id_len,
1138 packetdata.buffer = sock->outbuf;
1140 /* Encrypt payload of the packet. Encrypt with private message specific
1141 key if it exist, otherwise with session key. */
1142 cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1143 buffer->len, cipher->iv);
1145 /* Put the actual encrypted payload data into the buffer. */
1146 silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1148 /* Create the outgoing packet */
1149 silc_packet_assemble(&packetdata);
1151 /* Encrypt the header and padding of the packet. */
1152 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1153 packetdata.src_id_len + packetdata.dst_id_len +
1156 SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1157 sock->outbuf->data, sock->outbuf->len);
1159 /* Now actually send the packet */
1160 silc_client_packet_send_real(client, sock, force_send);
1161 silc_free(packetdata.dst_id);
1167 /* Closes connection to remote end. Free's all allocated data except
1168 for some information such as nickname etc. that are valid at all time. */
1170 void silc_client_close_connection(SilcClient client,
1171 SilcSocketConnection sock)
1173 SilcClientConnection conn;
1175 /* We won't listen for this connection anymore */
1176 silc_schedule_unset_listen_fd(sock->sock);
1178 /* Unregister all tasks */
1179 silc_task_unregister_by_fd(client->io_queue, sock->sock);
1180 silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1182 /* Close the actual connection */
1183 silc_net_close_connection(sock->sock);
1185 client->ops->say(client, sock->user_data,
1186 "Closed connection to host %s", sock->hostname);
1188 /* Free everything */
1189 if (sock->user_data) {
1190 conn = (SilcClientConnection)sock->user_data;
1192 /* XXX Free all client entries and channel entries. */
1194 /* Clear ID caches */
1195 silc_idcache_del_all(conn->client_cache);
1196 silc_idcache_del_all(conn->channel_cache);
1199 if (conn->remote_host)
1200 silc_free(conn->remote_host);
1202 silc_free(conn->local_id);
1203 if (conn->local_id_data)
1204 silc_free(conn->local_id_data);
1206 silc_cipher_free(conn->send_key);
1207 if (conn->receive_key)
1208 silc_cipher_free(conn->receive_key);
1210 silc_hmac_free(conn->hmac);
1211 if (conn->hmac_key) {
1212 memset(conn->hmac_key, 0, conn->hmac_key_len);
1213 silc_free(conn->hmac_key);
1215 if (conn->pending_commands)
1216 silc_dlist_uninit(conn->pending_commands);
1219 conn->remote_port = 0;
1220 conn->remote_type = 0;
1221 conn->send_key = NULL;
1222 conn->receive_key = NULL;
1224 conn->hmac_key = NULL;
1225 conn->hmac_key_len = 0;
1226 conn->local_id = NULL;
1227 conn->local_id_data = NULL;
1228 conn->remote_host = NULL;
1229 conn->current_channel = NULL;
1230 conn->pending_commands = NULL;
1232 silc_client_del_connection(client, conn);
1235 if (sock->protocol) {
1236 silc_protocol_free(sock->protocol);
1237 sock->protocol = NULL;
1239 silc_socket_free(sock);
1242 /* Called when we receive disconnection packet from server. This
1243 closes our end properly and displays the reason of the disconnection
1246 void silc_client_disconnected_by_server(SilcClient client,
1247 SilcSocketConnection sock,
1252 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1254 msg = silc_calloc(message->len + 1, sizeof(char));
1255 memcpy(msg, message->data, message->len);
1256 client->ops->say(client, sock->user_data, msg);
1259 SILC_SET_DISCONNECTED(sock);
1260 silc_client_close_connection(client, sock);
1263 /* Received error message from server. Display it on the screen.
1264 We don't take any action what so ever of the error message. */
1266 void silc_client_error_by_server(SilcClient client,
1267 SilcSocketConnection sock,
1272 msg = silc_calloc(message->len + 1, sizeof(char));
1273 memcpy(msg, message->data, message->len);
1274 client->ops->say(client, sock->user_data, msg);
1278 /* Called when notify is received and some async operation (such as command)
1279 is required before processing the notify message. This calls again the
1280 silc_client_notify_by_server and reprocesses the original notify packet. */
1282 static void silc_client_notify_by_server_pending(void *context)
1284 SilcPacketContext *p = (SilcPacketContext *)context;
1285 silc_client_notify_by_server(p->context, p->sock, p);
1288 /* Destructor for the pending command callback */
1290 static void silc_client_notify_by_server_destructor(void *context)
1292 silc_packet_context_free((SilcPacketContext *)context);
1295 /* Resolve client information from server by Client ID. */
1297 static void silc_client_notify_by_server_resolve(SilcClient client,
1298 SilcClientConnection conn,
1299 SilcPacketContext *packet,
1300 SilcClientID *client_id)
1302 SilcPacketContext *p = silc_packet_context_dup(packet);
1303 SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1305 p->context = (void *)client;
1306 p->sock = conn->sock;
1308 silc_client_send_command(client, conn, SILC_COMMAND_WHOIS, ++conn->cmd_ident,
1309 1, 3, idp->data, idp->len);
1310 silc_client_command_pending(conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
1311 silc_client_notify_by_server_destructor,
1312 silc_client_notify_by_server_pending, p);
1313 silc_buffer_free(idp);
1316 /* Received notify message from server */
1318 void silc_client_notify_by_server(SilcClient client,
1319 SilcSocketConnection sock,
1320 SilcPacketContext *packet)
1322 SilcBuffer buffer = packet->buffer;
1323 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1324 SilcNotifyPayload payload;
1325 SilcNotifyType type;
1326 SilcArgumentPayload args;
1328 SilcClientID *client_id = NULL;
1329 SilcChannelID *channel_id = NULL;
1330 SilcClientEntry client_entry;
1331 SilcClientEntry client_entry2;
1332 SilcChannelEntry channel;
1333 SilcChannelUser chu;
1334 SilcIDCacheEntry id_cache = NULL;
1336 unsigned int tmp_len, mode;
1338 payload = silc_notify_payload_parse(buffer);
1342 type = silc_notify_get_type(payload);
1343 args = silc_notify_get_args(payload);
1348 case SILC_NOTIFY_TYPE_NONE:
1349 /* Notify application */
1350 client->ops->notify(client, conn, type,
1351 silc_argument_get_arg_type(args, 1, NULL));
1354 case SILC_NOTIFY_TYPE_INVITE:
1356 * Someone invited me to a channel. Find Client and Channel entries
1357 * for the application.
1361 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1365 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1369 /* Find Client entry and if not found query it */
1370 client_entry = silc_idlist_get_client_by_id(client, conn, client_id);
1371 if (!client_entry) {
1372 silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1376 /* Get Channel ID */
1377 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1381 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1385 /* XXX Will ALWAYS fail because currently we don't have way to resolve
1386 channel information for channel that we're not joined to. */
1387 /* XXX ways to fix: use (extended) LIST command, or define the channel
1388 name to the notfy type when name resolving is not mandatory. */
1389 /* Find channel entry */
1390 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1391 SILC_ID_CHANNEL, &id_cache))
1394 channel = (SilcChannelEntry)id_cache->context;
1396 /* Notify application */
1397 client->ops->notify(client, conn, type, client_entry, channel);
1400 case SILC_NOTIFY_TYPE_JOIN:
1402 * Someone has joined to a channel. Get their ID and nickname and
1403 * cache them for later use.
1407 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1411 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1415 /* Find Client entry and if not found query it */
1416 client_entry = silc_idlist_get_client_by_id(client, conn, client_id);
1417 if (!client_entry) {
1418 silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1422 /* If nickname or username hasn't been resolved, do so */
1423 if (!client_entry->nickname || !client_entry->username) {
1424 silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1428 /* Get Channel ID */
1429 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1433 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1437 /* Get channel entry */
1438 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1439 SILC_ID_CHANNEL, &id_cache))
1442 channel = (SilcChannelEntry)id_cache->context;
1444 /* Add client to channel */
1445 chu = silc_calloc(1, sizeof(*chu));
1446 chu->client = client_entry;
1447 silc_list_add(channel->clients, chu);
1449 /* XXX add support for multiple same nicks on same channel. Check
1452 /* Notify application. The channel entry is sent last as this notify
1453 is for channel but application don't know it from the arguments
1455 client->ops->notify(client, conn, type, client_entry, channel);
1458 case SILC_NOTIFY_TYPE_LEAVE:
1460 * Someone has left a channel. We will remove it from the channel but
1461 * we'll keep it in the cache in case we'll need it later.
1465 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1469 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1473 /* Find Client entry */
1475 silc_idlist_get_client_by_id(client, conn, client_id);
1479 /* Get channel entry */
1480 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1484 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1485 SILC_ID_CHANNEL, &id_cache))
1488 channel = (SilcChannelEntry)id_cache->context;
1490 /* Remove client from channel */
1491 silc_list_start(channel->clients);
1492 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1493 if (chu->client == client_entry) {
1494 silc_list_del(channel->clients, chu);
1500 /* Notify application. The channel entry is sent last as this notify
1501 is for channel but application don't know it from the arguments
1503 client->ops->notify(client, conn, type, client_entry, channel);
1506 case SILC_NOTIFY_TYPE_SIGNOFF:
1508 * Someone left SILC. We'll remove it from all channels and from cache.
1512 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1516 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1520 /* Find Client entry */
1522 silc_idlist_get_client_by_id(client, conn, client_id);
1526 /* Remove from all channels */
1527 silc_client_remove_from_channels(client, conn, client_entry);
1529 /* Remove from cache */
1530 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT,
1533 /* Get signoff message */
1534 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1538 /* Notify application */
1539 client->ops->notify(client, conn, type, client_entry, tmp);
1542 if (client_entry->nickname)
1543 silc_free(client_entry->nickname);
1544 if (client_entry->server)
1545 silc_free(client_entry->server);
1546 if (client_entry->id)
1547 silc_free(client_entry->id);
1548 if (client_entry->send_key)
1549 silc_cipher_free(client_entry->send_key);
1550 if (client_entry->receive_key)
1551 silc_cipher_free(client_entry->receive_key);
1554 case SILC_NOTIFY_TYPE_TOPIC_SET:
1556 * Someone set the topic on a channel.
1560 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1564 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1568 /* Find Client entry */
1570 silc_idlist_get_client_by_id(client, conn, client_id);
1575 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1579 /* Get channel entry */
1580 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1584 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1585 SILC_ID_CHANNEL, &id_cache))
1588 channel = (SilcChannelEntry)id_cache->context;
1590 /* Notify application. The channel entry is sent last as this notify
1591 is for channel but application don't know it from the arguments
1593 client->ops->notify(client, conn, type, client_entry, tmp, channel);
1596 case SILC_NOTIFY_TYPE_NICK_CHANGE:
1598 * Someone changed their nickname. If we don't have entry for the new
1599 * ID we will query it and return here after it's done. After we've
1600 * returned we fetch the old entry and free it and notify the
1604 /* Get new Client ID */
1605 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1609 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1614 if (!SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
1617 /* Find Client entry and if not found query it */
1619 silc_idlist_get_client_by_id(client, conn, client_id);
1620 if (!client_entry2) {
1621 silc_client_notify_by_server_resolve(client, conn, packet, client_id);
1624 silc_free(client_id);
1626 /* Get old Client ID */
1627 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1631 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1635 /* Find old Client entry */
1637 silc_idlist_get_client_by_id(client, conn, client_id);
1641 /* Remove the old from cache */
1642 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT,
1645 /* Replace old ID entry with new one on all channels. */
1646 silc_client_replace_from_channels(client, conn, client_entry,
1649 /* Notify application */
1650 client->ops->notify(client, conn, type, client_entry, client_entry2);
1653 if (client_entry->nickname)
1654 silc_free(client_entry->nickname);
1655 if (client_entry->server)
1656 silc_free(client_entry->server);
1657 if (client_entry->id)
1658 silc_free(client_entry->id);
1659 if (client_entry->send_key)
1660 silc_cipher_free(client_entry->send_key);
1661 if (client_entry->receive_key)
1662 silc_cipher_free(client_entry->receive_key);
1665 case SILC_NOTIFY_TYPE_CMODE_CHANGE:
1667 * Someone changed a channel mode
1671 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1675 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1679 /* Find Client entry */
1681 silc_idlist_get_client_by_id(client, conn, client_id);
1686 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1690 SILC_GET32_MSB(mode, tmp);
1692 /* Get channel entry */
1693 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1697 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1698 SILC_ID_CHANNEL, &id_cache))
1701 channel = (SilcChannelEntry)id_cache->context;
1703 /* Save the new mode */
1704 channel->mode = mode;
1706 /* Notify application. The channel entry is sent last as this notify
1707 is for channel but application don't know it from the arguments
1709 client->ops->notify(client, conn, type, client_entry, mode, channel);
1712 case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1714 * Someone changed user's mode on a channel
1718 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1722 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1726 /* Find Client entry */
1728 silc_idlist_get_client_by_id(client, conn, client_id);
1733 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1737 SILC_GET32_MSB(mode, tmp);
1739 /* Get target Client ID */
1740 tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1744 silc_free(client_id);
1745 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1749 /* Find target Client entry */
1751 silc_idlist_get_client_by_id(client, conn, client_id);
1755 /* Get channel entry */
1756 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1760 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1761 SILC_ID_CHANNEL, &id_cache))
1764 channel = (SilcChannelEntry)id_cache->context;
1767 silc_list_start(channel->clients);
1768 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1769 if (chu->client == client_entry) {
1775 /* Notify application. The channel entry is sent last as this notify
1776 is for channel but application don't know it from the arguments
1778 client->ops->notify(client, conn, type, client_entry, mode,
1779 client_entry2, channel);
1782 case SILC_NOTIFY_TYPE_MOTD:
1784 * Received Message of the day
1788 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1792 /* Notify application */
1793 client->ops->notify(client, conn, type, tmp);
1796 case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
1798 * Router has enforced a new ID to a channel. Let's change the old
1799 * ID to the one provided here.
1802 /* Get the old ID */
1803 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1806 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1810 /* Get the channel entry */
1811 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1812 SILC_ID_CHANNEL, &id_cache))
1815 channel = (SilcChannelEntry)id_cache->context;
1817 /* Free the old ID */
1818 silc_free(channel_id);
1819 silc_free(channel->id);
1821 /* Get the new ID */
1822 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1825 channel->id = silc_id_payload_parse_id(tmp, tmp_len);
1829 id_cache->id = (void *)channel->id;
1831 /* Notify application */
1832 client->ops->notify(client, conn, type, channel, channel);
1835 case SILC_NOTIFY_TYPE_KICKED:
1837 * A client (maybe me) was kicked from a channel
1841 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1845 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1849 /* Find Client entry */
1851 silc_idlist_get_client_by_id(client, conn, client_id);
1855 /* Get channel entry */
1856 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1860 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1861 SILC_ID_CHANNEL, &id_cache))
1864 channel = (SilcChannelEntry)id_cache->context;
1867 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1869 /* Notify application. The channel entry is sent last as this notify
1870 is for channel but application don't know it from the arguments
1872 client->ops->notify(client, conn, type, client_entry, tmp, channel);
1874 /* If I was kicked from channel, remove the channel */
1875 if (client_entry == conn->local_entry) {
1876 if (conn->current_channel == channel)
1877 conn->current_channel = NULL;
1878 silc_idcache_del_by_id(conn->channel_cache,
1879 SILC_ID_CHANNEL, channel->id);
1880 silc_free(channel->channel_name);
1881 silc_free(channel->id);
1882 silc_free(channel->key);
1883 silc_cipher_free(channel->channel_key);
1893 silc_notify_payload_free(payload);
1895 silc_free(client_id);
1897 silc_free(channel_id);
1900 /* Processes the received new Client ID from server. Old Client ID is
1901 deleted from cache and new one is added. */
1903 void silc_client_receive_new_id(SilcClient client,
1904 SilcSocketConnection sock,
1907 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1908 int connecting = FALSE;
1910 if (!conn->local_entry)
1913 /* Delete old ID from ID cache */
1914 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1916 /* Save the new ID */
1918 silc_free(conn->local_id);
1919 if (conn->local_id_data)
1920 silc_free(conn->local_id_data);
1922 conn->local_id = silc_id_payload_get_id(idp);
1923 conn->local_id_data = silc_id_payload_get_data(idp);
1924 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1926 if (!conn->local_entry)
1927 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1929 conn->local_entry->nickname = conn->nickname;
1930 if (!conn->local_entry->username) {
1931 conn->local_entry->username =
1932 silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1933 sizeof(conn->local_entry->username));
1934 sprintf(conn->local_entry->username, "%s@%s", client->username,
1937 conn->local_entry->server = strdup(conn->remote_host);
1938 conn->local_entry->id = conn->local_id;
1940 /* Put it to the ID cache */
1941 silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1942 conn->local_id, (void *)conn->local_entry, TRUE);
1944 /* Notify application of successful connection. We do it here now that
1945 we've received the Client ID and are allowed to send traffic. */
1947 client->ops->connect(client, conn, TRUE);
1950 /* Processed received Channel ID for a channel. This is called when client
1951 joins to channel and server replies with channel ID. The ID is cached. */
1953 void silc_client_new_channel_id(SilcClient client,
1954 SilcSocketConnection sock,
1956 unsigned int mode, SilcIDPayload idp)
1958 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1959 SilcChannelEntry channel;
1961 SILC_LOG_DEBUG(("New channel ID"));
1963 channel = silc_calloc(1, sizeof(*channel));
1964 channel->channel_name = channel_name;
1965 channel->id = silc_id_payload_get_id(idp);
1966 channel->mode = mode;
1967 silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1969 conn->current_channel = channel;
1971 /* Put it to the ID cache */
1972 silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1973 (void *)channel->id, (void *)channel, TRUE);
1976 /* Saves channel key from encoded `key_payload'. This is used when we
1977 receive Channel Key Payload and when we are processing JOIN command
1980 void silc_client_save_channel_key(SilcClientConnection conn,
1981 SilcBuffer key_payload,
1982 SilcChannelEntry channel)
1984 unsigned char *id_string, *key, *cipher;
1985 unsigned int tmp_len;
1987 SilcIDCacheEntry id_cache = NULL;
1988 SilcChannelKeyPayload payload;
1990 payload = silc_channel_key_payload_parse(key_payload);
1994 id_string = silc_channel_key_get_id(payload, &tmp_len);
1996 silc_channel_key_payload_free(payload);
2000 id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
2002 silc_channel_key_payload_free(payload);
2008 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2009 SILC_ID_CHANNEL, &id_cache))
2012 /* Get channel entry */
2013 channel = (SilcChannelEntry)id_cache->context;
2017 key = silc_channel_key_get_key(payload, &tmp_len);
2018 cipher = silc_channel_key_get_cipher(payload, NULL);
2019 channel->key_len = tmp_len * 8;
2020 channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
2021 memcpy(channel->key, key, tmp_len);
2023 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
2024 conn->client->ops->say(conn->client, conn,
2025 "Cannot talk to channel: unsupported cipher %s", cipher);
2028 channel->channel_key->cipher->set_key(channel->channel_key->context,
2029 key, channel->key_len);
2031 /* Client is now joined to the channel */
2032 channel->on_channel = TRUE;
2036 silc_channel_key_payload_free(payload);
2039 /* Processes received key for channel. The received key will be used
2040 to protect the traffic on the channel for now on. Client must receive
2041 the key to the channel before talking on the channel is possible.
2042 This is the key that server has generated, this is not the channel
2043 private key, it is entirely local setting. */
2045 void silc_client_receive_channel_key(SilcClient client,
2046 SilcSocketConnection sock,
2049 SILC_LOG_DEBUG(("Received key for channel"));
2052 silc_client_save_channel_key(sock->user_data, packet, NULL);
2055 /* Process received message to a channel (or from a channel, really). This
2056 decrypts the channel message with channel specific key and parses the
2057 channel payload. Finally it displays the message on the screen. */
2059 void silc_client_channel_message(SilcClient client,
2060 SilcSocketConnection sock,
2061 SilcPacketContext *packet)
2063 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2064 SilcBuffer buffer = packet->buffer;
2065 SilcChannelPayload payload = NULL;
2066 SilcChannelID *id = NULL;
2067 SilcChannelEntry channel;
2068 SilcChannelUser chu;
2069 SilcIDCacheEntry id_cache = NULL;
2070 SilcClientID *client_id = NULL;
2074 if (packet->dst_id_type != SILC_ID_CHANNEL)
2077 client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2081 id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
2085 /* Find the channel entry from channels on this connection */
2086 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2087 SILC_ID_CHANNEL, &id_cache))
2090 channel = (SilcChannelEntry)id_cache->context;
2092 SILC_LOG_HEXDUMP(("channel key"), channel->key, channel->key_len);
2094 /* Decrypt the channel message payload. Push the IV out of the way,
2095 since it is not encrypted (after pushing buffer->tail has the IV). */
2096 SILC_LOG_HEXDUMP(("Packet"), buffer->data, buffer->len);
2097 silc_buffer_push_tail(buffer, channel->channel_key->cipher->block_len);
2098 SILC_LOG_HEXDUMP(("Packet"), buffer->data, buffer->len);
2099 SILC_LOG_HEXDUMP(("IV"), buffer->tail, 16);
2100 channel->channel_key->cipher->decrypt(channel->channel_key->context,
2101 buffer->data, buffer->data,
2102 buffer->len, buffer->tail);
2103 SILC_LOG_HEXDUMP(("Packet"), buffer->data, buffer->len);
2104 silc_buffer_pull_tail(buffer, channel->channel_key->cipher->block_len);
2105 SILC_LOG_HEXDUMP(("Packet"), buffer->data, buffer->len);
2107 /* Parse the channel message payload */
2108 payload = silc_channel_payload_parse(buffer);
2112 /* Find client entry */
2113 silc_list_start(channel->clients);
2114 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2115 if (!SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
2121 /* Pass the message to application */
2122 client->ops->channel_message(client, conn, found ? chu->client : NULL,
2123 channel, silc_channel_get_data(payload, NULL));
2129 silc_free(client_id);
2131 silc_channel_payload_free(payload);
2134 /* Private message received. This processes the private message and
2135 finally displays it on the screen. */
2137 void silc_client_private_message(SilcClient client,
2138 SilcSocketConnection sock,
2139 SilcPacketContext *packet)
2141 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2142 SilcBuffer buffer = packet->buffer;
2143 SilcIDCacheEntry id_cache;
2144 SilcClientID *remote_id = NULL;
2145 SilcClientEntry remote_client;
2146 unsigned short nick_len;
2147 unsigned char *nickname, *message = NULL;
2150 if (packet->src_id_type != SILC_ID_CLIENT)
2154 ret = silc_buffer_unformat(buffer,
2155 SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
2160 silc_buffer_pull(buffer, 2 + nick_len);
2162 message = silc_calloc(buffer->len + 1, sizeof(char));
2163 memcpy(message, buffer->data, buffer->len);
2165 remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2170 /* Check whether we know this client already */
2171 if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
2172 SILC_ID_CLIENT, &id_cache))
2174 /* Allocate client entry */
2175 remote_client = silc_calloc(1, sizeof(*remote_client));
2176 remote_client->id = remote_id;
2177 silc_parse_nickname(nickname, &remote_client->nickname,
2178 &remote_client->server, &remote_client->num);
2180 /* Save the client to cache */
2181 silc_idcache_add(conn->client_cache, remote_client->nickname,
2182 SILC_ID_CLIENT, remote_client->id, remote_client,
2185 remote_client = (SilcClientEntry)id_cache->context;
2188 /* Pass the private message to application */
2189 client->ops->private_message(client, conn, remote_client, message);
2191 /* See if we are away (gone). If we are away we will reply to the
2192 sender with the set away message. */
2193 if (conn->away && conn->away->away) {
2194 /* If it's me, ignore */
2195 if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
2198 /* Send the away message */
2199 silc_client_packet_send_private_message(client, sock, remote_client,
2201 strlen(conn->away->away), TRUE);
2206 silc_free(remote_id);
2209 memset(message, 0, buffer->len);
2212 silc_free(nickname);
2215 /* Removes a client entry from all channel it has joined. This really is
2216 a performance killer (client_entry should have pointers to channel
2219 void silc_client_remove_from_channels(SilcClient client,
2220 SilcClientConnection conn,
2221 SilcClientEntry client_entry)
2223 SilcIDCacheEntry id_cache;
2224 SilcIDCacheList list;
2225 SilcChannelEntry channel;
2226 SilcChannelUser chu;
2228 if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2229 SILC_ID_CHANNEL, &list))
2232 silc_idcache_list_first(list, &id_cache);
2233 channel = (SilcChannelEntry)id_cache->context;
2237 /* Remove client from channel */
2238 silc_list_start(channel->clients);
2239 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2240 if (chu->client == client_entry) {
2241 silc_list_del(channel->clients, chu);
2247 if (!silc_idcache_list_next(list, &id_cache))
2250 channel = (SilcChannelEntry)id_cache->context;
2253 silc_idcache_list_free(list);
2256 /* Replaces `old' client entries from all channels to `new' client entry.
2257 This can be called for example when nickname changes and old ID entry
2258 is replaced from ID cache with the new one. If the old ID entry is only
2259 updated, then this fucntion needs not to be called. */
2261 void silc_client_replace_from_channels(SilcClient client,
2262 SilcClientConnection conn,
2263 SilcClientEntry old,
2264 SilcClientEntry new)
2266 SilcIDCacheEntry id_cache;
2267 SilcIDCacheList list;
2268 SilcChannelEntry channel;
2269 SilcChannelUser chu;
2271 if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2272 SILC_ID_CHANNEL, &list))
2275 silc_idcache_list_first(list, &id_cache);
2276 channel = (SilcChannelEntry)id_cache->context;
2280 /* Replace client entry */
2281 silc_list_start(channel->clients);
2282 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2283 if (chu->client == old) {
2289 if (!silc_idcache_list_next(list, &id_cache))
2292 channel = (SilcChannelEntry)id_cache->context;
2295 silc_idcache_list_free(list);
2298 /* Parses mode mask and returns the mode as string. */
2300 char *silc_client_chmode(unsigned int mode)
2307 memset(string, 0, sizeof(string));
2309 if (mode & SILC_CHANNEL_MODE_PRIVATE)
2310 strncat(string, "p", 1);
2312 if (mode & SILC_CHANNEL_MODE_SECRET)
2313 strncat(string, "s", 1);
2315 if (mode & SILC_CHANNEL_MODE_PRIVKEY)
2316 strncat(string, "k", 1);
2318 if (mode & SILC_CHANNEL_MODE_INVITE)
2319 strncat(string, "i", 1);
2321 if (mode & SILC_CHANNEL_MODE_TOPIC)
2322 strncat(string, "t", 1);
2324 if (mode & SILC_CHANNEL_MODE_ULIMIT)
2325 strncat(string, "l", 1);
2327 if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
2328 strncat(string, "a", 1);
2330 /* Rest of mode is ignored */
2332 return strdup(string);
2335 /* Parses channel user mode mask and returns te mode as string */
2337 char *silc_client_chumode(unsigned int mode)
2344 memset(string, 0, sizeof(string));
2346 if (mode & SILC_CHANNEL_UMODE_CHANFO)
2347 strncat(string, "f", 1);
2349 if (mode & SILC_CHANNEL_UMODE_CHANOP)
2350 strncat(string, "o", 1);
2352 return strdup(string);
2355 /* Parses channel user mode and returns it as special mode character. */
2357 char *silc_client_chumode_char(unsigned int mode)
2364 memset(string, 0, sizeof(string));
2366 if (mode & SILC_CHANNEL_UMODE_CHANFO)
2367 strncat(string, "*", 1);
2369 if (mode & SILC_CHANNEL_UMODE_CHANOP)
2370 strncat(string, "@", 1);
2372 return strdup(string);