Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2001 Pekka Riikonen
+ Copyright (C) 1997 - 2002 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Send the packet */
ret = silc_packet_send(sock, force_send);
- if (ret != -2)
+ if (ret != -2) {
+ server->stat.packets_sent++;
return ret;
+ }
/* Mark that there is some outgoing data available for this connection.
This call sets the connection both for input and output (the input
SilcPacketType type,
SilcPacketFlags flags,
unsigned char *data,
- uint32 data_len,
+ SilcUInt32 data_len,
bool force_send)
{
void *dst_id = NULL;
void *dst_id,
SilcIdType dst_id_type,
unsigned char *data,
- uint32 data_len,
+ SilcUInt32 data_len,
bool force_send)
{
SilcPacketContext packetdata;
+ const SilcBufferStruct packet;
SilcIDListData idata = (SilcIDListData)sock->user_data;
SilcCipher cipher = NULL;
SilcHmac hmac = NULL;
- uint32 sequence = 0;
+ SilcUInt32 sequence = 0;
unsigned char *dst_id_data = NULL;
- uint32 dst_id_len = 0;
+ SilcUInt32 dst_id_len = 0;
int block_len = 0;
/* If disconnecting, ignore the data */
packetdata.dst_id = dst_id_data;
packetdata.dst_id_len = dst_id_len;
packetdata.dst_id_type = dst_id_type;
+ data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
+ packetdata.src_id_len +
+ packetdata.dst_id_len));
packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
packetdata.src_id_len + dst_id_len;
packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
- /* Prepare outgoing data buffer for packet sending */
- silc_packet_send_prepare(sock,
- SILC_PACKET_HEADER_LEN +
- packetdata.src_id_len +
- packetdata.dst_id_len,
- packetdata.padlen,
- data_len);
-
- SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
-
- packetdata.buffer = sock->outbuf;
-
- /* Put the data to the buffer */
- if (data && data_len)
- silc_buffer_put(sock->outbuf, data, data_len);
-
/* Create the outgoing packet */
- silc_packet_assemble(&packetdata, cipher);
+ if (!silc_packet_assemble(&packetdata, NULL, cipher, hmac, sock,
+ data, data_len, (const SilcBuffer)&packet)) {
+ SILC_LOG_ERROR(("Cannot assemble packet"));
+ goto out;
+ }
/* Encrypt the packet */
- silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf, sock->outbuf->len);
+ silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet, packet.len);
- SILC_LOG_HEXDUMP(("Outgoing packet (%d), len %d", sequence,
- sock->outbuf->len),
- sock->outbuf->data, sock->outbuf->len);
+ SILC_LOG_HEXDUMP(("Outgoing packet (%d), len %d", sequence, packet.len),
+ packet.data, packet.len);
/* Now actually send the packet */
silc_server_packet_send_real(server, sock, force_send);
+ out:
if (packetdata.src_id)
silc_free(packetdata.src_id);
if (packetdata.dst_id)
void *dst_id,
SilcIdType dst_id_type,
unsigned char *data,
- uint32 data_len,
+ SilcUInt32 data_len,
bool force_send)
{
SilcPacketContext packetdata;
+ const SilcBufferStruct packet;
SilcIDListData idata;
SilcCipher cipher = NULL;
SilcHmac hmac = NULL;
- uint32 sequence = 0;
+ SilcUInt32 sequence = 0;
unsigned char *dst_id_data = NULL;
- uint32 dst_id_len = 0;
+ SilcUInt32 dst_id_len = 0;
unsigned char *src_id_data = NULL;
- uint32 src_id_len = 0;
+ SilcUInt32 src_id_len = 0;
int block_len = 0;
SILC_LOG_DEBUG(("Sending packet, type %d", type));
packetdata.dst_id = dst_id_data;
packetdata.dst_id_len = dst_id_len;
packetdata.dst_id_type = dst_id_type;
+ data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
+ packetdata.src_id_len +
+ dst_id_len));
packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
packetdata.src_id_len + dst_id_len;
packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen, block_len);
- /* Prepare outgoing data buffer for packet sending */
- silc_packet_send_prepare(sock,
- SILC_PACKET_HEADER_LEN +
- packetdata.src_id_len +
- packetdata.dst_id_len,
- packetdata.padlen,
- data_len);
-
- SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
-
- packetdata.buffer = sock->outbuf;
-
- /* Put the data to the buffer */
- if (data && data_len)
- silc_buffer_put(sock->outbuf, data, data_len);
-
/* Create the outgoing packet */
- silc_packet_assemble(&packetdata, cipher);
+ if (!silc_packet_assemble(&packetdata, NULL, cipher, hmac, sock, data,
+ data_len, (const SilcBuffer)&packet)) {
+ SILC_LOG_ERROR(("Cannot assemble packe"));
+ goto out;
+ }
/* Encrypt the packet */
- silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf, sock->outbuf->len);
+ silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&packet, packet.len);
- SILC_LOG_HEXDUMP(("Outgoing packet (%d), len %d", sequence,
- sock->outbuf->len),
- sock->outbuf->data, sock->outbuf->len);
+ SILC_LOG_HEXDUMP(("Outgoing packet (%d), len %d", sequence, packet.len),
+ packet.data, packet.len);
/* Now actually send the packet */
silc_server_packet_send_real(server, sock, force_send);
+ out:
if (packetdata.src_id)
silc_free(packetdata.src_id);
if (packetdata.dst_id)
not allowed to send the packet. */
id = silc_id_str2id(packet->src_id, packet->src_id_len, packet->src_id_type);
if (id && !SILC_ID_SERVER_COMPARE(id, server->router->id)) {
+ const SilcBufferStruct p;
+
idata = (SilcIDListData)sock->user_data;
silc_buffer_push(buffer, buffer->data - buffer->head);
- silc_packet_send_prepare(sock, 0, 0, buffer->len);
- silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
+ if (!silc_packet_send_prepare(sock, 0, 0, buffer->len, idata->hmac_send,
+ (const SilcBuffer)&p)) {
+ SILC_LOG_ERROR(("Cannot send packet"));
+ silc_free(id);
+ return;
+ }
+ silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len);
silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++,
- sock->outbuf, sock->outbuf->len);
+ (SilcBuffer)&p, p.len);
SILC_LOG_HEXDUMP(("Broadcasted packet (%d), len %d", idata->psn_send - 1,
- sock->outbuf->len),
- sock->outbuf->data, sock->outbuf->len);
+ p.len), p.data, p.len);
/* Now actually send the packet */
silc_server_packet_send_real(server, sock, TRUE);
SilcPacketContext *packet)
{
SilcBuffer buffer = packet->buffer;
+ const SilcBufferStruct p;
SilcIDListData idata;
SILC_LOG_DEBUG(("Routing received packet"));
idata = (SilcIDListData)sock->user_data;
silc_buffer_push(buffer, buffer->data - buffer->head);
- silc_packet_send_prepare(sock, 0, 0, buffer->len);
- silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
+ if (!silc_packet_send_prepare(sock, 0, 0, buffer->len, idata->hmac_send,
+ (const SilcBuffer)&p)) {
+ SILC_LOG_ERROR(("Cannot send packet"));
+ return;
+ }
+ silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len);
silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++,
- sock->outbuf, sock->outbuf->len);
+ (SilcBuffer)&p, p.len);
SILC_LOG_HEXDUMP(("Routed packet (%d), len %d", idata->psn_send - 1,
- sock->outbuf->len),
- sock->outbuf->data, sock->outbuf->len);
+ p.len), p.data, p.len);
/* Now actually send the packet */
silc_server_packet_send_real(server, sock, TRUE);
void silc_server_packet_send_clients(SilcServer server,
SilcClientEntry *clients,
- uint32 clients_count,
+ SilcUInt32 clients_count,
SilcPacketType type,
SilcPacketFlags flags,
bool route,
unsigned char *data,
- uint32 data_len,
+ SilcUInt32 data_len,
bool force_send)
{
SilcSocketConnection sock = NULL;
SilcClientEntry client = NULL;
SilcServerEntry *routed = NULL;
- uint32 routed_count = 0;
+ SilcUInt32 routed_count = 0;
bool gone = FALSE;
int i, k;
/* Send to locally connected client */
sock = (SilcSocketConnection)client->connection;
+ if (!sock)
+ continue;
+
silc_server_packet_send_dest(server, sock, type, flags,
client->id, SILC_ID_CLIENT,
data, data_len, force_send);
SilcPacketContext *packet,
SilcCipher cipher,
SilcHmac hmac,
- uint32 sequence,
+ SilcUInt32 sequence,
unsigned char *data,
- uint32 data_len,
+ SilcUInt32 data_len,
bool channel_message,
bool force_send)
{
int block_len;
+ const SilcBufferStruct p;
if (!sock)
return;
+ data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
+ packet->src_id_len +
+ packet->dst_id_len));
packet->truelen = data_len + SILC_PACKET_HEADER_LEN +
packet->src_id_len + packet->dst_id_len;
else
packet->padlen = SILC_PACKET_PADLEN(packet->truelen, block_len);
- /* Prepare outgoing data buffer for packet sending */
- silc_packet_send_prepare(sock,
- SILC_PACKET_HEADER_LEN +
- packet->src_id_len +
- packet->dst_id_len,
- packet->padlen,
- data_len);
-
- packet->buffer = sock->outbuf;
-
/* Put the data to buffer, assemble and encrypt the packet. The packet
is encrypted with normal session key shared with the client, unless
the `channel_message' is TRUE. */
- silc_buffer_put(sock->outbuf, data, data_len);
- silc_packet_assemble(packet, cipher);
+ if (!silc_packet_assemble(packet, NULL, cipher, hmac, sock, data,
+ data_len, (const SilcBuffer)&p)) {
+ SILC_LOG_ERROR(("Cannot assemble packet"));
+ return;
+ }
+
if (channel_message)
- silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf,
+ silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p,
SILC_PACKET_HEADER_LEN + packet->src_id_len +
packet->dst_id_len + packet->padlen);
else
- silc_packet_encrypt(cipher, hmac, sequence, sock->outbuf,
- sock->outbuf->len);
+ silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p, p.len);
- SILC_LOG_HEXDUMP(("Channel packet (%d), len %d", sequence,
- sock->outbuf->len),
- sock->outbuf->data, sock->outbuf->len);
+ SILC_LOG_HEXDUMP(("Channel packet (%d), len %d", sequence, p.len),
+ p.data, p.len);
/* Now actually send the packet */
silc_server_packet_send_real(server, sock, force_send);
SilcPacketType type,
bool route,
unsigned char *data,
- uint32 data_len,
+ SilcUInt32 data_len,
bool force_send)
{
SilcSocketConnection sock = NULL;
SilcChannelClientEntry chl;
SilcHashTableList htl;
SilcIDListData idata;
- uint32 routed_count = 0;
+ SilcUInt32 routed_count = 0;
bool gone = FALSE;
int k;
if (sender && sock == sender)
continue;
- /* Route only once to router */
+ /* Route only once to router. Protocol prohibits sending channel
+ messages to more than one router. */
if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
if (gone)
continue;
sock = (SilcSocketConnection)client->connection;
idata = (SilcIDListData)client;
- if (sender && sock == sender)
+ if (!sock || (sender && sock == sender))
continue;
/* Send the packet */
force_send);
}
+ silc_hash_table_list_reset(&htl);
silc_free(routed);
silc_free(packetdata.src_id);
silc_free(packetdata.dst_id);
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);
+ SilcUInt32 mac_len = silc_hmac_len(channel->hmac);
+ SilcUInt32 iv_len = silc_cipher_get_block_len(channel->channel_key);
+ unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
- if (dlen > data_len) {
+ if (data_len <= mac_len + iv_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);
+ memcpy(iv, data + (data_len - iv_len), iv_len);
+ silc_channel_message_payload_encrypt(data, data_len - iv_len - mac_len,
+ data_len, iv, iv_len,
+ channel->channel_key, channel->hmac);
}
return TRUE;
void silc_server_packet_relay_to_channel(SilcServer server,
SilcSocketConnection sender_sock,
SilcChannelEntry channel,
- void *sender,
+ void *sender_id,
SilcIdType sender_type,
- void *sender_entry,
+ SilcClientEntry sender_entry,
unsigned char *data,
- uint32 data_len,
+ SilcUInt32 data_len,
bool force_send)
{
- bool found = FALSE;
SilcSocketConnection sock = NULL;
SilcPacketContext packetdata;
SilcClientEntry client = NULL;
SilcServerEntry *routed = NULL;
- SilcChannelClientEntry chl;
- uint32 routed_count = 0;
+ SilcChannelClientEntry chl, chl_sender;
+ SilcUInt32 routed_count = 0;
SilcIDListData idata;
SilcHashTableList htl;
bool gone = FALSE;
SILC_LOG_DEBUG(("Relaying packet to channel"));
+ if (!silc_server_client_on_channel(sender_entry, channel, &chl_sender))
+ return;
+
/* This encrypts the packet, if needed. It will be encrypted if
it came from the router thus it needs to be encrypted with the
channel key. If the channel key does not exist, then we know we
/* Set the packet context pointers. */
packetdata.flags = 0;
packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
- packetdata.src_id = silc_id_id2str(sender, sender_type);
- packetdata.src_id_len = silc_id_get_len(sender, sender_type);
+ packetdata.src_id = silc_id_id2str(sender_id, sender_type);
+ packetdata.src_id_len = silc_id_get_len(sender_id, sender_type);
packetdata.src_id_type = sender_type;
packetdata.dst_id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
routed = silc_calloc(silc_hash_table_count(channel->user_list),
sizeof(*routed));
- /* Mark that to the route the original sender if from is not routed */
- if (sender_type == SILC_ID_CLIENT) {
- client = (SilcClientEntry)sender_entry;
- if (client->router) {
- routed[routed_count++] = client->router;
- SILC_LOG_DEBUG(("************* router %s",
- silc_id_render(client->router->id, SILC_ID_SERVER)));
- }
- }
+ /* Assure we won't route the message back to the sender's way. */
+ if (sender_entry->router)
+ routed[routed_count++] = sender_entry->router;
/* Send the message to clients on the channel's client list. */
silc_hash_table_list(channel->user_list, &htl);
while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
client = chl->client;
- if (!client)
+ if (!client || client == sender_entry)
continue;
- /* Do not send to the sender */
- if (!found && client == sender_entry) {
- found = TRUE;
+ /* Check whether message sending is blocked */
+ if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)
+ continue;
+ if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS &&
+ !(chl_sender->mode & SILC_CHANNEL_UMODE_CHANOP) &&
+ !(chl_sender->mode & SILC_CHANNEL_UMODE_CHANFO))
+ continue;
+ if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS &&
+ sender_entry->mode & SILC_UMODE_ROBOT)
continue;
- }
/* If the client has set router it means that it is not locally
connected client and we will route the packet further. */
if (server->server_type == SILC_ROUTER && client->router) {
- /* Sender maybe server as well so we want to make sure that
- we won't send the message to the server it came from. */
- if (!found && SILC_ID_SERVER_COMPARE(client->router->id, sender)) {
- found = TRUE;
- routed[routed_count++] = client->router;
- continue;
- }
-
/* Check if we have sent the packet to this route already */
for (k = 0; k < routed_count; k++)
if (routed[k] == client->router)
break;
if (k < routed_count)
continue;
-
+
/* Get data used in packet header encryption, keys and stuff. */
sock = (SilcSocketConnection)client->router->connection;
idata = (SilcIDListData)client->router;
- /* Do not send to the sender. Check first whether the true
- sender's router is same as this client's router. Also check
- if the sender socket is the same as this client's router
+ /* Check if the sender socket is the same as this client's router
socket. */
- if (sender_entry &&
- ((SilcClientEntry)sender_entry)->router == client->router)
- continue;
if (sender_sock && sock == sender_sock)
continue;
/* Mark this route routed already. */
routed[routed_count++] = client->router;
- /* If the remote connection is router then we'll decrypt the
- channel message and re-encrypt it with the session key shared
- between us and the remote router. This is done because the
- channel keys are cell specific and we have different channel
- key than the remote router has. */
if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ /* The remote connection is router then we'll decrypt the
+ channel message and re-encrypt it with the session key shared
+ between us and the remote router. This is done because the
+ channel keys are cell specific and we have different channel
+ key than the remote router has. */
+
+ /* Route only once to router. Protocol prohibits sending channel
+ messages to more than one router. */
if (gone)
continue;
+ gone = TRUE;
SILC_LOG_DEBUG(("Remote is router, encrypt with session key"));
- gone = TRUE;
/* If private key mode is not set then decrypt the packet
and re-encrypt it */
- if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
- unsigned char *tmp = silc_calloc(data_len, sizeof(*data));
+ if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY) &&
+ channel->channel_key) {
+ unsigned char tmp[SILC_PACKET_MAX_LEN];
+
+ if (data_len > SILC_PACKET_MAX_LEN)
+ data_len = SILC_PACKET_MAX_LEN;
memcpy(tmp, data, data_len);
/* Decrypt the channel message (we don't check the MAC) */
- if (channel->channel_key &&
- !silc_channel_message_payload_decrypt(tmp, data_len,
- channel->channel_key,
- NULL)) {
- memset(tmp, 0, data_len);
- silc_free(tmp);
- continue;
- }
+ silc_channel_message_payload_decrypt(tmp, data_len,
+ channel->channel_key, NULL);
/* Now re-encrypt and send it to the router */
- silc_server_packet_send_srcdest(server, sock,
+ silc_server_packet_send_srcdest(server, sock,
SILC_PACKET_CHANNEL_MESSAGE, 0,
- sender, sender_type,
+ sender_id, sender_type,
channel->id, SILC_ID_CHANNEL,
tmp, data_len, force_send);
-
- /* Free the copy of the channel message */
- memset(tmp, 0, data_len);
- silc_free(tmp);
} else {
/* Private key mode is set, we don't have the channel key, so
just re-encrypt the entire packet and send it to the router. */
- silc_server_packet_send_srcdest(server, sock,
+ silc_server_packet_send_srcdest(server, sock,
SILC_PACKET_CHANNEL_MESSAGE, 0,
- sender, sender_type,
+ sender_id, sender_type,
channel->id, SILC_ID_CHANNEL,
data, data_len, force_send);
}
- continue;
+ } else {
+ /* Send the packet to normal server */
+ silc_server_packet_send_to_channel_real(server, sock, &packetdata,
+ idata->send_key,
+ idata->hmac_send,
+ idata->psn_send++,
+ data, data_len, TRUE,
+ force_send);
}
- /* Send the packet (to normal server) */
- silc_server_packet_send_to_channel_real(server, sock, &packetdata,
- idata->send_key,
- idata->hmac_send,
- idata->psn_send++,
- data, data_len, TRUE,
- force_send);
-
continue;
}
sock = (SilcSocketConnection)client->connection;
idata = (SilcIDListData)client;
- if (sender_sock && sock == sender_sock)
+ if (!sock || (sender_sock && sock == sender_sock))
continue;
SILC_LOG_DEBUG(("Sending packet to client ID(%s) %s (%s)",
force_send);
}
+ silc_hash_table_list_reset(&htl);
silc_free(routed);
silc_free(packetdata.src_id);
silc_free(packetdata.dst_id);
SilcPacketType type,
SilcPacketFlags flags,
unsigned char *data,
- uint32 data_len,
+ SilcUInt32 data_len,
bool force_send)
{
SilcChannelClientEntry chl;
force_send);
}
}
+ silc_hash_table_list_reset(&htl);
}
/* Routine used to send (relay, route) private messages to some destination.
SilcSocketConnection dst_sock,
SilcCipher cipher,
SilcHmac hmac,
- uint32 sequence,
+ SilcUInt32 sequence,
SilcPacketContext *packet)
{
SilcBuffer buffer = packet->buffer;
+ const SilcBufferStruct p;
+
+ silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len
+ + packet->dst_id_len + packet->padlen);
+ if (!silc_packet_send_prepare(dst_sock, 0, 0, buffer->len, hmac,
+ (const SilcBuffer)&p)) {
+ SILC_LOG_ERROR(("Cannot send packet"));
+ return;
+ }
+ silc_buffer_put((SilcBuffer)&p, buffer->data, buffer->len);
/* Re-encrypt and send if private messge key does not exist */
if (!(packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY)) {
-
- silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len
- + packet->dst_id_len + packet->padlen);
- silc_packet_send_prepare(dst_sock, 0, 0, buffer->len);
- silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len);
-
/* Re-encrypt packet */
- silc_packet_encrypt(cipher, hmac, sequence, dst_sock->outbuf, buffer->len);
-
- /* Send the packet */
- silc_server_packet_send_real(server, dst_sock, FALSE);
-
+ silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p, buffer->len);
} else {
/* Key exist so encrypt just header and send it */
- silc_buffer_push(buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len
- + packet->dst_id_len + packet->padlen);
- silc_packet_send_prepare(dst_sock, 0, 0, buffer->len);
- silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len);
-
- /* Encrypt header */
- silc_packet_encrypt(cipher, hmac, sequence, dst_sock->outbuf,
+ silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p,
SILC_PACKET_HEADER_LEN + packet->src_id_len +
packet->dst_id_len + packet->padlen);
-
- silc_server_packet_send_real(server, dst_sock, FALSE);
}
+
+ /* Send the packet */
+ silc_server_packet_send_real(server, dst_sock, FALSE);
}
/* Sends current motd to client */
void silc_server_send_motd(SilcServer server,
SilcSocketConnection sock)
{
- char *motd;
- uint32 motd_len;
+ char *motd, *motd_file = NULL;
+ SilcUInt32 motd_len;
- if (server->config && server->config->motd &&
- server->config->motd->motd_file) {
+ if (server->config)
+ motd_file = server->config->server_info->motd_file;
- motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
+ if (motd_file) {
+ motd = silc_file_readfile(motd_file, &motd_len);
if (!motd)
return;
SilcSocketConnection sock,
bool broadcast,
SilcNotifyType type,
- uint32 argc, ...)
+ SilcUInt32 argc, ...)
{
va_list ap;
SilcBuffer packet;
SilcSocketConnection sock,
bool broadcast,
SilcNotifyType type,
- uint32 argc,
+ SilcUInt32 argc,
SilcBuffer args)
{
SilcBuffer packet;
SilcSocketConnection sock,
bool broadcast,
SilcClientID *old_id,
- SilcClientID *new_id)
+ SilcClientID *new_id,
+ const char *nickname)
{
SilcBuffer idp1, idp2;
silc_server_send_notify(server, sock, broadcast,
SILC_NOTIFY_TYPE_NICK_CHANGE,
- 2, idp1->data, idp1->len, idp2->data, idp2->len);
+ 3, idp1->data, idp1->len, idp2->data, idp2->len,
+ nickname, nickname ? strlen(nickname) : 0);
silc_buffer_free(idp1);
silc_buffer_free(idp2);
}
SilcSocketConnection sock,
bool broadcast,
SilcChannelEntry channel,
- uint32 mode_mask,
+ SilcUInt32 mode_mask,
void *id, SilcIdType id_type,
- char *cipher, char *hmac,
- char *passphrase)
+ const char *cipher, const char *hmac,
+ const char *passphrase,
+ SilcPublicKey founder_key)
{
SilcBuffer idp;
- unsigned char mode[4];
+ unsigned char mode[4], *key = NULL;
+ SilcUInt32 key_len = 0;
idp = silc_id_payload_encode((void *)id, id_type);
SILC_PUT32_MSB(mode_mask, mode);
+ if (founder_key)
+ key = silc_pkcs_public_key_encode(founder_key, &key_len);
silc_server_send_notify_dest(server, sock, broadcast, (void *)channel->id,
SILC_ID_CHANNEL, SILC_NOTIFY_TYPE_CMODE_CHANGE,
- 5, idp->data, idp->len,
+ 6, idp->data, idp->len,
mode, 4,
cipher, cipher ? strlen(cipher) : 0,
hmac, hmac ? strlen(hmac) : 0,
passphrase, passphrase ?
- strlen(passphrase) : 0);
+ strlen(passphrase) : 0,
+ key, key_len);
+ silc_free(key);
silc_buffer_free(idp);
}
-/* Sends CUMODE_CHANGE notify type. This tells that `client_id' changed the
+/* Sends CUMODE_CHANGE notify type. This tells that `id' changed the
`target' client's mode on `channel'. The notify packet is always
destined to the channel. */
SilcSocketConnection sock,
bool broadcast,
SilcChannelEntry channel,
- uint32 mode_mask,
+ SilcUInt32 mode_mask,
void *id, SilcIdType id_type,
- SilcClientID *target)
+ SilcClientID *target,
+ SilcPublicKey founder_key)
{
SilcBuffer idp1, idp2;
- unsigned char mode[4];
+ unsigned char mode[4], *key = NULL;
+ SilcUInt32 key_len = 0;
idp1 = silc_id_payload_encode((void *)id, id_type);
idp2 = silc_id_payload_encode((void *)target, SILC_ID_CLIENT);
SILC_PUT32_MSB(mode_mask, mode);
+ if (founder_key)
+ key = silc_pkcs_public_key_encode(founder_key, &key_len);
silc_server_send_notify_dest(server, sock, broadcast, (void *)channel->id,
SILC_ID_CHANNEL,
- SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
+ SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
idp1->data, idp1->len,
mode, 4,
- idp2->data, idp2->len);
+ idp2->data, idp2->len,
+ key, key_len);
+ silc_free(key);
silc_buffer_free(idp1);
silc_buffer_free(idp2);
}
SilcSocketConnection sock,
bool broadcast,
SilcClientID *client_id,
- char *comment)
+ const char *comment,
+ void *killer, SilcIdType killer_type)
{
- SilcBuffer idp;
+ SilcBuffer idp1;
+ SilcBuffer idp2;
- idp = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
+ idp1 = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
+ idp2 = silc_id_payload_encode(killer, killer_type);
silc_server_send_notify_dest(server, sock, broadcast, (void *)client_id,
SILC_ID_CLIENT, SILC_NOTIFY_TYPE_KILLED,
- comment ? 2 : 1, idp->data, idp->len,
- comment, comment ? strlen(comment) : 0);
- silc_buffer_free(idp);
+ 3, idp1->data, idp1->len,
+ comment, comment ? strlen(comment) : 0,
+ idp2->data, idp2->len);
+ silc_buffer_free(idp1);
+ silc_buffer_free(idp2);
}
/* Sends UMODE_CHANGE notify type. This tells that `client_id' client's
SilcSocketConnection sock,
bool broadcast,
SilcClientID *client_id,
- uint32 mode_mask)
+ SilcUInt32 mode_mask)
{
SilcBuffer idp;
unsigned char mode[4];
silc_buffer_free(idp2);
}
+/* Sends WATCH notify type. This tells that the `client' was watched and
+ its status in the network has changed. */
+
+void silc_server_send_notify_watch(SilcServer server,
+ SilcSocketConnection sock,
+ SilcClientEntry watcher,
+ SilcClientEntry client,
+ const char *nickname,
+ SilcNotifyType type)
+{
+ SilcBuffer idp;
+ unsigned char mode[4], n[2];
+
+ idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+ SILC_PUT16_MSB(type, n);
+ SILC_PUT32_MSB(client->mode, mode);
+ silc_server_send_notify_dest(server, sock, FALSE, watcher->id,
+ SILC_ID_CLIENT, SILC_NOTIFY_TYPE_WATCH,
+ 4, idp->data, idp->len,
+ nickname, nickname ? strlen(nickname) : 0,
+ mode, sizeof(mode),
+ type != SILC_NOTIFY_TYPE_NONE ?
+ n : NULL, sizeof(n));
+ silc_buffer_free(idp);
+}
+
/* Sends notify message destined to specific entity. */
void silc_server_send_notify_dest(SilcServer server,
void *dest_id,
SilcIdType dest_id_type,
SilcNotifyType type,
- uint32 argc, ...)
+ SilcUInt32 argc, ...)
{
va_list ap;
SilcBuffer packet;
SilcChannelEntry channel,
bool route_notify,
SilcNotifyType type,
- uint32 argc, ...)
+ SilcUInt32 argc, ...)
{
va_list ap;
SilcBuffer packet;
SilcClientEntry sender,
SilcClientEntry client,
SilcNotifyType type,
- uint32 argc, ...)
+ SilcUInt32 argc, ...)
{
int k;
SilcSocketConnection sock = NULL;
SilcPacketContext packetdata;
SilcClientEntry c;
SilcClientEntry *sent_clients = NULL;
- uint32 sent_clients_count = 0;
+ SilcUInt32 sent_clients_count = 0;
SilcServerEntry *routed = NULL;
- uint32 routed_count = 0;
+ SilcUInt32 routed_count = 0;
SilcHashTableList htl, htl2;
SilcChannelEntry channel;
SilcChannelClientEntry chl, chl2;
SilcIDListData idata;
SilcBuffer packet;
unsigned char *data;
- uint32 data_len;
+ SilcUInt32 data_len;
bool force_send = FALSE;
va_list ap;
sock = (SilcSocketConnection)c->connection;
idata = (SilcIDListData)c;
+ if (!sock)
+ continue;
+
packetdata.dst_id = silc_id_id2str(c->id, SILC_ID_CLIENT);
packetdata.dst_id_len = silc_id_get_len(c->id, SILC_ID_CLIENT);
packetdata.dst_id_type = SILC_ID_CLIENT;
sent_clients[sent_clients_count++] = c;
}
}
+ silc_hash_table_list_reset(&htl2);
}
+ silc_hash_table_list_reset(&htl);
silc_free(routed);
silc_free(sent_clients);
silc_free(packetdata.src_id);
SilcSocketConnection sock,
bool broadcast,
void *id, SilcIdType id_type,
- uint32 id_len)
+ SilcUInt32 id_len)
{
SilcBuffer idp;
silc_server_packet_send(server, sock, SILC_PACKET_NEW_ID,
broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
idp->data, idp->len, FALSE);
-
- /* Send to backup routers if this is being broadcasted to primary
- router. */
- if (server->router && server->router->connection &&
- sock == server->router->connection && broadcast)
- silc_server_backup_send(server, NULL, SILC_PACKET_NEW_ID, 0,
- idp->data, idp->len, FALSE, TRUE);
-
silc_buffer_free(idp);
}
bool broadcast,
char *channel_name,
void *channel_id,
- uint32 channel_id_len,
- uint32 mode)
+ SilcUInt32 channel_id_len,
+ SilcUInt32 mode)
{
SilcBuffer packet;
unsigned char *cid;
- uint32 name_len = strlen(channel_name);
+ SilcUInt32 name_len = strlen(channel_name);
SILC_LOG_DEBUG(("Start"));
broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
packet->data, packet->len, FALSE);
- /* Send to backup routers if this is being broadcasted to primary
- router. */
- if (server->server_type == SILC_ROUTER &&
- server->router && server->router->connection &&
- sock == server->router->connection && broadcast)
- silc_server_backup_send(server, NULL, SILC_PACKET_NEW_CHANNEL, 0,
- packet->data, packet->len, FALSE, TRUE);
-
silc_free(cid);
silc_buffer_free(packet);
}
{
SilcBuffer packet;
unsigned char *chid;
- uint32 tmp_len;
+ SilcUInt32 tmp_len;
SILC_LOG_DEBUG(("Sending key to channel %s", channel->channel_name));
void silc_server_send_command(SilcServer server,
SilcSocketConnection sock,
SilcCommand command,
- uint16 ident,
- uint32 argc, ...)
+ SilcUInt16 ident,
+ SilcUInt32 argc, ...)
{
SilcBuffer packet;
va_list ap;
void silc_server_send_command_reply(SilcServer server,
SilcSocketConnection sock,
SilcCommand command,
- SilcCommandStatus status,
- uint16 ident,
- uint32 argc, ...)
+ SilcStatus status,
+ SilcStatus error,
+ SilcUInt16 ident,
+ SilcUInt32 argc, ...)
{
SilcBuffer packet;
va_list ap;
va_start(ap, argc);
- packet = silc_command_reply_payload_encode_vap(command, status, ident,
- argc, ap);
+ packet = silc_command_reply_payload_encode_vap(command, status, error,
+ ident, argc, ap);
silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
packet->data, packet->len, TRUE);
silc_buffer_free(packet);
void *dst_id,
SilcIdType dst_id_type,
SilcCommand command,
- SilcCommandStatus status,
- uint16 ident,
- uint32 argc, ...)
+ SilcStatus status,
+ SilcStatus error,
+ SilcUInt16 ident,
+ SilcUInt32 argc, ...)
{
SilcBuffer packet;
va_list ap;
va_start(ap, argc);
- packet = silc_command_reply_payload_encode_vap(command, status, ident,
- argc, ap);
+ packet = silc_command_reply_payload_encode_vap(command, status, error,
+ ident, argc, ap);
silc_server_packet_send_dest(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
dst_id, dst_id_type, packet->data,
packet->len, TRUE);
SilcSocketConnection dst_sock,
SilcCipher cipher,
SilcHmac hmac,
- uint32 sequence,
+ SilcUInt32 sequence,
SilcPacketContext *packet,
bool force_send)
{
+ const SilcBufferStruct p;
+
silc_buffer_push(packet->buffer, SILC_PACKET_HEADER_LEN + packet->src_id_len
+ packet->dst_id_len + packet->padlen);
+ if (!silc_packet_send_prepare(dst_sock, 0, 0, packet->buffer->len, hmac,
+ (const SilcBuffer)&p)) {
+ SILC_LOG_ERROR(("Cannot send packet"));
+ return;
+ }
+ silc_buffer_put((SilcBuffer)&p, packet->buffer->data, packet->buffer->len);
- silc_packet_send_prepare(dst_sock, 0, 0, packet->buffer->len);
- silc_buffer_put(dst_sock->outbuf, packet->buffer->data, packet->buffer->len);
-
/* Re-encrypt packet */
- silc_packet_encrypt(cipher, hmac, sequence, dst_sock->outbuf,
- packet->buffer->len);
+ silc_packet_encrypt(cipher, hmac, sequence, (SilcBuffer)&p, p.len);
/* Send the packet */
silc_server_packet_send_real(server, dst_sock, force_send);
void silc_server_send_connection_auth_request(SilcServer server,
SilcSocketConnection sock,
- uint16 conn_type,
+ SilcUInt16 conn_type,
SilcAuthMethod auth_meth)
{
SilcBuffer packet;
if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
(SILC_IS_DISCONNECTED(sock) == FALSE)) {
server->stat.packets_sent++;
-
- if (sock->outbuf->data - sock->outbuf->head)
- silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
-
silc_packet_send(sock, TRUE);
-
SILC_SET_CONNECTION_FOR_INPUT(server->schedule, sock->sock);
SILC_UNSET_OUTBUF_PENDING(sock);
silc_buffer_clear(sock->outbuf);