5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2006 Pekka Riikonen
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.
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.
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.
27 #include "silcserver.h"
28 #include "server_internal.h"
30 /************************** Types and definitions ***************************/
33 /************************ Static utility functions **************************/
35 /* Packet engine callback to receive a packet */
37 static SilcBool silc_server_packet_receive(SilcPacketEngine engine,
38 SilcPacketStream stream,
40 void *callback_context,
43 SilcServerThread thread = callback_context;
44 SilcEntryData data = silc_packet_get_context(stream);
46 /* Packets we do not handle */
47 switch (packet->type) {
48 case SILC_PACKET_HEARTBEAT:
49 case SILC_PACKET_SUCCESS:
50 case SILC_PACKET_FAILURE:
51 case SILC_PACKET_REJECT:
52 case SILC_PACKET_KEY_EXCHANGE:
53 case SILC_PACKET_KEY_EXCHANGE_1:
54 case SILC_PACKET_KEY_EXCHANGE_2:
55 case SILC_PACKET_REKEY:
56 case SILC_PACKET_REKEY_DONE:
57 case SILC_PACKET_CONNECTION_AUTH:
58 case SILC_PACKET_CONNECTION_AUTH_REQUEST:
63 /* Only specific packets can come without source ID present. */
64 if ((!packet->src_id || data->registered == FALSE) &&
65 packet->type != SILC_PACKET_NEW_CLIENT &&
66 packet->type != SILC_PACKET_NEW_SERVER &&
67 packet->type != SILC_PACKET_DISCONNECT)
70 /* NEW_CLIENT and NEW_SERVER are accepted only without source ID
71 and for unregistered connection. */
72 if (packet->src_id && (packet->type == SILC_PACKET_NEW_CLIENT ||
73 packet->type == SILC_PACKET_NEW_SERVER) &&
74 data->registered == TRUE)
77 /* Add the packet to packet queue */
78 silc_list_add(thread->packet_queue, packet);
80 /* Signal thread that packet has arrived */
81 if (!thread->new_packet) {
82 thread->new_packet = TRUE;
83 SILC_FSM_EVENT_SIGNAL(&thread->wait_event);
89 /* Packet engine callback to indicate end of stream */
91 static void silc_server_packet_eos(SilcPacketEngine engine,
92 SilcPacketStream stream,
93 void *callback_context,
96 SILC_LOG_DEBUG(("End of stream received"));
99 /* Packet engine callback to indicate error */
101 static void silc_server_packet_error(SilcPacketEngine engine,
102 SilcPacketStream stream,
103 SilcPacketError error,
104 void *callback_context,
105 void *stream_context)
110 /* Packet stream callbacks */
111 static SilcPacketCallbacks silc_server_stream_cbs =
113 silc_server_packet_receive,
114 silc_server_packet_eos,
115 silc_server_packet_error
118 /* Server FSM destructor */
120 static void silc_server_destructor(SilcFSM fsm, void *fsm_context,
121 void *destructor_context)
126 /* Creates new server thread. Adds to server threads list automatically and
127 starts the thread. Depending on server configuration the created thread
128 is either FSM thread of real thread. */
130 static SilcServerThread silc_server_new_thread(SilcServer server)
132 SilcServerThread thread;
134 SILC_LOG_DEBUG(("Creating new server thread"));
136 thread = silc_calloc(1, sizeof(*thread));
140 thread->server = server;
141 silc_list_init(thread->new_conns, struct SilcServerAcceptStruct, next);
143 /* Start packet engine */
144 thread->packet_engine =
145 silc_packet_engine_start(server->rng, server->server_type == SILC_ROUTER,
146 &silc_server_stream_cbs, thread);
147 if (!thread->packet_engine) {
153 silc_list_add(server->threads, thread);
155 /* Start the thread */
156 silc_fsm_thread_init(&thread->thread, &server->fsm, thread,
157 NULL, NULL, server->params->use_threads);
158 silc_fsm_start(&thread->thread, silc_server_thread_st_start);
160 /* Allocate data stack. Its allocation is allowed to fail so we don't
162 thread->stack = silc_stack_alloc(0);
167 /* Network listener callback to accept new connections */
169 static void silc_server_accept_connection(SilcNetStatus status,
170 SilcStream stream, void *context)
172 SilcServer server = context;
175 if (status != SILC_NET_OK) {
176 SILC_LOG_ERROR(("Error %d accepting new connection", status));
180 ac = silc_calloc(1, sizeof(*ac));
182 silc_stream_destroy(stream);
187 /* Add as new connection */
188 silc_list_add(server->new_conns, ac);
190 /* Signal server of new connection */
191 if (!server->new_connection) {
192 server->new_connection = TRUE;
193 SILC_FSM_EVENT_SIGNAL(&server->wait_event);
197 /* Packet thread destructor */
199 static void silc_server_thread_packet_dest(SilcFSM fsm, void *fsm_context,
200 void *destructor_context)
206 /****************************** Server thread *******************************/
208 /* Thread's start function. This may be FSM thread or real system thread,
209 depending on server configuration. */
211 SILC_FSM_STATE(silc_server_thread_st_start)
213 SilcServerThread thread = fsm_context;
215 SILC_LOG_DEBUG(("New server thread started"));
217 /*** Run thread's machine */
218 silc_fsm_init(&thread->fsm, thread, NULL, NULL, silc_fsm_get_schedule(fsm));
219 silc_fsm_event_init(&thread->wait_event, &thread->fsm, 0);
220 silc_fsm_start_sync(&thread->fsm, silc_server_thread_st_run);
222 /* Signal server that we are up */
223 SILC_FSM_EVENT_SIGNAL(&thread->server->thread_up);
225 /* Wait here for this thread to finish */
229 /* Thread's machine's main state where we wait for various events. */
231 SILC_FSM_STATE(silc_server_thread_st_run)
233 SilcServerThread thread = fsm_context;
235 SILC_LOG_DEBUG(("Start"));
237 /* Wait for events */
238 SILC_FSM_EVENT_WAIT(&thread->wait_event);
242 if (thread->new_packet) {
243 /*** Packet received */
247 SILC_LOG_DEBUG(("Processing incoming packets"));
249 /* Each packet is processed in FSM thread */
250 silc_list_start(thread->packet_queue);
251 while ((packet = silc_list_get(thread->packet_queue)) != SILC_LIST_END) {
252 /* XXX shouldn't the fsm be &thread->fsm */
253 t = silc_fsm_thread_alloc(fsm, thread, silc_server_thread_packet_dest,
256 silc_fsm_set_state_context(t, packet);
257 silc_fsm_start_sync(t, silc_server_st_packet_received);
261 /* Empty the queue */
262 silc_list_init(thread->packet_queue, struct SilcPacketStruct, next);
264 thread->new_packet = FALSE;
268 silc_mutex_lock(thread->server->lock);
270 if (thread->new_connection) {
271 /*** Accept new connection */
274 SILC_LOG_DEBUG(("Processing incoming connections"));
276 /* Accept the new connection in own thread */
277 silc_list_start(thread->new_conns);
278 while ((ac = silc_list_get(thread->new_conns)) != SILC_LIST_END) {
280 silc_fsm_thread_init(&ac->t, &thread->fsm, ac,
281 silc_server_accept_connection_dest,
283 silc_fsm_start(&ac->t, silc_server_st_accept_connection);
287 silc_list_init(thread->new_conns, struct SilcServerAcceptStruct, next);
289 thread->new_connection = FALSE;
290 silc_mutex_unlock(thread->server->lock);
295 #if defined(SILC_DEBUG)
297 #endif /* SILC_DEBUG */
302 /*************************** Main server machine ****************************/
304 /* The server's main state where we wait for various events */
306 SILC_FSM_STATE(silc_server_st_run)
308 SilcServer server = fsm_context;
310 SILC_LOG_DEBUG(("Start"));
312 /* Wait for events */
313 SILC_FSM_EVENT_WAIT(&server->wait_event);
317 if (server->run_callback && server->running) {
318 /* Call running callbcak back to application */
319 server->run_callback = FALSE;
320 server->running(server, server->running_context);
324 if (server->new_connection) {
325 /** New connection */
326 silc_fsm_next(fsm, silc_server_st_new_connection);
330 if (server->connect_router) {
331 /** Connect to router(s) */
332 silc_fsm_next(fsm, silc_server_st_connect_router);
336 if (server->get_statistics) {
337 /** Retrieve statistics */
338 silc_fsm_next(fsm, silc_server_st_get_stats);
342 if (server->reconfigure) {
343 /** Reconfigure server */
344 silc_fsm_next(fsm, silc_server_st_reconfigure);
348 if (server->server_shutdown) {
349 /** Shutdown server */
350 silc_fsm_next(fsm, silc_server_st_stop);
355 #if defined(SILC_DEBUG)
357 #endif /* SILC_DEBUG */
361 /* New connection received */
363 SILC_FSM_STATE(silc_server_st_new_connection)
365 SilcServer server = fsm_context;
366 SilcServerThread thread;
369 SILC_LOG_DEBUG(("Process new connections"));
371 silc_list_start(server->new_conns);
372 while ((ac = silc_list_get(server->new_conns)) != SILC_LIST_END) {
374 /* Find thread where to put this connection */
375 silc_list_start(server->threads);
376 while ((thread = silc_list_get(server->threads)) != SILC_LIST_END) {
377 if (!server->params->use_threads)
379 if (thread->num_conns < server->params->connections_per_thread)
384 /** Create new thread */
385 thread = silc_server_new_thread(server);
387 silc_list_del(server->new_conns, ac);
388 silc_stream_destroy(ac->stream);
393 silc_fsm_next(fsm, silc_server_st_wait_new_thread);
397 silc_list_del(server->new_conns, ac);
399 /* Give this connection to this thread */
400 silc_mutex_lock(server->lock);
401 silc_list_add(thread->new_conns, ac);
404 SILC_LOG_DEBUG(("Signal thread for new connection"));
406 /* Signal the thread for new connection */
407 if (!thread->new_connection) {
408 thread->new_connection = TRUE;
409 SILC_FSM_EVENT_SIGNAL(&thread->wait_event);
411 silc_mutex_unlock(server->lock);
414 server->new_connection = FALSE;
416 /** Connections processed */
417 silc_fsm_next(fsm, silc_server_st_run);
421 /* Wait here until newly created thread is up */
423 SILC_FSM_STATE(silc_server_st_wait_new_thread)
425 SilcServer server = fsm_context;
427 /* Wait here until new thread is up */
428 SILC_FSM_EVENT_WAIT(&server->thread_up);
430 /** Process new connections */
431 silc_fsm_next(fsm, silc_server_st_new_connection);
437 SILC_FSM_STATE(silc_server_st_stop)
440 SilcServer server = fsm_context;
442 SILC_LOG_INFO(("SILC Server shutting down"));
444 if (server->schedule) {
447 server->server_shutdown = TRUE;
449 /* Close all connections */
450 for (i = 0; i < server->config->param.connections_max; i++) {
451 if (!server->sockets[i])
453 if (!SILC_IS_LISTENER(server->sockets[i])) {
454 SilcSocketConnection sock = server->sockets[i];
455 SilcIDListData idata = sock->user_data;
458 idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
460 silc_schedule_task_del_by_context(server->schedule,
462 silc_schedule_task_del_by_fd(server->schedule,
463 server->sockets[i]->sock);
464 silc_server_disconnect_remote(server, server->sockets[i],
466 "Server is shutting down");
467 if (server->sockets[i]) {
469 silc_server_free_sock_user_data(server, sock,
470 "Server is shutting down");
471 silc_socket_free(sock);
474 silc_socket_free(server->sockets[i]);
475 server->sockets[i] = NULL;
476 server->stat.conn_num--;
480 /* We are not connected to network anymore */
481 server->standalone = TRUE;
483 silc_schedule_stop(server->schedule);
484 silc_schedule_uninit(server->schedule);
485 server->schedule = NULL;
487 silc_free(server->sockets);
488 server->sockets = NULL;
491 silc_server_protocols_unregister();
495 silc_fsm_next(fsm, silc_server_st_run);
499 /* Reconfigure server */
501 SILC_FSM_STATE(silc_server_st_reconfigure)
503 SilcServer server = fsm_context;
505 SILC_LOG_DEBUG(("Reconfiguring server"));
508 server->reconfigure = FALSE;
509 silc_fsm_next(fsm, silc_server_st_run);
515 SILC_FSM_STATE(silc_server_st_get_stats)
517 SilcServer server = fsm_context;
519 SILC_LOG_DEBUG(("Getting statistics"));
522 server->get_statistics = FALSE;
523 silc_fsm_next(fsm, silc_server_st_run);
528 /**************************** Public interface ******************************/
530 /* Allocates server context and returns it */
532 SilcServer silc_server_alloc(void *app_context, SilcServerParams params,
533 SilcSchedule schedule)
536 SilcServerParamInterface iface;
537 SilcBool id_created = FALSE;
539 SILC_LOG_DEBUG(("Allocating new server"));
541 if (!schedule || !params)
544 server = silc_calloc(1, sizeof(*server));
548 server->app_context = app_context;
549 server->schedule = schedule;
550 server->params = params;
551 server->server_type = SILC_SERVER;
552 server->standalone = TRUE;
554 server->sim = silc_dlist_init();
557 #if defined(SILC_DEBUG)
558 /* Set debugging on if configured */
559 if (params->debug_string) {
560 silc_log_debug(TRUE);
561 silc_log_set_debug_string(params->debug_string);
563 #endif /* SILC_DEBUG */
565 /* Allocate ID caches */
566 server->clients = silc_idcache_alloc(0, SILC_ID_CLIENT,
567 silc_server_destructor_client, server);
568 server->servers = silc_idcache_alloc(0, SILC_ID_SERVER,
569 silc_server_destructor_server, server);
570 server->channels = silc_idcache_alloc(0, SILC_ID_CHANNEL,
571 silc_server_destructor_channel,
573 if (!server->clients || !server->servers || !server->channels) {
574 SILC_LOG_ERROR(("Could not allocate ID cache"));
578 /* Allocate key repository */
579 server->repository = silc_skr_alloc(schedule);
580 if (!server->repository) {
581 SILC_LOG_ERROR(("Could not allocate key repository"));
585 /* Allocate server lock */
586 if (!silc_mutex_alloc(&server->lock)) {
587 SILC_LOG_DEBUG(("Could not allocate server lock"));
592 silc_fsm_init(&server->fsm, server, silc_server_destructor, NULL, schedule);
594 /* Init semaphore signallers */
595 silc_fsm_event_init(&server->wait_event, &server->fsm, 0);
596 silc_fsm_event_init(&server->thread_up, &server->fsm, 0);
598 /* Initialize lists */
599 silc_list_init(server->new_conns, struct SilcServerAcceptStruct, next);
600 silc_list_init(server->command_pool, struct SilcServerCommandStruct, next);
603 /* Register all paramsured ciphers, PKCS and hash functions. */
604 if (!silc_server_params_register_ciphers(server))
605 silc_cipher_register_default();
606 if (!silc_server_params_register_pkcs(server))
607 silc_pkcs_register_default();
608 if (!silc_server_params_register_hashfuncs(server))
609 silc_hash_register_default();
610 if (!silc_server_params_register_hmacs(server))
611 silc_hmac_register_default();
613 silc_cipher_register_default();
614 silc_pkcs_register_default();
615 silc_hash_register_default();
616 silc_hmac_register_default();
619 /* Initialize random number generator for the server. */
620 server->rng = silc_rng_alloc();
622 SILC_LOG_ERROR(("Could not allocate RNG"));
625 silc_rng_init(server->rng);
626 silc_rng_global_init(server->rng);
628 /* Initialize hash functions for server to use */
629 silc_hash_alloc("md5", &server->md5hash);
630 silc_hash_alloc("sha1", &server->sha1hash);
632 /* Steal public and private key from the params object */
633 server->public_key = server->params->server_info->public_key;
634 server->private_key = server->params->server_info->private_key;
635 server->params->server_info->public_key = NULL;
636 server->params->server_info->private_key = NULL;
638 /* Create network listener(s) */
639 server->listeners = silc_dlist_init();
640 if (!server->listeners)
642 silc_list_start(params->server_info->interfaces);
643 while ((iface = silc_list_get(params->server_info->interfaces)) !=
647 /* Create a Server ID for the server */
648 if (!silc_server_create_server_id(server, iface->ip, iface->port,
650 SILC_LOG_ERROR(("Could not create Server ID"));
657 SilcNetServer listener =
658 silc_net_create_server((const char **)&iface->ip, 1, iface->port,
659 params->require_reverse_lookup,
661 silc_server_accept_connection, server);
663 SILC_LOG_ERROR(("Could not bind %s on %d", iface->ip, iface->port));
667 silc_dlist_add(server->listeners, listener);
670 /* First, register log files paramsuration for error output */
671 // silc_server_params_setlogfiles(server);
673 /* Init watcher lists */
674 server->watcher_list =
675 silc_hash_table_alloc(1, silc_hash_client_id_hash, NULL,
676 silc_hash_data_compare, (void *)CLIENTID_HASH_LEN,
678 if (!server->watcher_list)
681 server->watcher_list_pk =
682 silc_hash_table_alloc(1, silc_hash_public_key, NULL,
683 silc_hash_public_key_compare, NULL,
685 if (!server->watcher_list_pk)
689 server->server_name = server->params->server_info->server_name;
690 server->params->server_info->server_name = NULL;
693 /* If server connections has been paramsured then we must be router as
694 normal server cannot have server connections, only router connections. */
695 if (server->params->servers) {
696 SilcServerParamsServer *ptr = server->params->servers;
698 server->server_type = SILC_ROUTER;
700 if (ptr->backup_router) {
701 server->server_type = SILC_BACKUP_ROUTER;
702 server->backup_router = TRUE;
703 server->id_entry->server_type = SILC_BACKUP_ROUTER;
711 if (server->server_type == SILC_ROUTER)
712 server->stat.routers++;
720 /* Free's the SILC server context */
722 void silc_server_free(SilcServer server)
725 SilcIDCacheList list;
726 SilcIDCacheEntry cache;
734 silc_dlist_start(server->sim);
735 while ((sim = silc_dlist_get(server->sim)) != SILC_LIST_END) {
736 silc_dlist_del(server->sim, sim);
740 silc_dlist_uninit(server->sim);
744 silc_server_backup_free(server);
745 silc_server_params_unref(&server->params_ref);
747 silc_rng_free(server->rng);
749 silc_pkcs_free(server->pkcs);
750 if (server->public_key)
751 silc_pkcs_public_key_free(server->public_key);
752 if (server->private_key)
753 silc_pkcs_private_key_free(server->private_key);
754 if (server->pending_commands)
755 silc_dlist_uninit(server->pending_commands);
756 if (server->id_entry)
757 silc_idlist_del_server(server->local_list, server->id_entry);
759 /* Delete all channels */
761 if (silc_idcache_get_all(server->local_list->channels, &list) &&
762 silc_idcache_list_first(list, &cache)) {
763 silc_idlist_del_channel(server->local_list, cache->context);
764 while (silc_idcache_list_next(list, &cache))
765 silc_idlist_del_channel(server->local_list, cache->context);
768 silc_idcache_list_free(list);
770 if (silc_idcache_get_all(server->global_list->channels, &list) &&
771 silc_idcache_list_first(list, &cache)) {
772 silc_idlist_del_channel(server->global_list, cache->context);
773 while (silc_idcache_list_next(list, &cache))
774 silc_idlist_del_channel(server->global_list, cache->context);
777 silc_idcache_list_free(list);
780 silc_hash_table_free(server->pk_hash);
782 /* Delete all clients */
784 if (silc_idcache_get_all(server->local_list->clients, &list) &&
785 silc_idcache_list_first(list, &cache)) {
786 silc_idlist_del_client(server->local_list, cache->context);
787 while (silc_idcache_list_next(list, &cache))
788 silc_idlist_del_client(server->local_list, cache->context);
791 silc_idcache_list_free(list);
793 if (silc_idcache_get_all(server->global_list->clients, &list) &&
794 silc_idcache_list_first(list, &cache)) {
795 silc_idlist_del_client(server->global_list, cache->context);
796 while (silc_idcache_list_next(list, &cache))
797 silc_idlist_del_client(server->global_list, cache->context);
800 silc_idcache_list_free(list);
803 /* Delete all servers */
805 if (silc_idcache_get_all(server->local_list->servers, &list) &&
806 silc_idcache_list_first(list, &cache)) {
807 silc_idlist_del_server(server->local_list, cache->context);
808 while (silc_idcache_list_next(list, &cache))
809 silc_idlist_del_server(server->local_list, cache->context);
812 silc_idcache_list_free(list);
814 if (silc_idcache_get_all(server->global_list->servers, &list) &&
815 silc_idcache_list_first(list, &cache)) {
816 silc_idlist_del_server(server->global_list, cache->context);
817 while (silc_idcache_list_next(list, &cache))
818 silc_idlist_del_server(server->global_list, cache->context);
821 silc_idcache_list_free(list);
825 silc_idcache_free(server->clients);
826 silc_idcache_free(server->servers);
827 silc_idcache_free(server->channels);
828 silc_hash_table_free(server->watcher_list);
829 silc_hash_table_free(server->watcher_list_pk);
831 silc_hash_free(server->md5hash);
832 silc_hash_free(server->sha1hash);
833 silc_hmac_unregister_all();
834 silc_hash_unregister_all();
835 silc_cipher_unregister_all();
836 silc_pkcs_unregister_all();
839 /* Starts the SILC server FSM machine and returns immediately. The
840 scheduler must be run or be running already when this returns. */
842 void silc_server_run(SilcServer server, SilcServerRunning running,
843 void *running_context)
845 SILC_LOG_INFO(("Starting SILC server"));
847 server->starttime = time(NULL);
848 server->running = running;
849 server->running_context = running_context;
851 /* Start the server */
852 silc_fsm_start_sync(&server->fsm, silc_server_st_run);
854 /* Signal the application when we are running */
855 server->run_callback = TRUE;
856 SILC_FSM_EVENT_SIGNAL(&server->wait_event);
858 /* Signal to connect to router */
859 server->connect_router = TRUE;
860 SILC_FSM_EVENT_SIGNAL(&server->wait_event);
862 /* Start getting statistics from the network on normal server */
863 if (server->server_type != SILC_ROUTER) {
864 server->get_statistics = TRUE;
865 SILC_FSM_EVENT_SIGNAL(&server->wait_event);
869 /* Stops the SILC server */
871 void silc_server_stop(SilcServer server, SilcServerStop stopped,
874 SILC_LOG_INFO(("Stopping SILC server"));
876 server->stopped = stopped;
877 server->stop_context = stop_context;
879 /* Signal that server is going down */
880 server->server_shutdown = TRUE;
881 SILC_FSM_EVENT_SIGNAL(&server->wait_event);
884 /* Disconnects remote connection */
886 SilcBool silc_server_disconnect(SilcServer server,
887 SilcPacketStream stream,
889 const char *error_string)