+Thu Nov 9 21:12:39 EET 2000 Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ * Changed silc_command_pending list to SilcDList. Also, added
+ `ident' field to SilcServerCommandPending structure to identify
+ the reply and to call correct callback.
+
+ Added silc_server_command_pending_check function to replace the
+ corresnponding macro. The silc_command_pending list is not
+ extern anymore.
+
+ * Added silc_command_set_ident into lib/silccore/silccommand.[ch]
+ to set identifier to previously allocated Command Payload. It
+ is used to set identifier for command when resending Command
+ Payload.
+
+ * Added silc_command_payload_encode_payload to encode Command
+ Payload buffer from SilcCommandPayload structure.
+
+ * Added silc_argument_payload_encode_payload to encode Argument
+ payload buffer from SilcArgumentPayload structure.
+
+Wed Nov 8 21:03:28 EET 2000 Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ * Changed WHOIS command to support router connection on server side.
+ The whois request is always sent to router unless the server is
+ standalone server. After server has received the reply from the
+ router will it send the reply to the client.
+
+ * Added silc_server_packet_broadcast into silcd/server.[ch] to
+ broadcast received broadcast packet. The function is used only
+ by router. The broadcast packet is always sent to the router's
+ primary route.
+
+ * Added silc_id_render function in lib/silcutil/silcutil.[ch] to
+ render given ID to printable string, for log files for example.
+
Tue Nov 7 22:14:19 EET 2000 Pekka Riikonen <priikone@poseidon.pspt.fi>
* Made basic router to router connections working. At least they
};
/* List of pending commands. */
-SilcServerCommandPending *silc_command_pending = NULL;
+SilcDList silc_command_pending;
/* Returns TRUE if the connection is registered. Unregistered connections
usually cannot send commands hence the check. */
silc_buffer_free(packet->buffer);
}
-/* Add new pending command to the list of pending commands. Currently
- pending commands are executed from command replies, thus we can
- execute any command after receiving some specific command reply.
-
- The argument `reply_cmd' is the command reply from where the callback
- function is to be called, thus, it IS NOT the command to be executed. */
+/* Add new pending command to be executed when reply to a command has been
+ received. The `reply_cmd' is the command that will call the `callback'
+ with `context' when reply has been received. If `ident' is non-zero
+ the `callback' will be executed when received reply with command
+ identifier `ident'. */
void silc_server_command_pending(SilcCommand reply_cmd,
+ unsigned short ident,
SilcCommandCb callback,
void *context)
{
- SilcServerCommandPending *reply, *r;
+ SilcServerCommandPending *reply;
reply = silc_calloc(1, sizeof(*reply));
reply->reply_cmd = reply_cmd;
+ reply->ident = ident;
reply->context = context;
reply->callback = callback;
+ silc_dlist_add(silc_command_pending, reply);
+}
- if (silc_command_pending == NULL) {
- silc_command_pending = reply;
- return;
- }
+/* Deletes pending command by reply command type. */
- for (r = silc_command_pending; r; r = r->next) {
- if (r->next == NULL) {
- r->next = reply;
+void silc_server_command_pending_del(SilcCommand reply_cmd,
+ unsigned short ident)
+{
+ SilcServerCommandPending *r;
+
+ while ((r = silc_dlist_get(silc_command_pending)) != SILC_LIST_END) {
+ if (r->reply_cmd == reply_cmd && r->ident == ident) {
+ silc_dlist_del(silc_command_pending, r);
break;
}
}
}
-/* Deletes pending command by reply command type. */
+/* Checks for pending commands and marks callbacks to be called from
+ the command reply function. Returns TRUE if there were pending command. */
-void silc_server_command_pending_del(SilcCommand reply_cmd)
+int silc_server_command_pending_check(SilcServerCommandReplyContext ctx,
+ SilcCommand command,
+ unsigned short ident)
{
- SilcServerCommandPending *r, *tmp;
-
- if (silc_command_pending) {
- if (silc_command_pending->reply_cmd == reply_cmd) {
- silc_free(silc_command_pending);
- silc_command_pending = NULL;
- return;
- }
-
- for (r = silc_command_pending; r; r = r->next) {
- if (r->next && r->next->reply_cmd == reply_cmd) {
- tmp = r->next;
- r->next = r->next->next;
- silc_free(tmp);
- break;
- }
+ SilcServerCommandPending *r;
+
+ while ((r = silc_dlist_get(silc_command_pending)) != SILC_LIST_END) {
+ if (r->reply_cmd == command && r->ident == ident) {
+ ctx->context = r->context;
+ ctx->callback = r->callback;
+ ctx->ident = ident;
+ return TRUE;
}
}
+
+ return FALSE;
}
/* Free's the command context allocated before executing the command */
count = atoi(tmp);
}
- /* Get all clients matching that nickname */
- if (!use_id) {
- clients = silc_idlist_get_clients_by_nickname(server->local_list,
- nick, server_name,
- &clients_count);
- } else {
- entry = silc_idlist_find_client_by_id(server->local_list, client_id);
- if (entry) {
- clients = silc_calloc(1, sizeof(*clients));
- clients[0] = entry;
- clients_count = 1;
- }
- }
+ /* Protocol dictates that we must always send the received WHOIS request
+ to our router if we are normal server, so let's do it now unless we
+ are standalone. We will not send any replies to the client until we
+ have received reply from the router. */
+ if (!server->standalone) {
+ SilcBuffer tmpbuf;
- if (!clients) {
-
- /* If we are normal server and are connected to a router we will
- make global query from the router. */
- if (server->server_type == SILC_SERVER && !server->standalone) {
+ silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
+ tmpbuf = silc_command_payload_encode_payload(cmd->payload);
- goto ok;
+ /* Send WHOIS command to our router */
+ silc_server_packet_send(server, (SilcSocketConnection)
+ server->id_entry->router->connection,
+ SILC_PACKET_COMMAND, cmd->packet->flags,
+ tmpbuf->data, tmpbuf->len, TRUE);
+ return;
+ } else {
+ /* We are standalone, let's just do local search and send reply to
+ requesting client. */
+
+ /* Get all clients matching that nickname */
+ if (!use_id) {
+ clients = silc_idlist_get_clients_by_nickname(server->local_list,
+ nick, server_name,
+ &clients_count);
+ } else {
+ entry = silc_idlist_find_client_by_id(server->local_list, client_id);
+ if (entry) {
+ clients = silc_calloc(1, sizeof(*clients));
+ clients[0] = entry;
+ clients_count = 1;
+ }
}
/* If we are router then we will check our global list as well. */
}
goto ok;
}
-
+
+#if 0
silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
SILC_STATUS_ERR_NO_SUCH_NICK,
3, tmp, strlen(tmp));
goto out;
+#endif
}
+ /* We are standalone and will send reply to client */
ok:
-
- /* XXX, works only for local server info */
-
+
status = SILC_STATUS_OK;
if (clients_count > 1)
status = SILC_STATUS_LIST_START;
/* Add the command to be pending. It will be re-executed after
router has replied back to us. */
cmd->pending = TRUE;
- silc_server_command_pending(SILC_COMMAND_JOIN,
+ silc_server_command_pending(SILC_COMMAND_JOIN, 0,
silc_server_command_join, context);
return;
}
/* XXX Send names command */
cmd->pending = TRUE;
- silc_server_command_pending(SILC_COMMAND_NAMES,
+ silc_server_command_pending(SILC_COMMAND_NAMES, 0,
silc_server_command_names, context);
return;
}
#ifndef COMMAND_H
#define COMMAND_H
+#include "command_reply.h"
+
/*
Structure holding one command and pointer to its function.
} *SilcServerCommandContext;
/* Structure holding pending commands. If command is pending it will be
- executed after command reply has been received and executed.
- Pending commands are used in cases where the original command request
- had to be forwarded to router. After router replies the pending
- command is re-executed. */
+ executed after command reply has been received and executed. */
typedef struct SilcServerCommandPendingStruct {
SilcCommand reply_cmd;
- void *context;
SilcCommandCb callback;
-
+ void *context;
+ unsigned short ident;
struct SilcServerCommandPendingStruct *next;
} SilcServerCommandPending;
-/* List of pending commands */
-extern SilcServerCommandPending *silc_command_pending;
-
/* Macros */
/* Macro used for command declaration in command list structure */
#define SILC_SERVER_CMD_FUNC(func) \
void silc_server_command_##func(void *context)
-/* Checks for pending commands */
-#define SILC_SERVER_COMMAND_CHECK_PENDING(ctx) \
-do { \
- if (silc_command_pending) { \
- SilcServerCommandPending *r; \
- SilcCommand cmd; \
- \
- cmd = silc_command_get(payload); \
- for (r = silc_command_pending; r; r = r->next) { \
- if (r->reply_cmd == cmd) { \
- ctx->context = r->context; \
- ctx->callback = r->callback; \
- break; \
- } \
- } \
- } \
-} while(0)
-
/* Executed pending command */
#define SILC_SERVER_COMMAND_EXEC_PENDING(ctx, cmd) \
do { \
if (ctx->callback) { \
(*ctx->callback)(ctx->context); \
- silc_server_command_pending_del(cmd); \
+ silc_server_command_pending_del(cmd, ctx->ident); \
} \
} while(0)
SilcSocketConnection sock,
SilcPacketContext *packet);
void silc_server_command_pending(SilcCommand reply_cmd,
+ unsigned short ident,
SilcCommandCb callback,
void *context);
-void silc_server_command_pending_del(SilcCommand reply_cmd);
+void silc_server_command_pending_del(SilcCommand reply_cmd,
+ unsigned short ident);
+int silc_server_command_pending_check(SilcServerCommandReplyContext ctx,
+ SilcCommand command,
+ unsigned short ident);
SILC_SERVER_CMD_FUNC(whois);
SILC_SERVER_CMD_FUNC(whowas);
SILC_SERVER_CMD_FUNC(identify);
#include "server_internal.h"
#include "command_reply.h"
+#define COMMAND_CHECK_STATUS \
+do { \
+ SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); \
+ if (status != SILC_STATUS_OK) { \
+ silc_server_command_reply_free(cmd); \
+ return; \
+ } \
+} while(0)
+
+#define COMMAND_CHECK_STATUS_LIST \
+do { \
+ SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL)); \
+ if (status != SILC_STATUS_OK && \
+ status != SILC_STATUS_LIST_START && \
+ status != SILC_STATUS_LIST_ITEM && \
+ status != SILC_STATUS_LIST_END) { \
+ silc_server_command_reply_free(cmd); \
+ return; \
+ } \
+} while(0)
+
/* Server command reply list. Not all commands have reply function as
they are never sent by server. More maybe added later if need appears. */
SilcServerCommandReply silc_command_reply_list[] =
{
SILC_SERVER_CMD_REPLY(join, JOIN),
+ SILC_SERVER_CMD_REPLY(identify, WHOIS),
SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
{ NULL, 0 },
SilcSocketConnection sock,
SilcBuffer buffer)
{
+ SilcServerCommandReply *cmd;
SilcServerCommandReplyContext ctx;
SilcCommandPayload payload;
+ SilcCommand command;
+ unsigned short ident;
/* Get command reply payload from packet */
payload = silc_command_payload_parse(buffer);
ctx->sock = sock;
ctx->payload = payload;
ctx->args = silc_command_get_args(ctx->payload);
+ ident = silc_command_get_ident(ctx->payload);
/* Check for pending commands and mark to be exeucted */
- SILC_SERVER_COMMAND_CHECK_PENDING(ctx);
-
+ silc_server_command_pending_check(ctx, silc_command_get(ctx->payload),
+ ident);
+
/* Execute command reply */
- SILC_SERVER_COMMAND_REPLY_EXEC(ctx);
+ command = silc_command_get(ctx->payload);
+ for (cmd = silc_command_reply_list; cmd->cb; cmd++)
+ if (cmd->cmd == command)
+ break;
+
+ if (cmd == NULL) {
+ silc_free(ctx);
+ return;
+ }
+
+ cmd->cb(ctx);
}
/* Free command reply context and its internals. */
}
}
-/* Received reply for forwarded JOIN command. Router has created or joined
- the client to the channel. We save some channel information locally
- for future use. */
+/* Caches the received WHOIS information. If we are normal server currently
+ we cache global information only for short period of time. If we are
+ router we want to cache them a bit longer since we can receive information
+ if any of the information becomes invalid. Normal server cannot receive
+ that information. Returns FALSE if something was wrong with the reply. */
-SILC_SERVER_CMD_REPLY_FUNC(join)
+static char
+silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
+{
+ int len, id_len;
+ unsigned char *id_data;
+ char *nickname, *username, *realname;
+ SilcClientID *client_id;
+
+ id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
+ nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
+ username = silc_argument_get_arg_type(cmd->args, 4, &len);
+ realname = silc_argument_get_arg_type(cmd->args, 5, &len);
+ if (!id_data || !nickname || !username || !realname)
+ return FALSE;
+
+ client_id = silc_id_payload_parse_id(id_data, id_len);
+
+
+ return TRUE;
+}
+
+/* Reiceved reply for WHOIS command. We sent the whois request to our
+ primary router, if we are normal server, and thus has now received reply
+ to the command. We will figure out what client originally sent us the
+ command and will send the reply to it. If we are router we will figure
+ out who server sent us the command and send reply to that one. */
+
+SILC_SERVER_CMD_REPLY_FUNC(whois)
{
SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
SilcServer server = cmd->server;
SilcCommandStatus status;
- SilcChannelID *id;
- SilcChannelEntry entry;
- unsigned int len;
- unsigned char *id_string;
- char *channel_name, *tmp;
SILC_LOG_DEBUG(("Start"));
- tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
- SILC_GET16_MSB(status, tmp);
- if (status != SILC_STATUS_OK)
- goto out;
+ COMMAND_CHECK_STATUS_LIST;
- /* Get channel name */
- tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
- if (!tmp)
- goto out;
+ /* Process one identify reply */
+ if (status == SILC_STATUS_OK) {
- /* Get channel ID */
- id_string = silc_argument_get_arg_type(cmd->args, 3, &len);
- if (!id_string)
- goto out;
+ }
- channel_name = strdup(tmp);
+ if (status == SILC_STATUS_LIST_START) {
- /* Add the channel to our local list. */
- id = silc_id_payload_parse_id(id_string, len);
- entry = silc_idlist_add_channel(server->local_list, channel_name,
- SILC_CHANNEL_MODE_NONE, id,
- server->id_entry->router, NULL);
- if (!entry) {
- silc_free(channel_name);
- silc_free(id);
- goto out;
}
- entry->global_users = TRUE;
+ if (status == SILC_STATUS_LIST_ITEM) {
- /* Execute pending JOIN command so that the client who originally
- wanted to join the channel will be joined after all. */
- SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_JOIN);
+ }
+
+ if (status == SILC_STATUS_LIST_END) {
+
+ }
+
+ /* Execute pending IDENTIFY command so that the client who originally
+ requested the identify information will get it after all. */
+ SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_IDENTIFY);
out:
silc_server_command_reply_free(cmd);
SILC_LOG_DEBUG(("Start"));
- SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL));
- if (status != SILC_STATUS_OK)
- goto out;
+ COMMAND_CHECK_STATUS_LIST;
/* Process one identify reply */
if (status == SILC_STATUS_OK) {
}
+ if (status == SILC_STATUS_LIST_ITEM) {
+
+ }
+
if (status == SILC_STATUS_LIST_END) {
}
out:
silc_server_command_reply_free(cmd);
}
+
+/* Received reply for forwarded JOIN command. Router has created or joined
+ the client to the channel. We save some channel information locally
+ for future use. */
+
+SILC_SERVER_CMD_REPLY_FUNC(join)
+{
+ SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
+ SilcServer server = cmd->server;
+ SilcCommandStatus status;
+ SilcChannelID *id;
+ SilcChannelEntry entry;
+ unsigned int len;
+ unsigned char *id_string;
+ char *channel_name, *tmp;
+
+ SILC_LOG_DEBUG(("Start"));
+
+ COMMAND_CHECK_STATUS;
+
+ /* Get channel name */
+ tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
+ if (!tmp)
+ goto out;
+
+ /* Get channel ID */
+ id_string = silc_argument_get_arg_type(cmd->args, 3, &len);
+ if (!id_string)
+ goto out;
+
+ channel_name = strdup(tmp);
+
+ /* Add the channel to our local list. */
+ id = silc_id_payload_parse_id(id_string, len);
+ entry = silc_idlist_add_channel(server->local_list, channel_name,
+ SILC_CHANNEL_MODE_NONE, id,
+ server->id_entry->router, NULL);
+ if (!entry) {
+ silc_free(channel_name);
+ silc_free(id);
+ goto out;
+ }
+
+ entry->global_users = TRUE;
+
+ /* Execute pending JOIN command so that the client who originally
+ wanted to join the channel will be joined after all. */
+ SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_JOIN);
+
+ out:
+ silc_server_command_reply_free(cmd);
+}
/* If defined this executes the pending command. */
void *context;
SilcCommandCb callback;
+ unsigned short ident;
} *SilcServerCommandReplyContext;
/* Macros */
#define SILC_SERVER_CMD_REPLY_FUNC(func) \
void silc_server_command_reply_##func(void *context)
-/* Macro used to execute command replies */
-#define SILC_SERVER_COMMAND_REPLY_EXEC(ctx) \
-do { \
- SilcServerCommandReply *cmd; \
- \
- for (cmd = silc_command_reply_list; cmd->cb; cmd++) \
- if (cmd->cmd == silc_command_get(ctx->payload)) { \
- cmd->cb(ctx); \
- break; \
- } \
- \
- if (cmd == NULL) { \
- silc_free(ctx); \
- return; \
- } \
-} while(0)
-
/* Prototypes */
void silc_server_command_reply_process(SilcServer server,
SilcSocketConnection sock,
SilcBuffer buffer);
SILC_SERVER_CMD_REPLY_FUNC(join);
+SILC_SERVER_CMD_REPLY_FUNC(whois);
SILC_SERVER_CMD_REPLY_FUNC(identify);
#endif
SilcPKCS pkcs;
SilcPublicKey public_key;
- /* Time when last received or sent data */
- long last_receive;
- long last_sent;
-
- /* Boolean value whether connection is registered */
- int registered;
+ unsigned short cmd_ident; /* Current command identifier, 0 not used */
+ long last_receive; /* Time last received data */
+ long last_sent; /* Time last sent data */
+ unsigned char registered; /* Boolean whether connection is registered */
} *SilcIDListData, SilcIDListDataStruct;
/*
if (ret == SILC_PACKET_NONE)
goto out;
-
+
+ /* Broadcast packet if it is marked as broadcast packet and it is
+ originated from router and we are router. */
+ 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);
+ }
+
/* Parse the incoming packet type */
silc_server_packet_parse_type(server, sock, packet);
}
/* Parser callback called by silc_packet_receive_process. This merely
- registers timeout that will handle the actual parsing whem appropriate. */
+ registers timeout that will handle the actual parsing when appropriate. */
void silc_server_packet_parse(SilcPacketParserContext *parser_context)
{
silc_server_packet_send_real(server, sock, force_send);
}
+/* 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. */
+
+void silc_server_packet_broadcast(SilcServer server,
+ SilcSocketConnection sock,
+ SilcPacketContext *packet)
+{
+ SilcBuffer buffer = packet->buffer;
+ SilcIDListData idata;
+ void *id;
+
+ SILC_LOG_DEBUG(("Broadcasting received broadcast packet"));
+
+ /* 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)) {
+ idata = (SilcIDListData)sock->user_data;
+ 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);
+
+ SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", sock->outbuf->len),
+ sock->outbuf->data, sock->outbuf->len);
+
+ /* Now actually send the packet */
+ silc_server_packet_send_real(server, sock, TRUE);
+ silc_free(id);
+ return;
+ }
+
+ SILC_LOG_DEBUG(("Will not broadcast to primary route since it is the "
+ "original sender of this packet"));
+ silc_free(id);
+}
+
/* Internal routine to actually create the channel packet and send it
to network. This is common function in channel message sending. If
`channel_message' is TRUE this encrypts the message as it is strictly
SILC_LOG_DEBUG(("Creating new channel"));
/* Create channel key */
- for (i = 0; i < 32; i++)
- channel_key[i] = silc_rng_get_byte(server->rng);
+ for (i = 0; i < 32; i++) channel_key[i] = silc_rng_get_byte(server->rng);
if (!cipher)
cipher = "twofish";
if (!server->standalone)
silc_server_send_new_id(server, (SilcSocketConnection)
server->id_entry->router->connection,
- server->server_type == SILC_SERVER ? TRUE : FALSE,
+ server->server_type == SILC_ROUTER ? TRUE : FALSE,
client->id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
/* Send the new client ID to the client. */
if (!id)
goto out;
+ /* 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) {
+ SILC_LOG_DEBUG(("Broadcasting received New ID packet"));
+ silc_server_packet_send(server, server->id_entry->router->connection,
+ packet->type,
+ packet->flags | SILC_PACKET_FLAG_BROADCAST,
+ buffer->data, buffer->len, FALSE);
+ }
+
/* If the packet is originated from the one who sent it to us we know
that the ID belongs to our cell, unless the sender was router. */
tmpid = silc_id_str2id(packet->src_id, SILC_ID_SERVER);
{
SilcClientEntry idlist;
+ SILC_LOG_DEBUG(("New client id(%s) from [%s] %s",
+ silc_id_render(id, SILC_ID_CLIENT),
+ sock->type == SILC_SOCKET_TYPE_SERVER ?
+ "Server" : "Router", sock->hostname));
+
/* Add the client to our local list. We are router and we keep
cell specific local database of all clients in the cell. */
idlist = silc_idlist_add_client(id_list, NULL, NULL, NULL,
{
SilcServerEntry idlist;
+ SILC_LOG_DEBUG(("New server id(%s) from [%s] %s",
+ silc_id_render(id, SILC_ID_SERVER),
+ sock->type == SILC_SOCKET_TYPE_SERVER ?
+ "Server" : "Router", sock->hostname));
+
/* Add the server to our local list. We are router and we keep
cell specific local database of all servers in the cell. */
idlist = silc_idlist_add_server(id_list, NULL, 0, id, router,
break;
case SILC_ID_CHANNEL:
+ SILC_LOG_DEBUG(("New channel id(%s) from [%s] %s",
+ silc_id_render(id, SILC_ID_CHANNEL),
+ sock->type == SILC_SOCKET_TYPE_SERVER ?
+ "Server" : "Router", sock->hostname));
+
/* Add the channel to our local list. We are router and we keep
cell specific local database of all channels in the cell. */
silc_idlist_add_channel(id_list, NULL, 0, id, router, NULL);
SilcSocketConnection sock,
unsigned char *data, unsigned int data_len,
int force_send);
+void silc_server_packet_broadcast(SilcServer server,
+ SilcSocketConnection sock,
+ SilcPacketContext *packet);
void silc_server_packet_send_to_channel(SilcServer server,
SilcChannelEntry channel,
SilcPacketType type,
10.2.1.6:passwd:priikone:1335:1:1
[RouterConnection]
-10.2.1.6:passwd:priikone:1333:1:1:0
+10.2.1.6:passwd:priikone:1335:1:1:0
[DenyConnection]
[RedirectClient]
can identify which command reply belongs to which originally
sent command. What this field includes is implementation
issue but it is recommended that wrapping counter value is
- used in the field.
+ used in the field. Value zero (0) in this field means that
+ no specific value is set.
.in 3
See [SILC1] for detailed description of different SILC commands,
the client simply sends the command packet to server and the server
processes it and replies with command reply packet.
-However, if the server is not able to process the command, it is usually
-sent to the server's router. This is case for example with commands such
+However, if the server is not able to process the command, it is sent
+to the server's router. This is case for example with commands such
as, SILC_COMMAND_JOIN and SILC_COMMAND_WHOIS commands. However, there
are other commands as well. For example, if client sends the WHOIS
command requesting specific information about some client the server must
send the WHOIS command to router so that all clients in SILC network
are searched. The router, on the other hand, sends the WHOIS command
-to further to receive the exact information about the requested client.
+further to receive the exact information about the requested client.
The WHOIS command travels all the way to the server who owns the client
and it replies with command reply packet. Finally, the server who
sent the command receives the command reply and it must be able to
It is also possible to search the user by Client ID. If <Client ID>
is provided server must use it as the search value instead of
- the <nickname>.
+ the <nickname>. One of the arguments must be given.
To prevent miss-use of this service wildcards in the nickname
or in the servername are not permitted. It is not allowed
The WHOIS request must be always forwarded to router by server
so that all users are searched. However, the server still must
- search its locally connected clients. The server must send
+ search its locally connected clients. The router must send
this command to the server who owns the requested client. That
- server must reply to the command.
+ server must reply to the command. Server should not send whois
+ replies to the client until it has received the reply from its
+ router.
Reply messages to the command:
# this sections includes all configured router connections. The first
# configured connection is the primary route.
#
-# Format: <remote host>:<auth method>:<auth data>:<port>:<version ID>:<class>
+# Format: <remote host>:<auth method>:<auth data>:<port>:<version ID>:<class>:<initiator>
#
[RouterConnection]
-#10.2.1.100:passwd:veryverysecret:706:1:1
+#10.2.1.100:passwd:veryverysecret:706:1:1:1
#
# Denied connections.
/* Generate IV */
if (!channel->iv)
- for (i = 0; i < 16; i++)
- channel->iv[i] = silc_rng_get_byte(client->rng);
+ for (i = 0; i < 16; i++) channel->iv[i] = silc_rng_get_byte(client->rng);
else
silc_hash_make(client->md5hash, channel->iv, 16, channel->iv);
return strdup(buf);
}
+
+/* Renders ID to suitable to print for example to log file. */
+
+char *silc_id_render(void *id, unsigned short type)
+{
+ char rid[256], tmp[100];
+ unsigned char tmps[2];
+
+ memset(rid, 0, sizeof(rid));
+ switch(type) {
+ case SILC_ID_SERVER:
+ {
+ SilcServerID *server_id = (SilcServerID *)id;
+ strcat(rid, inet_ntoa(server_id->ip));
+ memset(tmp, 0, sizeof(tmp));
+ snprintf(tmp, sizeof(tmp), ",%d,", ntohs(server_id->port));
+ strcat(rid, tmp);
+ SILC_PUT16_MSB(server_id->rnd, tmps);
+ memset(tmp, 0, sizeof(tmp));
+ snprintf(tmp, sizeof(tmp), "[%02x %02x]", tmps[0], tmps[1]);
+ strcat(rid, tmp);
+ }
+ break;
+ case SILC_ID_CLIENT:
+ {
+ SilcClientID *client_id = (SilcClientID *)id;
+ strcat(rid, inet_ntoa(client_id->ip));
+ memset(tmp, 0, sizeof(tmp));
+ snprintf(tmp, sizeof(tmp), ",%02x,", client_id->rnd);
+ strcat(rid, tmp);
+ memset(tmp, 0, sizeof(tmp));
+ snprintf(tmp, sizeof(tmp), "[%02x %02x %02x %02x...]",
+ client_id->hash[0], client_id->hash[1],
+ client_id->hash[2], client_id->hash[3]);
+ strcat(rid, tmp);
+ }
+ break;
+ case SILC_ID_CHANNEL:
+ {
+ SilcChannelID *channel_id = (SilcChannelID *)id;
+ strcat(rid, inet_ntoa(channel_id->ip));
+ memset(tmp, 0, sizeof(tmp));
+ snprintf(tmp, sizeof(tmp), ",%d,", ntohs(channel_id->port));
+ strcat(rid, tmp);
+ SILC_PUT16_MSB(channel_id->rnd, tmps);
+ memset(tmp, 0, sizeof(tmp));
+ snprintf(tmp, sizeof(tmp), "[%02x %02x]", tmps[0], tmps[1]);
+ strcat(rid, tmp);
+ }
+ break;
+ }
+
+ return strdup(rid);
+}
unsigned int *parsed_num,
unsigned int max_args);
char *silc_format(char *fmt, ...);
+char *silc_id_render(void *id, unsigned short type);
#endif