- }
-}
-
-/* Parser callback called by silc_packet_receive_process. Thie merely
- registers timeout that will handle the actual parsing when appropriate. */
-
-static SilcBool silc_client_packet_parse(SilcPacketParserContext *parser_context,
- void *context)
-{
- SilcClient client = (SilcClient)context;
- SilcSocketConnection sock = parser_context->sock;
- SilcClientConnection conn = (SilcClientConnection)sock->user_data;
- SilcPacketContext *packet = parser_context->packet;
- SilcPacketType ret;
-
- if (conn && conn->internal->hmac_receive && conn->sock == sock)
- conn->internal->psn_receive = parser_context->packet->sequence + 1;
-
- /* Parse the packet immediately */
- if (parser_context->normal)
- ret = silc_packet_parse(packet, conn->internal->receive_key);
- else
- ret = silc_packet_parse_special(packet, conn->internal->receive_key);
-
- if (ret == SILC_PACKET_NONE) {
- silc_packet_context_free(packet);
- silc_free(parser_context);
- return FALSE;
- }
-
- /* If protocol for this connection is key exchange or rekey then we'll
- process all packets synchronously, since there might be packets in
- queue that we are not able to decrypt without first processing the
- packets before them. */
- if (sock->protocol && sock->protocol->protocol &&
- (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
- sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
-
- /* Parse the incoming packet type */
- silc_client_packet_parse_type(client, sock, packet);
-
- /* Reprocess the buffer since we'll return FALSE. This is because
- the `conn->internal->receive_key' might have become valid by processing
- the previous packet */
- if (sock->type != SILC_SOCKET_TYPE_UNKNOWN)
- silc_packet_receive_process(sock, FALSE, conn->internal->receive_key,
- conn->internal->hmac_receive,
- conn->internal->psn_receive,
- silc_client_packet_parse, client);
- else
- silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
- silc_client_packet_parse, client);
-
- silc_packet_context_free(packet);
- silc_free(parser_context);
-
- return FALSE;
- }
-
- /* Parse the incoming packet type */
- silc_client_packet_parse_type(client, sock, packet);
- silc_packet_context_free(packet);
- silc_free(parser_context);
- return TRUE;
-}
-
-/* Parses the packet type and calls what ever routines the packet type
- requires. This is done for all incoming packets. */
-
-void silc_client_packet_parse_type(SilcClient client,
- SilcSocketConnection sock,
- SilcPacketContext *packet)
-{
- SilcBuffer buffer = packet->buffer;
- SilcPacketType type = packet->type;
-
- SILC_LOG_DEBUG(("Parsing %s packet", silc_get_packet_name(type)));
-
- /* Parse the packet type */
- switch(type) {
-
- case SILC_PACKET_DISCONNECT:
- silc_client_disconnected_by_server(client, sock, buffer);
- break;
-
- case SILC_PACKET_SUCCESS:
- /*
- * Success received for something. For now we can have only
- * one protocol for connection executing at once hence this
- * success message is for whatever protocol is executing currently.
- */
- if (sock->protocol)
- silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
- break;
-
- case SILC_PACKET_FAILURE:
- /*
- * Failure received for some protocol. Set the protocol state to
- * error and call the protocol callback. This fill cause error on
- * protocol and it will call the final callback.
- */
- silc_client_process_failure(client, sock, packet);
- break;
-
- case SILC_PACKET_REJECT:
- break;
-
- case SILC_PACKET_NOTIFY:
- /*
- * Received notify message
- */
- silc_client_notify_by_server(client, sock, packet);
- break;
-
- case SILC_PACKET_ERROR:
- /*
- * Received error message
- */
- silc_client_error_by_server(client, sock, buffer);
- break;
-
- case SILC_PACKET_CHANNEL_MESSAGE:
- /*
- * Received message to (from, actually) a channel
- */
- silc_client_channel_message(client, sock, packet);
- break;
-
- case SILC_PACKET_CHANNEL_KEY:
- /*
- * Received key for a channel. By receiving this key the client will be
- * able to talk to the channel it has just joined. This can also be
- * a new key for existing channel as keys expire peridiocally.
- */
- silc_client_receive_channel_key(client, sock, buffer);
- break;
-
- case SILC_PACKET_PRIVATE_MESSAGE:
- /*
- * Received private message
- */
- silc_client_private_message(client, sock, packet);
- break;
-
- case SILC_PACKET_PRIVATE_MESSAGE_KEY:
- /*
- * Received private message key indicator
- */
- silc_client_private_message_key(client, sock, packet);
- break;
-
- case SILC_PACKET_COMMAND:
- /*
- * Received command packet, a special case since normally client
- * does not receive commands.
- */
- silc_client_command_process(client, sock, packet);
- break;
-
- case SILC_PACKET_COMMAND_REPLY:
- /*
- * Recived reply for a command
- */
- silc_client_command_reply_process(client, sock, packet);
- break;
-
- case SILC_PACKET_KEY_EXCHANGE:
- if (sock->protocol && sock->protocol->protocol &&
- sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
- SilcClientKEInternalContext *proto_ctx =
- (SilcClientKEInternalContext *)sock->protocol->context;
-
- proto_ctx->packet = silc_packet_context_dup(packet);
- proto_ctx->dest_id_type = packet->src_id_type;
- proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
- packet->src_id_type);
- if (!proto_ctx->dest_id)
- break;
-
- /* Let the protocol handle the packet */
- silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
- } else {
- SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
- "protocol active, packet dropped."));
- }
- break;
-
- case SILC_PACKET_KEY_EXCHANGE_1:
- if (sock->protocol && sock->protocol->protocol &&
- (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
- sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
-
- if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
- SilcClientRekeyInternalContext *proto_ctx =
- (SilcClientRekeyInternalContext *)sock->protocol->context;
-
- if (proto_ctx->packet)
- silc_packet_context_free(proto_ctx->packet);
-
- proto_ctx->packet = silc_packet_context_dup(packet);
-
- /* Let the protocol handle the packet */
- silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
- } else {
- SilcClientKEInternalContext *proto_ctx =
- (SilcClientKEInternalContext *)sock->protocol->context;
-
- if (proto_ctx->packet)
- silc_packet_context_free(proto_ctx->packet);
-
- proto_ctx->packet = silc_packet_context_dup(packet);
- proto_ctx->dest_id_type = packet->src_id_type;
- proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
- packet->src_id_type);
- if (!proto_ctx->dest_id)
- break;
-
- /* Let the protocol handle the packet */
- silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
- }
- } else {
- SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
- "protocol active, packet dropped."));
- }
- break;
-
- case SILC_PACKET_KEY_EXCHANGE_2:
- if (sock->protocol && sock->protocol->protocol &&
- (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
- sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY)) {
-
- if (sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
- SilcClientRekeyInternalContext *proto_ctx =
- (SilcClientRekeyInternalContext *)sock->protocol->context;
-
- if (proto_ctx->packet)
- silc_packet_context_free(proto_ctx->packet);
-
- proto_ctx->packet = silc_packet_context_dup(packet);
-
- /* Let the protocol handle the packet */
- silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
- } else {
- SilcClientKEInternalContext *proto_ctx =
- (SilcClientKEInternalContext *)sock->protocol->context;
-
- if (proto_ctx->packet)
- silc_packet_context_free(proto_ctx->packet);
- if (proto_ctx->dest_id)
- silc_free(proto_ctx->dest_id);
- proto_ctx->packet = silc_packet_context_dup(packet);
- proto_ctx->dest_id_type = packet->src_id_type;
- proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_len,
- packet->src_id_type);
- if (!proto_ctx->dest_id)
- break;
-
- /* Let the protocol handle the packet */
- silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
- }
- } else {
- SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
- "protocol active, packet dropped."));
- }
- break;
-
- case SILC_PACKET_NEW_ID:
- {
- /*
- * Received new ID from server. This packet is received at
- * the connection to the server. New ID is also received when
- * user changes nickname but in that case the new ID is received
- * as command reply and not as this packet type.
- */
- SilcIDPayload idp;
-
- idp = silc_id_payload_parse(buffer->data, buffer->len);
- if (!idp)
- break;
- if (silc_id_payload_get_type(idp) != SILC_ID_CLIENT)
- break;
-
- silc_client_receive_new_id(client, sock, idp);
- silc_id_payload_free(idp);
- break;
- }
-
- case SILC_PACKET_HEARTBEAT:
- /*
- * Received heartbeat packet
- */
- SILC_LOG_DEBUG(("Heartbeat packet"));
- break;
-
- case SILC_PACKET_KEY_AGREEMENT:
- /*
- * Received key agreement packet
- */
- SILC_LOG_DEBUG(("Key agreement packet"));
- silc_client_key_agreement(client, sock, packet);
- break;
-
- case SILC_PACKET_REKEY:
- SILC_LOG_DEBUG(("Re-key packet"));
- /* We ignore this for now */
- break;
-
- case SILC_PACKET_REKEY_DONE:
- SILC_LOG_DEBUG(("Re-key done packet"));
-
- if (sock->protocol && sock->protocol->protocol &&
- sock->protocol->protocol->type == SILC_PROTOCOL_CLIENT_REKEY) {
-
- SilcClientRekeyInternalContext *proto_ctx =
- (SilcClientRekeyInternalContext *)sock->protocol->context;
-
- if (proto_ctx->packet)
- silc_packet_context_free(proto_ctx->packet);
-
- proto_ctx->packet = silc_packet_context_dup(packet);
-
- /* Let the protocol handle the packet */
- if (proto_ctx->responder == FALSE)
- silc_protocol_execute(sock->protocol, client->schedule, 0, 0);
- else
- /* Let the protocol handle the packet */
- silc_protocol_execute(sock->protocol, client->schedule,
- 0, 100000);
- } else {
- SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
- "protocol active, packet dropped."));
- }
- break;
-
- case SILC_PACKET_CONNECTION_AUTH_REQUEST:
- /*
- * Reveived reply to our connection authentication method request
- * packet. This is used to resolve the authentication method for the
- * current session from the server if the client does not know it.
- */
- silc_client_connection_auth_request(client, sock, packet);
- break;
-
- case SILC_PACKET_FTP:
- /* Received file transfer packet. */
- silc_client_ftp(client, sock, packet);
- break;
-
- default:
- SILC_LOG_DEBUG(("Incorrect packet type %d, packet dropped", type));
- break;
- }
-}
-
-/* Sends packet. This doesn't actually send the packet instead it assembles
- it and marks it to be sent. However, if force_send is TRUE the packet
- is sent immediately. if dst_id, cipher and hmac are NULL those parameters
- will be derived from sock argument. Otherwise the valid arguments sent
- are used. */
-
-void silc_client_packet_send(SilcClient client,
- SilcSocketConnection sock,
- SilcPacketType type,
- void *dst_id,
- SilcIdType dst_id_type,
- SilcCipher cipher,
- SilcHmac hmac,
- unsigned char *data,
- SilcUInt32 data_len,
- SilcBool force_send)
-{
- SilcPacketContext packetdata;
- const SilcBufferStruct packet;
- int block_len;
- SilcUInt32 sequence = 0;
-
- if (!sock)
- return;
-
- SILC_LOG_DEBUG(("Sending packet, type %d", type));
-
- /* Get data used in the packet sending, keys and stuff */
- if ((!cipher || !hmac || !dst_id) && sock->user_data) {
- if (!cipher && ((SilcClientConnection)sock->user_data)->internal->send_key)
- cipher = ((SilcClientConnection)sock->user_data)->internal->send_key;
-
- if (!hmac && ((SilcClientConnection)sock->user_data)->internal->hmac_send)
- hmac = ((SilcClientConnection)sock->user_data)->internal->hmac_send;