updates.
authorPekka Riikonen <priikone@silcnet.org>
Mon, 29 Oct 2001 19:26:11 +0000 (19:26 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 29 Oct 2001 19:26:11 +0000 (19:26 +0000)
16 files changed:
CHANGES
TODO
apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/idlist.h
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/packet_send.h
apps/silcd/server.c
apps/silcd/server_util.c
apps/silcd/silcd.c
doc/draft-riikonen-silc-pp-04.nroff
lib/silcclient/client_ftp.c
lib/silcclient/client_prvmsg.c
lib/silcclient/idlist.c
lib/silccore/silcpacket.c

diff --git a/CHANGES b/CHANGES
index b5fe2a1d55d2ac2ffbc4d012c0328b71b605e6d3..fa52bbf6c5b5c94d57bce697b74eb68ba62e438e 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -18,6 +18,22 @@ Mon Oct 29 17:43:04 EST 2001  Pekka Riikonen <priikone@silcnet.org>
        * Fixed a crash in client resolving in client_prvmsg.c in 
          client library.  Affected file lib/silcclient/client_prvmsg.c.
 
+       * Do not actually remove the client directly from ID cache
+         during SERVER_SIGNOFF, but invalidate it.  This way we
+         preserve the WHOWAS info for the client.  Affected file
+         silcd/server_util.c.
+
+       * Fixed SERVER_SIGNOFF notify handling in the server.  The
+         server is now able to process incoming SERVER_SIGNOFF notify
+         for a server that it doesn't even know about.  It will remove
+         the clients provided in the notify.  Affected file
+         silcd/packet_receive.c.
+
+       * Check for partial packet in data queue after every packet that
+         was found from the queue.  Return and wait for more data if 
+         there is partial data in queue.  Affecte file is
+         lib/silccore/silcpacket.c.
+
 Sun Oct 28 18:46:27 EST 2001  Pekka Riikonen <priikone@silcnet.org>
 
        * Added SilcClietFileError enum to indicate error in
diff --git a/TODO b/TODO
index feb6e8bcd69032d75863e34d67b6f30ee8c1066c..c601c8dd33efd29edc1ab12495b822caff5a410d 100644 (file)
--- a/TODO
+++ b/TODO
@@ -47,8 +47,6 @@ TODO/bugs In SILC Server
  o After backup resume protocol the TOPIC_SET was not handled correctly
    by all (unknown Channel ID).
 
- o Server signoff notifys does not go to normal servers from routers.
-
  o Channel user mode changes are notified unnecessarely when switching
    to backup router on router crash.
 
index e45e75af89aa670c05463896016d673d79855aec..59509fdda36d7fca1c2d65ebdee8220ba7b8e717 100644 (file)
@@ -3262,7 +3262,7 @@ SILC_SERVER_CMD_FUNC(join)
       }
     }
 
