Removed command packet processing from server.c and added it to
authorPekka Riikonen <priikone@silcnet.org>
Mon, 10 Jul 2000 05:42:59 +0000 (05:42 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 10 Jul 2000 05:42:59 +0000 (05:42 +0000)
command.c.
Implemented INFO command. Added support for testing that
connections are registered before executing commands.

apps/silcd/command.c
apps/silcd/command.h
apps/silcd/idlist.h
apps/silcd/server.c

index c3c58c3bf3981007b1ae20c9a31867650218ede0..d5661fe24ccdb9ce4cb19b42ec7d7b10afd198e8 100644 (file)
 /*
  * $Id$
  * $Log$
+ * Revision 1.8  2000/07/10 05:42:59  priikone
+ *     Removed command packet processing from server.c and added it to
+ *     command.c.
+ *     Implemented INFO command. Added support for testing that
+ *     connections are registered before executing commands.
+ *
  * Revision 1.7  2000/07/07 06:55:24  priikone
  *     Do not allow client to join twice on same channel.
  *
 #include "serverincludes.h"
 #include "server_internal.h"
 
+static int silc_server_is_registered(SilcServer server,
+                                    SilcSocketConnection sock,
+                                    SilcServerCommandContext cmd,
+                                    SilcCommand command);
+static void 
+silc_server_command_send_status_reply(SilcServerCommandContext cmd,
+                                     SilcCommand command,
+                                     SilcCommandStatus status);
+static void 
+silc_server_command_send_status_data(SilcServerCommandContext cmd,
+                                    SilcCommand command,
+                                    SilcCommandStatus status,
+                                    unsigned int arg_type,
+                                    unsigned char *arg,
+                                    unsigned int arg_len);
+static void silc_server_command_free(SilcServerCommandContext cmd);
+
 /* Server command list. */
 SilcServerCommand silc_command_list[] =
 {
@@ -86,6 +109,89 @@ SilcServerCommand silc_command_list[] =
 /* List of pending commands. */
 SilcServerCommandPending *silc_command_pending = NULL;
 
+/* Returns TRUE if the connection is registered. Unregistered connections
+   usually cannot send commands hence the check. */
+
+static int silc_server_is_registered(SilcServer server,
+                                    SilcSocketConnection sock,
+                                    SilcServerCommandContext cmd,
+                                    SilcCommand command)
+{
+  switch(sock->type) {
+  case SILC_SOCKET_TYPE_CLIENT:
+    {
+      SilcClientList *client = (SilcClientList *)sock->user_data;
+      if (client->registered)
+       return TRUE;
+      break;
+    }
+  case SILC_SOCKET_TYPE_SERVER:
+  case SILC_SOCKET_TYPE_ROUTER:
+    {
+      SilcServerList *serv = (SilcServerList *)sock->user_data;
+      if (serv->registered)
+       return TRUE;
+      break;
+    }
+  default:
+    break;
+  }
+
+  silc_server_command_send_status_reply(cmd, command,
+                                       SILC_STATUS_ERR_NOT_REGISTERED);
+  silc_server_command_free(cmd);
+  return FALSE;
+}
+
+/* Processes received command packet. */
+
+void silc_server_command_process(SilcServer server,
+                                SilcSocketConnection sock,
+                                SilcPacketContext *packet)
+{
+  SilcServerCommandContext ctx;
+  SilcServerCommand *cmd;
+  
+  /* Allocate command context. This must be free'd by the
+     command routine receiving it. */
+  ctx = silc_calloc(1, sizeof(*ctx));
+  ctx->server = server;
+  ctx->sock = sock;
+  ctx->packet = packet;        /* Save original packet */
+  
+  /* Parse the command payload in the packet */
+  ctx->payload = silc_command_parse_payload(packet->buffer);
+  if (!ctx->payload) {
+    SILC_LOG_ERROR(("Bad command payload, packet dropped"));
+    silc_buffer_free(packet->buffer);
+    silc_free(ctx);
+    return;
+  }
+  
+  /* Execute command. If this fails the packet is dropped. */
+  for (cmd = silc_command_list; cmd->cb; cmd++)
+    if (cmd->cmd == silc_command_get(ctx->payload)) {
+
+      if (!(cmd->flags & SILC_CF_REG)) {
+       cmd->cb(ctx);
+       break;
+      }
+      
+      if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
+       cmd->cb(ctx);
+       break;
+      }
+    }
+
+  if (cmd == NULL) {
+    SILC_LOG_ERROR(("Unknown command, packet dropped"));
+    silc_free(ctx);
+    return;
+  }
+
+  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.
@@ -665,11 +771,6 @@ SILC_SERVER_CMD_FUNC(invite)
      sender of this command must be at least channel operator. */
   /* XXX */
 
-  /* Check whether the requested client is already on the channel. */
-  /* XXX if we are normal server we don't know about global clients on
-     the channel thus we must request it (NAMES command), check from
-     local cache as well. */
-
   /* Find the connection data for the destination. If it is local we will
      send it directly otherwise we will send it to router for routing. */
   dest = silc_idlist_find_client_by_id(server->local_list->clients, dest_id);
@@ -678,6 +779,16 @@ SILC_SERVER_CMD_FUNC(invite)
   else
     dest_sock = silc_server_get_route(server, dest_id, SILC_ID_CLIENT);
 
+  /* Check whether the requested client is already on the channel. */
+  /* XXX if we are normal server we don't know about global clients on
+     the channel thus we must request it (NAMES command), check from
+     local cache as well. */
+  if (silc_server_client_on_channel(dest, channel)) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
+                                         SILC_STATUS_ERR_USER_ON_CHANNEL);
+    goto out;
+  }
+
   /* Send notify to the client that is invited to the channel */
   silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
                               "%s invites you to channel %s",
