From 901271466f6fc8f9f148c7bf2493b1813d891c16 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Sun, 23 Jun 2002 19:18:50 +0000 Subject: [PATCH] Added preliminary backup router support for standalone routers. --- CHANGES | 20 ++++ TODO | 15 ++- apps/silcd/packet_receive.c | 46 ++++++--- apps/silcd/server.c | 138 ++++++++++++++++++-------- apps/silcd/server_backup.c | 65 +++++++----- apps/silcd/server_util.c | 79 +++++++++++++-- apps/silcd/server_util.h | 7 +- doc/draft-riikonen-silc-spec-06.nroff | 6 +- lib/silcutil/silcutil.c | 2 +- 9 files changed, 279 insertions(+), 99 deletions(-) diff --git a/CHANGES b/CHANGES index b2f17924..837f2525 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,26 @@ Sun Jun 23 17:32:31 EEST 2002 Pekka Riikonen and on some it's not. Fallback encoding is used instead. Affected file lib/silcutil/silcstrutil.c. + * Fixed statistics updating for incoming server connection + which could cause problems when re-connecting. Affected + file silcd/server.c. + + * Preliminary backup router support for standalone router + added. Affected files in silcd/. + + * Mark server connections in backup router disabled before + and after backup protocol. Affected file is + silcd/server_backup.c. + + * Added support for reconnecting to remote server connection + even if the protocol fails, and if the configuration wants + us to keep trying to connect anyway. + + Server connection is not allowed to backup router if + backup router does not have connection to primary router yet. + + Affected file is silcd/server.c. + Sat Jun 22 21:34:59 EEST 2002 Pekka Riikonen * Added silc_client_udpate_server function to update changed diff --git a/TODO b/TODO index 6748473e..85336542 100644 --- a/TODO +++ b/TODO @@ -25,8 +25,19 @@ TODO/bugs In SILC Server o Backup router related issues (Fix this to 0.9.x): - o Channel user mode changes are notified unnecessarely when - switching to backup router on router crash. + o Complete backup router support with standalone router + + o Make the backup router work even if not all servers in the + cell use it. When primary goes down, also those that are + not using it (are not connected locally) are signoffed. + + o Configure use of backup router on normal server using HUP. + + o Configure use of backup router on router using HUP. + + o Rewrite SILC_LOG_DEBUG's in silcd/server_backup.c. + + o Testing o Add a timeout to handling incoming JOIN commands. It should be enforced that JOIN command is executed only once in a second or two diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index 95486d8f..a9f3f267 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -218,10 +218,17 @@ void silc_server_notify(SilcServer server, chl->client = client; chl->channel = channel; - /* If this is the first one on the channel then it is the founder of - the channel. */ - if (!silc_hash_table_count(channel->user_list)) - chl->mode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO); + if (server->server_type != SILC_ROUTER || + sock->type == SILC_SOCKET_TYPE_ROUTER) { + /* If this is the first one on the channel then it is the founder of + the channel. This is done on normal server and on router if this + notify is coming from router */ + if (!silc_hash_table_count(channel->user_list)) { + SILC_LOG_DEBUG(("Client %s is founder on channel", + silc_id_render(chl->client->id, SILC_ID_CLIENT))); + chl->mode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO); + } + } silc_hash_table_add(channel->user_list, client, chl); silc_hash_table_add(client->channels, channel, chl); @@ -915,17 +922,17 @@ void silc_server_notify(SilcServer server, is set on the channel now check whether this is the client that originally set the mode. */ - /* Get public key that must be present in notify */ - tmp = silc_argument_get_arg_type(args, 4, &tmp_len); - if (!tmp || !silc_pkcs_public_key_decode(tmp, tmp_len, - &founder_key)) { - chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO; - silc_server_force_cumode_change(server, sock, channel, chl, mode); - notify_sent = TRUE; - break; - } - if (channel->founder_key) { + /* Get public key that must be present in notify */ + tmp = silc_argument_get_arg_type(args, 4, &tmp_len); + if (!tmp || !silc_pkcs_public_key_decode(tmp, tmp_len, + &founder_key)) { + chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO; + silc_server_force_cumode_change(server, sock, channel, chl, mode); + notify_sent = TRUE; + break; + } + /* Now match the public key we have cached and public key sent. They must match. */ if (client && client->data.public_key && @@ -1287,9 +1294,14 @@ void silc_server_notify(SilcServer server, } silc_free(server_id); + /* Sending SERVER_SIGNOFF is not right way to signoff local connection */ + if (SILC_IS_LOCAL(server_entry)) + break; + /* Free all client entries that this server owns as they will become invalid now as well. */ silc_server_remove_clients_by_server(server, server_entry, TRUE); + silc_server_backup_del(server, server_entry); /* Remove the server entry */ silc_idlist_del_server(local ? server->local_list : @@ -2484,6 +2496,12 @@ SilcServerEntry silc_server_new_server(SilcServer server, silc_server_announce_clients(server, 0, sock); silc_server_announce_channels(server, 0, sock); } + + /* By default the servers connected to backup router are disabled + until backup router has become the primary */ + if (server->server_type == SILC_BACKUP_ROUTER && + sock->type == SILC_SOCKET_TYPE_SERVER) + idata->status |= SILC_IDLIST_STATUS_DISABLED; } return new_server; diff --git a/apps/silcd/server.c b/apps/silcd/server.c index b622ed87..fb135c4c 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -892,14 +892,23 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second) silc_ske_free(ctx->ske); silc_free(ctx->dest_id); silc_free(ctx); - silc_server_config_unref(&sconn->conn); - silc_free(sconn->remote_host); - silc_free(sconn->backup_replace_ip); - silc_free(sconn); silc_schedule_task_del_by_callback(server->schedule, silc_server_failure_callback); silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL); + + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add(server->schedule, 0, + silc_server_connect_to_router_retry, + sconn, 0, 1, SILC_TASK_TIMEOUT, + SILC_TASK_PRI_NORMAL); + return; + } + silc_server_config_unref(&sconn->conn); + silc_free(sconn->remote_host); + silc_free(sconn->backup_replace_ip); + silc_free(sconn); return; } @@ -923,14 +932,23 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second) silc_ske_free(ctx->ske); silc_free(ctx->dest_id); silc_free(ctx); - silc_server_config_unref(&sconn->conn); - silc_free(sconn->remote_host); - silc_free(sconn->backup_replace_ip); - silc_free(sconn); silc_schedule_task_del_by_callback(server->schedule, silc_server_failure_callback); silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL); + + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add(server->schedule, 0, + silc_server_connect_to_router_retry, + sconn, 0, 1, SILC_TASK_TIMEOUT, + SILC_TASK_PRI_NORMAL); + return; + } + silc_server_config_unref(&sconn->conn); + silc_free(sconn->remote_host); + silc_free(sconn->backup_replace_ip); + silc_free(sconn); return; } silc_ske_free_key_material(ctx->keymat); @@ -1049,6 +1067,16 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final) silc_free(ctx->dest_id); silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_AUTH_FAILED, NULL); + + /* Try reconnecting if configuration wants it */ + if (!sconn->no_reconnect) { + silc_schedule_task_add(server->schedule, 0, + silc_server_connect_to_router_retry, + sconn, 0, 1, SILC_TASK_TIMEOUT, + SILC_TASK_PRI_NORMAL); + goto out2; + } + goto out; } @@ -1156,12 +1184,10 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final) silc_server_announce_clients(server, 0, SILC_PRIMARY_ROUTE(server)); silc_server_announce_channels(server, 0, SILC_PRIMARY_ROUTE(server)); -#ifdef BACKUP_SINGLE_ROUTER /* 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, 0, TRUE); -#endif /* BACKUP_SINGLE_ROUTER */ } } else { /* Add this server to be our backup router */ @@ -1187,6 +1213,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final) if (sconn == server->router_conn) server->router_conn = NULL; + out2: /* Free the protocol object */ if (sock->protocol == protocol) sock->protocol = NULL; @@ -1601,12 +1628,30 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final) SilcServerConfigServer *sconn = ctx->sconfig.ref_ptr; SilcServerConfigRouter *rconn = ctx->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 && + ctx->conn_type == SILC_SOCKET_TYPE_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_free(sock->user_data); + server->stat.auth_failures++; + goto out; + } + if (ctx->conn_type == SILC_SOCKET_TYPE_ROUTER) { /* Verify whether this connection is after all allowed to connect */ if (!silc_server_connection_allowed(server, sock, ctx->conn_type, &server->config->param, rconn ? rconn->param : NULL, ctx->ske)) { + silc_free(sock->user_data); server->stat.auth_failures++; goto out; } @@ -1631,6 +1676,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final) &server->config->param, sconn ? sconn->param : NULL, ctx->ske)) { + silc_free(sock->user_data); server->stat.auth_failures++; goto out; } @@ -1680,15 +1726,6 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final) } entry->data.status |= SILC_IDLIST_STATUS_LOCAL; - /* Statistics */ - if (ctx->conn_type == SILC_SOCKET_TYPE_SERVER) { - server->stat.my_servers++; - } else { - server->stat.my_routers++; - server->stat.routers++; - } - server->stat.servers++; - id_entry = (void *)new_server; /* If the incoming connection is router and marked as backup router @@ -1704,6 +1741,15 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final) new_server->server_type = SILC_BACKUP_ROUTER; } + /* Statistics */ + if (ctx->conn_type == SILC_SOCKET_TYPE_SERVER) { + server->stat.my_servers++; + } else { + server->stat.my_routers++; + server->stat.routers++; + } + server->stat.servers++; + /* Check whether this connection is to be our primary router connection if we do not already have the primary route. */ if (!backup_router && @@ -2089,10 +2135,10 @@ void silc_server_packet_parse_type(SilcServer server, message = silc_memdup(packet->buffer->data + 1, packet->buffer->len - 1); - SILC_LOG_ERROR(("Disconnected by %s (%s): %s (%d) %s", - sock->ip, sock->hostname, - silc_get_status_message(status), status, - message ? message : "")); + SILC_LOG_INFO(("Disconnected by %s (%s): %s (%d) %s", + sock->ip, sock->hostname, + silc_get_status_message(status), status, + message ? message : "")); silc_free(message); } break; @@ -2515,7 +2561,7 @@ void silc_server_create_connection(SilcServer server, SILC_TASK_CALLBACK(silc_server_close_connection_final) { - silc_socket_free((SilcSocketConnection)context); + silc_socket_free(context); } /* Closes connection to socket connection */ @@ -2751,24 +2797,25 @@ void silc_server_free_sock_user_data(SilcServer server, server->standalone = TRUE; backup_router = NULL; } else { - SILC_LOG_INFO(("New primary router is backup router %s", - backup_router->server_name)); - SILC_LOG_DEBUG(("New primary router is backup router %s", - backup_router->server_name)); -#ifdef BACKUP_SINGLE_ROUTER + if (server->id_entry == backup_router) { + SILC_LOG_INFO(("We are now new router in this cell")); + SILC_LOG_DEBUG(("We are now new router in this cell")); + } else { + SILC_LOG_INFO(("New primary router is backup router %s", + backup_router->server_name)); + SILC_LOG_DEBUG(("New primary router is backup router %s", + backup_router->server_name)); + } if (server->id_entry != backup_router) { -#endif /* BACKUP_SINGLE_ROUTER */ server->id_entry->router = backup_router; server->router = backup_router; server->router_connect = time(0); server->backup_primary = TRUE; -#ifdef BACKUP_SINGLE_ROUTER } else { server->id_entry->router = NULL; server->router = NULL; server->standalone = TRUE; } -#endif /* BACKUP_SINGLE_ROUTER */ if (server->server_type == SILC_BACKUP_ROUTER) { server->server_type = SILC_ROUTER; @@ -2796,19 +2843,25 @@ void silc_server_free_sock_user_data(SilcServer server, } if (!backup_router) { - /* Free all client entries that this server owns as they will - become invalid now as well. */ - if (user_data->id) + /* As router, remove clients and channels always. As normal server + remove only if it is our primary router. Other connections + may be backup routers and these normal server don't handle here. */ + if (server->server_type != SILC_SERVER || + server->standalone || sock == SILC_PRIMARY_ROUTE(server)) { + /* Free all client entries that this server owns as they will + become invalid now as well. */ silc_server_remove_clients_by_server(server, user_data, TRUE); - if (server->server_type == SILC_SERVER) - silc_server_remove_channels_by_server(server, user_data); + if (server->server_type == SILC_SERVER) + silc_server_remove_channels_by_server(server, user_data); + } } else { /* Update the client entries of this server to the new backup router. This also removes the clients that *really* was owned by the primary router and went down with the router. */ silc_server_update_clients_by_server(server, user_data, backup_router, TRUE, TRUE); - silc_server_update_servers_by_server(server, user_data, backup_router); + silc_server_update_servers_by_server(server, user_data, backup_router, + TRUE); if (server->server_type == SILC_SERVER) silc_server_update_channels_by_server(server, user_data, backup_router); @@ -2830,7 +2883,7 @@ void silc_server_free_sock_user_data(SilcServer server, if (server->server_type == SILC_ROUTER) server->stat.cell_servers--; - if (backup_router) { + 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. */ if (server->server_type == SILC_ROUTER) @@ -3652,9 +3705,10 @@ static void silc_server_announce_get_clients(SilcServer server, silc_buffer_pull(*clients, idp->len); SILC_PUT32_MSB(client->mode, mode); - tmp = silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_UMODE_CHANGE, - 2, idp->data, idp->len, - mode, 4); + tmp = + silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_UMODE_CHANGE, + 2, idp->data, idp->len, + mode, 4); *umodes = silc_buffer_realloc(*umodes, (*umodes ? (*umodes)->truelen + tmp->len : diff --git a/apps/silcd/server_backup.c b/apps/silcd/server_backup.c index 70322dd9..299f1eee 100644 --- a/apps/silcd/server_backup.c +++ b/apps/silcd/server_backup.c @@ -125,8 +125,6 @@ SilcServerEntry silc_server_backup_get(SilcServer server, return NULL; for (i = 0; i < server->backup->servers_count; i++) { - SILC_LOG_HEXDUMP(("IP"), server_id->ip.data, 16); - SILC_LOG_HEXDUMP(("IP"), server->backup->servers[i].ip.data, 16); if (server->backup->servers[i].server && !memcmp(&server->backup->servers[i].ip, &server_id->ip.data, sizeof(server_id->ip.data))) @@ -137,19 +135,22 @@ SilcServerEntry silc_server_backup_get(SilcServer server, } /* Deletes the backup server `server_entry'. */ + void silc_server_backup_del(SilcServer server, SilcServerEntry server_entry) { int i; - SILC_LOG_DEBUG(("Start")); - if (!server->backup) return ; for (i = 0; i < server->backup->servers_count; i++) { if (server->backup->servers[i].server == server_entry) { + SILC_LOG_DEBUG(("Removing %s as backup router", + server_entry->server_name ? server_entry->server_name : + "")); server->backup->servers[i].server = NULL; - return; + memset(server->backup->servers[i].ip.data, 0, + sizeof(server->backup->servers[i].ip.data)); } } } @@ -288,6 +289,8 @@ void silc_server_backup_broadcast(SilcServer server, if (!backup || backup->connection == sender || server->backup->servers[i].local == FALSE) continue; + if (server->backup->servers[i].server == server->id_entry) + continue; idata = (SilcIDListData)backup; sock = backup->connection; @@ -334,8 +337,6 @@ void silc_server_backup_send(SilcServer server, if (!server->backup || server->server_type != SILC_ROUTER) return; - SILC_LOG_DEBUG(("Start")); - for (i = 0; i < server->backup->servers_count; i++) { backup = server->backup->servers[i].server; if (!backup) @@ -346,8 +347,14 @@ void silc_server_backup_send(SilcServer server, if (local && server->backup->servers[i].local == FALSE) continue; + if (server->backup->servers[i].server == server->id_entry) + continue; sock = backup->connection; + + SILC_LOG_DEBUG(("Sending %s packet to backup router %s (%s)", + silc_get_packet_name(type), sock->hostname, sock->ip)); + silc_server_packet_send(server, backup->connection, type, flags, data, data_len, force_send); } @@ -376,8 +383,6 @@ void silc_server_backup_send_dest(SilcServer server, if (!server->backup || server->server_type != SILC_ROUTER) return; - SILC_LOG_DEBUG(("Start")); - for (i = 0; i < server->backup->servers_count; i++) { backup = server->backup->servers[i].server; if (!backup) @@ -388,8 +393,14 @@ void silc_server_backup_send_dest(SilcServer server, if (local && server->backup->servers[i].local == FALSE) continue; + if (server->backup->servers[i].server == server->id_entry) + continue; sock = backup->connection; + + SILC_LOG_DEBUG(("Sending %s packet to backup router %s (%s)", + silc_get_packet_name(type), sock->hostname, sock->ip)); + silc_server_packet_send_dest(server, backup->connection, type, flags, dst_id, dst_id_type, data, data_len, force_send); @@ -478,7 +489,7 @@ void silc_server_backup_resume_router(SilcServer server, immediately after we've connected to our primary router. */ if (sock->type == SILC_SOCKET_TYPE_ROUTER && - server->router == sock->user_data && + sock && SILC_PRIMARY_ROUTE(server) == sock && type == SILC_SERVER_BACKUP_REPLACED) { /* We have been replaced by an backup router in our cell. We must mark our primary router connection disabled since we are not allowed @@ -990,7 +1001,7 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) /* Switch announced informations to our primary router of using the backup router. */ silc_server_update_servers_by_server(server, ctx->sock->user_data, - server->router); + server->router, TRUE); silc_server_update_clients_by_server(server, ctx->sock->user_data, server->router, TRUE, FALSE); if (server->server_type == SILC_SERVER) @@ -1089,7 +1100,6 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) case SILC_PROTOCOL_STATE_END: { - SilcIDListData idata; SilcServerEntry router, backup_router; /* We should have been received RESUMED packet from our primary @@ -1103,35 +1113,37 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) SILC_LOG_DEBUG(("********************************")); SILC_LOG_DEBUG(("Received RESUMED packet")); - /* We have now new primary router. All traffic goes there from now on. */ if (server->backup_router) server->server_type = SILC_BACKUP_ROUTER; + /* We have now new primary router. All traffic goes there from now on. */ router = (SilcServerEntry)ctx->sock->user_data; if (silc_server_backup_replaced_get(server, router->id, &backup_router)) { if (backup_router == server->router) { + /* We have new primary router now */ server->id_entry->router = router; server->router = router; + server->router->data.status &= ~SILC_IDLIST_STATUS_DISABLED; + SILC_LOG_INFO(("Switching back to primary router %s", server->router->server_name)); - SILC_LOG_DEBUG(("Switching back to primary router %s", - server->router->server_name)); - idata = (SilcIDListData)server->router; - idata->status &= ~SILC_IDLIST_STATUS_DISABLED; + + /* We cannot talk to backup router connection anymore, it's + enabled again if primary goes down. */ + backup_router->data.status |= SILC_IDLIST_STATUS_DISABLED; } else { - SILC_LOG_INFO(("Resuming the use of router %s", + /* We are connected to new primary and now continue using it */ + router->data.status &= ~SILC_IDLIST_STATUS_DISABLED; + SILC_LOG_INFO(("Resuming the use of primary router %s", router->server_name)); - SILC_LOG_DEBUG(("Resuming the use of router %s", - router->server_name)); - idata = (SilcIDListData)router; - idata->status &= ~SILC_IDLIST_STATUS_DISABLED; } /* Update the client entries of the backup router to the new router */ - silc_server_update_servers_by_server(server, backup_router, router); + silc_server_update_servers_by_server(server, backup_router, router, + FALSE); silc_server_update_clients_by_server(server, backup_router, router, TRUE, FALSE); if (server->server_type == SILC_SERVER) @@ -1190,7 +1202,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done) SilcIDCacheList list; SilcIDCacheEntry id_cache; - SILC_LOG_DEBUG(("Start")); + SILC_LOG_DEBUG(("Backup resuming protocol is ended")); if (protocol->state == SILC_PROTOCOL_STATE_ERROR || protocol->state == SILC_PROTOCOL_STATE_FAILURE) { @@ -1207,6 +1219,9 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done) if (sock->protocol == protocol) { sock->protocol = NULL; + SILC_LOG_DEBUG(("***************1 %s:%d", + sock->ip, sock->port)); + if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED) server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED; } @@ -1227,6 +1242,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done) if (sock->protocol == protocol) { sock->protocol = NULL; + SILC_LOG_DEBUG(("***************2")); + if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED) server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED; } diff --git a/apps/silcd/server_util.c b/apps/silcd/server_util.c index 6e3056c7..a09a9d90 100644 --- a/apps/silcd/server_util.c +++ b/apps/silcd/server_util.c @@ -287,6 +287,9 @@ bool silc_server_remove_clients_by_server(SilcServer server, if (server_signoff) { SilcBuffer args, not; + SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %d clients", + argc - 1)); + /* Send SERVER_SIGNOFF notify to our primary router */ if (server->router != entry) { args = silc_argument_payload_encode(1, argv, argv_lens, @@ -474,18 +477,23 @@ void silc_server_update_clients_by_server(SilcServer server, SILC_LOG_DEBUG(("Start")); - SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id, - SILC_ID_SERVER))); - SILC_LOG_DEBUG(("to %s", silc_id_render(to->id, - SILC_ID_SERVER))); - + if (from) + SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id, + SILC_ID_SERVER))); + if (to) + SILC_LOG_DEBUG(("to %s", silc_id_render(to->id, + SILC_ID_SERVER))); local = FALSE; if (silc_idcache_get_all(server->global_list->clients, &list)) { if (silc_idcache_list_first(list, &id_cache)) { while (id_cache) { client = (SilcClientEntry)id_cache->context; - if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) { + + /* If entry is disabled skip it. If entry is local to us, do not + switch it to anyone else, it is ours so skip it. */ + if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) || + SILC_IS_LOCAL(client)) { if (!silc_idcache_list_next(list, &id_cache)) break; else @@ -532,7 +540,11 @@ void silc_server_update_clients_by_server(SilcServer server, if (silc_idcache_list_first(list, &id_cache)) { while (id_cache) { client = (SilcClientEntry)id_cache->context; - if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) { + + /* If entry is disabled skip it. If entry is local to us, do not + switch it to anyone else, it is ours so skip it. */ + if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) || + SILC_IS_LOCAL(client)) { if (!silc_idcache_list_next(list, &id_cache)) break; else @@ -582,26 +594,48 @@ void silc_server_update_clients_by_server(SilcServer server, } /* Updates servers that are from `from' to be originated from `to'. This - will also update the server's connection to `to's connection. */ + will also update the server's connection to `to's connection. If + `local_toggle_enabled' is TRUE then local server's connections are + enabled, if FALSE they are disabled. */ void silc_server_update_servers_by_server(SilcServer server, SilcServerEntry from, - SilcServerEntry to) + SilcServerEntry to, + bool local_toggle_enabled) { SilcIDCacheList list = NULL; SilcIDCacheEntry id_cache = NULL; SilcServerEntry server_entry = NULL; - SILC_LOG_DEBUG(("Start")); - if (silc_idcache_get_all(server->local_list->servers, &list)) { if (silc_idcache_list_first(list, &id_cache)) { while (id_cache) { server_entry = (SilcServerEntry)id_cache->context; + + if (SILC_IS_LOCAL(server_entry)) { + if (server_entry != server->id_entry) { + if (local_toggle_enabled) + server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED; + else + server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED; + } + + /* If entry is local to us, do not switch it to any oneelse, + it is ours. */ + if (!silc_idcache_list_next(list, &id_cache)) + break; + else + continue; + } + if (server_entry->router == from) { + SILC_LOG_DEBUG(("Updating server (local) %s", + server_entry->server_name ? + server_entry->server_name : "")); server_entry->router = to; server_entry->connection = to->connection; } + if (!silc_idcache_list_next(list, &id_cache)) break; } @@ -613,10 +647,31 @@ void silc_server_update_servers_by_server(SilcServer server, if (silc_idcache_list_first(list, &id_cache)) { while (id_cache) { server_entry = (SilcServerEntry)id_cache->context; + + if (SILC_IS_LOCAL(server_entry)) { + if (server_entry != server->id_entry) { + if (local_toggle_enabled) + server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED; + else + server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED; + } + + /* If entry is local to us, do not switch it to anyone else, + it is ours. */ + if (!silc_idcache_list_next(list, &id_cache)) + break; + else + continue; + } + if (server_entry->router == from) { + SILC_LOG_DEBUG(("Updating server (global) %s", + server_entry->server_name ? + server_entry->server_name : "")); server_entry->router = to; server_entry->connection = to->connection; } + if (!silc_idcache_list_next(list, &id_cache)) break; } @@ -948,6 +1003,8 @@ bool silc_server_connection_allowed(SilcServer server, SilcUInt32 r_software_version, l_software_version; char *r_vendor_version = NULL, *l_vendor_version; + SILC_LOG_DEBUG(("Checking whether connection is allowed")); + /* Check version */ l_protocol_version = diff --git a/apps/silcd/server_util.h b/apps/silcd/server_util.h index 84ef0783..6f67e25c 100644 --- a/apps/silcd/server_util.h +++ b/apps/silcd/server_util.h @@ -45,10 +45,13 @@ void silc_server_update_clients_by_server(SilcServer server, bool remove_from); /* Updates servers that are from `from' to be originated from `to'. This - will also update the server's connection to `to's connection. */ + will also update the server's connection to `to's connection. If + `local_toggle_enabled' is TRUE then local server's connections are + enabled, if FALSE they are disabled. */ void silc_server_update_servers_by_server(SilcServer server, SilcServerEntry from, - SilcServerEntry to); + SilcServerEntry to, + bool local_toggle_enabled); /* Removes channels that are from `from. */ void silc_server_remove_channels_by_server(SilcServer server, diff --git a/doc/draft-riikonen-silc-spec-06.nroff b/doc/draft-riikonen-silc-spec-06.nroff index 45cd9476..ec1bb6cb 100644 --- a/doc/draft-riikonen-silc-spec-06.nroff +++ b/doc/draft-riikonen-silc-spec-06.nroff @@ -1630,14 +1630,14 @@ resuming protocol is executed. The protocol is advanced as follows: 5. Backup router MUST wait for all packets with type value 3 before it continues with the protocol. It knows from the session ID values set in the packet when it have received all packets. The session - value should be different in all packets it have send earlier. + value should be different in all packets it have sent earlier. After the packets is received the backup router sends the SILC_PACKET_RESUME_ROUTER packet with type value 4 to the primary router that came back online. This packet will indicate that the backup router is now ready to resign as being primary router. The session ID value in this packet MUST be the same as in first packet sent to the primary router. During this time - the backup router should still route all packets it is receiving + the backup router must still route all packets it is receiving from server connections. 6. The primary router receives the packet and send the @@ -1683,7 +1683,7 @@ packet: 3 SILC_SERVER_BACKUP_START_CONNECTED 4 SILC_SERVER_BACKUP_START_ENDING 5 SILC_SERVER_BACKUP_START_RESUMED - 6 SILC_SERVER_BACKUP_START_GLOBAL + 6 SILC_SERVER_BACKUP_START_RESUMED_GLOBAL 20 SILC_SERVER_BACKUP_START_REPLACED If any other value is found in the type field the packet must be diff --git a/lib/silcutil/silcutil.c b/lib/silcutil/silcutil.c index bcfa80de..57931f7e 100644 --- a/lib/silcutil/silcutil.c +++ b/lib/silcutil/silcutil.c @@ -995,7 +995,7 @@ static const SilcStatusMessage silc_status_messages[] = { { STAT(NOT_ENOUGH_PARAMS), "Not enough parameters" }, { STAT(TOO_MANY_PARAMS), "Too many parameters" }, { STAT(PERM_DENIED), "Permission denied" }, - { STAT(BANNED_FROM_SERVER),"You are banned from this server" }, + { STAT(BANNED_FROM_SERVER),"You are not allowed to connect" }, { STAT(BAD_PASSWORD), "Cannot join channel. Incorrect password" }, { STAT(CHANNEL_IS_FULL), "Cannot join channel. Channel is full" }, { STAT(NOT_INVITED), "Cannot join channel. You have not been invited" }, -- 2.24.0