X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=apps%2Fsilcd%2Fserver.c;h=bb5b3b279e819a72d240fa388f5b8fb7610d0e0a;hp=d4770c1f11f489def1cef96471d1e071fd8544c8;hb=4647050fc1a99a44f4ffeb002c0ba1c353695ec0;hpb=0a6ebeedacee8f43f604cddbf7dc6bc113c6515e diff --git a/apps/silcd/server.c b/apps/silcd/server.c index d4770c1f..bb5b3b27 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2007 Pekka Riikonen + Copyright (C) 1997 - 2008 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ SILC_TASK_CALLBACK(silc_server_get_stats); SILC_TASK_CALLBACK(silc_server_connect_router); +SILC_TASK_CALLBACK(silc_server_connect_to_router_retry); SILC_TASK_CALLBACK(silc_server_do_rekey); SILC_TASK_CALLBACK(silc_server_purge_expired_clients); static void silc_server_accept_new_connection(SilcNetStatus status, @@ -79,6 +80,9 @@ static SilcBool silc_server_packet_receive(SilcPacketEngine engine, SilcServer server = callback_context; SilcIDListData idata = stream_context; + if (!idata) + return FALSE; + /* Packets we do not handle */ switch (packet->type) { case SILC_PACKET_HEARTBEAT: @@ -99,12 +103,13 @@ static SilcBool silc_server_packet_receive(SilcPacketEngine engine, !(idata->status & SILC_IDLIST_STATUS_REGISTERED)) && packet->type != SILC_PACKET_NEW_CLIENT && packet->type != SILC_PACKET_NEW_SERVER && + packet->type != SILC_PACKET_RESUME_CLIENT && packet->type != SILC_PACKET_CONNECTION_AUTH_REQUEST && packet->type != SILC_PACKET_DISCONNECT) return FALSE; - /* NEW_CLIENT and NEW_SERVER are accepted only without source ID - and for unregistered connection. */ + /* NEW_CLIENT and NEW_SERVER are accepted only without source ID and + for unregistered connection. */ if (packet->src_id && (packet->type == SILC_PACKET_NEW_CLIENT || packet->type == SILC_PACKET_NEW_SERVER) && (idata->status & SILC_IDLIST_STATUS_REGISTERED)) @@ -126,7 +131,8 @@ static SilcBool silc_server_packet_receive(SilcPacketEngine engine, silc_id_str2id(packet->src_id, packet->src_id_len, packet->src_id_type, &client_id, sizeof(client_id))) { if (!SILC_ID_CLIENT_COMPARE(client->id, &client_id)) { - SILC_LOG_DEBUG(("Packet source is not same as sender")); + SILC_LOG_DEBUG(("Packet source is not same as sender, packet %s", + silc_get_packet_name(packet->type))); return FALSE; } } @@ -188,7 +194,35 @@ static void silc_server_packet_eos(SilcPacketEngine engine, SilcServer server = callback_context; SilcIDListData idata = silc_packet_get_context(stream); - SILC_LOG_DEBUG(("End of stream received")); + SILC_LOG_DEBUG(("End of stream received, sock %p", stream)); + + if (!idata) + return; + + if (server->router_conn && server->router_conn->sock == stream && + !server->router && server->standalone) { + silc_server_create_connections(server); + silc_server_free_sock_user_data(server, stream, NULL); + } else { + /* If backup disconnected then mark that resuming will not be allowed */ + if (server->server_type == SILC_ROUTER && !server->backup_router && + idata->conn_type == SILC_CONN_SERVER) { + SilcServerEntry server_entry = (SilcServerEntry)idata; + if (server_entry->server_type == SILC_BACKUP_ROUTER) + server->backup_closed = TRUE; + } + + silc_server_free_sock_user_data(server, stream, NULL); + } + + silc_server_close_connection(server, stream); +} + +SILC_TASK_CALLBACK(silc_server_packet_error_timeout) +{ + SilcServer server = app_context; + SilcPacketStream stream = context; + SilcIDListData idata = silc_packet_get_context(stream); if (!idata) return; @@ -225,6 +259,8 @@ static void silc_server_packet_error(SilcPacketEngine engine, const char *ip; SilcUInt16 port; + SILC_LOG_DEBUG(("Packet error, sock %p", stream)); + if (!idata || !sock) return; @@ -235,22 +271,12 @@ static void silc_server_packet_error(SilcPacketEngine engine, SILC_CONNTYPE_STRING(idata->conn_type), silc_packet_error_string(error))); - if (server->router_conn && server->router_conn->sock == stream && - !server->router && server->standalone) { - silc_server_create_connections(server); - } else { - /* If backup disconnected then mark that resuming will not be allowed */ - if (server->server_type == SILC_ROUTER && !server->backup_router && - idata->conn_type == SILC_CONN_SERVER) { - SilcServerEntry server_entry = (SilcServerEntry)idata; - if (server_entry->server_type == SILC_BACKUP_ROUTER) - server->backup_closed = TRUE; - } - - silc_server_free_sock_user_data(server, stream, NULL); - } + if (!silc_packet_stream_is_valid(stream)) + return; - silc_server_close_connection(server, stream); + silc_schedule_task_add_timeout(server->schedule, + silc_server_packet_error_timeout, + stream, 0, 0); } /* Packet stream callbacks */ @@ -374,21 +400,18 @@ static void silc_server_packet_parse_type(SilcServer server, server->backup_noswitch = (status == SILC_STATUS_OK ? FALSE : TRUE); /* If backup disconnected then mark that resuming will not be allowed */ -#if 0 if (server->server_type == SILC_ROUTER && !server->backup_router && - sock->type == SILC_CONN_SERVER && sock->user_data) { - SilcServerEntry server_entry = sock->user_data; + idata->conn_type == SILC_CONN_SERVER) { + SilcServerEntry server_entry = (SilcServerEntry)idata; if (server_entry->server_type == SILC_BACKUP_ROUTER) server->backup_closed = TRUE; } /* Handle the disconnection from our end too */ - if (sock->user_data && SILC_IS_LOCAL(sock->user_data)) + if (SILC_IS_LOCAL(idata)) silc_server_free_sock_user_data(server, sock, NULL); - SILC_SET_DISCONNECTING(sock); silc_server_close_connection(server, sock); server->backup_noswitch = FALSE; -#endif } break; @@ -517,9 +540,7 @@ static void silc_server_packet_parse_type(SilcServer server, router resuming protocol. */ if (packet->flags & SILC_PACKET_FLAG_LIST) break; -#if 0 silc_server_backup_resume_router(server, sock, packet); -#endif break; default: @@ -653,6 +674,10 @@ void silc_server_free(SilcServer server) } } + silc_schedule_task_del_by_context(server->schedule, server); + silc_schedule_uninit(server->schedule); + server->schedule = NULL; + silc_idcache_free(server->local_list->clients); silc_idcache_free(server->local_list->servers); silc_idcache_free(server->local_list->channels); @@ -670,10 +695,6 @@ void silc_server_free(SilcServer server) silc_skr_free(server->repository); silc_packet_engine_stop(server->packet_engine); - silc_schedule_task_del_by_context(server->schedule, server); - silc_schedule_uninit(server->schedule); - server->schedule = NULL; - silc_free(server->local_list); silc_free(server->global_list); silc_free(server->server_name); @@ -710,60 +731,19 @@ silc_server_listen(SilcServer server, const char *server_ip, SilcUInt16 port) SilcBool silc_server_init_secondary(SilcServer server) { - return TRUE; -#if 0 - int sock = 0; - SilcPacketStream newsocket = NULL; SilcServerConfigServerInfoInterface *interface; + SilcNetListener listener; for (interface = server->config->server_info->secondary; interface; - interface = interface->next, sock++) { - - if (!silc_server_listen(server, - interface->server_ip, interface->port, &sock_list[sock])) - goto err; - - /* Set socket to non-blocking mode */ - silc_net_set_socket_nonblock(sock_list[sock]); - - /* Add ourselves also to the socket table. The entry allocated above - is sent as argument for fast referencing in the future. */ - silc_socket_alloc(sock_list[sock], - SILC_CONN_SERVER, NULL, &newsocket); - server->sockets[sock_list[sock]] = newsocket; - SILC_SET_LISTENER(newsocket); - - /* Perform name and address lookups to resolve the listenning address - and port. */ - if (!silc_net_check_local_by_sock(sock_list[sock], &newsocket->hostname, - &newsocket->ip)) { - if ((server->config->require_reverse_lookup && !newsocket->hostname) || - !newsocket->ip) { - SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s", - newsocket->hostname ? newsocket->hostname : - newsocket->ip ? newsocket->ip : "")); - server->stat.conn_failures++; - goto err; - } - if (!newsocket->hostname) - newsocket->hostname = strdup(newsocket->ip); - } - newsocket->port = silc_net_get_local_port(sock); - - newsocket->user_data = (void *)server->id_entry; - silc_schedule_task_add(server->schedule, sock_list[sock], - silc_server_accept_new_connection, - (void *)server, 0, 0, - SILC_TASK_FD, - SILC_TASK_PRI_NORMAL); + interface = interface->next) { + listener = silc_server_listen(server, interface->server_ip, + interface->port); + if (!listener) + return FALSE; + silc_dlist_add(server->listeners, listener); } return TRUE; - - err: - do silc_net_close_server(sock_list[sock--]); while (sock >= 0); -#endif /* 0 */ - return FALSE; } /* Initializes the entire SILC server. This is called always before running @@ -878,7 +858,6 @@ SilcBool silc_server_init(SilcServer server) server->config->server_info->primary->port); if (!listener) goto err; - silc_dlist_add(server->listeners, listener); /* Create a Server ID for the server. */ @@ -906,12 +885,16 @@ SilcBool silc_server_init(SilcServer server) the ID list. */ id_entry = silc_idlist_add_server(server->local_list, strdup(server->server_name), - server->server_type, server->id, NULL, NULL); + server->server_type, + silc_id_dup(server->id, SILC_ID_SERVER), + NULL, NULL); if (!id_entry) { SILC_LOG_ERROR(("Could not add local server to cache")); goto err; } id_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED; + id_entry->data.conn_type = (server->server_type == SILC_SERVER ? + SILC_CONN_SERVER : SILC_CONN_ROUTER); server->id_entry = id_entry; /* Create secondary TCP listeners */ @@ -940,24 +923,12 @@ SilcBool silc_server_init(SilcServer server) } } -#if 0 - /* Register the ID Cache purge task. This periodically purges the ID cache - and removes the expired cache entries. */ - - /* Clients local list */ - server->purge_i = purge = silc_calloc(1, sizeof(*purge)); - purge->cache = server->local_list->clients; - purge->timeout = 600; - silc_schedule_task_add_timeout(server->schedule, silc_idlist_purge, - (void *)purge, purge->timeout, 0); - - /* Clients global list */ - server->purge_g = purge = silc_calloc(1, sizeof(*purge)); - purge->cache = server->global_list->clients; - purge->timeout = 300; - silc_schedule_task_add_timeout(server->schedule, silc_idlist_purge, - (void *)purge, purge->timeout, 0); -#endif /Ã* 0 */ + if (server->server_type != SILC_ROUTER) { + server->stat.servers = 1; + server->stat.cell_servers = 1; + } else { + server->stat.routers = 1; + } /* If we are normal server we'll retrieve network statisticial information once in a while from the router. */ @@ -965,9 +936,6 @@ SilcBool silc_server_init(SilcServer server) silc_schedule_task_add_timeout(server->schedule, silc_server_get_stats, server, 10, 0); - if (server->server_type == SILC_ROUTER) - server->stat.routers++; - /* Start packet engine */ server->packet_engine = silc_packet_engine_start(server->rng, server->server_type == SILC_ROUTER, @@ -993,32 +961,28 @@ SilcBool silc_server_init(SilcServer server) return FALSE; } -#if 0 /* Task callback to close a socket connection after rehash */ SILC_TASK_CALLBACK(silc_server_rehash_close_connection) { - SilcServer server = context; - SilcPacketStream sock = server->sockets[fd]; + SilcServer server = app_context; + SilcPacketStream sock = context; + SilcIDListData idata = silc_packet_get_context(sock); + const char *hostname; + SilcUInt16 port; - if (!sock) - return; + silc_socket_stream_get_info(silc_packet_stream_get_stream(sock), + NULL, &hostname, NULL, &port); SILC_LOG_INFO(("Connection %s:%d [%s] is unconfigured", - sock->hostname, sock->port, - (sock->type == SILC_CONN_UNKNOWN ? "Unknown" : - sock->type == SILC_CONN_CLIENT ? "Client" : - sock->type == SILC_CONN_SERVER ? "Server" : - "Router"))); + hostname, port, SILC_CONNTYPE_STRING(idata->conn_type))); silc_schedule_task_del_by_context(server->schedule, sock); silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_BANNED_FROM_SERVER, "This connection is removed from " "configuration"); - if (sock->user_data) - silc_server_free_sock_user_data(server, sock, NULL); + silc_server_free_sock_user_data(server, sock, NULL); } -#endif /* 0 */ /* This function basically reads the config file again and switches the config object pointed by the server object. After that, we have to fix various @@ -1027,7 +991,6 @@ SILC_TASK_CALLBACK(silc_server_rehash_close_connection) SilcBool silc_server_rehash(SilcServer server) { -#if 0 SilcServerConfig newconfig; SILC_LOG_INFO(("Rehashing server")); @@ -1043,12 +1006,6 @@ SilcBool silc_server_rehash(SilcServer server) return FALSE; } - /* Reinit scheduler if necessary */ - if (newconfig->param.connections_max > server->config->param.connections_max) - if (!silc_schedule_reinit(server->schedule, - newconfig->param.connections_max)) - return FALSE; - /* Fix the server_name field */ if (strcmp(server->server_name, newconfig->server_info->server_name)) { silc_free(server->server_name); @@ -1067,13 +1024,10 @@ SilcBool silc_server_rehash(SilcServer server) /* Update the idcache list with a fresh pointer */ silc_free(server->id_entry->server_name); server->id_entry->server_name = strdup(server->server_name); - if (!silc_idcache_del_by_context(server->local_list->servers, - server->id_entry)) - return FALSE; - if (!silc_idcache_add(server->local_list->servers, - strdup(server->id_entry->server_name), - server->id_entry->id, server->id_entry, 0, NULL)) - return FALSE; + silc_idcache_update_by_context(server->local_list->servers, + server->id_entry, NULL, + strdup(server->id_entry->server_name), + TRUE); } /* Set logging */ @@ -1089,13 +1043,6 @@ SilcBool silc_server_rehash(SilcServer server) server->private_key = newconfig->server_info->private_key; newconfig->server_info->public_key = NULL; newconfig->server_info->private_key = NULL; - - /* Allocate PKCS context for local public and private keys */ - silc_pkcs_free(server->pkcs); - if (!silc_pkcs_alloc(server->public_key->name, &server->pkcs)) - return FALSE; - silc_pkcs_public_key_set(server->pkcs, server->public_key); - silc_pkcs_private_key_set(server->pkcs, server->private_key); } /* Check for unconfigured server and router connections and close @@ -1124,11 +1071,10 @@ SilcBool silc_server_rehash(SilcServer server) SilcPacketStream sock; sock = silc_server_find_socket_by_host(server, SILC_CONN_ROUTER, ptr->host, ptr->port); - if (sock && !SILC_IS_LISTENER(sock)) - silc_schedule_task_add(server->schedule, sock->sock, - silc_server_rehash_close_connection, - server, 0, 1, SILC_TASK_TIMEOUT, - SILC_TASK_PRI_NORMAL); + if (sock) + silc_schedule_task_add_timeout(server->schedule, + silc_server_rehash_close_connection, + sock, 0, 1); } } } @@ -1154,11 +1100,10 @@ SilcBool silc_server_rehash(SilcServer server) SilcPacketStream sock; sock = silc_server_find_socket_by_host(server, SILC_CONN_SERVER, ptr->host, 0); - if (sock && !SILC_IS_LISTENER(sock)) - silc_schedule_task_add(server->schedule, sock->sock, - silc_server_rehash_close_connection, - server, 0, 1, SILC_TASK_TIMEOUT, - SILC_TASK_PRI_NORMAL); + if (sock) + silc_schedule_task_add_timeout(server->schedule, + silc_server_rehash_close_connection, + sock, 0, 1); } } } @@ -1185,10 +1130,9 @@ SilcBool silc_server_rehash(SilcServer server) sock = silc_server_find_socket_by_host(server, SILC_CONN_CLIENT, ptr->host, 0); if (sock) - silc_schedule_task_add(server->schedule, sock->sock, - silc_server_rehash_close_connection, - server, 0, 1, SILC_TASK_TIMEOUT, - SILC_TASK_PRI_NORMAL); + silc_schedule_task_add_timeout(server->schedule, + silc_server_rehash_close_connection, + sock, 0, 1); } } } @@ -1231,7 +1175,6 @@ SilcBool silc_server_rehash(SilcServer server) #endif /* SILC_DEBUG */ SILC_LOG_DEBUG(("Server rehashed")); -#endif /* 0 */ return TRUE; } @@ -1271,6 +1214,9 @@ void silc_server_stop(SilcServer server) while ((ps = silc_dlist_get(list))) { SilcIDListData idata = silc_packet_get_context(ps); + if (!silc_packet_stream_is_valid(ps)) + continue; + if (idata) idata->status &= ~SILC_IDLIST_STATUS_DISABLED; @@ -1279,7 +1225,7 @@ void silc_server_stop(SilcServer server) silc_server_free_sock_user_data(server, ps, "Server is shutting down"); } - silc_dlist_uninit(list); + silc_packet_engine_free_streams_list(list); } /* We are not connected to network anymore */ @@ -1291,6 +1237,14 @@ void silc_server_stop(SilcServer server) silc_server_http_uninit(server); + /* Cancel any possible retry timeouts */ + silc_schedule_task_del_by_callback(server->schedule, + silc_server_connect_router); + silc_schedule_task_del_by_callback(server->schedule, + silc_server_connect_to_router_retry); + silc_schedule_task_del_by_callback(server->schedule, + silc_server_connect_to_router); + silc_schedule_stop(server->schedule); SILC_LOG_DEBUG(("Server stopped")); @@ -1309,13 +1263,10 @@ SILC_TASK_CALLBACK(silc_server_purge_expired_clients) silc_dlist_start(server->expired_clients); while ((client = silc_dlist_get(server->expired_clients))) { - if (client->data.status & SILC_IDLIST_STATUS_REGISTERED) - continue; - /* For unregistered clients the created timestamp is actually unregistered timestamp. Make sure client remains in history at least 500 seconds. */ - if (curtime - client->data.created < 500) + if (client->data.created && curtime - client->data.created < 500) continue; id_list = (client->data.status & SILC_IDLIST_STATUS_LOCAL ? @@ -1338,6 +1289,8 @@ SILC_TASK_CALLBACK(silc_server_purge_expired_clients) void silc_server_connection_free(SilcServerConnection sconn) { + if (!sconn) + return; SILC_LOG_DEBUG(("Free connection %p", sconn)); silc_dlist_del(sconn->server->conns, sconn); silc_server_config_unref(&sconn->conn); @@ -1391,19 +1344,30 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, unsigned char id[32]; SilcUInt32 id_len; SilcID remote_id; + const char *ip; - SILC_LOG_DEBUG(("Connection authentication completed")); + SILC_LOG_DEBUG(("Connection %p authentication completed, entry %p", + sconn, entry)); - sconn->op = NULL; + entry->op = NULL; if (success == FALSE) { /* Authentication failed */ - /* XXX retry connecting */ - silc_server_disconnect_remote(server, sconn->sock, - SILC_STATUS_ERR_AUTH_FAILED, NULL); + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } + if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); + silc_server_free_sock_user_data(server, sconn->sock, NULL); + silc_server_disconnect_remote(server, sconn->sock, + SILC_STATUS_ERR_AUTH_FAILED, NULL); return; } @@ -1425,15 +1389,20 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, strdup(sconn->remote_host), SILC_SERVER, NULL, NULL, sconn->sock); if (!id_entry) { - silc_server_disconnect_remote(server, sconn->sock, - SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); - silc_server_connection_free(sconn); - silc_free(entry); + silc_server_free_sock_user_data(server, sconn->sock, NULL); + silc_server_disconnect_remote(server, sconn->sock, + SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); return; } + /* Statistics */ + server->stat.my_servers++; + if (server->server_type == SILC_ROUTER) + server->stat.servers++; + SILC_LOG_DEBUG(("my_servers %d", server->stat.my_servers)); + silc_idlist_add_data(id_entry, (SilcIDListData)entry); break; @@ -1449,12 +1418,11 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_STR_DATA(server->server_name, strlen(server->server_name)), SILC_STR_END)) { - silc_server_disconnect_remote(server, sconn->sock, - SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); - silc_server_connection_free(sconn); - silc_free(entry); + silc_server_free_sock_user_data(server, sconn->sock, NULL); + silc_server_disconnect_remote(server, sconn->sock, + SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); return; } @@ -1488,12 +1456,20 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_ID_SERVER), NULL, sconn->sock); if (!id_entry) { - silc_server_disconnect_remote(server, sconn->sock, - SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } + if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); - silc_server_connection_free(sconn); - silc_free(entry); + silc_server_free_sock_user_data(server, sconn->sock, NULL); + silc_server_disconnect_remote(server, sconn->sock, + SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); return; } @@ -1504,6 +1480,12 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_IDLIST_STATUS_LOCAL); idata->sconn = sconn; + /* Statistics */ + server->stat.my_routers++; + if (server->server_type == SILC_ROUTER) + server->stat.routers++; + SILC_LOG_DEBUG(("my_routers %d", server->stat.my_routers)); + if (!sconn->backup) { /* Mark this router our primary router if we're still standalone */ if (server->standalone) { @@ -1532,14 +1514,29 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, silc_server_announce_channels(server, 0, SILC_PRIMARY_ROUTE(server)); } -#if 0 /* If we are backup router then this primary router is whom we are backing up. */ - if (server->server_type == SILC_BACKUP_ROUTER) - silc_server_backup_add(server, server->id_entry, sock->ip, + if (server->server_type == SILC_BACKUP_ROUTER) { + silc_socket_stream_get_info(silc_packet_stream_get_stream(sconn-> + sock), + NULL, NULL, &ip, NULL); + silc_server_backup_add(server, server->id_entry, ip, sconn->remote_port, TRUE); -#endif /* 0 */ + } } +#if 0 + else { + /* We already have primary router. Disconnect this connection */ + SILC_LOG_DEBUG(("We already have primary router, disconnect")); + silc_idlist_del_server(server->global_list, id_entry); + if (sconn->callback) + (*sconn->callback)(server, NULL, sconn->callback_context); + silc_server_free_sock_user_data(server, sconn->sock, NULL); + silc_server_disconnect_remote(server, sconn->sock, + SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); + return; + } +#endif /* 0 */ } else { /* Add this server to be our backup router */ id_entry->server_type = SILC_BACKUP_ROUTER; @@ -1550,12 +1547,11 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, break; default: - silc_server_disconnect_remote(server, sconn->sock, - SILC_STATUS_ERR_AUTH_FAILED, NULL); if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); - silc_server_connection_free(sconn); - silc_free(entry); + silc_server_free_sock_user_data(server, sconn->sock, NULL); + silc_server_disconnect_remote(server, sconn->sock, + SILC_STATUS_ERR_AUTH_FAILED, NULL); return; } @@ -1571,33 +1567,16 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, silc_schedule_task_add_timeout(server->schedule, silc_server_do_rekey, sconn->sock, sconn->rekey_timeout, 0); -#if 0 - /* Perform keepalive. */ - silc_socket_set_heartbeat(sock, param->keepalive_secs, server, - silc_server_perform_heartbeat, - server->schedule); -#endif /* 0 */ - /* Set the entry as packet stream context */ silc_packet_set_context(sconn->sock, id_entry); - out: /* Call the completion callback to indicate that we've connected to the router */ if (sconn && sconn->callback) (*sconn->callback)(server, id_entry, sconn->callback_context); -#if 0 - /* Free the temporary connection data context */ - if (sconn) { - silc_server_config_unref(&sconn->conn); - silc_free(sconn->remote_host); - silc_free(sconn->backup_replace_ip); - silc_free(sconn); - } if (sconn == server->router_conn) server->router_conn = NULL; -#endif /* 0 */ silc_free(entry); } @@ -1612,7 +1591,7 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status, { SilcPacketStream sock = context; SilcUnknownEntry entry = silc_packet_get_context(sock); - SilcServerConnection sconn = silc_ske_get_context(ske); + SilcServerConnection sconn = entry->data.sconn; SilcServer server = entry->server; SilcServerConfigRouter *conn = sconn->conn.ref_ptr; SilcAuthMethod auth_meth = SILC_AUTH_NONE; @@ -1623,20 +1602,30 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status, SilcHmac hmac_send, hmac_receive; SilcHash hash; - sconn->op = NULL; + SILC_LOG_DEBUG(("Connection %p, SKE completed, entry %p", sconn, entry)); + + entry->op = NULL; if (status != SILC_SKE_STATUS_OK) { /* SKE failed */ SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)", silc_ske_map_status(status), entry->hostname, entry->ip)); - - /* XXX retry connecting */ silc_ske_free(ske); - silc_server_disconnect_remote(server, sconn->sock, - SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL); + + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } + if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); - silc_server_connection_free(sconn); + silc_server_free_sock_user_data(server, sconn->sock, NULL); + silc_server_disconnect_remote(server, sconn->sock, + SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL); return; } @@ -1645,16 +1634,23 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status, /* Set the keys into use. The data will be encrypted after this. */ if (!silc_ske_set_keys(ske, keymat, prop, &send_key, &receive_key, &hmac_send, &hmac_receive, &hash)) { + silc_ske_free(ske); - /* XXX retry connecting */ + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } /* Error setting keys */ - silc_ske_free(ske); - silc_server_disconnect_remote(server, sconn->sock, - SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL); if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); - silc_server_connection_free(sconn); + silc_server_free_sock_user_data(server, sconn->sock, NULL); + silc_server_disconnect_remote(server, sconn->sock, + SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL); return; } silc_packet_set_keys(sconn->sock, send_key, receive_key, hmac_send, @@ -1665,15 +1661,23 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status, connauth = silc_connauth_alloc(server->schedule, ske, server->config->conn_auth_timeout); if (!connauth) { - /* XXX retry connecting */ + silc_ske_free(ske); + + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } /** Error allocating auth protocol */ - silc_ske_free(ske); - silc_server_disconnect_remote(server, sconn->sock, - SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); - silc_server_connection_free(sconn); + silc_server_free_sock_user_data(server, sconn->sock, NULL); + silc_server_disconnect_remote(server, sconn->sock, + SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); return; } @@ -1694,10 +1698,12 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status, } } + entry->data.rekey = rekey; + /* Start connection authentication */ - sconn->op = - silc_connauth_initiator(connauth, server->server_type == SILC_ROUTER ? - SILC_CONN_ROUTER : SILC_CONN_SERVER, auth_meth, + entry->op = + silc_connauth_initiator(connauth, server->server_type == SILC_SERVER ? + SILC_CONN_SERVER : SILC_CONN_ROUTER, auth_meth, auth_data, auth_data_len, silc_server_ke_auth_compl, sconn); } @@ -1723,6 +1729,16 @@ void silc_server_start_key_exchange(SilcServerConnection sconn) if (!sconn->sock) { SILC_LOG_ERROR(("Cannot connect: cannot create packet stream")); silc_stream_destroy(sconn->stream); + + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } + if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); silc_server_connection_free(sconn); @@ -1734,6 +1750,16 @@ void silc_server_start_key_exchange(SilcServerConnection sconn) if (!silc_packet_set_ids(sconn->sock, SILC_ID_SERVER, server->id, 0, NULL)) { silc_packet_stream_destroy(sconn->sock); + + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } + if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); silc_server_connection_free(sconn); @@ -1744,12 +1770,27 @@ void silc_server_start_key_exchange(SilcServerConnection sconn) entry = silc_calloc(1, sizeof(*entry)); if (!entry) { silc_packet_stream_destroy(sconn->sock); + + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } + + if (sconn->callback) + (*sconn->callback)(server, NULL, sconn->callback_context); silc_server_connection_free(sconn); return; } entry->server = server; + entry->data.sconn = sconn; silc_packet_set_context(sconn->sock, entry); + SILC_LOG_DEBUG(("Created unknown connection %p", entry)); + /* Set Key Exchange flags from configuration, but fall back to global settings too. */ memset(¶ms, 0, sizeof(params)); @@ -1758,12 +1799,22 @@ void silc_server_start_key_exchange(SilcServerConnection sconn) params.flags |= SILC_SKE_SP_FLAG_PFS; /* Start SILC Key Exchange protocol */ - SILC_LOG_DEBUG(("Starting key exchange protocol")); + SILC_LOG_DEBUG(("Starting key exchange protocol, connection %p", sconn)); ske = silc_ske_alloc(server->rng, server->schedule, server->repository, server->public_key, server->private_key, sconn); if (!ske) { silc_free(entry); silc_packet_stream_destroy(sconn->sock); + + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + return; + } + if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); silc_server_connection_free(sconn); @@ -1775,7 +1826,7 @@ void silc_server_start_key_exchange(SilcServerConnection sconn) /* Start key exchange protocol */ params.version = silc_version_string; params.timeout_secs = server->config->key_exchange_timeout; - sconn->op = silc_ske_initiator(ske, sconn->sock, ¶ms, NULL); + entry->op = silc_ske_initiator(ske, sconn->sock, ¶ms, NULL); } /* Timeout callback that will be called to retry connecting to remote @@ -1808,7 +1859,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_retry) /* If we've reached max retry count, give up. */ if ((sconn->retry_count > param->reconnect_count) && - !param->reconnect_keep_trying) { + sconn->no_reconnect) { SILC_LOG_ERROR(("Could not connect, giving up")); if (sconn->callback) @@ -1842,7 +1893,7 @@ static void silc_server_connection_established(SilcNetStatus status, switch (status) { case SILC_NET_OK: - SILC_LOG_DEBUG(("Connection to %s:%d established", + SILC_LOG_DEBUG(("Connection %p to %s:%d established", sconn, sconn->remote_host, sconn->remote_port)); /* Continue with key exchange protocol */ @@ -1855,10 +1906,16 @@ static void silc_server_connection_established(SilcNetStatus status, SILC_LOG_ERROR(("Could not connect to %s:%d: %s", sconn->remote_host, sconn->remote_port, silc_net_get_error_string(status))); - - if (sconn->callback) - (*sconn->callback)(server, NULL, sconn->callback_context); - silc_server_connection_free(sconn); + if (!sconn->no_reconnect) { + silc_schedule_task_add_timeout(sconn->server->schedule, + silc_server_connect_to_router_retry, + sconn, 1, 0); + silc_dlist_del(server->conns, sconn); + } else { + if (sconn->callback) + (*sconn->callback)(server, NULL, sconn->callback_context); + silc_server_connection_free(sconn); + } break; default: @@ -1869,6 +1926,7 @@ static void silc_server_connection_established(SilcNetStatus status, silc_schedule_task_add_timeout(sconn->server->schedule, silc_server_connect_to_router_retry, sconn, 1, 0); + silc_dlist_del(server->conns, sconn); } else { if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); @@ -1908,6 +1966,8 @@ SILC_TASK_CALLBACK(silc_server_connect_router) SILC_LOG_INFO(("Unconfigured %s connection %s:%d, cannot connect", (sconn->backup ? "backup router" : "router"), sconn->remote_host, sconn->remote_port)); + if (sconn->callback) + (*sconn->callback)(server, NULL, sconn->callback_context); silc_server_connection_free(sconn); return; } @@ -1924,6 +1984,8 @@ SILC_TASK_CALLBACK(silc_server_connect_router) if (!sconn->op) { SILC_LOG_ERROR(("Could not connect to router %s:%d", sconn->remote_host, sconn->remote_port)); + if (sconn->callback) + (*sconn->callback)(server, NULL, sconn->callback_context); silc_server_connection_free(sconn); return; } @@ -1942,6 +2004,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) SilcServer server = context; SilcServerConnection sconn; SilcServerConfigRouter *ptr; + SilcServerConfigConnParams *param; /* Don't connect if we are shutting down. */ if (server->server_shutdown) @@ -1952,7 +2015,6 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) "normal server" : server->server_type == SILC_ROUTER ? "router" : "backup router/normal server"))); - /* XXX */ if (!server->config->routers) { /* There wasn't a configured router, we will continue but we don't have a connection to outside world. We will be standalone server. */ @@ -1961,6 +2023,12 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) return; } + /* Cancel any possible retry timeouts */ + silc_schedule_task_del_by_callback(server->schedule, + silc_server_connect_router); + silc_schedule_task_del_by_callback(server->schedule, + silc_server_connect_to_router_retry); + /* Create the connections to all our routes */ for (ptr = server->config->routers; ptr; ptr = ptr->next) { @@ -1984,7 +2052,8 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) silc_net_is_ip(ptr->host) ? ptr->host : NULL, silc_net_is_ip(ptr->host) ? - NULL : ptr->host, ptr->port)) { + NULL : ptr->host, ptr->port, + SILC_CONN_ROUTER)) { SILC_LOG_DEBUG(("We are already connected to %s:%d", ptr->host, ptr->port)); @@ -2002,11 +2071,8 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) if (!sock) continue; server->backup_noswitch = TRUE; -#if 0 - if (sock->user_data) - silc_server_free_sock_user_data(server, sock, NULL); + silc_server_free_sock_user_data(server, sock, NULL); silc_server_disconnect_remote(server, sock, 0, NULL); -#endif /* 0 */ server->backup_noswitch = FALSE; SILC_LOG_DEBUG(("Reconnecting to primary router")); } else { @@ -2014,10 +2080,13 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) } } + param = (ptr->param ? ptr->param : &server->config->param); + /* Allocate connection object for hold connection specific stuff. */ sconn = silc_calloc(1, sizeof(*sconn)); if (!sconn) continue; + sconn->server = server; sconn->remote_host = strdup(ptr->host); sconn->remote_port = ptr->port; sconn->backup = ptr->backup_router; @@ -2025,10 +2094,10 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) sconn->backup_replace_ip = strdup(ptr->backup_replace_ip); sconn->backup_replace_port = ptr->backup_replace_port; } + sconn->no_reconnect = param->reconnect_keep_trying == FALSE; SILC_LOG_DEBUG(("Created connection %p", sconn)); - /* XXX */ if (!server->router_conn && !sconn->backup) server->router_conn = sconn; @@ -2078,13 +2147,28 @@ silc_server_accept_get_auth(SilcConnAuth connauth, if (cconfig->publickeys) *repository = server->repository; - entry->data.conn_type = conn_type; + if (cconfig->publickeys) { + if (server->config->prefer_passphrase_auth) { + *repository = NULL; + } else { + *passphrase = NULL; + *passphrase_len = 0; + } + } + + entry->conn_type = conn_type; return TRUE; } /* Remote end is server */ if (conn_type == SILC_CONN_SERVER) { - SilcServerConfigServer *sconfig = entry->sconfig.ref_ptr; + SilcServerConfigServer *sconfig; + + /* If we are normal server, don't accept the connection */ + if (server->server_type == SILC_SERVER) + return FALSE; + + sconfig = entry->sconfig.ref_ptr; if (!sconfig) return FALSE; @@ -2093,7 +2177,16 @@ silc_server_accept_get_auth(SilcConnAuth connauth, if (sconfig->publickeys) *repository = server->repository; - entry->data.conn_type = conn_type; + if (sconfig->publickeys) { + if (server->config->prefer_passphrase_auth) { + *repository = NULL; + } else { + *passphrase = NULL; + *passphrase_len = 0; + } + } + + entry->conn_type = conn_type; return TRUE; } @@ -2108,7 +2201,16 @@ silc_server_accept_get_auth(SilcConnAuth connauth, if (rconfig->publickeys) *repository = server->repository; - entry->data.conn_type = conn_type; + if (rconfig->publickeys) { + if (server->config->prefer_passphrase_auth) { + *repository = NULL; + } else { + *passphrase = NULL; + *passphrase_len = 0; + } + } + + entry->conn_type = conn_type; return TRUE; } @@ -2128,12 +2230,12 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, SilcServerConfigConnParams *param = &server->config->param; SilcServerConnection sconn; void *id_entry; - const char *hostname; + const char *hostname, *ip; SilcUInt16 port; entry->op = NULL; silc_socket_stream_get_info(silc_packet_stream_get_stream(sock), - NULL, &hostname, NULL, &port); + NULL, &hostname, &ip, &port); if (success == FALSE) { /* Authentication failed */ @@ -2142,19 +2244,23 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, server->stat.auth_failures++; silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL); + silc_server_config_unref(&entry->cconfig); + silc_server_config_unref(&entry->sconfig); + silc_server_config_unref(&entry->rconfig); + silc_server_free_sock_user_data(server, sock, NULL); goto out; } SILC_LOG_DEBUG(("Checking whether connection is allowed")); - switch (entry->data.conn_type) { + switch (entry->conn_type) { case SILC_CONN_CLIENT: { SilcClientEntry client; SilcServerConfigClient *conn = entry->cconfig.ref_ptr; /* Verify whether this connection is after all allowed to connect */ - if (!silc_server_connection_allowed(server, sock, entry->data.conn_type, + if (!silc_server_connection_allowed(server, sock, entry->conn_type, &server->config->param, conn->param, silc_connauth_get_ske(connauth))) { @@ -2180,6 +2286,10 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_STATUS_ERR_PERM_DENIED, "We do not have connection to backup " "router established, try later"); + silc_server_config_unref(&entry->cconfig); + silc_server_config_unref(&entry->sconfig); + silc_server_config_unref(&entry->rconfig); + silc_server_free_sock_user_data(server, sock, NULL); server->stat.auth_failures++; /* From here on, wait 20 seconds for the backup router to appear. */ @@ -2204,9 +2314,14 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, server->stat.auth_failures++; silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_AUTH_FAILED, NULL); + silc_server_config_unref(&entry->cconfig); + silc_server_config_unref(&entry->sconfig); + silc_server_config_unref(&entry->rconfig); + silc_server_free_sock_user_data(server, sock, NULL); goto out; } entry->data.status |= SILC_IDLIST_STATUS_LOCAL; + entry->data.conn_type = SILC_CONN_CLIENT; /* Statistics */ server->stat.my_clients++; @@ -2234,6 +2349,7 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, } /* Add public key to repository */ + SILC_LOG_DEBUG(("Add client public key to repository")); if (!silc_server_get_public_key_by_client(server, client, NULL)) silc_skr_add_public_key_simple(server->repository, entry->data.public_key, @@ -2260,7 +2376,7 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, and we do not have connection to primary router, do not allow the connection. */ if (server->server_type == SILC_BACKUP_ROUTER && - entry->data.conn_type == SILC_CONN_SERVER && + entry->conn_type == SILC_CONN_SERVER && !SILC_PRIMARY_ROUTE(server)) { SILC_LOG_INFO(("Will not accept server connection because we do " "not have primary router connection established")); @@ -2268,17 +2384,24 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_STATUS_ERR_PERM_DENIED, "We do not have connection to primary " "router established, try later"); + silc_server_config_unref(&entry->cconfig); + silc_server_config_unref(&entry->sconfig); + silc_server_config_unref(&entry->rconfig); + silc_server_free_sock_user_data(server, sock, NULL); server->stat.auth_failures++; goto out; } - if (entry->data.conn_type == SILC_CONN_ROUTER) { + if (entry->conn_type == SILC_CONN_ROUTER) { /* Verify whether this connection is after all allowed to connect */ if (!silc_server_connection_allowed(server, sock, - entry->data.conn_type, + entry->conn_type, &server->config->param, rconn ? rconn->param : NULL, silc_connauth_get_ske(connauth))) { + silc_server_config_unref(&entry->cconfig); + silc_server_config_unref(&entry->sconfig); + silc_server_config_unref(&entry->rconfig); server->stat.auth_failures++; goto out; } @@ -2307,10 +2430,10 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, } } - if (entry->data.conn_type == SILC_CONN_SERVER) { + if (entry->conn_type == SILC_CONN_SERVER) { /* Verify whether this connection is after all allowed to connect */ if (!silc_server_connection_allowed(server, sock, - entry->data.conn_type, + entry->conn_type, &server->config->param, srvconn ? srvconn->param : NULL, silc_connauth_get_ske(connauth))) { @@ -2340,7 +2463,6 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, /* If we are primary router and we have backup router configured but it has not connected to use yet, do not accept any other connection. */ -#if 0 if (server->wait_backup && server->server_type == SILC_ROUTER && !server->backup_router && !backup_router) { SilcServerConfigRouter *router; @@ -2356,6 +2478,10 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_STATUS_ERR_PERM_DENIED, "We do not have connection to backup " "router established, try later"); + silc_server_config_unref(&entry->cconfig); + silc_server_config_unref(&entry->sconfig); + silc_server_config_unref(&entry->rconfig); + silc_server_free_sock_user_data(server, sock, NULL); server->stat.auth_failures++; /* From here on, wait 20 seconds for the backup router to appear. */ @@ -2365,14 +2491,13 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, goto out; } } -#endif /* 0 */ SILC_LOG_DEBUG(("Remote host is %s", - entry->data.conn_type == SILC_CONN_SERVER ? + entry->conn_type == SILC_CONN_SERVER ? "server" : (backup_router ? "backup router" : "router"))); SILC_LOG_INFO(("Connection %s (%s) is %s", entry->hostname, - entry->ip, entry->data.conn_type == SILC_CONN_SERVER ? + entry->ip, entry->conn_type == SILC_CONN_SERVER ? "server" : (backup_router ? "backup router" : "router"))); @@ -2381,15 +2506,15 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, server. We mark ourselves as router for this server if we really are router. */ new_server = - silc_idlist_add_server((entry->data.conn_type == SILC_CONN_SERVER ? + silc_idlist_add_server((entry->conn_type == SILC_CONN_SERVER ? server->local_list : (backup_router ? server->local_list : server->global_list)), NULL, - (entry->data.conn_type == SILC_CONN_SERVER ? + (entry->conn_type == SILC_CONN_SERVER ? SILC_SERVER : SILC_ROUTER), NULL, - (entry->data.conn_type == SILC_CONN_SERVER ? + (entry->conn_type == SILC_CONN_SERVER ? server->id_entry : (backup_router ? server->id_entry : NULL)), sock); @@ -2397,10 +2522,15 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_LOG_ERROR(("Could not add new server to cache")); silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_AUTH_FAILED, NULL); + silc_server_config_unref(&entry->cconfig); + silc_server_config_unref(&entry->sconfig); + silc_server_config_unref(&entry->rconfig); + silc_server_free_sock_user_data(server, sock, NULL); server->stat.auth_failures++; goto out; } entry->data.status |= SILC_IDLIST_STATUS_LOCAL; + entry->data.conn_type = entry->conn_type; id_entry = (void *)new_server; @@ -2426,9 +2556,11 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, if (entry->data.conn_type == SILC_CONN_SERVER) { server->stat.my_servers++; server->stat.servers++; + SILC_LOG_DEBUG(("my_servers %d", server->stat.my_servers)); } else { server->stat.my_routers++; server->stat.routers++; + SILC_LOG_DEBUG(("my_routers %d", server->stat.my_routers)); } /* Check whether this connection is to be our primary router connection @@ -2472,14 +2604,6 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, /* Connection has been fully established now. Everything is ok. */ SILC_LOG_DEBUG(("New connection %p authenticated", sconn)); -#if 0 - /* Perform keepalive. */ - if (param->keepalive_secs) - silc_socket_set_heartbeat(sock, param->keepalive_secs, server, - silc_server_perform_heartbeat, - server->schedule); -#endif - /* Perform Quality of Service */ if (param->qos) silc_socket_stream_set_qos(silc_packet_stream_get_stream(sock), @@ -2525,6 +2649,10 @@ silc_server_accept_completed(SilcSKE ske, SilcSKEStatus status, silc_ske_free(ske); silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL); + silc_server_config_unref(&entry->cconfig); + silc_server_config_unref(&entry->sconfig); + silc_server_config_unref(&entry->rconfig); + silc_server_free_sock_user_data(server, sock, NULL); return; } @@ -2537,6 +2665,7 @@ silc_server_accept_completed(SilcSKE ske, SilcSKEStatus status, silc_ske_free(ske); silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL); + silc_server_free_sock_user_data(server, sock, NULL); return; } silc_packet_set_keys(sock, send_key, receive_key, hmac_send, @@ -2547,6 +2676,8 @@ silc_server_accept_completed(SilcSKE ske, SilcSKEStatus status, pk = silc_pkcs_public_key_encode(idata->public_key, &pk_len); silc_hash_make(server->sha1hash, pk, pk_len, idata->fingerprint); + silc_hash_alloc(silc_hash_get_name(prop->hash), &idata->hash); + SILC_LOG_DEBUG(("Starting connection authentication")); server->stat.auth_attempts++; @@ -2557,6 +2688,10 @@ silc_server_accept_completed(SilcSKE ske, SilcSKEStatus status, silc_ske_free(ske); silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); + silc_server_config_unref(&entry->cconfig); + silc_server_config_unref(&entry->sconfig); + silc_server_config_unref(&entry->rconfig); + silc_server_free_sock_user_data(server, sock, NULL); return; } @@ -2616,6 +2751,8 @@ static void silc_server_accept_new_connection(SilcNetStatus status, } server->stat.conn_num++; + SILC_LOG_DEBUG(("Created packet stream %p", packet_stream)); + /* Set source ID to packet stream */ if (!silc_packet_set_ids(packet_stream, SILC_ID_SERVER, server->id, 0, NULL)) { @@ -2635,6 +2772,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status, silc_server_disconnect_remote(server, packet_stream, SILC_STATUS_ERR_BANNED_FROM_SERVER, deny->reason); + silc_server_free_sock_user_data(server, packet_stream, NULL); return; } @@ -2653,6 +2791,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status, server->stat.conn_failures++; silc_server_disconnect_remote(server, packet_stream, SILC_STATUS_ERR_BANNED_FROM_SERVER, NULL); + silc_server_free_sock_user_data(server, packet_stream, NULL); return; } @@ -2662,6 +2801,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status, server->stat.conn_failures++; silc_server_disconnect_remote(server, packet_stream, SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); + silc_server_free_sock_user_data(server, packet_stream, NULL); return; } entry->hostname = hostname; @@ -2671,6 +2811,8 @@ static void silc_server_accept_new_connection(SilcNetStatus status, entry->data.conn_type = SILC_CONN_UNKNOWN; silc_packet_set_context(packet_stream, entry); + SILC_LOG_DEBUG(("Created unknown connection %p", entry)); + silc_server_config_ref(&entry->cconfig, server->config, cconfig); silc_server_config_ref(&entry->sconfig, server->config, sconfig); silc_server_config_ref(&entry->rconfig, server->config, rconfig); @@ -2697,6 +2839,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status, server->stat.conn_failures++; silc_server_disconnect_remote(server, packet_stream, SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); + silc_server_free_sock_user_data(server, packet_stream, NULL); return; } silc_ske_set_callbacks(ske, silc_server_verify_key, @@ -2771,8 +2914,8 @@ SILC_TASK_CALLBACK(silc_server_do_rekey) SILC_CONNTYPE_STRING(idata->conn_type))); /* Allocate SKE */ - ske = silc_ske_alloc(server->rng, server->schedule, server->repository, - server->public_key, server->private_key, sock); + ske = silc_ske_alloc(server->rng, server->schedule, NULL, + server->public_key, NULL, sock); if (!ske) return; @@ -2819,13 +2962,13 @@ static void silc_server_rekey(SilcServer server, SilcPacketStream sock, SilcIDListData idata = silc_packet_get_context(sock); SilcSKE ske; - SILC_LOG_DEBUG(("Executing rekey protocol with %s:%d [%s]", + SILC_LOG_DEBUG(("Executing rekey protocol with %s:%d [%s], sock %p", idata->sconn->remote_host, idata->sconn->remote_port, - SILC_CONNTYPE_STRING(idata->conn_type))); + SILC_CONNTYPE_STRING(idata->conn_type), sock)); /* Allocate SKE */ - ske = silc_ske_alloc(server->rng, server->schedule, server->repository, - server->public_key, server->private_key, sock); + ske = silc_ske_alloc(server->rng, server->schedule, NULL, + server->public_key, NULL, sock); if (!ske) { silc_packet_free(packet); return; @@ -2846,7 +2989,7 @@ static void silc_server_rekey(SilcServer server, SilcPacketStream sock, SILC_TASK_CALLBACK(silc_server_close_connection_final) { - silc_packet_stream_destroy(context); + silc_packet_stream_unref(context); } /* Closes connection to socket connection */ @@ -2859,6 +3002,9 @@ void silc_server_close_connection(SilcServer server, const char *hostname; SilcUInt16 port; + if (!silc_packet_stream_is_valid(sock)) + return; + memset(tmp, 0, sizeof(tmp)); // silc_socket_get_error(sock, tmp, sizeof(tmp)); silc_socket_stream_get_info(silc_packet_stream_get_stream(sock), @@ -2874,6 +3020,11 @@ void silc_server_close_connection(SilcServer server, idata->sconn = NULL; } + /* Take a reference and then destroy the stream. The last reference + is released later in a timeout callback. */ + silc_packet_stream_ref(sock); + silc_packet_stream_destroy(sock); + /* Close connection with timeout */ server->stat.conn_num--; silc_schedule_task_del_by_all(server->schedule, 0, @@ -2897,7 +3048,7 @@ void silc_server_disconnect_remote(SilcServer server, if (!sock) return; - SILC_LOG_DEBUG(("Disconnecting remote host")); + SILC_LOG_DEBUG(("Disconnecting remote host, sock %p", sock)); va_start(ap, status); cp = va_arg(ap, char *); @@ -2965,6 +3116,11 @@ void silc_server_free_client_data(SilcServer server, SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR); silc_schedule_task_del_by_context(server->schedule, client); + if (client->data.sconn) { + silc_server_connection_free(client->data.sconn); + client->data.sconn = NULL; + } + /* We will not delete the client entry right away. We will take it into history (for WHOWAS command) for 5 minutes, unless we're shutting down server. */ @@ -2974,6 +3130,7 @@ void silc_server_free_client_data(SilcServer server, client->router = NULL; client->connection = NULL; client->data.created = silc_time(); + silc_dlist_del(server->expired_clients, client); silc_dlist_add(server->expired_clients, client); } else { /* Delete directly since we're shutting down server */ @@ -2991,14 +3148,21 @@ void silc_server_free_sock_user_data(SilcServer server, SilcPacketStream sock, const char *signoff_message) { - SilcIDListData idata = silc_packet_get_context(sock); + SilcIDListData idata; + const char *ip; + SilcUInt16 port; - SILC_LOG_DEBUG(("Start")); + if (!sock) + return; + SILC_LOG_DEBUG(("Start, sock %p", sock)); + + idata = silc_packet_get_context(sock); if (!idata) return; - silc_schedule_task_del_by_context(server->schedule, sock); + silc_schedule_task_del_by_all(server->schedule, 0, silc_server_do_rekey, + sock); /* Cancel active protocols */ if (idata) { @@ -3019,8 +3183,6 @@ void silc_server_free_sock_user_data(SilcServer server, SilcClientEntry client_entry = (SilcClientEntry)idata; silc_server_free_client_data(server, sock, client_entry, TRUE, signoff_message); - if (idata->sconn) - silc_server_connection_free(idata->sconn); silc_packet_set_context(sock, NULL); break; } @@ -3044,6 +3206,9 @@ void silc_server_free_sock_user_data(SilcServer server, if (server->server_shutdown || server->backup_noswitch) backup_router = NULL; + silc_socket_stream_get_info(silc_packet_stream_get_stream(sock), + NULL, NULL, &ip, &port); + /* If this was our primary router connection then we're lost to the outside world. */ if (server->router == user_data) { @@ -3080,17 +3245,15 @@ void silc_server_free_sock_user_data(SilcServer server, /* We stop here to take a breath */ sleep(2); -#if 0 if (server->backup_router) { server->server_type = SILC_ROUTER; /* We'll need to constantly try to reconnect to the primary router so that we'll see when it comes back online. */ - silc_server_backup_reconnect(server, sock->ip, sock->port, + silc_server_create_connection(server, TRUE, FALSE, ip, port, silc_server_backup_connected, NULL); } -#endif /* 0 */ /* Mark this connection as replaced */ silc_server_backup_replaced_add(server, user_data->id, @@ -3182,22 +3345,31 @@ void silc_server_free_sock_user_data(SilcServer server, } server->backup_noswitch = FALSE; - /* Free the server entry */ - silc_server_backup_del(server, user_data); - silc_server_backup_replaced_del(server, user_data); - silc_idlist_del_data(user_data); - if (!silc_idlist_del_server(server->local_list, user_data)) - silc_idlist_del_server(server->global_list, user_data); + if (idata->sconn) { + silc_server_connection_free(idata->sconn); + idata->sconn = NULL; + } + + /* Statistics */ if (idata->conn_type == SILC_CONN_SERVER) { server->stat.my_servers--; server->stat.servers--; - } else { + SILC_LOG_DEBUG(("my_servers %d", server->stat.my_servers)); + } else if (idata->conn_type == SILC_CONN_ROUTER) { server->stat.my_routers--; server->stat.routers--; + SILC_LOG_DEBUG(("my_routers %d", server->stat.my_routers)); } if (server->server_type == SILC_ROUTER) server->stat.cell_servers--; + /* Free the server entry */ + silc_server_backup_del(server, user_data); + silc_server_backup_replaced_del(server, user_data); + silc_idlist_del_data(user_data); + if (!silc_idlist_del_server(server->local_list, user_data)) + silc_idlist_del_server(server->global_list, user_data); + if (backup_router && backup_router != server->id_entry) { /* Announce all of our stuff that was created about 5 minutes ago. The backup router knows all the other stuff already. */ @@ -3212,8 +3384,6 @@ void silc_server_free_sock_user_data(SilcServer server, backup_router->connection); } - if (idata->sconn) - silc_server_connection_free(idata->sconn); silc_packet_set_context(sock, NULL); break; } @@ -3222,10 +3392,18 @@ void silc_server_free_sock_user_data(SilcServer server, { SilcUnknownEntry entry = (SilcUnknownEntry)idata; - SILC_LOG_DEBUG(("Freeing unknown connection data")); + SILC_LOG_DEBUG(("Freeing unknown connection data %p", entry)); + + if (idata->sconn) { + if (server->router_conn == idata->sconn) { + if (!server->no_reconnect) + silc_server_create_connections(server); + server->router_conn = NULL; + } - if (idata->sconn) silc_server_connection_free(idata->sconn); + idata->sconn = NULL; + } silc_idlist_del_data(idata); silc_free(entry); silc_packet_set_context(sock, NULL); @@ -3898,6 +4076,7 @@ static void silc_server_announce_get_servers(SilcServer server, SilcIDCacheEntry id_cache; SilcServerEntry entry; SilcBuffer idp; + void *tmp; /* Go through all clients in the list */ if (silc_idcache_get_all(id_list->servers, &list)) { @@ -3914,11 +4093,14 @@ static void silc_server_announce_get_servers(SilcServer server, idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER); - *servers = silc_buffer_realloc(*servers, - (*servers ? - silc_buffer_truelen((*servers)) + - silc_buffer_len(idp) : - silc_buffer_len(idp))); + tmp = silc_buffer_realloc(*servers, + (*servers ? + silc_buffer_truelen((*servers)) + + silc_buffer_len(idp) : + silc_buffer_len(idp))); + if (!tmp) + return; + *servers = tmp; silc_buffer_pull_tail(*servers, ((*servers)->end - (*servers)->data)); silc_buffer_put(*servers, idp->data, silc_buffer_len(idp)); silc_buffer_pull(*servers, silc_buffer_len(idp)); @@ -3992,6 +4174,7 @@ static void silc_server_announce_get_clients(SilcServer server, SilcBuffer idp; SilcBuffer tmp; unsigned char mode[4]; + void *tmp2; /* Go through all clients in the list */ if (silc_idcache_get_all(id_list->clients, &list)) { @@ -4006,13 +4189,21 @@ static void silc_server_announce_get_clients(SilcServer server, if (!client->connection && !client->router) continue; - idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT); + SILC_LOG_DEBUG(("Announce Client ID %s", + silc_id_render(client->id, SILC_ID_CLIENT))); - *clients = silc_buffer_realloc(*clients, - (*clients ? - silc_buffer_truelen((*clients)) + - silc_buffer_len(idp) : - silc_buffer_len(idp))); + idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT); + if (!idp) + return; + + tmp2 = silc_buffer_realloc(*clients, + (*clients ? + silc_buffer_truelen((*clients)) + + silc_buffer_len(idp) : + silc_buffer_len(idp))); + if (!tmp2) + return; + *clients = tmp2; silc_buffer_pull_tail(*clients, ((*clients)->end - (*clients)->data)); silc_buffer_put(*clients, idp->data, silc_buffer_len(idp)); silc_buffer_pull(*clients, silc_buffer_len(idp)); @@ -4022,11 +4213,14 @@ static void silc_server_announce_get_clients(SilcServer server, silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_UMODE_CHANGE, 2, idp->data, silc_buffer_len(idp), mode, 4); - *umodes = silc_buffer_realloc(*umodes, - (*umodes ? - silc_buffer_truelen((*umodes)) + - silc_buffer_len(tmp) : - silc_buffer_len(tmp))); + tmp2 = silc_buffer_realloc(*umodes, + (*umodes ? + silc_buffer_truelen((*umodes)) + + silc_buffer_len(tmp) : + silc_buffer_len(tmp))); + if (!tmp2) + return; + *umodes = tmp2; silc_buffer_pull_tail(*umodes, ((*umodes)->end - (*umodes)->data)); silc_buffer_put(*umodes, tmp->data, silc_buffer_len(tmp)); silc_buffer_pull(*umodes, silc_buffer_len(tmp)); @@ -4113,6 +4307,7 @@ void silc_server_announce_get_inviteban(SilcServer server, { SilcBuffer list, idp, idp2, tmp2; SilcUInt32 type; + void *ptype; SilcHashTableList htl; const unsigned char a[1] = { 0x03 }; @@ -4124,9 +4319,10 @@ void silc_server_announce_get_inviteban(SilcServer server, type = silc_hash_table_count(channel->invite_list); SILC_PUT16_MSB(type, list->data); silc_hash_table_list(channel->invite_list, &htl); - while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) - list = silc_argument_payload_encode_one(list, tmp2->data, silc_buffer_len(tmp2), - type); + while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) + list = silc_argument_payload_encode_one(list, tmp2->data, + silc_buffer_len(tmp2), + SILC_PTR_TO_32(ptype)); silc_hash_table_list_reset(&htl); idp2 = silc_id_payload_encode(server->id, SILC_ID_SERVER); @@ -4148,9 +4344,10 @@ void silc_server_announce_get_inviteban(SilcServer server, type = silc_hash_table_count(channel->ban_list); SILC_PUT16_MSB(type, list->data); silc_hash_table_list(channel->ban_list, &htl); - while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) - list = silc_argument_payload_encode_one(list, tmp2->data, silc_buffer_len(tmp2), - type); + while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) + list = silc_argument_payload_encode_one(list, tmp2->data, + silc_buffer_len(tmp2), + SILC_PTR_TO_32(ptype)); silc_hash_table_list_reset(&htl); *ban = @@ -4179,6 +4376,7 @@ void silc_server_announce_get_channel_users(SilcServer server, int len; unsigned char mode[4], ulimit[4]; char *hmac; + void *tmp2; SILC_LOG_DEBUG(("Start")); @@ -4215,10 +4413,13 @@ void silc_server_announce_get_channel_users(SilcServer server, SILC_CHANNEL_MODE_ULIMIT ? sizeof(ulimit) : 0)); len = silc_buffer_len(tmp); - *channel_modes = + tmp2 = silc_buffer_realloc(*channel_modes, (*channel_modes ? silc_buffer_truelen((*channel_modes)) + len : len)); + if (!tmp2) + return; + *channel_modes = tmp2; silc_buffer_pull_tail(*channel_modes, ((*channel_modes)->end - (*channel_modes)->data)); @@ -4233,6 +4434,9 @@ void silc_server_announce_get_channel_users(SilcServer server, while (silc_hash_table_get(&htl, NULL, (void *)&chl)) { clidp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT); + SILC_LOG_DEBUG(("JOIN Client %s", silc_id_render(chl->client->id, + SILC_ID_CLIENT))); + /* JOIN Notify */ tmp = silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_JOIN, 2, clidp->data, @@ -4240,10 +4444,13 @@ void silc_server_announce_get_channel_users(SilcServer server, chidp->data, silc_buffer_len(chidp)); len = silc_buffer_len(tmp); - *channel_users = + tmp2 = silc_buffer_realloc(*channel_users, (*channel_users ? silc_buffer_truelen((*channel_users)) + len : len)); + if (!tmp2) + return; + *channel_users = tmp2; silc_buffer_pull_tail(*channel_users, ((*channel_users)->end - (*channel_users)->data)); @@ -4265,11 +4472,14 @@ void silc_server_announce_get_channel_users(SilcServer server, fkey ? fkey->data : NULL, fkey ? silc_buffer_len(fkey) : 0); len = silc_buffer_len(tmp); - *channel_users_modes = + tmp2 = silc_buffer_realloc(*channel_users_modes, (*channel_users_modes ? silc_buffer_truelen((*channel_users_modes)) + len : len)); + if (!tmp2) + return; + *channel_users_modes = tmp2; silc_buffer_pull_tail(*channel_users_modes, ((*channel_users_modes)->end - (*channel_users_modes)->data)); @@ -4311,6 +4521,7 @@ void silc_server_announce_get_channels(SilcServer server, SilcUInt16 name_len; int len; int i = *channel_users_modes_c; + void *tmp; SilcBool announce; SILC_LOG_DEBUG(("Start")); @@ -4326,16 +4537,23 @@ void silc_server_announce_get_channels(SilcServer server, else announce = TRUE; + SILC_LOG_DEBUG(("Announce Channel ID %s", + silc_id_render(channel->id, SILC_ID_CHANNEL))); + silc_id_id2str(channel->id, SILC_ID_CHANNEL, cid, sizeof(cid), &id_len); name_len = strlen(channel->channel_name); if (announce) { len = 4 + name_len + id_len + 4; - *channels = + tmp = silc_buffer_realloc(*channels, (*channels ? silc_buffer_truelen((*channels)) + len : len)); + if (!tmp) + break; + *channels = tmp; + silc_buffer_pull_tail(*channels, ((*channels)->end - (*channels)->data)); silc_buffer_format(*channels, @@ -4356,15 +4574,23 @@ void silc_server_announce_get_channels(SilcServer server, if (announce) { /* Channel user modes */ - *channel_users_modes = silc_realloc(*channel_users_modes, - sizeof(**channel_users_modes) * - (i + 1)); + tmp = silc_realloc(*channel_users_modes, + sizeof(**channel_users_modes) * (i + 1)); + if (!tmp) + break; + *channel_users_modes = tmp; (*channel_users_modes)[i] = NULL; - *channel_modes = silc_realloc(*channel_modes, - sizeof(**channel_modes) * (i + 1)); + tmp = silc_realloc(*channel_modes, + sizeof(**channel_modes) * (i + 1)); + if (!tmp) + break; + *channel_modes = tmp; (*channel_modes)[i] = NULL; - *channel_ids = silc_realloc(*channel_ids, - sizeof(**channel_ids) * (i + 1)); + tmp = silc_realloc(*channel_ids, + sizeof(**channel_ids) * (i + 1)); + if (!tmp) + break; + *channel_ids = tmp; (*channel_ids)[i] = NULL; silc_server_announce_get_channel_users(server, channel, &(*channel_modes)[i], @@ -4373,18 +4599,27 @@ void silc_server_announce_get_channels(SilcServer server, (*channel_ids)[i] = channel->id; /* Channel's topic */ - *channel_topics = silc_realloc(*channel_topics, - sizeof(**channel_topics) * (i + 1)); + tmp = silc_realloc(*channel_topics, + sizeof(**channel_topics) * (i + 1)); + if (!tmp) + break; + *channel_topics = tmp; (*channel_topics)[i] = NULL; silc_server_announce_get_channel_topic(server, channel, &(*channel_topics)[i]); /* Channel's invite and ban list */ - *channel_invites = silc_realloc(*channel_invites, - sizeof(**channel_invites) * (i + 1)); + tmp = silc_realloc(*channel_invites, + sizeof(**channel_invites) * (i + 1)); + if (!tmp) + break; + *channel_invites = tmp; (*channel_invites)[i] = NULL; - *channel_bans = silc_realloc(*channel_bans, - sizeof(**channel_bans) * (i + 1)); + tmp = silc_realloc(*channel_bans, + sizeof(**channel_bans) * (i + 1)); + if (!tmp) + break; + *channel_bans = tmp; (*channel_bans)[i] = NULL; silc_server_announce_get_inviteban(server, channel, &(*channel_invites)[i], @@ -4630,10 +4865,10 @@ void silc_server_announce_watches(SilcServer server, /* Assembles user list and users mode list from the `channel'. */ SilcBool silc_server_get_users_on_channel(SilcServer server, - SilcChannelEntry channel, - SilcBuffer *user_list, - SilcBuffer *mode_list, - SilcUInt32 *user_count) + SilcChannelEntry channel, + SilcBuffer *user_list, + SilcBuffer *mode_list, + SilcUInt32 *user_count) { SilcChannelClientEntry chl; SilcHashTableList htl;