CONNECT, CLOSE and SHUTDOWN commands.
authorPekka Riikonen <priikone@silcnet.org>
Sat, 24 Feb 2001 22:47:01 +0000 (22:47 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sat, 24 Feb 2001 22:47:01 +0000 (22:47 +0000)
CHANGES
apps/silcd/command.c
apps/silcd/command.h
apps/silcd/server.c
apps/silcd/server.h
apps/silcd/server_internal.h
doc/draft-riikonen-silc-spec-01.nroff
lib/silcclient/command.c
lib/silcclient/command.h
lib/silccore/silccommand.h
lib/silccore/silcmode.h

diff --git a/CHANGES b/CHANGES
index 0fc7f959ae3e885357793e670c00200fd5ef79fe..a0299768cf1d481eb27a39ce9b8135e91b123d04 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,21 @@
+Sat Feb 24 23:45:49 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * DIE command was renamed to SHUTDOWN.  Updated the both code
+         and protocol specs.
+
+       * Defined SILC_UMODE_NONE, SILC_UMODE_SERVER_OPERATOR and
+         SILC_UMODE_ROUTER_OPERATOR modes into lib/silccore/silcmode.h.
+
+       * Implemented CONNECT, CLOSE and SHUTDOWN commands to the server
+         side.
+
+       * Added function silc_server_create_connection function to create
+         connection to remote router.  My server implementation actually
+         does not allow router to connect to normal server (it expects
+         that normal server always initiates the connection to the router)
+         so the CONNECT command is only good for connecting to another
+         router.
+
 Sat Feb 24 16:03:45 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Added SILC_NOTIFY_TYPE_KICKED to indicate that the client
index 05c385d6bb3667443f5bab9e601848f2ba4740c8..c72a18c970d2d4d533610a281991f3bb605a6bec 100644 (file)
@@ -69,7 +69,8 @@ SilcServerCommand silc_command_list[] =
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
   SILC_SERVER_CMD(close, CLOSE,
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
-  SILC_SERVER_CMD(die, DIE, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
+  SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG | 
+                 SILC_CF_OPER),
   SILC_SERVER_CMD(silcoper, SILCOPER,
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
@@ -1693,10 +1694,6 @@ SILC_SERVER_CMD_FUNC(info)
   silc_server_command_free(cmd);
 }
 
-SILC_SERVER_CMD_FUNC(connect)
-{
-}
-
 /* Server side of command PING. This just replies to the ping. */
 
 SILC_SERVER_CMD_FUNC(ping)
@@ -1736,10 +1733,6 @@ SILC_SERVER_CMD_FUNC(ping)
   silc_server_command_free(cmd);
 }
 
-SILC_SERVER_CMD_FUNC(oper)
-{
-}
-
 /* Assembles USERS command and executes it. This is called when client
    joins to a channel and we wan't to send USERS command reply to the 
    client. */
@@ -2965,22 +2958,159 @@ SILC_SERVER_CMD_FUNC(kick)
   silc_server_command_free(cmd);
 }
 
+SILC_SERVER_CMD_FUNC(oper)
+{
+}
+
+SILC_SERVER_CMD_FUNC(silcoper)
+{
+}
+
+/* Server side command of CONNECT. Connects us to the specified remote
+   server or router. */
+
+SILC_SERVER_CMD_FUNC(connect)
+{
+  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  SilcServer server = cmd->server;
+  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  unsigned char *tmp;
+  unsigned int tmp_len;
+  unsigned int port;
+
+  SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 0, 0);
+
+  /* Check whether client has the permissions. */
+  if (client->mode == SILC_UMODE_NONE) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
+                                         SILC_STATUS_ERR_NO_SERVER_PRIV);
+    goto out;
+  }
+
+  if (server->server_type == SILC_ROUTER && 
+      client->mode & SILC_UMODE_SERVER_OPERATOR) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
+                                         SILC_STATUS_ERR_NO_ROUTER_PRIV);
+    goto out;
+  }
+
+  /* Get the remote server */
+  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+  if (!tmp) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
+                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+    goto out;
+  }
+
+  /* Get port */
+  tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+  if (tmp)
+    SILC_GET32_MSB(port, tmp);
+
+  /* Create the connection. It is done with timeout and is async. */
+  silc_server_create_connection(server, tmp, port);
+
+  /* Send reply to the sender */
+  silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
+                                       SILC_STATUS_OK);
+
+ out:
+  silc_server_command_free(cmd);
+}
+
 SILC_SERVER_CMD_FUNC(restart)
 {
 }
