+/* This checks whether the relayed packet came from router. If it did
+ then we'll need to encrypt it with the channel key. This is called
+ from the silc_server_packet_relay_to_channel. */
+
+static bool
+silc_server_packet_relay_to_channel_encrypt(SilcServer server,
+ SilcSocketConnection sock,
+ SilcChannelEntry channel,
+ unsigned char *data,
+ unsigned int data_len)
+{
+ /* If we are router and the packet came from router and private key
+ has not been set for the channel then we must encrypt the packet
+ as it was decrypted with the session key shared between us and the
+ router which sent it. This is so, because cells does not share the
+ same channel key. */
+ if (server->server_type == SILC_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_ROUTER &&
+ !(channel->mode & SILC_CHANNEL_MODE_PRIVKEY) &&
+ channel->channel_key) {
+ SilcBuffer chp;
+ uint32 iv_len, i;
+ uint16 dlen, flags;
+
+ iv_len = silc_cipher_get_block_len(channel->channel_key);
+ if (channel->iv[0] == '\0')
+ for (i = 0; i < iv_len; i++) channel->iv[i] =
+ silc_rng_get_byte(server->rng);
+ else
+ silc_hash_make(server->md5hash, channel->iv, iv_len, channel->iv);
+
+ /* Encode new payload. This encrypts it also. */
+ SILC_GET16_MSB(flags, data);
+ SILC_GET16_MSB(dlen, data + 2);
+
+ if (dlen > data_len) {
+ SILC_LOG_WARNING(("Corrupted channel message, cannot relay it"));
+ return FALSE;
+ }
+
+ chp = silc_channel_message_payload_encode(flags, dlen, data + 4,
+ iv_len, channel->iv,
+ channel->channel_key,
+ channel->hmac);
+ memcpy(data, chp->data, chp->len);
+ silc_buffer_free(chp);
+ }
+
+ return TRUE;
+}
+