Fixed silc_server_packet_broadcast to sen correct broadcast
authorPekka Riikonen <priikone@silcnet.org>
Tue, 21 Nov 2000 20:46:12 +0000 (20:46 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 21 Nov 2000 20:46:12 +0000 (20:46 +0000)
packets.
Changed code to use new SilcPacketContext reference count system.
Made joinin working on router connections.

apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/protocol.c
apps/silcd/protocol.h
apps/silcd/server.c
apps/silcd/server_internal.h

index d027389b01878bce964b3a1b159e2627302ec1a7..31a736a1e240cc5c61fe22d7dcf1de1045207d75 100644 (file)
@@ -116,12 +116,12 @@ void silc_server_command_process(SilcServer server,
     SilcClientEntry client = (SilcClientEntry)sock->user_data;
 
     if (!client)
-      goto out;
+      return;
 
     /* Allow only one command executed in 2 seconds. */
     curtime = time(NULL);
     if (client->last_command && (curtime - client->last_command) < 2)
-      goto out;
+      return;
 
     /* Update access time */
     client->last_command = curtime;
@@ -133,13 +133,14 @@ void silc_server_command_process(SilcServer server,
   ctx = silc_calloc(1, sizeof(*ctx));
   ctx->server = server;
   ctx->sock = sock;
-  ctx->packet = packet;        /* Save original packet */
+  ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
   
   /* Parse the command payload in the packet */
   ctx->payload = silc_command_payload_parse(packet->buffer);
   if (!ctx->payload) {
     SILC_LOG_ERROR(("Bad command payload, packet dropped"));
     silc_buffer_free(packet->buffer);
+    silc_packet_context_free(packet);
     silc_free(ctx);
     return;
   }
@@ -162,12 +163,9 @@ void silc_server_command_process(SilcServer server,
 
   if (cmd == NULL) {
     SILC_LOG_ERROR(("Unknown command, packet dropped"));
-    silc_free(ctx);
-    goto out;
+    silc_server_command_free(ctx);
+    return;
   }
-
- out:
-  silc_buffer_free(packet->buffer);
 }
 
 /* Add new pending command to be executed when reply to a command has been
@@ -237,7 +235,10 @@ int silc_server_command_pending_check(SilcServer server,
 static void silc_server_command_free(SilcServerCommandContext cmd)
 {
   if (cmd) {
-    silc_command_free_payload(cmd->payload);
+    if (cmd->payload)
+      silc_command_free_payload(cmd->payload);
+    if (cmd->packet)
+      silc_packet_context_free(cmd->packet);
     silc_free(cmd);
   }
 }
@@ -366,7 +367,7 @@ SILC_SERVER_CMD_FUNC(whois)
 
     /* Send WHOIS command to our router */
     silc_server_packet_send(server, (SilcSocketConnection)
-                           server->id_entry->router->connection,
+                           server->router->connection,
                            SILC_PACKET_COMMAND, cmd->packet->flags,
                            tmpbuf->data, tmpbuf->len, TRUE);
     return;
@@ -592,7 +593,7 @@ SILC_SERVER_CMD_FUNC(identify)
     /* Send IDENTIFY command to our router */
     silc_buffer_push(buffer, buffer->data - buffer->head);
     silc_server_packet_forward(server, (SilcSocketConnection)
-                              server->id_entry->router->connection,
+                              server->router->connection,
                               buffer->data, buffer->len, TRUE);
     return;
   }
@@ -697,18 +698,12 @@ SILC_SERVER_CMD_FUNC(nick)
                           &new_id);
 
   /* Send notify about nickname change to our router. We send the new
-     ID and ask to replace it with the old one. */
-  if (cmd->server->server_type == SILC_SERVER && !cmd->server->standalone)
-    silc_server_send_replace_id(server, server->id_entry->router->connection, 
-                               FALSE, client->id,
-                               SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
-                               new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
-
-  /* If we are router we have to distribute the new Client ID to all 
-     routers in SILC. */
-  if (cmd->server->server_type == SILC_ROUTER && !cmd->server->standalone)
-    silc_server_send_replace_id(server, server->id_entry->router->connection,  
-                               TRUE, client->id,
+     ID and ask to replace it with the old one. If we are router the
+     packet is broadcasted. */
+  if (!cmd->server->standalone)
+    silc_server_send_replace_id(server, server->router->connection, 
+                               server->server_type == SILC_SERVER ? 
+                               FALSE : TRUE, client->id,
                                SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
                                new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
 
@@ -1297,6 +1292,8 @@ silc_server_command_join_channel(SilcServer server,
     client = silc_idlist_find_client_by_id(server->local_list, id);
     if (!client) {
       /* XXX */
+      SILC_LOG_ERROR(("Forwarded join command did not find the client who "
+                     "wanted to join the channel"));
       goto out;
     }
     silc_free(id);
@@ -1407,6 +1404,7 @@ silc_server_command_join_channel(SilcServer server,
       silc_task_register(server->timeout_queue, sock->sock,
                         silc_server_command_join_notify, ctx,
                         0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+      goto out;
     }
 
     /* Send NAMES command reply to the joined channel so the user sees who
@@ -1487,7 +1485,7 @@ SILC_SERVER_CMD_FUNC(join)
        /* Forward the original JOIN command to the router */
        silc_buffer_push(buffer, buffer->data - buffer->head);
        silc_server_packet_forward(server, (SilcSocketConnection)
-                                  server->id_entry->router->connection,
+                                  server->router->connection,
                                   buffer->data, buffer->len, TRUE);
        
        /* Add the command to be pending. It will be re-executed after
@@ -1751,7 +1749,7 @@ SILC_SERVER_CMD_FUNC(cmode)
       if (server->server_type == SILC_SERVER) {
        if (!server->standalone)
          silc_server_packet_send(server, 
-                                 cmd->server->id_entry->router->connection,
+                                 cmd->server->router->connection,
                                  SILC_PACKET_CHANNEL_KEY, 0, packet->data,
                                  packet->len, TRUE);
       } else {
@@ -1921,7 +1919,7 @@ SILC_SERVER_CMD_FUNC(cmode)
       if (server->server_type == SILC_SERVER) {
        if (!server->standalone)
          silc_server_packet_send(server, 
-                                 cmd->server->id_entry->router->connection,
+                                 cmd->server->router->connection,
                                  SILC_PACKET_CHANNEL_KEY, 0, packet->data,
                                  packet->len, TRUE);
       } else {
@@ -1984,7 +1982,7 @@ SILC_SERVER_CMD_FUNC(cmode)
       if (server->server_type == SILC_SERVER) {
        if (!server->standalone)
          silc_server_packet_send(server, 
-                                 cmd->server->id_entry->router->connection,
+                                 cmd->server->router->connection,
                                  SILC_PACKET_CHANNEL_KEY, 0, packet->data,
                                  packet->len, TRUE);
       } else {
@@ -2287,7 +2285,7 @@ SILC_SERVER_CMD_FUNC(leave)
      of clients on the channel. */
   if (!server->standalone)
     silc_server_send_remove_channel_user(server, 
-                                        server->id_entry->router->connection,
+                                        server->router->connection,
                                         server->server_type == SILC_ROUTER ?
                                         TRUE : FALSE, id_entry->id, id);
 
@@ -2326,7 +2324,7 @@ SILC_SERVER_CMD_FUNC(leave)
   if (server->server_type == SILC_SERVER) {
     if (!server->standalone)
       silc_server_packet_send(server, 
-                             cmd->server->id_entry->router->connection,
+                             cmd->server->router->connection,
                              SILC_PACKET_CHANNEL_KEY, 0, packet->data,
                              packet->len, TRUE);
   } else {
index 83eb257cfce88e0299ac71fe4c143eb11cd64279..64d099fd277df0f207c64aee985d21a02e21377f 100644 (file)
@@ -277,7 +277,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
   /* Add the channel to our local list. */
   entry = silc_idlist_add_channel(server->local_list, channel_name, 
                                  SILC_CHANNEL_MODE_NONE, id, 
-                                 server->id_entry->router, NULL);
+                                 server->router, NULL);
   if (!entry) {
     silc_free(channel_name);
     silc_free(id);
index 6bfef69e912a7bcb1aa3c2acea418784385cff22..685b5ab654250a9c5ff10b64d9db5566c23710dd 100644 (file)
@@ -160,7 +160,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
           properties packet from initiator. */
        status = silc_ske_responder_start(ske, ctx->rng, ctx->sock,
                                          silc_version_string,
-                                         ctx->packet, NULL, NULL);
+                                         ctx->packet->buffer, NULL, NULL);
       } else {
        SilcSKEStartPayload *start_payload;
 
@@ -211,10 +211,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
           paylaod reply we just got from the responder. The callback
           function will receive the processed payload where we will
           save it. */
-       status = 
-         silc_ske_initiator_phase_1(ctx->ske,
-                                    ctx->packet,
-                                    NULL, NULL);
+       status = silc_ske_initiator_phase_1(ctx->ske, ctx->packet->buffer,
+                                           NULL, NULL);
       }
 
       if (status != SILC_SKE_STATUS_OK) {
@@ -243,8 +241,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
        /* Process the received Key Exchange 1 Payload packet from
           the initiator. This also creates our parts of the Diffie
           Hellman algorithm. */
-       status = 
-         silc_ske_responder_phase_2(ctx->ske, ctx->packet, NULL, NULL);
+       status = silc_ske_responder_phase_2(ctx->ske, ctx->packet->buffer, 
+                                           NULL, NULL);
       } else {
        /* Call the Phase-2 function. This creates Diffie Hellman
           key exchange parameters and sends our public part inside
@@ -290,9 +288,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
       } else {
        /* Finish the protocol. This verifies the Key Exchange 2 payload
           sent by responder. */
-       status = 
-         silc_ske_initiator_finish(ctx->ske,
-                                   ctx->packet, NULL, NULL, NULL, NULL);
+       status = silc_ske_initiator_finish(ctx->ske, ctx->packet->buffer, 
+                                          NULL, NULL, NULL, NULL);
       }
 
       if (status != SILC_SKE_STATUS_OK) {
@@ -509,12 +506,12 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth)
 
        /* Parse the received authentication data packet. The received
           payload is Connection Auth Payload. */
-       silc_buffer_unformat(ctx->packet,
+       silc_buffer_unformat(ctx->packet->buffer,
                             SILC_STR_UI_SHORT(&payload_len),
                             SILC_STR_UI_SHORT(&conn_type),
                             SILC_STR_END);
        
-       if (payload_len != ctx->packet->len) {
+       if (payload_len != ctx->packet->buffer->len) {
          SILC_LOG_ERROR(("Bad payload in authentication packet"));
          SILC_LOG_DEBUG(("Bad payload in authentication packet"));
          protocol->state = SILC_PROTOCOL_STATE_ERROR;
@@ -535,8 +532,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth)
        
        if (payload_len > 0) {
          /* Get authentication data */
-         silc_buffer_pull(ctx->packet, 4);
-         silc_buffer_unformat(ctx->packet,
+         silc_buffer_pull(ctx->packet->buffer, 4);
+         silc_buffer_unformat(ctx->packet->buffer,
                               SILC_STR_UI_XNSTRING_ALLOC(&auth_data, 
                                                          payload_len),
                               SILC_STR_END);
index 7748faa19f007e854b1b36ec6f75edbf5a1b4d21..a4ea9b36548d62494934ebb8dbd41628dd1d062f 100644 (file)
@@ -43,7 +43,7 @@ typedef struct {
   SilcIdType dest_id_type;
 
   SilcTask timeout_task;
-  SilcBuffer packet;
+  SilcPacketContext *packet;
   SilcSKE ske;
 } SilcServerKEInternalContext;
 
@@ -75,7 +75,7 @@ typedef struct {
   SilcIdType dest_id_type;
 
   SilcTask timeout_task;
-  SilcBuffer packet;
+  SilcPacketContext *packet;
   unsigned short conn_type;
 } SilcServerConnAuthInternalContext;
 
index ec5359bcac9632f5be132ccf37786d9408236a9d..f2b7e17ae987e992f237514f97591c3b6f7ef78d 100644 (file)
@@ -585,7 +585,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
     /* Error occured during protocol */
     silc_protocol_free(protocol);
     if (ctx->packet)
-      silc_buffer_free(ctx->packet);
+      silc_packet_context_free(ctx->packet);
     if (ctx->ske)
       silc_ske_free(ctx->ske);
     if (ctx->dest_id)
@@ -634,7 +634,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
   /* Free old protocol as it is finished now */
   silc_protocol_free(protocol);
   if (ctx->packet)
-    silc_buffer_free(ctx->packet);
+    silc_packet_context_free(ctx->packet);
   silc_free(ctx);
   sock->protocol = NULL;
 
@@ -738,6 +738,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
   sock->user_data = (void *)id_entry;
   sock->type = SILC_SOCKET_TYPE_ROUTER;
   server->id_entry->router = id_entry;
+  server->router = id_entry;
 
  out:
   /* Free the temporary connection data context */
@@ -747,7 +748,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
   /* Free the protocol object */
   silc_protocol_free(protocol);
   if (ctx->packet)
-    silc_buffer_free(ctx->packet);
+    silc_packet_context_free(ctx->packet);
   if (ctx->ske)
     silc_ske_free(ctx->ske);
   silc_free(ctx);
@@ -863,7 +864,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_second)
     /* Error occured during protocol */
     silc_protocol_free(protocol);
     if (ctx->packet)
-      silc_buffer_free(ctx->packet);
+      silc_packet_context_free(ctx->packet);
     if (ctx->ske)
       silc_ske_free(ctx->ske);
     if (ctx->dest_id)
@@ -889,7 +890,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_second)
   /* Free old protocol as it is finished now */
   silc_protocol_free(protocol);
   if (ctx->packet)
-    silc_buffer_free(ctx->packet);
+    silc_packet_context_free(ctx->packet);
   silc_free(ctx);
   sock->protocol = NULL;
 
@@ -931,7 +932,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
     /* Error occured during protocol */
     silc_protocol_free(protocol);
     if (ctx->packet)
-      silc_buffer_free(ctx->packet);
+      silc_packet_context_free(ctx->packet);
     if (ctx->ske)
       silc_ske_free(ctx->ske);
     if (ctx->dest_id)
@@ -1002,8 +1003,10 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
       if (server->standalone && sock->type == SILC_SOCKET_TYPE_ROUTER) {
        SILC_LOG_DEBUG(("We are not standalone server anymore"));
        server->standalone = FALSE;
-       if (!server->id_entry->router)
+       if (!server->id_entry->router) {
          server->id_entry->router = id_entry;
+         server->router = id_entry;
+       }
       }
       break;
     }
@@ -1024,7 +1027,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
 
   silc_protocol_free(protocol);
   if (ctx->packet)
-    silc_buffer_free(ctx->packet);
+    silc_packet_context_free(ctx->packet);
   if (ctx->ske)
     silc_ske_free(ctx->ske);
   if (ctx->dest_id)
@@ -1195,8 +1198,7 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
   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);
+    silc_server_packet_broadcast(server, server->router->connection, packet);
   }
 
   /* Parse the incoming packet type */
@@ -1204,11 +1206,7 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
 
  out:
   silc_buffer_clear(sock->inbuf);
-  if (packet->src_id)
-    silc_free(packet->src_id);
-  if (packet->dst_id)
-    silc_free(packet->dst_id);
-  silc_free(packet);
+  silc_packet_context_free(packet);
   silc_free(parse_ctx);
 }
 
@@ -1251,7 +1249,6 @@ void silc_server_packet_parse_type(SilcServer server,
                                   SilcSocketConnection sock,
                                   SilcPacketContext *packet)
 {
-  SilcBuffer buffer = packet->buffer;
   SilcPacketType type = packet->type;
 
   SILC_LOG_DEBUG(("Parsing packet type %d", type));
@@ -1261,6 +1258,7 @@ void silc_server_packet_parse_type(SilcServer server,
   case SILC_PACKET_DISCONNECT:
     SILC_LOG_DEBUG(("Disconnect packet"));
     break;
+
   case SILC_PACKET_SUCCESS:
     /*
      * Success received for something. For now we can have only
@@ -1273,6 +1271,7 @@ void silc_server_packet_parse_type(SilcServer server,
                              sock->protocol, sock->sock, 0, 0);
     }
     break;
+
   case SILC_PACKET_FAILURE:
     /*
      * Failure received for something. For now we can have only
@@ -1287,11 +1286,19 @@ void silc_server_packet_parse_type(SilcServer server,
                              sock->protocol, sock->sock, 0, 0);
     }
     break;
+
   case SILC_PACKET_REJECT:
     SILC_LOG_DEBUG(("Reject packet"));
     return;
     break;
 
+  case SILC_PACKET_NOTIFY:
+    /*
+     * Received notify packet.
+     */
+    SILC_LOG_DEBUG(("Notify packet"));
+    break;
+
     /* 
      * Channel packets
      */
@@ -1364,7 +1371,7 @@ void silc_server_packet_parse_type(SilcServer server,
       SilcServerKEInternalContext *proto_ctx = 
        (SilcServerKEInternalContext *)sock->protocol->context;
 
-      proto_ctx->packet = buffer;
+      proto_ctx->packet = silc_packet_context_dup(packet);
 
       /* Let the protocol handle the packet */
       sock->protocol->execute(server->timeout_queue, 0, 
@@ -1386,9 +1393,9 @@ void silc_server_packet_parse_type(SilcServer server,
        (SilcServerKEInternalContext *)sock->protocol->context;
 
       if (proto_ctx->packet)
-       silc_buffer_free(proto_ctx->packet);
+       silc_packet_context_free(proto_ctx->packet);
 
-      proto_ctx->packet = buffer;
+      proto_ctx->packet = silc_packet_context_dup(packet);
       proto_ctx->dest_id_type = packet->src_id_type;
       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
 
@@ -1411,9 +1418,9 @@ void silc_server_packet_parse_type(SilcServer server,
        (SilcServerKEInternalContext *)sock->protocol->context;
 
       if (proto_ctx->packet)
-       silc_buffer_free(proto_ctx->packet);
+       silc_packet_context_free(proto_ctx->packet);
 
-      proto_ctx->packet = buffer;
+      proto_ctx->packet = silc_packet_context_dup(packet);
       proto_ctx->dest_id_type = packet->src_id_type;
       proto_ctx->dest_id = silc_id_str2id(packet->src_id, packet->src_id_type);
 
@@ -1431,6 +1438,8 @@ void silc_server_packet_parse_type(SilcServer server,
     /* If we receive this packet we will send to the other end information
        about our mandatory authentication method for the connection. 
        This packet maybe received at any time. */
+    SILC_LOG_DEBUG(("Connection authentication request packet"));
+    break;
 
     /*
      * Connection Authentication protocol packets
@@ -1445,7 +1454,7 @@ void silc_server_packet_parse_type(SilcServer server,
       SilcServerConnAuthInternalContext *proto_ctx = 
        (SilcServerConnAuthInternalContext *)sock->protocol->context;
 
-      proto_ctx->packet = buffer;
+      proto_ctx->packet = silc_packet_context_dup(packet);
 
       /* Let the protocol handle the packet */
       sock->protocol->execute(server->timeout_queue, 0, 
@@ -1510,6 +1519,10 @@ void silc_server_packet_parse_type(SilcServer server,
     break;
 
   case SILC_PACKET_REMOVE_ID:
+    /*
+     * Received remove ID Packet. 
+     */
+    SILC_LOG_DEBUG(("Remove ID packet"));
     break;
 
   case SILC_PACKET_REMOVE_CHANNEL_USER:
@@ -1703,8 +1716,7 @@ void silc_server_packet_forward(SilcServer server,
 /* 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. */
+   function. This does not test or set the broadcast flag. */
 
 void silc_server_packet_broadcast(SilcServer server,
                                  SilcSocketConnection sock,
@@ -1719,9 +1731,11 @@ void silc_server_packet_broadcast(SilcServer server,
   /* 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)) {
+  if (id && SILC_ID_SERVER_COMPARE(id, server->router->id)) {
     idata = (SilcIDListData)sock->user_data;
-    silc_packet_send_prepare(sock, 0, 0, buffer->len);
+
+    silc_buffer_push(buffer, buffer->data - buffer->head);
+    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);
@@ -1834,7 +1848,7 @@ void silc_server_packet_send_to_channel(SilcServer server,
     SilcServerEntry router;
 
     /* Get data used in packet header encryption, keys and stuff. */
-    router = server->id_entry->router;
+    router = server->router;
     sock = (SilcSocketConnection)router->connection;
     idata = (SilcIDListData)router;
     
@@ -1952,7 +1966,7 @@ void silc_server_packet_relay_to_channel(SilcServer server,
       channel->global_users) {
     SilcServerEntry router;
 
-    router = server->id_entry->router;
+    router = server->router;
 
     /* Check that the sender is not our router. */
     if (sender_sock != (SilcSocketConnection)router->connection) {
@@ -2101,11 +2115,11 @@ void silc_server_packet_relay_command_reply(SilcServer server,
   /* Source must be server or router */
   if (packet->src_id_type != SILC_ID_SERVER &&
       sock->type != SILC_SOCKET_TYPE_ROUTER)
-    goto out;
+    return;
 
   /* Destination must be client */
   if (packet->dst_id_type != SILC_ID_CLIENT)
-    goto out;
+    return;
 
   /* Execute command reply locally for the command */
   silc_server_command_reply_process(server, sock, buffer);
@@ -2115,8 +2129,9 @@ void silc_server_packet_relay_command_reply(SilcServer server,
   /* Destination must be one of ours */
   client = silc_idlist_find_client_by_id(server->local_list, id);
   if (!client) {
+    SILC_LOG_ERROR(("Cannot relay command reply to unknown client"));
     silc_free(id);
-    goto out;
+    return;
   }
 
   /* Relay the packet to the client */
@@ -2135,12 +2150,9 @@ void silc_server_packet_relay_command_reply(SilcServer server,
                      buffer->len);
     
   /* Send the packet */
-  silc_server_packet_send_real(server, dst_sock, FALSE);
+  silc_server_packet_send_real(server, dst_sock, TRUE);
 
   silc_free(id);
-
- out:
-  silc_buffer_free(buffer);
 }
 
 /* Closes connection to socket connection */
@@ -2441,7 +2453,6 @@ void silc_server_private_message(SilcServer server,
                                 SilcSocketConnection sock,
                                 SilcPacketContext *packet)
 {
-  SilcBuffer buffer = packet->buffer;
   SilcClientID *id;
   SilcServerEntry router;
   SilcSocketConnection dst_sock;
@@ -2483,7 +2494,7 @@ void silc_server_private_message(SilcServer server,
                                                idata->send_key,
                                                idata->hmac,
                                                packet);
-      goto out;
+      return;
     }
 
     /* Seems that client really is directly connected to us */
@@ -2491,13 +2502,13 @@ void silc_server_private_message(SilcServer server,
     silc_server_private_message_send_internal(server, dst_sock, 
                                              idata->send_key,
                                              idata->hmac, packet);
-    goto out;
+    return;
   }
 
   /* Destination belongs to someone not in this server. If we are normal
      server our action is to send the packet to our router. */
   if (server->server_type == SILC_SERVER && !server->standalone) {
-    router = server->id_entry->router;
+    router = server->router;
 
     /* Send to primary route */
     if (router) {
@@ -2507,7 +2518,7 @@ void silc_server_private_message(SilcServer server,
                                                idata->send_key,
                                                idata->hmac, packet);
     }
-    goto out;
+    return;
   }
 
   /* We are router and we will perform route lookup for the destination 
@@ -2522,15 +2533,12 @@ void silc_server_private_message(SilcServer server,
       silc_server_private_message_send_internal(server, dst_sock, 
                                                idata->send_key,
                                                idata->hmac, packet);
-
-    goto out;
+    return;
   }
 
  err:
   silc_server_send_error(server, sock, 
                         "No such nickname: Private message not sent");
- out:
-  silc_buffer_free(buffer);
 }
 
 /* Process received channel message. The message can be originated from
@@ -2544,7 +2552,6 @@ void silc_server_channel_message(SilcServer server,
   SilcChannelClientEntry chl;
   SilcChannelID *id = NULL;
   void *sender = NULL;
-  SilcBuffer buffer = packet->buffer;
 
   SILC_LOG_DEBUG(("Processing channel message"));
 
@@ -2591,7 +2598,6 @@ void silc_server_channel_message(SilcServer server,
     silc_free(sender);
   if (id)
     silc_free(id);
-  silc_buffer_free(buffer);
 }
 
 /* Received channel key packet. We distribute the key to all of our locally
@@ -2608,7 +2614,6 @@ void silc_server_channel_key(SilcServer server,
   SilcChannelID *id = NULL;
   SilcChannelEntry channel;
   SilcChannelClientEntry chl;
-  SilcClientEntry client;
   unsigned char *tmp;
   unsigned int tmp_len;
   char *cipher;
@@ -2647,31 +2652,24 @@ void silc_server_channel_key(SilcServer server,
   if (!silc_cipher_alloc(cipher, &channel->channel_key))
     goto out;
 
-  channel->key_len = tmp_len * 8;
-  channel->key = silc_calloc(tmp_len, sizeof(unsigned char));
-  memcpy(channel->key, tmp, tmp_len);
-  channel->channel_key->cipher->set_key(channel->channel_key->context, 
-                                       tmp, tmp_len);
-
   /* Distribute the key to all clients on the channel */
-  /* XXX Some other sender should be used, I think this is not correct */
   silc_list_start(channel->user_list);
   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
-    client = chl->client;
-
-    if (client)
-      silc_server_packet_send_dest(server, client->connection,
-                                  SILC_PACKET_CHANNEL_KEY, 0,
-                                  client->id, SILC_ID_CLIENT,
-                                  buffer->data, buffer->len, FALSE);
+    silc_server_packet_send(server, chl->client->connection,
+                           SILC_PACKET_CHANNEL_KEY, 0,
+                           buffer->data, buffer->len, TRUE);
   }
 
+  channel->key_len = tmp_len * 8;
+  channel->key = silc_calloc(tmp_len, sizeof(unsigned char));
+  memcpy(channel->key, tmp, tmp_len);
+  channel->channel_key->cipher->set_key(channel->channel_key->context, 
+                                       tmp, tmp_len);
  out:
   if (id)
     silc_free(id);
   if (payload)
     silc_channel_key_payload_free(payload);
-  silc_buffer_free(buffer);
 }
 
 /* Sends current motd to client */
@@ -3062,6 +3060,19 @@ void silc_server_replace_id(SilcServer server,
   if (!id2)
     goto out;
 
+  /* If we are router and this packet is not already broadcast packet
+     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->server_type == SILC_ROUTER &&
+      sock->type == SILC_SOCKET_TYPE_SERVER &&
+      !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+    SILC_LOG_DEBUG(("Broadcasting received Replace ID packet"));
+    silc_server_packet_send(server, server->router->connection, packet->type,
+                           packet->flags | SILC_PACKET_FLAG_BROADCAST, 
+                           buffer->data, buffer->len, FALSE);
+  }
+
   /* Replace the old ID */
   switch(old_id_type) {
   case SILC_ID_CLIENT:
@@ -3141,7 +3152,7 @@ SilcChannelEntry silc_server_new_channel(SilcServer server,
   /* Notify other routers about the new channel. We send the packet
      to our primary route. */
   if (server->standalone == FALSE) {
-    silc_server_send_new_id(server, server->id_entry->router->connection,
+    silc_server_send_new_id(server, server->router->connection,
                            server->server_type == SILC_SERVER ? FALSE : TRUE,
                            entry->id, SILC_ID_CHANNEL, SILC_ID_CHANNEL_LEN);
   }
@@ -3207,7 +3218,7 @@ SilcClientEntry silc_server_new_client(SilcServer server,
   /* Notify our router about new client on the SILC network */
   if (!server->standalone)
     silc_server_send_new_id(server, (SilcSocketConnection) 
-                           server->id_entry->router->connection, 
+                           server->router->connection, 
                            server->server_type == SILC_ROUTER ? TRUE : FALSE,
                            client->id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
   
@@ -3316,8 +3327,8 @@ SilcServerEntry silc_server_new_server(SilcServer server,
      to our router. If we are normal server we won't send anything
      since this connection must be our router connection. */
   if (server->server_type == SILC_ROUTER && !server->standalone &&
-      server->id_entry->router->connection != sock)
-    silc_server_send_new_id(server, server->id_entry->router->connection,
+      server->router->connection != sock)
+    silc_server_send_new_id(server, server->router->connection,
                            TRUE, new_server->id, SILC_ID_SERVER, 
                            SILC_ID_SERVER_LEN);
 
@@ -3362,10 +3373,11 @@ void silc_server_new_id(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. */
-  if (!server->standalone && sock->type == SILC_SOCKET_TYPE_SERVER &&
-      server->server_type == SILC_ROUTER) {
+  if (!server->standalone && 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->id_entry->router->connection,
+    silc_server_packet_send(server, server->router->connection,
                            packet->type, 
                            packet->flags | SILC_PACKET_FLAG_BROADCAST,
                            buffer->data, buffer->len, FALSE);
@@ -3384,8 +3396,8 @@ void silc_server_new_id(SilcServer server, SilcSocketConnection sock,
     /*    router = server->id_entry; */
   } else {
     id_list = server->global_list;
-    router_sock = (SilcSocketConnection)server->id_entry->router->connection;
-    router = server->id_entry->router;
+    router_sock = (SilcSocketConnection)server->router->connection;
+    router = server->router;
   }
 
   silc_free(tmpid);
@@ -3476,6 +3488,19 @@ void silc_server_remove_channel_user(SilcServer server,
   if (!client_id || !channel_id)
     goto out;
 
+  /* If we are router and this packet is not already broadcast packet
+     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 &&
+      sock->type == SILC_SOCKET_TYPE_SERVER &&
+      !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+    SILC_LOG_DEBUG(("Broadcasting received Remove Channel User packet"));
+    silc_server_packet_send(server, server->router->connection, packet->type,
+                           packet->flags | SILC_PACKET_FLAG_BROADCAST, 
+                           buffer->data, buffer->len, FALSE);
+  }
+
   /* XXX routers should check server->global_list as well */
   /* Get channel entry */
   channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
index 7278c6a3c6e94b503c010d2676670781707ad8ad..429988c4a001d667ac1e6778080954e4bed5e6cb 100644 (file)
@@ -56,8 +56,13 @@ struct SilcServerStruct {
   int listenning;
   SilcServerID *id;
   SilcIdType id_type;
+
+  /* Server's own ID entry. */
   SilcServerEntry id_entry;
 
+  /* Back pointer to the primary router of this server. */
+  SilcServerEntry router;
+
   /* SILC server task queues */
   SilcTaskQueue io_queue;
   SilcTaskQueue timeout_queue;