+ }
+
+ case SILC_CONN_SERVER:
+ case SILC_CONN_ROUTER:
+ {
+ SilcServerEntry new_server;
+ SilcBool initiator = FALSE;
+ SilcBool backup_local = FALSE;
+ SilcBool backup_router = FALSE;
+ char *backup_replace_ip = NULL;
+ SilcUInt16 backup_replace_port = 0;
+ SilcServerConfigServer *srvconn = entry->sconfig.ref_ptr;
+ SilcServerConfigRouter *rconn = entry->rconfig.ref_ptr;
+
+ /* If we are backup router and this is incoming server connection
+ and we do not have connection to primary router, do not allow
+ the connection. */
+ if (server->server_type == SILC_BACKUP_ROUTER &&
+ 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"));
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_PERM_DENIED,
+ "We do not have connection to primary "
+ "router established, try later");
+ silc_server_free_sock_user_data(server, sock, NULL);
+ server->stat.auth_failures++;
+ goto out;
+ }
+
+ 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->conn_type,
+ &server->config->param,
+ rconn ? rconn->param : NULL,
+ silc_connauth_get_ske(connauth))) {
+ server->stat.auth_failures++;
+ goto out;
+ }
+
+ if (rconn) {
+ if (rconn->param) {
+ param = rconn->param;
+
+ if (!param->keepalive_secs)
+ param->keepalive_secs = server->config->param.keepalive_secs;
+
+ if (!param->qos && server->config->param.qos) {
+ param->qos = server->config->param.qos;
+ param->qos_rate_limit = server->config->param.qos_rate_limit;
+ param->qos_bytes_limit = server->config->param.qos_bytes_limit;
+ param->qos_limit_sec = server->config->param.qos_limit_sec;
+ param->qos_limit_usec = server->config->param.qos_limit_usec;
+ }
+ }
+
+ initiator = rconn->initiator;
+ backup_local = rconn->backup_local;
+ backup_router = rconn->backup_router;
+ backup_replace_ip = rconn->backup_replace_ip;
+ backup_replace_port = rconn->backup_replace_port;
+ }
+ }
+
+ 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->conn_type,
+ &server->config->param,
+ srvconn ? srvconn->param : NULL,
+ silc_connauth_get_ske(connauth))) {
+ server->stat.auth_failures++;
+ goto out;
+ }
+ if (srvconn) {
+ if (srvconn->param) {
+ param = srvconn->param;
+
+ if (!param->keepalive_secs)
+ param->keepalive_secs = server->config->param.keepalive_secs;
+
+ if (!param->qos && server->config->param.qos) {
+ param->qos = server->config->param.qos;
+ param->qos_rate_limit = server->config->param.qos_rate_limit;
+ param->qos_bytes_limit = server->config->param.qos_bytes_limit;
+ param->qos_limit_sec = server->config->param.qos_limit_sec;
+ param->qos_limit_usec = server->config->param.qos_limit_usec;
+ }
+ }
+
+ backup_router = srvconn->backup_router;
+ }
+ }
+
+ /* 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 (server->wait_backup && server->server_type == SILC_ROUTER &&
+ !server->backup_router && !backup_router) {
+ SilcServerConfigRouter *router;
+ router = silc_server_config_get_backup_router(server);
+ if (router && strcmp(server->config->server_info->primary->server_ip,
+ ip) &&
+ silc_server_find_socket_by_host(server,
+ SILC_CONN_SERVER,
+ router->backup_replace_ip, 0)) {
+ SILC_LOG_INFO(("Will not accept connections because we do "
+ "not have backup router connection established"));
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_PERM_DENIED,
+ "We do not have connection to backup "
+ "router established, try later");
+ 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. */
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_backup_router_wait,
+ (void *)server, 20, 0);
+ goto out;
+ }
+ }
+
+ SILC_LOG_DEBUG(("Remote host is %s",
+ 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->conn_type == SILC_CONN_SERVER ?
+ "server" : (backup_router ?
+ "backup router" : "router")));
+
+ /* Add the server into server cache. The server name and Server ID
+ is updated after we have received NEW_SERVER packet from the
+ server. We mark ourselves as router for this server if we really
+ are router. */
+ new_server =
+ silc_idlist_add_server((entry->conn_type == SILC_CONN_SERVER ?
+ server->local_list : (backup_router ?
+ server->local_list :
+ server->global_list)),
+ NULL,
+ (entry->conn_type == SILC_CONN_SERVER ?
+ SILC_SERVER : SILC_ROUTER),
+ NULL,
+ (entry->conn_type == SILC_CONN_SERVER ?
+ server->id_entry : (backup_router ?
+ server->id_entry : NULL)),
+ sock);
+ if (!new_server) {
+ SILC_LOG_ERROR(("Could not add new server to cache"));
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_AUTH_FAILED, NULL);
+ 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;
+
+ /* If the incoming connection is router and marked as backup router
+ then add it to be one of our backups */
+ if (entry->data.conn_type == SILC_CONN_ROUTER && backup_router) {
+ /* Change it back to SERVER type since that's what it really is. */
+ if (backup_local)
+ entry->data.conn_type = SILC_CONN_SERVER;
+ new_server->server_type = SILC_BACKUP_ROUTER;
+
+ SILC_SERVER_SEND_OPERS(server, FALSE, TRUE, SILC_NOTIFY_TYPE_NONE,
+ ("Backup router %s is now online",
+ entry->hostname));
+
+ /* Remove the backup waiting with timeout */
+ silc_schedule_task_add_timeout(server->schedule,
+ silc_server_backup_router_wait,
+ (void *)server, 10, 0);
+ }
+
+ /* Statistics */
+ 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
+ if we do not already have the primary route. */
+ if (!backup_router &&
+ server->standalone && entry->data.conn_type == SILC_CONN_ROUTER) {
+ if (silc_server_config_is_primary_route(server) && !initiator)
+ break;
+
+ SILC_LOG_DEBUG(("We are not standalone server anymore"));
+ server->standalone = FALSE;
+ if (!server->id_entry->router) {
+ server->id_entry->router = id_entry;
+ server->router = id_entry;
+ }
+ }