+
+/* Server side command of CLOSE. Closes connection to a specified server. */
  
 SILC_SERVER_CMD_FUNC(close)
 {
+  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  SilcServer server = cmd->server;
+  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcServerID *server_id;
+  SilcServerEntry server_entry;
+  unsigned char *tmp;
+  unsigned int tmp_len;
+
+  SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 0, 0);
+
+  /* Check whether client has the permissions. */
+  if (client->mode == SILC_UMODE_NONE) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
+                                         SILC_STATUS_ERR_NO_SERVER_PRIV);
+    goto out;
+  }
+
+  /* Get the server ID */
+  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+  if (!tmp) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
+                                         SILC_STATUS_ERR_NO_SERVER_ID);
+    goto out;
+  }
+  server_id = silc_id_payload_parse_id(tmp, tmp_len);
+  if (!server_id) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
+                                         SILC_STATUS_ERR_NO_SERVER_ID);
+    goto out;
+  }
+
+  /* Check that the server ID is valid and that I have an active
+     connection to it. Check only local list as it holds the local
+     connections. */
+  server_entry = silc_idlist_find_server_by_id(server->local_list,
+                                              server_id, NULL);
+  if (!server_entry) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
+                                         SILC_STATUS_ERR_NO_SERVER_ID);
+    goto out;
+  }
+
+  /* Close the connection to the server */
+  silc_server_free_sock_user_data(server, server_entry->connection);
+  silc_server_disconnect_remote(server, server_entry->connection,
+                               "Server closed connection: "
+                               "Closed by operator");
+  
+  /* Send reply to the sender */
+  silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
+                                       SILC_STATUS_OK);
+
+ out:
+  silc_server_command_free(cmd);
 }
+
+/* Server side command of SHUTDOWN. Shutdowns the server and closes all
+   active connections. */
  
-SILC_SERVER_CMD_FUNC(die)
+SILC_SERVER_CMD_FUNC(shutdown)
 {
+  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  SilcServer server = cmd->server;
+  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+
+  SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
+
+  /* Check whether client has the permission. */
+  if (client->mode == SILC_UMODE_NONE) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
+                                         SILC_STATUS_ERR_NO_SERVER_PRIV);
+    goto out;
+  }
+
+  /* Then, gracefully, or not, bring the server down. */
+  silc_server_stop(server);
+
+  /* Send reply to the sender */
+  silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
+                                       SILC_STATUS_OK);
+
+ out:
+  silc_server_command_free(cmd);
 }
  
-SILC_SERVER_CMD_FUNC(silcoper)
-{
-}
-
 /* Server side command of LEAVE. Removes client from a channel. */
 
 SILC_SERVER_CMD_FUNC(leave)
index 9180768a213efafdd7a0a8b635a7c2c2f1897aea..8fc42e1ed2fa91b7e4fae50478e1b2da0ec02ed9 100644 (file)
@@ -150,7 +150,7 @@ SILC_SERVER_CMD_FUNC(kick);
 SILC_SERVER_CMD_FUNC(ignore);
 SILC_SERVER_CMD_FUNC(restart);
 SILC_SERVER_CMD_FUNC(close);
-SILC_SERVER_CMD_FUNC(die);
+SILC_SERVER_CMD_FUNC(shutdown);
 SILC_SERVER_CMD_FUNC(silcoper);
 SILC_SERVER_CMD_FUNC(leave);
 SILC_SERVER_CMD_FUNC(users);
