updates.
[silc.git] / apps / silcd / serverid.c
1 /*
2
3   id.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2001 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "serverincludes.h"
23 #include "server_internal.h"
24
25 /* Creates a Server ID. Newly created Server ID is returned to the
26    new_id argument. */
27
28 void silc_id_create_server_id(int sock, SilcRng rng, SilcServerID **new_id)
29 {
30   struct sockaddr_in server;
31   int rval, len;
32
33   SILC_LOG_DEBUG(("Creating new Server ID"));
34
35   *new_id = silc_calloc(1, sizeof(**new_id));
36
37   /* Get IP address */
38   len = sizeof(server);
39   rval = getsockname(sock, (struct sockaddr *)&server, &len);
40   if (rval < 0) {
41     SILC_LOG_ERROR(("Could not get IP address: %s", strerror(errno)));
42     silc_free(*new_id);
43     *new_id = NULL;
44     return;
45   }
46
47   /* Create the ID */
48   /* XXX Does not support IPv6 */
49   memcpy((*new_id)->ip.data, &server.sin_addr.s_addr, 4);
50   (*new_id)->ip.data_len = 4;
51   (*new_id)->port = server.sin_port;
52   (*new_id)->rnd = silc_rng_get_rn16(rng);
53
54   SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(*new_id, SILC_ID_SERVER)));
55 }
56
57 /* Creates Client ID. This assures that there are no collisions in the
58    created Client IDs.  If the collision would occur (meaning that there
59    are 2^8 occurences of the `nickname' this will return FALSE, and the
60    caller must recall the function with different nickname. If this returns
61    TRUE the new ID was created successfully. */
62
63 bool silc_id_create_client_id(SilcServer server,
64                               SilcServerID *server_id, SilcRng rng,
65                               SilcHash md5hash, char *nickname, 
66                               SilcClientID **new_id)
67 {
68   unsigned char hash[16];
69   bool finding = FALSE;
70
71   SILC_LOG_DEBUG(("Creating new Client ID"));
72
73   *new_id = silc_calloc(1, sizeof(**new_id));
74
75   /* Create hash of the nickanem */
76   silc_hash_make(md5hash, nickname, strlen(nickname), hash);
77
78   /* Create the ID */
79   memcpy((*new_id)->ip.data, server_id->ip.data, server_id->ip.data_len);
80   (*new_id)->ip.data_len = server_id->ip.data_len;
81   (*new_id)->rnd = silc_rng_get_byte(rng);
82   memcpy((*new_id)->hash, hash, CLIENTID_HASH_LEN);
83
84   /* Assure that the ID does not exist already */
85   while (1) {
86     if (!silc_idlist_find_client_by_id(server->local_list, 
87                                        *new_id, FALSE, NULL))
88       if (!silc_idlist_find_client_by_id(server->global_list, 
89                                          *new_id, FALSE, NULL))
90         break;
91
92     /* The ID exists, start increasing the rnd from 0 until we find a
93        ID that does not exist. If we wrap and it still exists then we
94        will return FALSE and the caller must send some other nickname
95        since this cannot be used anymore. */
96     (*new_id)->rnd++;
97
98     if (finding && (*new_id)->rnd == 0)
99       return FALSE;
100
101     if (!finding) {
102       (*new_id)->rnd = 0;
103       finding = TRUE;
104     }
105   }
106
107   SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(*new_id, SILC_ID_CLIENT)));
108
109   return TRUE;
110 }
111
112 /* Creates Channel ID */
113
114 bool silc_id_create_channel_id(SilcServer server,
115                                SilcServerID *router_id, SilcRng rng,
116                                SilcChannelID **new_id)
117 {
118   bool finding = TRUE;
119
120   SILC_LOG_DEBUG(("Creating new Channel ID"));
121
122   *new_id = silc_calloc(1, sizeof(**new_id));
123
124   /* Create the ID */
125   memcpy((*new_id)->ip.data, router_id->ip.data, router_id->ip.data_len);
126   (*new_id)->ip.data_len = router_id->ip.data_len;
127   (*new_id)->port = router_id->port;
128   (*new_id)->rnd = silc_rng_get_rn16(rng);
129
130   /* Assure that the ID does not exist already */
131   while (1) {
132     if (!silc_idlist_find_channel_by_id(server->local_list, 
133                                         *new_id, NULL))
134       break;
135
136     (*new_id)->rnd++;
137     
138     if (finding && (*new_id)->rnd == 0)
139       return FALSE;
140     
141     if (!finding) {
142       (*new_id)->rnd = 0;
143       finding = TRUE;
144     }
145   }
146
147   SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(*new_id, SILC_ID_CHANNEL)));
148
149   return TRUE;
150 }