Implemented CHANNEL_UMODE_QUEIT mode. Fixed fatal bugs in server.
[silc.git] / apps / silcd / packet_receive.c
index 9a0a7ba802671f962dc7216466d5dc2f1b7e9b57..67454f94e9bd49bf01130f8da8fdf41d6330bc0b 100644 (file)
@@ -86,7 +86,7 @@ void silc_server_notify(SilcServer server,
      we will broadcast it. The sending socket really cannot be router or
      the router is buggy. If this packet is coming from router then it must
      have the broadcast flag set already and we won't do anything. */
-  if (!server->standalone && server->server_type == SILC_ROUTER &&
+  if (server->server_type == SILC_ROUTER &&
       sock->type == SILC_SOCKET_TYPE_SERVER &&
       !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
     SILC_LOG_DEBUG(("Broadcasting received Notify packet"));
@@ -97,12 +97,13 @@ void silc_server_notify(SilcServer server,
       if (!channel_id)
        goto out;
 
-      silc_server_packet_send_dest(server, server->router->connection, 
-                                  packet->type,
-                                  packet->flags | SILC_PACKET_FLAG_BROADCAST, 
-                                  channel_id, SILC_ID_CHANNEL,
-                                  packet->buffer->data, packet->buffer->len, 
-                                  FALSE);
+      if (!server->standalone)
+       silc_server_packet_send_dest(server, server->router->connection, 
+                                    packet->type, packet->flags | 
+                                    SILC_PACKET_FLAG_BROADCAST, 
+                                    channel_id, SILC_ID_CHANNEL,
+                                    packet->buffer->data, 
+                                    packet->buffer->len, FALSE);
       silc_server_backup_send_dest(server, (SilcServerEntry)sock->user_data, 
                                   packet->type, packet->flags,
                                   channel_id, SILC_ID_CHANNEL,
@@ -110,11 +111,12 @@ void silc_server_notify(SilcServer server,
                                   FALSE, TRUE);
     } else {
       /* Packet is destined to client or server */
-      silc_server_packet_send(server, server->router->connection, 
-                             packet->type,
-                             packet->flags | SILC_PACKET_FLAG_BROADCAST, 
-                             packet->buffer->data, packet->buffer->len, 
-                             FALSE);
+      if (!server->standalone)
+       silc_server_packet_send(server, server->router->connection, 
+                               packet->type,
+                               packet->flags | SILC_PACKET_FLAG_BROADCAST, 
+                               packet->buffer->data, packet->buffer->len, 
+                               FALSE);
       silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
                              packet->type, packet->flags,
                              packet->buffer->data, packet->buffer->len, 
@@ -554,6 +556,20 @@ void silc_server_notify(SilcServer server,
        SILC_LOG_DEBUG(("CMODE change is not allowed"));
        goto out;
       }
+    } else {
+      if (server->server_type == SILC_ROUTER &&
+         channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH &&
+         !(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
+       SILC_LOG_DEBUG(("Enforcing sender to change channel mode"));
+       silc_server_send_notify_cmode(server, sock, FALSE, channel,
+                                     channel->mode, server->id,
+                                     SILC_ID_SERVER,
+                                     channel->cipher,
+                                     channel->hmac_name,
+                                     channel->passphrase,
+                                     channel->founder_key);
+       goto out;
+      }
     }
 
     /* Send the same notify to the channel */
@@ -744,7 +760,7 @@ void silc_server_notify(SilcServer server,
        if (!silc_server_client_on_channel(client, channel, &chl))
          goto out;
        
-       if (client != client2) {
+       if (client != client2 && server->server_type == SILC_ROUTER) {
          /* Sender must be operator */
          if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
              !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
@@ -752,7 +768,6 @@ void silc_server_notify(SilcServer server,
            goto out;
          }
 
-         /* Check that target is on channel */
          if (!silc_server_client_on_channel(client2, channel, &chl))
            goto out;
 
@@ -764,7 +779,29 @@ void silc_server_notify(SilcServer server,
        }
       }
 
+      /* Get target channel 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
@@ -813,7 +850,7 @@ void silc_server_notify(SilcServer server,
 
        /* Now match the public key we have cached and public key sent.
           They must match. */
-       if (client && client->data.public_key && 
+       if (client->data.public_key && 
            !silc_pkcs_public_key_compare(channel->founder_key,
                                          client->data.public_key)) {
          mode &= ~SILC_CHANNEL_UMODE_CHANFO;
@@ -1850,6 +1887,10 @@ void silc_server_channel_message(SilcServer server,
       SILC_LOG_DEBUG(("Channel is silenced from operators"));
       goto out;
     }
+    if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
+      SILC_LOG_DEBUG(("Sender is quieted on the channel"));
+      goto out;
+    }
 
     /* If the packet is coming from router, but the client entry is local 
        entry to us then some router is rerouting this to us and it is not 
@@ -2105,7 +2146,15 @@ SilcClientEntry silc_server_new_client(SilcServer server,
                            server->router->connection, 
                            server->server_type == SILC_ROUTER ? TRUE : FALSE,
                            client->id, SILC_ID_CLIENT, id_len);
-  
+
+  /* Distribute to backup routers */
+  if (server->server_type == SILC_ROUTER) {
+    SilcBuffer idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+    silc_server_backup_send(server, NULL, SILC_PACKET_NEW_ID, 0,
+                           idp->data, idp->len, FALSE, TRUE);
+    silc_buffer_free(idp);
+  }
+
   /* Send the new client ID to the client. */
   silc_server_send_new_id(server, sock, FALSE, client->id, SILC_ID_CLIENT,
                          silc_id_get_len(client->id, SILC_ID_CLIENT));
@@ -2258,8 +2307,16 @@ SilcServerEntry silc_server_new_server(SilcServer server,
                            TRUE, new_server->id, SILC_ID_SERVER, 
                            silc_id_get_len(server_id, SILC_ID_SERVER));
 
-  if (server->server_type == SILC_ROUTER)
+  if (server->server_type == SILC_ROUTER) {
+    /* Distribute to backup routers */
+    SilcBuffer idp = silc_id_payload_encode(new_server->id, SILC_ID_SERVER);
+    silc_server_backup_send(server, NULL, SILC_PACKET_NEW_ID, 0,
+                           idp->data, idp->len, FALSE, TRUE);
+    silc_buffer_free(idp);
+
+    /* Statistics */
     server->stat.cell_servers++;
+  }
 
   /* Check whether this router connection has been replaced by an
      backup router. If it has been then we'll disable the server and will
@@ -2478,14 +2535,15 @@ static void silc_server_new_id_real(SilcServer server,
 
   /* 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 (broadcast && !server->standalone && server->server_type == SILC_ROUTER &&
+  if (broadcast && server->server_type == SILC_ROUTER &&
       sock->type == SILC_SOCKET_TYPE_SERVER &&
       !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
     SILC_LOG_DEBUG(("Broadcasting received New ID packet"));
-    silc_server_packet_send(server, server->router->connection,
-                           packet->type, 
-                           packet->flags | SILC_PACKET_FLAG_BROADCAST,
-                           buffer->data, buffer->len, FALSE);
+    if (!server->standalone)
+      silc_server_packet_send(server, server->router->connection,
+                             packet->type, 
+                             packet->flags | SILC_PACKET_FLAG_BROADCAST,
+                             buffer->data, buffer->len, FALSE);
     silc_server_backup_send(server, (SilcServerEntry)sock->user_data, 
                            packet->type, packet->flags,
                            packet->buffer->data, packet->buffer->len, 
@@ -2525,14 +2583,16 @@ void silc_server_new_id_list(SilcServer server, SilcSocketConnection sock,
   /* If the sender of this packet is server and we are router we need to
      broadcast this packet to other routers in the network. Broadcast
      this list packet instead of multiple New ID packets. */
-  if (!server->standalone && server->server_type == SILC_ROUTER &&
+  if (server->server_type == SILC_ROUTER &&
       sock->type == SILC_SOCKET_TYPE_SERVER &&
       !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
     SILC_LOG_DEBUG(("Broadcasting received New ID List packet"));
-    silc_server_packet_send(server, server->router->connection,
-                           packet->type, 
-                           packet->flags | SILC_PACKET_FLAG_BROADCAST,
-                           packet->buffer->data, packet->buffer->len, FALSE);
+    if (!server->standalone)
+      silc_server_packet_send(server, server->router->connection,
+                             packet->type, 
+                             packet->flags | SILC_PACKET_FLAG_BROADCAST,
+                             packet->buffer->data, 
+                             packet->buffer->len, FALSE);
     silc_server_backup_send(server, (SilcServerEntry)sock->user_data, 
                            packet->type, packet->flags,
                            packet->buffer->data, packet->buffer->len, 
@@ -2823,14 +2883,16 @@ void silc_server_new_channel_list(SilcServer server,
   /* If the sender of this packet is server and we are router we need to
      broadcast this packet to other routers in the network. Broadcast
      this list packet instead of multiple New Channel packets. */
-  if (!server->standalone && server->server_type == SILC_ROUTER &&
+  if (server->server_type == SILC_ROUTER &&
       sock->type == SILC_SOCKET_TYPE_SERVER &&
       !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
     SILC_LOG_DEBUG(("Broadcasting received New Channel List packet"));
-    silc_server_packet_send(server, server->router->connection,
-                           packet->type, 
-                           packet->flags | SILC_PACKET_FLAG_BROADCAST,
-                           packet->buffer->data, packet->buffer->len, FALSE);
+    if (!server->standalone)
+      silc_server_packet_send(server, server->router->connection,
+                             packet->type, 
+                             packet->flags | SILC_PACKET_FLAG_BROADCAST,
+                             packet->buffer->data, 
+                             packet->buffer->len, FALSE);
     silc_server_backup_send(server, (SilcServerEntry)sock->user_data, 
                            packet->type, packet->flags,
                            packet->buffer->data, packet->buffer->len, 
@@ -3314,6 +3376,7 @@ void silc_server_resume_client(SilcServer server,
     server->stat.clients--;
     if (server->stat.cell_clients)
       server->stat.cell_clients--;
+    silc_server_del_from_watcher_list(server, client);
     silc_idlist_del_client(server->local_list, client);
     client = detached_client;
 
@@ -3529,14 +3592,15 @@ void silc_server_resume_client(SilcServer server,
 
     /* 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 && server->server_type == SILC_ROUTER &&
+    if (server->server_type == SILC_ROUTER &&
        sock->type == SILC_SOCKET_TYPE_SERVER &&
        !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
       SILC_LOG_DEBUG(("Broadcasting received Resume Client packet"));
-      silc_server_packet_send(server, server->router->connection,
-                             packet->type, 
-                             packet->flags | SILC_PACKET_FLAG_BROADCAST,
-                             buffer->data, buffer->len, FALSE);
+      if (!server->standalone)
+       silc_server_packet_send(server, server->router->connection,
+                               packet->type, 
+                               packet->flags | SILC_PACKET_FLAG_BROADCAST,
+                               buffer->data, buffer->len, FALSE);
       silc_server_backup_send(server, (SilcServerEntry)sock->user_data, 
                              packet->type, packet->flags,
                              packet->buffer->data, packet->buffer->len,