index 215657586fdf863b0a5f911f5ccda05e9a031635..a020fa61bd6cf3354f8cd8de4787567b1a279334 100644 (file)
@@ -622,7 +622,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router)
       /* Allocate connection object for hold connection specific stuff. */
       sconn = silc_calloc(1, sizeof(*sconn));
       sconn->server = server;
-      sconn->remote_host = server->config->routers->host;
+      sconn->remote_host = strdup(server->config->routers->host);
       sconn->remote_port = server->config->routers->port;
 
       silc_task_register(server->timeout_queue, fd, 
@@ -652,7 +652,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router)
        /* Allocate connection object for hold connection specific stuff. */
        sconn = silc_calloc(1, sizeof(*sconn));
        sconn->server = server;
-       sconn->remote_host = ptr->host;
+       sconn->remote_host = strdup(ptr->host);
        sconn->remote_port = ptr->port;
 
        silc_task_register(server->timeout_queue, fd, 
@@ -870,8 +870,10 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
 
  out:
   /* Free the temporary connection data context */
-  if (sconn)
+  if (sconn) {
+    silc_free(sconn->remote_host);
     silc_free(sconn);
+  }
 
   /* Free the protocol object */
   silc_protocol_free(protocol);
@@ -1752,6 +1754,25 @@ void silc_server_packet_parse_type(SilcServer server,
   
 }
 
+/* Creates connection to a remote router. */
+
+void silc_server_create_connection(SilcServer server,
+                                  char *remote_host, unsigned int port)
+{
+  SilcServerConnection sconn;
+
+  /* Allocate connection object for hold connection specific stuff. */
+  sconn = silc_calloc(1, sizeof(*sconn));
+  sconn->server = server;
+  sconn->remote_host = strdup(remote_host);
+  sconn->remote_port = port;
+
+  silc_task_register(server->timeout_queue, 0, 
+                    silc_server_connect_router,
+                    (void *)sconn, 0, 1, SILC_TASK_TIMEOUT, 
+                    SILC_TASK_PRI_NORMAL);
+}
+
 /* Closes connection to socket connection */
 
 void silc_server_close_connection(SilcServer server,
index 1b83e1a836216f968e0b4fd3fad50e784e18665d..4d4ab240abeb1065c590045f3e79f03d4d4b31e1 100644 (file)
@@ -87,6 +87,8 @@ void silc_server_packet_parse(SilcPacketParserContext *parser_context);
 void silc_server_packet_parse_type(SilcServer server, 
                                   SilcSocketConnection sock,
                                   SilcPacketContext *packet);
+void silc_server_create_connection(SilcServer server,
+                                  char *remote_host, unsigned int port);
 void silc_server_close_connection(SilcServer server,
                                  SilcSocketConnection sock);
 void silc_server_free_client_data(SilcServer server, 
index 874b452064e36be4ace754a23e845a71d72e715c..bc0e3d755d8bacb00cdb1bc43e946bc70e84471f 100644 (file)
@@ -57,7 +57,6 @@ typedef struct {
 } SilcServerStatistics;
 
 typedef struct {
-  void *id_entry;
   SilcSocketConnection sock;
 
   /* Remote host name and port */
index 7e9c35cb81ab41852c88cb42c204fdf777887c87..1c286fc06a6c7ac17d5e52f9c64bd5002109344a 100644 (file)
@@ -2258,15 +2258,12 @@ List of all defined commands in SILC follows.
    11   SILC_COMMAND_CONNECT
 
         Max Arguments:  2
-            Arguments:  (1) <Server ID>  
-                        (2) [<remote server/router>[ <port>]]
+            Arguments:  (1) <remote server/router>  (2) [<port>]
 
         This command is used by operators to force a server to try to
-        establish a new connection to another router (if the connecting
-        server is normal server) or server (if the connecting server is
-        router server).  Operator may specify the server/router to be
-        connected by setting <remote server> argument.  The separator
-        between <remote server address> and <port> is whitespace (` ').
+        establish a new connection to remote server or router. The
+        Operator must specify the server/router to be connected by
+        setting <remote server> argument.  The port is 32 bit MSB value.
 
         Reply messages to the command:
 
@@ -2284,7 +2281,6 @@ List of all defined commands in SILC follows.
             SILC_STATUS_ERR_NOT_REGISTERED
             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS
             SILC_STATUS_ERR_TOO_MANY_PARAMS
-            SILC_STATUS_ERR_NO_SUCH_SERVER_ID
             SILC_STATUS_ERR_NO_SERVER_PRIV
             SILC_STATUS_ERR_NO_ROUTER_PRIV
 
@@ -2884,7 +2880,7 @@ List of all defined commands in SILC follows.
             SILC_STATUS_ERR_NO_SUCH_SERVER_ID
 
 
-   22   SILC_COMMAND_DIE
+   22   SILC_COMMAND_SHUTDOWN
 
         Max Arguments:  0
             Arguments:  None
index 8a3e691037b6e0551e3277777a10722adbd43966..288a138af4d461306a88901fd94a3659ee7c9edb 100644 (file)
@@ -51,7 +51,7 @@ SilcClientCommand silc_command_list[] =
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER, 2),
   SILC_CLIENT_CMD(close, CLOSE, "CLOSE",
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER, 2),
-  SILC_CLIENT_CMD(die, DIE, "DIE",
+  SILC_CLIENT_CMD(shutdown, SHUTDOWN, "SHUTDOWN",
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER, 2),
   SILC_CLIENT_CMD(silcoper, SILCOPER, "SILOPER",
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER, 2),
@@ -1237,7 +1237,7 @@ SILC_CLIENT_CMD_FUNC(close)
 {
 }
  
-SILC_CLIENT_CMD_FUNC(die)
+SILC_CLIENT_CMD_FUNC(shutdown)
 {
 }
  
index cf236483e51669995812f32c21537ff07aebd56a..a47c7461f420a0edc6f6bacbda15544e86a451b4 100644 (file)
@@ -164,7 +164,7 @@ SILC_CLIENT_CMD_FUNC(cumode);
 SILC_CLIENT_CMD_FUNC(kick);
 SILC_CLIENT_CMD_FUNC(restart);
 SILC_CLIENT_CMD_FUNC(close);
-SILC_CLIENT_CMD_FUNC(die);
+SILC_CLIENT_CMD_FUNC(shutdown);
 SILC_CLIENT_CMD_FUNC(silcoper);
 SILC_CLIENT_CMD_FUNC(leave);
 SILC_CLIENT_CMD_FUNC(users);
index d6e982633afc27aa6863fd4079ab39c870b3f799..4f29464c3a8a5e2143b7df781cf40671d7a74c55 100644 (file)
@@ -76,7 +76,7 @@ typedef enum {
 #define SILC_COMMAND_KICK              19
 #define        SILC_COMMAND_RESTART            20
 #define        SILC_COMMAND_CLOSE              21
-#define        SILC_COMMAND_DIE                22
+#define        SILC_COMMAND_SHUTDOWN           22
 #define SILC_COMMAND_SILCOPER          23
 #define SILC_COMMAND_LEAVE             24
 #define SILC_COMMAND_USERS             25
index 26b45c748e85e4e443620e79a0ab39041d009c7e..53d04ee4b55ca52c0749f0957fe3f9d79f89c93c 100644 (file)
@@ -39,4 +39,9 @@
 #define SILC_CHANNEL_UMODE_CHANFO     0x0001 /* channel founder */
 #define SILC_CHANNEL_UMODE_CHANOP     0x0002 /* channel operator */
 
+/* SILC modes */
+#define SILC_UMODE_NONE               0x0000 /* Normal SILC user */
+#define SILC_UMODE_SERVER_OPERATOR    0x0001 /* Server operator */
+#define SILC_UMODE_ROUTER_OPERATOR    0x0002 /* Router (SILC) operator */
+
 #endif