Added.
[silc.git] / lib / silcserver / server_util.c
diff --git a/lib/silcserver/server_util.c b/lib/silcserver/server_util.c
new file mode 100644 (file)
index 0000000..4ce698e
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+
+  server_util.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 1997 - 2005 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+*/
+/* $Id$ */
+
+#include "silc.h"
+#include "silcserver.h"
+#include "server_internal.h"
+
+SilcBool silc_server_check_watcher_list(SilcServer server,
+                                   SilcClientEntry client,
+                                   const char *new_nick,
+                                   SilcNotifyType notify)
+{
+  return TRUE;
+}
+
+/* This function is used to send the notify packets and motd to the
+   incoming client connection. */
+
+void silc_server_send_welcome(SilcServerAccept ac, SilcClientEntry client)
+{
+  SilcServer server = ac->thread->server;
+  SilcPacketStream stream = client->stream;
+
+  SILC_LOG_DEBUG(("Send welcome notifys"));
+
+  /* Send some nice info to the client */
+  SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
+                         ("Welcome to the SILC Network %s",
+                          client->username));
+  SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
+                         ("Your host is %s, running version %s",
+                          server->server_name, SILC_DIST_VERSION_STRING));
+
+  if (server->server_type == SILC_ROUTER) {
+    SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
+                           ("There are %d clients, %d servers and %d "
+                            "routers in SILC Network",
+                            server->stat.clients, server->stat.servers,
+                            server->stat.routers));
+  } else {
+    if (server->stat.clients && server->stat.servers + 1)
+      SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
+                             ("There are %d clients, %d servers and %d "
+                              "routers in SILC Network",
+                              server->stat.clients, server->stat.servers,
+                              (server->standalone ? 0 :
+                               !server->stat.routers ? 1 :
+                               server->stat.routers)));
+  }
+
+  if (server->stat.cell_clients && server->stat.cell_servers + 1)
+    SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
+                           ("There are %d clients on %d servers in our cell",
+                            server->stat.cell_clients,
+                            server->stat.cell_servers));
+  if (server->server_type == SILC_ROUTER) {
+    SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
+                           ("I have %d clients, %d channels, %d servers and "
+                            "%d routers",
+                            server->stat.my_clients,
+                            server->stat.my_channels,
+                            server->stat.my_servers,
+                            server->stat.my_routers));
+  } else {
+    SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
+                           ("I have %d clients and %d channels formed",
+                            server->stat.my_clients,
+                            server->stat.my_channels));
+  }
+
+  if (server->stat.server_ops || server->stat.router_ops)
+    SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
+                           ("There are %d server operators and %d router "
+                            "operators online",
+                            server->stat.server_ops,
+                            server->stat.router_ops));
+  if (server->stat.my_router_ops + server->stat.my_server_ops)
+    SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
+                           ("I have %d operators online",
+                            server->stat.my_router_ops +
+                            server->stat.my_server_ops));
+
+  SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
+                         ("Your connection is secured with %s cipher, "
+                          "key length %d bits",
+                          silc_cipher_get_name(ac->prop->cipher),
+                          silc_cipher_get_key_len(ac->prop->cipher)));
+  SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
+                         ("Your current nickname is %s",
+                          client->nickname));
+
+  /* Send motd */
+  silc_server_send_motd(server, stream);
+}
+
+/* Creates new Client ID. */
+
+SilcBool silc_server_create_client_id(SilcServer server, char *nickname,
+                                     SilcClientID *new_id)
+{
+  unsigned char hash[16];
+  SilcBool finding = FALSE;
+
+  SILC_LOG_DEBUG(("Creating new Client ID"));
+
+  /* Create hash of the nickname (it's already checked as valid identifier
+     string). */
+  silc_hash_make(server->md5hash, nickname, strlen(nickname), hash);
+
+  /* Create the ID */
+  memcpy(new_id->ip.data, server->id.ip.data, server->id.ip.data_len);
+  new_id->ip.data_len = server->id.ip.data_len;
+  new_id->rnd = silc_rng_get_byte(server->rng);
+  memcpy(new_id->hash, hash, CLIENTID_HASH_LEN);
+
+  /* Assure that the ID does not exist already */
+  while (1) {
+    if (!silc_server_find_client_by_id(server, new_id, FALSE, NULL))
+      break;
+
+    /* The ID exists, start increasing the rnd from 0 until we find a
+       ID that does not exist. If we wrap and it still exists then we
+       will return FALSE and the caller must send some other nickname
+       since this cannot be used anymore. */
+    new_id->rnd++;
+
+    if (finding && new_id->rnd == 0)
+      return FALSE;
+
+    if (!finding) {
+      new_id->rnd = 0;
+      finding = TRUE;
+    }
+  }
+
+  SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(new_id, SILC_ID_CLIENT)));
+
+  return TRUE;
+}
+
+/* Creates a Server ID. */
+
+SilcBool silc_server_create_server_id(SilcServer server,
+                                     const char *ip, SilcUInt16 port,
+                                     SilcServerID *new_id)
+{
+  SILC_LOG_DEBUG(("Creating new Server ID"));
+
+  if (!new_id)
+    return FALSE;
+
+  /* Create the ID */
+
+  if (!silc_net_addr2bin(ip, new_id->ip.data, sizeof(new_id->ip.data)))
+    return FALSE;
+
+  new_id->ip.data_len = silc_net_is_ip4(ip) ? 4 : 16;
+  new_id->port = SILC_SWAB_16(port);
+  new_id->rnd = silc_rng_get_rn16(server->rng);
+
+  SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(new_id, SILC_ID_SERVER)));
+
+  return TRUE;
+}
+
+/* Checks whether the `server_id' is valid.  It must be based to the
+   IP address provided in the `remote' socket connection. */
+
+SilcBool silc_server_check_server_id(const char *ip_address,
+                                    SilcServerID *server_id)
+{
+  unsigned char ip[16];
+
+  if (!silc_net_addr2bin(ip_address, ip, sizeof(ip)))
+    return FALSE;
+
+  if (silc_net_is_ip4(ip_address)) {
+    if (!memcmp(server_id->ip.data, ip, 4))
+      return TRUE;
+  } else {
+    if (!memcmp(server_id->ip.data, ip, 16))
+      return TRUE;
+  }
+
+  return FALSE;
+}