Added silc_server_remove_servers_by_server to remove servers
[silc.git] / apps / silcd / server_util.c
1 /*
2
3   server_util.c 
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2002 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 "serverincludes.h"
22 #include "server_internal.h"
23
24 extern char *server_version;
25
26 /* Removes the client from channels and possibly removes the channels
27    as well.  After removing those channels that exist, their channel
28    keys are regnerated. This is called only by the function
29    silc_server_remove_clients_by_server. */
30
31 static void
32 silc_server_remove_clients_channels(SilcServer server,
33                                     SilcServerEntry server_entry,
34                                     SilcHashTable clients,
35                                     SilcClientEntry client,
36                                     SilcHashTable channels)
37 {
38   SilcChannelEntry channel;
39   SilcChannelClientEntry chl, chl2;
40   SilcHashTableList htl, htl2;
41
42   if (!client)
43     return;
44
45   SILC_LOG_DEBUG(("Remove client from all channels"));
46
47   if (silc_hash_table_find(clients, client, NULL, NULL))
48     silc_hash_table_del(clients, client);
49
50   /* Remove the client from all channels. The client is removed from
51      the channels' user list. */
52   silc_hash_table_list(client->channels, &htl);
53   while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
54     channel = chl->channel;
55
56     /* Remove channel if this is last client leaving the channel, unless
57        the channel is permanent. */
58     if (server->server_type == SILC_ROUTER &&
59         silc_hash_table_count(channel->user_list) < 2) {
60       if (silc_hash_table_find(channels, channel, NULL, NULL))
61         silc_hash_table_del(channels, channel);
62       silc_schedule_task_del_by_context(server->schedule, channel->rekey);
63       silc_server_channel_delete(server, channel);
64       continue;
65     }
66
67     silc_hash_table_del(client->channels, channel);
68     silc_hash_table_del(channel->user_list, chl->client);
69     channel->user_count--;
70
71     /* If there is no global users on the channel anymore mark the channel
72        as local channel. Do not check if the removed client is local client. */
73     if (server->server_type != SILC_ROUTER && channel->global_users && 
74         chl->client->router && !silc_server_channel_has_global(channel))
75       channel->global_users = FALSE;
76
77     silc_free(chl);
78
79     /* Update statistics */
80     if (SILC_IS_LOCAL(client))
81       server->stat.my_chanclients--;
82     if (server->server_type == SILC_ROUTER) {
83       server->stat.cell_chanclients--;
84       server->stat.chanclients--;
85     }
86
87     /* If there is not at least one local user on the channel then we don't
88        need the channel entry anymore, we can remove it safely, unless the
89        channel is permanent channel */
90     if (server->server_type != SILC_ROUTER &&
91         !silc_server_channel_has_local(channel)) {
92       if (silc_hash_table_find(channels, channel, NULL, NULL))
93         silc_hash_table_del(channels, channel);
94       silc_schedule_task_del_by_context(server->schedule, channel->rekey);
95       silc_server_channel_delete(server, channel);
96       continue;
97     }
98
99     /* Mark other local clients to the table of clients whom will receive
100        the SERVER_SIGNOFF notify. */
101     silc_hash_table_list(channel->user_list, &htl2);
102     while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
103       SilcClientEntry c = chl2->client;
104       if (!c)
105         continue;
106
107       /* Add client to table, if it's not from the signoff server */
108       if (c->router != server_entry &&
109           !silc_hash_table_find(clients, c, NULL, NULL))
110         silc_hash_table_add(clients, c, c);
111     }
112     silc_hash_table_list_reset(&htl2);
113
114     /* Add the channel to the the channels list to regenerate the 
115        channel key */
116     if (!silc_hash_table_find(channels, channel, NULL, NULL))
117       silc_hash_table_add(channels, channel, channel);
118   }
119   silc_hash_table_list_reset(&htl);
120 }
121
122 /* This function removes all client entries that are originated from
123    `router' and are owned by `entry'.  `router' and `entry' can be same
124    too.  If `server_signoff' is TRUE then SERVER_SIGNOFF notify is 
125    distributed to our local clients. */
126
127 bool silc_server_remove_clients_by_server(SilcServer server,
128                                           SilcServerEntry router,
129                                           SilcServerEntry entry,
130                                           bool server_signoff)
131 {
132   SilcIDCacheList list = NULL;
133   SilcIDCacheEntry id_cache = NULL;
134   SilcClientEntry client = NULL;
135   SilcBuffer idp;
136   unsigned char **argv = NULL;
137   SilcUInt32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
138   SilcHashTableList htl;
139   SilcChannelEntry channel;
140   SilcHashTable channels, clients;
141   int i;
142
143   if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED))
144     return FALSE;
145
146   SILC_LOG_DEBUG(("Removing clients by %s",
147                   entry->server_name ? entry->server_name : "server"));
148
149   if (!router)
150     router = entry;
151
152   /* Allocate the hash table that holds the channels that require
153      channel key re-generation after we've removed this server's clients
154      from the channels. */
155   channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
156                                    NULL, NULL, TRUE);
157   clients = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
158                                   NULL, NULL, TRUE);
159
160   if (server_signoff) {
161     idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
162     argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
163     argv_lens = silc_realloc(argv_lens,  sizeof(*argv_lens) * (argc + 1));
164     argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
165     argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
166     memcpy(argv[argc], idp->data, idp->len);
167     argv_lens[argc] = idp->len;
168     argv_types[argc] = argc + 1;
169     argc++;
170     silc_buffer_free(idp);
171   }
172
173   if (silc_idcache_get_all(server->local_list->clients, &list)) {
174     if (silc_idcache_list_first(list, &id_cache)) {
175       while (id_cache) {
176         client = (SilcClientEntry)id_cache->context;
177
178         /* If client is not registered, is not originated from `router'
179            or is not owned by `entry', skip it. */
180         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
181             client->router != router ||
182             !SILC_ID_COMPARE(client->id, entry->id, client->id->ip.data_len)) {
183           if (!silc_idcache_list_next(list, &id_cache))
184             break;
185           else
186             continue;
187         }
188
189         if (server_signoff) {
190           idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
191           argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
192           argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
193                                    (argc + 1));
194           argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
195                                     (argc + 1));
196           argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
197           memcpy(argv[argc], idp->data, idp->len);
198           argv_lens[argc] = idp->len;
199           argv_types[argc] = argc + 1;
200           argc++;
201           silc_buffer_free(idp);
202         }
203
204         /* Update statistics */
205         server->stat.clients--;
206         if (server->stat.cell_clients)
207           server->stat.cell_clients--;
208         SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
209         SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
210
211         silc_server_remove_clients_channels(server, entry, clients,
212                                             client, channels);
213         silc_server_del_from_watcher_list(server, client);
214
215         /* Remove the client entry */
216         if (!server_signoff) {
217           client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
218           id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
219         } else {
220           silc_idlist_del_client(server->local_list, client);
221         }
222
223         if (!silc_idcache_list_next(list, &id_cache))
224           break;
225       }
226     }
227     silc_idcache_list_free(list);
228   }
229   
230   if (silc_idcache_get_all(server->global_list->clients, &list)) {
231
232     if (silc_idcache_list_first(list, &id_cache)) {
233       while (id_cache) {
234         client = (SilcClientEntry)id_cache->context;
235
236         /* If client is not registered, is not originated from `router'
237            or is not owned by `entry', skip it. */
238         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
239             client->router != router ||
240             !SILC_ID_COMPARE(client->id, entry->id, client->id->ip.data_len)) {
241           if (!silc_idcache_list_next(list, &id_cache))
242             break;
243           else
244             continue;
245         }
246
247         if (server_signoff) {
248           idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
249           argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
250           argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
251                                    (argc + 1));
252           argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
253                                     (argc + 1));
254           argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
255           memcpy(argv[argc], idp->data, idp->len);
256           argv_lens[argc] = idp->len;
257           argv_types[argc] = argc + 1;
258           argc++;
259           silc_buffer_free(idp);
260         }
261
262         /* Update statistics */
263         server->stat.clients--;
264         if (server->stat.cell_clients)
265           server->stat.cell_clients--;
266         SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
267         SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
268
269         silc_server_remove_clients_channels(server, entry, clients,
270                                             client, channels);
271         silc_server_del_from_watcher_list(server, client);
272
273         /* Remove the client entry */
274         if (!server_signoff) {
275           client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
276           id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
277         } else {
278           silc_idlist_del_client(server->global_list, client);
279         }
280
281         if (!silc_idcache_list_next(list, &id_cache))
282           break;
283       }
284     }
285     silc_idcache_list_free(list);
286   }
287
288   /* Send the SERVER_SIGNOFF notify */
289   if (server_signoff) {
290     SilcBuffer args, not;
291
292     SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %s with %d clients",
293                     silc_id_render(entry->id, SILC_ID_SERVER), argc - 1));
294
295     /* Send SERVER_SIGNOFF notify to our primary router */
296     if (server->router != entry) {
297       args = silc_argument_payload_encode(1, argv, argv_lens,
298                                           argv_types);
299       silc_server_send_notify_args(server, SILC_PRIMARY_ROUTE(server),
300                                    SILC_BROADCAST(server),
301                                    SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
302                                    argc, args);
303       silc_buffer_free(args);
304     }
305
306     /* Send to local clients. We also send the list of client ID's that
307        is to be removed for those servers that would like to use that list. */
308     args = silc_argument_payload_encode(argc, argv, argv_lens,
309                                         argv_types);
310     not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF, 
311                                           argc, args);
312     silc_server_packet_send_clients(server, clients,
313                                     SILC_PACKET_NOTIFY, 0, FALSE,
314                                     not->data, not->len, FALSE);
315
316     silc_buffer_free(args);
317     silc_buffer_free(not);
318     for (i = 0; i < argc; i++)
319       silc_free(argv[i]);
320     silc_free(argv);
321     silc_free(argv_lens);
322     silc_free(argv_types);
323     silc_hash_table_free(clients);
324   }
325
326   /* We must now re-generate the channel key for all channels that had
327      this server's client(s) on the channel. As they left the channel we
328      must re-generate the channel key. */
329   silc_hash_table_list(channels, &htl);
330   while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
331     if (!silc_server_create_channel_key(server, channel, 0)) {
332       silc_hash_table_list_reset(&htl);
333       silc_hash_table_free(channels);
334       return FALSE;
335     }
336
337     /* Do not send the channel key if private channel key mode is set */
338     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
339       continue;
340
341     silc_server_send_channel_key(server, NULL, channel, 
342                                  server->server_type == SILC_ROUTER ? 
343                                  FALSE : !server->standalone);
344   }
345   silc_hash_table_list_reset(&htl);
346   silc_hash_table_free(channels);
347
348   return TRUE;
349 }
350
351 static SilcServerEntry
352 silc_server_update_clients_by_real_server(SilcServer server,
353                                           SilcServerEntry from,
354                                           SilcClientEntry client,
355                                           bool local,
356                                           SilcIDCacheEntry client_cache)
357 {
358   SilcServerEntry server_entry;
359   SilcIDCacheEntry id_cache = NULL;
360   SilcIDCacheList list;
361
362   if (!silc_idcache_get_all(server->local_list->servers, &list))
363     return NULL;
364
365   if (silc_idcache_list_first(list, &id_cache)) {
366     while (id_cache) {
367       server_entry = (SilcServerEntry)id_cache->context;
368       if (server_entry != from &&
369           SILC_ID_COMPARE(server_entry->id, client->id, 
370                           client->id->ip.data_len)) {
371         SILC_LOG_DEBUG(("Found (local) %s",
372                         silc_id_render(server_entry->id, SILC_ID_SERVER)));
373
374         if (!server_entry->data.send_key && server_entry->router) {
375           SILC_LOG_DEBUG(("Server not locally connected, use its router"));
376           /* If the client is not marked as local then move it to local list
377              since the server is local. */
378           if (!local) {
379             SILC_LOG_DEBUG(("Moving client to local list"));
380             silc_idcache_add(server->local_list->clients, client_cache->name,
381                              client_cache->id, client_cache->context,
382                              client_cache->expire, NULL);
383             silc_idcache_del_by_context(server->global_list->clients, client);
384           }
385           server_entry = server_entry->router;
386         } else {
387           /* If the client is not marked as local then move it to local list
388              since the server is local. */
389           if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
390             SILC_LOG_DEBUG(("Moving client to local list"));
391             silc_idcache_add(server->local_list->clients, client_cache->name,
392                              client_cache->id, client_cache->context,
393                              client_cache->expire, NULL);
394             silc_idcache_del_by_context(server->global_list->clients, client);
395           }
396         }
397
398         silc_idcache_list_free(list);
399         return server_entry;
400       }
401
402       if (!silc_idcache_list_next(list, &id_cache))
403         break;
404     }
405   }
406
407   silc_idcache_list_free(list);
408
409   if (!silc_idcache_get_all(server->global_list->servers, &list))
410     return NULL;
411
412   if (silc_idcache_list_first(list, &id_cache)) {
413     while (id_cache) {
414       server_entry = (SilcServerEntry)id_cache->context;
415       if (server_entry != from &&
416           SILC_ID_COMPARE(server_entry->id, client->id, 
417                           client->id->ip.data_len)) {
418         SILC_LOG_DEBUG(("Found (global) %s",
419                         silc_id_render(server_entry->id, SILC_ID_SERVER)));
420
421         if (!server_entry->data.send_key && server_entry->router) {
422           SILC_LOG_DEBUG(("Server not locally connected, use its router"));
423           /* If the client is marked as local then move it to global list
424              since the server is global. */
425           if (local) {
426             SILC_LOG_DEBUG(("Moving client to global list"));
427             silc_idcache_add(server->global_list->clients, client_cache->name,
428                              client_cache->id, client_cache->context,
429                              client_cache->expire, NULL);
430             silc_idcache_del_by_context(server->local_list->clients, client);
431           }
432           server_entry = server_entry->router;
433         } else {
434           /* If the client is marked as local then move it to global list
435              since the server is global. */
436           if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
437             SILC_LOG_DEBUG(("Moving client to global list"));
438             silc_idcache_add(server->global_list->clients, client_cache->name,
439                              client_cache->id, client_cache->context,
440                              client_cache->expire, NULL);
441             silc_idcache_del_by_context(server->local_list->clients, client);
442           }
443         }
444
445         silc_idcache_list_free(list);
446         return server_entry;
447       }
448
449       if (!silc_idcache_list_next(list, &id_cache))
450         break;
451     }
452   }
453
454   silc_idcache_list_free(list);
455
456   return NULL;
457 }
458
459 /* Updates the clients that are originated from the `from' to be originated
460    from the `to'. If the `resolve_real_server' is TRUE then this will
461    attempt to figure out which clients really are originated from the
462    `from' and which are originated from a server that we have connection
463    to, when we've acting as backup router. If it is FALSE the `to' will
464    be the new source. This function also removes the clients that are
465    *really* originated from `from' if `remove_from' is TRUE. These are
466    clients that the `from' owns, and not just clients that are behind
467    the `from'. If `from' is NULL then all non-local clients are switched
468    to `to'. */
469
470 void silc_server_update_clients_by_server(SilcServer server, 
471                                           SilcServerEntry from,
472                                           SilcServerEntry to,
473                                           bool resolve_real_server,
474                                           bool remove_from)
475 {
476   SilcIDCacheList list = NULL;
477   SilcIDCacheEntry id_cache = NULL;
478   SilcClientEntry client = NULL;
479   bool local;
480
481   if (from)
482     SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id,
483                                                   SILC_ID_SERVER)));
484   if (to)
485     SILC_LOG_DEBUG(("to %s", silc_id_render(to->id,
486                                             SILC_ID_SERVER)));
487
488   local = FALSE;
489   if (silc_idcache_get_all(server->global_list->clients, &list)) {
490     if (silc_idcache_list_first(list, &id_cache)) {
491       while (id_cache) {
492         client = (SilcClientEntry)id_cache->context;
493
494         /* If entry is disabled skip it.  If entry is local to us, do not
495            switch it to anyone else, it is ours so skip it. */
496         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
497             SILC_IS_LOCAL(client)) {
498           if (!silc_idcache_list_next(list, &id_cache))
499             break;
500           else
501             continue;
502         }
503
504         SILC_LOG_DEBUG(("Client (global) %s", 
505                         silc_id_render(client->id, SILC_ID_CLIENT)));
506         if (client->router)
507           SILC_LOG_DEBUG(("Client->router (global) %s", 
508                           silc_id_render(client->router->id, SILC_ID_SERVER)));
509
510         if (from) {
511           if (client->router == from) {
512             /* Skip clients that are *really* owned by the `from' */
513             if (remove_from && SILC_ID_COMPARE(from->id, client->id, 
514                                                client->id->ip.data_len)) {
515               SILC_LOG_DEBUG(("Found really owned client, skip it"));
516               if (!silc_idcache_list_next(list, &id_cache))
517                 break;
518               else
519                 continue;
520             }
521
522             if (resolve_real_server) {
523               client->router = 
524                 silc_server_update_clients_by_real_server(server, from, client,
525                                                           local, id_cache);
526               if (!client->router) {
527                 if (server->server_type == SILC_ROUTER)
528                   client->router = from;
529                 else
530                   client->router = to;
531               }
532             } else {
533               client->router = to;
534             }
535           }
536         } else {
537           /* All are changed */
538           client->router = to;
539         }
540
541         if (client->router)
542           SILC_LOG_DEBUG(("Client changed to %s", 
543                           silc_id_render(client->router->id, SILC_ID_CLIENT)));
544
545         if (!silc_idcache_list_next(list, &id_cache))
546           break;
547       }
548     }
549     silc_idcache_list_free(list);
550   }
551
552   local = TRUE;
553   if (silc_idcache_get_all(server->local_list->clients, &list)) {
554     if (silc_idcache_list_first(list, &id_cache)) {
555       while (id_cache) {
556         client = (SilcClientEntry)id_cache->context;
557
558         /* If entry is disabled skip it.  If entry is local to us, do not
559            switch it to anyone else, it is ours so skip it. */
560         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
561             SILC_IS_LOCAL(client)) {
562           if (!silc_idcache_list_next(list, &id_cache))
563             break;
564           else
565             continue;
566         }
567
568         SILC_LOG_DEBUG(("Client (local) %s", 
569                         silc_id_render(client->id, SILC_ID_CLIENT)));
570         if (client->router)
571           SILC_LOG_DEBUG(("Client->router (local) %s", 
572                           silc_id_render(client->router->id, SILC_ID_SERVER)));
573
574         if (from) {
575           if (client->router == from) {
576             /* Skip clients that are *really* owned by the `from' */
577             if (remove_from && SILC_ID_COMPARE(from->id, client->id, 
578                                                client->id->ip.data_len)) {
579               SILC_LOG_DEBUG(("Found really owned client, skip it"));
580               if (!silc_idcache_list_next(list, &id_cache))
581                 break;
582               else
583                 continue;
584             }
585
586             if (resolve_real_server) {
587               client->router = 
588                 silc_server_update_clients_by_real_server(server, from, client,
589                                                           local, id_cache);
590               if (!client->router)
591                 client->router = from;
592             } else {
593               client->router = to;
594             }
595           }
596         } else {
597           /* All are changed */
598           client->router = to;
599         }
600
601         if (client->router)
602           SILC_LOG_DEBUG(("Client changed to %s", 
603                           silc_id_render(client->router->id, SILC_ID_CLIENT)));
604
605         if (!silc_idcache_list_next(list, &id_cache))
606           break;
607       }
608     }
609     silc_idcache_list_free(list);
610   }
611
612   if (remove_from)
613     /* Now remove the clients that are still marked as orignated from the
614        `from'. These are the clients that really was owned by the `from' and
615        not just exist behind the `from'. */
616     silc_server_remove_clients_by_server(server, from, from, TRUE);
617 }
618
619 /* Updates servers that are from `from' to be originated from `to'.  This
620    will also update the server's connection to `to's connection. */
621
622 void silc_server_update_servers_by_server(SilcServer server, 
623                                           SilcServerEntry from,
624                                           SilcServerEntry to)
625 {
626   SilcIDCacheList list = NULL;
627   SilcIDCacheEntry id_cache = NULL;
628   SilcServerEntry server_entry = NULL;
629
630   SILC_LOG_DEBUG(("Updating servers"));
631
632   if (silc_idcache_get_all(server->local_list->servers, &list)) {
633     if (silc_idcache_list_first(list, &id_cache)) {
634       while (id_cache) {
635         server_entry = (SilcServerEntry)id_cache->context;
636
637         /* If entry is local to us, do not switch it to any anyone else,
638            it is ours. */
639         if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
640             server_entry == from) {
641           if (!silc_idcache_list_next(list, &id_cache))
642             break;
643           else
644             continue;
645         }
646
647         /* If we are standalone router, any server that is not directly
648            connected to cannot exist anymore.  If we are not standalone
649            we update it correctly. */
650         if (server->server_type == SILC_ROUTER && server->standalone) {
651           silc_server_backup_del(server, server_entry);
652           silc_server_backup_replaced_del(server, server_entry);
653           silc_idlist_del_data(server_entry);
654           silc_idlist_del_server(server->local_list, server_entry);
655           server->stat.servers--;
656           server->stat.cell_servers--;
657         } else {
658           /* XXX if we are not standalone, do a check from local config
659              whether this server is in our cell, but not connected to
660              us (in which case we must remove it). */
661
662           if (server_entry->router == from) {
663             SILC_LOG_DEBUG(("Updating server (local) %s",
664                             server_entry->server_name ? 
665                             server_entry->server_name : ""));
666             server_entry->router = to;
667             server_entry->connection = to->connection;
668           }
669         }
670
671         if (!silc_idcache_list_next(list, &id_cache))
672           break;
673       }
674     }
675     silc_idcache_list_free(list);
676   }
677
678   if (silc_idcache_get_all(server->global_list->servers, &list)) {
679     if (silc_idcache_list_first(list, &id_cache)) {
680       while (id_cache) {
681         server_entry = (SilcServerEntry)id_cache->context;
682
683         /* If entry is local to us, do not switch it to anyone else,
684            it is ours. */
685         if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
686             server_entry == from) {
687           if (!silc_idcache_list_next(list, &id_cache))
688             break;
689           else
690             continue;
691         }
692
693         /* If we are standalone router, any server that is not directly
694            connected to cannot exist anymore.  If we are not standalone
695            we update it correctly. */
696         if (server->server_type == SILC_ROUTER && server->standalone) {
697           silc_server_backup_del(server, server_entry);
698           silc_server_backup_replaced_del(server, server_entry);
699           silc_idlist_del_data(server_entry);
700           silc_idlist_del_server(server->global_list, server_entry);
701           server->stat.servers--;
702           server->stat.cell_servers--;
703         } else {
704           /* XXX if we are not standalone, do a check from local config
705              whether this server is in our cell, but not connected to
706              us (in which case we must remove it). */
707
708           if (server_entry->router == from) {
709             SILC_LOG_DEBUG(("Updating server (global) %s",
710                             server_entry->server_name ? 
711                             server_entry->server_name : ""));
712             server_entry->router = to;
713             server_entry->connection = to->connection;
714           }
715         }
716
717         if (!silc_idcache_list_next(list, &id_cache))
718           break;
719       }
720     }
721     silc_idcache_list_free(list);
722   }
723 }
724
725
726 /* Toggles the enabled/disabled status of local server connections.  Packets
727    can be sent to the servers when `toggle_enabled' is TRUE and will be
728    dropped if `toggle_enabled' is FALSE, after this function is called. */
729
730 void silc_server_local_servers_toggle_enabled(SilcServer server,
731                                               bool toggle_enabled)
732 {
733   SilcIDCacheList list = NULL;
734   SilcIDCacheEntry id_cache = NULL;
735   SilcServerEntry server_entry = NULL;
736
737   if (silc_idcache_get_all(server->local_list->servers, &list)) {
738     if (silc_idcache_list_first(list, &id_cache)) {
739       while (id_cache) {
740         server_entry = (SilcServerEntry)id_cache->context;
741         if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
742           if (!silc_idcache_list_next(list, &id_cache))
743             break;
744           else
745             continue;
746         }
747
748         if (toggle_enabled)
749           server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
750         else
751           server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
752
753         if (!silc_idcache_list_next(list, &id_cache))
754           break;
755       }
756     }
757     silc_idcache_list_free(list);
758   }
759
760   if (silc_idcache_get_all(server->global_list->servers, &list)) {
761     if (silc_idcache_list_first(list, &id_cache)) {
762       while (id_cache) {
763         server_entry = (SilcServerEntry)id_cache->context;
764         if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
765           if (!silc_idcache_list_next(list, &id_cache))
766             break;
767           else
768             continue;
769         }
770
771         if (toggle_enabled)
772           server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
773         else
774           server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
775
776         if (!silc_idcache_list_next(list, &id_cache))
777           break;
778       }
779     }
780     silc_idcache_list_free(list);
781   }
782 }
783
784 /* Removes servers that are originated from the `from'.  The server
785    entry is deleted in this function.  If `remove_clients' is TRUE then
786    all clients originated from the server are removed too, and server
787    signoff is sent.  Note that this does not remove the `from'.  This
788    also does not remove locally connected servers. */
789
790 void silc_server_remove_servers_by_server(SilcServer server,
791                                           SilcServerEntry from,
792                                           bool remove_clients)
793 {
794   SilcIDCacheList list = NULL;
795   SilcIDCacheEntry id_cache = NULL;
796   SilcServerEntry server_entry = NULL;
797
798   SILC_LOG_DEBUG(("Removing servers by %s",
799                   from->server_name ? from->server_name : "server"));
800
801   if (silc_idcache_get_all(server->local_list->servers, &list)) {
802     if (silc_idcache_list_first(list, &id_cache)) {
803       while (id_cache) {
804         server_entry = (SilcServerEntry)id_cache->context;
805         if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
806           server_entry->router != from || server_entry == from) {
807           if (!silc_idcache_list_next(list, &id_cache))
808             break;
809           else
810             continue;
811         }
812
813         /* Remove clients owned by this server */
814         if (remove_clients)
815           silc_server_remove_clients_by_server(server, from, server_entry,
816                                                TRUE);
817
818         /* Remove the server */
819         silc_idlist_del_server(server->local_list, server_entry);
820
821         if (!silc_idcache_list_next(list, &id_cache))
822           break;
823       }
824     }
825     silc_idcache_list_free(list);
826   }
827
828   if (silc_idcache_get_all(server->global_list->servers, &list)) {
829     if (silc_idcache_list_first(list, &id_cache)) {
830       while (id_cache) {
831         server_entry = (SilcServerEntry)id_cache->context;
832         if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
833           server_entry->router != from || server_entry == from) {
834           if (!silc_idcache_list_next(list, &id_cache))
835             break;
836           else
837             continue;
838         }
839
840         /* Remove clients owned by this server */
841         if (remove_clients)
842           silc_server_remove_clients_by_server(server, from, server_entry,
843                                                TRUE);
844
845         /* Remove the server */
846         silc_idlist_del_server(server->global_list, server_entry);
847
848         if (!silc_idcache_list_next(list, &id_cache))
849           break;
850       }
851     }
852     silc_idcache_list_free(list);
853   }
854 }
855
856 /* Removes channels that are from `from. */
857
858 void silc_server_remove_channels_by_server(SilcServer server, 
859                                            SilcServerEntry from)
860 {
861   SilcIDCacheList list = NULL;
862   SilcIDCacheEntry id_cache = NULL;
863   SilcChannelEntry channel = NULL;
864
865   SILC_LOG_DEBUG(("Removing channels by server"));
866
867   if (silc_idcache_get_all(server->global_list->channels, &list)) {
868     if (silc_idcache_list_first(list, &id_cache)) {
869       while (id_cache) {
870         channel = (SilcChannelEntry)id_cache->context;
871         if (channel->router == from)
872           silc_idlist_del_channel(server->global_list, channel);
873         if (!silc_idcache_list_next(list, &id_cache))
874           break;
875       }
876     }
877     silc_idcache_list_free(list);
878   }
879 }
880
881 /* Updates channels that are from `from' to be originated from `to'.  */
882
883 void silc_server_update_channels_by_server(SilcServer server, 
884                                            SilcServerEntry from,
885                                            SilcServerEntry to)
886 {
887   SilcIDCacheList list = NULL;
888   SilcIDCacheEntry id_cache = NULL;
889   SilcChannelEntry channel = NULL;
890
891   SILC_LOG_DEBUG(("Updating channels by server"));
892
893   if (silc_idcache_get_all(server->global_list->channels, &list)) {
894     if (silc_idcache_list_first(list, &id_cache)) {
895       while (id_cache) {
896         channel = (SilcChannelEntry)id_cache->context;
897         if (channel->router == from)
898           channel->router = to;
899         if (!silc_idcache_list_next(list, &id_cache))
900           break;
901       }
902     }
903     silc_idcache_list_free(list);
904   }
905 }
906
907 /* Checks whether given channel has global users.  If it does this returns
908    TRUE and FALSE if there is only locally connected clients on the channel. */
909
910 bool silc_server_channel_has_global(SilcChannelEntry channel)
911 {
912   SilcChannelClientEntry chl;
913   SilcHashTableList htl;
914
915   silc_hash_table_list(channel->user_list, &htl);
916   while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
917     if (chl->client->router) {
918       silc_hash_table_list_reset(&htl);
919       return TRUE;
920     }
921   }
922   silc_hash_table_list_reset(&htl);
923
924   return FALSE;
925 }
926
927 /* Checks whether given channel has locally connected users.  If it does this
928    returns TRUE and FALSE if there is not one locally connected client. */
929
930 bool silc_server_channel_has_local(SilcChannelEntry channel)
931 {
932   SilcChannelClientEntry chl;
933   SilcHashTableList htl;
934
935   silc_hash_table_list(channel->user_list, &htl);
936   while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
937     if (!chl->client->router) {
938       silc_hash_table_list_reset(&htl);
939       return TRUE;
940     }
941   }
942   silc_hash_table_list_reset(&htl);
943
944   return FALSE;
945 }
946
947 /* This function removes the channel and all users on the channel, unless
948    the channel is permanent.  In this case the channel is disabled but all
949    users are removed from the channel.  Returns TRUE if the channel is
950    destroyed totally, and FALSE if it is permanent and remains. */
951
952 bool silc_server_channel_delete(SilcServer server,
953                                 SilcChannelEntry channel)
954 {
955   SilcChannelClientEntry chl;
956   SilcHashTableList htl;
957   bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
958
959   if (delchan) {
960     SILC_LOG_DEBUG(("Deleting %s channel", channel->channel_name));
961
962     /* Update statistics */
963     if (server->server_type == SILC_ROUTER)
964       server->stat.chanclients -= channel->user_count;
965
966     /* Totally delete the channel and all users on the channel. The
967        users are deleted automatically in silc_idlist_del_channel. */
968     silc_schedule_task_del_by_context(server->schedule, channel->rekey);
969     if (silc_idlist_del_channel(server->local_list, channel)) {
970       server->stat.my_channels--;
971       if (server->server_type == SILC_ROUTER) {
972         server->stat.channels--;
973         server->stat.cell_channels--;
974       }
975     } else {
976       if (silc_idlist_del_channel(server->global_list, channel))
977         if (server->server_type == SILC_ROUTER)
978           server->stat.channels--;
979     }
980
981     return FALSE;
982   }
983
984   /* Channel is permanent, do not remove it, remove only users */
985   channel->disabled = TRUE;
986   silc_hash_table_list(channel->user_list, &htl);
987   while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
988     silc_hash_table_del(chl->client->channels, channel);
989     silc_hash_table_del(channel->user_list, chl->client);
990     channel->user_count--;
991
992     /* Update statistics */
993     if (SILC_IS_LOCAL(chl->client))
994       server->stat.my_chanclients--;
995     if (server->server_type == SILC_ROUTER) {
996       server->stat.cell_chanclients--;
997       server->stat.chanclients--;
998     }
999
1000     silc_free(chl);
1001   }
1002   silc_hash_table_list_reset(&htl);
1003
1004   SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
1005
1006   return TRUE;
1007 }
1008
1009 /* Returns TRUE if the given client is on the channel.  FALSE if not. 
1010    This works because we assure that the user list on the channel is
1011    always in up to date thus we can only check the channel list from 
1012    `client' which is faster than checking the user list from `channel'. */
1013
1014 bool silc_server_client_on_channel(SilcClientEntry client,
1015                                    SilcChannelEntry channel,
1016                                    SilcChannelClientEntry *chl)
1017 {
1018   if (!client || !channel)
1019     return FALSE;
1020
1021   return silc_hash_table_find(client->channels, channel, NULL, 
1022                               (void **)chl);
1023 }
1024
1025 /* Checks string for bad characters and returns TRUE if they are found. */
1026
1027 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
1028 {
1029   int i;
1030
1031   for (i = 0; i < name_len; i++) {
1032     if (!isascii(name[i]))
1033       return TRUE;
1034     if (name[i] <= 32) return TRUE;
1035     if (name[i] == ' ') return TRUE;
1036     if (name[i] == '*') return TRUE;
1037     if (name[i] == '?') return TRUE;
1038     if (name[i] == ',') return TRUE;
1039   }
1040
1041   return FALSE;
1042 }
1043
1044 /* Modifies the `name' if it includes bad characters and returns new
1045    allocated name that does not include bad characters. */
1046
1047 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
1048 {
1049   int i;
1050   char *newname = strdup(name);
1051
1052   for (i = 0; i < name_len; i++) {
1053     if (!isascii(newname[i])) newname[i] = '_';
1054     if (newname[i] <= 32) newname[i] = '_';
1055     if (newname[i] == ' ') newname[i] = '_';
1056     if (newname[i] == '*') newname[i] = '_';
1057     if (newname[i] == '?') newname[i] = '_';
1058     if (newname[i] == ',') newname[i] = '_';
1059   }
1060
1061   return newname;
1062 }
1063
1064 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
1065    socket connections with the IP address does not exist. */
1066
1067 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
1068                                          SilcSocketType type)
1069 {
1070   int i, count;
1071
1072   for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1073     if (server->sockets[i] && !strcmp(server->sockets[i]->ip, ip) &&
1074         server->sockets[i]->type == type)
1075       count++;
1076   }
1077
1078   return count;
1079 }
1080
1081 /* Find number of sockets by IP address indicated by remote host, indicatd
1082    by `ip' or `hostname', `port', and `type'.  Returns 0 if socket connections
1083    does not exist. If `ip' is provided then `hostname' is ignored. */
1084
1085 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server, 
1086                                              const char *ip,
1087                                              const char *hostname,
1088                                              SilcUInt16 port,
1089                                              SilcSocketType type)
1090 {
1091   int i, count;
1092
1093   if (!ip && !hostname)
1094     return 0;
1095
1096   for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1097     if (server->sockets[i] && 
1098         ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
1099          (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
1100         server->sockets[i]->port == port &&
1101         server->sockets[i]->type == type)
1102       count++;
1103   }
1104
1105   return count;
1106 }
1107
1108 /* Finds locally cached public key by the public key received in the SKE. 
1109    If we have it locally cached then we trust it and will use it in the
1110    authentication protocol.  Returns the locally cached public key or NULL
1111    if we do not find the public key.  */
1112
1113 SilcPublicKey silc_server_find_public_key(SilcServer server, 
1114                                           SilcHashTable local_public_keys,
1115                                           SilcPublicKey remote_public_key)
1116 {
1117   SilcPublicKey cached_key;
1118
1119   SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
1120                   silc_hash_table_count(local_public_keys)));
1121
1122   if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
1123                                 (void **)&cached_key, NULL, 
1124                                 silc_hash_public_key, NULL,
1125                                 silc_hash_public_key_compare, NULL)) {
1126     SILC_LOG_ERROR(("Public key not found"));
1127     return NULL;
1128   }
1129
1130   SILC_LOG_DEBUG(("Found public key"));
1131
1132   return cached_key;
1133 }
1134
1135 /* This returns the first public key from the table of public keys.  This
1136    is used only in cases where single public key exists in the table and
1137    we want to get a pointer to it.  For public key tables that has multiple
1138    keys in it the silc_server_find_public_key must be used. */
1139
1140 SilcPublicKey silc_server_get_public_key(SilcServer server,
1141                                          SilcHashTable local_public_keys)
1142 {
1143   SilcPublicKey cached_key;
1144   SilcHashTableList htl;
1145
1146   SILC_LOG_DEBUG(("Start"));
1147
1148   assert(silc_hash_table_count(local_public_keys) < 2);
1149
1150   silc_hash_table_list(local_public_keys, &htl);
1151   if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
1152     return NULL;
1153   silc_hash_table_list_reset(&htl);
1154
1155   return cached_key;
1156 }
1157
1158 /* Check whether the connection `sock' is allowed to connect to us.  This
1159    checks for example whether there is too much connections for this host,
1160    and required version for the host etc. */
1161
1162 bool silc_server_connection_allowed(SilcServer server, 
1163                                     SilcSocketConnection sock,
1164                                     SilcSocketType type,
1165                                     SilcServerConfigConnParams *global,
1166                                     SilcServerConfigConnParams *params,
1167                                     SilcSKE ske)
1168 {
1169   SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
1170                             server->stat.my_clients :
1171                             type == SILC_SOCKET_TYPE_SERVER ?
1172                             server->stat.my_servers :
1173                             server->stat.my_routers);
1174   SilcUInt32 num_sockets, max_hosts, max_per_host;
1175   SilcUInt32 r_protocol_version, l_protocol_version;
1176   SilcUInt32 r_software_version, l_software_version;
1177   char *r_vendor_version = NULL, *l_vendor_version;
1178
1179   SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1180
1181   /* Check version */
1182
1183   l_protocol_version = 
1184     silc_version_to_num(params && params->version_protocol ? 
1185                         params->version_protocol : 
1186                         global->version_protocol);
1187   l_software_version = 
1188     silc_version_to_num(params && params->version_software ? 
1189                         params->version_software : 
1190                         global->version_software);
1191   l_vendor_version = (params && params->version_software_vendor ? 
1192                       params->version_software_vendor : 
1193                       global->version_software_vendor);
1194   
1195   if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1196                                     &r_software_version, NULL,
1197                                     &r_vendor_version)) {
1198     sock->version = r_protocol_version;
1199
1200     /* Match protocol version */
1201     if (l_protocol_version && r_protocol_version &&
1202         r_protocol_version < l_protocol_version) {
1203       SILC_LOG_INFO(("Connection %s (%s) is too old version",
1204                      sock->hostname, sock->ip));
1205       silc_server_disconnect_remote(server, sock, 
1206                                     SILC_STATUS_ERR_BAD_VERSION,
1207                                     "You support too old protocol version");
1208       return FALSE;
1209     }
1210
1211     /* Math software version */
1212     if (l_software_version && r_software_version &&
1213         r_software_version < l_software_version) {
1214       SILC_LOG_INFO(("Connection %s (%s) is too old version",
1215                      sock->hostname, sock->ip));
1216       silc_server_disconnect_remote(server, sock, 
1217                                     SILC_STATUS_ERR_BAD_VERSION,
1218                                     "You support too old software version");
1219       return FALSE;
1220     }
1221
1222     /* Regex match vendor version */
1223     if (l_vendor_version && r_vendor_version && 
1224         !silc_string_match(l_vendor_version, r_vendor_version)) {
1225       SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1226                      sock->hostname, sock->ip));
1227       silc_server_disconnect_remote(server, sock, 
1228                                     SILC_STATUS_ERR_BAD_VERSION,
1229                                     "Your software is not supported");
1230       return FALSE;
1231     }
1232   }
1233   silc_free(r_vendor_version);
1234
1235   /* Check for maximum connections limit */
1236
1237   num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
1238   max_hosts = (params ? params->connections_max : global->connections_max);
1239   max_per_host = (params ? params->connections_max_per_host :
1240                   global->connections_max_per_host);
1241
1242   if (max_hosts && conn_number >= max_hosts) {
1243     SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1244                    sock->hostname, sock->ip));
1245     silc_server_disconnect_remote(server, sock, 
1246                                   SILC_STATUS_ERR_RESOURCE_LIMIT,
1247                                   "Server is full, try again later");
1248     return FALSE;
1249   }
1250
1251   if (num_sockets >= max_per_host) {
1252     SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1253                    sock->hostname, sock->ip));
1254     silc_server_disconnect_remote(server, sock, 
1255                                   SILC_STATUS_ERR_RESOURCE_LIMIT,
1256                                   "Too many connections from your host");
1257     return FALSE;
1258   }
1259
1260   return TRUE;
1261 }
1262
1263 /* Checks that client has rights to add or remove channel modes. If any
1264    of the checks fails FALSE is returned. */
1265
1266 bool silc_server_check_cmode_rights(SilcServer server,
1267                                     SilcChannelEntry channel,
1268                                     SilcChannelClientEntry client,
1269                                     SilcUInt32 mode)
1270 {
1271   bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1272   bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1273
1274   /* Check whether has rights to change anything */
1275   if (!is_op && !is_fo)
1276     return FALSE;
1277
1278   /* Check whether has rights to change everything */
1279   if (is_op && is_fo)
1280     return TRUE;
1281
1282   /* Founder implies operator */
1283   if (is_fo)
1284     is_op = TRUE;
1285
1286   /* We know that client is channel operator, check that they are not
1287      changing anything that requires channel founder rights. Rest of the
1288      modes are available automatically for channel operator. */
1289
1290   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1291     if (is_op && !is_fo)
1292       return FALSE;
1293   } else {
1294     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1295       if (is_op && !is_fo)
1296         return FALSE;
1297     }
1298   }
1299   
1300   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1301     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1302       if (is_op && !is_fo)
1303         return FALSE;
1304     }
1305   } else {
1306     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1307       if (is_op && !is_fo)
1308         return FALSE;
1309     }
1310   }
1311
1312   if (mode & SILC_CHANNEL_MODE_CIPHER) {
1313     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1314       if (is_op && !is_fo)
1315         return FALSE;
1316     }
1317   } else {
1318     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1319       if (is_op && !is_fo)
1320         return FALSE;
1321     }
1322   }
1323   
1324   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1325     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1326       if (is_op && !is_fo)
1327         return FALSE;
1328     }
1329   } else {
1330     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1331       if (is_op && !is_fo)
1332         return FALSE;
1333     }
1334   }
1335   
1336   if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1337     if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1338       if (is_op && !is_fo)
1339         return FALSE;
1340     }
1341   } else {
1342     if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1343       if (is_op && !is_fo)
1344         return FALSE;
1345     }
1346   }
1347   
1348   if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1349     if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1350       if (is_op && !is_fo)
1351         return FALSE;
1352     }
1353   } else {
1354     if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1355       if (is_op && !is_fo)
1356         return FALSE;
1357     }
1358   }
1359   
1360   return TRUE;
1361 }
1362
1363 /* Check that the client has rights to change its user mode.  Returns
1364    FALSE if setting some mode is not allowed. */
1365
1366 bool silc_server_check_umode_rights(SilcServer server,
1367                                     SilcClientEntry client,
1368                                     SilcUInt32 mode)
1369 {
1370   bool server_op = FALSE, router_op = FALSE;
1371
1372   if (mode & SILC_UMODE_SERVER_OPERATOR) {
1373     /* Cannot set server operator mode (must use OPER command) */
1374     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1375       return FALSE;
1376   } else {
1377     /* Remove the server operator rights */
1378     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1379       server_op = TRUE;
1380   }
1381
1382   if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1383     /* Cannot set router operator mode (must use SILCOPER command) */
1384     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1385       return FALSE;
1386   } else {
1387     /* Remove the router operator rights */
1388     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1389       router_op = TRUE;
1390   }
1391
1392   if (server_op)
1393     SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1394   if (router_op)
1395     SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1396
1397   return TRUE;
1398 }
1399
1400 /* This function is used to send the notify packets and motd to the
1401    incoming client connection. */
1402
1403 void silc_server_send_connect_notifys(SilcServer server,
1404                                       SilcSocketConnection sock,
1405                                       SilcClientEntry client)
1406 {
1407   SilcIDListData idata = (SilcIDListData)client;
1408
1409   SILC_LOG_DEBUG(("Send welcome notifys"));
1410
1411   /* Send some nice info to the client */
1412   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1413                           ("Welcome to the SILC Network %s",
1414                            client->username));
1415   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1416                           ("Your host is %s, running version %s",
1417                            server->server_name, server_version));
1418
1419   if (server->server_type == SILC_ROUTER) {
1420     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1421                             ("There are %d clients, %d servers and %d "
1422                              "routers in SILC Network",
1423                              server->stat.clients, server->stat.servers + 1,
1424                              server->stat.routers));
1425   } else {
1426     if (server->stat.clients && server->stat.servers + 1)
1427       SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1428                               ("There are %d clients, %d servers and %d "
1429                                "routers in SILC Network",
1430                                server->stat.clients, server->stat.servers + 1,
1431                                (server->standalone ? 0 :
1432                                 !server->stat.routers ? 1 :
1433                                 server->stat.routers)));
1434   }
1435
1436   if (server->stat.cell_clients && server->stat.cell_servers + 1)
1437     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1438                             ("There are %d clients on %d server in our cell",
1439                              server->stat.cell_clients,
1440                              server->stat.cell_servers + 1));
1441   if (server->server_type == SILC_ROUTER) {
1442     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1443                             ("I have %d clients, %d channels, %d servers and "
1444                              "%d routers",
1445                              server->stat.my_clients, 
1446                              server->stat.my_channels,
1447                              server->stat.my_servers,
1448                              server->stat.my_routers));
1449   } else {
1450     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1451                             ("I have %d clients and %d channels formed",
1452                              server->stat.my_clients,
1453                              server->stat.my_channels));
1454   }
1455
1456   if (server->stat.server_ops || server->stat.router_ops)
1457     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1458                             ("There are %d server operators and %d router "
1459                              "operators online",
1460                              server->stat.server_ops,
1461                              server->stat.router_ops));
1462   if (server->stat.my_router_ops + server->stat.my_server_ops)
1463     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1464                             ("I have %d operators online",
1465                              server->stat.my_router_ops +
1466                              server->stat.my_server_ops));
1467
1468   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1469                           ("Your connection is secured with %s cipher, "
1470                            "key length %d bits",
1471                            idata->send_key->cipher->name,
1472                            idata->send_key->cipher->key_len));
1473   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1474                           ("Your current nickname is %s",
1475                            client->nickname));
1476
1477   /* Send motd */
1478   silc_server_send_motd(server, sock);
1479 }
1480
1481 /* Kill the client indicated by `remote_client' sending KILLED notify
1482    to the client, to all channels client has joined and to primary
1483    router if needed.  The killed client is also removed from all channels. */
1484
1485 void silc_server_kill_client(SilcServer server,
1486                              SilcClientEntry remote_client,
1487                              const char *comment,
1488                              void *killer_id,
1489                              SilcIdType killer_id_type)
1490 {
1491   SilcBuffer killed, killer;
1492
1493   SILC_LOG_DEBUG(("Killing client %s", 
1494                   silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1495
1496   /* Send the KILL notify packets. First send it to the channel, then
1497      to our primary router and then directly to the client who is being
1498      killed right now. */
1499
1500   killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1501   killer = silc_id_payload_encode(killer_id, killer_id_type);
1502
1503   /* Send KILLED notify to the channels. It is not sent to the client
1504      as it will be sent differently destined directly to the client and not
1505      to the channel. */
1506   silc_server_send_notify_on_channels(server, remote_client, 
1507                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
1508                                       3, killed->data, killed->len,
1509                                       comment, comment ? strlen(comment) : 0,
1510                                       killer->data, killer->len);
1511
1512   /* Send KILLED notify to primary route */
1513   silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1514                                  SILC_BROADCAST(server), remote_client->id,
1515                                  comment, killer_id, killer_id_type);
1516
1517   /* Send KILLED notify to the client directly */
1518   if (remote_client->connection || remote_client->router)
1519     silc_server_send_notify_killed(server, remote_client->connection ? 
1520                                    remote_client->connection : 
1521                                    remote_client->router->connection, FALSE,
1522                                    remote_client->id, comment, 
1523                                    killer_id, killer_id_type);
1524
1525   /* Remove the client from all channels. This generates new keys to the
1526      channels as well. */
1527   silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
1528                                    NULL, TRUE);
1529
1530   /* Remove the client entry, If it is locally connected then we will also
1531      disconnect the client here */
1532   if (remote_client->connection) {
1533     /* Remove locally conneted client */
1534     SilcSocketConnection sock = remote_client->connection;
1535     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1536     silc_server_close_connection(server, sock);
1537   } else {
1538     /* Update statistics */
1539     server->stat.clients--;
1540     if (server->stat.cell_clients)
1541       server->stat.cell_clients--;
1542     SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1543     SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1544
1545     if (SILC_IS_LOCAL(remote_client)) {
1546       server->stat.my_clients--;
1547       silc_schedule_task_del_by_context(server->schedule, remote_client);
1548       silc_idlist_del_data(remote_client);
1549     }
1550
1551     /* Remove remote client */
1552     if (!silc_idlist_del_client(server->global_list, remote_client)) {
1553       /* Remove this client from watcher list if it is */
1554       silc_server_del_from_watcher_list(server, remote_client);
1555       silc_idlist_del_client(server->local_list, remote_client);  
1556     }
1557   }
1558
1559   silc_buffer_free(killer);
1560   silc_buffer_free(killed);
1561 }
1562
1563 typedef struct {
1564   SilcServer server;
1565   SilcClientEntry client;
1566   SilcNotifyType notify;
1567   const char *new_nick;
1568 } WatcherNotifyContext;
1569
1570 static void 
1571 silc_server_check_watcher_list_foreach(void *key, void *context, 
1572                                        void *user_context)
1573 {
1574   WatcherNotifyContext *notify = user_context;
1575   SilcClientEntry entry = context;
1576   SilcSocketConnection sock;
1577
1578   if (entry == notify->client)
1579     return;
1580
1581   sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1582                                       NULL, NULL);
1583   if (sock) {
1584     SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1585                     silc_id_render(entry->id, SILC_ID_CLIENT)));
1586
1587     /* Send the WATCH notify */
1588     silc_server_send_notify_watch(notify->server, sock, entry, 
1589                                   notify->client, 
1590                                   notify->new_nick ? notify->new_nick :
1591                                   (const char *)notify->client->nickname, 
1592                                   notify->notify);
1593   }
1594 }
1595
1596 /* This function checks whether the `client' nickname is being watched
1597    by someone, and notifies the watcher of the notify change of notify
1598    type indicated by `notify'. */
1599
1600 bool silc_server_check_watcher_list(SilcServer server,
1601                                     SilcClientEntry client,
1602                                     const char *new_nick,
1603                                     SilcNotifyType notify)
1604 {
1605   unsigned char hash[16];
1606   WatcherNotifyContext n;
1607
1608   SILC_LOG_DEBUG(("Checking watcher list %s",
1609                   client->nickname ? client->nickname : (unsigned char *)""));
1610
1611   /* If the watching is rejected by the client do nothing */
1612   if (client->mode & SILC_UMODE_REJECT_WATCHING)
1613     return FALSE;
1614
1615   /* Make hash from the nick, or take it from Client ID */
1616   if (client->nickname) {
1617     char nick[128 + 1];
1618     memset(nick, 0, sizeof(nick));
1619     silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1620     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1621   } else {
1622     memset(hash, 0, sizeof(hash));
1623     memcpy(hash, client->id->hash, sizeof(client->id->hash));
1624   }
1625
1626   n.server = server;
1627   n.client = client;
1628   n.new_nick = new_nick;
1629   n.notify = notify;
1630
1631   /* Send notify to all watchers */
1632   silc_hash_table_find_foreach(server->watcher_list, hash,
1633                                silc_server_check_watcher_list_foreach, &n);
1634
1635   return TRUE;
1636 }
1637
1638 /* Remove the `client' from watcher list. After calling this the `client'
1639    is not watching any nicknames. */
1640
1641 bool silc_server_del_from_watcher_list(SilcServer server,
1642                                        SilcClientEntry client)
1643 {
1644   SilcHashTableList htl;
1645   void *key;
1646   SilcClientEntry entry;
1647   bool found = FALSE;
1648
1649   silc_hash_table_list(server->watcher_list, &htl);
1650   while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1651     if (entry == client) {
1652       silc_hash_table_del_by_context(server->watcher_list, key, client);
1653
1654       if (client->id)
1655         SILC_LOG_DEBUG(("Removing %s from WATCH list",
1656                         silc_id_render(client->id, SILC_ID_CLIENT)));
1657
1658       /* Now check whether there still exists entries with this key, if not
1659          then free the key to not leak memory. */
1660       if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1661         silc_free(key);
1662
1663       found = TRUE;
1664     }
1665   }
1666   silc_hash_table_list_reset(&htl);
1667
1668   return found;
1669 }
1670
1671 /* Force the client indicated by `chl' to change the channel user mode
1672    on channel indicated by `channel' to `forced_mode'. */
1673
1674 bool silc_server_force_cumode_change(SilcServer server,
1675                                      SilcSocketConnection sock,
1676                                      SilcChannelEntry channel,
1677                                      SilcChannelClientEntry chl,
1678                                      SilcUInt32 forced_mode)
1679 {
1680   SilcBuffer idp1, idp2;
1681   unsigned char cumode[4];
1682
1683   SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1684
1685   if (sock)
1686     silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1687                                    server->id, SILC_ID_SERVER,
1688                                    chl->client->id, NULL);
1689
1690   idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1691   idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1692   SILC_PUT32_MSB(forced_mode, cumode);
1693   silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1694                                      SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1695                                      3, idp1->data, idp1->len,
1696                                      cumode, sizeof(cumode),
1697                                      idp2->data, idp2->len);
1698   silc_buffer_free(idp1);
1699   silc_buffer_free(idp2);
1700
1701   return TRUE;
1702 }
1703
1704 /* Find active socket connection by the IP address and port indicated by
1705    `ip' and `port', and socket connection type of `type'. */
1706
1707 SilcSocketConnection
1708 silc_server_find_socket_by_host(SilcServer server,
1709                                 SilcSocketType type,
1710                                 const char *ip, SilcUInt16 port)
1711 {
1712   int i;
1713
1714   for (i = 0; i < server->config->param.connections_max; i++) {
1715     if (!server->sockets[i])
1716       continue;
1717     if (!strcmp(server->sockets[i]->ip, ip) &&
1718         (!port || server->sockets[i]->port == port) &&
1719         server->sockets[i]->type == type)
1720       return server->sockets[i];
1721   }
1722
1723   return NULL;
1724 }