From 3e37906cf71ce93ee7faa4a6b9469abbd6811196 Mon Sep 17 00:00:00 2001 From: Emanuele Giaquinta Date: Tue, 4 Mar 2008 18:15:51 +0000 Subject: Remove long unmaintained botnet module. git-svn-id: http://svn.irssi.org/repos/irssi/trunk@4723 dbcabf3a-b0e7-0310-adc4-f8d773084564 --- docs/Makefile.am | 1 - docs/botnet.txt | 316 --------------- src/irc/bot/Makefile.am | 32 -- src/irc/bot/bot-events.c | 201 ---------- src/irc/bot/bot-irc-commands.c | 164 -------- src/irc/bot/bot-users.c | 579 ---------------------------- src/irc/bot/bot-users.h | 56 --- src/irc/bot/bot.c | 52 --- src/irc/bot/bot.h | 26 -- src/irc/bot/botnet-connection.c | 592 ---------------------------- src/irc/bot/botnet-users.c | 219 ----------- src/irc/bot/botnet-users.h | 13 - src/irc/bot/botnet.c | 827 ---------------------------------------- src/irc/bot/botnet.h | 134 ------- src/irc/bot/botnets.sample | 15 - src/irc/bot/module.h | 3 - src/irc/bot/users.sample | 18 - 17 files changed, 3248 deletions(-) delete mode 100644 docs/botnet.txt delete mode 100644 src/irc/bot/Makefile.am delete mode 100644 src/irc/bot/bot-events.c delete mode 100644 src/irc/bot/bot-irc-commands.c delete mode 100644 src/irc/bot/bot-users.c delete mode 100644 src/irc/bot/bot-users.h delete mode 100644 src/irc/bot/bot.c delete mode 100644 src/irc/bot/bot.h delete mode 100644 src/irc/bot/botnet-connection.c delete mode 100644 src/irc/bot/botnet-users.c delete mode 100644 src/irc/bot/botnet-users.h delete mode 100644 src/irc/bot/botnet.c delete mode 100644 src/irc/bot/botnet.h delete mode 100644 src/irc/bot/botnets.sample delete mode 100644 src/irc/bot/module.h delete mode 100644 src/irc/bot/users.sample diff --git a/docs/Makefile.am b/docs/Makefile.am index 8541ef1d..5e222564 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -4,7 +4,6 @@ man_MANS = \ irssi.1 doc_DATA = \ - botnet.txt \ design.txt \ formats.txt \ manual.txt \ diff --git a/docs/botnet.txt b/docs/botnet.txt deleted file mode 100644 index 8b5f9ba7..00000000 --- a/docs/botnet.txt +++ /dev/null @@ -1,316 +0,0 @@ - - Irssi's botnet description - - Copyright (c) 1999-2000 Timo Sirainen - - - 0. History - - draft v0.1 : 21.8.1999 - - Just a first draft of my botnet design I did on a boring friday - work afternoon :) I'll try to implement this to irssi some day, it - feels pretty interesting now so it might be pretty soon even. Any - comments are welcome :) - - draft v0.2 : 21.11.1999 - - Exactly three months since the first draft :) Now I actually have - some code done, just committed pretty simple botnet to irssi CVS. - Made several changes to this document.. Still missing much details - but the basic idea should be clear. - - draft v0.3 : 21.05.2000 - - Strange, again the same day. I really didn't plan this :) - Reformatted the text, added lots of text, implemented more of the - stuff. - - - 1. General - - 1.1 Description - - A small description of what botnet would do: A group of bots - efficiently working together to perform their tasks. Like when - someone's trying to take over your channel, bots will quickly - decide who deops/kicks whom instead of multiple bots deopping or - trying to kick the same people. - - Irssi's botnet is pretty much based on trust. Some malicious bot - can quite well mess up the whole botnet. Connecting the bots to - each other via ssh would be a good idea. - - 1.2 Configuration - - example config file: - - mybotnet = - { - priority=5; - nick=mybot; - uplinks = ( - { host = "main.botnet.org"; password = "mypass"; }, - { host = "alter.botnet.org"; password = "pass2"; } - ); - downlinks = ( - { password = "thepass"; valid_addrs = ( "192.168.0.*" ); }, - { password = "blah"; valid_addrs = ( "*.botnet.org" ); }, - { password = "localpass"; valid_addrs = ( "127.*" ); } - ); - } - - When connecting to botnet, the bot first tries to connect to the - first bot in uplinks list, then the second, etc. Setting port to -1 - will prevent connecting to the bot, 0 uses the default. - - 1.3 Botnet master - - To avoid total chaos inside botnet, the bots shouldn't do (almost) - anything without a command from botnet's master. The master should - know everything, and give commands to clients that can perform the - task best. - - Master is the bot with the highest priority. If there's multiple - with the same priority, the one that already was the master will - stay master. When joining two botnets to one, the uplink's master - stays. If link to master breaks, the closest bot to it will choose - a new one. - - The priorities should be given so that the bots that have the - fastest connections and are in the middle of the botnet have the - highest priorities. - - 1.4 Command format - - Commands that are sent inside botnet are in the following format: - - COMMAND [command specific data..] - - If to_nick is '-', the command should be sent to everyone. - - - 2. Handshake - - First host checks from bots' valid_addrs who is connecting. If - there's no matches it just disconnects the client. - - CLIENT: PASS - HOST : (if error, disconnect) - - CLIENT: NICK - HOST : NICKERROR | CONNECTED - - If nick is already in use, the host sends NICKERROR and waits for - new nick. - - Now we're connected to botnet. The commands from now on use the - format specified in section 1.4. - - Both the client and the host sends information to other side of - all the clients they serve (if any): - - BOTINFO - - BOTINFOs must be sent sorted so that connected_to_nick bot is - always known. Like first comes the bots connected to the - host/client, then the bots connected to them etc. - - If the client had downlinks, nick collisions might happen. The - uplink is responsible for noticing them from BOTINFO commands. - It should automatically replace the nicks with new ones and - send nick change command to client and all it's downlinks. For - example if host received: - - BOTINFO bot highbot 10 - - And the bot already exists, the BOTINFO is changed to: - - BOTINFO bot2 highbot 10 - - And the client and it's downlinks are notified: - - BOTNICK bot2 bot - - After sending BOTINFOs, the host tells the current master: - - MASTER - - The client now checks if it's priority is higher than the current - master's. If it is, it will send the MASTER command without any - parameters. - - - 3. Bot connections - - 3.1 General - - Everyone's connections should be kept in n-way tree. Example: - - - [highuplink] - _____________/ | | \ - / | [h5] [h6] - [h1] | / | \ - / \ | [h7] | [h8] - [h2] [h3] | | \ - | [uplink] [h9] [h10] - [h4] / | \ - [up2] | [up1] - / | | | - [up3] [up4] | [up5] - | - [we] - / \ - [client1] [client2] - / \ - [c3] [c4] - - - Botnet should try to keep together even if some hub in the middle - crashes. Each bot should have at least two uplinks in case one - dies. For example if [uplink] dies, [we] and [up1] could connect - to [up2], and [up2] could connect to [highuplink]. - - When connection is closed to some bot, a notice is sent by the - bot's uplink: - - BOTQUIT - - The quit notice should be sent only about the bot that was - disconnected. Bots should figure out themselves the other bots and - remove them too from their lists. - - 3.2 Lag - - Each bot should send PING commands to their up/downlinks every - now and then (1min?) to check that the connection is still active. - If the PONG isn't received in 10 seconds, it's priority should be - temporarily lowered to -1. If the PONG isn't received in 3 - minutes, the whole connection should be closed. - - Master should know lag times of every bots. It could then - automatically raise/lower bots' priorities depending on how big - their lag is. Master could also lower it's own priority and pass - the master status to someone else with lower lag. - - If there's lot of lag (>3sec?) somewhere and something urgent - happens, the botnet could split and behave independently. - - - 4. IRC networks - - 4.1 Server connections - - When bot is connected to some irc server and is ready to take - commands, it says: - - IRCJOIN - - Tag is the bot specific unique tag of the server, so that the bot - can connect multiple times to same IRC network. All IRC related - commands should specify the server tag where it should be sent. - - If bot quits an irc network, it says: - - IRCQUIT - - 4.2 IRC commands - - Master asks a bot to send some command to IRC server by saying: - - CMD - - can't really be anything, since the bot should also be - able to reply to it. The is for identifying the command/reply - pair. Master should keep the command in memory until it receives - the reply: - - CMDREPLY - - The command could get a reply of multiple lines, so - specifies if the reply is the last line (1 or 0). - - If the command failed for some reason, the bot will reply with - - CMDFAIL - - and master should send the command to some other bot. - - 4.3 Channels - - When joined/left channels, the bot says: - - CHANJOIN - CHANPART - - After BOTJOIN, master tries to op the bot. When bot receives +o, - it says: - - CHANOP - - If it is the first opped bot in channel, master orders the bot to - op the rest of the bots. - - If the bot is kicked, it says: - - CHANKICK - - When master notices that bot is kicked, it first checks if there's - any other opped bots in channel. If not, it waits for a random - pause, 5-10sec before letting the bot join the channel again so - that it won't get autorejoin ban. - - If bot can't join channel, it says: - - CHANBANNED - (or) - CHANCANTJOIN - - When received BOTBANNED, master tries to unban bot or set a ban - exception. BOTCANTJOIN results as invite to channel. - - 4.4 Channel information - - When master notices that bot is the first one joined to channel, - it asks the bot for some channel information: - - CMD NAMES - CMD WHO - CMD MODE - CMD MODE b - CMD MODE e (if IRC network supports this) - CMD MODE I (if IRC network supports this) - - It's also possible that if several bots join immediately after the - first bot, the commands are shared between all the bots. - - Bots should cache the information as much as possible, at least - NAMES command. - - 4.5 Channel priorities - - Every channel has a priority: LOW, NORMAL, HIGH. - - Normally LOW operates just as NORMAL channels, except when some - channel has HIGH priority and bots are really busy, LOW channels - just wait until there's time for them. - - In NORMAL channels, the most urgent operations (kicks, ops, deops) - are performed quite soon even while bots are busy handling HIGH - priority commands. - - Channels shouldn't normally be HIGH priority, but if attack - against channel is detected (like someone comes from split, gets - ops and gets to op someone else), it's priority is set to HIGH. - When channel's priority is HIGH, botnet does everything it can to - get rid of unauthorized opped people as fast as possible. - - LOW channel's priority can also be raised to HIGH, but it's - priority is dropped back to LOW if some NORMAL channel's priority - is raised to HIGH too. - - Master notifies about channel's priority change by saying: - - CHANPRIORITY - diff --git a/src/irc/bot/Makefile.am b/src/irc/bot/Makefile.am deleted file mode 100644 index a97abf07..00000000 --- a/src/irc/bot/Makefile.am +++ /dev/null @@ -1,32 +0,0 @@ -moduledir = $(libdir)/irssi/modules -module_LTLIBRARIES = libirc_bot.la - -libirc_bot_la_LDFLAGS = -avoid-version - -INCLUDES = \ - -I$(top_srcdir)/src \ - -I$(top_srcdir)/src/core/ \ - -I$(top_srcdir)/src/irc/core/ \ - $(GLIB_CFLAGS) - -libirc_bot_la_LIBADD = -lcrypt - -libirc_bot_la_SOURCES = \ - bot.c \ - bot-irc-commands.c \ - bot-events.c \ - bot-users.c \ - botnet.c \ - botnet-connection.c \ - botnet-users.c - -noinst_HEADERS = \ - bot.h \ - bot-users.h \ - botnet.h \ - botnet-users.h \ - module.h - -EXTRA_DIST = \ - users.sample \ - botnets.sample diff --git a/src/irc/bot/bot-events.c b/src/irc/bot/bot-events.c deleted file mode 100644 index 9ef646de..00000000 --- a/src/irc/bot/bot-events.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - bot-events.c : IRC bot plugin for irssi - - Copyright (C) 1999 Timo Sirainen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "module.h" -#include "signals.h" -#include "commands.h" - -#include "irc.h" -#include "irc-servers.h" -#include "irc-channels.h" -#include "nicklist.h" -#include "modes.h" -#include "netsplit.h" - -#include "bot-users.h" - -static int get_flags(USER_REC *user, IRC_CHANNEL_REC *channel) -{ - USER_CHAN_REC *userchan; - - g_return_val_if_fail(user != NULL, 0); - g_return_val_if_fail(channel != NULL, 0); - - userchan = g_hash_table_lookup(user->channels, channel->name); - return (user->flags | (userchan == NULL ? 0 : userchan->flags)) & - (~user->not_flags); -} - -static void event_massjoin(IRC_CHANNEL_REC *channel, GSList *users) -{ - USER_REC *user; - USER_CHAN_REC *userchan; - NICK_REC *nick; - GString *modestr, *nickstr; - int flags; - - g_return_if_fail(channel != NULL); - g_return_if_fail(users != NULL); - - modestr = g_string_new(NULL); - nickstr = g_string_new(NULL); - - for (; users != NULL; users = users->next) { - user = users->data; - userchan = g_hash_table_lookup(user->channels, channel->name); - nick = userchan->nickrec; - - flags = get_flags(user, channel); - if (!nick->op && (flags & USER_AUTO_OP)) { - g_string_sprintfa(modestr, "+o"); - g_string_sprintfa(nickstr, "%s,", nick->nick); - } - - if (!nick->voice && !nick->op && (flags & USER_AUTO_VOICE)) { - g_string_sprintfa(modestr, "+v"); - g_string_sprintfa(nickstr, "%s,", nick->nick); - } - } - - if (nickstr->len > 0) { - g_string_truncate(nickstr, nickstr->len-1); - g_string_sprintfa(modestr, " %s", nickstr->str); - - channel_set_mode(channel->server, channel->name, modestr->str); - } - - g_string_free(modestr, TRUE); - g_string_free(nickstr, TRUE); -} - -/* Parse channel mode string */ -static void parse_channel_mode(IRC_CHANNEL_REC *channel, const char *mode, - const char *nick, const char *address) -{ - NETSPLIT_CHAN_REC *splitnick; - NICK_REC *nickrec; - USER_REC *user; - GString *str; - char *ptr, *curmode, type, *dup, *modestr; - int flags; - - g_return_if_fail(channel != NULL); - g_return_if_fail(nick != NULL); - g_return_if_fail(mode != NULL); - - user = botuser_find(nick, address); - flags = user == NULL ? 0 : get_flags(user, channel); - - if (!channel->chanop || (flags & USER_MASTER) || - g_strcasecmp(nick, channel->server->nick) == 0) { - /* can't do anything or we/master did mode change, - don't bother checking what */ - return; - } - - /* check if unwanted people got ops */ - str = g_string_new(NULL); - dup = modestr = g_strdup(mode); - - type = '+'; - curmode = cmd_get_param(&modestr); - for (; *curmode != '\0'; curmode++) { - if (*curmode == '+' || *curmode == '-') { - type = *curmode; - continue; - } - - if (!HAS_MODE_ARG(type, *curmode)) - ptr = NULL; - else { - ptr = cmd_get_param(&modestr); - if (*ptr == '\0') continue; - } - - if (*curmode != 'o') - continue; - - if (type == '-' && strcmp(channel->server->nick, ptr) == 0) { - /* we aren't chanop anymore .. */ - g_string_truncate(str, 0); - break; - } - - if (type != '+') - continue; - - /* check that op is valid */ - nickrec = nicklist_find(CHANNEL(channel), ptr); - if (nickrec == NULL || nickrec->host == NULL) - continue; - - user = botuser_find(ptr, nickrec->host); - flags = user == NULL ? 0 : get_flags(user, channel); - if (flags & USER_OP) - continue; - - if (address == NULL) { - /* server opped, check if user was opped before netsplit. */ - splitnick = netsplit_find_channel(channel->server, nickrec->nick, nickrec->host, channel->name); - if (splitnick != NULL && splitnick->op) - continue; - } - - /* this one isn't supposed to get ops! */ - g_string_sprintfa(str, "%s ", ptr); - } - g_free(dup); - - if (str->len != 0) - signal_emit("command deop", 3, str->str, channel->server, channel); - g_string_free(str, TRUE); -} - -static void event_mode(IRC_SERVER_REC *server, const char *data, - const char *nick, const char *address) -{ - IRC_CHANNEL_REC *chanrec; - char *params, *channel, *mode; - - g_return_if_fail(data != NULL); - - params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &channel, &mode); - - if (ischannel(*channel)) { - /* channel mode change */ - chanrec = irc_channel_find(server, channel); - if (chanrec != NULL) - parse_channel_mode(chanrec, mode, nick, address); - } - - g_free(params); -} - -void bot_events_init(void) -{ - signal_add_last("bot massjoin", (SIGNAL_FUNC) event_massjoin); - signal_add("event mode", (SIGNAL_FUNC) event_mode); -} - -void bot_events_deinit(void) -{ - signal_remove("bot massjoin", (SIGNAL_FUNC) event_massjoin); - signal_remove("event mode", (SIGNAL_FUNC) event_mode); -} diff --git a/src/irc/bot/bot-irc-commands.c b/src/irc/bot/bot-irc-commands.c deleted file mode 100644 index 9ed39acd..00000000 --- a/src/irc/bot/bot-irc-commands.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - bot-irc-commands.c : IRC bot plugin for irssi - - Copyright (C) 1999-2000 Timo Sirainen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "module.h" -#include "signals.h" -#include "commands.h" - -#include "irc.h" -#include "irc-servers.h" -#include "channels.h" -#include "nicklist.h" -#include "irc-masks.h" - -#include "bot-users.h" -#include "botnet-users.h" - -static void event_privmsg(IRC_SERVER_REC *server, const char *data, - const char *nick, const char *address) -{ - char *params, *target, *msg, *args, *str; - - g_return_if_fail(data != NULL); - - params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); - if (ischannel(*target)) { - g_free(params); - return; - } - - /* private message for us */ - str = g_strconcat("bot command ", msg, NULL); - args = strchr(str+12, ' '); - if (args != NULL) *args++ = '\0'; else args = ""; - - g_strdown(str); - if (signal_emit(str, 4, server, args, nick, address)) { - /* msg was a command - the msg event. */ - signal_stop(); - } - g_free(str); - g_free(params); -} - -static void botcmd_op(IRC_SERVER_REC *server, const char *data, - const char *nick, const char *address) -{ - CHANNEL_REC *channel; - USER_REC *user; - USER_CHAN_REC *userchan; - GSList *tmp; - - g_return_if_fail(data != NULL); - - if (*data == '\0') { - /* no password given? .. */ - return; - } - - user = botuser_find(nick, address); - if (user == NULL || (user->not_flags & USER_OP) || - !botuser_verify_password(user, data)) { - /* not found, can't op with this mask or failed password */ - return; - } - - /* find the channels where to op.. */ - for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { - channel = tmp->data; - - userchan = g_hash_table_lookup(user->channels, channel->name); - if ((user->flags & USER_OP) || (userchan->flags & USER_OP)) - signal_emit("command op", 3, nick, server, channel); - } -} - -static void botcmd_ident(IRC_SERVER_REC *server, const char *data, - const char *nick, const char *address) -{ - USER_REC *user; - char *mask; - - g_return_if_fail(data != NULL); - - user = botuser_find(nick, address); - if (user != NULL) { - /* Already know this host */ - return; - } - - user = botuser_find(nick, NULL); - if (user == NULL || !botuser_verify_password(user, data)) { - /* failed password */ - return; - } - - /* add the new mask */ - mask = irc_get_mask(nick, address, IRC_MASK_USER | IRC_MASK_DOMAIN); - botcmd_user_add_mask(user, mask); - - irc_send_cmdv(server, "NOTICE %s :Added new mask %s", nick, mask); - g_free(mask); -} - -static void botcmd_pass(IRC_SERVER_REC *server, const char *data, - const char *nick, const char *address) -{ - USER_REC *user; - char *params, *pass, *newpass; - - g_return_if_fail(data != NULL); - - params = event_get_params(data, 2, &pass, &newpass); - - user = botuser_find(nick, address); - if (user == NULL || *pass == '\0') { - g_free(params); - return; - } - - if (user->password != NULL && - (*newpass == '\0' || !botuser_verify_password(user, pass))) { - g_free(params); - return; - } - - /* change the password */ - botcmd_user_set_password(user, user->password == NULL ? pass : newpass); - irc_send_cmdv(server, "NOTICE %s :Password changed", nick); - - g_free(params); -} - -void bot_irc_commands_init(void) -{ - signal_add("event privmsg", (SIGNAL_FUNC) event_privmsg); - signal_add_last("bot command op", (SIGNAL_FUNC) botcmd_op); - signal_add_last("bot command ident", (SIGNAL_FUNC) botcmd_ident); - signal_add_last("bot command pass", (SIGNAL_FUNC) botcmd_pass); -} - -void bot_irc_commands_deinit(void) -{ - signal_remove("event privmsg", (SIGNAL_FUNC) event_privmsg); - signal_remove("bot command op", (SIGNAL_FUNC) botcmd_op); - signal_remove("bot command ident", (SIGNAL_FUNC) botcmd_ident); - signal_remove("bot command pass", (SIGNAL_FUNC) botcmd_pass); -} diff --git a/src/irc/bot/bot-users.c b/src/irc/bot/bot-users.c deleted file mode 100644 index 35d7b8c8..00000000 --- a/src/irc/bot/bot-users.c +++ /dev/null @@ -1,579 +0,0 @@ -/* - bot-users.c : IRC bot plugin for irssi - user handling - - Copyright (C) 1999-2000 Timo Sirainen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef _XOPEN_SOURCE -#define _XOPEN_SOURCE /* for crypt() */ -#endif - -#include "module.h" -#include "signals.h" -#include "misc.h" -#include "lib-config/iconfig.h" - -#include "irc.h" -#include "irc-servers.h" -#include "irc-channels.h" -#include "irc-nicklist.h" -#include "masks.h" - -#include "bot-users.h" - -#define WRITE_USERS_INTERVAL (60*15) - -static char *user_flags = "oavm"; /* Keep these in the same order as USER_xxx flags */ - -static CONFIG_REC *userconfig; -static GHashTable *users; - -static int writeusers_tag; -static time_t last_write; - -int botuser_flags2value(const char *flags) -{ - char *pos; - int val; - - g_return_val_if_fail(flags != NULL, 0); - - val = 0; - while (*flags != '\0') { - pos = strchr(user_flags, *flags); - if (pos != NULL) - val |= 1 << (int) (pos-user_flags); - flags++; - } - - return val; -} - -char *botuser_value2flags(int value) -{ - char *str, *p; - int n; - - p = str = g_malloc(USER_FLAG_COUNT+1); - for (n = 0; n < USER_FLAG_COUNT; n++) { - if (value & (1 << n)) - *p++ = user_flags[n]; - } - *p = '\0'; - - return str; -} - -/* save channel specific user record */ -static void botuser_save_chan(const char *key, USER_CHAN_REC *rec, CONFIG_NODE *node) -{ - CONFIG_NODE *noderec; - char *str; - - if (rec->flags == 0) { - /* no flags in this channel - no need to save to config */ - config_node_set_str(userconfig, node, rec->channel, NULL); - return; - } - - noderec = config_node_section(node, rec->channel, NODE_TYPE_BLOCK); - - str = botuser_value2flags(rec->flags); - config_node_set_str(userconfig, noderec, "flags", str); - g_free_not_null(str); -} - -static void botuser_config_save(USER_REC *user) -{ - CONFIG_NODE *node, *subnode, *noderec; - GSList *tmp; - char *str; - - user->last_modify = time(NULL); - - node = config_node_traverse(userconfig, "users", TRUE); - node = config_node_section(node, user->nick, NODE_TYPE_BLOCK); - - str = user->flags == 0 ? NULL : - botuser_value2flags(user->flags); - config_node_set_str(userconfig, node, "flags", str); - g_free_not_null(str); - - config_node_set_str(userconfig, node, "password", user->password); - config_node_set_int(userconfig, node, "last_modify", (int) user->last_modify); - - /* Save masks */ - if (user->masks == NULL) - config_node_set_str(userconfig, node, "masks", NULL); - else { - subnode = config_node_section(node, "masks", NODE_TYPE_LIST); - - for (tmp = user->masks; tmp != NULL; tmp = tmp->next) { - USER_MASK_REC *rec = tmp->data; - - noderec = config_node_section(subnode, NULL, NODE_TYPE_BLOCK); - config_node_set_str(userconfig, noderec, "mask", rec->mask); - - str = user->flags == 0 ? NULL : - botuser_value2flags(rec->not_flags); - config_node_set_str(userconfig, noderec, "not_flags", str); - g_free_not_null(str); - } - } - - /* Save channels */ - if (g_hash_table_size(user->channels) == 0) - config_node_set_str(userconfig, node, "channels", NULL); - else { - subnode = config_node_section(node, "channels", NODE_TYPE_LIST); - g_hash_table_foreach(user->channels, (GHFunc) botuser_save_chan, subnode); - } -} - -static int botuser_find_mask(USER_REC *user, const char *nick, const char *host) -{ - GSList *tmp; - - g_return_val_if_fail(user != NULL, FALSE); - g_return_val_if_fail(nick != NULL, FALSE); - g_return_val_if_fail(host != NULL, FALSE); - - /* Check that masks match */ - for (tmp = user->masks; tmp != NULL; tmp = tmp->next) { - USER_MASK_REC *rec = tmp->data; - - if (mask_match_address(NULL, rec->mask, nick, host)) { - user->not_flags = rec->not_flags; - return TRUE; - } - } - - return FALSE; -} - -static USER_MASK_REC *botuser_find_full_mask(USER_REC *user, const char *mask) -{ - GSList *tmp; - - g_return_val_if_fail(user != NULL, FALSE); - g_return_val_if_fail(mask != NULL, FALSE); - - for (tmp = user->masks; tmp != NULL; tmp = tmp->next) { - USER_MASK_REC *rec = tmp->data; - - if (g_strcasecmp(rec->mask, mask) == 0) - return rec; - } - - return NULL; -} - -static void botuser_getusers_hash(void *key, USER_REC *user, GList **list) -{ - *list = g_list_append(*list, user); -} - -USER_REC *botuser_find(const char *nick, const char *host) -{ - USER_REC *user; - char *stripnick; - GList *list, *tmp; - - g_return_val_if_fail(nick != NULL, NULL); - - /* First check for user with same nick */ - stripnick = irc_nick_strip(nick); - user = g_hash_table_lookup(users, stripnick); - g_free(stripnick); - - if (user != NULL && host != NULL && - !botuser_find_mask(user, nick, host)) { - /* mask didn't match, check for more.. */ - user = NULL; - } - - if (user != NULL || host == NULL) - return user; - - /* Check for different nicks.. */ - list = NULL; - g_hash_table_foreach(users, (GHFunc) botuser_getusers_hash, &list); - for (tmp = list; tmp != NULL; tmp = tmp->next) { - if (botuser_find_mask(tmp->data, nick, host)) { - user = tmp->data; - break; - } - } - g_list_free(list); - - return user; -} - -USER_REC *botuser_find_rec(CHANNEL_REC *channel, NICK_REC *nick) -{ - USER_REC *user, *rec; - USER_CHAN_REC *userchan; - GList *list, *tmp; - - g_return_val_if_fail(channel != NULL, NULL); - g_return_val_if_fail(nick != NULL, NULL); - - user = NULL; list = NULL; - g_hash_table_foreach(users, (GHFunc) botuser_getusers_hash, &list); - for (tmp = list; tmp != NULL; tmp = tmp->next) { - rec = tmp->data; - - userchan = g_hash_table_lookup(rec->channels, channel->name); - if (userchan != NULL && userchan->nickrec == nick) { - user = rec; - break; - } - } - g_list_free(list); - - return user; -} - -USER_CHAN_REC *botuser_get_channel(USER_REC *user, const char *channel) -{ - USER_CHAN_REC *rec; - - g_return_val_if_fail(user != NULL, NULL); - g_return_val_if_fail(channel != NULL, NULL); - - rec = g_hash_table_lookup(user->channels, channel); - if (rec != NULL) return rec; - - rec = g_new0(USER_CHAN_REC, 1); - rec->channel = g_strdup(channel); - g_hash_table_insert(user->channels, rec->channel, rec); - return rec; -} - -USER_REC *botuser_add(const char *nick) -{ - USER_REC *user; - - /* Add new user */ - user = g_new0(USER_REC, 1); - user->nick = g_strdup(nick); - g_hash_table_insert(users, user->nick, user); - - botuser_config_save(user); - return user; -} - -void botuser_set_flags(USER_REC *user, int flags) -{ - user->flags = flags; - botuser_config_save(user); -} - -void botuser_set_channel_flags(USER_REC *user, const char *channel, int flags) -{ - USER_CHAN_REC *rec; - - rec = botuser_get_channel(user, channel); - if (rec != NULL) rec->flags = flags; - - botuser_config_save(user); -} - -static USER_MASK_REC *botuser_create_mask(USER_REC *user, const char *mask) -{ - USER_MASK_REC *rec; - - rec = g_new0(USER_MASK_REC, 1); - rec->mask = g_strdup(mask); - - user->masks = g_slist_append(user->masks, rec); - return rec; -} - -USER_MASK_REC *botuser_add_mask(USER_REC *user, const char *mask) -{ - USER_MASK_REC *rec; - - rec = botuser_create_mask(user, mask); - botuser_config_save(user); - return rec; -} - -void botuser_set_mask_notflags(USER_REC *user, const char *mask, int not_flags) -{ - USER_MASK_REC *rec; - - rec = botuser_find_full_mask(user, mask); - if (rec == NULL) rec = botuser_create_mask(user, mask); - - rec->not_flags = not_flags; - botuser_config_save(user); -} - -void botuser_set_password(USER_REC *user, const char *password) -{ - char *pass, salt[3]; - - g_return_if_fail(user != NULL); - g_return_if_fail(password != NULL); - - salt[0] = rand()%20 + 'A'; - salt[1] = rand()%20 + 'A'; - salt[2] = '\0'; - pass = crypt(password, salt); - - if (user->password != NULL) g_free(user->password); - user->password = g_strdup(pass); - botuser_config_save(user); -} - -int botuser_verify_password(USER_REC *user, const char *password) -{ - char *pass, salt[3]; - - g_return_val_if_fail(user != NULL, FALSE); - g_return_val_if_fail(password != NULL, FALSE); - - if (user->password == NULL || strlen(user->password) < 3) - return FALSE; - - salt[0] = user->password[0]; - salt[1] = user->password[1]; - salt[2] = '\0'; - pass = crypt(password, salt); - return strcmp(user->password, pass) == 0; -} - -void botuser_save(const char *fname) -{ - config_write(userconfig, fname, 0600); -} - -static void event_massjoin(CHANNEL_REC *channel, GSList *nicks) -{ - USER_REC *user; - USER_CHAN_REC *userchan; - GSList *users; - - g_return_if_fail(channel != NULL); - g_return_if_fail(nicks != NULL); - - users = NULL; - for (; nicks != NULL; nicks = nicks->next) { - NICK_REC *rec = nicks->data; - - user = botuser_find(rec->nick, rec->host); - if (user != NULL) { - userchan = botuser_get_channel(user, channel->name); - userchan->nickrec = rec; - users = g_slist_append(users, user); - } - } - - if (users != NULL) { - signal_emit("bot massjoin", 2, channel, users); - g_slist_free(users); - } -} - -/* channel synced - find everyone's NICK_REC's */ -static void sig_channel_sync(CHANNEL_REC *channel) -{ - USER_REC *user; - USER_CHAN_REC *userchan; - GSList *tmp, *nicks; - - g_return_if_fail(channel != NULL); - - nicks = nicklist_getnicks(channel); - for (tmp = nicks; tmp != NULL; tmp = tmp->next) { - NICK_REC *rec = tmp->data; - - if (rec->send_massjoin) - continue; /* This will be checked in "massjoin" signal */ - - user = botuser_find(rec->nick, rec->host); - if (user != NULL) { - userchan = botuser_get_channel(user, channel->name); - userchan->nickrec = rec; - } - } - g_slist_free(nicks); -} - -/* user left channel - remove from users record */ -static void sig_nicklist_remove(CHANNEL_REC *channel, NICK_REC *nick) -{ - USER_REC *user; - USER_CHAN_REC *userchan; - - g_return_if_fail(channel != NULL); - g_return_if_fail(nick != NULL); - - user = botuser_find_rec(channel, nick); - userchan = user == NULL ? NULL : - g_hash_table_lookup(user->channels, channel->name); - if (userchan != NULL) userchan->nickrec = NULL; -} - -/* Free memory used by user channel record */ -static void user_destroy_chan(const char *key, USER_CHAN_REC *rec) -{ - g_free(rec->channel); - g_free(rec); -} - -static void usermask_destroy(USER_MASK_REC *rec) -{ - g_free(rec->mask); - g_free(rec); -} - -/* Free memory used by user record */ -static void user_destroy(const char *key, USER_REC *user) -{ - g_slist_foreach(user->masks, (GFunc) usermask_destroy, NULL); - g_slist_free(user->masks); - - g_hash_table_foreach(user->channels, (GHFunc) user_destroy_chan, NULL); - g_hash_table_destroy(user->channels); - - g_free_not_null(user->password); - g_free(user->nick); - g_free(user); -} - -static int sig_write_users(void) -{ - if (last_write + WRITE_USERS_INTERVAL <= time(NULL)) { - last_write = time(NULL); - config_write(userconfig, NULL, -1); - } - return 1; -} - -static void botuser_config_read_user(CONFIG_NODE *node) -{ - USER_REC *user; - USER_CHAN_REC *userchan; - USER_MASK_REC *usermask; - CONFIG_NODE *subnode; - GSList *tmp; - char *value; - - g_return_if_fail(node != NULL); - - /* nick = { ... } */ - if (node->key == NULL || node->value == NULL) - return; - - /* Add new user */ - user = g_new0(USER_REC, 1); - user->nick = g_strdup(node->key); - g_hash_table_insert(users, user->nick, user); - - /* password, flags, modify time */ - user->password = g_strdup(config_node_get_str(node, "password", NULL)); - user->flags = botuser_flags2value(config_node_get_str(node, "flags", "")); - user->last_modify = (time_t) config_node_get_int(node, "last_modify", 0); - - /* get masks */ - user->masks = NULL; - subnode = config_node_section(node, "masks", -1); - tmp = subnode == NULL ? NULL : subnode->value; - for (; tmp != NULL; tmp = tmp->next) { - subnode = tmp->data; - - value = config_node_get_str(subnode, "mask", NULL); - if (value == NULL) continue; /* mask is required */ - - usermask = botuser_create_mask(user, value); - value = config_node_get_str(subnode, "not_flags", ""); - usermask->not_flags = botuser_flags2value(value); - } - - /* get channels - must be last, messes up pvalue */ - user->channels = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal); - subnode = config_node_section(node, "channels", -1); - tmp = subnode == NULL ? NULL : subnode->value; - for (; tmp != NULL; tmp = tmp->next) { - subnode = tmp->data; - - value = config_node_get_str(subnode, "channel", NULL); - if (value == NULL) continue; /* channel is required */ - - /* create user channel specific record */ - userchan = g_new0(USER_CHAN_REC, 1); - userchan->channel = g_strdup(value); - g_hash_table_insert(user->channels, userchan->channel, userchan); - - value = config_node_get_str(subnode, "flags", ""); - userchan->flags = botuser_flags2value(value); - } -} - -static void botuser_config_read(void) -{ - CONFIG_NODE *node; - GSList *tmp; - char *fname; - - /* Read users from ~/.irssi/users */ - fname = g_strdup_printf("%s/users", get_irssi_dir()); - userconfig = config_open(fname, 0600); - g_free(fname); - - if (userconfig == NULL) - return; /* access denied?! */ - - config_parse(userconfig); - - node = config_node_traverse(userconfig, "users", FALSE); - tmp = node == NULL ? NULL : node->value; - for (; tmp != NULL; tmp = tmp->next) - botuser_config_read_user(tmp->data); -} - -void bot_users_init(void) -{ - users = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal); - - last_write = time(NULL); - writeusers_tag = g_timeout_add(10000, (GSourceFunc) sig_write_users, NULL); - - botuser_config_read(); - signal_add_last("massjoin", (SIGNAL_FUNC) event_massjoin); - signal_add_last("channel sync", (SIGNAL_FUNC) sig_channel_sync); - signal_add_last("nicklist remove", (SIGNAL_FUNC) sig_nicklist_remove); -} - -void bot_users_deinit(void) -{ - if (userconfig != NULL) { - config_write(userconfig, NULL, -1); - config_close(userconfig); - } - - g_source_remove(writeusers_tag); - - g_hash_table_foreach(users, (GHFunc) user_destroy, NULL); - g_hash_table_destroy(users); - - signal_remove("massjoin", (SIGNAL_FUNC) event_massjoin); - signal_remove("channel sync", (SIGNAL_FUNC) sig_channel_sync); - signal_remove("nicklist remove", (SIGNAL_FUNC) sig_nicklist_remove); -} diff --git a/src/irc/bot/bot-users.h b/src/irc/bot/bot-users.h deleted file mode 100644 index 8023e9a6..00000000 --- a/src/irc/bot/bot-users.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef __BOT_USERS_H -#define __BOT_USERS_H - -#define USER_OP 0x0001 -#define USER_AUTO_OP 0x0002 -#define USER_AUTO_VOICE 0x0004 -#define USER_MASTER 0x0008 - -#define USER_FLAG_COUNT 4 - -/* Channel specific flags */ -typedef struct { - char *channel; - int flags; - NICK_REC *nickrec; /* Nick record in channel, - FIXME: User can be in channel with multiple nicks too! */ -} USER_CHAN_REC; - -typedef struct { - char *mask; - int not_flags; /* do not let this mask use these flags.. */ -} USER_MASK_REC; - -/* User specific flags */ -typedef struct { - char *nick; - int flags; - char *password; - - GSList *masks; - GHashTable *channels; - - int not_flags; /* active not_flags based on current host mask, - botuser_find() updates this */ - time_t last_modify; /* last time the user settings were modified */ -} USER_REC; - -int botuser_flags2value(const char *flags); -char *botuser_value2flags(int value); - -USER_REC *botuser_find(const char *nick, const char *host); -USER_REC *botuser_find_rec(CHANNEL_REC *channel, NICK_REC *nick); - -USER_REC *botuser_add(const char *nick); -void botuser_set_flags(USER_REC *user, int flags); -void botuser_set_channel_flags(USER_REC *user, const char *channel, int flags); - -USER_MASK_REC *botuser_add_mask(USER_REC *user, const char *mask); -void botuser_set_mask_notflags(USER_REC *user, const char *mask, int not_flags); - -void botuser_set_password(USER_REC *user, const char *password); -int botuser_verify_password(USER_REC *user, const char *password); - -void botuser_save(const char *fname); - -#endif diff --git a/src/irc/bot/bot.c b/src/irc/bot/bot.c deleted file mode 100644 index f2beee4d..00000000 --- a/src/irc/bot/bot.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - bot.c : IRC bot plugin for irssi - - Copyright (C) 1999-2000 Timo Sirainen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "module.h" -#include "modules.h" - -void bot_irc_commands_deinit(void); -void bot_irc_commands_init(void); - -void bot_events_init(void); -void bot_events_deinit(void); - -void bot_users_init(void); -void bot_users_deinit(void); - -void botnet_init(void); -void botnet_deinit(void); - -void irc_bot_init(void) -{ - bot_users_init(); - bot_irc_commands_init(); - bot_events_init(); - botnet_init(); - - module_register("bot", "irc"); -} - -void irc_bot_deinit(void) -{ - bot_users_deinit(); - bot_irc_commands_deinit(); - bot_events_deinit(); - botnet_deinit(); -} diff --git a/src/irc/bot/bot.h b/src/irc/bot/bot.h deleted file mode 100644 index a518d4bd..00000000 --- a/src/irc/bot/bot.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __BOT_H -#define __BOT_H - -typedef struct -{ - PLUGIN_REC *plugin; - gboolean loaded; - - GHashTable *users; - GSList *botnets; - - gchar *nick; - gint rank; - - time_t last_write; -} -PLUGIN_DATA; - -void plugin_bot_events(PLUGIN_REC *plugin); - -#include "botnet.h" -#include "users.h" - -#define MODULE_NAME "bot" - -#endif diff --git a/src/irc/bot/botnet-connection.c b/src/irc/bot/botnet-connection.c deleted file mode 100644 index 1039cea0..00000000 --- a/src/irc/bot/botnet-connection.c +++ /dev/null @@ -1,592 +0,0 @@ -/* - botnet-connection.c : IRC bot plugin for irssi - - Copyright (C) 1999-2000 Timo Sirainen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "module.h" -#include "network.h" -#include "net-nonblock.h" -#include "signals.h" -#include "commands.h" -#include "misc.h" -#include "line-split.h" -#include "lib-config/iconfig.h" - -#include "botnet.h" -#include "bot-users.h" - -#define BOTNET_RECONNECT_TIME (60*5) - -static int reconnect_tag; - -static int sig_reconnect(void) -{ - GSList *tmp; - - for (tmp = botnets; tmp != NULL; tmp = tmp->next) { - BOTNET_REC *rec = tmp->data; - - if (rec->reconnect) - botnet_connect(rec); - } - - return 1; -} - -static void sig_bot_read(BOT_REC *bot) -{ - BOTNET_REC *botnet; - char tmpbuf[1024], *str; - int ret, recvlen, reconnect; - - botnet = bot->botnet; - for (;;) { - recvlen = bot->handle == NULL ? -1 : - net_receive(bot->handle, tmpbuf, sizeof(tmpbuf)); - ret = line_split(tmpbuf, recvlen, &str, &bot->buffer); - - if (ret == 0) - break; - if (ret == -1) { - /* connection lost */ - reconnect = !bot->disconnect && bot->uplink; - bot_destroy(bot); - - if (reconnect) { - /* wasn't intentional disconnection from - our uplink, reconnect */ - botnet_connect(botnet); - } - break; - } - - fprintf(stderr, "%s\r\n", str); - signal_emit("botnet event", 2, bot, str); - } -} - -static void connect_downlink(BOTNET_REC *botnet, GIOChannel *handle, - IPADDR *ip, const char *host) -{ - BOT_DOWNLINK_REC *downlink; - BOT_REC *bot; - - g_return_if_fail(botnet != NULL); - - /* identify the bot who's trying to connect.. */ - downlink = bot_downlink_find(botnet, ip, host); - if (downlink == NULL || downlink->password == NULL) { - /* unknown bot, close connection / - bot didn't have password, don't let it connect to us */ - net_disconnect(handle); - return; - } - - bot = g_new0(BOT_REC, 1); - bot->botnet = botnet; - bot->link = downlink; - g_node_append_data(botnet->bots, bot); - - /* connected.. */ - bot->handle = handle; - bot->read_tag = g_input_add(handle, G_INPUT_READ, (GInputFunction) sig_bot_read, bot); -} - -typedef struct { - char *botnet; - IPADDR ip; - GIOChannel *handle; -} BOT_CONNECT_REC; - -static void sig_host_got(RESOLVED_NAME_REC *name, BOT_CONNECT_REC *rec) -{ - BOTNET_REC *botnet; - - botnet = botnet_find(rec->botnet); - if (botnet == NULL || !botnet->connected) { - /* this botnet isn't connected anymore.. */ - net_disconnect(rec->handle); - } else { - connect_downlink(botnet, rec->handle, &rec->ip, - name->error ? NULL : name->name); - } - g_free(rec->botnet); - g_free(rec); -} - -static void sig_botnet_listen(BOTNET_REC *botnet) -{ - BOT_CONNECT_REC *rec; - IPADDR ip; - GIOChannel *handle; - - g_return_if_fail(botnet != NULL); - - /* accept connection */ - handle = net_accept(botnet->listen_handle, &ip, NULL); - if (handle == NULL) - return; - - rec = g_new0(BOT_CONNECT_REC, 1); - rec->botnet = g_strdup(botnet->name); - memcpy(&rec->ip, &ip, sizeof(IPADDR)); - rec->handle = handle; - - if (!net_gethostbyaddr_nonblock(&ip, (NET_HOST_CALLBACK) sig_host_got, rec)) { - /* failed for some reason, try without host */ - connect_downlink(botnet, handle, &ip, NULL); - g_free(rec->botnet); - g_free(rec); - } -} - -static int botnet_listen(BOTNET_REC *botnet) -{ - IPADDR addr; - int port; - - g_return_val_if_fail(botnet != NULL, FALSE); - - if (botnet->port <= 0) - return FALSE; - - port = botnet->port; - if (botnet->addr == NULL) - botnet->listen_handle = net_listen(NULL, &port); - else { - net_host2ip(botnet->addr, &addr); - botnet->listen_handle = net_listen(&addr, &port); - } - - if (botnet->listen_handle == NULL) { - g_warning("Couldn't start listening botnet\n"); - return FALSE; - } - - botnet->listen_tag = g_input_add(botnet->listen_handle, G_INPUT_READ, - (GInputFunction) sig_botnet_listen, botnet); - - return TRUE; -} - -static void sig_botnet_connected(GIOChannel *handle, BOT_UPLINK_REC *uplink) -{ - BOTNET_REC *botnet; - BOT_REC *bot; - - g_return_if_fail(uplink != NULL); - - botnet = uplink->botnet; - - if (handle == NULL) { - /* error, try another bot */ - botnet_connect(botnet); - return; - } - - /* connected to bot */ - bot = g_new0(BOT_REC, 1); - bot->botnet = botnet; - bot->link = uplink; - bot->uplink = TRUE; - - bot->handle = handle; - bot->read_tag = g_input_add(handle, G_INPUT_READ, (GInputFunction) sig_bot_read, bot); - - botnet->uplink = bot; - g_node_append_data(botnet->bots, bot); - - /* send nick/pass */ - bot_send_cmdv(bot, "PASS %s", uplink->password); - bot_send_cmdv(bot, "NICK %s", botnet->nick); -} - -void botnet_connect(BOTNET_REC *botnet) -{ - BOT_REC *bot; - BOT_UPLINK_REC *uplink, *best; - GSList *tmp; - time_t now; - - g_return_if_fail(botnet != NULL); - - botnet->reconnect = FALSE; - if (botnet->bots == NULL) { - /* create bot record for us */ - bot = g_new0(BOT_REC, 1); - bot->botnet = botnet; - bot->nick = g_strdup(botnet->nick); - bot->priority = botnet->priority; - bot->connected = TRUE; - bot->master = TRUE; - - bot->read_tag = -1; - - botnet->connected = TRUE; - botnet->master = bot; - - botnet->bots = g_node_new(bot); - } - - if (botnet->listen_handle == NULL) { - /* start listening */ - botnet_listen(botnet); - } - - if (botnet->uplinks == NULL) { - /* we have no uplinks */ - return; - } - - /* find some bot where we can try to connect to */ - now = time(NULL); - uplink = best = NULL; - for (tmp = botnet->uplinks; tmp != NULL; tmp = tmp->next) { - uplink = tmp->data; - - if (uplink->last_connect+BOTNET_RECONNECT_TIME > now) - continue; - - if (uplink->last_connect == 0) { - /* haven't yet tried to connect to this bot */ - best = uplink; - break; - } - - if (best == NULL || uplink->last_connect < best->last_connect) - best = uplink; - } - - if (best == NULL) { - /* reconnect later */ - botnet->reconnect = TRUE; - return; - } - - /* connect to uplink */ - best->last_connect = time(NULL); - net_connect_nonblock(best->host, best->port, NULL, (NET_CALLBACK) sig_botnet_connected, best); -} - -static int botnet_send_botinfo(GNode *node, BOT_REC *client) -{ - BOT_REC *parent, *bot; - - bot = node->data; - parent = node->parent == NULL ? NULL : node->parent->data; - if (parent == NULL && client->uplink) parent = client; - - bot_send_cmdv(client, "%s - BOTINFO %s %s %d", bot->botnet->nick, bot->nick, - parent != NULL ? parent->nick : "-", bot->priority); - return FALSE; -} - -/* send botnet links to specified bot */ -static void botnet_send_links(BOT_REC *bot, int downlinks) -{ - GNode *node; - - if (!downlinks) { - /* send uplinks */ - if (bot->botnet->uplink == NULL) - return; - - node = g_node_find(bot->botnet->bots, G_IN_ORDER, - G_TRAVERSE_ALL, bot->botnet->uplink); - if (node == NULL) - return; - - g_node_traverse(node, G_LEVEL_ORDER, G_TRAVERSE_ALL, -1, - (GNodeTraverseFunc) botnet_send_botinfo, bot); - return; - } - - /* send downlinks = all non-uplink nodes */ - for (node = bot->botnet->bots->children; node != NULL; node = node->next) { - BOT_REC *rec = node->data; - - if (rec == bot || rec->uplink || !rec->connected) - continue; - - g_node_traverse(node, G_LEVEL_ORDER, G_TRAVERSE_ALL, -1, - (GNodeTraverseFunc) botnet_send_botinfo, bot); - } -} - -static void botnet_connect_event_uplink(BOT_REC *bot, const char *data) -{ - BOTNET_REC *botnet; - BOT_REC *ownbot; - char *str, *p; - int num; - - botnet = bot->botnet; - g_return_if_fail(botnet != NULL); - - if (g_strcasecmp(data, "NICKERROR") == 0) { - /* nick already in use, change it by adding a number - at the end of it */ - p = botnet->nick+strlen(botnet->nick); - while (p > botnet->nick && i_isdigit(p[-1])) p--; - num = *p == '\0' ? 2 : atoi(p)+1; *p = '\0'; - str = g_strdup_printf("%s%d", botnet->nick, num); - g_free(botnet->nick); botnet->nick = str; - - ownbot = botnet->bots->data; - g_free(ownbot->nick); ownbot->nick = g_strdup(str); - - /* try again.. */ - bot_send_cmdv(bot, "NICK %s", botnet->nick); - - return; - } - - if (g_strcasecmp(data, "CONNECTED") == 0) { - /* connected, wait for SYNC command */ - bot->connected = TRUE; - return; - } - - /* error? what? */ -} - -static void botnet_event(BOT_REC *bot, const char *data) -{ - BOT_DOWNLINK_REC *downlink; - char *fname; - - g_return_if_fail(bot != NULL); - g_return_if_fail(data != NULL); - - if (bot->connected) - return; - - signal_stop_by_name("botnet event"); - - if (bot->uplink) { - botnet_connect_event_uplink(bot, data); - return; - } - - downlink = bot->link; - - if (!bot->pass_ok && g_strncasecmp(data, "PASS ", 5) == 0) { - /* password sent, check that it matches */ - if (strcmp(data+5, downlink->password) == 0) { - /* ok, connected! */ - bot->pass_ok = TRUE; - } else { - /* wrong password, disconnect */ - bot_disconnect(bot); - } - return; - } - - if (g_strncasecmp(data, "NICK ", 5) == 0) { - /* set bot's nick */ - if (!bot->pass_ok) { - /* password has to be sent before nick, kill the - stupid bot. */ - bot_disconnect(bot); - return; - } - - if (g_strcasecmp(bot->botnet->nick, data+5) == 0 || - bot_find_nick(bot->botnet, data+5) != NULL) { - /* nick already exists */ - bot_send_cmd(bot, "NICKERROR"); - return; - } - - /* set the nick */ - bot->nick = g_strdup(data+5); - bot->connected = TRUE; - bot_send_cmd(bot, "CONNECTED"); - - /* send info about all the bots that are connected now - to this botnet */ - botnet_send_botinfo(bot->botnet->bots, bot); - botnet_send_links(bot, FALSE); - botnet_send_links(bot, TRUE); - bot_send_cmdv(bot, "%s - MASTER %s", bot->botnet->nick, bot->botnet->master->nick); - - /* send our current user configuration */ - fname = g_strdup_printf("%s/users.temp", get_irssi_dir()); - botuser_save(fname); - botnet_send_file(bot->botnet, bot->nick, fname); - g_free(fname); - - /* send sync msg */ - bot_send_cmdv(bot, "%s - SYNC", bot->botnet->nick); - return; - } - - /* pass/nick not sent yet */ - bot_send_cmd(bot, "ERROR"); -} - -static void botnet_event_sync(BOT_REC *bot) -{ - /* send our record to host */ - botnet_send_botinfo(bot->botnet->bots, bot); - - /* send our downlinks to host */ - botnet_send_links(bot, TRUE); - - signal_stop_by_name("botnet event"); -} - -static BOT_REC *bot_add(BOTNET_REC *botnet, const char *nick, const char *parent) -{ - GNode *node; - BOT_REC *rec; - - g_return_val_if_fail(botnet != NULL, NULL); - g_return_val_if_fail(nick != NULL, NULL); - - node = bot_find_nick(botnet, nick); - if (node != NULL) return node->data; - - node = bot_find_nick(botnet, parent); - if (node == NULL) return NULL; - - rec = g_new0(BOT_REC, 1); - rec->botnet = botnet; - rec->nick = g_strdup(nick); - - rec->read_tag = -1; - rec->connected = TRUE; - - g_node_append_data(node, rec); - return rec; -} - -static void botnet_event_botinfo(BOT_REC *bot, const char *data, const char *sender) -{ - char *nick, *parent, *priority; - void *free_arg; - BOT_REC *rec; - - /*str = g_strdup_printf("BOTINFO %s", data); - botnet_broadcast(bot->botnet, bot, sender, str); - g_free(str);*/ - - if (!cmd_get_params(data, &free_arg, 3, &nick, &parent, &priority)) - return; - if (*parent == '-' && parent[1] == '\0') - parent = NULL; - - if (parent == NULL && bot->botnet->uplink != NULL && - bot->botnet->uplink == bot) { - /* our uplink */ - if (bot->nick == NULL) bot->nick = g_strdup(nick); - rec = bot; - } else { - rec = bot_add(bot->botnet, nick, parent); - } - - if (rec != NULL) { - rec->priority = atoi(priority); - } - cmd_params_free(free_arg); -} - -static void botnet_event_botquit(BOT_REC *bot, const char *data) -{ - GNode *node; - - node = bot_find_nick(bot->botnet, data); - if (node != NULL) bot_destroy(node->data); - - signal_stop_by_name("botnet event"); -} - -static void sig_bot_disconnected(BOT_REC *bot) -{ - BOT_REC *master, *tmpbot; - GNode *node; - char *str; - - if (!bot->botnet->connected) - return; - - if (bot->connected && bot->handle != NULL) { - /* send notice to rest of the botnet about quit */ - str = g_strdup_printf("BOTQUIT %s", bot->nick); - botnet_broadcast(bot->botnet, bot, NULL, str); - g_free(str); - } - - if (bot->master) { - /* master quit */ - node = bot_find_path(bot->botnet, bot->nick); - tmpbot = node == NULL ? NULL : node->data; - - if (tmpbot != NULL && tmpbot->disconnect) { - /* we lost the connection to master - find new - master for the botnet*/ - master = botnet_find_master(bot->botnet, NULL); - botnet_set_master(bot->botnet, master); - - str = g_strdup_printf("MASTER %s", master->nick); - botnet_broadcast(bot->botnet, bot, NULL, str); - g_free(str); - } - } -} - -static int print_bot(GNode *node) -{ - BOT_REC *bot = node->data; - - fprintf(stderr, "%s %d %d\r\n", bot->nick, bot->connected, bot->disconnect); - return FALSE; -} - -static void cmd_bots(void) -{ - BOTNET_REC *botnet = botnet_find("ircnet"); - - fprintf(stderr, "\r\n"); - g_node_traverse(botnet->bots, G_LEVEL_ORDER, G_TRAVERSE_ALL, -1, - (GNodeTraverseFunc) print_bot, NULL); -} - -void botnet_connection_init(void) -{ - reconnect_tag = g_timeout_add(BOTNET_RECONNECT_TIME*1000, (GSourceFunc) sig_reconnect, NULL); - - signal_add("botnet event", (SIGNAL_FUNC) botnet_event); - signal_add("botnet event sync", (SIGNAL_FUNC) botnet_event_sync); - signal_add("botnet event botinfo", (SIGNAL_FUNC) botnet_event_botinfo); - signal_add("botnet event botquit", (SIGNAL_FUNC) botnet_event_botquit); - signal_add("bot disconnected", (SIGNAL_FUNC) sig_bot_disconnected); - command_bind("bots", NULL, (SIGNAL_FUNC) cmd_bots); -} - -void botnet_connection_deinit(void) -{ - g_source_remove(reconnect_tag); - - signal_remove("botnet event", (SIGNAL_FUNC) botnet_event); - signal_remove("botnet event sync", (SIGNAL_FUNC) botnet_event_sync); - signal_remove("botnet event botinfo", (SIGNAL_FUNC) botnet_event_botinfo); - signal_remove("botnet event botquit", (SIGNAL_FUNC) botnet_event_botquit); - signal_remove("bot disconnected", (SIGNAL_FUNC) sig_bot_disconnected); - command_unbind("bots", (SIGNAL_FUNC) cmd_bots); -} diff --git a/src/irc/bot/botnet-users.c b/src/irc/bot/botnet-users.c deleted file mode 100644 index 9369a2a1..00000000 --- a/src/irc/bot/botnet-users.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - botnet-users.c : IRC bot plugin for irssi - - Copyright (C) 1999-2000 Timo Sirainen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "module.h" -#include "signals.h" -#include "commands.h" - -#include "irc.h" -#include "irc-servers.h" -#include "channels.h" -#include "nicklist.h" -#include "masks.h" - -#include "bot-users.h" -#include "botnet.h" - -void botcmd_user_add(const char *nick) -{ - char *str; - - botuser_add(nick); - - str = g_strdup_printf("USER_ADD %s", nick); - botnet_broadcast(NULL, NULL, NULL, str); - g_free(str); -} - -void botcmd_user_set_flags(USER_REC *user, int flags) -{ - char *str, *flagstr; - - botuser_set_flags(user, flags); - - flagstr = botuser_value2flags(flags); - str = g_strdup_printf("USER_FLAGS %s %s", user->nick, flagstr); - g_free(flagstr); - - botnet_broadcast(NULL, NULL, NULL, str); - g_free(str); -} - -void botcmd_user_set_channel_flags(USER_REC *user, const char *channel, int flags) -{ - char *str, *flagstr; - - botuser_set_channel_flags(user, channel, flags); - - flagstr = botuser_value2flags(flags); - str = g_strdup_printf("USER_CHAN_FLAGS %s %s %s", user->nick, channel, flagstr); - g_free(flagstr); - - botnet_broadcast(NULL, NULL, NULL, str); - g_free(str); -} - -void botcmd_user_add_mask(USER_REC *user, const char *mask) -{ - char *str; - - botuser_add_mask(user, mask); - - str = g_strdup_printf("USER_ADD_MASK %s %s", user->nick, mask); - botnet_broadcast(NULL, NULL, NULL, str); - g_free(str); -} - -void botcmd_user_set_mask_notflags(USER_REC *user, const char *mask, int not_flags) -{ - char *str, *flagstr; - - botuser_set_mask_notflags(user, mask, not_flags); - - flagstr = botuser_value2flags(not_flags); - str = g_strdup_printf("USER_MASK_NOTFLAGS %s %s %s", user->nick, mask, flagstr); - g_free(flagstr); - - botnet_broadcast(NULL, NULL, NULL, str); - g_free(str); -} - -void botcmd_user_set_password(USER_REC *user, const char *password) -{ - char *str; - - botuser_set_password(user, password); - - str = g_strdup_printf("USER_PASS %s %s", user->nick, password); - botnet_broadcast(NULL, NULL, NULL, str); - g_free(str); -} - -static void botnet_event_user_add(BOT_REC *bot, const char *data, const char *sender) -{ - char *nick; - void *free_arg; - - if (!cmd_get_params(data, &free_arg, 1, &nick)) - return; - - botuser_add(nick); - cmd_params_free(free_arg); -} - -static void botnet_event_user_flags(BOT_REC *bot, const char *data, const char *sender) -{ - USER_REC *user; - char *nick, *flags; - void *free_arg; - - if (!cmd_get_params(data, &free_arg, 2, &nick, &flags)) - return; - - user = botuser_find(nick, NULL); - if (user == NULL) user = botuser_add(nick); - botuser_set_flags(user, botuser_flags2value(flags)); - - cmd_params_free(free_arg); -} - -static void botnet_event_user_chan_flags(BOT_REC *bot, const char *data, const char *sender) -{ - USER_REC *user; - char *nick, *channel, *flags; - void *free_arg; - - if (!cmd_get_params(data, &free_arg, 3, &nick, &channel, &flags)) - return; - - user = botuser_find(nick, NULL); - if (user == NULL) user = botuser_add(nick); - botuser_set_channel_flags(user, channel, botuser_flags2value(flags)); - - cmd_params_free(free_arg); -} - -static void botnet_event_user_add_mask(BOT_REC *bot, const char *data, const char *sender) -{ - USER_REC *user; - char *nick, *mask; - void *free_arg; - - if (!cmd_get_params(data, &free_arg, 2, &nick, &mask)) - return; - - user = botuser_find(nick, NULL); - if (user == NULL) user = botuser_add(nick); - botuser_add_mask(user, mask); - - cmd_params_free(free_arg); -} - -static void botnet_event_user_mask_notflags(BOT_REC *bot, const char *data, const char *sender) -{ - USER_REC *user; - char *nick, *mask, *not_flags; - void *free_arg; - - if (!cmd_get_params(data, &free_arg, 3, &nick, &mask, ¬_flags)) - return; - - user = botuser_find(nick, NULL); - if (user == NULL) user = botuser_add(nick); - botuser_set_mask_notflags(user, mask, botuser_flags2value(not_flags)); - - cmd_params_free(free_arg); -} - -static void botnet_event_user_pass(BOT_REC *bot, const char *data, const char *sender) -{ - USER_REC *user; - char *nick, *pass; - void *free_arg; - - if (!cmd_get_params(data, &free_arg, 2, &nick, &pass)) - return; - - user = botuser_find(nick, NULL); - if (user == NULL) user = botuser_add(nick); - botuser_set_password(user, pass); - - cmd_params_free(free_arg); -} - -void botnet_users_init(void) -{ - signal_add("botnet event user_add", (SIGNAL_FUNC) botnet_event_user_add); - signal_add("botnet event user_flags", (SIGNAL_FUNC) botnet_event_user_flags); - signal_add("botnet event user_chan_flags", (SIGNAL_FUNC) botnet_event_user_chan_flags); - signal_add("botnet event user_add_mask", (SIGNAL_FUNC) botnet_event_user_add_mask); - signal_add("botnet event user_mask_notflags", (SIGNAL_FUNC) botnet_event_user_mask_notflags); - signal_add("botnet event user_pass", (SIGNAL_FUNC) botnet_event_user_pass); -} - -void botnet_users_deinit(void) -{ - signal_remove("botnet event user_add", (SIGNAL_FUNC) botnet_event_user_add); - signal_remove("botnet event user_flags", (SIGNAL_FUNC) botnet_event_user_flags); - signal_remove("botnet event user_chan_flags", (SIGNAL_FUNC) botnet_event_user_chan_flags); - signal_remove("botnet event user_add_mask", (SIGNAL_FUNC) botnet_event_user_add_mask); - signal_remove("botnet event user_mask_notflags", (SIGNAL_FUNC) botnet_event_user_mask_notflags); - signal_remove("botnet event user_pass", (SIGNAL_FUNC) botnet_event_user_pass); -} diff --git a/src/irc/bot/botnet-users.h b/src/irc/bot/botnet-users.h deleted file mode 100644 index 303a0890..00000000 --- a/src/irc/bot/botnet-users.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __BOTNET_USERS_H -#define __BOTNET_USERS_H - -void botcmd_user_add(const char *nick); -void botcmd_user_set_flags(USER_REC *user, int flags); -void botcmd_user_set_channel_flags(USER_REC *user, const char *channel, int flags); - -void botcmd_user_add_mask(USER_REC *user, const char *mask); -void botcmd_user_set_mask_notflags(USER_REC *user, const char *mask, int not_flags); - -void botcmd_user_set_password(USER_REC *user, const char *password); - -#endif diff --git a/src/irc/bot/botnet.c b/src/irc/bot/botnet.c deleted file mode 100644 index 3eb038e5..00000000 --- a/src/irc/bot/botnet.c +++ /dev/null @@ -1,827 +0,0 @@ -/* - botnet.c : IRC bot plugin for irssi - - Copyright (C) 1999-2000 Timo Sirainen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "module.h" -#include "network.h" -#include "net-nonblock.h" -#include "signals.h" -#include "commands.h" -#include "misc.h" -#include "line-split.h" -#include "lib-config/iconfig.h" - -#include "botnet.h" - -void botnet_connection_init(void); -void botnet_connection_deinit(void); - -void botnet_users_deinit(void); -void botnet_users_init(void); - -GSList *botnets; - -void bot_send_cmd(BOT_REC *bot, const char *data) -{ - g_return_if_fail(bot != NULL); - g_return_if_fail(data != NULL); - - net_transmit(bot->handle, data, strlen(data)); - net_transmit(bot->handle, "\n", 1); -} - -void bot_send_cmdv(BOT_REC *bot, const char *format, ...) -{ - va_list args; - char *str; - - va_start(args, format); - - str = g_strdup_vprintf(format, args); - bot_send_cmd(bot, str); - g_free(str); - - va_end(args); -} - -static void botnet_broadcast_single(BOTNET_REC *botnet, BOT_REC *except_bot, - const char *source, const char *data) -{ - GNode *node; - char *str; - - g_return_if_fail(botnet != NULL); - g_return_if_fail(data != NULL); - - str = g_strdup_printf("%s - %s", source != NULL ? source : - botnet->nick, data); - for (node = botnet->bots->children; node != NULL; node = node->next) { - BOT_REC *rec = node->data; - - if (rec != except_bot && rec->handle != NULL) - bot_send_cmd(rec, str); - } - g_free(str); -} - -/* broadcast a message to everyone in bot network, except for `except_bot' - if it's not NULL. If botnet is NULL, the message is sent to all botnets. */ -void botnet_broadcast(BOTNET_REC *botnet, BOT_REC *except_bot, - const char *source, const char *data) -{ - GSList *tmp; - - g_return_if_fail(data != NULL); - - if (botnet != NULL) { - botnet_broadcast_single(botnet, except_bot, source, data); - return; - } - - /* broadcast to all botnets */ - for (tmp = botnets; tmp != NULL; tmp = tmp->next) { - BOTNET_REC *rec = tmp->data; - - botnet_broadcast_single(rec, except_bot, source, data); - } -} - -void botnet_send_cmd(BOTNET_REC *botnet, const char *source, - const char *target, const char *data) -{ - GNode *node; - char *str; - - g_return_if_fail(botnet != NULL); - g_return_if_fail(target != NULL); - g_return_if_fail(data != NULL); - - node = bot_find_path(botnet, target); - if (node == NULL) { - g_warning("Can't find route for target %s", target); - return; - } - - str = g_strdup_printf("%s %s %s", source != NULL ? source : - botnet->nick, target, data); - bot_send_cmd(node->data, str); - g_free(str); -} - -static void escape_buffer(char *buffer, int len) -{ - char *dest, *tempbuf, *p; - - dest = buffer; - tempbuf = p = g_malloc(len*2+2); - while (len > 0) { - if (*buffer == '\0') { - *p++ = '\\'; - *p++ = '0'; - } else if (*buffer == '\r') { - *p++ = '\\'; - *p++ = 'r'; - } else if (*buffer == '\n') { - *p++ = '\\'; - *p++ = 'n'; - } else if (*buffer == '\\') { - *p++ = '\\'; - *p++ = '\\'; - } else { - *p++ = *buffer; - } - len--; buffer++; - } - *p++ = '\0'; - - len = (int) (p-tempbuf); - memcpy(dest, tempbuf, len); - g_free(tempbuf); -} - -int botnet_send_file(BOTNET_REC *botnet, const char *target, const char *fname) -{ - GNode *node; - GString *str; - char buffer[1024]; - int f, len; - - node = bot_find_path(botnet, target); - if (node == NULL) { - g_warning("Can't find route for target %s", target); - return FALSE; - } - - f = open(fname, O_RDONLY); - if (f == -1) return FALSE; - - str = g_string_new(NULL); - - g_string_sprintf(str, "%s %s FILE %s", botnet->nick, target, g_basename(fname)); - bot_send_cmd(node->data, str->str); - - while ((len = read(f, buffer, sizeof(buffer)/2-2)) > 0) { - escape_buffer(buffer, len); - - g_string_sprintf(str, "%s %s FILE %s", botnet->nick, target, buffer); - bot_send_cmd(node->data, str->str); - } - - g_string_sprintf(str, "%s %s FILE", botnet->nick, target); - bot_send_cmd(node->data, str->str); - g_string_free(str, TRUE); - - close(f); - return TRUE; -} - -BOTNET_REC *botnet_find(const char *name) -{ - GSList *tmp; - - g_return_val_if_fail(name != NULL, NULL); - - for (tmp = botnets; tmp != NULL; tmp = tmp->next) { - BOTNET_REC *rec = tmp->data; - - if (g_strcasecmp(rec->name, name) == 0) - return rec; - } - - return NULL; -} - -typedef struct { - gconstpointer key; - int priority; - GNode *node; -} BOT_FIND_REC; - -static int gnode_find_nick(GNode *node, BOT_FIND_REC *rec) -{ - BOT_REC *bot = node->data; - - if (bot == NULL) return FALSE; - - if (bot->nick != NULL && g_strcasecmp(bot->nick, rec->key) == 0) { - rec->node = node; - return TRUE; - } - - return FALSE; -} - -GNode *bot_find_nick(BOTNET_REC *botnet, const char *nick) -{ - BOT_FIND_REC rec; - - g_return_val_if_fail(botnet != NULL, NULL); - g_return_val_if_fail(nick != NULL, NULL); - - rec.key = nick; - rec.node = NULL; - g_node_traverse(botnet->bots, 0, G_TRAVERSE_ALL, -1, - (GNodeTraverseFunc) gnode_find_nick, &rec); - return rec.node; -} - -/* Return the bot who we should send the message if we wanted `nick' to get it. */ -GNode *bot_find_path(BOTNET_REC *botnet, const char *nick) -{ - BOT_FIND_REC rec; - GNode *node; - - g_return_val_if_fail(botnet != NULL, NULL); - g_return_val_if_fail(nick != NULL, NULL); - - rec.key = nick; - rec.node = NULL; - for (node = botnet->bots->children; node != NULL; node = node->next) { - g_node_traverse(node, 0, G_TRAVERSE_ALL, -1, - (GNodeTraverseFunc) gnode_find_nick, &rec); - if (rec.node != NULL) return node; - } - return rec.node; -} - -/* check if `addr' is an IP address - this is checked to make sure that - if we have an address like "192.168.0.*", it wouldn't match to host name - 192.168.0.host.org */ -static int is_ip_mask(const char *addr) -{ - while (*addr != '\0') { - if (!i_isdigit(*addr) && *addr != '.' && - *addr != '*' && *addr != '?') return FALSE; - addr++; - } - - return TRUE; -} - -BOT_DOWNLINK_REC *bot_downlink_find(BOTNET_REC *botnet, IPADDR *ip, const char *host) -{ - GSList *tmp, *tmp2; - char ipname[MAX_IP_LEN]; - - g_return_val_if_fail(botnet != NULL, NULL); - g_return_val_if_fail(ip != NULL, NULL); - - net_ip2host(ip, ipname); - - for (tmp = botnet->downlinks; tmp != NULL; tmp = tmp->next) { - BOT_DOWNLINK_REC *rec = tmp->data; - - for (tmp2 = rec->valid_addrs; tmp2 != NULL; tmp2 = tmp2->next) { - if (match_wildcards(tmp2->data, ipname)) - return rec; - if (match_wildcards(tmp2->data, host) && - !is_ip_mask(tmp2->data)) - return rec; - } - } - - return NULL; -} - -static int gnode_find_master(GNode *node, BOT_FIND_REC *rec) -{ - BOT_REC *bot = node->data; - - if (bot == NULL) return FALSE; - - if (!bot->disconnect && bot->priority > rec->priority) { - rec->node = node; - return TRUE; - } - - return FALSE; -} - -BOT_REC *botnet_find_master(BOTNET_REC *botnet, BOT_REC *old_master) -{ - BOT_FIND_REC rec; - - g_return_val_if_fail(botnet != NULL, NULL); - - rec.node = NULL; - rec.priority = old_master == NULL ? -1 : old_master->priority; - g_node_traverse(botnet->bots, 0, G_TRAVERSE_ALL, -1, - (GNodeTraverseFunc) gnode_find_master, &rec); - return rec.node == NULL ? old_master : rec.node->data; -} - -void botnet_set_master(BOTNET_REC *botnet, BOT_REC *bot) -{ - g_return_if_fail(botnet != NULL); - g_return_if_fail(bot != NULL); - - if (botnet->master != NULL) - botnet->master->master = FALSE; - - bot->master = TRUE; - botnet->master = bot; -} - -void bot_nick_destroy(BOT_CHANNEL_REC *rec, NICK_REC *nick) -{ - g_return_if_fail(rec != NULL); - g_return_if_fail(nick != NULL); - - rec->nicks = g_slist_remove(rec->nicks, nick); - - g_free(nick->nick); - g_free_not_null(nick->realname); - g_free_not_null(nick->host); - g_free(nick); -} - -void bot_channel_destroy(BOT_IRCNET_REC *ircnet, BOT_CHANNEL_REC *rec) -{ - g_return_if_fail(ircnet != NULL); - g_return_if_fail(rec != NULL); - - ircnet->channels = g_slist_remove(ircnet->channels, rec); - - while (rec->nicks != NULL) - bot_nick_destroy(rec, rec->nicks->data); - - g_slist_foreach(rec->banlist, (GFunc) g_free, NULL); - g_slist_foreach(rec->ebanlist, (GFunc) g_free, NULL); - g_slist_foreach(rec->invitelist, (GFunc) g_free, NULL); - - g_slist_free(rec->banlist); - g_slist_free(rec->ebanlist); - g_slist_free(rec->invitelist); - - g_free_not_null(rec->mode); - g_free_not_null(rec->key); - g_free(rec->name); - g_free(rec); -} - -void bot_ircnet_destroy(BOT_REC *bot, BOT_IRCNET_REC *rec) -{ - g_return_if_fail(bot != NULL); - g_return_if_fail(rec != NULL); - - bot->ircnets = g_slist_remove(bot->ircnets, bot); - - while (rec->channels != NULL) - bot_channel_destroy(rec, rec->channels->data); - - g_free(rec->tag); - g_free(rec->ircnet); - g_free(rec->server); - g_free(rec->nick); - g_free(rec); -} - -void bot_disconnect(BOT_REC *bot) -{ - bot->disconnect = TRUE; - - signal_emit("bot disconnected", 1, bot); - - if (bot->read_tag != -1) { - g_source_remove(bot->read_tag); - bot->read_tag = -1; - } - if (bot->handle != NULL) { - net_disconnect(bot->handle); - bot->handle = NULL; - } -} - -static void bot_mark_disconnect(GNode *node) -{ - BOT_REC *bot = node->data; - - bot->disconnect = TRUE; -} - -#define bot_mark_disconnects(node) \ - g_node_traverse(node, G_LEVEL_ORDER, G_TRAVERSE_ALL, -1, \ - (GNodeTraverseFunc) bot_mark_disconnect, NULL) - -void bot_destroy(BOT_REC *bot) -{ - GNode *node; - - g_return_if_fail(bot != NULL); - - node = g_node_find(bot->botnet->bots, 0, G_TRAVERSE_ALL, bot); - if (node != NULL) { - if (!bot->disconnect) - bot_mark_disconnects(node); - } - - bot_disconnect(bot); - - if (node != NULL) { - while (node->children != NULL) - bot_destroy(node->children->data); - g_node_destroy(node); - } - - if (bot->botnet->uplink == bot) - bot->botnet->uplink = NULL; - if (bot->botnet->master == bot) - bot->botnet->master = NULL; - - while (bot->ircnets != NULL) - bot_ircnet_destroy(bot, bot->ircnets->data); - - line_split_free(bot->buffer); - g_free_not_null(bot->nick); - g_free(bot); -} - -void bot_downlink_destroy(BOT_DOWNLINK_REC *rec) -{ - rec->botnet->downlinks = g_slist_remove(rec->botnet->downlinks, rec); - - g_slist_foreach(rec->valid_addrs, (GFunc) g_free, NULL); - g_slist_free(rec->valid_addrs); - - g_free_not_null(rec->password); - g_free(rec); -} - -void bot_uplink_destroy(BOT_UPLINK_REC *rec) -{ - rec->botnet->uplinks = g_slist_remove(rec->botnet->uplinks, rec); - - g_free(rec->host); - g_free_not_null(rec->password); - g_free(rec); -} - -void botnet_disconnect(BOTNET_REC *botnet) -{ - botnet->connected = FALSE; - - bot_destroy(botnet->bots->data); - botnet->bots = NULL; - - if (botnet->listen_tag != -1) { - g_source_remove(botnet->listen_tag); - botnet->listen_tag = -1; - } - if (botnet->listen_handle != NULL) { - net_disconnect(botnet->listen_handle); - botnet->listen_handle = NULL; - } -} - -static void botnet_destroy(BOTNET_REC *botnet) -{ - botnets = g_slist_remove(botnets, botnet); - - while (botnet->uplinks != NULL) - bot_uplink_destroy(botnet->uplinks->data); - while (botnet->downlinks != NULL) - bot_downlink_destroy(botnet->downlinks->data); - - botnet_disconnect(botnet); - - g_free_not_null(botnet->addr); - g_free(botnet->name); - g_free(botnet->nick); - g_free(botnet); -} - -static void botnet_event(BOT_REC *bot, const char *data) -{ - char *source, *target, *command, *args, *event; - void *free_arg; - - if (!bot->connected) - return; - - if (!cmd_get_params(data, &free_arg, 4 | PARAM_FLAG_GETREST, - &source, &target, &command, &args)) - return; - - if (*target == '-' && target[1] == '\0') - target = NULL; - g_strdown(command); - - event = g_strconcat("botnet event ", command, NULL); - signal_emit(event, 4, bot, args, source, target); - g_free(event); - - cmd_params_free(free_arg); -} - -/* broadcast the signal forward */ -static void botnet_event_broadcast(BOT_REC *bot, const char *data) -{ - char *source, *target, *command; - void *free_arg; - - if (!bot->connected) - return; - - if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, - &source, &target, &command)) - return; - - if (g_strcasecmp(target, bot->botnet->nick) == 0) { - /* message was for us */ - cmd_params_free(free_arg); - return; - } - - if (*target == '-' && target[1] == '\0') { - /* broadcast */ - botnet_broadcast(bot->botnet, bot, source, command); - } else { - /* send to specified target */ - botnet_send_cmd(bot->botnet, source, target, command); - } - - cmd_params_free(free_arg); -} - -static void botnet_event_master(BOT_REC *bot, const char *data, const char *sender) -{ - BOTNET_REC *botnet; - BOT_REC *master; - GNode *node; - char *str; - - botnet = bot->botnet; - - node = bot_find_nick(bot->botnet, data); - master = node == NULL ? NULL : node->data; - master = botnet_find_master(bot->botnet, master); - g_return_if_fail(master != NULL); - - if (node == NULL || node->data != master) { - /* no, we don't agree with that master - - send our own to everyone. */ - bot = NULL; - } - - botnet_set_master(botnet, master); - - str = g_strdup_printf("MASTER %s", master->nick); - botnet_broadcast(botnet, bot, sender, str); - g_free(str); - - signal_stop_by_name("botnet event"); -} - -static int unescape_data(const char *input, char *output) -{ - int len; - - len = 0; - while (*input != '\0') { - if (*input != '\\') - *output++ = *input; - else { - input++; - g_return_val_if_fail(*input != '\0', len); - switch (*input) { - case '\\': - *output++ = '\\'; - break; - case '0': - *output++ = '\0'; - break; - case 'r': - *output++ = '\r'; - break; - case 'n': - *output++ = '\n'; - break; - } - } - input++; - len++; - } - - return len; -} - -static void botnet_event_file(BOT_REC *bot, const char *data, const char *sender, const char *target) -{ - GNode *node; - char *tempbuf, *str; - int len; - - if (g_strcasecmp(target, bot->botnet->nick) != 0) - return; - - node = bot_find_nick(bot->botnet, sender); - g_return_if_fail(node != NULL); - - bot = node->data; - if (bot->file_handle <= 0) { - /* first line - data contains file name */ - str = g_strdup_printf("%s/%s", get_irssi_dir(), data); - bot->file_handle = open(str, O_CREAT|O_TRUNC|O_WRONLY, 0600); - g_free(str); - } else if (*data == '\0') { - /* no data - end of file */ - if (bot->file_handle > 0) { - close(bot->file_handle); - bot->file_handle = -1; - } - } else { - /* file data */ - tempbuf = g_malloc(strlen(data)*2+2); - len = unescape_data(data, tempbuf); - write(bot->file_handle, tempbuf, len); - g_free(tempbuf); - } -} - -static void botnet_config_read_ips(BOT_DOWNLINK_REC *rec, CONFIG_NODE *node) -{ - GSList *tmp; - - g_return_if_fail(rec != NULL); - g_return_if_fail(node != NULL); - - node = config_node_section(node, "valid_addrs", -1); - tmp = node == NULL ? NULL : node->value; - for (; tmp != NULL; tmp = tmp->next) { - node = tmp->data; - rec->valid_addrs = g_slist_append(rec->valid_addrs, g_strdup(node->value)); - } -} - -static void botnet_config_read_uplink(BOTNET_REC *botnet, CONFIG_NODE *node) -{ - BOT_UPLINK_REC *rec; - char *value; - - g_return_if_fail(botnet != NULL); - g_return_if_fail(node != NULL); - - value = config_node_get_str(node, "host", NULL); - if (value == NULL) return; /* host required */ - - rec = g_new0(BOT_UPLINK_REC, 1); - rec->botnet = botnet; - rec->host = g_strdup(value); - rec->port = config_node_get_int(node, "port", DEFAULT_BOTNET_PORT); - rec->password = g_strdup(config_node_get_str(node, "password", NULL)); - - botnet->uplinks = g_slist_append(botnet->uplinks, rec); -} - -static void botnet_config_read_downlink(BOTNET_REC *botnet, CONFIG_NODE *node) -{ - BOT_DOWNLINK_REC *rec; - - g_return_if_fail(botnet != NULL); - g_return_if_fail(node != NULL); - - rec = g_new0(BOT_DOWNLINK_REC, 1); - - botnet_config_read_ips(rec, node); - if (rec->valid_addrs == NULL) { - g_free(rec); - return; - } - - rec->botnet = botnet; - rec->password = g_strdup(config_node_get_str(node, "password", NULL)); - botnet->downlinks = g_slist_append(botnet->downlinks, rec); -} - -static void botnet_config_read_botnet(CONFIG_NODE *node) -{ - CONFIG_NODE *subnode; - BOTNET_REC *botnet; - GSList *tmp; - - g_return_if_fail(node != NULL); - - if (node->key == NULL || node->value == NULL) - return; - - /* New botnet */ - botnet = g_new0(BOTNET_REC, 1); - botnet->name = g_strdup(node->key); - botnet->nick = g_strdup(config_node_get_str(node, "nick", "bot")); - botnet->priority = config_node_get_int(node, "priority", DEFAULT_BOTNET_PRIORITY); - botnet->autoconnect = config_node_get_bool(node, "autoconnect", FALSE); - - botnet->addr = g_strdup(config_node_get_str(node, "listen_addr", NULL)); - botnet->port = config_node_get_int(node, "listen_port", DEFAULT_BOTNET_PORT); - - botnet->listen_tag = -1; - - /* read uplinks */ - subnode = config_node_section(node, "uplinks", -1); - tmp = subnode == NULL ? NULL : subnode->value; - for (; tmp != NULL; tmp = tmp->next) - botnet_config_read_uplink(botnet, tmp->data); - - /* read downlinks */ - subnode = config_node_section(node, "downlinks", -1); - tmp = subnode == NULL ? NULL : subnode->value; - for (; tmp != NULL; tmp = tmp->next) - botnet_config_read_downlink(botnet, tmp->data); - - botnets = g_slist_append(botnets, botnet); -} - -static void botnet_config_read(void) -{ - CONFIG_REC *config; - CONFIG_NODE *node; - GSList *tmp; - char *fname; - - /* Read botnets from ~/.irssi/botnets */ - fname = g_strdup_printf("%s/botnets", get_irssi_dir()); - config = config_open(fname, -1); - g_free(fname); - - if (config == NULL) - return; - - config_parse(config); - - node = config_node_traverse(config, "botnets", FALSE); - tmp = node == NULL ? NULL : node->value; - for (; tmp != NULL; tmp = tmp->next) - botnet_config_read_botnet(tmp->data); - config_close(config); -} - -/* FIXME: this command is just temporary */ -static void cmd_botnet(const char *data) -{ - BOTNET_REC *botnet; - char *str; - - botnet = botnets->data; - - str = g_strdup_printf("BCAST %s", data); - botnet_broadcast(botnet, NULL, NULL, str); - g_free(str); -} - -static void autoconnect_botnets(void) -{ - GSList *tmp; - - for (tmp = botnets; tmp != NULL; tmp = tmp->next) { - BOTNET_REC *rec = tmp->data; - - if (rec->autoconnect) - botnet_connect(rec); - } -} - -void botnet_init(void) -{ - botnet_config_read(); - botnet_connection_init(); - botnet_users_init(); - - signal_add("botnet event", (SIGNAL_FUNC) botnet_event); - signal_add_last("botnet event", (SIGNAL_FUNC) botnet_event_broadcast); - signal_add("botnet event master", (SIGNAL_FUNC) botnet_event_master); - signal_add("botnet event file", (SIGNAL_FUNC) botnet_event_file); - command_bind("botnet", NULL, (SIGNAL_FUNC) cmd_botnet); - - autoconnect_botnets(); -} - -void botnet_deinit(void) -{ - while (botnets) - botnet_destroy(botnets->data); - - botnet_connection_deinit(); - botnet_users_deinit(); - - signal_remove("botnet event", (SIGNAL_FUNC) botnet_event); - signal_remove("botnet event", (SIGNAL_FUNC) botnet_event_broadcast); - signal_remove("botnet event master", (SIGNAL_FUNC) botnet_event_master); - signal_remove("botnet event file", (SIGNAL_FUNC) botnet_event_file); - command_unbind("botnet", (SIGNAL_FUNC) cmd_botnet); -} diff --git a/src/irc/bot/botnet.h b/src/irc/bot/botnet.h deleted file mode 100644 index 0372de22..00000000 --- a/src/irc/bot/botnet.h +++ /dev/null @@ -1,134 +0,0 @@ -#ifndef __BOT_BOTNET_H -#define __BOT_BOTNET_H - -#include "nicklist.h" - -#define DEFAULT_BOTNET_PORT 2255 -#define DEFAULT_BOTNET_PRIORITY 5 - -typedef struct _botnet_rec BOTNET_REC; - -typedef struct { - char *name; - GSList *nicks; /* NICK_RECs */ - unsigned int chanop:1; - - GSList *banlist; - GSList *ebanlist; - GSList *invitelist; - - char *mode; - int limit; - char *key; -} BOT_CHANNEL_REC; - -typedef struct { - char *tag; /* same as server->tag */ - char *ircnet; - char *server; - char *nick; - - GSList *channels; -} BOT_IRCNET_REC; - -typedef struct { - BOTNET_REC *botnet; - void *link; /* NULL, BOT_UPLINK_REC or BOT_DOWNLINK_REC */ - - unsigned int uplink:1; /* this is our uplink */ - unsigned int pass_ok:1; /* downlink's password was ok */ - unsigned int connected:1; /* bot is in this botnet now */ - unsigned int disconnect:1; /* just disconnecting this bot.. */ - unsigned int master:1; /* this bot is the bot network's current master */ - - char *nick; /* bot's unique nick in botnet */ - int priority; - - GIOChannel *handle; - int read_tag; - LINEBUF_REC *buffer; - - int file_handle; /* if bot is sending a file to us */ - - GSList *ircnets; -} BOT_REC; - -typedef struct { - BOTNET_REC *botnet; - - char *host; - int port; - char *password; - - time_t last_connect; -} BOT_UPLINK_REC; - -typedef struct { - BOTNET_REC *botnet; - - GSList *valid_addrs; /* IP/host masks where this bot is allowed to connect */ - char *password; -} BOT_DOWNLINK_REC; - -struct _botnet_rec { - unsigned int connected:1; - unsigned int autoconnect:1; - unsigned int reconnect:1; - - char *name; /* botnet name */ - char *nick; /* our nick in botnet */ - int priority; /* our priority in botnet */ - - char *addr; /* in what address we should listen, NULL = all */ - int port; /* what port we should listen, 0 = default, -1 = don't listen */ - - GIOChannel *listen_handle; - int listen_tag; - - GSList *uplinks; - GSList *downlinks; - - GNode *bots; - BOT_REC *uplink; /* our current uplink */ - BOT_REC *master; /* link to current master */ -}; - -extern GSList *botnets; - -void bot_send_cmd(BOT_REC *bot, const char *data); -void bot_send_cmdv(BOT_REC *bot, const char *format, ...); - -/* broadcast a message to everyone in bot network, except for `except_bot' - if it's not NULL. If botnet is NULL, the message is sent to all botnets. */ -void botnet_broadcast(BOTNET_REC *botnet, BOT_REC *except_bot, - const char *source, const char *data); - -void botnet_send_cmd(BOTNET_REC *botnet, const char *source, - const char *target, const char *data); - -int botnet_send_file(BOTNET_REC *botnet, const char *target, const char *fname); - -BOT_REC *botnet_find_master(BOTNET_REC *botnet, BOT_REC *old_master); -void botnet_set_master(BOTNET_REC *botnet, BOT_REC *bot); - -BOTNET_REC *botnet_find(const char *name); -GNode *bot_find_nick(BOTNET_REC *botnet, const char *nick); -/* Return the bot who we should send the message if we wanted `nick' to get it. */ -GNode *bot_find_path(BOTNET_REC *botnet, const char *nick); - -BOT_DOWNLINK_REC *bot_downlink_find(BOTNET_REC *botnet, IPADDR *ip, const char *host); - -void bot_nick_destroy(BOT_CHANNEL_REC *rec, NICK_REC *nick); -void bot_channel_destroy(BOT_IRCNET_REC *ircnet, BOT_CHANNEL_REC *rec); -void bot_ircnet_destroy(BOT_REC *bot, BOT_IRCNET_REC *rec); - -void bot_disconnect(BOT_REC *bot); -void bot_destroy(BOT_REC *bot); - -void bot_downlink_destroy(BOT_DOWNLINK_REC *rec); -void bot_uplink_destroy(BOT_UPLINK_REC *rec); - -void botnet_connect(BOTNET_REC *botnet); -void botnet_disconnect(BOTNET_REC *botnet); - -#endif diff --git a/src/irc/bot/botnets.sample b/src/irc/bot/botnets.sample deleted file mode 100644 index 01ce9684..00000000 --- a/src/irc/bot/botnets.sample +++ /dev/null @@ -1,15 +0,0 @@ -botnets = { - irssinet = { - nick = irssibot; - priority = 5; - autoconnect = yes; - uplinks = ( - { host = "main.botnet.org"; password = "mypass"; } - ); - downlinks = ( - { password = "thepass"; valid_addrs = ( "192.168.0.*" ); }, - { password = "blah"; valid_addrs = ( "*.botnet.org" ); }, - { password = "localpass"; valid_addrs = ( "127.*" ); } - ); - }; -}; diff --git a/src/irc/bot/module.h b/src/irc/bot/module.h deleted file mode 100644 index 3ae857fa..00000000 --- a/src/irc/bot/module.h +++ /dev/null @@ -1,3 +0,0 @@ -#include "common.h" - -#define MODULE_NAME "irc/bot" diff --git a/src/irc/bot/users.sample b/src/irc/bot/users.sample deleted file mode 100644 index 72e534a8..00000000 --- a/src/irc/bot/users.sample +++ /dev/null @@ -1,18 +0,0 @@ -users = -{ - mynick = { - flags = oa; - masks = ( - { mask="*!*@somewhere" }, - { mask="*!*@somewhere.else"; not_flags=a; } - ); - }; - - other = { - masks = ( { mask="*!nick@home.org"; } ); - channels = ( - { channel = "#irssi";flags = oa; }, - { channel = "#chan";flags = oa; } - ); - }; -}; -- cgit v1.2.3