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)
61 /* Initializes the client. This makes all the necessary steps to make
62 the client ready to be run. One must call silc_client_run to run the
65 int silc_client_init(SilcClient client)
67 SILC_LOG_DEBUG(("Initializing client"));
69 /* Initialize hash functions for client to use */
70 silc_hash_alloc("md5", &client->md5hash);
71 silc_hash_alloc("sha1", &client->sha1hash);
73 /* Initialize none cipher */
74 silc_cipher_alloc("none", &client->none_cipher);
76 /* Initialize random number generator */
77 client->rng = silc_rng_alloc();
78 silc_rng_init(client->rng);
79 silc_math_primegen_init(); /* XXX */
81 /* Register protocols */
82 silc_client_protocols_register();
84 /* Initialize the scheduler */
85 silc_schedule_init(&client->io_queue, &client->timeout_queue,
86 &client->generic_queue, 5000);
91 /* Stops the client. This is called to stop the client and thus to stop
94 void silc_client_stop(SilcClient client)
96 SILC_LOG_DEBUG(("Stopping client"));
98 /* Stop the scheduler, although it might be already stopped. This
99 doesn't hurt anyone. This removes all the tasks and task queues,
101 silc_schedule_stop();
102 silc_schedule_uninit();
104 silc_client_protocols_unregister();
106 SILC_LOG_DEBUG(("Client stopped"));
109 /* Runs the client. */
111 void silc_client_run(SilcClient client)
113 SILC_LOG_DEBUG(("Running client"));
115 /* Start the scheduler, the heart of the SILC client. When this returns
116 the program will be terminated. */
120 /* Allocates and adds new connection to the client. This adds the allocated
121 connection to the connection table and returns a pointer to it. A client
122 can have multiple connections to multiple servers. Every connection must
123 be added to the client using this function. User data `context' may
124 be sent as argument. */
126 SilcClientConnection silc_client_add_connection(SilcClient client,
131 SilcClientConnection conn;
134 conn = silc_calloc(1, sizeof(*conn));
136 /* Initialize ID caches */
137 conn->client_cache = silc_idcache_alloc(0);
138 conn->channel_cache = silc_idcache_alloc(0);
139 conn->server_cache = silc_idcache_alloc(0);
140 conn->client = client;
141 conn->remote_host = strdup(hostname);
142 conn->remote_port = port;
143 conn->context = context;
144 conn->pending_commands = silc_dlist_init();
146 /* Add the connection to connections table */
147 for (i = 0; i < client->conns_count; i++)
148 if (client->conns && !client->conns[i]) {
149 client->conns[i] = conn;
153 client->conns = silc_realloc(client->conns, sizeof(*client->conns)
154 * (client->conns_count + 1));
155 client->conns[client->conns_count] = conn;
156 client->conns_count++;
161 /* Removes connection from client. */
163 void silc_client_del_connection(SilcClient client, SilcClientConnection conn)
167 for (i = 0; i < client->conns_count; i++)
168 if (client->conns[i] == conn) {
169 if (conn->pending_commands)
170 silc_dlist_uninit(conn->pending_commands);
172 client->conns[i] = NULL;
176 /* Internal context for connection process. This is needed as we
177 doing asynchronous connecting. */
180 SilcClientConnection conn;
186 } SilcClientInternalConnectContext;
189 silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
193 /* XXX In the future we should give up this non-blocking connect all
194 together and use threads instead. */
195 /* Create connection to server asynchronously */
196 sock = silc_net_create_connection_async(ctx->port, ctx->host);
200 /* Register task that will receive the async connect and will
202 ctx->task = silc_task_register(ctx->client->io_queue, sock,
203 silc_client_connect_to_server_start,
206 SILC_TASK_PRI_NORMAL);
207 silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
208 silc_schedule_set_listen_fd(sock, ctx->task->iomask);
215 /* Connects to remote server. This is the main routine used to connect
216 to SILC server. Returns -1 on error and the created socket otherwise.
217 The `context' is user context that is saved into the SilcClientConnection
218 that is created after the connection is created. */
220 int silc_client_connect_to_server(SilcClient client, int port,
221 char *host, void *context)
223 SilcClientInternalConnectContext *ctx;
224 SilcClientConnection conn;
227 SILC_LOG_DEBUG(("Connecting to port %d of server %s",
230 conn = silc_client_add_connection(client, host, port, context);
232 client->ops->say(client, conn,
233 "Connecting to port %d of server %s", port, host);
235 /* Allocate internal context for connection process. This is
236 needed as we are doing async connecting. */
237 ctx = silc_calloc(1, sizeof(*ctx));
238 ctx->client = client;
240 ctx->host = strdup(host);
244 /* Do the actual connecting process */
245 sock = silc_client_connect_to_server_internal(ctx);
247 silc_client_del_connection(client, conn);
251 /* Start SILC Key Exchange (SKE) protocol to negotiate shared secret
252 key material between client and server. This function can be called
253 directly if application is performing its own connecting and does not
254 use the connecting provided by this library. */
256 int silc_client_start_key_exchange(SilcClient client,
257 SilcClientConnection conn,
260 SilcProtocol protocol;
261 SilcClientKEInternalContext *proto_ctx;
264 /* Allocate new socket connection object */
265 silc_socket_alloc(fd, SILC_SOCKET_TYPE_SERVER, (void *)conn, &conn->sock);
266 if (conn->sock == NULL) {
267 client->ops->say(client, conn,
268 "Error: Could not allocate connection socket");
272 conn->nickname = strdup(client->username);
273 conn->sock->hostname = conn->remote_host;
274 conn->sock->port = conn->remote_port;
276 /* Allocate internal Key Exchange context. This is sent to the
277 protocol as context. */
278 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
279 proto_ctx->client = (void *)client;
280 proto_ctx->sock = conn->sock;
281 proto_ctx->rng = client->rng;
282 proto_ctx->responder = FALSE;
284 /* Perform key exchange protocol. silc_client_connect_to_server_final
285 will be called after the protocol is finished. */
286 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
287 &protocol, (void *)proto_ctx,
288 silc_client_connect_to_server_second);
290 client->ops->say(client, conn,
291 "Error: Could not start authentication protocol");
294 conn->sock->protocol = protocol;
296 /* Register the connection for network input and output. This sets
297 that scheduler will listen for incoming packets for this connection
298 and sets that outgoing packets may be sent to this connection as well.
299 However, this doesn't set the scheduler for outgoing traffic, it will
300 be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
301 later when outgoing data is available. */
302 context = (void *)client;
303 SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
305 /* Execute the protocol */
306 protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
310 /* Start of the connection to the remote server. This is called after
311 succesful TCP/IP connection has been established to the remote host. */
313 SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
315 SilcClientInternalConnectContext *ctx =
316 (SilcClientInternalConnectContext *)context;
317 SilcClient client = ctx->client;
318 SilcClientConnection conn = ctx->conn;
319 int opt, opt_len = sizeof(opt);
321 SILC_LOG_DEBUG(("Start"));
323 /* Check the socket status as it might be in error */
324 getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
326 if (ctx->tries < 2) {
327 /* Connection failed but lets try again */
328 client->ops->say(client, conn, "Could not connect to server %s: %s",
329 ctx->host, strerror(opt));
330 client->ops->say(client, conn,
331 "Connecting to port %d of server %s resumed",
332 ctx->port, ctx->host);
334 /* Unregister old connection try */
335 silc_schedule_unset_listen_fd(fd);
336 silc_net_close_connection(fd);
337 silc_task_unregister(client->io_queue, ctx->task);
340 silc_client_connect_to_server_internal(ctx);
343 /* Connection failed and we won't try anymore */
344 client->ops->say(client, conn, "Could not connect to server %s: %s",
345 ctx->host, strerror(opt));
346 silc_schedule_unset_listen_fd(fd);
347 silc_net_close_connection(fd);
348 silc_task_unregister(client->io_queue, ctx->task);
351 /* Notify application of failure */
352 client->ops->connect(client, conn, FALSE);
353 silc_client_del_connection(client, conn);
358 silc_schedule_unset_listen_fd(fd);
359 silc_task_unregister(client->io_queue, ctx->task);
362 if (!silc_client_start_key_exchange(client, conn, fd)) {
363 silc_net_close_connection(fd);
364 client->ops->connect(client, conn, FALSE);
368 /* Second part of the connecting to the server. This executed
369 authentication protocol. */
371 SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
373 SilcProtocol protocol = (SilcProtocol)context;
374 SilcClientKEInternalContext *ctx =
375 (SilcClientKEInternalContext *)protocol->context;
376 SilcClient client = (SilcClient)ctx->client;
377 SilcSocketConnection sock = NULL;
378 SilcClientConnAuthInternalContext *proto_ctx;
380 SILC_LOG_DEBUG(("Start"));
382 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
383 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
384 /* Error occured during protocol */
385 SILC_LOG_DEBUG(("Error during KE protocol"));
386 silc_protocol_free(protocol);
388 silc_ske_free(ctx->ske);
390 silc_free(ctx->dest_id);
391 ctx->sock->protocol = NULL;
393 /* Notify application of failure */
394 client->ops->connect(client, ctx->sock->user_data, FALSE);
399 /* Allocate internal context for the authentication protocol. This
400 is sent as context for the protocol. */
401 proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
402 proto_ctx->client = (void *)client;
403 proto_ctx->sock = sock = ctx->sock;
404 proto_ctx->ske = ctx->ske; /* Save SKE object from previous protocol */
405 proto_ctx->dest_id_type = ctx->dest_id_type;
406 proto_ctx->dest_id = ctx->dest_id;
408 /* Resolve the authentication method to be used in this connection */
409 if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
410 sock->port, &proto_ctx->auth_meth,
411 &proto_ctx->auth_data,
412 &proto_ctx->auth_data_len))
414 /* XXX do AUTH_REQUEST resolcing with server */
415 proto_ctx->auth_meth = SILC_PROTOCOL_CONN_AUTH_NONE;
418 /* Free old protocol as it is finished now */
419 silc_protocol_free(protocol);
421 silc_packet_context_free(ctx->packet);
423 /* silc_free(ctx->keymat....); */
424 sock->protocol = NULL;
426 /* Allocate the authentication protocol. This is allocated here
427 but we won't start it yet. We will be receiving party of this
428 protocol thus we will wait that connecting party will make
430 silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH,
431 &sock->protocol, (void *)proto_ctx,
432 silc_client_connect_to_server_final);
434 /* Execute the protocol */
435 sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
438 /* Finalizes the connection to the remote SILC server. This is called
439 after authentication protocol has been completed. This send our
440 user information to the server to receive our client ID from
443 SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
445 SilcProtocol protocol = (SilcProtocol)context;
446 SilcClientConnAuthInternalContext *ctx =
447 (SilcClientConnAuthInternalContext *)protocol->context;
448 SilcClient client = (SilcClient)ctx->client;
449 SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
452 SILC_LOG_DEBUG(("Start"));
454 if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
455 protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
456 /* Error occured during protocol */
457 SILC_LOG_DEBUG(("Error during authentication protocol"));
458 silc_protocol_free(protocol);
460 silc_free(ctx->auth_data);
462 silc_ske_free(ctx->ske);
464 silc_free(ctx->dest_id);
465 conn->sock->protocol = NULL;
467 /* Notify application of failure */
468 client->ops->connect(client, ctx->sock->user_data, FALSE);
473 /* Send NEW_CLIENT packet to the server. We will become registered
474 to the SILC network after sending this packet and we will receive
475 client ID from the server. */
476 packet = silc_buffer_alloc(2 + 2 + strlen(client->username) +
477 strlen(client->realname));
478 silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
479 silc_buffer_format(packet,
480 SILC_STR_UI_SHORT(strlen(client->username)),
481 SILC_STR_UI_XNSTRING(client->username,
482 strlen(client->username)),
483 SILC_STR_UI_SHORT(strlen(client->realname)),
484 SILC_STR_UI_XNSTRING(client->realname,
485 strlen(client->realname)),
488 /* Send the packet */
489 silc_client_packet_send(client, ctx->sock, SILC_PACKET_NEW_CLIENT,
491 packet->data, packet->len, TRUE);
492 silc_buffer_free(packet);
494 /* Save remote ID. */
495 conn->remote_id = ctx->dest_id;
496 conn->remote_id_data = silc_id_id2str(ctx->dest_id, SILC_ID_SERVER);
497 conn->remote_id_data_len = SILC_ID_SERVER_LEN;
499 silc_protocol_free(protocol);
501 silc_free(ctx->auth_data);
503 silc_ske_free(ctx->ske);
505 conn->sock->protocol = NULL;
508 /* Internal routine that sends packet or marks packet to be sent. This
509 is used directly only in special cases. Normal cases should use
510 silc_server_packet_send. Returns < 0 on error. */
512 static int silc_client_packet_send_real(SilcClient client,
513 SilcSocketConnection sock,
518 /* Send the packet */
519 ret = silc_packet_send(sock, force_send);
523 /* Mark that there is some outgoing data available for this connection.
524 This call sets the connection both for input and output (the input
525 is set always and this call keeps the input setting, actually).
526 Actual data sending is performed by silc_client_packet_process. */
527 SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
529 /* Mark to socket that data is pending in outgoing buffer. This flag
530 is needed if new data is added to the buffer before the earlier
531 put data is sent to the network. */
532 SILC_SET_OUTBUF_PENDING(sock);
537 /* Packet processing callback. This is used to send and receive packets
538 from network. This is generic task. */
540 SILC_TASK_CALLBACK(silc_client_packet_process)
542 SilcClient client = (SilcClient)context;
543 SilcSocketConnection sock = NULL;
544 SilcClientConnection conn;
547 SILC_LOG_DEBUG(("Processing packet"));
549 SILC_CLIENT_GET_SOCK(client, fd, sock);
553 conn = (SilcClientConnection)sock->user_data;
556 if (type == SILC_TASK_WRITE) {
557 SILC_LOG_DEBUG(("Writing data to connection"));
559 if (sock->outbuf->data - sock->outbuf->head)
560 silc_buffer_push(sock->outbuf,
561 sock->outbuf->data - sock->outbuf->head);
563 ret = silc_client_packet_send_real(client, sock, TRUE);
565 /* If returned -2 could not write to connection now, will do
570 /* The packet has been sent and now it is time to set the connection
571 back to only for input. When there is again some outgoing data
572 available for this connection it will be set for output as well.
573 This call clears the output setting and sets it only for input. */
574 SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
575 SILC_UNSET_OUTBUF_PENDING(sock);
577 silc_buffer_clear(sock->outbuf);
581 /* Packet receiving */
582 if (type == SILC_TASK_READ) {
583 SILC_LOG_DEBUG(("Reading data from connection"));
585 /* Read data from network */
586 ret = silc_packet_receive(sock);
592 SILC_LOG_DEBUG(("Read EOF"));
594 /* If connection is disconnecting already we will finally
595 close the connection */
596 if (SILC_IS_DISCONNECTING(sock)) {
597 client->ops->disconnect(client, conn);
598 silc_client_close_connection(client, sock);
602 client->ops->say(client, conn, "Connection closed: premature EOF");
603 SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
604 client->ops->disconnect(client, conn);
605 silc_client_close_connection(client, sock);
609 /* Process the packet. This will call the parser that will then
610 decrypt and parse the packet. */
611 silc_packet_receive_process(sock, conn->receive_key, conn->hmac,
612 silc_client_packet_parse, client);
616 /* Parses whole packet, received earlier. */
618 SILC_TASK_CALLBACK(silc_client_packet_parse_real)
620 SilcPacketParserContext *parse_ctx = (SilcPacketParserContext *)context;
621 SilcClient client = (SilcClient)parse_ctx->context;
622 SilcPacketContext *packet = parse_ctx->packet;
623 SilcBuffer buffer = packet->buffer;
624 SilcSocketConnection sock = parse_ctx->sock;
625 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
628 SILC_LOG_DEBUG(("Start"));
630 /* Decrypt the received packet */
631 ret = silc_packet_decrypt(conn->receive_key, conn->hmac, buffer, packet);
636 /* Parse the packet. Packet type is returned. */
637 ret = silc_packet_parse(packet);
639 /* Parse the packet header in special way as this is "special"
641 ret = silc_packet_parse_special(packet);
644 if (ret == SILC_PACKET_NONE)
647 /* Parse the incoming packet type */
648 silc_client_packet_parse_type(client, sock, packet);
651 silc_buffer_clear(sock->inbuf);
652 silc_packet_context_free(packet);
653 silc_free(parse_ctx);
656 /* Parser callback called by silc_packet_receive_process. Thie merely
657 registers timeout that will handle the actual parsing when appropriate. */
659 void silc_client_packet_parse(SilcPacketParserContext *parser_context)
661 SilcClient client = (SilcClient)parser_context->context;
663 /* Parse the packet */
664 silc_task_register(client->timeout_queue, parser_context->sock->sock,
665 silc_client_packet_parse_real,
666 (void *)parser_context, 0, 1,
668 SILC_TASK_PRI_NORMAL);
671 /* Parses the packet type and calls what ever routines the packet type
672 requires. This is done for all incoming packets. */
674 void silc_client_packet_parse_type(SilcClient client,
675 SilcSocketConnection sock,
676 SilcPacketContext *packet)
678 SilcBuffer buffer = packet->buffer;
679 SilcPacketType type = packet->type;
681 SILC_LOG_DEBUG(("Parsing packet type %d", type));
683 /* Parse the packet type */
685 case SILC_PACKET_DISCONNECT:
686 silc_client_disconnected_by_server(client, sock, buffer);
688 case SILC_PACKET_SUCCESS:
690 * Success received for something. For now we can have only
691 * one protocol for connection executing at once hence this
692 * success message is for whatever protocol is executing currently.
694 if (sock->protocol) {
695 sock->protocol->execute(client->timeout_queue, 0,
696 sock->protocol, sock->sock, 0, 0);
699 case SILC_PACKET_FAILURE:
701 * Failure received for some protocol. Set the protocol state to
702 * error and call the protocol callback. This fill cause error on
703 * protocol and it will call the final callback.
705 if (sock->protocol) {
706 sock->protocol->state = SILC_PROTOCOL_STATE_FAILURE;
707 sock->protocol->execute(client->timeout_queue, 0,
708 sock->protocol, sock->sock, 0, 0);
710 /* XXX We have only two protocols currently thus we know what this
711 failure indication is. */
712 if (buffer->len >= 4) {
713 unsigned int failure;
715 SILC_GET32_MSB(failure, buffer->data);
717 /* Notify application */
718 client->ops->failure(client, sock->user_data, sock->protocol,
723 case SILC_PACKET_REJECT:
726 case SILC_PACKET_NOTIFY:
728 * Received notify message
730 silc_client_notify_by_server(client, sock, packet);
733 case SILC_PACKET_ERROR:
735 * Received error message
737 silc_client_error_by_server(client, sock, buffer);
740 case SILC_PACKET_CHANNEL_MESSAGE:
742 * Received message to (from, actually) a channel
744 silc_client_channel_message(client, sock, packet);
746 case SILC_PACKET_CHANNEL_KEY:
748 * Received key for a channel. By receiving this key the client will be
749 * able to talk to the channel it has just joined. This can also be
750 * a new key for existing channel as keys expire peridiocally.
752 silc_client_receive_channel_key(client, sock, buffer);
755 case SILC_PACKET_PRIVATE_MESSAGE:
757 * Received private message
759 silc_client_private_message(client, sock, packet);
761 case SILC_PACKET_PRIVATE_MESSAGE_KEY:
763 * Received private message key
767 case SILC_PACKET_COMMAND_REPLY:
769 * Recived reply for a command
771 silc_client_command_reply_process(client, sock, packet);
774 case SILC_PACKET_KEY_EXCHANGE:
775 if (sock->protocol) {
776 SilcClientKEInternalContext *proto_ctx =
777 (SilcClientKEInternalContext *)sock->protocol->context;
779 proto_ctx->packet = silc_packet_context_dup(packet);
780 proto_ctx->dest_id_type = packet->src_id_type;
781 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
782 packet->src_id_type);
783 if (!proto_ctx->dest_id)
786 /* Let the protocol handle the packet */
787 sock->protocol->execute(client->timeout_queue, 0,
788 sock->protocol, sock->sock, 0, 0);
790 SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
791 "protocol active, packet dropped."));
793 /* XXX Trigger KE protocol?? Rekey actually! */
797 case SILC_PACKET_KEY_EXCHANGE_1:
798 if (sock->protocol) {
801 SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
802 "protocol active, packet dropped."));
805 case SILC_PACKET_KEY_EXCHANGE_2:
806 if (sock->protocol) {
807 SilcClientKEInternalContext *proto_ctx =
808 (SilcClientKEInternalContext *)sock->protocol->context;
810 if (proto_ctx->packet)
811 silc_packet_context_free(proto_ctx->packet);
813 proto_ctx->packet = silc_packet_context_dup(packet);
814 proto_ctx->dest_id_type = packet->src_id_type;
815 proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
816 packet->src_id_type);
817 if (!proto_ctx->dest_id)
820 /* Let the protocol handle the packet */
821 sock->protocol->execute(client->timeout_queue, 0,
822 sock->protocol, sock->sock, 0, 0);
824 SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
825 "protocol active, packet dropped."));
829 case SILC_PACKET_NEW_ID:
832 * Received new ID from server. This packet is received at
833 * the connection to the server. New ID is also received when
834 * user changes nickname but in that case the new ID is received
835 * as command reply and not as this packet type.
839 idp = silc_id_payload_parse(buffer);
842 if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
845 silc_client_receive_new_id(client, sock, idp);
846 silc_id_payload_free(idp);
850 case SILC_PACKET_HEARTBEAT:
852 * Received heartbeat packet
854 SILC_LOG_DEBUG(("Heartbeat packet"));
858 SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
863 /* Sends packet. This doesn't actually send the packet instead it assembles
864 it and marks it to be sent. However, if force_send is TRUE the packet
865 is sent immediately. if dst_id, cipher and hmac are NULL those parameters
866 will be derived from sock argument. Otherwise the valid arguments sent
869 void silc_client_packet_send(SilcClient client,
870 SilcSocketConnection sock,
873 SilcIdType dst_id_type,
877 unsigned int data_len,
880 SilcPacketContext packetdata;
882 SILC_LOG_DEBUG(("Sending packet, type %d", type));
884 /* Get data used in the packet sending, keys and stuff */
885 if ((!cipher || !hmac || !dst_id) && sock->user_data) {
886 if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
887 cipher = ((SilcClientConnection)sock->user_data)->send_key;
889 if (!hmac && ((SilcClientConnection)sock->user_data)->hmac)
890 hmac = ((SilcClientConnection)sock->user_data)->hmac;
892 if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
893 dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
894 dst_id_type = SILC_ID_SERVER;
898 /* Set the packet context pointers */
899 packetdata.flags = 0;
900 packetdata.type = type;
901 if (((SilcClientConnection)sock->user_data)->local_id_data)
902 packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
904 packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
905 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
906 packetdata.src_id_type = SILC_ID_CLIENT;
908 packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
909 packetdata.dst_id_len = silc_id_get_len(dst_id_type);
910 packetdata.dst_id_type = dst_id_type;
912 packetdata.dst_id = NULL;
913 packetdata.dst_id_len = 0;
914 packetdata.dst_id_type = SILC_ID_NONE;
916 packetdata.rng = client->rng;
917 packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
918 packetdata.src_id_len + packetdata.dst_id_len;
919 packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
921 /* Prepare outgoing data buffer for packet sending */
922 silc_packet_send_prepare(sock,
923 SILC_PACKET_HEADER_LEN +
924 packetdata.src_id_len +
925 packetdata.dst_id_len,
929 SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
931 packetdata.buffer = sock->outbuf;
933 /* Put the data to the buffer */
934 if (data && data_len)
935 silc_buffer_put(sock->outbuf, data, data_len);
937 /* Create the outgoing packet */
938 silc_packet_assemble(&packetdata);
940 /* Encrypt the packet */
942 silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
944 SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
945 sock->outbuf->data, sock->outbuf->len);
947 /* Now actually send the packet */
948 silc_client_packet_send_real(client, sock, force_send);
951 /* Sends packet to a channel. Packet to channel is always encrypted
952 differently from "normal" packets. SILC header of the packet is
953 encrypted with the next receiver's key and the rest of the packet is
954 encrypted with the channel specific key. Padding and HMAC is computed
955 with the next receiver's key. */
957 void silc_client_packet_send_to_channel(SilcClient client,
958 SilcSocketConnection sock,
959 SilcChannelEntry channel,
961 unsigned int data_len,
965 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
967 SilcPacketContext packetdata;
970 unsigned char *id_string;
972 SILC_LOG_DEBUG(("Sending packet to channel"));
974 if (!channel || !channel->key) {
975 client->ops->say(client, conn,
976 "Cannot talk to channel: key does not exist");
982 for (i = 0; i < 16; i++) channel->iv[i] = silc_rng_get_byte(client->rng);
984 silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
986 /* Encode the channel payload */
987 payload = silc_channel_payload_encode(data_len, data, 16, channel->iv,
990 client->ops->say(client, conn,
991 "Error: Could not create packet to be sent to channel");
995 /* Get data used in packet header encryption, keys and stuff. Rest
996 of the packet (the payload) is, however, encrypted with the
997 specified channel key. */
998 cipher = conn->send_key;
1000 id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1002 /* Set the packet context pointers. The destination ID is always
1003 the Channel ID of the channel. Server and router will handle the
1004 distribution of the packet. */
1005 packetdata.flags = 0;
1006 packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
1007 packetdata.src_id = conn->local_id_data;
1008 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1009 packetdata.src_id_type = SILC_ID_CLIENT;
1010 packetdata.dst_id = id_string;
1011 packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
1012 packetdata.dst_id_type = SILC_ID_CHANNEL;
1013 packetdata.rng = client->rng;
1014 packetdata.truelen = payload->len + SILC_PACKET_HEADER_LEN +
1015 packetdata.src_id_len + packetdata.dst_id_len;
1016 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1017 packetdata.src_id_len +
1018 packetdata.dst_id_len));
1020 /* Prepare outgoing data buffer for packet sending */
1021 silc_packet_send_prepare(sock,
1022 SILC_PACKET_HEADER_LEN +
1023 packetdata.src_id_len +
1024 packetdata.dst_id_len,
1028 packetdata.buffer = sock->outbuf;
1030 /* Encrypt payload of the packet. This is encrypted with the channel key. */
1031 channel->channel_key->cipher->encrypt(channel->channel_key->context,
1032 payload->data, payload->data,
1033 payload->len - 16, /* -IV_LEN */
1036 /* Put the actual encrypted payload data into the buffer. */
1037 silc_buffer_put(sock->outbuf, payload->data, payload->len);
1039 /* Create the outgoing packet */
1040 silc_packet_assemble(&packetdata);
1042 /* Encrypt the header and padding of the packet. This is encrypted
1043 with normal session key shared with our server. */
1044 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1045 packetdata.src_id_len + packetdata.dst_id_len +
1048 SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
1049 sock->outbuf->data, sock->outbuf->len);
1051 /* Now actually send the packet */
1052 silc_client_packet_send_real(client, sock, force_send);
1053 silc_buffer_free(payload);
1054 silc_free(id_string);
1057 /* Sends private message to remote client. If private message key has
1058 not been set with this client then the message will be encrypted using
1059 normal session keys. Private messages are special packets in SILC
1060 network hence we need this own function for them. This is similiar
1061 to silc_client_packet_send_to_channel except that we send private
1064 void silc_client_packet_send_private_message(SilcClient client,
1065 SilcSocketConnection sock,
1066 SilcClientEntry client_entry,
1067 unsigned char *data,
1068 unsigned int data_len,
1071 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1073 SilcPacketContext packetdata;
1074 unsigned int nick_len;
1078 SILC_LOG_DEBUG(("Sending private message"));
1080 /* Create private message payload */
1081 nick_len = strlen(conn->nickname);
1082 buffer = silc_buffer_alloc(2 + nick_len + data_len);
1083 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
1084 silc_buffer_format(buffer,
1085 SILC_STR_UI_SHORT(nick_len),
1086 SILC_STR_UI_XNSTRING(conn->nickname,
1088 SILC_STR_UI_XNSTRING(data, data_len),
1091 /* If we don't have private message specific key then private messages
1092 are just as any normal packet thus call normal packet sending. If
1093 the key exist then the encryption process is a bit different and
1094 will be done in the rest of this function. */
1095 if (!client_entry->send_key) {
1096 silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
1097 client_entry->id, SILC_ID_CLIENT, NULL, NULL,
1098 buffer->data, buffer->len, force_send);
1102 /* We have private message specific key */
1104 /* Get data used in the encryption */
1105 cipher = client_entry->send_key;
1108 /* Set the packet context pointers. */
1109 packetdata.flags = 0;
1110 packetdata.type = SILC_PACKET_PRIVATE_MESSAGE;
1111 packetdata.src_id = conn->local_id_data;
1112 packetdata.src_id_len = SILC_ID_CLIENT_LEN;
1113 packetdata.src_id_type = SILC_ID_CLIENT;
1115 packetdata.dst_id = silc_id_id2str(client_entry->id, SILC_ID_CLIENT);
1117 packetdata.dst_id = conn->local_id_data;
1118 packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
1119 packetdata.dst_id_type = SILC_ID_CLIENT;
1120 packetdata.rng = client->rng;
1121 packetdata.truelen = buffer->len + SILC_PACKET_HEADER_LEN +
1122 packetdata.src_id_len + packetdata.dst_id_len;
1123 packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
1124 packetdata.src_id_len +
1125 packetdata.dst_id_len));
1127 /* Prepare outgoing data buffer for packet sending */
1128 silc_packet_send_prepare(sock,
1129 SILC_PACKET_HEADER_LEN +
1130 packetdata.src_id_len +
1131 packetdata.dst_id_len,
1135 packetdata.buffer = sock->outbuf;
1137 /* Encrypt payload of the packet. Encrypt with private message specific
1138 key if it exist, otherwise with session key. */
1139 cipher->cipher->encrypt(cipher->context, buffer->data, buffer->data,
1140 buffer->len, cipher->iv);
1142 /* Put the actual encrypted payload data into the buffer. */
1143 silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
1145 /* Create the outgoing packet */
1146 silc_packet_assemble(&packetdata);
1148 /* Encrypt the header and padding of the packet. */
1149 silc_packet_encrypt(cipher, hmac, sock->outbuf, SILC_PACKET_HEADER_LEN +
1150 packetdata.src_id_len + packetdata.dst_id_len +
1153 SILC_LOG_HEXDUMP(("Private message packet, len %d", sock->outbuf->len),
1154 sock->outbuf->data, sock->outbuf->len);
1156 /* Now actually send the packet */
1157 silc_client_packet_send_real(client, sock, force_send);
1158 silc_free(packetdata.dst_id);
1164 /* Closes connection to remote end. Free's all allocated data except
1165 for some information such as nickname etc. that are valid at all time. */
1167 void silc_client_close_connection(SilcClient client,
1168 SilcSocketConnection sock)
1170 SilcClientConnection conn;
1172 /* We won't listen for this connection anymore */
1173 silc_schedule_unset_listen_fd(sock->sock);
1175 /* Unregister all tasks */
1176 silc_task_unregister_by_fd(client->io_queue, sock->sock);
1177 silc_task_unregister_by_fd(client->timeout_queue, sock->sock);
1179 /* Close the actual connection */
1180 silc_net_close_connection(sock->sock);
1182 client->ops->say(client, sock->user_data,
1183 "Closed connection to host %s", sock->hostname ?
1184 sock->hostname : sock->ip);
1186 /* Free everything */
1187 if (sock->user_data) {
1188 conn = (SilcClientConnection)sock->user_data;
1190 /* XXX Free all client entries and channel entries. */
1192 /* Clear ID caches */
1193 silc_idcache_del_all(conn->client_cache);
1194 silc_idcache_del_all(conn->channel_cache);
1197 if (conn->remote_host)
1198 silc_free(conn->remote_host);
1200 silc_free(conn->local_id);
1201 if (conn->local_id_data)
1202 silc_free(conn->local_id_data);
1204 silc_cipher_free(conn->send_key);
1205 if (conn->receive_key)
1206 silc_cipher_free(conn->receive_key);
1208 silc_hmac_free(conn->hmac);
1209 if (conn->hmac_key) {
1210 memset(conn->hmac_key, 0, conn->hmac_key_len);
1211 silc_free(conn->hmac_key);
1213 if (conn->pending_commands)
1214 silc_dlist_uninit(conn->pending_commands);
1217 conn->remote_port = 0;
1218 conn->remote_type = 0;
1219 conn->send_key = NULL;
1220 conn->receive_key = NULL;
1222 conn->hmac_key = NULL;
1223 conn->hmac_key_len = 0;
1224 conn->local_id = NULL;
1225 conn->local_id_data = NULL;
1226 conn->remote_host = NULL;
1227 conn->current_channel = NULL;
1228 conn->pending_commands = NULL;
1230 silc_client_del_connection(client, conn);
1233 if (sock->protocol) {
1234 silc_protocol_free(sock->protocol);
1235 sock->protocol = NULL;
1237 silc_socket_free(sock);
1240 /* Called when we receive disconnection packet from server. This
1241 closes our end properly and displays the reason of the disconnection
1244 void silc_client_disconnected_by_server(SilcClient client,
1245 SilcSocketConnection sock,
1250 SILC_LOG_DEBUG(("Server disconnected us, sock %d", sock->sock));
1252 msg = silc_calloc(message->len + 1, sizeof(char));
1253 memcpy(msg, message->data, message->len);
1254 client->ops->say(client, sock->user_data, msg);
1257 SILC_SET_DISCONNECTED(sock);
1258 silc_client_close_connection(client, sock);
1261 /* Received error message from server. Display it on the screen.
1262 We don't take any action what so ever of the error message. */
1264 void silc_client_error_by_server(SilcClient client,
1265 SilcSocketConnection sock,
1270 msg = silc_calloc(message->len + 1, sizeof(char));
1271 memcpy(msg, message->data, message->len);
1272 client->ops->say(client, sock->user_data, msg);
1276 /* Called when notify is received and some async operation (such as command)
1277 is required before processing the notify message. This calls again the
1278 silc_client_notify_by_server and reprocesses the original notify packet. */
1280 static void silc_client_notify_by_server_pending(void *context)
1282 SilcPacketContext *p = (SilcPacketContext *)context;
1283 silc_client_notify_by_server(p->context, p->sock, p);
1284 silc_packet_context_free(p);
1287 /* Received notify message from server */
1289 void silc_client_notify_by_server(SilcClient client,
1290 SilcSocketConnection sock,
1291 SilcPacketContext *packet)
1293 SilcBuffer buffer = packet->buffer;
1294 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1295 SilcNotifyPayload payload;
1296 SilcNotifyType type;
1297 SilcArgumentPayload args;
1299 SilcClientID *client_id = NULL;
1300 SilcChannelID *channel_id = NULL;
1301 SilcClientEntry client_entry;
1302 SilcClientEntry client_entry2;
1303 SilcChannelEntry channel;
1304 SilcChannelUser chu;
1305 SilcIDCacheEntry id_cache = NULL;
1307 unsigned int tmp_len, mode;
1309 payload = silc_notify_payload_parse(buffer);
1313 type = silc_notify_get_type(payload);
1314 args = silc_notify_get_args(payload);
1319 case SILC_NOTIFY_TYPE_NONE:
1320 /* Notify application */
1321 client->ops->notify(client, conn, type,
1322 silc_argument_get_arg_type(args, 1, NULL));
1325 case SILC_NOTIFY_TYPE_INVITE:
1327 * Someone invited me to a channel. Find Client and Channel entries
1328 * for the application.
1332 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1336 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1340 /* Find Client entry and if not found query it */
1341 client_entry = silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
1342 if (!client_entry) {
1343 SilcPacketContext *p = silc_packet_context_dup(packet);
1344 p->context = (void *)client;
1346 silc_client_command_pending(conn, SILC_COMMAND_WHOIS, SILC_IDLIST_IDENT,
1347 silc_client_notify_by_server_pending, p);
1351 /* Get Channel ID */
1352 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1356 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1360 /* XXX Will ALWAYS fail because currently we don't have way to resolve
1361 channel information for channel that we're not joined to. */
1362 /* XXX ways to fix: use (extended) LIST command, or define the channel
1363 name to the notfy type when name resolving is not mandatory. */
1364 /* Find channel entry */
1365 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1366 SILC_ID_CHANNEL, &id_cache))
1369 channel = (SilcChannelEntry)id_cache->context;
1371 /* Notify application */
1372 client->ops->notify(client, conn, type, client_entry, channel);
1375 case SILC_NOTIFY_TYPE_JOIN:
1377 * Someone has joined to a channel. Get their ID and nickname and
1378 * cache them for later use.
1382 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1386 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1390 /* Find Client entry and if not found query it */
1391 client_entry = silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
1392 if (!client_entry) {
1393 SilcPacketContext *p = silc_packet_context_dup(packet);
1394 p->context = (void *)client;
1396 silc_client_command_pending(conn, SILC_COMMAND_WHOIS, SILC_IDLIST_IDENT,
1397 silc_client_notify_by_server_pending, p);
1401 /* If nickname or username hasn't been resolved, do so */
1402 if (!client_entry->nickname || !client_entry->username) {
1403 SilcPacketContext *p = silc_packet_context_dup(packet);
1404 SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1405 silc_client_send_command(client, conn, SILC_COMMAND_WHOIS,
1406 SILC_IDLIST_IDENT, 1,
1407 3, idp->data, idp->len);
1408 p->context = (void *)client;
1410 silc_client_command_pending(conn, SILC_COMMAND_WHOIS, SILC_IDLIST_IDENT,
1411 silc_client_notify_by_server_pending, p);
1415 /* Get channel entry */
1416 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1420 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1421 SILC_ID_CHANNEL, &id_cache))
1424 channel = (SilcChannelEntry)id_cache->context;
1426 /* Add client to channel */
1427 chu = silc_calloc(1, sizeof(*chu));
1428 chu->client = client_entry;
1429 silc_list_add(channel->clients, chu);
1431 /* XXX add support for multiple same nicks on same channel. Check
1434 /* Notify application. The channel entry is sent last as this notify
1435 is for channel but application don't know it from the arguments
1437 client->ops->notify(client, conn, type, client_entry, channel);
1440 case SILC_NOTIFY_TYPE_LEAVE:
1442 * Someone has left a channel. We will remove it from the channel but
1443 * we'll keep it in the cache in case we'll need it later.
1447 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1451 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1455 /* Find Client entry */
1457 silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1461 /* Get channel entry */
1462 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1466 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1467 SILC_ID_CHANNEL, &id_cache))
1470 channel = (SilcChannelEntry)id_cache->context;
1472 /* Remove client from channel */
1473 silc_list_start(channel->clients);
1474 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1475 if (chu->client == client_entry) {
1476 silc_list_del(channel->clients, chu);
1482 /* Notify application. The channel entry is sent last as this notify
1483 is for channel but application don't know it from the arguments
1485 client->ops->notify(client, conn, type, client_entry, channel);
1488 case SILC_NOTIFY_TYPE_SIGNOFF:
1490 * Someone left SILC. We'll remove it from all channels and from cache.
1494 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1498 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1502 /* Find Client entry */
1504 silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1508 /* Remove from all channels */
1509 silc_client_remove_from_channels(client, conn, client_entry);
1511 /* Remove from cache */
1512 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT,
1515 /* Notify application */
1516 client->ops->notify(client, conn, type, client_entry);
1519 if (client_entry->nickname)
1520 silc_free(client_entry->nickname);
1521 if (client_entry->server)
1522 silc_free(client_entry->server);
1523 if (client_entry->id)
1524 silc_free(client_entry->id);
1525 if (client_entry->send_key)
1526 silc_cipher_free(client_entry->send_key);
1527 if (client_entry->receive_key)
1528 silc_cipher_free(client_entry->receive_key);
1531 case SILC_NOTIFY_TYPE_TOPIC_SET:
1533 * Someone set the topic on a channel.
1537 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1541 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1545 /* Find Client entry */
1547 silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1552 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1556 /* Get channel entry */
1557 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1561 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1562 SILC_ID_CHANNEL, &id_cache))
1565 channel = (SilcChannelEntry)id_cache->context;
1567 /* Notify application. The channel entry is sent last as this notify
1568 is for channel but application don't know it from the arguments
1570 client->ops->notify(client, conn, type, client_entry, tmp, channel);
1573 case SILC_NOTIFY_TYPE_NICK_CHANGE:
1575 * Someone changed their nickname. If we don't have entry for the new
1576 * ID we will query it and return here after it's done. After we've
1577 * returned we fetch the old entry and free it and notify the
1581 /* Get new Client ID */
1582 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1586 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1591 if (!SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
1594 /* Find Client entry and if not found query it */
1596 silc_idlist_get_client_by_id(client, conn, client_id, TRUE);
1597 if (!client_entry2) {
1598 SilcPacketContext *p = silc_packet_context_dup(packet);
1599 p->context = (void *)client;
1601 silc_client_command_pending(conn, SILC_COMMAND_WHOIS, SILC_IDLIST_IDENT,
1602 silc_client_notify_by_server_pending, p);
1605 silc_free(client_id);
1607 /* Get old Client ID */
1608 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1612 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1616 /* Find old Client entry */
1618 silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1622 /* Remove the old from cache */
1623 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT,
1626 /* Replace old ID entry with new one on all channels. */
1627 silc_client_replace_from_channels(client, conn, client_entry,
1630 /* Notify application */
1631 client->ops->notify(client, conn, type, client_entry, client_entry2);
1634 if (client_entry->nickname)
1635 silc_free(client_entry->nickname);
1636 if (client_entry->server)
1637 silc_free(client_entry->server);
1638 if (client_entry->id)
1639 silc_free(client_entry->id);
1640 if (client_entry->send_key)
1641 silc_cipher_free(client_entry->send_key);
1642 if (client_entry->receive_key)
1643 silc_cipher_free(client_entry->receive_key);
1646 case SILC_NOTIFY_TYPE_CMODE_CHANGE:
1648 * Someone changed a channel mode
1652 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1656 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1660 /* Find Client entry */
1662 silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1667 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1671 SILC_GET32_MSB(mode, tmp);
1673 /* Get channel entry */
1674 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1678 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1679 SILC_ID_CHANNEL, &id_cache))
1682 channel = (SilcChannelEntry)id_cache->context;
1684 /* Save the new mode */
1685 channel->mode = mode;
1687 /* Notify application. The channel entry is sent last as this notify
1688 is for channel but application don't know it from the arguments
1690 client->ops->notify(client, conn, type, client_entry, mode, channel);
1693 case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
1695 * Someone changed user's mode on a channel
1699 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1703 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1707 /* Find Client entry */
1709 silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1714 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1718 SILC_GET32_MSB(mode, tmp);
1720 /* Get target Client ID */
1721 tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
1725 silc_free(client_id);
1726 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1730 /* Find target Client entry */
1732 silc_idlist_get_client_by_id(client, conn, client_id, FALSE);
1736 /* Get channel entry */
1737 channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
1741 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1742 SILC_ID_CHANNEL, &id_cache))
1745 channel = (SilcChannelEntry)id_cache->context;
1748 silc_list_start(channel->clients);
1749 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
1750 if (chu->client == client_entry) {
1756 /* Notify application. The channel entry is sent last as this notify
1757 is for channel but application don't know it from the arguments
1759 client->ops->notify(client, conn, type, client_entry, mode,
1760 client_entry2, channel);
1763 case SILC_NOTIFY_TYPE_MOTD:
1765 * Received Message of the day
1769 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1773 /* Notify application */
1774 client->ops->notify(client, conn, type, tmp);
1777 case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
1779 * Router has enforced a new ID to a channel. Let's change the old
1780 * ID to the one provided here.
1783 /* Get the old ID */
1784 tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
1787 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1791 /* Get the channel entry */
1792 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
1793 SILC_ID_CHANNEL, &id_cache))
1796 channel = (SilcChannelEntry)id_cache->context;
1798 /* Free the old ID */
1799 silc_free(channel_id);
1800 silc_free(channel->id);
1802 /* Get the new ID */
1803 tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
1806 channel->id = silc_id_payload_parse_id(tmp, tmp_len);
1810 id_cache->id = (void *)channel->id;
1812 /* Notify application */
1813 client->ops->notify(client, conn, type, channel, channel);
1821 silc_notify_payload_free(payload);
1823 silc_free(client_id);
1825 silc_free(channel_id);
1828 /* Processes the received new Client ID from server. Old Client ID is
1829 deleted from cache and new one is added. */
1831 void silc_client_receive_new_id(SilcClient client,
1832 SilcSocketConnection sock,
1835 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1836 int connecting = FALSE;
1838 if (!conn->local_entry)
1841 /* Delete old ID from ID cache */
1842 silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
1844 /* Save the new ID */
1846 silc_free(conn->local_id);
1847 if (conn->local_id_data)
1848 silc_free(conn->local_id_data);
1850 conn->local_id = silc_id_payload_get_id(idp);
1851 conn->local_id_data = silc_id_payload_get_data(idp);
1852 conn->local_id_data_len = silc_id_payload_get_len(idp);;
1854 if (!conn->local_entry)
1855 conn->local_entry = silc_calloc(1, sizeof(*conn->local_entry));
1857 conn->local_entry->nickname = conn->nickname;
1858 if (!conn->local_entry->username) {
1859 conn->local_entry->username =
1860 silc_calloc(strlen(client->username) + strlen(client->hostname) + 1,
1861 sizeof(conn->local_entry->username));
1862 sprintf(conn->local_entry->username, "%s@%s", client->username,
1865 conn->local_entry->server = strdup(conn->remote_host);
1866 conn->local_entry->id = conn->local_id;
1868 /* Put it to the ID cache */
1869 silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
1870 conn->local_id, (void *)conn->local_entry, TRUE);
1872 /* Notify application of successful connection. We do it here now that
1873 we've received the Client ID and are allowed to send traffic. */
1875 client->ops->connect(client, conn, TRUE);
1878 /* Processed received Channel ID for a channel. This is called when client
1879 joins to channel and server replies with channel ID. The ID is cached. */
1881 void silc_client_new_channel_id(SilcClient client,
1882 SilcSocketConnection sock,
1884 unsigned int mode, SilcIDPayload idp)
1886 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1887 SilcChannelEntry channel;
1889 SILC_LOG_DEBUG(("New channel ID"));
1891 channel = silc_calloc(1, sizeof(*channel));
1892 channel->channel_name = channel_name;
1893 channel->id = silc_id_payload_get_id(idp);
1894 channel->mode = mode;
1895 silc_list_init(channel->clients, struct SilcChannelUserStruct, next);
1897 conn->current_channel = channel;
1899 /* Put it to the ID cache */
1900 silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
1901 (void *)channel->id, (void *)channel, TRUE);
1904 /* Saves channel key from encoded `key_payload'. This is used when we
1905 receive Channel Key Payload and when we are processing JOIN command
1908 void silc_client_save_channel_key(SilcClientConnection conn,
1909 SilcBuffer key_payload,
1910 SilcChannelEntry channel)
1912 unsigned char *id_string, *key, *cipher;
1913 unsigned int tmp_len;
1915 SilcIDCacheEntry id_cache = NULL;
1916 SilcChannelKeyPayload payload;
1918 payload = silc_channel_key_payload_parse(key_payload);
1922 id_string = silc_channel_key_get_id(payload, &tmp_len);
1924 silc_channel_key_payload_free(payload);
1928 id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
1930 silc_channel_key_payload_free(payload);
1936 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
1937 SILC_ID_CHANNEL, &id_cache))
1940 /* Get channel entry */
1941 channel = (SilcChannelEntry)id_cache->context;
1945 key = silc_channel_key_get_key(payload, &tmp_len);
1946 cipher = silc_channel_key_get_cipher(payload, NULL);
1947 channel->key_len = tmp_len;
1948 channel->key = silc_calloc(tmp_len, sizeof(*channel->key));
1949 memcpy(channel->key, key, tmp_len);
1951 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
1952 conn->client->ops->say(conn->client, conn,
1953 "Cannot talk to channel: unsupported cipher %s", cipher);
1956 channel->channel_key->cipher->set_key(channel->channel_key->context,
1959 /* Client is now joined to the channel */
1960 channel->on_channel = TRUE;
1964 silc_channel_key_payload_free(payload);
1967 /* Processes received key for channel. The received key will be used
1968 to protect the traffic on the channel for now on. Client must receive
1969 the key to the channel before talking on the channel is possible.
1970 This is the key that server has generated, this is not the channel
1971 private key, it is entirely local setting. */
1973 void silc_client_receive_channel_key(SilcClient client,
1974 SilcSocketConnection sock,
1977 SILC_LOG_DEBUG(("Received key for channel"));
1980 silc_client_save_channel_key(sock->user_data, packet, NULL);
1983 /* Process received message to a channel (or from a channel, really). This
1984 decrypts the channel message with channel specific key and parses the
1985 channel payload. Finally it displays the message on the screen. */
1987 void silc_client_channel_message(SilcClient client,
1988 SilcSocketConnection sock,
1989 SilcPacketContext *packet)
1991 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
1992 SilcBuffer buffer = packet->buffer;
1993 SilcChannelPayload payload = NULL;
1994 SilcChannelID *id = NULL;
1995 SilcChannelEntry channel;
1996 SilcChannelUser chu;
1997 SilcIDCacheEntry id_cache = NULL;
1998 SilcClientID *client_id = NULL;
2002 if (packet->dst_id_type != SILC_ID_CHANNEL)
2005 client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2009 id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
2013 /* Find the channel entry from channels on this connection */
2014 if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
2015 SILC_ID_CHANNEL, &id_cache))
2018 channel = (SilcChannelEntry)id_cache->context;
2020 /* Decrypt the channel message payload. Push the IV out of the way,
2021 since it is not encrypted (after pushing buffer->tail has the IV). */
2022 silc_buffer_push_tail(buffer, 16);
2023 channel->channel_key->cipher->decrypt(channel->channel_key->context,
2024 buffer->data, buffer->data,
2025 buffer->len, buffer->tail);
2026 silc_buffer_pull_tail(buffer, 16);
2028 /* Parse the channel message payload */
2029 payload = silc_channel_payload_parse(buffer);
2034 nickname = "[unknown]";
2035 silc_list_start(channel->clients);
2036 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2037 if (!SILC_ID_CLIENT_COMPARE(chu->client->id, client_id)) {
2038 nickname = chu->client->nickname;
2043 /* Pass the message to application */
2044 client->ops->channel_message(client, conn, nickname,
2045 channel->channel_name,
2046 silc_channel_get_data(payload, NULL));
2052 silc_free(client_id);
2054 silc_channel_payload_free(payload);
2057 /* Private message received. This processes the private message and
2058 finally displays it on the screen. */
2060 void silc_client_private_message(SilcClient client,
2061 SilcSocketConnection sock,
2062 SilcPacketContext *packet)
2064 SilcClientConnection conn = (SilcClientConnection)sock->user_data;
2065 SilcBuffer buffer = packet->buffer;
2066 unsigned short nick_len;
2067 unsigned char *nickname, *message;
2071 ret = silc_buffer_unformat(buffer,
2072 SILC_STR_UI16_NSTRING_ALLOC(&nickname, &nick_len),
2077 silc_buffer_pull(buffer, 2 + nick_len);
2079 message = silc_calloc(buffer->len + 1, sizeof(char));
2080 memcpy(message, buffer->data, buffer->len);
2082 /* Pass the private message to application */
2083 client->ops->private_message(client, conn, nickname, message);
2085 /* See if we are away (gone). If we are away we will reply to the
2086 sender with the set away message. */
2087 if (conn->away && conn->away->away) {
2088 SilcClientID *remote_id;
2089 SilcClientEntry remote_client;
2090 SilcIDCacheEntry id_cache;
2092 if (packet->src_id_type != SILC_ID_CLIENT)
2095 remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
2100 /* If it's me, ignore */
2101 if (!SILC_ID_CLIENT_COMPARE(remote_id, conn->local_id))
2104 /* Check whether we know this client already */
2105 if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
2106 SILC_ID_CLIENT, &id_cache))
2108 /* Allocate client entry */
2109 remote_client = silc_calloc(1, sizeof(*remote_client));
2110 remote_client->id = remote_id;
2111 silc_parse_nickname(nickname, &remote_client->nickname,
2112 &remote_client->server, &remote_client->num);
2114 /* Save the client to cache */
2115 silc_idcache_add(conn->client_cache, remote_client->nickname,
2116 SILC_ID_CLIENT, remote_client->id, remote_client,
2119 silc_free(remote_id);
2120 remote_client = (SilcClientEntry)id_cache->context;
2123 /* Send the away message */
2124 silc_client_packet_send_private_message(client, sock, remote_client,
2126 strlen(conn->away->away), TRUE);
2130 memset(message, 0, buffer->len);
2132 silc_free(nickname);
2135 /* Removes a client entry from all channel it has joined. This really is
2136 a performance killer (client_entry should have pointers to channel
2139 void silc_client_remove_from_channels(SilcClient client,
2140 SilcClientConnection conn,
2141 SilcClientEntry client_entry)
2143 SilcIDCacheEntry id_cache;
2144 SilcIDCacheList list;
2145 SilcChannelEntry channel;
2146 SilcChannelUser chu;
2148 if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2149 SILC_ID_CHANNEL, &list))
2152 silc_idcache_list_first(list, &id_cache);
2153 channel = (SilcChannelEntry)id_cache->context;
2157 /* Remove client from channel */
2158 silc_list_start(channel->clients);
2159 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2160 if (chu->client == client_entry) {
2161 silc_list_del(channel->clients, chu);
2167 if (!silc_idcache_list_next(list, &id_cache))
2170 channel = (SilcChannelEntry)id_cache->context;
2173 silc_idcache_list_free(list);
2176 /* Replaces `old' client entries from all channels to `new' client entry.
2177 This can be called for example when nickname changes and old ID entry
2178 is replaced from ID cache with the new one. If the old ID entry is only
2179 updated, then this fucntion needs not to be called. */
2181 void silc_client_replace_from_channels(SilcClient client,
2182 SilcClientConnection conn,
2183 SilcClientEntry old,
2184 SilcClientEntry new)
2186 SilcIDCacheEntry id_cache;
2187 SilcIDCacheList list;
2188 SilcChannelEntry channel;
2189 SilcChannelUser chu;
2191 if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
2192 SILC_ID_CHANNEL, &list))
2195 silc_idcache_list_first(list, &id_cache);
2196 channel = (SilcChannelEntry)id_cache->context;
2200 /* Replace client entry */
2201 silc_list_start(channel->clients);
2202 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
2203 if (chu->client == old) {
2209 if (!silc_idcache_list_next(list, &id_cache))
2212 channel = (SilcChannelEntry)id_cache->context;
2215 silc_idcache_list_free(list);
2218 /* Parses mode mask and returns the mode as string. */
2220 char *silc_client_chmode(unsigned int mode)
2227 memset(string, 0, sizeof(string));
2229 if (mode & SILC_CHANNEL_MODE_PRIVATE)
2230 strncat(string, "p", 1);
2232 if (mode & SILC_CHANNEL_MODE_SECRET)
2233 strncat(string, "s", 1);
2235 if (mode & SILC_CHANNEL_MODE_PRIVKEY)
2236 strncat(string, "k", 1);
2238 if (mode & SILC_CHANNEL_MODE_INVITE)
2239 strncat(string, "i", 1);
2241 if (mode & SILC_CHANNEL_MODE_TOPIC)
2242 strncat(string, "t", 1);
2244 if (mode & SILC_CHANNEL_MODE_ULIMIT)
2245 strncat(string, "l", 1);
2247 if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
2248 strncat(string, "a", 1);
2250 /* Rest of mode is ignored */
2252 return strdup(string);
2255 /* Parses channel user mode mask and returns te mode as string */
2257 char *silc_client_chumode(unsigned int mode)
2264 memset(string, 0, sizeof(string));
2266 if (mode & SILC_CHANNEL_UMODE_CHANFO)
2267 strncat(string, "f", 1);
2269 if (mode & SILC_CHANNEL_UMODE_CHANOP)
2270 strncat(string, "o", 1);
2272 return strdup(string);
2275 /* Parses channel user mode and returns it as special mode character. */
2277 char *silc_client_chumode_char(unsigned int mode)
2284 memset(string, 0, sizeof(string));
2286 if (mode & SILC_CHANNEL_UMODE_CHANFO)
2287 strncat(string, "*", 1);
2289 if (mode & SILC_CHANNEL_UMODE_CHANOP)
2290 strncat(string, "@", 1);
2292 return strdup(string);