diff options
Diffstat (limited to 'src/irc/bot/botnet-connection.c')
-rw-r--r-- | src/irc/bot/botnet-connection.c | 592 |
1 files changed, 0 insertions, 592 deletions
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); -} |