From: Pekka Riikonen Date: Sun, 19 Nov 2000 12:00:46 +0000 (+0000) Subject: updates X-Git-Tag: 1.2.beta1~2654 X-Git-Url: http://git.silcnet.org/gitweb/?p=crypto.git;a=commitdiff_plain;h=ca321a7eee00d2507f83e068461076a6f9f1eb86 updates --- diff --git a/CHANGES b/CHANGES index 825e2f44..9b005e69 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,39 @@ +Thu Nov 9 21:12:39 EET 2000 Pekka Riikonen + + * 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 + + * 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 * Made basic router to router connections working. At least they diff --git a/apps/silcd/command.c b/apps/silcd/command.c index 4c4c67be..d937dd36 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -76,7 +76,7 @@ SilcServerCommand silc_command_list[] = }; /* 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. */ @@ -170,59 +170,61 @@ void silc_server_command_process(SilcServer server, 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 */ @@ -347,27 +349,38 @@ SILC_SERVER_CMD_FUNC(whois) 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. */ @@ -383,17 +396,18 @@ SILC_SERVER_CMD_FUNC(whois) } 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; @@ -1286,7 +1300,7 @@ SILC_SERVER_CMD_FUNC(join) /* 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; } @@ -2360,7 +2374,7 @@ SILC_SERVER_CMD_FUNC(names) /* 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; } diff --git a/apps/silcd/command.h b/apps/silcd/command.h index 1ced0891..21677e8f 100644 --- a/apps/silcd/command.h +++ b/apps/silcd/command.h @@ -21,6 +21,8 @@ #ifndef COMMAND_H #define COMMAND_H +#include "command_reply.h" + /* Structure holding one command and pointer to its function. @@ -58,21 +60,15 @@ typedef struct { } *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 */ @@ -83,30 +79,12 @@ extern SilcServerCommandPending *silc_command_pending; #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) @@ -115,9 +93,14 @@ void silc_server_command_process(SilcServer server, 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); diff --git a/apps/silcd/command_reply.c b/apps/silcd/command_reply.c index 48e906cd..853a52ff 100644 --- a/apps/silcd/command_reply.c +++ b/apps/silcd/command_reply.c @@ -23,11 +23,33 @@ #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 }, @@ -39,8 +61,11 @@ void silc_server_command_reply_process(SilcServer server, 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); @@ -57,12 +82,24 @@ void silc_server_command_reply_process(SilcServer server, 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. */ @@ -75,56 +112,69 @@ void silc_server_command_reply_free(SilcServerCommandReplyContext 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. */ +/* 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); @@ -143,9 +193,7 @@ SILC_SERVER_CMD_REPLY_FUNC(identify) 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) { @@ -173,6 +221,10 @@ SILC_SERVER_CMD_REPLY_FUNC(identify) } + if (status == SILC_STATUS_LIST_ITEM) { + + } + if (status == SILC_STATUS_LIST_END) { } @@ -184,3 +236,55 @@ SILC_SERVER_CMD_REPLY_FUNC(identify) 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); +} diff --git a/apps/silcd/command_reply.h b/apps/silcd/command_reply.h index c8faa73c..9b5479e1 100644 --- a/apps/silcd/command_reply.h +++ b/apps/silcd/command_reply.h @@ -40,6 +40,7 @@ typedef struct { /* If defined this executes the pending command. */ void *context; SilcCommandCb callback; + unsigned short ident; } *SilcServerCommandReplyContext; /* Macros */ @@ -52,28 +53,12 @@ typedef struct { #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 diff --git a/apps/silcd/idlist.h b/apps/silcd/idlist.h index 47448b95..9ac13a59 100644 --- a/apps/silcd/idlist.h +++ b/apps/silcd/idlist.h @@ -53,12 +53,10 @@ typedef struct { 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; /* diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 249991f9..6f1204a2 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -1185,7 +1185,16 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real) 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); @@ -1200,7 +1209,7 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real) } /* 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) { @@ -1688,6 +1697,46 @@ void silc_server_packet_forward(SilcServer server, 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 @@ -3060,8 +3109,7 @@ SilcChannelEntry silc_server_new_channel(SilcServer server, 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"; @@ -3175,7 +3223,7 @@ SilcClientEntry silc_server_new_client(SilcServer server, 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. */ @@ -3327,6 +3375,17 @@ void silc_server_new_id(SilcServer server, SilcSocketConnection sock, 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); @@ -3351,6 +3410,11 @@ void silc_server_new_id(SilcServer server, SilcSocketConnection sock, { 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, @@ -3362,6 +3426,11 @@ void silc_server_new_id(SilcServer server, SilcSocketConnection sock, { 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, @@ -3370,6 +3439,11 @@ void silc_server_new_id(SilcServer server, SilcSocketConnection sock, 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); diff --git a/apps/silcd/server.h b/apps/silcd/server.h index edad5b47..f6dd8e39 100644 --- a/apps/silcd/server.h +++ b/apps/silcd/server.h @@ -103,6 +103,9 @@ void silc_server_packet_forward(SilcServer server, 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, diff --git a/apps/silcd/testi2.conf b/apps/silcd/testi2.conf index 08d85fae..a4719076 100644 --- a/apps/silcd/testi2.conf +++ b/apps/silcd/testi2.conf @@ -44,7 +44,7 @@ errorlogfile:silcd2.log:10000 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] diff --git a/doc/draft-riikonen-silc-pp-01.nroff b/doc/draft-riikonen-silc-pp-01.nroff index 2ca38888..bc7e8a51 100644 --- a/doc/draft-riikonen-silc-pp-01.nroff +++ b/doc/draft-riikonen-silc-pp-01.nroff @@ -1585,7 +1585,8 @@ o Command Unifier (2 bytes) - Unifies this command at the 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, diff --git a/doc/draft-riikonen-silc-spec-01.nroff b/doc/draft-riikonen-silc-spec-01.nroff index 5410afdb..9e6e731c 100644 --- a/doc/draft-riikonen-silc-spec-01.nroff +++ b/doc/draft-riikonen-silc-spec-01.nroff @@ -1580,14 +1580,14 @@ Client usually sends the commands in the SILC network. In this case 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 @@ -1736,7 +1736,7 @@ List of all defined commands in SILC follows. It is also possible to search the user by Client ID. If is provided server must use it as the search value instead of - the . + the . 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 @@ -1745,9 +1745,11 @@ List of all defined commands in SILC follows. 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: diff --git a/doc/example_silcd.conf b/doc/example_silcd.conf index 18499cc4..b08f0563 100644 --- a/doc/example_silcd.conf +++ b/doc/example_silcd.conf @@ -125,10 +125,10 @@ infologfile:silcd.log:10000 # this sections includes all configured router connections. The first # configured connection is the primary route. # -# Format: ::::: +# Format: :::::: # [RouterConnection] -#10.2.1.100:passwd:veryverysecret:706:1:1 +#10.2.1.100:passwd:veryverysecret:706:1:1:1 # # Denied connections. diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index 4ba45528..92fac57b 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -968,8 +968,7 @@ void silc_client_packet_send_to_channel(SilcClient client, /* 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); diff --git a/lib/silcutil/silcutil.c b/lib/silcutil/silcutil.c index 81b5afe2..74f040e5 100644 --- a/lib/silcutil/silcutil.c +++ b/lib/silcutil/silcutil.c @@ -544,3 +544,57 @@ char *silc_format(char *fmt, ...) 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); +} diff --git a/lib/silcutil/silcutil.h b/lib/silcutil/silcutil.h index 1c6f764e..546b1a8b 100644 --- a/lib/silcutil/silcutil.h +++ b/lib/silcutil/silcutil.h @@ -44,5 +44,6 @@ void silc_parse_command_line(unsigned char *buffer, unsigned int *parsed_num, unsigned int max_args); char *silc_format(char *fmt, ...); +char *silc_id_render(void *id, unsigned short type); #endif