X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=apps%2Fsilcd%2Fpacket_receive.c;h=e49fafb59e7fb9a6d34595eff5748831a191b5a3;hp=2e96fa3e6d58c74b7eb1f4202fcba4554182b5c2;hb=382d15d447b7a95390decfa783836ae4fe255b3d;hpb=020c82f67da6042ac9ebded18f3b1a482c9b4995 diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index 2e96fa3e..e49fafb5 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -362,7 +362,8 @@ void silc_server_notify(SilcServer server, silc_schedule_task_del_by_context(server->schedule, client); /* Remove the client from all channels. */ - silc_server_remove_from_channels(server, NULL, client, TRUE, tmp, FALSE); + silc_server_remove_from_channels(server, NULL, client, TRUE, + tmp, FALSE, FALSE); /* Check if anyone is watching this nickname */ if (server->server_type == SILC_ROUTER) @@ -1067,46 +1068,34 @@ void silc_server_notify(SilcServer server, goto out; } - /* Get the added invite */ + /* Get the invite action */ tmp = silc_argument_get_arg_type(args, 4, &tmp_len); - if (tmp) { - if (!channel->invite_list) - channel->invite_list = silc_calloc(tmp_len + 2, - sizeof(*channel->invite_list)); - else - channel->invite_list = silc_realloc(channel->invite_list, - sizeof(*channel->invite_list) * - (tmp_len + - strlen(channel->invite_list) + - 2)); - if (tmp[tmp_len - 1] == ',') - tmp[tmp_len - 1] = '\0'; - - strncat(channel->invite_list, tmp, tmp_len); - strncat(channel->invite_list, ",", 1); - } + if (tmp && tmp_len == 1) { + SilcUInt8 action = (SilcUInt8)tmp[0]; + SilcUInt16 iargc = 0; + SilcArgumentPayload iargs; + + /* Get invite list */ + tmp = silc_argument_get_arg_type(args, 5, &tmp_len); + if (!tmp || tmp_len < 2) + goto out; - /* Get the deleted invite */ - tmp = silc_argument_get_arg_type(args, 5, &tmp_len); - if (tmp && channel->invite_list) { - char *start, *end, *n; - - if (!strncmp(channel->invite_list, tmp, - strlen(channel->invite_list) - 1)) { - silc_free(channel->invite_list); - channel->invite_list = NULL; - } else { - start = strstr(channel->invite_list, tmp); - if (start && strlen(start) >= tmp_len) { - end = start + tmp_len; - n = silc_calloc(strlen(channel->invite_list) - tmp_len, sizeof(*n)); - strncat(n, channel->invite_list, start - channel->invite_list); - strncat(n, end + 1, ((channel->invite_list + - strlen(channel->invite_list)) - end) - 1); - silc_free(channel->invite_list); - channel->invite_list = n; - } - } + /* Parse the arguments to see they are constructed correctly */ + SILC_GET16_MSB(iargc, tmp); + iargs = silc_argument_payload_parse(tmp + 2, tmp_len - 2, iargc); + if (!iargs) + goto out; + + if (action == 0 && !channel->invite_list) + channel->invite_list = + silc_hash_table_alloc(0, silc_hash_ptr, + NULL, NULL, NULL, + silc_server_inviteban_destruct, channel, TRUE); + + /* Proces the invite action */ + silc_server_inviteban_process(server, channel->invite_list, action, + iargs); + silc_argument_payload_free(iargs); } break; @@ -1293,7 +1282,7 @@ void silc_server_notify(SilcServer server, /* Remove the client from all channels. */ silc_server_remove_from_channels(server, NULL, client, - TRUE, NULL, FALSE); + TRUE, NULL, FALSE, FALSE); /* Check if anyone is watching this nickname */ if (server->server_type == SILC_ROUTER) @@ -1317,9 +1306,22 @@ 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)) + /* For local entrys SERVER_SIGNOFF is processed only on backup router. + It is possible that router sends server signoff for a server. If + backup router has it as local connection it will be closed. */ + if (SILC_IS_LOCAL(server_entry)) { + if (server->server_type == SILC_BACKUP_ROUTER) { + sock = server_entry->connection; + SILC_LOG_DEBUG(("Closing connection %s after SERVER_SIGNOFF", + sock->hostname)); + SILC_SET_DISCONNECTING(sock); + if (sock->user_data) + silc_server_free_sock_user_data(server, sock, NULL); + silc_server_close_connection(server, sock); + } + break; + } /* Remove all servers that are originated from this server, and remove the clients of those servers too. */ @@ -1396,41 +1398,53 @@ void silc_server_notify(SilcServer server, if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) goto out; - /* From protocol version 1.1 we get the kicker's ID as well. */ + /* Get the kicker's Client ID */ tmp = silc_argument_get_arg_type(args, 3, &tmp_len); - if (tmp) { - client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL); - if (!client_id) - goto out; + if (!tmp) + goto out; + client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL); + if (!client_id) + goto out; - /* If the the client is not in local list we check global list */ - client2 = silc_idlist_find_client_by_id(server->global_list, + /* If the the client is not in local list we check global list */ + client2 = silc_idlist_find_client_by_id(server->global_list, + client_id, TRUE, NULL); + if (!client2) { + client2 = silc_idlist_find_client_by_id(server->local_list, client_id, TRUE, NULL); if (!client2) { - client2 = silc_idlist_find_client_by_id(server->local_list, - client_id, TRUE, NULL); - if (!client2) { - silc_free(client_id); - goto out; - } - } - silc_free(client_id); - - /* Kicker must be operator on channel */ - if (!silc_server_client_on_channel(client2, channel, &chl)) - goto out; - if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) && - !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) { - SILC_LOG_DEBUG(("Kicking is not allowed")); + silc_free(client_id); goto out; } } + silc_free(client_id); + + /* Kicker must be operator on channel */ + if (!silc_server_client_on_channel(client2, channel, &chl)) + goto out; + if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) && + !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) { + SILC_LOG_DEBUG(("Kicking is not allowed")); + goto out; + } /* Send to channel */ silc_server_packet_send_to_channel(server, sock, channel, packet->type, FALSE, packet->buffer->data, packet->buffer->len, FALSE); + /* Remove the client from channel's invite list */ + if (channel->invite_list && silc_hash_table_count(channel->invite_list)) { + SilcBuffer ab; + SilcArgumentPayload iargs; + tmp = silc_argument_get_arg_type(args, 1, &tmp_len); + ab = silc_argument_payload_encode_one(NULL, tmp, tmp_len, 3); + iargs = silc_argument_payload_parse(ab->data, ab->len, 1); + silc_server_inviteban_process(server, channel->invite_list, 1, iargs); + silc_buffer_free(ab); + silc_argument_payload_free(iargs); + } + /* Remove the client from channel */ silc_server_remove_from_one_channel(server, sock, channel, client, FALSE); @@ -1481,34 +1495,34 @@ void silc_server_notify(SilcServer server, if (comment_len > 128) comment_len = 127; - /* From protocol version 1.1 we get the killer's ID as well. */ + /* Get the killer's Client ID */ tmp = silc_argument_get_arg_type(args, 3, &tmp_len); - if (tmp) { - client_id = silc_id_payload_parse_id(tmp, tmp_len, &id_type); - if (!client_id) - goto out; + if (!tmp) + goto out; + client_id = silc_id_payload_parse_id(tmp, tmp_len, &id_type); + if (!client_id) + goto out; - if (id_type == SILC_ID_CLIENT) { - /* If the the client is not in local list we check global list */ - client2 = silc_idlist_find_client_by_id(server->global_list, + if (id_type == SILC_ID_CLIENT) { + /* If the the client is not in local list we check global list */ + client2 = silc_idlist_find_client_by_id(server->global_list, + client_id, TRUE, NULL); + if (!client2) { + client2 = silc_idlist_find_client_by_id(server->local_list, client_id, TRUE, NULL); if (!client2) { - client2 = silc_idlist_find_client_by_id(server->local_list, - client_id, TRUE, NULL); - if (!client2) { - silc_free(client_id); - goto out; - } - } - silc_free(client_id); - - /* Killer must be router operator */ - if (server->server_type != SILC_SERVER && - !(client2->mode & SILC_UMODE_ROUTER_OPERATOR)) { - SILC_LOG_DEBUG(("Killing is not allowed")); + silc_free(client_id); goto out; } } + silc_free(client_id); + + /* Killer must be router operator */ + if (server->server_type != SILC_SERVER && + !(client2->mode & SILC_UMODE_ROUTER_OPERATOR)) { + SILC_LOG_DEBUG(("Killing is not allowed")); + goto out; + } } /* Send the notify to local clients on the channels except to the @@ -1520,7 +1534,7 @@ void silc_server_notify(SilcServer server, /* Remove the client from all channels */ silc_server_remove_from_channels(server, NULL, client, FALSE, NULL, - FALSE); + FALSE, TRUE); /* Check if anyone is watching this nickname */ silc_server_check_watcher_list(server, client, NULL, @@ -1642,41 +1656,34 @@ void silc_server_notify(SilcServer server, } silc_free(channel_id); - /* Get the new ban and add it to the ban list */ + /* Get the ban action */ tmp = silc_argument_get_arg_type(args, 2, &tmp_len); - if (tmp) { - if (!channel->ban_list) - channel->ban_list = silc_calloc(tmp_len + 2, - sizeof(*channel->ban_list)); - else - channel->ban_list = silc_realloc(channel->ban_list, - sizeof(*channel->ban_list) * - (tmp_len + - strlen(channel->ban_list) + 2)); - strncat(channel->ban_list, tmp, tmp_len); - strncat(channel->ban_list, ",", 1); - } + if (tmp && tmp_len == 1) { + SilcUInt8 action = (SilcUInt8)tmp[0]; + SilcUInt16 iargc = 0; + SilcArgumentPayload iargs; - /* Get the ban to be removed and remove it from the list */ - tmp = silc_argument_get_arg_type(args, 3, &tmp_len); - if (tmp && channel->ban_list) { - char *start, *end, *n; - - if (!strncmp(channel->ban_list, tmp, strlen(channel->ban_list) - 1)) { - silc_free(channel->ban_list); - channel->ban_list = NULL; - } else { - start = strstr(channel->ban_list, tmp); - if (start && strlen(start) >= tmp_len) { - end = start + tmp_len; - n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n)); - strncat(n, channel->ban_list, start - channel->ban_list); - strncat(n, end + 1, ((channel->ban_list + - strlen(channel->ban_list)) - end) - 1); - silc_free(channel->ban_list); - channel->ban_list = n; - } - } + /* Get ban list */ + tmp = silc_argument_get_arg_type(args, 3, &tmp_len); + if (!tmp || tmp_len < 2) + goto out; + + /* Parse the arguments to see they are constructed correctly */ + SILC_GET16_MSB(iargc, tmp); + iargs = silc_argument_payload_parse(tmp + 2, tmp_len - 2, iargc); + if (!iargs) + goto out; + + if (action == 0 && !channel->ban_list) + channel->ban_list = + silc_hash_table_alloc(0, silc_hash_ptr, + NULL, NULL, NULL, + silc_server_inviteban_destruct, channel, TRUE); + + /* Proces the ban action */ + silc_server_inviteban_process(server, channel->ban_list, action, + iargs); + silc_argument_payload_free(iargs); } break; @@ -1707,7 +1714,7 @@ void silc_server_notify(SilcServer server, client_id, FALSE, NULL); if (client) { silc_server_remove_from_channels(server, NULL, client, TRUE, - NULL, TRUE); + NULL, TRUE, FALSE); silc_idlist_del_data(client); silc_idlist_del_client(server->global_list, client); } @@ -2102,9 +2109,12 @@ void silc_server_channel_key(SilcServer server, /* Save the channel key */ channel = silc_server_save_channel_key(server, buffer, NULL); - if (!channel) + if (!channel) { + SILC_LOG_ERROR(("Bad channel key from %s (%s)", + sock->hostname, sock->ip)); return; - + } + /* Distribute the key to everybody who is on the channel. If we are router we will also send it to locally connected servers. */ silc_server_send_channel_key(server, sock, channel, FALSE); @@ -3667,7 +3677,8 @@ void silc_server_resume_client(SilcServer server, server->stat.clients--; if (server->stat.cell_clients) server->stat.cell_clients--; - silc_server_remove_from_channels(server, NULL, client, FALSE, NULL, FALSE); + silc_server_remove_from_channels(server, NULL, client, FALSE, + NULL, FALSE, FALSE); silc_server_del_from_watcher_list(server, client); if (!silc_idlist_del_client(server->local_list, client)) silc_idlist_del_client(server->global_list, client); @@ -3927,5 +3938,4 @@ void silc_server_resume_client(SilcServer server, } silc_free(client_id); - silc_idlist_del_data(detached_client); }