SilcClientEntry client = (SilcClientEntry)sock->user_data;
if (!client)
- goto out;
+ return;
/* Allow only one command executed in 2 seconds. */
curtime = time(NULL);
if (client->last_command && (curtime - client->last_command) < 2)
- goto out;
+ return;
/* Update access time */
client->last_command = curtime;
ctx = silc_calloc(1, sizeof(*ctx));
ctx->server = server;
ctx->sock = sock;
- ctx->packet = packet; /* Save original packet */
+ ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
/* Parse the command payload in the packet */
ctx->payload = silc_command_payload_parse(packet->buffer);
if (!ctx->payload) {
SILC_LOG_ERROR(("Bad command payload, packet dropped"));
silc_buffer_free(packet->buffer);
+ silc_packet_context_free(packet);
silc_free(ctx);
return;
}
if (cmd == NULL) {
SILC_LOG_ERROR(("Unknown command, packet dropped"));
- silc_free(ctx);
- goto out;
+ silc_server_command_free(ctx);
+ return;
}
-
- out:
- silc_buffer_free(packet->buffer);
}
/* Add new pending command to be executed when reply to a command has been
static void silc_server_command_free(SilcServerCommandContext cmd)
{
if (cmd) {
- silc_command_free_payload(cmd->payload);
+ if (cmd->payload)
+ silc_command_free_payload(cmd->payload);
+ if (cmd->packet)
+ silc_packet_context_free(cmd->packet);
silc_free(cmd);
}
}
/* Send WHOIS command to our router */
silc_server_packet_send(server, (SilcSocketConnection)
- server->id_entry->router->connection,
+ server->router->connection,
SILC_PACKET_COMMAND, cmd->packet->flags,
tmpbuf->data, tmpbuf->len, TRUE);
return;
/* Send IDENTIFY command to our router */
silc_buffer_push(buffer, buffer->data - buffer->head);
silc_server_packet_forward(server, (SilcSocketConnection)
- server->id_entry->router->connection,
+ server->router->connection,
buffer->data, buffer->len, TRUE);
return;
}
&new_id);
/* Send notify about nickname change to our router. We send the new
- ID and ask to replace it with the old one. */
- if (cmd->server->server_type == SILC_SERVER && !cmd->server->standalone)
- silc_server_send_replace_id(server, server->id_entry->router->connection,
- FALSE, client->id,
- SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
- new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
-
- /* If we are router we have to distribute the new Client ID to all
- routers in SILC. */
- if (cmd->server->server_type == SILC_ROUTER && !cmd->server->standalone)
- silc_server_send_replace_id(server, server->id_entry->router->connection,
- TRUE, client->id,
+ ID and ask to replace it with the old one. If we are router the
+ packet is broadcasted. */
+ if (!cmd->server->standalone)
+ silc_server_send_replace_id(server, server->router->connection,
+ server->server_type == SILC_SERVER ?
+ FALSE : TRUE, client->id,
SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
client = silc_idlist_find_client_by_id(server->local_list, id);
if (!client) {
/* XXX */
+ SILC_LOG_ERROR(("Forwarded join command did not find the client who "
+ "wanted to join the channel"));
goto out;
}
silc_free(id);
silc_task_register(server->timeout_queue, sock->sock,
silc_server_command_join_notify, ctx,
0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+ goto out;
}
/* Send NAMES command reply to the joined channel so the user sees who
/* Forward the original JOIN command to the router */
silc_buffer_push(buffer, buffer->data - buffer->head);
silc_server_packet_forward(server, (SilcSocketConnection)
- server->id_entry->router->connection,
+ server->router->connection,
buffer->data, buffer->len, TRUE);
/* Add the command to be pending. It will be re-executed after
if (server->server_type == SILC_SERVER) {
if (!server->standalone)
silc_server_packet_send(server,
- cmd->server->id_entry->router->connection,
+ cmd->server->router->connection,
SILC_PACKET_CHANNEL_KEY, 0, packet->data,
packet->len, TRUE);
} else {
if (server->server_type == SILC_SERVER) {
if (!server->standalone)
silc_server_packet_send(server,
- cmd->server->id_entry->router->connection,
+ cmd->server->router->connection,
SILC_PACKET_CHANNEL_KEY, 0, packet->data,
packet->len, TRUE);
} else {
if (server->server_type == SILC_SERVER) {
if (!server->standalone)
silc_server_packet_send(server,
- cmd->server->id_entry->router->connection,
+ cmd->server->router->connection,
SILC_PACKET_CHANNEL_KEY, 0, packet->data,
packet->len, TRUE);
} else {
of clients on the channel. */
if (!server->standalone)
silc_server_send_remove_channel_user(server,
- server->id_entry->router->connection,
+ server->router->connection,
server->server_type == SILC_ROUTER ?
TRUE : FALSE, id_entry->id, id);
if (server->server_type == SILC_SERVER) {
if (!server->standalone)
silc_server_packet_send(server,
- cmd->server->id_entry->router->connection,
+ cmd->server->router->connection,
SILC_PACKET_CHANNEL_KEY, 0, packet->data,
packet->len, TRUE);
} else {
/* Error occured during protocol */
silc_protocol_free(protocol);
if (ctx->packet)
- silc_buffer_free(ctx->packet);
+ silc_packet_context_free(ctx->packet);
if (ctx->ske)
silc_ske_free(ctx->ske);
if (ctx->dest_id)
/* Free old protocol as it is finished now */
silc_protocol_free(protocol);
if (ctx->packet)
- silc_buffer_free(ctx->packet);
+ silc_packet_context_free(ctx->packet);
silc_free(ctx);
sock->protocol = NULL;
sock->user_data = (void *)id_entry;
sock->type = SILC_SOCKET_TYPE_ROUTER;
server->id_entry->router = id_entry;
+ server->router = id_entry;
out:
/* Free the temporary connection data context */
/* Free the protocol object */
silc_protocol_free(protocol);
if (ctx->packet)
- silc_buffer_free(ctx->packet);
+ silc_packet_context_free(ctx->packet);
if (ctx->ske)
silc_ske_free(ctx->ske);
silc_free(ctx);
/* Error occured during protocol */
silc_protocol_free(protocol);
if (ctx->packet)
- silc_buffer_free(ctx->packet);
+ silc_packet_context_free(ctx->packet);
if (ctx->ske)
silc_ske_free(ctx->ske);
if (ctx->dest_id)
/* Free old protocol as it is finished now */
silc_protocol_free(protocol);
if (ctx->packet)
- silc_buffer_free(ctx->packet);
+ silc_packet_context_free(ctx->packet);
silc_free(ctx);
sock->protocol = NULL;
/* Error occured during protocol */
silc_protocol_free(protocol);
if (ctx->packet)
- silc_buffer_free(ctx->packet);
+ silc_packet_context_free(ctx->packet);
if (ctx->ske)
silc_ske_free(ctx->ske);
if (ctx->dest_id)
if (server->standalone && sock->type == SILC_SOCKET_TYPE_ROUTER) {
SILC_LOG_DEBUG(("We are not standalone server anymore"));
server->standalone = FALSE;
- if (!server->id_entry->router)
+ if (!server->id_entry->router) {
server->id_entry->router = id_entry;
+ server->router = id_entry;
+ }
}
break;
}
silc_protocol_free(protocol);
if (ctx->packet)
- silc_buffer_free(ctx->packet);
+ silc_packet_context_free(ctx->packet);
if (ctx->ske)
silc_ske_free(ctx->ske);
if (ctx->dest_id)
if (server->server_type == SILC_ROUTER &&
sock->type == SILC_SOCKET_TYPE_ROUTER &&
packet->flags & SILC_PACKET_FLAG_BROADCAST) {
- silc_server_packet_broadcast(server, server->id_entry->router->connection,
- packet);
+ silc_server_packet_broadcast(server, server->router->connection, packet);
}
/* Parse the incoming packet type */
out:
silc_buffer_clear(sock->inbuf);
- if (packet->src_id)
- silc_free(packet->src_id);
- if (packet->dst_id)
- silc_free(packet->dst_id);
- silc_free(packet);
+ silc_packet_context_free(packet);
silc_free(parse_ctx);
}
SilcSocketConnection sock,
SilcPacketContext *packet)
{
- SilcBuffer buffer = packet->buffer;
SilcPacketType type = packet->type;
SILC_LOG_DEBUG(("Parsing packet type %d", type));
case SILC_PACKET_DISCONNECT:
SILC_LOG_DEBUG(("Disconnect packet"));
break;
+
case SILC_PACKET_SUCCESS:
/*
* Success received for something. For now we can have only
sock->protocol, sock->sock, 0, 0);
}
break;
+
case SILC_PACKET_FAILURE:
/*
* Failure received for something. For now we can have only
sock->protocol, sock->sock, 0, 0);
}
break;
+
case SILC_PACKET_REJECT:
SILC_LOG_DEBUG(("Reject packet"));
return;
break;
+ case SILC_PACKET_NOTIFY:
+ /*
+ * Received notify packet.
+ */
+ SILC_LOG_DEBUG(("Notify packet"));
+ break;
+
/*
* Channel packets
*/
SilcServerKEInternalContext *proto_ctx =
(SilcServerKEInternalContext *)sock->protocol->context;
- proto_ctx->packet = buffer;
+ proto_ctx->packet = silc_packet_context_dup(packet);
/* Let the protocol handle the packet */
sock->protocol->execute(server->timeout_queue, 0,
(SilcServerKEInternalContext *)sock->protocol->context;
if (proto_ctx->packet)
- silc_buffer_free(proto_ctx->packet);
+ silc_packet_context_free(proto_ctx->packet);
- proto_ctx->packet = buffer;
+ 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_type);
(SilcServerKEInternalContext *)sock->protocol->context;
if (proto_ctx->packet)
- silc_buffer_free(proto_ctx->packet);
+ silc_packet_context_free(proto_ctx->packet);
- proto_ctx->packet = buffer;
+ 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_type);
/* If we receive this packet we will send to the other end information
about our mandatory authentication method for the connection.
This packet maybe received at any time. */
+ SILC_LOG_DEBUG(("Connection authentication request packet"));
+ break;
/*
* Connection Authentication protocol packets
SilcServerConnAuthInternalContext *proto_ctx =
(SilcServerConnAuthInternalContext *)sock->protocol->context;
- proto_ctx->packet = buffer;
+ proto_ctx->packet = silc_packet_context_dup(packet);
/* Let the protocol handle the packet */
sock->protocol->execute(server->timeout_queue, 0,
break;
case SILC_PACKET_REMOVE_ID:
+ /*
+ * Received remove ID Packet.
+ */
+ SILC_LOG_DEBUG(("Remove ID packet"));
break;
case SILC_PACKET_REMOVE_CHANNEL_USER:
/* Broadcast received packet to our primary route. This function is used
by router to further route received broadcast packet. It is expected
that the broadcast flag from the packet is checked before calling this
- function. This does not check for the broadcast flag. The `sock' must
- be the socket of the primary route. */
+ function. This does not test or set the broadcast flag. */
void silc_server_packet_broadcast(SilcServer server,
SilcSocketConnection sock,
/* If the packet is originated from our primary route we are
not allowed to send the packet. */
id = silc_id_str2id(packet->src_id, packet->src_id_type);
- if (id && SILC_ID_SERVER_COMPARE(id, server->id_entry->router->id)) {
+ if (id && SILC_ID_SERVER_COMPARE(id, server->router->id)) {
idata = (SilcIDListData)sock->user_data;
- silc_packet_send_prepare(sock, 0, 0, buffer->len);
+
+ 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);
silc_packet_encrypt(idata->send_key, idata->hmac,
sock->outbuf, sock->outbuf->len);
SilcServerEntry router;
/* Get data used in packet header encryption, keys and stuff. */
- router = server->id_entry->router;
+ router = server->router;
sock = (SilcSocketConnection)router->connection;
idata = (SilcIDListData)router;
channel->global_users) {
SilcServerEntry router;
- router = server->id_entry->router;
+ router = server->router;
/* Check that the sender is not our router. */
if (sender_sock != (SilcSocketConnection)router->connection) {
/* Source must be server or router */
if (packet->src_id_type != SILC_ID_SERVER &&
sock->type != SILC_SOCKET_TYPE_ROUTER)
- goto out;
+ return;
/* Destination must be client */
if (packet->dst_id_type != SILC_ID_CLIENT)
- goto out;
+ return;
/* Execute command reply locally for the command */
silc_server_command_reply_process(server, sock, buffer);
/* Destination must be one of ours */
client = silc_idlist_find_client_by_id(server->local_list, id);
if (!client) {
+ SILC_LOG_ERROR(("Cannot relay command reply to unknown client"));
silc_free(id);
- goto out;
+ return;
}
/* Relay the packet to the client */
buffer->len);
/* Send the packet */
- silc_server_packet_send_real(server, dst_sock, FALSE);
+ silc_server_packet_send_real(server, dst_sock, TRUE);
silc_free(id);
-
- out:
- silc_buffer_free(buffer);
}
/* Closes connection to socket connection */
SilcSocketConnection sock,
SilcPacketContext *packet)
{
- SilcBuffer buffer = packet->buffer;
SilcClientID *id;
SilcServerEntry router;
SilcSocketConnection dst_sock;
idata->send_key,
idata->hmac,
packet);
- goto out;
+ return;
}
/* Seems that client really is directly connected to us */
silc_server_private_message_send_internal(server, dst_sock,
idata->send_key,
idata->hmac, packet);
- goto out;
+ return;
}
/* Destination belongs to someone not in this server. If we are normal
server our action is to send the packet to our router. */
if (server->server_type == SILC_SERVER && !server->standalone) {
- router = server->id_entry->router;
+ router = server->router;
/* Send to primary route */
if (router) {
idata->send_key,
idata->hmac, packet);
}
- goto out;
+ return;
}
/* We are router and we will perform route lookup for the destination
silc_server_private_message_send_internal(server, dst_sock,
idata->send_key,
idata->hmac, packet);
-
- goto out;
+ return;
}
err:
silc_server_send_error(server, sock,
"No such nickname: Private message not sent");
- out:
- silc_buffer_free(buffer);
}
/* Process received channel message. The message can be originated from
SilcChannelClientEntry chl;
SilcChannelID *id = NULL;
void *sender = NULL;
- SilcBuffer buffer = packet->buffer;
SILC_LOG_DEBUG(("Processing channel message"));
silc_free(sender);
if (id)
silc_free(id);
- silc_buffer_free(buffer);
}
/* Received channel key packet. We distribute the key to all of our locally
SilcChannelID *id = NULL;
SilcChannelEntry channel;
SilcChannelClientEntry chl;
- SilcClientEntry client;
unsigned char *tmp;
unsigned int tmp_len;
char *cipher;
if (!silc_cipher_alloc(cipher, &channel->channel_key))
goto out;
- channel->key_len = tmp_len * 8;
- channel->key = silc_calloc(tmp_len, sizeof(unsigned char));
- memcpy(channel->key, tmp, tmp_len);
- channel->channel_key->cipher->set_key(channel->channel_key->context,
- tmp, tmp_len);
-
/* Distribute the key to all clients on the channel */
- /* XXX Some other sender should be used, I think this is not correct */
silc_list_start(channel->user_list);
while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
- client = chl->client;
-
- if (client)
- silc_server_packet_send_dest(server, client->connection,
- SILC_PACKET_CHANNEL_KEY, 0,
- client->id, SILC_ID_CLIENT,
- buffer->data, buffer->len, FALSE);
+ silc_server_packet_send(server, chl->client->connection,
+ SILC_PACKET_CHANNEL_KEY, 0,
+ buffer->data, buffer->len, TRUE);
}
+ channel->key_len = tmp_len * 8;
+ channel->key = silc_calloc(tmp_len, sizeof(unsigned char));
+ memcpy(channel->key, tmp, tmp_len);
+ channel->channel_key->cipher->set_key(channel->channel_key->context,
+ tmp, tmp_len);
out:
if (id)
silc_free(id);
if (payload)
silc_channel_key_payload_free(payload);
- silc_buffer_free(buffer);
}
/* Sends current motd to client */
if (!id2)
goto out;
+ /* If we are router and this packet is not already broadcast packet
+ we will broadcast it. The sending socket really cannot be router or
+ the router is buggy. If this packet is coming from router then it must
+ have the broadcast flag set already and we won't do anything. */
+ if (server->server_type == SILC_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_SERVER &&
+ !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+ SILC_LOG_DEBUG(("Broadcasting received Replace ID packet"));
+ silc_server_packet_send(server, server->router->connection, packet->type,
+ packet->flags | SILC_PACKET_FLAG_BROADCAST,
+ buffer->data, buffer->len, FALSE);
+ }
+
/* Replace the old ID */
switch(old_id_type) {
case SILC_ID_CLIENT:
/* Notify other routers about the new channel. We send the packet
to our primary route. */
if (server->standalone == FALSE) {
- silc_server_send_new_id(server, server->id_entry->router->connection,
+ silc_server_send_new_id(server, server->router->connection,
server->server_type == SILC_SERVER ? FALSE : TRUE,
entry->id, SILC_ID_CHANNEL, SILC_ID_CHANNEL_LEN);
}
/* Notify our router about new client on the SILC network */
if (!server->standalone)
silc_server_send_new_id(server, (SilcSocketConnection)
- server->id_entry->router->connection,
+ server->router->connection,
server->server_type == SILC_ROUTER ? TRUE : FALSE,
client->id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
to our router. If we are normal server we won't send anything
since this connection must be our router connection. */
if (server->server_type == SILC_ROUTER && !server->standalone &&
- server->id_entry->router->connection != sock)
- silc_server_send_new_id(server, server->id_entry->router->connection,
+ server->router->connection != sock)
+ silc_server_send_new_id(server, server->router->connection,
TRUE, new_server->id, SILC_ID_SERVER,
SILC_ID_SERVER_LEN);
/* If the sender of this packet is server and we are router we need to
broadcast this packet to other routers in the network. */
- if (!server->standalone && sock->type == SILC_SOCKET_TYPE_SERVER &&
- server->server_type == SILC_ROUTER) {
+ if (!server->standalone && server->server_type == SILC_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_SERVER &&
+ !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
SILC_LOG_DEBUG(("Broadcasting received New ID packet"));
- silc_server_packet_send(server, server->id_entry->router->connection,
+ silc_server_packet_send(server, server->router->connection,
packet->type,
packet->flags | SILC_PACKET_FLAG_BROADCAST,
buffer->data, buffer->len, FALSE);
/* router = server->id_entry; */
} else {
id_list = server->global_list;
- router_sock = (SilcSocketConnection)server->id_entry->router->connection;
- router = server->id_entry->router;
+ router_sock = (SilcSocketConnection)server->router->connection;
+ router = server->router;
}
silc_free(tmpid);
if (!client_id || !channel_id)
goto out;
+ /* If we are router and this packet is not already broadcast packet
+ we will broadcast it. The sending socket really cannot be router or
+ the router is buggy. If this packet is coming from router then it must
+ have the broadcast flag set already and we won't do anything. */
+ if (!server->standalone && server->server_type == SILC_ROUTER &&
+ sock->type == SILC_SOCKET_TYPE_SERVER &&
+ !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+ SILC_LOG_DEBUG(("Broadcasting received Remove Channel User packet"));
+ silc_server_packet_send(server, server->router->connection, packet->type,
+ packet->flags | SILC_PACKET_FLAG_BROADCAST,
+ buffer->data, buffer->len, FALSE);
+ }
+
/* XXX routers should check server->global_list as well */
/* Get channel entry */
channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);