Added SILC Thread Queue API
[runtime.git] / lib / silcserver / server_util.c
1 /*
2
3   server_util.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2006 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; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id$ */
20
21 #include "silc.h"
22 #include "silcserver.h"
23 #include "server_internal.h"
24
25 /* Return next available command identifier. */
26
27 SilcUInt16 silc_server_cmd_ident(SilcServer server)
28 {
29   SilcUInt16 cmd_ident;
30
31   silc_mutex_lock(server->lock);
32   cmd_ident = ++server->cmd_ident;
33   silc_mutex_unlock(server->lock);
34
35   return cmd_ident;
36 }
37
38 /* XXX locking */
39
40 SilcBool silc_server_check_watcher_list(SilcServer server,
41                                     SilcClientEntry client,
42                                     const char *new_nick,
43                                     SilcNotifyType notify)
44 {
45   return TRUE;
46 }
47
48 /* This function is used to send the notify packets and motd to the
49    incoming client connection. */
50
51 void silc_server_send_welcome(SilcServerAccept ac, SilcClientEntry client)
52 {
53   SilcServer server = ac->thread->server;
54   SilcPacketStream stream = client->stream;
55
56   SILC_LOG_DEBUG(("Send welcome notifys"));
57
58   /* Send some nice info to the client */
59   SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
60                           ("Welcome to the SILC Network %s",
61                            client->username));
62   SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
63                           ("Your host is %s, running version %s",
64                            server->server_name, SILC_DIST_VERSION_STRING));
65
66   if (server->server_type == SILC_ROUTER) {
67     SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
68                             ("There are %d clients, %d servers and %d "
69                              "routers in SILC Network",
70                              server->stat.clients, server->stat.servers,
71                              server->stat.routers));
72   } else {
73     if (server->stat.clients && server->stat.servers + 1)
74       SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
75                               ("There are %d clients, %d servers and %d "
76                                "routers in SILC Network",
77                                server->stat.clients, server->stat.servers,
78                                (server->standalone ? 0 :
79                                 !server->stat.routers ? 1 :
80                                 server->stat.routers)));
81   }
82
83   if (server->stat.cell_clients && server->stat.cell_servers + 1)
84     SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
85                             ("There are %d clients on %d servers in our cell",
86                              server->stat.cell_clients,
87                              server->stat.cell_servers));
88   if (server->server_type == SILC_ROUTER) {
89     SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
90                             ("I have %d clients, %d channels, %d servers and "
91                              "%d routers",
92                              server->stat.my_clients,
93                              server->stat.my_channels,
94                              server->stat.my_servers,
95                              server->stat.my_routers));
96   } else {
97     SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
98                             ("I have %d clients and %d channels formed",
99                              server->stat.my_clients,
100                              server->stat.my_channels));
101   }
102
103   if (server->stat.server_ops || server->stat.router_ops)
104     SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
105                             ("There are %d server operators and %d router "
106                              "operators online",
107                              server->stat.server_ops,
108                              server->stat.router_ops));
109   if (server->stat.my_router_ops + server->stat.my_server_ops)
110     SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
111                             ("I have %d operators online",
112                              server->stat.my_router_ops +
113                              server->stat.my_server_ops));
114
115   SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
116                           ("Your connection is secured with %s cipher, "
117                            "key length %d bits",
118                            silc_cipher_get_name(ac->prop->cipher),
119                            silc_cipher_get_key_len(ac->prop->cipher)));
120   SILC_SERVER_SEND_NOTIFY(server, stream, SILC_NOTIFY_TYPE_NONE,
121                           ("Your current nickname is %s",
122                            client->nickname));
123
124   /* Send motd */
125   silc_server_send_motd(server, stream);
126 }
127
128 /* Creates new Client ID. */
129
130 SilcBool silc_server_create_client_id(SilcServer server, char *nickname,
131                                       SilcClientID *new_id)
132 {
133   unsigned char hash[16];
134   SilcBool finding = FALSE;
135
136   SILC_LOG_DEBUG(("Creating new Client ID"));
137
138   /* Create hash of the nickname (it's already checked as valid identifier
139      string). */
140   silc_hash_make(server->md5hash, nickname, strlen(nickname), hash);
141
142   /* Create the ID */
143   memset(new_id, 0, sizeof(*new_id));
144   memcpy(new_id->ip.data, server->id.ip.data, server->id.ip.data_len);
145   new_id->ip.data_len = server->id.ip.data_len;
146   new_id->rnd = silc_rng_get_byte(server->rng);
147   memcpy(new_id->hash, hash, CLIENTID_HASH_LEN);
148
149   /* Assure that the ID does not exist already */
150   while (1) {
151     if (!silc_server_find_client_by_id(server, new_id, FALSE, NULL))
152       break;
153
154     /* The ID exists, start increasing the rnd from 0 until we find a
155        ID that does not exist. If we wrap and it still exists then we
156        will return FALSE and the caller must send some other nickname
157        since this cannot be used anymore. */
158     new_id->rnd++;
159
160     if (finding && new_id->rnd == 0)
161       return FALSE;
162
163     if (!finding) {
164       new_id->rnd = 0;
165       finding = TRUE;
166     }
167   }
168
169   SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(new_id, SILC_ID_CLIENT)));
170
171   return TRUE;
172 }
173
174 /* Creates a Server ID. */
175
176 SilcBool silc_server_create_server_id(SilcServer server,
177                                       const char *ip, SilcUInt16 port,
178                                       SilcServerID *new_id)
179 {
180   SILC_LOG_DEBUG(("Creating new Server ID"));
181
182   if (!new_id)
183     return FALSE;
184
185   /* Create the ID */
186
187   if (!silc_net_addr2bin(ip, new_id->ip.data, sizeof(new_id->ip.data)))
188     return FALSE;
189
190   new_id->ip.data_len = silc_net_is_ip4(ip) ? 4 : 16;
191   new_id->port = SILC_SWAB_16(port);
192   new_id->rnd = silc_rng_get_rn16(server->rng);
193
194   SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(new_id, SILC_ID_SERVER)));
195
196   return TRUE;
197 }
198
199 /* Checks whether the `server_id' is valid.  It must be based to the
200    IP address provided in the `remote' socket connection. */
201
202 SilcBool silc_server_check_server_id(const char *ip_address,
203                                      SilcServerID *server_id)
204 {
205   unsigned char ip[16];
206
207   if (!silc_net_addr2bin(ip_address, ip, sizeof(ip)))
208     return FALSE;
209
210   if (silc_net_is_ip4(ip_address)) {
211     if (!memcmp(server_id->ip.data, ip, 4))
212       return TRUE;
213   } else {
214     if (!memcmp(server_id->ip.data, ip, 16))
215       return TRUE;
216   }
217
218   return FALSE;
219 }