The SILC Project

source navigation ]
identifier search ]
freetext search ]
file search ]

silc/silcd/server.c

  1 /*
  2 
  3   server.c
  4 
  5   Author: Pekka Riikonen <priikone@silcnet.org>
  6 
  7   Copyright (C) 1997 - 2005 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 /*
 20  * This is the actual SILC server than handles everything relating to
 21  * servicing the SILC connections. This is also a SILC router as a router
 22  * is also normal server.
 23  */
 24 /* $Id: server.c,v 1.347 2005/04/23 13:32:24 priikone Exp $ */
 25 
 26 #include "serverincludes.h"
 27 #include "server_internal.h"
 28 
 29 /* Static prototypes */
 30 SILC_TASK_CALLBACK(silc_server_rehash_close_connection);
 31 SILC_TASK_CALLBACK(silc_server_connect_to_router_retry);
 32 SILC_TASK_CALLBACK(silc_server_connect_router);
 33 SILC_TASK_CALLBACK(silc_server_connect_to_router_second);
 34 SILC_TASK_CALLBACK(silc_server_connect_to_router_final);
 35 SILC_TASK_CALLBACK(silc_server_accept_new_connection);
 36 SILC_TASK_CALLBACK(silc_server_accept_new_connection_second);
 37 SILC_TASK_CALLBACK(silc_server_accept_new_connection_final);
 38 SILC_TASK_CALLBACK(silc_server_packet_process);
 39 SILC_TASK_CALLBACK(silc_server_packet_parse_real);
 40 SILC_TASK_CALLBACK(silc_server_close_connection_final);
 41 SILC_TASK_CALLBACK(silc_server_free_client_data_timeout);
 42 SILC_TASK_CALLBACK(silc_server_timeout_remote);
 43 SILC_TASK_CALLBACK(silc_server_channel_key_rekey);
 44 SILC_TASK_CALLBACK(silc_server_get_stats);
 45 SILC_TASK_CALLBACK(silc_server_connect_router);
 46 
 47 /* Allocates a new SILC server object. This has to be done before the server
 48    can be used. After allocation one must call silc_server_init to initialize
 49    the server. The new allocated server object is returned to the new_server
 50    argument. */
 51 
 52 int silc_server_alloc(SilcServer *new_server)
 53 {
 54   SilcServer server;
 55 
 56   SILC_LOG_DEBUG(("Allocating new server object"));
 57 
 58   server = silc_calloc(1, sizeof(*server));
 59   server->server_type = SILC_SERVER;
 60   server->standalone = TRUE;
 61   server->local_list = silc_calloc(1, sizeof(*server->local_list));
 62   server->global_list = silc_calloc(1, sizeof(*server->global_list));
 63   server->pending_commands = silc_dlist_init();
 64 #ifdef SILC_SIM
 65   server->sim = silc_dlist_init();
 66 #endif
 67 
 68   *new_server = server;
 69 
 70   return TRUE;
 71 }
 72 
 73 /* Free's the SILC server object. This is called at the very end before
 74    the program ends. */
 75 
 76 void silc_server_free(SilcServer server)
 77 {
 78   SilcIDCacheList list;
 79   SilcIDCacheEntry cache;
 80 
 81   if (!server)
 82     return;
 83 
 84 #ifdef SILC_SIM
 85   {
 86     SilcSim sim;
 87     silc_dlist_start(server->sim);
 88     while ((sim = silc_dlist_get(server->sim)) != SILC_LIST_END) {
 89       silc_dlist_del(server->sim, sim);
 90       silc_sim_close(sim);
 91       silc_sim_free(sim);
 92     }
 93     silc_dlist_uninit(server->sim);
 94   }
 95 #endif
 96 
 97   silc_server_backup_free(server);
 98   silc_server_config_unref(&server->config_ref);
 99   if (server->rng)
100     silc_rng_free(server->rng);
101   if (server->pkcs)
102     silc_pkcs_free(server->pkcs);
103   if (server->public_key)
104     silc_pkcs_public_key_free(server->public_key);
105   if (server->private_key)
106     silc_pkcs_private_key_free(server->private_key);
107   if (server->pending_commands)
108     silc_dlist_uninit(server->pending_commands);
109   if (server->id_entry)
110     silc_idlist_del_server(server->local_list, server->id_entry);
111 
112   /* Delete all channels */
113   list = NULL;
114   if (silc_idcache_get_all(server->local_list->channels, &list) &&
115       silc_idcache_list_first(list, &cache)) {
116     silc_idlist_del_channel(server->local_list, cache->context);
117     while (silc_idcache_list_next(list, &cache))
118       silc_idlist_del_channel(server->local_list, cache->context);
119   }
120   if (list)
121     silc_idcache_list_free(list);
122   list = NULL;
123   if (silc_idcache_get_all(server->global_list->channels, &list) &&
124       silc_idcache_list_first(list, &cache)) {
125     silc_idlist_del_channel(server->global_list, cache->context);
126     while (silc_idcache_list_next(list, &cache))
127       silc_idlist_del_channel(server->global_list, cache->context);
128   }
129   if (list)
130     silc_idcache_list_free(list);
131 
132   if (server->pk_hash)
133     silc_hash_table_free(server->pk_hash);
134 
135   /* Delete all clients */
136   list = NULL;
137   if (silc_idcache_get_all(server->local_list->clients, &list) &&
138       silc_idcache_list_first(list, &cache)) {
139     silc_idlist_del_client(server->local_list, cache->context);
140     while (silc_idcache_list_next(list, &cache))
141       silc_idlist_del_client(server->local_list, cache->context);
142   }
143   if (list)
144     silc_idcache_list_free(list);
145   list = NULL;
146   if (silc_idcache_get_all(server->global_list->clients, &list) &&
147       silc_idcache_list_first(list, &cache)) {
148     silc_idlist_del_client(server->global_list, cache->context);
149     while (silc_idcache_list_next(list, &cache))
150       silc_idlist_del_client(server->global_list, cache->context);
151   }
152   if (list)
153     silc_idcache_list_free(list);
154 
155 
156   /* Delete all servers */
157   list = NULL;
158   if (silc_idcache_get_all(server->local_list->servers, &list) &&
159       silc_idcache_list_first(list, &cache)) {
160     silc_idlist_del_server(server->local_list, cache->context);
161     while (silc_idcache_list_next(list, &cache))
162       silc_idlist_del_server(server->local_list, cache->context);
163   }
164   if (list)
165     silc_idcache_list_free(list);
166   list = NULL;
167   if (silc_idcache_get_all(server->global_list->servers, &list) &&
168       silc_idcache_list_first(list, &cache)) {
169     silc_idlist_del_server(server->global_list, cache->context);
170     while (silc_idcache_list_next(list, &cache))
171       silc_idlist_del_server(server->global_list, cache->context);
172   }
173   if (list)
174     silc_idcache_list_free(list);
175 
176   silc_idcache_free(server->local_list->clients);
177   silc_idcache_free(server->local_list->servers);
178   silc_idcache_free(server->local_list->channels);
179   silc_idcache_free(server->global_list->clients);
180   silc_idcache_free(server->global_list->servers);
181   silc_idcache_free(server->global_list->channels);
182   silc_hash_table_free(server->watcher_list);
183   silc_hash_table_free(server->watcher_list_pk);
184 
185   silc_hash_free(server->md5hash);
186   silc_hash_free(server->sha1hash);
187   silc_hmac_unregister_all();
188   silc_hash_unregister_all();
189   silc_cipher_unregister_all();
190   silc_pkcs_unregister_all();
191 
192   silc_free(server->local_list);
193   silc_free(server->global_list);
194   silc_free(server->server_name);
195   silc_free(server->id_string);
196   silc_free(server->purge_i);
197   silc_free(server->purge_g);
198   silc_free(server);
199 }
200 
201 /* Creates a new server listener. */
202 
203 static bool silc_server_listen(SilcServer server, const char *server_ip,
204                                SilcUInt16 port, int *sock)
205 {
206   *sock = silc_net_create_server(port, server_ip);
207   if (*sock < 0) {
208     SILC_SERVER_LOG_ERROR(("Could not create server listener: %s on %hu",
209                         server_ip, port));
210     return FALSE;
211   }
212   return TRUE;
213 }
214 
215 /* Adds a secondary listener. */
216 
217 bool silc_server_init_secondary(SilcServer server)
218 {
219   int sock = 0, sock_list[server->config->param.connections_max];
220   SilcSocketConnection newsocket = NULL;
221   SilcServerConfigServerInfoInterface *interface;
222 
223   for (interface = server->config->server_info->secondary; interface;
224         interface = interface->next, sock++) {
225 
226     if (!silc_server_listen(server,
227         interface->server_ip, interface->port, &sock_list[sock]))
228       goto err;
229 
230     /* Set socket to non-blocking mode */
231     silc_net_set_socket_nonblock(sock_list[sock]);
232 
233     /* Add ourselves also to the socket table. The entry allocated above
234        is sent as argument for fast referencing in the future. */
235     silc_socket_alloc(sock_list[sock],
236                       SILC_SOCKET_TYPE_SERVER, NULL, &newsocket);
237     server->sockets[sock_list[sock]] = newsocket;
238     SILC_SET_LISTENER(newsocket);
239 
240     /* Perform name and address lookups to resolve the listenning address
241        and port. */
242     if (!silc_net_check_local_by_sock(sock_list[sock], &newsocket->hostname,
243                             &newsocket->ip)) {
244       if ((server->config->require_reverse_lookup && !newsocket->hostname) ||
245         !newsocket->ip) {
246         SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s",
247                       newsocket->hostname ? newsocket->hostname :
248                       newsocket->ip ? newsocket->ip : ""));
249         server->stat.conn_failures++;
250         goto err;
251       }
252       if (!newsocket->hostname)
253         newsocket->hostname = strdup(newsocket->ip);
254     }
255     newsocket->port = silc_net_get_local_port(sock);
256 
257     newsocket->user_data = (void *)server->id_entry;
258     silc_schedule_task_add(server->schedule, sock_list[sock],
259                            silc_server_accept_new_connection,
260                            (void *)server, 0, 0,
261                            SILC_TASK_FD,
262                            SILC_TASK_PRI_NORMAL);
263   }
264 
265   return TRUE;
266 
267  err:
268   do silc_net_close_server(sock_list[sock--]); while (sock >= 0);
269   return FALSE;
270 }
271 
272 /* Initializes the entire SILC server. This is called always before running
273    the server. This is called only once at the initialization of the program.
274    This binds the server to its listenning port. After this function returns
275    one should call silc_server_run to start the server. This returns TRUE
276    when everything is ok to run the server. Configuration file must be
277    read and parsed before calling this. */
278 
279 bool silc_server_init(SilcServer server)
280 {
281   int sock = -1;
282   SilcServerID *id;
283   SilcServerEntry id_entry;
284   SilcIDListPurge purge;
285   SilcSocketConnection newsocket = NULL;
286 
287   SILC_LOG_DEBUG(("Initializing server"));
288 
289   server->starttime = time(NULL);
290 
291   /* Take config object for us */
292   silc_server_config_ref(&server->config_ref, server->config,
293                          server->config);
294 
295 #ifdef SILC_DEBUG
296   /* Set debugging on if configured */
297   if (server->config->debug_string) {
298     silc_debug = TRUE;
299     silc_log_set_debug_string(server->config->debug_string);
300   }
301 #endif /* SILC_DEBUG */
302 
303   /* Steal public and private key from the config object */
304   server->public_key = server->config->server_info->public_key;
305   server->private_key = server->config->server_info->private_key;
306   server->config->server_info->public_key = NULL;
307   server->config->server_info->private_key = NULL;
308 
309   /* Register all configured ciphers, PKCS and hash functions. */
310   if (!silc_server_config_register_ciphers(server))
311     silc_cipher_register_default();
312   if (!silc_server_config_register_pkcs(server))
313     silc_pkcs_register_default();
314   if (!silc_server_config_register_hashfuncs(server))
315     silc_hash_register_default();
316   if (!silc_server_config_register_hmacs(server))
317     silc_hmac_register_default();
318 
319   /* Initialize random number generator for the server. */
320   server->rng = silc_rng_alloc();
321   silc_rng_init(server->rng);
322   silc_rng_global_init(server->rng);
323 
324   /* Initialize hash functions for server to use */
325   silc_hash_alloc("md5", &server->md5hash);
326   silc_hash_alloc("sha1", &server->sha1hash);
327 
328   /* Allocate PKCS context for local public and private keys */
329   if (!silc_pkcs_alloc(server->public_key->name, &server->pkcs))
330     goto err;
331   silc_pkcs_public_key_set(server->pkcs, server->public_key);
332   silc_pkcs_private_key_set(server->pkcs, server->private_key);
333 
334   /* Initialize the scheduler */
335   server->schedule = silc_schedule_init(server->config->param.connections_max,
336                                         server);
337   if (!server->schedule)
338     goto err;
339 
340   /* First, register log files configuration for error output */
341   silc_server_config_setlogfiles(server);
342 
343   /* Initialize ID caches */
344   server->local_list->clients =
345     silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor,
346                        server, FALSE, TRUE);
347   server->local_list->servers =
348     silc_idcache_alloc(0, SILC_ID_SERVER, NULL, NULL, FALSE, TRUE);
349   server->local_list->channels =
350     silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL, NULL, FALSE, TRUE);
351 
352   /* These are allocated for normal server as well as these hold some
353      global information that the server has fetched from its router. For
354      router these are used as they are supposed to be used on router. */
355   server->global_list->clients =
356     silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor,
357                        server, FALSE, TRUE);
358   server->global_list->servers =
359     silc_idcache_alloc(0, SILC_ID_SERVER, NULL, NULL, FALSE, TRUE);
360   server->global_list->channels =
361     silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL, NULL, FALSE, TRUE);
362 
363   /* Init watcher lists */
364   server->watcher_list =
365     silc_hash_table_alloc(1, silc_hash_client_id_hash, NULL,
366                           silc_hash_data_compare, (void *)CLIENTID_HASH_LEN,
367                           NULL, NULL, TRUE);
368   if (!server->watcher_list)
369     goto err;
370   server->watcher_list_pk =
371     silc_hash_table_alloc(1, silc_hash_public_key, NULL,
372                           silc_hash_public_key_compare, NULL,
373                           NULL, NULL, TRUE);
374   if (!server->watcher_list_pk)
375     goto err;
376 
377   /* Init public key list */
378   server->pk_hash =
379     silc_hash_table_alloc(0, silc_hash_public_key, NULL,
380                           silc_hash_public_key_compare, NULL,
381                           NULL, NULL, TRUE);
382 
383   if (!server->pk_hash)
384     goto err;
385 
386   /* Create a listening server */
387   if (!silc_server_listen(server,
388                 server->config->server_info->primary == NULL ? NULL :
389                         server->config->server_info->primary->server_ip,
390                 server->config->server_info->primary == NULL ? 0 :
391                         server->config->server_info->primary->port,
392                 &sock))
393     goto err;
394 
395   /* Set socket to non-blocking mode */
396   silc_net_set_socket_nonblock(sock);
397   server->sock = sock;
398 
399   /* Allocate the entire socket list that is used in server. Eventually
400      all connections will have entry in this table (it is a table of
401      pointers to the actual object that is allocated individually
402      later). */
403   server->sockets = silc_calloc(server->config->param.connections_max,
404                                 sizeof(*server->sockets));
405   if (!server->sockets)
406     goto err;
407 
408   /* Add ourselves also to the socket table. The entry allocated above
409      is sent as argument for fast referencing in the future. */
410   silc_socket_alloc(sock, SILC_SOCKET_TYPE_SERVER, NULL, &newsocket);
411   server->sockets[sock] = newsocket;
412   SILC_SET_LISTENER(newsocket);
413 
414   /* Perform name and address lookups to resolve the listenning address
415      and port. */
416   if (!silc_net_check_local_by_sock(sock, &newsocket->hostname,
417                                     &newsocket->ip)) {
418     if ((server->config->require_reverse_lookup && !newsocket->hostname) ||
419         !newsocket->ip) {
420       SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s",
421                       newsocket->hostname ? newsocket->hostname :
422                       newsocket->ip ? newsocket->ip : ""));
423       server->stat.conn_failures++;
424       goto err;
425     }
426     if (!newsocket->hostname)
427       newsocket->hostname = strdup(newsocket->ip);
428   }
429   newsocket->port = silc_net_get_local_port(sock);
430 
431   /* Create a Server ID for the server. */
432   silc_id_create_server_id(newsocket->ip, newsocket->port, server->rng, &id);
433   if (!id)
434     goto err;
435 
436   server->id = id;
437   server->id_string = silc_id_id2str(id, SILC_ID_SERVER);
438   server->id_string_len = silc_id_get_len(id, SILC_ID_SERVER);
439   server->server_name = server->config->server_info->server_name;
440   server->config->server_info->server_name = NULL;
441 
442   /* Add ourselves to the server list. We don't have a router yet
443      beacuse we haven't established a route yet. It will be done later.
444      For now, NULL is sent as router. This allocates new entry to
445      the ID list. */
446   id_entry =
447     silc_idlist_add_server(server->local_list, strdup(server->server_name),
448                            server->server_type, server->id, NULL, NULL);
449   if (!id_entry) {
450     SILC_LOG_ERROR(("Could not add ourselves to cache"));
451     goto err;
452   }
453   id_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
454 
455   /* Put the allocated socket pointer also to the entry allocated above
456      for fast back-referencing to the socket list. */
457   newsocket->user_data = (void *)id_entry;
458   id_entry->connection = (void *)newsocket;
459   server->id_entry = id_entry;
460 
461   /* Register protocols */
462   silc_server_protocols_register();
463 
464   /* Create connections to configured routers. */
465   silc_server_create_connections(server);
466 
467   /* Add listener task to the scheduler. This task receives new connections
468      to the server. This task remains on the queue until the end of the
469      program. */
470   silc_schedule_task_add(server->schedule, sock,
471                          silc_server_accept_new_connection,
472                          (void *)server, 0, 0,
473                          SILC_TASK_FD,
474                          SILC_TASK_PRI_NORMAL);
475 
476   if (silc_server_init_secondary(server) == FALSE)
477     goto err;
478 
479   server->listenning = TRUE;
480 
481   /* If server connections has been configured then we must be router as
482      normal server cannot have server connections, only router connections. */
483   if (server->config->servers) {
484     SilcServerConfigServer *ptr = server->config->servers;
485 
486     server->server_type = SILC_ROUTER;
487     while (ptr) {
488       if (ptr->backup_router) {
489         server->server_type = SILC_BACKUP_ROUTER;
490         server->backup_router = TRUE;
491         server->id_entry->server_type = SILC_BACKUP_ROUTER;
492         break;
493       }
494       ptr = ptr->next;
495     }
496   }
497 
498   /* Register the ID Cache purge task. This periodically purges the ID cache
499      and removes the expired cache entries. */
500 
501   /* Clients local list */
502   server->purge_i = purge = silc_calloc(1, sizeof(*purge));
503   purge->cache = server->local_list->clients;
504   purge->timeout = 600;
505   silc_schedule_task_add(server->schedule, 0, silc_idlist_purge,
506                          (void *)purge, purge->timeout, 0,
507                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
508 
509   /* Clients global list */
510   server->purge_g = purge = silc_calloc(1, sizeof(*purge));
511   purge->cache = server->global_list->clients;
512   purge->timeout = 300;
513   silc_schedule_task_add(server->schedule, 0, silc_idlist_purge,
514                          (void *)purge, purge->timeout, 0,
515                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
516 
517   /* If we are normal server we'll retrieve network statisticial information
518      once in a while from the router. */
519   if (server->server_type != SILC_ROUTER)
520     silc_schedule_task_add(server->schedule, 0, silc_server_get_stats,
521                            server, 10, 0, SILC_TASK_TIMEOUT,
522                            SILC_TASK_PRI_LOW);
523 
524   if (server->server_type == SILC_ROUTER)
525     server->stat.routers++;
526 
527   SILC_LOG_DEBUG(("Server initialized"));
528 
529   /* We are done here, return succesfully */
530   return TRUE;
531 
532  err:
533   silc_server_config_unref(&server->config_ref);
534   silc_net_close_server(sock);
535   return FALSE;
536 }
537 
538 /* Task callback to close a socket connection after rehash */
539 
540 SILC_TASK_CALLBACK(silc_server_rehash_close_connection)
541 {
542   SilcServer server = context;
543   SilcSocketConnection sock = server->sockets[fd];
544 
545   if (!sock)
546     return;
547 
548   SILC_LOG_INFO(("Connection %s:%d [%s] is unconfigured",
549                  sock->hostname, sock->port,
550                  (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
551                   sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
552                   sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
553                   "Router")));
554   silc_schedule_task_del_by_context(server->schedule, sock);
555   silc_server_disconnect_remote(server, sock,
556                                 SILC_STATUS_ERR_BANNED_FROM_SERVER,
557                                 "This connection is removed from "
558                                 "configuration");
559   if (sock->user_data)
560     silc_server_free_sock_user_data(server, sock, NULL);
561 }
562 
563 /* This function basically reads the config file again and switches the config
564    object pointed by the server object. After that, we have to fix various
565    things such as the server_name and the listening ports.
566    Keep in mind that we no longer have the root privileges at this point. */
567 
568 bool silc_server_rehash(SilcServer server)
569 {
570   SilcServerConfig newconfig;
571 
572   SILC_LOG_INFO(("Rehashing server"));
573 
574   /* Reset the logging system */
575   silc_log_quick = TRUE;
576   silc_log_flush_all();
577 
578   /* Start the main rehash phase (read again the config file) */
579   newconfig = silc_server_config_alloc(server->config_file);
580   if (!newconfig) {
581     SILC_LOG_ERROR(("Rehash FAILED."));
582     return FALSE;
583   }
584 
585   /* Reinit scheduler if necessary */
586   if (newconfig->param.connections_max > server->config->param.connections_max)
587     if (!silc_schedule_reinit(server->schedule,
588                               newconfig->param.connections_max))
589       return FALSE;
590 
591   /* Fix the server_name field */
592   if (strcmp(server->server_name, newconfig->server_info->server_name)) {
593     silc_free(server->server_name);
594 
595     /* Check server name */
596     server->server_name =
597       silc_identifier_check(newconfig->server_info->server_name,
598                             strlen(newconfig->server_info->server_name),
599                             SILC_STRING_LOCALE, 256, NULL);
600     if (!server->server_name) {
601       SILC_LOG_ERROR(("Malformed server name string '%s'",
602                       server->config->server_info->server_name));
603       return FALSE;
604     }
605 
606     /* Update the idcache list with a fresh pointer */
607     silc_free(server->id_entry->server_name);
608     server->id_entry->server_name = strdup(server->server_name);
609     if (!silc_idcache_del_by_context(server->local_list->servers,
610                                      server->id_entry))
611       return FALSE;
612     if (!silc_idcache_add(server->local_list->servers,
613                           strdup(server->id_entry->server_name),
614                           server->id_entry->id, server->id_entry, 0, NULL))
615       return FALSE;
616   }
617 
618   /* Set logging */
619   silc_server_config_setlogfiles(server);
620 
621   /* Change new key pair if necessary */
622   if (newconfig->server_info->public_key &&
623       !silc_pkcs_public_key_compare(server->public_key,
624                                     newconfig->server_info->public_key)) {
625     silc_pkcs_public_key_free(server->public_key);
626     silc_pkcs_private_key_free(server->private_key);
627     server->public_key = newconfig->server_info->public_key;
628     server->private_key = newconfig->server_info->private_key;
629     newconfig->server_info->public_key = NULL;
630     newconfig->server_info->private_key = NULL;
631 
632     /* Allocate PKCS context for local public and private keys */
633     silc_pkcs_free(server->pkcs);
634     if (!silc_pkcs_alloc(server->public_key->name, &server->pkcs))
635       return FALSE;
636     silc_pkcs_public_key_set(server->pkcs, server->public_key);
637     silc_pkcs_private_key_set(server->pkcs, server->private_key);
638   }
639 
640   /* Check for unconfigured server and router connections and close
641      connections that were unconfigured. */
642 
643   if (server->config->routers) {
644     SilcServerConfigRouter *ptr;
645     SilcServerConfigRouter *newptr;
646     bool found;
647 
648     for (ptr = server->config->routers; ptr; ptr = ptr->next) {
649       found = FALSE;
650 
651       /* Check whether new config has this one too */
652       for (newptr = newconfig->routers; newptr; newptr = newptr->next) {
653         if (silc_string_compare(newptr->host, ptr->host) &&
654             newptr->port == ptr->port &&
655             newptr->initiator == ptr->initiator) {
656           found = TRUE;
657           break;
658         }
659       }
660 
661       if (!found && ptr->host) {
662         /* Remove this connection */
663         SilcSocketConnection sock;
664         sock = silc_server_find_socket_by_host(server, SILC_SOCKET_TYPE_ROUTER,
665                                                ptr->host, ptr->port);
666         if (sock && !SILC_IS_LISTENER(sock))
667           silc_schedule_task_add(server->schedule, sock->sock,
668                                  silc_server_rehash_close_connection,
669                                  server, 0, 1, SILC_TASK_TIMEOUT,
670                                  SILC_TASK_PRI_NORMAL);
671       }
672     }
673   }
674 
675   if (server->config->servers) {
676     SilcServerConfigServer *ptr;
677     SilcServerConfigServer *newptr;
678     bool found;
679 
680     for (ptr = server->config->servers; ptr; ptr = ptr->next) {
681       found = FALSE;
682 
683       /* Check whether new config has this one too */
684       for (newptr = newconfig->servers; newptr; newptr = newptr->next) {
685         if (silc_string_compare(newptr->host, ptr->host)) {
686           found = TRUE;
687           break;
688         }
689       }
690 
691       if (!found && ptr->host) {
692         /* Remove this connection */
693         SilcSocketConnection sock;
694         sock = silc_server_find_socket_by_host(server, SILC_SOCKET_TYPE_SERVER,
695                                                ptr->host, 0);
696         if (sock && !SILC_IS_LISTENER(sock))
697           silc_schedule_task_add(server->schedule, sock->sock,
698                                  silc_server_rehash_close_connection,
699                                  server, 0, 1, SILC_TASK_TIMEOUT,
700                                  SILC_TASK_PRI_NORMAL);
701       }
702     }
703   }
704 
705   if (server->config->clients) {
706     SilcServerConfigClient *ptr;
707     SilcServerConfigClient *newptr;
708     bool found;
709 
710     for (ptr = server->config->clients; ptr; ptr = ptr->next) {
711       found = FALSE;
712 
713       /* Check whether new config has this one too */
714       for (newptr = newconfig->clients; newptr; newptr = newptr->next) {
715         if (silc_string_compare(newptr->host, ptr->host)) {
716           found = TRUE;
717           break;
718         }
719       }
720 
721       if (!found && ptr->host) {
722         /* Remove this connection */
723         SilcSocketConnection sock;
724         sock = silc_server_find_socket_by_host(server, SILC_SOCKET_TYPE_CLIENT,
725                                                ptr->host, 0);
726         if (sock)
727           silc_schedule_task_add(server->schedule, sock->sock,
728                                  silc_server_rehash_close_connection,
729                                  server, 0, 1, SILC_TASK_TIMEOUT,
730                                  SILC_TASK_PRI_NORMAL);
731       }
732     }
733   }
734 
735   /* Create connections after rehash */
736   silc_server_create_connections(server);
737 
738   /* Check whether our router status has changed */
739   if (newconfig->servers) {
740     SilcServerConfigServer *ptr = newconfig->servers;
741 
742     server->server_type = SILC_ROUTER;
743     while (ptr) {
744       if (ptr->backup_router) {
745         server->server_type = SILC_BACKUP_ROUTER;
746         server->backup_router = TRUE;
747         server->id_entry->server_type = SILC_BACKUP_ROUTER;
748         break;
749       }
750       ptr = ptr->next;
751     }
752   }
753 
754   /* Our old config is gone now. We'll unreference our reference made in
755      silc_server_init and then destroy it since we are destroying it
756      underneath the application (layer which called silc_server_init). */
757   silc_server_config_unref(&server->config_ref);
758   silc_server_config_destroy(server->config);
759 
760   /* Take new config context */
761   server->config = newconfig;
762   silc_server_config_ref(&server->config_ref, server->config, server->config);
763 
764 #ifdef SILC_DEBUG
765   /* Set debugging on if configured */
766   if (server->config->debug_string) {
767     silc_debug = TRUE;
768     silc_log_set_debug_string(server->config->debug_string);
769   }
770 #endif /* SILC_DEBUG */
771 
772   SILC_LOG_DEBUG(("Server rehashed"));
773 
774   return TRUE;
775 }
776 
777 /* The heart of the server. This runs the scheduler thus runs the server.
778    When this returns the server has been stopped and the program will
779    be terminated. */
780 
781 void silc_server_run(SilcServer server)
782 {
783   SILC_LOG_INFO(("SILC Server started"));
784 
785   /* Start the scheduler, the heart of the SILC server. When this returns
786      the program will be terminated. */
787   silc_schedule(server->schedule);
788 }
789 
790 /* Stops the SILC server. This function is used to shutdown the server.
791    This is usually called after the scheduler has returned. After stopping
792    the server one should call silc_server_free. */
793 
794 void silc_server_stop(SilcServer server)
795 {
796   SILC_LOG_INFO(("SILC Server shutting down"));
797 
798   if (server->schedule) {
799     int i;
800 
801     server->server_shutdown = TRUE;
802 
803     /* Close all connections */
804     for (i = 0; i < server->config->param.connections_max; i++) {
805       if (!server->sockets[i])
806         continue;
807       if (!SILC_IS_LISTENER(server->sockets[i])) {
808         SilcSocketConnection sock = server->sockets[i];
809         SilcIDListData idata = sock->user_data;
810 
811         if (idata)
812           idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
813 
814         silc_schedule_task_del_by_context(server->schedule,
815                                           server->sockets[i]);
816         silc_schedule_task_del_by_fd(server->schedule,
817                                      server->sockets[i]->sock);
818         silc_server_disconnect_remote(server, server->sockets[i],
819                                       SILC_STATUS_OK,
820                                       "Server is shutting down");
821         if (server->sockets[i]) {
822           if (sock->user_data)
823             silc_server_free_sock_user_data(server, sock,
824                                             "Server is shutting down");
825           silc_socket_free(sock);
826         }
827       } else {
828         silc_socket_free(server->sockets[i]);
829         server->sockets[i] = NULL;
830         server->stat.conn_num--;
831       }
832     }
833 
834     /* We are not connected to network anymore */
835     server->standalone = TRUE;
836 
837     silc_schedule_stop(server->schedule);
838     silc_schedule_uninit(server->schedule);
839     server->schedule = NULL;
840 
841     silc_free(server->sockets);
842     server->sockets = NULL;
843   }
844 
845   silc_server_protocols_unregister();
846 
847   SILC_LOG_DEBUG(("Server stopped"));
848 }
849 
850 /* Function that is called when the network connection to a router has
851    been established.  This will continue with the key exchange protocol
852    with the remote router. */
853 
854 void silc_server_start_key_exchange(SilcServer server,
855                                     SilcServerConnection sconn,
856                                     int sock)
857 {
858   SilcSocketConnection newsocket;
859   SilcProtocol protocol;
860   SilcServerKEInternalContext *proto_ctx;
861   SilcServerConfigRouter *conn =
862     (SilcServerConfigRouter *) sconn->conn.ref_ptr;
863   void *context;
864 
865   /* Cancel any possible retry timeouts */
866   silc_schedule_task_del_by_callback(server->schedule,
867                                      silc_server_connect_to_router_retry);
868 
869   /* Set socket options */
870   silc_net_set_socket_nonblock(sock);
871   silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
872 
873   /* Create socket connection for the connection. Even though we
874      know that we are connecting to a router we will mark the socket
875      to be unknown connection until we have executed authentication
876      protocol. */
877   silc_socket_alloc(sock, SILC_SOCKET_TYPE_UNKNOWN, NULL, &newsocket);
878   server->sockets[sock] = newsocket;
879   newsocket->hostname = strdup(sconn->remote_host);
880   newsocket->ip = strdup(sconn->remote_host);
881   newsocket->port = sconn->remote_port;
882   sconn->sock = newsocket;
883 
884   /* Allocate internal protocol context. This is sent as context
885      to the protocol. */
886   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
887   proto_ctx->server = (void *)server;
888   proto_ctx->context = (void *)sconn;
889   proto_ctx->sock = newsocket;
890   proto_ctx->rng = server->rng;
891   proto_ctx->responder = FALSE;
892 
893   /* Set Key Exchange flags from configuration, but fall back to global
894      settings too. */
895   SILC_GET_SKE_FLAGS(conn, proto_ctx);
896   if (server->config->param.key_exchange_pfs)
897     proto_ctx->flags |= SILC_SKE_SP_FLAG_PFS;
898 
899   /* Perform key exchange protocol. silc_server_connect_to_router_second
900      will be called after the protocol is finished. */
901   silc_protocol_alloc(SILC_PROTOCOL_SERVER_KEY_EXCHANGE,
902                       &protocol, proto_ctx,
903                       silc_server_connect_to_router_second);
904   newsocket->protocol = protocol;
905 
906   /* Register a timeout task that will be executed if the protocol
907      is not executed within set limit. */
908   proto_ctx->timeout_task =
909     silc_schedule_task_add(server->schedule, sock,
910                            silc_server_timeout_remote,
911                            server, server->config->key_exchange_timeout, 0,
912                            SILC_TASK_TIMEOUT,
913                            SILC_TASK_PRI_LOW);
914 
915   /* Register the connection for network input and output. This sets
916      that scheduler will listen for incoming packets for this connection
917      and sets that outgoing packets may be sent to this connection as
918      well. However, this doesn't set the scheduler for outgoing traffic,
919      it will be set separately by calling SILC_SET_CONNECTION_FOR_OUTPUT,
920      later when outgoing data is available. */
921   context = (void *)server;
922   SILC_REGISTER_CONNECTION_FOR_IO(sock);
923 
924   /* Run the protocol */
925   silc_protocol_execute(protocol, server->schedule, 0, 0);
926 }
927 
928 /* Timeout callback that will be called to retry connecting to remote
929    router. This is used by both normal and router server. This will wait
930    before retrying the connecting. The timeout is generated by exponential
931    backoff algorithm. */
932 
933 SILC_TASK_CALLBACK(silc_server_connect_to_router_retry)
934 {
935   SilcServer server = app_context;
936   SilcServerConnection sconn = (SilcServerConnection)context;
937   SilcServerConfigRouter *conn = sconn->conn.ref_ptr;
938   SilcServerConfigConnParams *param =
939                 (conn->param ? conn->param : &server->config->param);
940 
941   /* Don't retry if we are shutting down. */
942   if (server->server_shutdown) {
943     silc_server_config_unref(&sconn->conn);
944     silc_free(sconn->remote_host);
945     silc_free(sconn->backup_replace_ip);
946     silc_free(sconn);
947     return;
948   }
949 
950   SILC_LOG_INFO(("Retrying connecting to a router"));
951 
952   /* Calculate next timeout */
953   if (sconn->retry_count >= 1) {
954     sconn->retry_timeout = sconn->retry_timeout * SILC_SERVER_RETRY_MULTIPLIER;
955     if (sconn->retry_timeout > param->reconnect_interval_max)
956       sconn->retry_timeout = param->reconnect_interval_max;
957   } else {
958     sconn->retry_timeout = param->reconnect_interval;
959   }
960   sconn->retry_count++;
961   sconn->retry_timeout = sconn->retry_timeout +
962     (silc_rng_get_rn32(server->rng) % SILC_SERVER_RETRY_RANDOMIZER);
963 
964   /* If we've reached max retry count, give up. */
965   if ((sconn->retry_count > param->reconnect_count) &&
966       !param->reconnect_keep_trying) {
967     SILC_LOG_ERROR(("Could not connect to router, giving up"));
968     silc_server_config_unref(&sconn->conn);
969     silc_free(sconn->remote_host);
970     silc_free(sconn->backup_replace_ip);
971     silc_free(sconn);
972     return;
973   }
974 
975   SILC_LOG_DEBUG(("Retrying connecting to a router in %d seconds",
976                   sconn->retry_timeout));
977 
978   /* We will lookup a fresh pointer later */
979   silc_server_config_unref(&sconn->conn);
980 
981   /* Wait one before retrying */
982   silc_schedule_task_add(server->schedule, 0, silc_server_connect_router,
983                          context, sconn->retry_timeout, 0,
984                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
985 }
986 
987 /* Callback for async connection to remote router */
988 
989 SILC_TASK_CALLBACK(silc_server_connection_established)
990 {
991   SilcServer server = app_context;
992   SilcServerConnection sconn = (SilcServerConnection)context;
993   int sock = fd;
994   int opt = EINVAL, optlen = sizeof(opt), ret;
995 
996   ret = silc_net_get_socket_opt(sock, SOL_SOCKET, SO_ERROR, &opt, &optlen);
997 
998   silc_schedule_task_del_by_fd(server->schedule, sock);
999   silc_schedule_unset_listen_fd(server->schedule, sock);
1000 
1001   if (ret != 0 || opt != 0) {
1002     SILC_LOG_ERROR(("Could not connect to router %s:%d: %s",
1003                     sconn->remote_host, sconn->remote_port, strerror(opt)));
1004     silc_net_close_connection(sock);
1005     if (!sconn->no_reconnect) {
1006       silc_schedule_task_add(server->schedule, 0,
1007                              silc_server_connect_to_router_retry,
1008                              context, 1, 0, SILC_TASK_TIMEOUT,
1009                              SILC_TASK_PRI_NORMAL);
1010     } else {
1011       silc_server_config_unref(&sconn->conn);
1012       silc_free(sconn->remote_host);
1013       silc_free(sconn->backup_replace_ip);
1014       silc_free(sconn);
1015     }
1016     return;
1017   }
1018 
1019   SILC_LOG_DEBUG(("Connection to router %s:%d established", sconn->remote_host,
1020                  sconn->remote_port));
1021 
1022   /* Continue with key exchange protocol */
1023   silc_server_start_key_exchange(server, sconn, sock);
1024 }
1025 
1026 /* Generic routine to use connect to a router. */
1027 
1028 SILC_TASK_CALLBACK(silc_server_connect_router)
1029 {
1030   SilcServer server = app_context;
1031