+ SILC_UNSET_INBUF_PENDING(sock);
+ parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
+ if (!parse_ctx)
+ return FALSE;
+ parse_ctx->packet = silc_packet_context_alloc();
+ parse_ctx->packet->buffer = silc_buffer_alloc_size(paddedlen);
+ parse_ctx->packet->type = (SilcPacketType)header[3];
+ parse_ctx->packet->padlen = (SilcUInt8)header[4];
+ parse_ctx->packet->sequence = sequence++;
+ parse_ctx->sock = sock;
+ parse_ctx->context = parser_context;
+
+ /* Check whether this is normal or special packet */
+ if (local_is_router) {
+ if (header[3] == SILC_PACKET_PRIVATE_MESSAGE &&
+ (header[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
+ parse_ctx->normal = FALSE;
+ else if (header[3] != SILC_PACKET_CHANNEL_MESSAGE ||
+ (header[3] == SILC_PACKET_CHANNEL_MESSAGE &&
+ sock->type == SILC_SOCKET_TYPE_ROUTER))
+ parse_ctx->normal = TRUE;
+ } else {
+ if (header[3] == SILC_PACKET_PRIVATE_MESSAGE &&
+ (header[2] & SILC_PACKET_FLAG_PRIVMSG_KEY))
+ parse_ctx->normal = FALSE;
+ else if (header[3] != SILC_PACKET_CHANNEL_MESSAGE)
+ parse_ctx->normal = TRUE;
+ }
+
+ SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
+ sequence - 1, paddedlen + mac_len),
+ sock->inbuf->data, paddedlen + mac_len);
+
+ /* Put the decrypted part, and rest of the encrypted data, and decrypt */
+ silc_buffer_put(parse_ctx->packet->buffer, header, block_len);
+ silc_buffer_pull(parse_ctx->packet->buffer, block_len);
+ silc_buffer_put(parse_ctx->packet->buffer, sock->inbuf->data + block_len,
+ paddedlen - block_len);
+ if (cipher) {
+ silc_cipher_set_iv(cipher, iv);
+ ret = silc_packet_decrypt(cipher, hmac, parse_ctx->packet->sequence,
+ parse_ctx->packet->buffer,
+ parse_ctx->normal);
+ if (ret < 0) {
+ SILC_LOG_WARNING(("Packet decryption failed %s:%d [%s] [%s]",
+ sock->hostname, sock->port,
+ silc_get_packet_name(parse_ctx->packet->type),
+ (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
+ sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
+ sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
+ "Router")));
+ memset(tmp, 0, sizeof(tmp));
+ silc_packet_context_free(parse_ctx->packet);
+ silc_free(parse_ctx);