X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=apps%2Fsilcd%2Fserver.c;h=f03581bcd081bbe9135d07e59bf6ba2f103be4a4;hp=73f363613f1a24ae59237900b29a411248142b12;hb=HEAD;hpb=80d86bcecbd9cc7a1b70423db4879acb4da134b9 diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 73f36361..f03581bc 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -201,6 +201,8 @@ static void silc_server_packet_eos(SilcPacketEngine engine, if (server->router_conn && server->router_conn->sock == stream && !server->router && server->standalone) { + if (idata->sconn && idata->sconn->callback) + (*idata->sconn->callback)(server, NULL, idata->sconn->callback_context); silc_server_create_connections(server); silc_server_free_sock_user_data(server, stream, NULL); } else { @@ -212,6 +214,8 @@ static void silc_server_packet_eos(SilcPacketEngine engine, server->backup_closed = TRUE; } + if (idata->sconn && idata->sconn->callback) + (*idata->sconn->callback)(server, NULL, idata->sconn->callback_context); silc_server_free_sock_user_data(server, stream, NULL); } @@ -239,6 +243,8 @@ SILC_TASK_CALLBACK(silc_server_packet_error_timeout) server->backup_closed = TRUE; } + if (idata->sconn && idata->sconn->callback) + (*idata->sconn->callback)(server, NULL, idata->sconn->callback_context); silc_server_free_sock_user_data(server, stream, NULL); } @@ -695,6 +701,10 @@ 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); @@ -929,7 +939,6 @@ SilcBool silc_server_init(SilcServer server) } else { server->stat.routers = 1; } - /* If we are normal server we'll retrieve network statisticial information once in a while from the router. */ if (server->server_type != SILC_ROUTER) @@ -1263,13 +1272,12 @@ 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 ? @@ -1325,7 +1333,8 @@ void silc_server_create_connection(SilcServer server, sconn->no_conf = dynamic; sconn->server = server; - SILC_LOG_DEBUG(("Created connection %p", sconn)); + SILC_LOG_DEBUG(("Created connection %p to %s:%d", sconn, + remote_host, port)); silc_schedule_task_add_timeout(server->schedule, silc_server_connect_router, sconn, 0, 0); @@ -1356,13 +1365,19 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, if (success == FALSE) { /* Authentication failed */ - /* 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; + } 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; } @@ -1384,11 +1399,11 @@ 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_free_sock_user_data(server, sconn->sock, NULL); - silc_server_disconnect_remote(server, sconn->sock, - SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); return; } @@ -1413,11 +1428,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_free_sock_user_data(server, sconn->sock, NULL); - silc_server_disconnect_remote(server, sconn->sock, - SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); return; } @@ -1451,11 +1466,18 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_ID_SERVER), NULL, sconn->sock); if (!id_entry) { + /* 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_RESOURCE_LIMIT, NULL); return; } @@ -1465,6 +1487,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, idata->status |= (SILC_IDLIST_STATUS_REGISTERED | SILC_IDLIST_STATUS_LOCAL); idata->sconn = sconn; + idata->sconn->callback = NULL; /* Statistics */ server->stat.my_routers++; @@ -1509,19 +1532,22 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, silc_server_backup_add(server, server->id_entry, ip, sconn->remote_port, TRUE); } + } #if 0 - } else { + 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); + 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_free_sock_user_data(server, sconn->sock, NULL); silc_server_disconnect_remote(server, sconn->sock, SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); return; -#endif /* 0 */ } +#endif /* 0 */ } else { /* Add this server to be our backup router */ id_entry->server_type = SILC_BACKUP_ROUTER; @@ -1532,11 +1558,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_free_sock_user_data(server, sconn->sock, NULL); - silc_server_disconnect_remote(server, sconn->sock, - SILC_STATUS_ERR_AUTH_FAILED, NULL); return; } @@ -1576,9 +1602,9 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status, { SilcPacketStream sock = context; SilcUnknownEntry entry = silc_packet_get_context(sock); - SilcServerConnection sconn = entry->data.sconn; - SilcServer server = entry->server; - SilcServerConfigRouter *conn = sconn->conn.ref_ptr; + SilcServerConnection sconn; + SilcServer server; + SilcServerConfigRouter *conn; SilcAuthMethod auth_meth = SILC_AUTH_NONE; void *auth_data = NULL; SilcUInt32 auth_data_len = 0; @@ -1587,22 +1613,31 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status, SilcHmac hmac_send, hmac_receive; SilcHash hash; - SILC_LOG_DEBUG(("Connection %p, SKE completed, entry %p", sconn, entry)); - + server = entry->server; + sconn = entry->data.sconn; + conn = sconn->conn.ref_ptr; entry->op = NULL; + SILC_LOG_DEBUG(("Connection %p, SKE completed, entry %p", sconn, entry)); + 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); + + /* 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_KEY_EXCHANGE_FAILED, NULL); return; } @@ -1611,16 +1646,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_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, @@ -1631,15 +1673,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_free_sock_user_data(server, sconn->sock, NULL); - silc_server_disconnect_remote(server, sconn->sock, - SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); return; } @@ -1691,6 +1741,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); @@ -1701,9 +1761,19 @@ void silc_server_start_key_exchange(SilcServerConnection sconn) /* Set source ID to packet stream */ 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_packet_stream_destroy(sconn->sock); silc_server_connection_free(sconn); return; } @@ -1712,6 +1782,18 @@ 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; } @@ -1734,9 +1816,19 @@ void silc_server_start_key_exchange(SilcServerConnection sconn) 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_packet_stream_destroy(sconn->sock); silc_server_connection_free(sconn); return; } @@ -1779,7 +1871,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) @@ -1826,10 +1918,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: @@ -1880,6 +1978,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; } @@ -1896,6 +1996,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; } @@ -1914,6 +2016,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) @@ -1989,6 +2092,8 @@ 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) @@ -2001,9 +2106,9 @@ 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)); - if (!server->router_conn && !sconn->backup) server->router_conn = sconn; @@ -2501,6 +2606,7 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, sconn->remote_port = port; silc_dlist_add(server->conns, sconn); idata->sconn = sconn; + idata->sconn->callback = NULL; idata->last_receive = time(NULL); /* Add the common data structure to the ID entry. */ @@ -2715,6 +2821,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status, entry->port = port; entry->server = server; entry->data.conn_type = SILC_CONN_UNKNOWN; + entry->data.status |= SILC_IDLIST_STATUS_LOCAL; silc_packet_set_context(packet_stream, entry); SILC_LOG_DEBUG(("Created unknown connection %p", entry)); @@ -2909,8 +3016,6 @@ void silc_server_close_connection(SilcServer server, 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), @@ -3036,6 +3141,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 */ @@ -3155,7 +3261,7 @@ void silc_server_free_sock_user_data(SilcServer server, /* We'll need to constantly try to reconnect to the primary router so that we'll see when it comes back online. */ - silc_server_create_connection(server, FALSE, FALSE, ip, port, + silc_server_create_connection(server, TRUE, FALSE, ip, port, silc_server_backup_connected, NULL); }