Remove long unmaintained botnet module.

git-svn-id: http://svn.irssi.org/repos/irssi/trunk@4723 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Emanuele Giaquinta 2008-03-04 18:15:51 +00:00 committed by exg
commit 3e37906cf7
17 changed files with 0 additions and 3248 deletions

View file

@ -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

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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

View file

@ -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();
}

View file

@ -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

View file

@ -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);
}

View file

@ -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, &not_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);
}

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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.*" ); }
);
};
};

View file

@ -1,3 +0,0 @@
#include "common.h"
#define MODULE_NAME "irc/bot"

View file

@ -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; }
);
};
};