@@ -729,8 +840,75 @@ SILC_SERVER_CMD_FUNC(kill)
 {
 }
 
+/* Server side of command INFO. This sends information about us to 
+   the client. If client requested specific server we will send the 
+   command to that server. */
+
 SILC_SERVER_CMD_FUNC(info)
 {
+  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  SilcServer server = cmd->server;
+  SilcBuffer packet;
+  unsigned int argc;
+  unsigned char *id_string;
+  char info_string[256], *dest_server;
+
+  argc = silc_command_get_arg_num(cmd->payload);
+  if (argc < 1) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
+                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+    goto out;
+  }
+  if (argc > 1) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
+                                         SILC_STATUS_ERR_TOO_MANY_PARAMS);
+    goto out;
+  }
+
+  /* Get server name */
+  dest_server = silc_command_get_arg_type(cmd->payload, 1, NULL);
+  if (!dest_server) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
+                                         SILC_STATUS_ERR_NO_SUCH_SERVER);
+    goto out;
+  }
+
+  if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
+    /* Send our reply */
+    memset(info_string, 0, sizeof(info_string));
+    snprintf(info_string, sizeof(info_string), "%s %s %s <%s>",
+            server->config->admin_info->location,
+            server->config->admin_info->server_type,
+            server->config->admin_info->admin_name,
+            server->config->admin_info->admin_email);
+
+    id_string = silc_id_id2str(server->id, SILC_ID_SERVER);
+
+    packet = 
+      silc_command_encode_reply_payload_va(SILC_COMMAND_INFO,
+                                          SILC_STATUS_OK, 2,
+                                          2, id_string, SILC_ID_SERVER_LEN,
+                                          3, info_string, 
+                                          strlen(info_string));
+    silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
+                           packet->data, packet->len, FALSE);
+    
+    silc_free(id_string);
+    silc_buffer_free(packet);
+  } else {
+    /* Send this command to the requested server */
+
+    if (server->server_type == SILC_SERVER && !server->standalone) {
+
+    }
+
+    if (server->server_type == SILC_ROUTER) {
+
+    }
+  }
+  
+ out:
+  silc_server_command_free(cmd);
 }
 
 SILC_SERVER_CMD_FUNC(connect)
index d7ed494402f85815512825d49220991aab85bb6e..d5c96e9b28c7df3c211a62765547108333a0e605 100644 (file)
@@ -82,24 +82,6 @@ extern SilcServerCommandPending *silc_command_pending;
 #define SILC_SERVER_CMD_FUNC(func) \
 void silc_server_command_##func(void *context)
 
