Merged silc_1_1_branch to trunk.
[silc.git] / apps / silcd / serverid.c
index fb29b468412e6f2b828f4949aacd2b222385094e..73641c65dd13449a7dce351be999dab4db56f420 100644 (file)
@@ -1,16 +1,16 @@
 /*
 
-  id.c
+  serverid.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2007 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; either version 2 of the License, or
   (at your option) any later version.
-  
+
   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
 /* Creates a Server ID. Newly created Server ID is returned to the
    new_id argument. */
 
-void silc_id_create_server_id(int sock, SilcRng rng, SilcServerID **new_id)
+void silc_id_create_server_id(const char *ip, SilcUInt16 port, SilcRng rng,
+                             SilcServerID **new_id)
 {
-  struct sockaddr_in server;
-  int rval, len;
-
   SILC_LOG_DEBUG(("Creating new Server ID"));
 
   *new_id = silc_calloc(1, sizeof(**new_id));
 
-  /* Get IP address */
-  len = sizeof(server);
-  rval = getsockname(sock, (struct sockaddr *)&server, &len);
-  if (rval < 0) {
-    SILC_LOG_ERROR(("Could not get IP address: %s", strerror(errno)));
+  /* Create the ID */
+
+  if (!silc_net_addr2bin(ip, (*new_id)->ip.data,
+                        sizeof((*new_id)->ip.data))) {
     silc_free(*new_id);
     *new_id = NULL;
     return;
   }
 
-  /* Create the ID */
-  /* XXX Does not support IPv6 */
-  SILC_PUT32_MSB(server.sin_addr.s_addr, (*new_id)->ip.data);
-  (*new_id)->ip.data_len = 4;
-  (*new_id)->port = server.sin_port;
-  (*new_id)->rnd = silc_rng_get_rn16(rng);
+  (*new_id)->ip.data_len = silc_net_is_ip4(ip) ? 4 : 16;
+  (*new_id)->port = SILC_SWAB_16(port);
+  (*new_id)->rnd = 0xff;
 
   SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(*new_id, SILC_ID_SERVER)));
 }
@@ -60,20 +54,22 @@ void silc_id_create_server_id(int sock, SilcRng rng, SilcServerID **new_id)
    caller must recall the function with different nickname. If this returns
    TRUE the new ID was created successfully. */
 
-bool silc_id_create_client_id(SilcServer server,
-                             SilcServerID *server_id, SilcRng rng,
-                             SilcHash md5hash, char *nickname, 
-                             SilcClientID **new_id)
+SilcBool silc_id_create_client_id(SilcServer server,
+                                 SilcServerID *server_id, SilcRng rng,
+                                 SilcHash md5hash,
+                                 unsigned char *nickname, SilcUInt32 nick_len,
+                                 SilcClientID **new_id)
 {
   unsigned char hash[16];
-  bool finding = FALSE;
+  SilcBool finding = FALSE;
 
   SILC_LOG_DEBUG(("Creating new Client ID"));
 
   *new_id = silc_calloc(1, sizeof(**new_id));
 
-  /* Create hash of the nickanem */
-  silc_hash_make(md5hash, nickname, strlen(nickname), hash);
+  /* Create hash of the nickname (it's already checked as valid identifier
+     string). */
+  silc_hash_make(md5hash, nickname, nick_len, hash);
 
   /* Create the ID */
   memcpy((*new_id)->ip.data, server_id->ip.data, server_id->ip.data_len);
@@ -83,9 +79,9 @@ bool silc_id_create_client_id(SilcServer server,
 
   /* Assure that the ID does not exist already */
   while (1) {
-    if (!silc_idlist_find_client_by_id(server->local_list, 
+    if (!silc_idlist_find_client_by_id(server->local_list,
                                       *new_id, FALSE, NULL))
-      if (!silc_idlist_find_client_by_id(server->global_list, 
+      if (!silc_idlist_find_client_by_id(server->global_list,
                                         *new_id, FALSE, NULL))
        break;
 
@@ -111,11 +107,11 @@ bool silc_id_create_client_id(SilcServer server,
 
 /* Creates Channel ID */
 
-bool silc_id_create_channel_id(SilcServer server,
-                              SilcServerID *router_id, SilcRng rng,
-                              SilcChannelID **new_id)
+SilcBool silc_id_create_channel_id(SilcServer server,
+                                  SilcServerID *router_id, SilcRng rng,
+                                  SilcChannelID **new_id)
 {
-  bool finding = TRUE;
+  SilcBool finding = TRUE;
 
   SILC_LOG_DEBUG(("Creating new Channel ID"));
 
@@ -129,17 +125,15 @@ bool silc_id_create_channel_id(SilcServer server,
 
   /* Assure that the ID does not exist already */
   while (1) {
-    if (!silc_idlist_find_channel_by_id(server->local_list, 
+    if (!silc_idlist_find_channel_by_id(server->local_list,
                                        *new_id, NULL))
-      if (!silc_idlist_find_channel_by_id(server->global_list, 
-                                         *new_id, NULL))
-       break;
-    
+      break;
+
     (*new_id)->rnd++;
-    
+
     if (finding && (*new_id)->rnd == 0)
       return FALSE;
-    
+
     if (!finding) {
       (*new_id)->rnd = 0;
       finding = TRUE;
@@ -150,3 +144,29 @@ bool silc_id_create_channel_id(SilcServer 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_id_is_valid_server_id(SilcServer server,
+                                   SilcServerID *server_id,
+                                   SilcPacketStream remote)
+{
+  unsigned char ip[16];
+  const char *remote_ip;
+  SilcStream stream = silc_packet_stream_get_stream(remote);
+
+  silc_socket_stream_get_info(stream, NULL, NULL, &remote_ip, NULL);
+  if (!silc_net_addr2bin(remote_ip, ip, sizeof(ip)))
+    return FALSE;
+
+  if (silc_net_is_ip4(remote_ip)) {
+    if (!memcmp(server_id->ip.data, ip, 4))
+      return TRUE;
+  } else {
+    if (!memcmp(server_id->ip.data, ip, 16))
+      return TRUE;
+  }
+
+  return FALSE;
+}