Fixed founder mode chaning in JOIN and CUMODE_CHANGE notifys.
authorPekka Riikonen <priikone@silcnet.org>
Tue, 18 Jun 2002 17:09:22 +0000 (17:09 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 18 Jun 2002 17:09:22 +0000 (17:09 +0000)
Close all connections and listeners in silc_server_stop.

CHANGES
TODO
apps/silcd/command.c
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/server.c
apps/silcd/server_internal.h
lib/silcclient/client.c
lib/silcutil/silcsockconn.h

diff --git a/CHANGES b/CHANGES
index 58b2428c39efba8772820e313c5946b77dc0e3ae..1edc1a5ee762fed06ac4d5a6b6abcbf764a8519d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,20 @@
+Tue Jun 18 17:14:52 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
+
+       * When authenticating as founder during JOIN command, check
+         that the one authenticating becomes the only founder on the
+         channel.  Affected file silcd/command.c.
+
+       * Better checking for founder mode setting when CUMODE_CHANGE
+         notify is received.  Affected file silcd/packet_receive.c.
+
+       * Close all connections when shutting down the server by sending
+         DISCONNECT packet.  Close all listeners too when shutting
+         down the server.  Affected file silcd/server.c.
+
+       * Handle DISCONNECT packet correctly in client library by
+         calling the "disconnect" client operation.  Affected file
+         lib/silcclient/client.c.
+
 Tue Jun 18 10:26:27 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
 
        * The log file is not dupped internally anymore in
diff --git a/TODO b/TODO
index 5b9372be64388df3386d4b542200d3a6b5d54a60..6748473e9cb70694fde6aef779484e508351baa4 100644 (file)
--- a/TODO
+++ b/TODO
@@ -19,10 +19,6 @@ TODO/bugs In SILC Client Library
 TODO/bugs In SILC Server
 ========================
 
- o Make the "one founder per channel" check during join -founder as well.
-
- o Make the "one founder per channel" during CUMODE notify as well.
-
  o Implement the <Requested Attributes> and the Attribute Payload to
    the core library, client and server.  Maybe implementations of
    RFC 2425 and RFC 2426 to make it complete.
index 14d50d2d1c454ba632f22b192ba40e51d7af8081..50d620a2adda7e60277baea9e5072cd618499543 100644 (file)
@@ -3220,6 +3220,8 @@ static void silc_server_command_join_channel(SilcServer server,
    */
   if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
     SilcIDListData idata = (SilcIDListData)client;
+    SilcChannelClientEntry chl2;
+    SilcHashTableList htl;
 
     if (channel->founder_key && idata->public_key &&
        silc_pkcs_public_key_compare(channel->founder_key, 
@@ -3228,6 +3230,19 @@ static void silc_server_command_join_channel(SilcServer server,
       if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
                                channel->founder_key, 0, server->sha1hash,
                                client->id, SILC_ID_CLIENT)) {
+
+       /* There cannot be anyone else as founder on the channel now.  This
+          client is definitely the founder due to this authentication */
+       silc_hash_table_list(channel->user_list, &htl);
+       while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
+         if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
+           chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+           silc_server_force_cumode_change(server, NULL, channel, chl2,
+                                           chl2->mode);
+           break;
+         }
+       silc_hash_table_list_reset(&htl);
+
        umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
        founder = TRUE;
       }
@@ -3415,6 +3430,7 @@ static void silc_server_command_join_channel(SilcServer server,
      we'll ignore it (in packet_receive.c) so we must send it here. If
      we are router then this will send it to local clients and local
      servers. */
+  SILC_LOG_DEBUG(("Send JOIN notify to channel"));
   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
                                     SILC_NOTIFY_TYPE_JOIN, 2,
                                     clidp->data, clidp->len,
@@ -3443,22 +3459,23 @@ static void silc_server_command_join_channel(SilcServer server,
        notify the mode change to the channel. */
     if (founder) {
       SILC_PUT32_MSB(chl->mode, mode);
+      SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
                                         SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
                                         clidp->data, clidp->len,
                                         mode, 4, clidp->data, clidp->len,
                                         fkey, fkey_len);
-      
-      /* Set CUMODE notify type to network */
-      if (!server->standalone)
-       silc_server_send_notify_cumode(server, server->router->connection,
-                                      server->server_type == SILC_ROUTER ? 
-                                      TRUE : FALSE, channel,
-                                      chl->mode, client->id, SILC_ID_CLIENT,
-                                      client->id, channel->founder_key);
     }
   }
 
+  /* Set CUMODE notify type to network */
+  if (founder && !server->standalone)
+    silc_server_send_notify_cumode(server, server->router->connection,
+                                  server->server_type == SILC_ROUTER ?
+                                  TRUE : FALSE, channel,
+                                  chl->mode, client->id, SILC_ID_CLIENT,
+                                  client->id, channel->founder_key);
+
   silc_buffer_free(reply);
   silc_buffer_free(clidp);
   silc_buffer_free(chidp);
index bd9545f8f1361b3f6b8af4be008eff578da4c5f1..1c71e7e65d59893f564abfe404a3394a47f90074 100644 (file)
@@ -786,40 +786,21 @@ void silc_server_notify(SilcServer server,
        }
       }
 
-      /* Get target channel entry */
+      /* Get target channel user entry */
       if (!silc_server_client_on_channel(client2, channel, &chl))
        goto out;
 
       if (mode & SILC_CHANNEL_UMODE_CHANFO &&
-         !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) && !client &&
-         server->server_type == SILC_ROUTER) {
-       /* Get the founder of the channel and if found then this client
-          cannot be the founder since there already is one. */
-       silc_hash_table_list(channel->user_list, &htl);
-       while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
-         if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
-           mode &= ~SILC_CHANNEL_UMODE_CHANFO;
-           silc_server_force_cumode_change(server, sock, channel, chl, mode);
-           notify_sent = TRUE;
-           break;
-         }
-       silc_hash_table_list_reset(&htl);
-       if (!(mode & SILC_CHANNEL_UMODE_CHANFO))
-         break;
-      }
-
-      if (client && mode & SILC_CHANNEL_UMODE_CHANFO &&
-         !(chl->mode & SILC_CHANNEL_UMODE_CHANFO) && 
-         server->server_type == SILC_ROUTER) {
-       /* Check whether this client is allowed to be channel founder on
-          this channel. */
+         !(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
+         server->server_type == SILC_ROUTER &&
+         sock->user_data != server->router) {
        SilcPublicKey founder_key = NULL;
 
        /* If channel doesn't have founder auth mode then it's impossible
           that someone would be getting founder rights with CUMODE command.
           In that case there already either is founder or there isn't
           founder at all on the channel. */
-       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
+       if (client && !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
          /* Force the mode to not have founder mode */
          mode &= ~SILC_CHANNEL_UMODE_CHANFO;
          silc_server_force_cumode_change(server, sock, channel, chl, mode);
@@ -833,7 +814,8 @@ void silc_server_notify(SilcServer server,
        while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
          if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
            mode &= ~SILC_CHANNEL_UMODE_CHANFO;
-           silc_server_force_cumode_change(server, sock, channel, chl, mode);
+           silc_server_force_cumode_change(server, sock, channel,
+                                           chl, mode);
            notify_sent = TRUE;
            break;
          }
@@ -855,28 +837,47 @@ void silc_server_notify(SilcServer server,
          break;
        }
 
-       /* Now match the public key we have cached and public key sent.
-          They must match. */
-       if (client->data.public_key && 
-           !silc_pkcs_public_key_compare(channel->founder_key,
-                                         client->data.public_key)) {
-         mode &= ~SILC_CHANNEL_UMODE_CHANFO;
-         silc_server_force_cumode_change(server, sock, channel, chl, mode);
-         notify_sent = TRUE;
-         break;
-       }
-       if (!silc_pkcs_public_key_compare(channel->founder_key,
-                                         founder_key)) {
-         mode &= ~SILC_CHANNEL_UMODE_CHANFO;
-         silc_server_force_cumode_change(server, sock, channel, chl, mode);
-         notify_sent = TRUE;
-         break;
+       if (channel->founder_key) {
+         /* Now match the public key we have cached and public key sent.
+            They must match. */
+         if (client && client->data.public_key && 
+             !silc_pkcs_public_key_compare(channel->founder_key,
+                                           client->data.public_key)) {
+           mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+           silc_server_force_cumode_change(server, sock, channel, chl, mode);
+           notify_sent = TRUE;
+           break;
+         }
+         if (!silc_pkcs_public_key_compare(channel->founder_key,
+                                           founder_key)) {
+           mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+           silc_server_force_cumode_change(server, sock, channel, chl, mode);
+           notify_sent = TRUE;
+           break;
+         }
        }
 
+       /* There cannot be anyone else as founder on the channel now.  This
+          client is definitely the founder due to this authentication */
+       silc_hash_table_list(channel->user_list, &htl);
+       while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
+         if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
+           chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+           silc_server_force_cumode_change(server, NULL, channel, chl2,
+                                           chl2->mode);
+           break;
+         }
+       silc_hash_table_list_reset(&htl);
+
        if (founder_key)
          silc_pkcs_public_key_free(founder_key);
       }
 
+      if (server->server_type == SILC_ROUTER && chl->mode == mode) {
+       SILC_LOG_DEBUG(("Mode is changed already"));
+       break;
+      }
+
       SILC_LOG_DEBUG(("Changing the channel user mode"));
 
       /* Change the mode */
index 512ee42370873ddc32a9922497a821b3c7646e0e..737da431691b217c016fe740ef10760ee4212286 100644 (file)
@@ -173,9 +173,9 @@ void silc_server_packet_send_dest(SilcServer server,
   /* Set the packet context pointers */
   packetdata.type = type;
   packetdata.flags = flags;
-  packetdata.src_id = silc_id_id2str(server->id, server->id_type);
-  packetdata.src_id_len = silc_id_get_len(server->id, server->id_type);
-  packetdata.src_id_type = server->id_type;
+  packetdata.src_id = silc_id_id2str(server->id, SILC_ID_SERVER);
+  packetdata.src_id_len = silc_id_get_len(server->id, SILC_ID_SERVER);
+  packetdata.src_id_type = SILC_ID_SERVER;
   packetdata.dst_id = dst_id_data;
   packetdata.dst_id_len = dst_id_len;
   packetdata.dst_id_type = dst_id_type;
index 0f3e2da518a05afdb0a171c576690dddf8a98066..93e81034a7eb663347607fc84591458234ba15f5 100644 (file)
@@ -167,6 +167,7 @@ bool silc_server_init_secondary(SilcServer server)
     silc_socket_alloc(sock_list[sock],
                      SILC_SOCKET_TYPE_SERVER, NULL, &newsocket);
     server->sockets[sock_list[sock]] = newsocket;
+    SILC_SET_LISTENER(newsocket);
 
     /* Perform name and address lookups to resolve the listenning address
        and port. */
@@ -310,6 +311,7 @@ bool silc_server_init(SilcServer server)
      is sent as argument for fast referencing in the future. */
   silc_socket_alloc(sock, SILC_SOCKET_TYPE_SERVER, NULL, &newsocket);
   server->sockets[sock] = newsocket;
+  SILC_SET_LISTENER(newsocket);
 
   /* Perform name and address lookups to resolve the listenning address
      and port. */
@@ -336,7 +338,6 @@ bool silc_server_init(SilcServer server)
   server->id = id;
   server->id_string = silc_id_id2str(id, SILC_ID_SERVER);
   server->id_string_len = silc_id_get_len(id, SILC_ID_SERVER);
-  server->id_type = SILC_ID_SERVER;
   server->server_name = server->config->server_info->server_name;
   server->config->server_info->server_name = NULL;
 
@@ -577,17 +578,31 @@ void silc_server_stop(SilcServer server)
   if (server->schedule) {
     int i;
 
+    /* Close all connections */
     for (i = 0; i < server->config->param.connections_max; i++) {
       if (!server->sockets[i])
        continue;
-      silc_socket_free(server->sockets[i]);
+      if (!SILC_IS_LISTENER(server->sockets[i])) {
+       silc_schedule_task_del_by_context(server->schedule,
+                                         server->sockets[i]);
+       silc_server_disconnect_remote(server, server->sockets[i], 
+                                     SILC_STATUS_OK, 
+                                     "Server is shutting down");
+      } else {
+       silc_socket_free(server->sockets[i]);
+       server->sockets[i] = NULL;
+      }
     }
-    silc_free(server->sockets);
-    server->sockets = NULL;
+
+    /* We are not connected to network anymore */
+    server->standalone = TRUE;
 
     silc_schedule_stop(server->schedule);
     silc_schedule_uninit(server->schedule);
     server->schedule = NULL;
+
+    silc_free(server->sockets);
+    server->sockets = NULL;
   }
 
   silc_server_protocols_unregister();
@@ -1230,6 +1245,14 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
                 sock->ip));
 
   /* Listenning port */
+  if (!server->sockets[(SilcUInt32)proto_ctx->context]) {
+    silc_server_disconnect_remote(server, sock,
+                                 SILC_STATUS_ERR_RESOURCE_LIMIT,
+                                 "Connection refused");
+    server->stat.conn_failures++;
+    silc_free(proto_ctx);
+    return;
+  }
   port = server->sockets[(SilcUInt32)proto_ctx->context]->port;
 
   /* Check whether this connection is denied to connect to us. */
@@ -2057,7 +2080,8 @@ void silc_server_packet_parse_type(SilcServer server,
       status = (SilcStatus)packet->buffer->data[0];
       if (packet->buffer->len > 1 &&
          silc_utf8_valid(packet->buffer->data + 1, packet->buffer->len - 1))
-       message = silc_memdup(packet->buffer->data, packet->buffer->len);
+       message = silc_memdup(packet->buffer->data + 1,
+                             packet->buffer->len - 1);
 
       SILC_LOG_ERROR(("Disconnected by %s (%s): %s (%d) %s", 
                      sock->ip, sock->hostname,
index 7b27b6c31def002196c4b01047712288137f9ad1..f0984f40b7606ce638cc359bcdfb49e2e867e50a 100644 (file)
@@ -65,28 +65,28 @@ typedef struct {
 */
 struct SilcServerStruct {
   char *server_name;
-  int server_type;
   int sock;
+  SilcServerEntry id_entry;
   SilcServerID *id;
   unsigned char *id_string;
   SilcUInt32 id_string_len;
-  SilcIdType id_type;
-
   SilcUInt32 starttime;
-  bool standalone;                  /* TRUE if server is standalone, and
+
+  unsigned int server_type    : 2;   /* Server type (server.h) */
+  unsigned int standalone     : 1;   /* Set if server is standalone, and
                                        does not have connection to network. */
-  bool listenning;                  /* TRUE if server is listenning for
+  unsigned int listenning     : 1;   /* Set if server is listenning for
                                        incoming connections. */
-  bool background;
-  SilcServerEntry id_entry;         /* Server's own ID entry */
+  unsigned int background     : 1;   /* Set when server is on background */
+  unsigned int backup_router  : 1;   /* Set if this is backup router */
+  unsigned int backup_primary : 1;   /* Set if we've switched our primary
+                                       router to a backup router. */
+
   SilcServerEntry router;           /* Pointer to the primary router */
   unsigned long router_connect;             /* Time when router was connected */
-  SilcServerBackup backup;          /* Backup routers */
-  bool backup_router;               /* TRUE if this is backup router */
-  bool backup_primary;              /* TRUE if we've switched our primary
-                                       router to a backup router. */
   SilcServerConnection router_conn;  /* non-NULL when connecting to the
                                        primary router, and NULL otherwise. */
+  SilcServerBackup backup;          /* Backup routers */
 
   /* Current command identifier, 0 not used */
   SilcUInt16 cmd_ident;
index 59945b6ece412ab3f45141dfd179852ed4724552..f389f60dd0cfbd78023d6cf91414878c72946591 100644 (file)
@@ -1471,12 +1471,17 @@ void silc_client_close_connection(SilcClient client,
 SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later)
 {
   SilcClient client = (SilcClient)context;
+  SilcClientConnection conn;
   SilcSocketConnection sock;
 
   SILC_CLIENT_GET_SOCK(client, fd, sock);
   if (sock == NULL)
     return;
 
+  conn = (SilcClientConnection)sock->user_data;
+  if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
+    client->internal->ops->disconnect(client, conn);
+
   silc_client_close_connection_real(client, sock, sock->user_data);
 }
 
index d7acdf95834fec56ec665effca95ac3846eeb539..a78f393970907cfdc63f7dc1a3a4f3454da50aa0 100644 (file)
@@ -101,6 +101,7 @@ typedef enum {
 #define SILC_SF_HOST_LOOKUP      5 /* performing host lookup for socket */
 #define SILC_SF_DISABLED         6 /* socket connection is disabled,
                                      no data is sent or received. */
+#define SILC_SF_LISTENER         7
 
 /****s* silcutil/SilcSocketConnectionAPI/SilcSocketConnectionStruct
  *
@@ -215,13 +216,15 @@ struct SilcSocketConnectionStruct {
 #define SILC_SET_DISCONNECTING(x) SF_SET((x), SILC_SF_DISCONNECTING)
 #define SILC_SET_DISCONNECTED(x) SF_SET((x), SILC_SF_DISCONNECTED)
 #define SILC_SET_HOST_LOOKUP(x) SF_SET((x), SILC_SF_HOST_LOOKUP)
-#define SILC_SET_DISABLED(x) SF_SET((x), SILC_SF_HOST_LOOKUP)
+#define SILC_SET_DISABLED(x) SF_SET((x), SILC_SF_DISABLED)
+#define SILC_SET_LISTENER(x) SF_SET((x), SILC_SF_LISTENER)
 #define SILC_UNSET_OUTBUF_PENDING(x) SF_UNSET((x), SILC_SF_OUTBUF_PENDING)
 #define SILC_UNSET_INBUF_PENDING(x) SF_UNSET((x), SILC_SF_INBUF_PENDING)
 #define SILC_UNSET_DISCONNECTING(x) SF_UNSET((x), SILC_SF_DISCONNECTING)
 #define SILC_UNSET_DISCONNECTED(x) SF_UNSET((x), SILC_SF_DISCONNECTED)
 #define SILC_UNSET_HOST_LOOKUP(x) SF_UNSET((x), SILC_SF_HOST_LOOKUP)
 #define SILC_UNSET_DISABLED(x) SF_UNSET((x), SILC_SF_DISABLED)
+#define SILC_UNSET_LISTENER(x) SF_UNSET((x), SILC_SF_LISTENER)
 
 /* Checking for flags */
 #define SILC_IS_OUTBUF_PENDING(x) SF_IS((x), SILC_SF_OUTBUF_PENDING)
@@ -230,6 +233,7 @@ struct SilcSocketConnectionStruct {
 #define SILC_IS_DISCONNECTED(x) SF_IS((x), SILC_SF_DISCONNECTED)
 #define SILC_IS_HOST_LOOKUP(x) SF_IS((x), SILC_SF_HOST_LOOKUP)
 #define SILC_IS_DISABLED(x) SF_IS((x), SILC_SF_DISABLED)
+#define SILC_IS_LISTENER(x) SF_IS((x), SILC_SF_LISTENER)
 
 /* Prototypes */