5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005 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_SEMA_POST(&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_SEMA_POST(&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_sema_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_SEMA_POST(&thread->server->thread_up);
225 /* Wait here for this thread to finish */
226 return SILC_FSM_WAIT;
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_SEMA_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 t = silc_fsm_thread_alloc(fsm, thread, silc_server_thread_packet_dest,
255 silc_fsm_set_state_context(t, packet);
256 silc_fsm_start_sync(t, silc_server_st_packet_received);
260 /* Empty the queue */
261 silc_list_init(thread->packet_queue, struct SilcPacketStruct, next);
263 thread->new_packet = FALSE;
264 return SILC_FSM_CONTINUE;
267 silc_mutex_lock(thread->server->lock);
269 if (thread->new_connection) {
270 /*** Accept new connection */
273 SILC_LOG_DEBUG(("Processing incoming connections"));
275 /* Accept the new connection in own thread */
276 silc_list_start(thread->new_conns);
277 while ((ac = silc_list_get(thread->new_conns)) != SILC_LIST_END) {
279 ac->t = silc_fsm_thread_alloc(&thread->fsm, ac,
280 silc_server_accept_connection_dest,
282 silc_fsm_start(ac->t, silc_server_st_accept_connection);
286 silc_list_init(thread->new_conns, struct SilcServerAcceptStruct, next);
288 thread->new_connection = FALSE;
289 silc_mutex_unlock(thread->server->lock);
290 return SILC_FSM_CONTINUE;
294 #if defined(SILC_DEBUG)
296 #endif /* SILC_DEBUG */
297 return SILC_FSM_CONTINUE;
301 /*************************** Main server machine ****************************/
303 /* The server's main state where we wait for various events */
305 SILC_FSM_STATE(silc_server_st_run)
307 SilcServer server = fsm_context;
309 SILC_LOG_DEBUG(("Start"));
311 /* Wait for events */
312 SILC_FSM_SEMA_WAIT(&server->wait_event);
316 if (server->run_callback && server->running) {
317 /* Call running callbcak back to application */
318 server->run_callback = FALSE;
319 server->running(server, server->running_context);
320 return SILC_FSM_CONTINUE;
323 if (server->new_connection) {
324 /** New connection */
325 silc_fsm_next(fsm, silc_server_st_new_connection);
326 return SILC_FSM_CONTINUE;
329 if (server->connect_router) {
330 /** Connect to router(s) */
331 silc_fsm_next(fsm, silc_server_st_connect_router);
332 return SILC_FSM_CONTINUE;
335 if (server->get_statistics) {
336 /** Retrieve statistics */
337 silc_fsm_next(fsm, silc_server_st_get_stats);
338 return SILC_FSM_CONTINUE;
341 if (server->reconfigure) {
342 /** Reconfigure server */
343 silc_fsm_next(fsm, silc_server_st_reconfigure);
344 return SILC_FSM_CONTINUE;
347 if (server->server_shutdown) {
348 /** Shutdown server */
349 silc_fsm_next(fsm, silc_server_st_stop);
350 return SILC_FSM_CONTINUE;
354 #if defined(SILC_DEBUG)
356 #endif /* SILC_DEBUG */
357 return SILC_FSM_CONTINUE;
360 /* New connection received */
362 SILC_FSM_STATE(silc_server_st_new_connection)
364 SilcServer server = fsm_context;
365 SilcServerThread thread;
368 SILC_LOG_DEBUG(("Process new connections"));
370 silc_list_start(server->new_conns);
371 while ((ac = silc_list_get(server->new_conns)) != SILC_LIST_END) {
373 /* Find thread where to put this connection */
374 silc_list_start(server->threads);
375 while ((thread = silc_list_get(server->threads)) != SILC_LIST_END) {
376 if (!server->params->use_threads)
378 if (thread->num_conns < server->params->connections_per_thread)
383 /** Create new thread */
384 thread = silc_server_new_thread(server);
386 silc_list_del(server->new_conns, ac);
387 silc_stream_destroy(ac->stream);
392 silc_fsm_next(fsm, silc_server_st_wait_new_thread);
393 return SILC_FSM_CONTINUE;
396 silc_list_del(server->new_conns, ac);
398 /* Give this connection to this thread */
399 silc_mutex_lock(server->lock);
400 silc_list_add(thread->new_conns, ac);
403 SILC_LOG_DEBUG(("Signal thread for new connection"));
405 /* Signal the thread for new connection */
406 if (!thread->new_connection) {
407 thread->new_connection = TRUE;
408 SILC_FSM_SEMA_POST(&thread->wait_event);
410 silc_mutex_unlock(server->lock);
413 server->new_connection = FALSE;
415 /** Connections processed */
416 silc_fsm_next(fsm, silc_server_st_run);
417 return SILC_FSM_CONTINUE;
420 /* Wait here until newly created thread is up */
422 SILC_FSM_STATE(silc_server_st_wait_new_thread)
424 SilcServer server = fsm_context;
426 /* Wait here until new thread is up */
427 SILC_FSM_SEMA_WAIT(&server->thread_up);
429 /** Process new connections */
430 silc_fsm_next(fsm, silc_server_st_new_connection);
431 return SILC_FSM_CONTINUE;
436 SILC_FSM_STATE(silc_server_st_stop)
439 SilcServer server = fsm_context;
441 SILC_LOG_INFO(("SILC Server shutting down"));
443 if (server->schedule) {
446 server->server_shutdown = TRUE;
448 /* Close all connections */
449 for (i = 0; i < server->config->param.connections_max; i++) {
450 if (!server->sockets[i])
452 if (!SILC_IS_LISTENER(server->sockets[i])) {
453 SilcSocketConnection sock = server->sockets[i];
454 SilcIDListData idata = sock->user_data;
457 idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
459 silc_schedule_task_del_by_context(server->schedule,
461 silc_schedule_task_del_by_fd(server->schedule,
462 server->sockets[i]->sock);
463 silc_server_disconnect_remote(server, server->sockets[i],
465 "Server is shutting down");
466 if (server->sockets[i]) {
468 silc_server_free_sock_user_data(server, sock,
469 "Server is shutting down");
470 silc_socket_free(sock);
473 silc_socket_free(server->sockets[i]);
474 server->sockets[i] = NULL;
475 server->stat.conn_num--;
479 /* We are not connected to network anymore */
480 server->standalone = TRUE;
482 silc_schedule_stop(server->schedule);
483 silc_schedule_uninit(server->schedule);
484 server->schedule = NULL;
486 silc_free(server->sockets);
487 server->sockets = NULL;
490 silc_server_protocols_unregister();
494 silc_fsm_next(fsm, silc_server_st_run);
495 return SILC_FSM_CONTINUE;
498 /* Reconfigure server */
500 SILC_FSM_STATE(silc_server_st_reconfigure)
502 SilcServer server = fsm_context;
504 SILC_LOG_DEBUG(("Reconfiguring server"));
507 server->reconfigure = FALSE;
508 silc_fsm_next(fsm, silc_server_st_run);
509 return SILC_FSM_CONTINUE;
514 SILC_FSM_STATE(silc_server_st_get_stats)
516 SilcServer server = fsm_context;
518 SILC_LOG_DEBUG(("Getting statistics"));
521 server->get_statistics = FALSE;
522 silc_fsm_next(fsm, silc_server_st_run);
523 return SILC_FSM_CONTINUE;
527 /**************************** Public interface ******************************/
529 /* Allocates server context and returns it */
531 SilcServer silc_server_alloc(void *app_context, SilcServerParams params,
532 SilcSchedule schedule)
535 SilcServerParamInterface iface;
536 SilcBool id_created = FALSE;
538 SILC_LOG_DEBUG(("Allocating new server"));
540 if (!schedule || !params)
543 server = silc_calloc(1, sizeof(*server));
547 server->app_context = app_context;
548 server->schedule = schedule;
549 server->params = params;
550 server->server_type = SILC_SERVER;
551 server->standalone = TRUE;
553 server->sim = silc_dlist_init();
556 #if defined(SILC_DEBUG)
557 /* Set debugging on if configured */
558 if (params->debug_string) {
559 silc_log_debug(TRUE);
560 silc_log_set_debug_string(params->debug_string);
562 #endif /* SILC_DEBUG */
564 /* Allocate ID caches */
565 server->clients = silc_idcache_alloc(0, SILC_ID_CLIENT,
566 silc_server_destructor_client, server);
567 server->servers = silc_idcache_alloc(0, SILC_ID_SERVER,
568 silc_server_destructor_server, server);
569 server->channels = silc_idcache_alloc(0, SILC_ID_CHANNEL,
570 silc_server_destructor_channel,
572 if (!server->clients || !server->servers || !server->channels) {
573 SILC_LOG_ERROR(("Could not allocate ID cache"));
577 /* Allocate key repository */
578 server->repository = silc_skr_alloc(schedule);
579 if (!server->repository) {
580 SILC_LOG_ERROR(("Could not allocate key repository"));
584 /* Allocate server lock */
585 if (!silc_mutex_alloc(&server->lock)) {
586 SILC_LOG_DEBUG(("Could not allocate server lock"));
591 silc_fsm_init(&server->fsm, server, silc_server_destructor, NULL, schedule);
593 /* Init semaphore signallers */
594 silc_fsm_sema_init(&server->wait_event, &server->fsm, 0);
595 silc_fsm_sema_init(&server->thread_up, &server->fsm, 0);
597 /* Initialize lists */
598 silc_list_init(server->new_conns, struct SilcServerAcceptStruct, next);
599 silc_list_init(server->command_pool, struct SilcServerCommandStruct, next);
602 /* Register all paramsured ciphers, PKCS and hash functions. */
603 if (!silc_server_params_register_ciphers(server))
604 silc_cipher_register_default();
605 if (!silc_server_params_register_pkcs(server))
606 silc_pkcs_register_default();
607 if (!silc_server_params_register_hashfuncs(server))
608 silc_hash_register_default();
609 if (!silc_server_params_register_hmacs(server))
610 silc_hmac_register_default();
612 silc_cipher_register_default();
613 silc_pkcs_register_default();
614 silc_hash_register_default();
615 silc_hmac_register_default();
618 /* Initialize random number generator for the server. */
619 server->rng = silc_rng_alloc();
621 SILC_LOG_ERROR(("Could not allocate RNG"));
624 silc_rng_init(server->rng);
625 silc_rng_global_init(server->rng);
627 /* Initialize hash functions for server to use */
628 silc_hash_alloc("md5", &server->md5hash);
629 silc_hash_alloc("sha1", &server->sha1hash);
631 /* Steal public and private key from the params object */
632 server->public_key = server->params->server_info->public_key;
633 server->private_key = server->params->server_info->private_key;
634 server->params->server_info->public_key = NULL;
635 server->params->server_info->private_key = NULL;
637 /* Allocate PKCS context for local public and private keys */
638 if (!silc_pkcs_alloc(server->public_key->name, SILC_PKCS_SILC,
641 silc_pkcs_public_key_set(server->pkcs, server->public_key);
642 silc_pkcs_private_key_set(server->pkcs, server->private_key);
644 /* Create network listener(s) */
645 server->listeners = silc_dlist_init();
646 if (!server->listeners)
648 silc_list_start(params->server_info->interfaces);
649 while ((iface = silc_list_get(params->server_info->interfaces)) !=
653 /* Create a Server ID for the server */
654 if (!silc_server_create_server_id(server, iface->ip, iface->port,
656 SILC_LOG_ERROR(("Could not create Server ID"));
663 SilcNetServer listener =
664 silc_net_create_server((const char **)&iface->ip, 1, iface->port,
665 params->require_reverse_lookup,
667 silc_server_accept_connection, server);
669 SILC_LOG_ERROR(("Could not bind %s on %d", iface->ip, iface->port));
673 silc_dlist_add(server->listeners, listener);
676 /* First, register log files paramsuration for error output */
677 // silc_server_params_setlogfiles(server);
679 /* Init watcher lists */
680 server->watcher_list =
681 silc_hash_table_alloc(1, silc_hash_client_id_hash, NULL,
682 silc_hash_data_compare, (void *)CLIENTID_HASH_LEN,
684 if (!server->watcher_list)
687 server->watcher_list_pk =
688 silc_hash_table_alloc(1, silc_hash_public_key, NULL,
689 silc_hash_public_key_compare, NULL,
691 if (!server->watcher_list_pk)
695 server->server_name = server->params->server_info->server_name;
696 server->params->server_info->server_name = NULL;
699 /* If server connections has been paramsured then we must be router as
700 normal server cannot have server connections, only router connections. */
701 if (server->params->servers) {
702 SilcServerParamsServer *ptr = server->params->servers;
704 server->server_type = SILC_ROUTER;
706 if (ptr->backup_router) {
707 server->server_type = SILC_BACKUP_ROUTER;
708 server->backup_router = TRUE;
709 server->id_entry->server_type = SILC_BACKUP_ROUTER;
717 if (server->server_type == SILC_ROUTER)
718 server->stat.routers++;
726 /* Free's the SILC server context */
728 void silc_server_free(SilcServer server)
731 SilcIDCacheList list;
732 SilcIDCacheEntry cache;
740 silc_dlist_start(server->sim);
741 while ((sim = silc_dlist_get(server->sim)) != SILC_LIST_END) {
742 silc_dlist_del(server->sim, sim);
746 silc_dlist_uninit(server->sim);
750 silc_server_backup_free(server);
751 silc_server_params_unref(&server->params_ref);
753 silc_rng_free(server->rng);
755 silc_pkcs_free(server->pkcs);
756 if (server->public_key)
757 silc_pkcs_public_key_free(server->public_key);
758 if (server->private_key)
759 silc_pkcs_private_key_free(server->private_key);
760 if (server->pending_commands)
761 silc_dlist_uninit(server->pending_commands);
762 if (server->id_entry)
763 silc_idlist_del_server(server->local_list, server->id_entry);
765 /* Delete all channels */
767 if (silc_idcache_get_all(server->local_list->channels, &list) &&
768 silc_idcache_list_first(list, &cache)) {
769 silc_idlist_del_channel(server->local_list, cache->context);
770 while (silc_idcache_list_next(list, &cache))
771 silc_idlist_del_channel(server->local_list, cache->context);
774 silc_idcache_list_free(list);
776 if (silc_idcache_get_all(server->global_list->channels, &list) &&
777 silc_idcache_list_first(list, &cache)) {
778 silc_idlist_del_channel(server->global_list, cache->context);
779 while (silc_idcache_list_next(list, &cache))
780 silc_idlist_del_channel(server->global_list, cache->context);
783 silc_idcache_list_free(list);
786 silc_hash_table_free(server->pk_hash);
788 /* Delete all clients */
790 if (silc_idcache_get_all(server->local_list->clients, &list) &&
791 silc_idcache_list_first(list, &cache)) {
792 silc_idlist_del_client(server->local_list, cache->context);
793 while (silc_idcache_list_next(list, &cache))
794 silc_idlist_del_client(server->local_list, cache->context);
797 silc_idcache_list_free(list);
799 if (silc_idcache_get_all(server->global_list->clients, &list) &&
800 silc_idcache_list_first(list, &cache)) {
801 silc_idlist_del_client(server->global_list, cache->context);
802 while (silc_idcache_list_next(list, &cache))
803 silc_idlist_del_client(server->global_list, cache->context);
806 silc_idcache_list_free(list);
809 /* Delete all servers */
811 if (silc_idcache_get_all(server->local_list->servers, &list) &&
812 silc_idcache_list_first(list, &cache)) {
813 silc_idlist_del_server(server->local_list, cache->context);
814 while (silc_idcache_list_next(list, &cache))
815 silc_idlist_del_server(server->local_list, cache->context);
818 silc_idcache_list_free(list);
820 if (silc_idcache_get_all(server->global_list->servers, &list) &&
821 silc_idcache_list_first(list, &cache)) {
822 silc_idlist_del_server(server->global_list, cache->context);
823 while (silc_idcache_list_next(list, &cache))
824 silc_idlist_del_server(server->global_list, cache->context);
827 silc_idcache_list_free(list);
831 silc_idcache_free(server->clients);
832 silc_idcache_free(server->servers);
833 silc_idcache_free(server->channels);
834 silc_hash_table_free(server->watcher_list);
835 silc_hash_table_free(server->watcher_list_pk);
837 silc_hash_free(server->md5hash);
838 silc_hash_free(server->sha1hash);
839 silc_hmac_unregister_all();
840 silc_hash_unregister_all();
841 silc_cipher_unregister_all();
842 silc_pkcs_unregister_all();
845 /* Starts the SILC server FSM machine and returns immediately. The
846 scheduler must be run or be running already when this returns. */
848 void silc_server_run(SilcServer server, SilcServerRunning running,
849 void *running_context)
851 SILC_LOG_INFO(("Starting SILC server"));
853 server->starttime = time(NULL);
854 server->running = running;
855 server->running_context = running_context;
857 /* Start the server */
858 silc_fsm_start_sync(&server->fsm, silc_server_st_run);
860 /* Signal the application when we are running */
861 server->run_callback = TRUE;
862 SILC_FSM_SEMA_POST(&server->wait_event);
864 /* Signal to connect to router */
865 server->connect_router = TRUE;
866 SILC_FSM_SEMA_POST(&server->wait_event);
868 /* Start getting statistics from the network on normal server */
869 if (server->server_type != SILC_ROUTER) {
870 server->get_statistics = TRUE;
871 SILC_FSM_SEMA_POST(&server->wait_event);
875 /* Stops the SILC server */
877 void silc_server_stop(SilcServer server, SilcServerStop stopped,
880 SILC_LOG_INFO(("Stopping SILC server"));
882 server->stopped = stopped;
883 server->stop_context = stop_context;
885 /* Signal that server is going down */
886 server->server_shutdown = TRUE;
887 SILC_FSM_SEMA_POST(&server->wait_event);
890 /* Disconnects remote connection */
892 SilcBool silc_server_disconnect(SilcServer server,
893 SilcPacketStream stream,
895 const char *error_string)