-    if (!channel || !channel->id) {
+    if (!channel || channel->disabled) {
       /* Channel not found */
 
       /* If we are standalone server we don't have a router, we just create 
@@ -5014,7 +5014,7 @@ SILC_SERVER_CMD_FUNC(users)
     channel = silc_idlist_find_channel_by_name(server->local_list, 
                                               channel_name, NULL);
 
-  if (!channel) {
+  if (!channel || channel->disabled) {
     if (server->server_type != SILC_ROUTER && !server->standalone &&
        !cmd->pending) {
       SilcBuffer tmpbuf;
index c718c3baebde33a3a8f4d7dc18d2b03208118efb..cb6c6973793d99e1480b6b5f09b61e7c27232a36 100644 (file)
@@ -816,10 +816,10 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
     server->stat.my_channels++;
   } else {
     /* The entry exists. */
-    if (cache->id)
-      silc_free(cache->id);
+    silc_free(cache->id);
     entry->id = id;
     cache->id = entry->id;
+    entry->disabled = FALSE;
 
     /* Remove the founder auth data if the mode is not set but we have
        them in the entry */
index 6e8e2c946cd05e026cd0881efff381c865f8797b..0436d9a4ed2481969e2cfa6a527e0b0561ef7b21 100644 (file)
@@ -491,6 +491,7 @@ struct SilcChannelEntryStruct {
   SilcServerChannelRekey rekey;
 
   unsigned long created;
+  bool disabled;
 };
 
 /* 
index 3d4662e3d91b55ee4acd1e4d59c3c1a0bf888bdc..099a45574fd7746e9ce36bc4c09cf4dd4ef29074 100644 (file)
@@ -827,6 +827,48 @@ void silc_server_notify(SilcServer server,
       server_entry = silc_idlist_find_server_by_id(server->local_list, 
                                                   server_id, TRUE, NULL);
       if (!server_entry) {
+       /* If we are normal server then we might not have the server. Check
+          whether router was kind enough to send the list of all clients
+          that actually was to be removed. Remove them if the list is
+          available. */
+       if (server->server_type != SILC_ROUTER &&
+           silc_argument_get_arg_num(args) > 1) {
+         int i;
+
+         for (i = 1; i < silc_argument_get_arg_num(args); i++) {
+           /* Get Client ID */
+           tmp = silc_argument_get_arg_type(args, i + 1, &tmp_len);
+           if (!tmp)
+             continue;
+           client_id = silc_id_payload_parse_id(tmp, tmp_len);
+           if (!client_id)
+             continue;
+
+           /* Get client entry */
+           client = silc_idlist_find_client_by_id(server->global_list, 
+                                                  client_id, TRUE, &cache);
+           if (!client) {
+             client = silc_idlist_find_client_by_id(server->local_list, 
+                                                    client_id, TRUE, &cache);
+             if (!client) {
+               silc_free(client_id);
+               continue;
+             }
+           }
+           silc_free(client_id);
+
+           /* Remove the client from all channels. */
+           silc_server_remove_from_channels(server, NULL, client, 
+                                            TRUE, NULL, FALSE);
+           
+           client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+           cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
+           server->stat.clients--;
+           if (server->server_type == SILC_ROUTER)
+             server->stat.cell_clients--;
+         }
+       }
+
        silc_free(server_id);
        goto out;
       }
index d2e19b7410a4f6ccf00e7e4d11dc5ec59c586f4a..acea26441504832a4e180c87770b109229f7d35a 100644 (file)
@@ -386,6 +386,78 @@ void silc_server_packet_route(SilcServer server,
   silc_server_packet_send_real(server, sock, TRUE);
 }
 
+/* This routine can be used to send a packet to table of clients provided
+   in `clients'. If `route' is FALSE the packet is routed only to local
+   clients (for server locally connected, and for router local cell). */
+
+void silc_server_packet_send_clients(SilcServer server,
+                                    SilcClientEntry *clients,
+                                    uint32 clients_count,
+                                    SilcPacketType type, 
+                                    SilcPacketFlags flags,
+                                    bool route,
+                                    unsigned char *data, 
+                                    uint32 data_len,
+                                    bool force_send)
+{
+  SilcSocketConnection sock = NULL;
+  SilcClientEntry client = NULL;
+  SilcServerEntry *routed = NULL;
+  uint32 routed_count = 0;
+  bool gone = FALSE;
+  int i, k;
+
+  SILC_LOG_DEBUG(("Sending packet to list of clients"));
+
+  /* Send to all clients in table */
+  for (i = 0; i < clients_count; i++) {
+    client = clients[i];
+
+    /* If client has router set it is not locally connected client and
+       we will route the message to the router set in the client. Though,
+       send locally connected server in all cases. */
+    if (server->server_type == SILC_ROUTER && client->router && 
+       ((!route && client->router->router == server->id_entry) || route)) {
+
+      /* Check if we have sent the packet to this route already */
+      for (k = 0; k < routed_count; k++)
+       if (routed[k] == client->router)
+         break;
+      if (k < routed_count)
+       continue;
+
+      /* Route only once to router */
+      sock = (SilcSocketConnection)client->router->connection;
+      if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
+       if (gone)
+         continue;
+       gone = TRUE;
+      }
+
+      /* Send the packet */
+      silc_server_packet_send_dest(server, sock, type, flags,
+                                  client->router->id, SILC_ID_SERVER,
+                                  data, data_len, force_send);
+
+      /* Mark this route routed already */
+      routed = silc_realloc(routed, sizeof(*routed) * (routed_count + 1));
+      routed[routed_count++] = client->router;
+      continue;
+    }
+
+    if (client->router)
+      continue;
+
+    /* Send to locally connected client */
+    sock = (SilcSocketConnection)client->connection;
+    silc_server_packet_send_dest(server, sock, type, flags,
+                                client->id, SILC_ID_CLIENT,
+                                data, data_len, force_send);
+  }
+
+  silc_free(routed);
+}
+
 /* Internal routine to actually create the channel packet and send it
    to network. This is common function in channel message sending. If
    `channel_message' is TRUE this encrypts the message as it is strictly
index 25efb1a1159b00203049168ffee832bc93a04c6d..48e12977d35862ffbf5056ba36e38d3ef92fc312 100644 (file)
@@ -59,6 +59,15 @@ void silc_server_packet_broadcast(SilcServer server,
 void silc_server_packet_route(SilcServer server,
                              SilcSocketConnection sock,
                              SilcPacketContext *packet);
+void silc_server_packet_send_clients(SilcServer server,
+                                    SilcClientEntry *clients,
+                                    uint32 clients_count,
+                                    SilcPacketType type, 
+                                    SilcPacketFlags flags,
+                                    bool route,
+                                    unsigned char *data, 
+                                    uint32 data_len,
+                                    bool force_send);
 void silc_server_packet_send_to_channel(SilcServer server,
                                        SilcSocketConnection sender,
                                        SilcChannelEntry channel,
index a735140a7009c1f68cc03afb64683d693ed40f5a..78558f4bc21d64ca29c097bc855efd7b693579e9 100644 (file)
@@ -2516,7 +2516,7 @@ void silc_server_remove_from_channels(SilcServer server,
        SilcChannelClientEntry chl2;
        SilcHashTableList htl2;
 
-       channel->id = NULL;
+       channel->disabled = TRUE;
 
        silc_hash_table_list(channel->user_list, &htl2);
        while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
@@ -2636,7 +2636,7 @@ int silc_server_remove_from_one_channel(SilcServer server,
       SilcChannelClientEntry chl2;
       SilcHashTableList htl2;
       
-      channel->id = NULL;
+      channel->disabled = TRUE;
       
       silc_hash_table_list(channel->user_list, &htl2);
       while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
index 5f4c9ea855a3fdc2f02505d029179532e1006517..d0488095ef5bc64af9752cb4895796b5dedfe707 100644 (file)
@@ -212,7 +212,11 @@ bool silc_server_remove_clients_by_server(SilcServer server,
 
        /* Remove the client entry */
        silc_server_remove_clients_channels(server, NULL, client, channels);
