updates
authorPekka Riikonen <priikone@silcnet.org>
Sun, 19 Nov 2000 12:00:46 +0000 (12:00 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 19 Nov 2000 12:00:46 +0000 (12:00 +0000)
15 files changed:
CHANGES
apps/silcd/command.c
apps/silcd/command.h
apps/silcd/command_reply.c
apps/silcd/command_reply.h
apps/silcd/idlist.h
apps/silcd/server.c
apps/silcd/server.h
apps/silcd/testi2.conf
doc/draft-riikonen-silc-pp-01.nroff
doc/draft-riikonen-silc-spec-01.nroff
doc/example_silcd.conf
lib/silcclient/client.c
lib/silcutil/silcutil.c
lib/silcutil/silcutil.h

diff --git a/CHANGES b/CHANGES
index 825e2f44c86380e478a6e43f37d1924d669303b6..9b005e6958317a04d6f203d236008273a20e62fa 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,39 @@
+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
index 4c4c67be5329a9f6663c49577bc27dfaf15315b8..d937dd36822c3aad7c0f0b83777d910d26163038 100644 (file)
@@ -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;
     }
index 1ced0891082df4ea576fa14e50edf7a0a3154f43..21677e8f287ee70126694eea0842a44d186efbef 100644 (file)
@@ -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);
index 48e906cdeb2a6a1843646065104a96d974e86416..853a52ff79dd3c372d188be634ac140c3a30b280 100644 (file)
 #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);
+}
index c8faa73c7648d883dc83ccd3ae8169f069932b46..9b5479e115571172d564be928dfbdabb0a8d55dd 100644 (file)
@@ -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
index 47448b95465c78db971c3bc132743c4523bb9b57..9ac13a59ee7a8d0d3465091bb66edc56393dd739 100644 (file)
@@ -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;
 
 /* 
index 249991f9438973d82863dc311833d009770ae9f6..6f1204a2d92ae92a3e5a1f1f4f3521d4f295fd9f 100644 (file)
@@ -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);
index edad5b4752671152a7dff0cd0a0d170a05290ceb..f6dd8e398f0bf0a89a727a10c7170421f860f4b9 100644 (file)
@@ -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,
index 08d85faefb2daf3cea152f65d0233af6d8076bf2..a4719076f28242534fce4fba9de5fb322593c97e 100644 (file)
@@ -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]
index 2ca388886efa9aa33b6012320fda266f6be9f8b2..bc7e8a515e3d93f5910b88116f8dd21b5737b878 100644 (file)
@@ -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,
index 5410afdbb9b5990bb98ea102b7f1e6bfedeaa173..9e6e731cde3c7fd50f6ffb64043387c30d242115 100644 (file)
@@ -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 <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
@@ -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:
 
index 18499cc4319bcd0a49e65bfdef4fd49f62e93143..b08f05636003a63d3f7d9885ff70896878fe645c 100644 (file)
@@ -125,10 +125,10 @@ infologfile:silcd.log:10000
 # 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.
index 4ba45528d9ecf1980317823d3c1fa7d3d794f3a6..92fac57bc5e0d83bbb78cfefe473bbf9429fb942 100644 (file)
@@ -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);
 
index 81b5afe2e41fc76345850024037b214f8a7e1a4c..74f040e5de3ba8ed9212ef8b0fa5c5a62d698045 100644 (file)
@@ -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);
+}
index 1c6f764e1f4df3ccb595d6ccc8e9a3b24d6be295..546b1a8bab65adb82646a80b8b7428a9acaed4c2 100644 (file)
@@ -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