if (!client)
return;
- SILC_LOG_DEBUG(("Remove client from all channels"));
+ SILC_LOG_DEBUG(("Remove client %s from all channels",
+ client->nickname ? client->nickname :
+ (unsigned char *)""));
if (silc_hash_table_find(clients, client, NULL, NULL))
silc_hash_table_del(clients, client);
static SilcServerEntry
silc_server_update_clients_by_real_server(SilcServer server,
SilcServerEntry from,
+ SilcServerEntry to,
SilcClientEntry client,
bool local,
SilcIDCacheEntry client_cache)
SilcServerEntry server_entry;
SilcIDCacheEntry id_cache = NULL;
SilcIDCacheList list;
+ bool tolocal = (to == server->id_entry);
if (!silc_idcache_get_all(server->local_list->servers, &list))
return NULL;
while (id_cache) {
server_entry = (SilcServerEntry)id_cache->context;
if (server_entry != from &&
+ (tolocal || server_entry != server->id_entry) &&
SILC_ID_COMPARE(server_entry->id, client->id,
client->id->ip.data_len)) {
SILC_LOG_DEBUG(("Found (local) %s",
if (silc_idcache_list_first(list, &id_cache)) {
while (id_cache) {
server_entry = (SilcServerEntry)id_cache->context;
- if (server_entry != from &&
+ if (server_entry != from && server_entry != server->id_entry &&
+ (tolocal || server_entry != server->id_entry) &&
SILC_ID_COMPARE(server_entry->id, client->id,
client->id->ip.data_len)) {
SILC_LOG_DEBUG(("Found (global) %s",
if (client->router == from) {
if (resolve_real_server) {
client->router =
- silc_server_update_clients_by_real_server(server, from, client,
- local, id_cache);
+ silc_server_update_clients_by_real_server(server, from, to,
+ client, local,
+ id_cache);
if (!client->router) {
if (server->server_type == SILC_ROUTER)
client->router = from;
if (client->router)
SILC_LOG_DEBUG(("Client changed to %s",
- silc_id_render(client->router->id, SILC_ID_CLIENT)));
+ silc_id_render(client->router->id, SILC_ID_SERVER)));
if (!silc_idcache_list_next(list, &id_cache))
break;
if (client->router == from) {
if (resolve_real_server) {
client->router =
- silc_server_update_clients_by_real_server(server, from, client,
- local, id_cache);
+ silc_server_update_clients_by_real_server(server, from, to,
+ client, local,
+ id_cache);
if (!client->router)
client->router = from;
} else {
if (client->router)
SILC_LOG_DEBUG(("Client changed to %s",
- silc_id_render(client->router->id, SILC_ID_CLIENT)));
+ silc_id_render(client->router->id, SILC_ID_SERVER)));
if (!silc_idcache_list_next(list, &id_cache))
break;
silc_hash_table_list(channel->user_list, &htl);
while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
- if (!chl->client->router) {
+ if (SILC_IS_LOCAL(chl->client)) {
silc_hash_table_list_reset(&htl);
return TRUE;
}
SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
("Your connection is secured with %s cipher, "
"key length %d bits",
- idata->send_key->cipher->name,
- idata->send_key->cipher->key_len));
+ silc_cipher_get_name(idata->send_key),
+ silc_cipher_get_key_len(idata->send_key)));
SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
("Your current nickname is %s",
client->nickname));
/* Remove the client from all channels. This generates new keys to the
channels as well. */
silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
- NULL, TRUE);
+ NULL, TRUE, TRUE);
/* Remove the client entry, If it is locally connected then we will also
disconnect the client here */
SilcClientEntry entry = context;
SilcSocketConnection sock;
+ if (!context)
+ return;
+
if (entry == notify->client)
return;
return NULL;
}
+
+/* This function can be used to match the invite and ban lists. */
+
+bool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
+ SilcUInt8 type, void *check)
+{
+ unsigned char *tmp = NULL;
+ SilcUInt32 len = 0, t;
+ SilcHashTableList htl;
+ SilcBuffer entry, idp = NULL;
+ bool ret = FALSE;
+
+ if (type < 1 || type > 3 || !check)
+ return FALSE;
+
+ if (type == 1) {
+ tmp = strdup((char *)check);
+ if (!tmp)
+ return FALSE;
+ }
+ if (type == 2) {
+ tmp = silc_pkcs_public_key_encode(check, &len);
+ if (!tmp)
+ return FALSE;
+ }
+ if (type == 3) {
+ idp = silc_id_payload_encode(check, SILC_ID_CLIENT);
+ if (!idp)
+ return FALSE;
+ tmp = idp->data;
+ len = idp->len;
+ }
+
+ /* Compare the list */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&t, (void **)&entry)) {
+ if (type == t) {
+ if (type == 1) {
+ if (silc_string_match(entry->data, tmp)) {
+ ret = TRUE;
+ break;
+ }
+ } else if (!memcmp(entry->data, tmp, len)) {
+ ret = TRUE;
+ break;
+ }
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+
+ if (!idp)
+ silc_free(tmp);
+ silc_buffer_free(idp);
+ return ret;
+}
+
+/* Process invite or ban information */
+
+void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
+ SilcUInt8 action, SilcArgumentPayload args)
+{
+ unsigned char *tmp;
+ SilcUInt32 type, len;
+ SilcBuffer tmp2;
+ SilcHashTableList htl;
+
+ SILC_LOG_DEBUG(("Processing invite/ban for %s action",
+ action == 0x00 ? "ADD" : "DEL"));
+
+ /* Add the information to invite list */
+ if (action == 0x00) {
+ /* Traverse all arguments and add to the hash table according to
+ their type. */
+ tmp = silc_argument_get_first_arg(args, &type, &len);
+ while (tmp) {
+ if (type == 1) {
+ /* Invite string. Get the old invite string from hash table
+ and append this at the end of the existing one. */
+ if (!silc_hash_table_find(list, (void *)1, NULL, (void **)&tmp2)) {
+ tmp2 = silc_calloc(1, sizeof(*tmp2));
+ silc_hash_table_add(list, (void *)1, tmp2);
+ }
+ if (tmp[len - 1] == ',')
+ tmp[len - 1] = '\0';
+ if (len) {
+ silc_buffer_strformat(tmp2, tmp, SILC_STR_END);
+ silc_buffer_strformat(tmp2, ",", SILC_STR_END);
+ }
+
+ } else if (type == 2) {
+ /* Public key. Check first if the public key is already on the
+ list and ignore it if it is, otherwise, add it to hash table. */
+
+ /* Check if the public key is in the list already */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+ if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
+ tmp = NULL;
+ break;
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+
+ /* Add new public key to invite list */
+ if (tmp) {
+ tmp2 = silc_buffer_alloc_size(len);
+ silc_buffer_put(tmp2, tmp, len);
+ silc_hash_table_add(list, (void *)2, tmp2);
+ }
+
+ } else if (type == 3) {
+ /* Client ID */
+
+ /* Check if the ID is in the list already */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+ if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
+ tmp = NULL;
+ break;
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+
+ /* Add new Client ID to invite list */
+ if (tmp) {
+ tmp2 = silc_buffer_alloc_size(len);
+ silc_buffer_put(tmp2, tmp, len);
+ silc_hash_table_add(list, (void *)3, tmp2);
+ }
+ }
+
+ tmp = silc_argument_get_next_arg(args, &type, &len);
+ }
+ }
+
+ /* Delete information to invite list */
+ if (action == 0x01 && list) {
+ /* Now delete the arguments from invite list */
+ tmp = silc_argument_get_first_arg(args, &type, &len);
+ while (tmp) {
+ if (type == 1) {
+ /* Invite string. Get the old string from hash table and delete
+ the requested string. */
+ char *string = NULL, *start, *end, *n;
+
+ if (silc_hash_table_find(list, (void *)1, NULL, (void **)&tmp2)) {
+ string = tmp2->head;
+ if (tmp2->truelen && !strncmp(string, tmp, tmp2->truelen - 1)) {
+ /* Delete entire string */
+ silc_hash_table_del(list, (void *)1);
+ } else if (tmp2->truelen) {
+ /* Delete part of the string */
+ start = strstr(string, tmp);
+ if (start && strlen(start) >= len) {
+ end = start + len;
+ n = silc_calloc(strlen(string) - len, sizeof(*n));
+ strncat(n, string, start - string);
+ strncat(n, end + 1, ((string + strlen(string)) - end) - 1);
+ silc_free(tmp2->head);
+ silc_buffer_set(tmp2, n, strlen(n));
+ }
+ }
+ }
+
+ } else if (type == 2) {
+ /* Public key. */
+
+ /* Delete from the invite list */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+ if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
+ silc_hash_table_del_by_context(list, (void *)2, tmp2);
+ break;
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+
+ } else if (type == 3) {
+ /* Client ID */
+
+ /* Delete from the invite list */
+ silc_hash_table_list(list, &htl);
+ while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+ if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
+ silc_hash_table_del_by_context(list, (void *)3, tmp2);
+ break;
+ }
+ }
+ silc_hash_table_list_reset(&htl);
+ }
+
+ tmp = silc_argument_get_next_arg(args, &type, &len);
+ }
+ }
+}
+
+/* Destructor for invite and ban list entrys */
+
+void silc_server_inviteban_destruct(void *key, void *context,
+ void *user_context)
+{
+ silc_buffer_free(context);
+}
+
+/* Creates connections accoring to configuration. */
+
+void silc_server_create_connections(SilcServer server)
+{
+ silc_schedule_task_del_by_callback(server->schedule,
+ silc_server_connect_to_router);
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_connect_to_router, server, 0, 1,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+}