-/* Macro used to execute commands */
-#define SILC_SERVER_COMMAND_EXEC(ctx)                          \
-do {                                                           \
-  SilcServerCommand *cmd;                                      \
-                                                               \
-  for (cmd = silc_command_list; cmd->cb; cmd++)                        \
-    if (cmd->cmd == silc_command_get(ctx->payload)) {          \
-      cmd->cb(ctx);                                            \
-      break;                                                   \
-    }                                                          \
-                                                               \
-  if (cmd == NULL) {                                           \
-    SILC_LOG_ERROR(("Unknown command, packet dropped"));       \
-    silc_free(ctx);                                            \
-    return;                                                    \
-  }                                                            \
-} while(0)
-
 /* Checks for pending commands */
 #define SILC_SERVER_COMMAND_CHECK_PENDING(ctx)         \
 do {                                                   \
@@ -128,6 +110,9 @@ do {                                                        \
 } while(0)
 
 /* Prototypes */
+void silc_server_command_process(SilcServer server,
+                                SilcSocketConnection sock,
+                                SilcPacketContext *packet);
 void silc_server_command_pending(SilcCommand reply_cmd,
                                 SilcCommandCb callback,
                                 void *context);
index 36ccb033febac0c29a932da7d623c001d867e7cf..c958e26ab82fd8ca124ee87b0f0a5c7ef9409fb7 100644 (file)
@@ -84,6 +84,9 @@ struct SilcServerListStruct {
   int server_type;
   SilcServerID *id;
 
+  /* TRUE when server is registered to server */
+  int registered;
+
   /* Pointer to the router */
   struct SilcServerListStruct *router;
 
@@ -201,6 +204,9 @@ struct SilcClientListStruct {
   SilcClientID *id;
   int mode;
 
+  /* TRUE when client is registered to server */
+  int registered;
+
   /* Pointer to the router */
   SilcServerList *router;
 
index 059535864952e758e2df71e54b0c823ffdae2a06..c0836ec73bd90e42b355ba007fa985ba46a35846 100644 (file)
 /*
  * $Id$
  * $Log$
+ * Revision 1.7  2000/07/10 05:43:00  priikone
+ *     Removed command packet processing from server.c and added it to
+ *     command.c.
+ *     Implemented INFO command. Added support for testing that
+ *     connections are registered before executing commands.
+ *
  * Revision 1.6  2000/07/07 06:55:59  priikone
  *     Added SILC style public key support and made server to use
  *     it at all time.
@@ -135,10 +141,9 @@ void silc_server_free(SilcServer server)
 
 int silc_server_init(SilcServer server)
 {
-  int *sock = NULL, sock_count, i;
+  int *sock = NULL, sock_count = 0, i;
   SilcServerID *id;
   SilcServerList *id_entry;
-  SilcHashObject hash;
 
   SILC_LOG_DEBUG(("Initializing server"));
   assert(server);
@@ -200,16 +205,20 @@ int silc_server_init(SilcServer server)
        silc_pkcs_private_key_alloc("rsa", private_key, prv_len);
       
       /* XXX Save keys */
-      silc_pkcs_save_public_key("pubkey.pub", server->public_key);
-      silc_pkcs_save_private_key("privkey.prv", server->private_key, NULL);
+      silc_pkcs_save_public_key("pubkey.pub", server->public_key,
+                               SILC_PKCS_FILE_PEM);
+      silc_pkcs_save_private_key("privkey.prv", server->private_key, NULL,
+                                SILC_PKCS_FILE_BIN);
 
       memset(public_key, 0, pk_len);
       memset(private_key, 0, prv_len);
       silc_free(public_key);
       silc_free(private_key);
     } else {
-      silc_pkcs_load_public_key("pubkey.pub", &server->public_key);
-      silc_pkcs_load_private_key("privkey.prv", &server->private_key);
+      silc_pkcs_load_public_key("pubkey.pub", &server->public_key,
+                               SILC_PKCS_FILE_PEM);
+      silc_pkcs_load_private_key("privkey.prv", &server->private_key,
+                                SILC_PKCS_FILE_BIN);
     }
   }
 
@@ -1663,37 +1672,11 @@ void silc_server_packet_parse_type(SilcServer server,
      * Command packets
      */
   case SILC_PACKET_COMMAND:
-    {
-      /*
-       * Recived command. Allocate command context and execute the command.
-       */
-      SilcServerCommandContext ctx;
-
-      SILC_LOG_DEBUG(("Command packet"));
-
-      /* Router cannot send command packet */
-      if (sock->type == SILC_SOCKET_TYPE_ROUTER)
-       break;
-
-      /* Allocate command context. This must be free'd by the
-        command routine receiving it. */
-      ctx = silc_calloc(1, sizeof(*ctx));
-      ctx->server = server;
-      ctx->sock = sock;
-      ctx->packet = packet;    /* Save original packet */
-
-      /* Parse the command payload in the packet */
-      ctx->payload = silc_command_parse_payload(buffer);
-      if (!ctx->payload) {
-       SILC_LOG_ERROR(("Bad command payload, packet dropped"));
-       silc_free(ctx);
-       return;
-      }
-
-      /* Execute command. If this fails the packet is dropped. */
-      SILC_SERVER_COMMAND_EXEC(ctx);
-      silc_buffer_free(buffer);
-    }
+    /*
+     * Recived command. Allocate command context and execute the command.
+     */
+    SILC_LOG_DEBUG(("Command packet"));
+    silc_server_command_process(server, sock, packet);
     break;
 
   case SILC_PACKET_COMMAND_REPLY:
@@ -3705,6 +3688,7 @@ SilcClientList *silc_server_new_client(SilcServer server,
 
   /* Set the pointers to the client list and create new client ID */
   id_entry = (SilcClientList *)sock->user_data;
+  id_entry->registered = TRUE;
   id_entry->nickname = strdup(username);
   id_entry->username = username;
   id_entry->userinfo = realname;
@@ -3795,6 +3779,7 @@ SilcServerList *silc_server_new_server(SilcServer server,
 
   /* Save ID and name */
   id_entry = (SilcServerList *)sock->user_data;
+  id_entry->registered = TRUE;
   id_entry->id = silc_id_str2id(id_string, SILC_ID_SERVER);
   id_entry->server_name = server_name;