+ silc_server_stop(silcd);
+}
+
+/* Dump server statistics into a file into /tmp directory */
+
+SILC_TASK_CALLBACK(dump_stats)
+{
+ FILE *fdd;
+ int fild;
+ char filename[256];
+
+ memset(filename, 0, sizeof(filename));
+ snprintf(filename, sizeof(filename) - 1, "/tmp/silcd.%d.stats-XXXXXX", getpid());
+ fild = mkstemp(filename);
+ if (fild == -1)
+ return;
+
+ fdd = fdopen(fild, "w");
+ if (fdd == NULL) {
+ close(fild);
+ unlink(filename);
+ return;
+ }
+
+#define STAT_OUTPUT(fmt, stat) fprintf(fdd, fmt "\n", (int)stat);
+
+ fprintf(fdd, "SILC Server %s Statistics\n\n", silcd->server_name);
+ fprintf(fdd, "Local Stats:\n");
+ STAT_OUTPUT(" My clients : %d", silcd->stat.my_clients);
+ STAT_OUTPUT(" My servers : %d", silcd->stat.my_servers);
+ STAT_OUTPUT(" My routers : %d", silcd->stat.my_routers);
+ STAT_OUTPUT(" My channels : %d", silcd->stat.my_channels);
+ STAT_OUTPUT(" My joined users : %d", silcd->stat.my_chanclients);
+ STAT_OUTPUT(" My aways : %d", silcd->stat.my_aways);
+ STAT_OUTPUT(" My detached clients : %d", silcd->stat.my_detached);
+ STAT_OUTPUT(" My server operators : %d", silcd->stat.my_server_ops);
+ STAT_OUTPUT(" My router operators : %d", silcd->stat.my_router_ops);
+ fprintf(fdd, "\nGlobal Stats:\n");
+ STAT_OUTPUT(" Cell clients : %d", silcd->stat.cell_clients);
+ STAT_OUTPUT(" Cell servers : %d", silcd->stat.cell_servers);
+ STAT_OUTPUT(" Cell channels : %d", silcd->stat.cell_channels);
+ STAT_OUTPUT(" Cell joined users : %d", silcd->stat.cell_chanclients);
+ STAT_OUTPUT(" All clients : %d", silcd->stat.clients);
+ STAT_OUTPUT(" All servers : %d", silcd->stat.servers);
+ STAT_OUTPUT(" All routers : %d", silcd->stat.routers);
+ STAT_OUTPUT(" All channels : %d", silcd->stat.channels);
+ STAT_OUTPUT(" All joined users : %d", silcd->stat.chanclients);
+ STAT_OUTPUT(" All aways : %d", silcd->stat.aways);
+ STAT_OUTPUT(" All detached clients : %d", silcd->stat.detached);
+ STAT_OUTPUT(" All server operators : %d", silcd->stat.server_ops);
+ STAT_OUTPUT(" All router operators : %d", silcd->stat.router_ops);
+ fprintf(fdd, "\nGeneral Stats:\n");
+ STAT_OUTPUT(" Connection attempts : %d", silcd->stat.conn_attempts);
+ STAT_OUTPUT(" Connection failures : %d", silcd->stat.conn_failures);
+ STAT_OUTPUT(" Authentication attempts : %d", silcd->stat.auth_attempts);
+ STAT_OUTPUT(" Authentication failures : %d", silcd->stat.auth_failures);
+ STAT_OUTPUT(" Packets sent : %d", silcd->stat.packets_sent);
+ STAT_OUTPUT(" Packets received : %d", silcd->stat.packets_received);
+ STAT_OUTPUT(" Commands sent : %d", silcd->stat.commands_sent);
+ STAT_OUTPUT(" Commands received : %d", silcd->stat.commands_received);
+ STAT_OUTPUT(" Connections : %d", silcd->stat.conn_num);
+
+#undef STAT_OUTPUT
+
+#ifdef SILC_DEBUG
+ /* Dump internal flags */
+ fprintf(fdd, "\nDumping internal flags\n");
+ fprintf(fdd, " server_type : %d\n", silcd->server_type);
+ fprintf(fdd, " standalone : %d\n", silcd->standalone);
+ fprintf(fdd, " listenning : %d\n", silcd->listenning);
+ fprintf(fdd, " background : %d\n", silcd->background);
+ fprintf(fdd, " backup_router : %d\n", silcd->backup_router);
+ fprintf(fdd, " backup_primary : %d\n", silcd->backup_primary);
+ fprintf(fdd, " backup_noswitch : %d\n", silcd->backup_noswitch);
+ fprintf(fdd, " backup_closed : %d\n", silcd->backup_closed);
+ fprintf(fdd, " wait_backup : %d\n", silcd->wait_backup);
+ if (silcd->router)
+ fprintf(fdd, " primary router : %s\n",
+ silcd->router->server_name ? silcd->router->server_name : "");
+
+ /* Dump connections */
+ {
+ SilcPacketStream s;
+ SilcDList conns = silc_packet_engine_get_streams(silcd->packet_engine);
+
+ fprintf(fdd, "\nDumping connections\n");
+ silc_dlist_start(conns);
+ while ((s = silc_dlist_get(conns))) {
+ const char *hostname, *ip;
+ SilcUInt16 port;
+ SilcSocket sock;
+ SilcIDListData idata = silc_packet_get_context(s);
+ if (!silc_socket_stream_get_info(silc_packet_stream_get_stream(s),
+ &sock, &hostname, &ip, &port))
+ continue;
+ fprintf(fdd, " %d: host %s ip %s port %d type %d\n",
+ sock, hostname ? hostname : "N/A",
+ ip ? ip : "N/A", port, idata ? idata->conn_type : 0);
+ }
+ silc_dlist_uninit(conns);
+ }
+
+ /* Dump lists */
+ {
+ SilcList list;
+ SilcIDCacheEntry id_cache = NULL;
+ SilcServerEntry server_entry;
+ SilcClientEntry client_entry;
+ SilcChannelEntry channel_entry;
+ int c;
+
+ fprintf(fdd, "\nDumping databases\n");
+
+ if (silc_idcache_get_all(silcd->local_list->servers, &list)) {
+ c = 1;
+ fprintf(fdd, "\nServers in local-list:\n");
+ while ((id_cache = silc_list_get(list))) {
+ server_entry = (SilcServerEntry)id_cache->context;
+ fprintf(fdd, " %d: name %s id %s status 0x%x\n", c,
+ server_entry->server_name ? server_entry->server_name :
+ "N/A", server_entry->id ?
+ silc_id_render(server_entry->id, SILC_ID_SERVER) : "N/A",
+ server_entry->data.status);
+ c++;
+ }
+ }
+ if (silc_idcache_get_all(silcd->global_list->servers, &list)) {
+ fprintf(fdd, "\nServers in global-list:\n");
+ c = 1;
+ while ((id_cache = silc_list_get(list))) {
+ server_entry = (SilcServerEntry)id_cache->context;
+ fprintf(fdd, " %d: name %s id %s status 0x%x\n", c,
+ server_entry->server_name ? server_entry->server_name :
+ "N/A", server_entry->id ?
+ silc_id_render(server_entry->id, SILC_ID_SERVER) : "N/A",
+ server_entry->data.status);
+ c++;
+ }
+ }
+ if (silc_idcache_get_all(silcd->local_list->clients, &list)) {
+ fprintf(fdd, "\nClients in local-list:\n");
+ c = 1;
+ while ((id_cache = silc_list_get(list))) {
+ client_entry = (SilcClientEntry)id_cache->context;
+ server_entry = client_entry->router;
+ fprintf(fdd, " %d: name %s id %s status 0x%x from %s\n", c,
+ client_entry->nickname ? client_entry->nickname :
+ (unsigned char *)"N/A", client_entry->id ?
+ silc_id_render(client_entry->id, SILC_ID_CLIENT) : "N/A",
+ client_entry->data.status, server_entry ?
+ server_entry->server_name ? server_entry->server_name :
+ "N/A" : "local");
+ c++;
+ }
+ }
+ if (silc_idcache_get_all(silcd->global_list->clients, &list)) {
+ fprintf(fdd, "\nClients in global-list:\n");
+ c = 1;
+ while ((id_cache = silc_list_get(list))) {
+ client_entry = (SilcClientEntry)id_cache->context;
+ server_entry = client_entry->router;
+ fprintf(fdd, " %d: name %s id %s status 0x%x from %s\n", c,
+ client_entry->nickname ? client_entry->nickname :
+ (unsigned char *)"N/A", client_entry->id ?
+ silc_id_render(client_entry->id, SILC_ID_CLIENT) : "N/A",
+ client_entry->data.status, server_entry ?
+ server_entry->server_name ? server_entry->server_name :
+ "N/A" : "local");
+ c++;
+ }
+ }
+ if (silc_idcache_get_all(silcd->local_list->channels, &list)) {
+ fprintf(fdd, "\nChannels in local-list:\n");
+ c = 1;
+ while ((id_cache = silc_list_get(list))) {
+ channel_entry = (SilcChannelEntry)id_cache->context;
+ fprintf(fdd, " %d: name %s id %s\n", c,
+ channel_entry->channel_name ? channel_entry->channel_name :
+ "N/A", channel_entry->id ?
+ silc_id_render(channel_entry->id, SILC_ID_CHANNEL) : "N/A");
+ c++;
+ }
+ }
+ if (silc_idcache_get_all(silcd->global_list->channels, &list)) {
+ fprintf(fdd, "\nChannels in global-list:\n");
+ c = 1;
+ while ((id_cache = silc_list_get(list))) {
+ channel_entry = (SilcChannelEntry)id_cache->context;
+ fprintf(fdd, " %d: name %s id %s\n", c,
+ channel_entry->channel_name ? channel_entry->channel_name :
+ "N/A", channel_entry->id ?
+ silc_id_render(channel_entry->id, SILC_ID_CHANNEL) : "N/A");
+ c++;
+ }
+ }
+ }
+#endif
+
+ fflush(fdd);
+ fclose(fdd);
+}
+
+#ifdef SILC_DEBUG
+
+typedef struct {
+ int level;
+ const char *string;
+} DebugLevel;
+
+static DebugLevel debug_levels[] = {
+ /* Very basic stuff from silcd/ */
+ { 3, "silcd\\.c,server\\.c" },
+
+ /* More stuff from silcd/ */
+ { 7, "silcd\\.c,server\\.c,command\\.c,server_backup\\.c,packet_send\\.c" },
+
+ /* All basic stuff from silcd/ */
+ { 10, "silc_server_*" },
+
+ /* All from silcd/ */
+ { 15, "*silcd*,*serverid*,silc_server_*,*idlist*" },
+
+ /* All from silcd/ and basic stuff from libs */
+ { 20, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,*silcske*" },
+
+ /* All from silcd/ and more stuff from libs */
+ { 25, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,"
+ "*silcpacket*,*ske*,*silcrng*" },
+
+ /* All from silcd/ and even more stuff from libs */
+ { 30, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,"
+ "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*" },
+
+ /* All from silcd/ and even more stuff from libs + all from silccore */
+ { 35, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,"
+ "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
+ "*silcid*,*argument*" },
+
+ /* All from silcd/, all from silccore, silccrypt and silcmath */
+ { 40, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,"
+ "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
+ "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*" },
+
+ /* All from silcd/, all from silccore, silccrypt and silcmath + stuff
+ from silcutil */
+ { 45, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,"
+ "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
+ "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
+ "*sockconn*" },
+
+ /* All from silcd/, all from silccore, silccrypt and silcmath + more stuff
+ from silcutil */
+ { 50, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,"
+ "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
+ "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
+ "*sockconn*,*net*" },
+
+ /* All from silcd/, all from silccore, silccrypt and silcmath + more stuff
+ from silcutil */
+ { 55, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcconauth*,"
+ "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
+ "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
+ "*sockconn*,*net*,*log*,*config*" },
+
+ /* All */
+ { 90, "*" },
+
+ { -1, NULL },
+};
+
+static void silc_get_debug_level(int level)
+{
+ int i;
+
+ if (level < 0)
+ return;
+
+ for (i = 0; debug_levels[i].string; i++)
+ if (level <= debug_levels[i].level) {
+ silc_log_set_debug_string(debug_levels[i].string);
+ break;
+ }