-       silc_idlist_del_client(server->local_list, client);
+       client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+       id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
+       server->stat.clients--;
+       if (server->server_type == SILC_ROUTER)
+         server->stat.cell_clients--;
 
        if (!silc_idcache_list_next(list, &id_cache))
          break;
@@ -264,7 +268,11 @@ bool silc_server_remove_clients_by_server(SilcServer server,
 
        /* Remove the client entry */
        silc_server_remove_clients_channels(server, NULL, client, channels);
-       silc_idlist_del_client(server->global_list, client);
+       client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+       id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
+       server->stat.clients--;
+       if (server->server_type == SILC_ROUTER)
+         server->stat.cell_clients--;
 
        if (!silc_idcache_list_next(list, &id_cache))
          break;
@@ -291,7 +299,8 @@ bool silc_server_remove_clients_by_server(SilcServer server,
       silc_buffer_free(args);
     }
 
-    /* Send to local clients */
+    /* Send to local clients. We also send the list of client ID's that
+       is to be removed for those servers that would like to use that list. */
     args = silc_argument_payload_encode(argc, argv, argv_lens,
                                        argv_types);
     not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF, 
@@ -473,8 +482,6 @@ void silc_server_update_clients_by_server(SilcServer server,
     if (silc_idcache_list_first(list, &id_cache)) {
       while (id_cache) {
        client = (SilcClientEntry)id_cache->context;
-       
-
        if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
          if (!silc_idcache_list_next(list, &id_cache))
            break;
@@ -522,7 +529,6 @@ void silc_server_update_clients_by_server(SilcServer server,
     if (silc_idcache_list_first(list, &id_cache)) {
       while (id_cache) {
        client = (SilcClientEntry)id_cache->context;
-
        if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
          if (!silc_idcache_list_next(list, &id_cache))
            break;
index 6a8b62b4bdba6e7fddf6c9e56a052119f2651a25..ed64407f3b5762a27df78aba40c04b8e7982656d 100644 (file)
@@ -102,6 +102,7 @@ int main(int argc, char **argv)
   char *config_file = NULL;
   SilcServer silcd;
   struct sigaction sa;
+  char pid[10];
 
   silc_debug = FALSE;
 
@@ -197,6 +198,12 @@ int main(int argc, char **argv)
     /* Before running the server, fork to background and set
        both user and group no non-root */    
     silc_server_daemonise(silcd);
+
+  /* Set /var/run/silcd.pid */
+  unlink("/var/run/silcd/pid");
+  memset(pid, 0, sizeof(pid));
+  snprintf(pid, sizeof(pid) - 1, "%d\n", getpid());
+  silc_file_writefile("/var/run/silcd.pid", pid, strlen(pid));
   
   /* Run the server. When this returns the server has been stopped
      and we will exit. */
index d825d1ff60467bf962d43b2acab429db075e1181..e16ee17ff208ed3ac595fa715b8e8900aa12067e 100644 (file)
@@ -1367,7 +1367,8 @@ Also, all ID's sent in arguments are sent inside ID Payload.
       maximum number of arguments are reached another 
       SILC_NOTIFY_TYPE_SERVER_SIGNOFF notify packet MUST be sent.
       When this notify packet is sent between routers the Client ID's
-      MAY be omitted.
+      MAY be omitted.  Server receiving the Client ID's in the payload
+      may use them directly to remove the client.
 
 
 12    SILC_NOTIFY_TYPE_KICKED
index 9badcc72d8c66cf6fb5200f1a7e9d0026401888c..fca04ad45fcefd03746b5fac8823f8f7796b4cb5 100644 (file)
@@ -185,7 +185,9 @@ static void silc_client_ftp_send_packet(SilcSocketConnection sock,
   silc_client_packet_send(client, sock, SILC_PACKET_FTP, NULL, 0, NULL, NULL,
                          session->packet->data, session->packet->len, TRUE);
 
-  silc_buffer_clear(session->packet);
+  /* Clear buffer */
+  session->packet->data = session->packet->tail = session->packet->head;
+  session->packet->len = 0;
 }
 
 /* SFTP monitor callback for SFTP server. This reports the application 
@@ -635,7 +637,8 @@ void silc_client_ftp_free_sessions(SilcClient client,
     SilcClientFtpSession session;
     silc_dlist_start(conn->ftp_sessions);
     while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
-      session->sock->user_data = NULL;
+      if (session->sock)
+       session->sock->user_data = NULL;
       silc_client_ftp_session_free(session);
     }
     silc_dlist_del(conn->ftp_sessions, session);
@@ -657,7 +660,8 @@ void silc_client_ftp_session_free_client(SilcClientConnection conn,
   silc_dlist_start(conn->ftp_sessions);
   while ((session = silc_dlist_get(conn->ftp_sessions)) != SILC_LIST_END) {
     if (session->client_entry == client_entry) {
-      session->sock->user_data = NULL;
+      if (session->sock)
+       session->sock->user_data = NULL;
       silc_client_ftp_session_free(session);
       break;
     }
index 2f10542746658fd3fe4856463164d5e79c93933c..5acc8610abd2d3d4fa446ee3cca7980f319abd0a 100644 (file)
@@ -147,7 +147,7 @@ void silc_client_private_message(SilcClient client,
 {
   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
   SilcPrivateMessagePayload payload = NULL;
-  SilcIDCacheEntry id_cache;
+  SilcIDCacheEntry id_cache = NULL;
   SilcClientID *remote_id = NULL;
   SilcClientEntry remote_client;
   SilcMessageFlags flags;
index f5686a7214c9ebacaf09a75326ea321b2b37269c..45b91af63be83cc43f66f30693201022a5effa1d 100644 (file)
@@ -216,8 +216,10 @@ SILC_CLIENT_CMD_FUNC(get_clients_list_callback)
     SILC_GET16_MSB(idp_len, client_id_list->data + 2);
     idp_len += 4;
     client_id = silc_id_payload_parse_id(client_id_list->data, idp_len);
-    if (!client_id)
+    if (!client_id) {
+      silc_buffer_pull(client_id_list, idp_len);
       continue;
+    }
 
     /* Get the client entry */
     if (silc_idcache_find_by_id_one_ext(i->conn->client_cache, 
@@ -295,8 +297,10 @@ void silc_client_get_clients_by_list(SilcClient client,
     SILC_GET16_MSB(idp_len, client_id_list->data + 2);
     idp_len += 4;
     client_id = silc_id_payload_parse_id(client_id_list->data, idp_len);
-    if (!client_id)
+    if (!client_id) {
+      silc_buffer_pull(client_id_list, idp_len);
       continue;
+    }
 
     /* Check if we have this client cached already. */
     id_cache = NULL;
index d05c0bd104196fd37b6217ed7b9ef27d6cfc8b4e..d18781a4807725c2c92a506742356e41df9eee12 100644 (file)
@@ -344,6 +344,11 @@ void silc_packet_receive_process(SilcSocketConnection sock,
   /* Parse the packets from the data */
   while (sock->inbuf->len > 0 && cont) {
 
+    if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN) {
+      SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
+      return;
+    }
+
     /* Decrypt first 16 bytes of the packet */
     if (!SILC_IS_INBUF_PENDING(sock) && cipher)
       silc_cipher_decrypt(cipher, sock->inbuf->data, sock->inbuf->data,