lib/eggdrop/botnet.c File Reference


Detailed Description

Contains all botnet related stuff.

This file contains all functions dealing with other bots on the botnet.

Todo:
A lot ... And then to write a module that actually uses this -_-

Definition in file botnet.c.

#include <eggdrop/eggdrop.h>

Go to the source code of this file.

Data Structures

struct  botnet_search_prio_t

Defines

#define BAD_BOTNAME_CHARS   " *?@:"
 A string of characters that aren't allowed in a botname.

Functions

static int botnet_cleanup (void *client_data)
 Deletes all bots marked as deleted.
static void botnet_really_delete (botnet_bot_t *bot)
 Completely delete a bot.
static int botnet_clear_all ()
 Deletes all bots.
int botnet_init ()
 Inits the whole botnet stuff.
int botnet_shutdown (void)
 Shuts the whole botnet stuff down.
int botnet_set_name (const char *name)
 Set the botname of this bot.
const char * botnet_get_name ()
 Returns the bots name on the botnet.
const botnet_bot_tbotnet_get_head ()
 Returns the first bot in the linked list.
botnet_bot_tbotnet_lookup (const char *name)
 Find a bot by its name.
botnet_bot_tbotnet_new (const char *name, user_t *user, botnet_bot_t *uplink, botnet_bot_t *direction, xml_node_t *info, botnet_handler_t *handler, void *client_data, event_owner_t *owner, int netburst)
 Adds a bot to the botnet.
int botnet_unlink (botnet_entity_t *from, botnet_bot_t *bot, const char *reason)
 To request unlinking a bot.
static void botnet_recursive_delete (botnet_bot_t *bot, botnet_bot_t *root, const char *reason)
 Deletes a subtree of the botnet.
void botnet_count_subtree (botnet_bot_t *bot, int *bots, int *members)
 Count the number of bots and partymembers in a subtree.
int botnet_delete (botnet_bot_t *bot, const char *reason)
 Deletes a bot.
int botnet_delete_by_owner (struct egg_module *module, void *script)
 Deletes all bots with a given owner.
static void botnet_recursive_replay_net (botnet_bot_t *dst, botnet_bot_t *start)
 For internal use by botnet_replay_net().
void botnet_replay_net (botnet_bot_t *dst)
 Sends a replay of the current botnet to a bot.
void botnet_link_failed (user_t *user, const char *reason)
 Does some cleanup in case a connection attempt to a bot failed.
void botnet_link_success (botnet_bot_t *bot)
 Does some cleanup after the connection has been fully established.
static int botnet_find_min (const void *uid, void *userptr, void *param)
 callback function for the user walker.
static int botnet_link_prio (const void *uid, void *userptr, void *param)
 callback function for the user walker.
void botnet_autolink ()
 Try to link one or more bots based on their priority setting.
int botnet_check_direction (botnet_bot_t *direction, botnet_bot_t *src)
int botnet_link (botnet_entity_t *src, botnet_bot_t *dst, const char *target)
const char * botnet_get_info (botnet_bot_t *bot, const char *name)
void botnet_set_info (botnet_bot_t *bot, const char *name, const char *value)
void botnet_set_info_int (botnet_bot_t *bot, const char *name, int value)
void botnet_member_join (partychan_t *chan, partymember_t *p, int linking)
 Sends a partyline channel join out to the botnet.
void botnet_announce_login (partymember_t *p)
 Sends a partyline join out to the botnet.
void botnet_member_part (partychan_t *chan, partymember_t *p, const char *reason, int len)
void botnet_chanmsg (partychan_t *chan, botnet_entity_t *src, const char *text, int len)
void botnet_broadcast (botnet_entity_t *src, const char *text, int len)
void botnet_set_nick (partymember_t *p, const char *oldnick)
void botnet_member_quit (partymember_t *p, const char *reason, int len)
void botnet_botmsg (botnet_bot_t *src, botnet_bot_t *dst, const char *command, const char *text, int len)
void botnet_botbroadcast (botnet_bot_t *src, const char *command, const char *text, int len)
void botnet_extension (int mode, botnet_entity_t *src, botnet_bot_t *dst, egg_module_t *mod, const char *cmd, const char *text, int len)

Variables

static const char rcsid [] = "$Id: botnet.c,v 1.13 2007-09-13 22:20:55 sven Exp $"
static char * botname
static char * default_botname = "eggdrop"
static hash_table_tbot_ht = NULL
static botnet_bot_tbot_head
static botnet_bot_tlocalbot_head
static int nbots = 0
static int linking_bots = 0
 Number of bots that are currently in the process of being linked.
static bind_table_tBT_request_link
static bind_table_tBT_link
static bind_table_tBT_disc
static bind_table_tBT_bot
static bind_table_tBT_extension


Define Documentation

#define BAD_BOTNAME_CHARS   " *?@:"

A string of characters that aren't allowed in a botname.

Definition at line 36 of file botnet.c.

Referenced by botnet_new().


Function Documentation

void botnet_announce_login ( partymember_t p  ) 

Sends a partyline join out to the botnet.

This function simply calls the on_login callback for all directly linked bots except the one the event came from. It should only be called by exactly one function.

Parameters:
p The user that has joined the partyline.
Warning:
If this function is referenced by any other function except partychan_new() it is a bug.

Definition at line 870 of file botnet.c.

References partymember::bot, BOT_DELETED, botnet_bot::client_data, botnet_bot::direction, botnet_bot::flags, botnet_bot::handler, botnet_bot::next_local, and botnet_handler_t::on_login.

Referenced by partymember_new().

00871 {
00872   botnet_bot_t *tmp;
00873 
00874   for (tmp = localbot_head; tmp; tmp = tmp->next_local) {
00875     if (tmp->flags & BOT_DELETED || (p->bot && tmp == p->bot->direction)) continue;
00876     if (tmp->handler && tmp->handler->on_login) tmp->handler->on_login(tmp->client_data, p);
00877   }
00878 }

void botnet_autolink ( void   ) 

Try to link one or more bots based on their priority setting.

This function should be called regulary by the core. If there are no bots in the process of being linked at the moment this function will try to link to some of the bots that are currently not connected to the botnet.

To determine which bots should be linked in which order the user setting bot.link-priority is used. If it exists and has a positive integer value the bot is considered for linking.

The first time this function is called it will search all user records for the one with the lowest positive link-priority. All bots with this exact priority will be linked simultaniously. Once the last of this connection attempts has succeded or failed this function will be called again and try to link to the bot with the lowest priority that is higher than the privious one. This will continue until no bot to link to is found. In that case the priority threahold is reset to 1. When this function is called by the core the next time the whole process will start again.

Definition at line 727 of file botnet.c.

References botnet_find_min(), botnet_link_prio(), linking_bots, botnet_search_prio_t::min_prio, and user_walk().

Referenced by botnet_link_failed(), botnet_link_success(), core_secondly(), and main().

00728 {
00729   static int priority = 0;
00730   botnet_search_prio_t data = {priority, INT_MAX};
00731 
00732   if (linking_bots) return;
00733   user_walk(botnet_find_min, &data);
00734   
00735   if (data.min_prio == INT_MAX) {
00736     priority = 0;
00737     return;
00738   }
00739 
00740   priority = data.min_prio;
00741 
00742   user_walk(botnet_link_prio, &priority);
00743 }

void botnet_botbroadcast ( botnet_bot_t src,
const char *  command,
const char *  text,
int  len 
)

Definition at line 948 of file botnet.c.

References bind_check(), BOT_DELETED, botnet_bot::client_data, botnet_bot::direction, botnet_bot::flags, botnet_bot::handler, botnet_bot::next_local, NULL, and botnet_handler_t::on_botbroadcast.

Referenced by got_bbroadcast(), and got_botbroadcast().

00949 {
00950   botnet_bot_t *tmp;
00951 
00952   if (!text) len = 0;
00953   else if (len < 0) len = strlen(text);
00954 
00955   bind_check(BT_bot, NULL, command, src, command, text);
00956 
00957   for (tmp = localbot_head; tmp; tmp = tmp->next_local) {
00958     if (tmp->flags & BOT_DELETED || (src && tmp == src->direction)) continue;
00959     if (tmp->handler && tmp->handler->on_botbroadcast) tmp->handler->on_botbroadcast(tmp->client_data, src, command, text, len);
00960   }
00961 }

void botnet_botmsg ( botnet_bot_t src,
botnet_bot_t dst,
const char *  command,
const char *  text,
int  len 
)

Definition at line 935 of file botnet.c.

References bind_check(), botnet_bot::client_data, botnet_bot::direction, botnet_bot::handler, NULL, and botnet_handler_t::on_botmsg.

Referenced by got_botmsg().

00936 {
00937   if (!text) len = 0;
00938   else if (len < 0) len = strlen(text);
00939 
00940   if (dst) {
00941     botnet_bot_t *dir = dst->direction;
00942     if (dir->handler && dir->handler->on_botmsg) dir->handler->on_botmsg(dir->client_data, src, dst, command, text, len);
00943     return;
00944   }
00945   bind_check(BT_bot, NULL, command, src, command, text);
00946 }

void botnet_broadcast ( botnet_entity_t src,
const char *  text,
int  len 
)

Definition at line 903 of file botnet.c.

References botnet_entity::bot, BOT_DELETED, botnet_bot::client_data, botnet_bot::direction, botnet_bot::flags, botnet_bot::handler, botnet_bot::next_local, botnet_handler_t::on_bcast, and partymember_local_broadcast().

Referenced by got_bcast(), and got_broadcast().

00904 {
00905   botnet_bot_t *tmp;
00906 
00907   if (len < 0) len = strlen(text);
00908   for (tmp = localbot_head; tmp; tmp = tmp->next_local) {
00909     if (tmp->flags & BOT_DELETED || (src && src->bot && tmp == src->bot->direction)) continue;
00910     if (tmp->handler && tmp->handler->on_bcast) tmp->handler->on_bcast(tmp->client_data, src, text, len);
00911   }
00912   partymember_local_broadcast(src, text, len);
00913 }

void botnet_chanmsg ( partychan_t chan,
botnet_entity_t src,
const char *  text,
int  len 
)

Definition at line 890 of file botnet.c.

References botnet_entity::bot, partymember::bot, BOT_DELETED, botnet_bot::client_data, botnet_bot::direction, ENTITY_PARTYMEMBER, botnet_bot::flags, botnet_bot::handler, botnet_bot::next_local, botnet_handler_t::on_chanmsg, botnet_entity::user, and botnet_entity::what.

Referenced by chan_msg().

00891 {
00892   botnet_bot_t *tmp, *srcbot;
00893 
00894   if (src->what == ENTITY_PARTYMEMBER) srcbot = src->user->bot;
00895   else srcbot = src->bot;
00896 
00897   for (tmp = localbot_head; tmp; tmp = tmp->next_local) {
00898     if (tmp->flags & BOT_DELETED || (srcbot && tmp == srcbot->direction)) continue;
00899     if (tmp->handler && tmp->handler->on_chanmsg) tmp->handler->on_chanmsg(tmp->client_data, chan, src, text, len);
00900   }
00901 }

int botnet_check_direction ( botnet_bot_t direction,
botnet_bot_t src 
)

Definition at line 745 of file botnet.c.

References _, botnet_bot::direction, LOG_MISC, botnet_bot::name, and putlog().

Referenced by get_entity(), got_actchan(), got_away(), got_bcast(), got_botbroadcast(), got_botmsg(), got_chat(), got_join(), got_link(), got_motd(), got_nickchange(), got_nlinked(), got_part(), got_unlinked(), got_versions(), got_who(), and idx_on_read().

00746 {
00747   if (!src || src->direction != direction) {
00748     putlog(LOG_MISC, "*", _("Fake message from %s rejected! (direction != %s)."), direction->name, src ? src->name : _("non-existent bot"));
00749     return 1;
00750   }
00751   return 0;
00752 }

static int botnet_cleanup ( void *  client_data  )  [static]

Deletes all bots marked as deleted.

Parameters:
client_data Ignored.
Returns:
Always 0.
Todo:
Return something useful or change it to void.

Definition at line 764 of file botnet.c.

References botnet_really_delete(), botnet_bot::flags, botnet_bot::next, and PARTY_DELETED.

Referenced by botnet_delete().

00765 {
00766   botnet_bot_t *bot, *next;
00767 
00768   for (bot = bot_head; bot; bot = next) {
00769     next = bot->next;
00770     if (bot->flags & PARTY_DELETED) botnet_really_delete(bot);
00771   }
00772   return 0;
00773 }

static int botnet_clear_all (  )  [static]

Deletes all bots.

Deletes all bots without calling any binds or callbacks (except for on_delete).

Returns:
The number of killed bots.
Warning:
Should probably never be called except during shutdowns and should never ever return a non-zero value.
Todo:
Implement this!

Definition at line 343 of file botnet.c.

Referenced by botnet_shutdown().

00344 {
00345   int ret = 0;
00346   return ret;
00347 }

void botnet_count_subtree ( botnet_bot_t bot,
int *  bots,
int *  members 
)

Count the number of bots and partymembers in a subtree.

Counts bots and partymembers on and behind a certain bot in the current botnet.

Parameters:
bot The bot to start from. Must not be NULL.
bots A pointer to the variable to contain the number of bots. May be NULL.
members A pointer to the variable to contain the number of partymembers. May be NULL.
Warning:
This function never initializes the parameters bots and members! Do it yourself before every call unless you want to add up more subtrees!

Definition at line 471 of file botnet.c.

References BOT_DELETED, botnet_count_subtree(), botnet_bot::flags, botnet_bot::next, partymember_count_by_bot(), and botnet_bot::uplink.

Referenced by botnet_count_subtree(), and botnet_delete().

00472 {
00473   int m;
00474   botnet_bot_t *tmp;
00475 
00476   for (tmp = bot_head; tmp; tmp = tmp->next) {
00477     if (tmp->flags & BOT_DELETED) continue;
00478     if (tmp->uplink == bot) botnet_count_subtree(tmp, bots, members);
00479   }
00480 
00481   m = partymember_count_by_bot(bot);
00482   if (bots) ++*bots;
00483   if (members) *members += m;
00484 }

int botnet_delete ( botnet_bot_t bot,
const char *  reason 
)

Deletes a bot.

Marks a bot as deleted, clears out anything linked via this bot, triggers the binds, logs it and sends it out to the botnet.

Parameters:
bot The bot to delete.
reason Some text explaining the Hows and Whys of the unlink.
Returns:
0 on success, -1 on failure.

Definition at line 498 of file botnet.c.

References BOT_DELETED, botnet_cleanup(), botnet_count_subtree(), botnet_link_failed(), botnet_recursive_delete(), botnet_bot::client_data, botnet_bot::direction, user::flags, botnet_bot::flags, garbage_add(), GARBAGE_ONCE, botnet_bot::handler, LOG_MISC, botnet_bot::name, botnet_bot::next_local, NULL, botnet_handler_t::on_lost_bot, putlog(), botnet_bot::uplink, botnet_bot::user, and USER_LINKING_BOT.

Referenced by botnet_delete_by_owner(), botnet_unlink(), do_ping(), got_bquit(), got_bye(), got_newbot(), got_nlinked(), got_thisbot(), got_unlinked(), idx_on_delete(), idx_on_eof(), idx_on_read(), oldbotnet_on_delete(), oldbotnet_on_eof(), and oldbotnet_on_read().

00499 {
00500   char obuf[512];
00501   const botnet_bot_t *tmp;
00502 
00503   if (bot->flags & BOT_DELETED) return -1;
00504 
00505   if (!bot->uplink) {
00506     int bots = 0, users = 0;
00507     botnet_count_subtree(bot, &bots, &users);
00508     snprintf(obuf, sizeof(obuf), "Unlinked from: %s (%s) (lost %d bots and %d users)", bot->name, reason, bots, users);
00509     reason = obuf;
00510   }
00511 
00512   for (tmp = localbot_head; tmp; tmp = tmp->next_local) {
00513     if (tmp->flags & BOT_DELETED || tmp == bot->direction) continue;
00514     if (tmp->handler && tmp->handler->on_lost_bot) tmp->handler->on_lost_bot(tmp->client_data, bot, reason);
00515   }
00516 
00517   botnet_recursive_delete(bot, bot, reason);
00518 
00519   if (!bot->uplink) putlog(LOG_MISC, "*", "%s", reason);
00520   else putlog(LOG_MISC, "*", "(%s) %s", bot->uplink->name, reason);
00521 
00522   if (bot->user && bot->user->flags & USER_LINKING_BOT) botnet_link_failed(bot->user, reason);
00523 
00524   garbage_add(botnet_cleanup, NULL, GARBAGE_ONCE);
00525 
00526   return 0;
00527 }

int botnet_delete_by_owner ( struct egg_module module,
void *  script 
)

Deletes all bots with a given owner.

Calls botnet_delete() for every bot with a given owner. In the first search only the list of local bots is searched. After that the whole list is searched but it'd be a really wyrd botnet if a match was found there.

Parameters:
module The module whose bots should be deleted.
script The script whose bots should be deleted. NULL matches everything.
Returns:
The number of deleted bots. (Not counting recursive deletes.)

Definition at line 542 of file botnet.c.

References _, BOT_DELETED, botnet_delete(), event_owner_b::client_data, botnet_bot::flags, event_owner_b::module, botnet_bot::next_local, and botnet_bot::owner.

Referenced by script_remove_events_by_owner().

00543 {
00544   int ret = 0;
00545   botnet_bot_t *tmp;
00546 
00547   for (tmp = localbot_head; tmp; tmp = tmp->next_local) {
00548     if (tmp->flags & BOT_DELETED) continue;
00549     if (tmp->owner && tmp->owner->module == module && (!script || tmp->owner->client_data == script)) {
00550       ++ret;
00551       botnet_delete(tmp, _("Module unloaded"));
00552     }
00553   }
00554 
00555   for (tmp = bot_head; tmp; tmp = tmp->next_local) {
00556     if (tmp->flags & BOT_DELETED) continue;
00557     if (tmp->owner && tmp->owner->module == module && (!script || tmp->owner->client_data == script)) {
00558       ++ret;
00559       botnet_delete(tmp, _("Module unloaded"));
00560     }
00561   }
00562 
00563   return ret;
00564 }

void botnet_extension ( int  mode,
botnet_entity_t src,
botnet_bot_t dst,
egg_module_t mod,
const char *  cmd,
const char *  text,
int  len 
)

Definition at line 963 of file botnet.c.

References bind_check(), partymember::bot, botnet_entity::bot, BOT_DELETED, botnet_bot::client_data, botnet_bot::direction, ENTITY_BOT, EXTENSION_ALL, EXTENSION_ONE, botnet_bot::flags, botnet_bot::handler, event_owner_b::module, botnet_bot::next_local, NULL, botnet_handler_t::on_extension, botnet_bot::owner, botnet_entity::user, and botnet_entity::what.

Referenced by got_away(), got_extension(), got_motd(), got_privmsg(), got_versions(), and got_who().

00964 {
00965   botnet_bot_t *tmp, *srcbot = src->what == ENTITY_BOT ? src->bot : src->user->bot;
00966 
00967   if (!text) len = 0;
00968   else if (len < 0) len = strlen(text);
00969 
00970   if (!dst) bind_check(BT_extension, NULL, cmd, src, cmd, text);
00971   if (mode == EXTENSION_ONE) {
00972     if (dst && dst->direction->handler && dst->direction->handler->on_extension)
00973       dst->direction->handler->on_extension(dst->direction->client_data, src, dst, cmd, text, len);
00974     return;
00975   }
00976 
00977   for (tmp = localbot_head; tmp; tmp = tmp->next_local) {
00978     if (tmp->flags & BOT_DELETED || (srcbot && tmp == srcbot->direction)) continue;
00979     if (mod && !(tmp->owner && tmp->owner->module == mod)) continue;
00980     if (tmp->handler && tmp->handler->on_extension)
00981       tmp->handler->on_extension(tmp->client_data, src, mode == EXTENSION_ALL ? NULL : tmp, cmd, text, len);
00982   }
00983 }

static int botnet_find_min ( const void *  uid,
void *  userptr,
void *  param 
) [static]

callback function for the user walker.

This function is a helper function for botnet_autolink(). It is called by user_walk() for every user in the bots database. It searches for the user with the lowest link priority.

Parameters:
uid A pointer to the uid of the user. Ignored.
userptr A a pointer to the pointer to the user.
param A botnet_search_prio_t struct.
Returns:
Always 0 and never checked.

Definition at line 657 of file botnet.c.

References _, botnet_lookup(), user::flags, user::handle, linking_bots, LOG_MISC, botnet_search_prio_t::min_prio, NULL, botnet_search_prio_t::priority, putlog(), USER_BOT, user_get_setting(), USER_LINKED_BOT, and USER_LINKING_BOT.

Referenced by botnet_autolink().

00658 {
00659   int p;
00660   char *prio;
00661   user_t *u = *(user_t **) userptr;
00662   botnet_search_prio_t *data = param;
00663 
00664   if (!(u->flags & USER_BOT) || u->flags & USER_LINKED_BOT) return 0;
00665   if (u->flags & USER_LINKING_BOT) {
00666     putlog(LOG_MISC, "*", _("Warning: botnet_autolink() was called while still connecting to %s."), u->handle);
00667     if (linking_bots < 1) linking_bots = 1;
00668     return 0;
00669   }
00670   if (botnet_lookup(u->handle) || user_get_setting(u, NULL, "bot.link-priority", &prio)) return 0;
00671 
00672   p = atoi(prio);
00673   if (p > data->priority && p < data->min_prio) data->min_prio = p;
00674 
00675   return 0;
00676 }

const botnet_bot_t* botnet_get_head ( void   ) 

Returns the first bot in the linked list.

Returns:
The first bot on the botnet.
Todo:
There has to be a better way to do whatever needs to be done than messing with this list.

Definition at line 230 of file botnet.c.

Referenced by party_bots().

00231 {
00232   return bot_head;
00233 }

const char* botnet_get_info ( botnet_bot_t bot,
const char *  name 
)

Definition at line 814 of file botnet.c.

References botnet_bot::info, and xml_node_get_str().

Referenced by on_new_bot().

00815 {
00816   char *ret;
00817 
00818   xml_node_get_str(&ret, bot->info, name, 0, (void *) 0);
00819   return ret;
00820 }

const char* botnet_get_name ( void   ) 

int botnet_init ( void   ) 

Inits the whole botnet stuff.

Returns:
Always 0

Definition at line 137 of file botnet.c.

References BIND_BREAKABLE, BIND_STACKABLE, bind_table_add(), botname, BTN_BOTNET_BOT, BTN_BOTNET_DISC, BTN_BOTNET_EXTENSION, BTN_BOTNET_LINK, BTN_BOTNET_REQUEST_LINK, default_botname, hash_table_create(), HASH_TABLE_STRINGS, nbots, and NULL.

Referenced by eggdrop_init().

00138 {
00139   nbots = 0;
00140   bot_head = NULL;
00141   localbot_head = NULL;
00142 
00143   botname = default_botname;
00144   bot_ht = hash_table_create(NULL, NULL, 13, HASH_TABLE_STRINGS);
00145 
00146   BT_request_link = bind_table_add(BTN_BOTNET_REQUEST_LINK, 2, "Us", 0, BIND_BREAKABLE);
00147   BT_link = bind_table_add(BTN_BOTNET_LINK, 1, "B", 0, BIND_STACKABLE);
00148   BT_disc = bind_table_add(BTN_BOTNET_DISC, 3, "BBs", 0, BIND_STACKABLE);
00149   BT_bot = bind_table_add(BTN_BOTNET_BOT, 3, "Bss", 0, 0);
00150   BT_extension = bind_table_add(BTN_BOTNET_EXTENSION, 3, "Ess", 0, 0);
00151   return 0;
00152 }

int botnet_link ( botnet_entity_t src,
botnet_bot_t dst,
const char *  target 
)

Definition at line 775 of file botnet.c.

References _, bind_check(), bot_entity, botnet_lookup(), botnet_bot::client_data, botnet_bot::direction, ENTITY_PARTYMEMBER, user::flags, user::handle, botnet_bot::handler, linking_bots, NULL, botnet_handler_t::on_link, partymember_msg(), botnet_entity::user, USER_BOT, user_get_setting(), USER_LINKING_BOT, user_lookup_by_handle(), and botnet_entity::what.

Referenced by botnet_link_prio(), got_link(), got_unlink(), and party_link().

00776 {
00777   char *type, *priority;
00778   user_t *user;
00779   botnet_entity_t entity_me = bot_entity((botnet_bot_t *) 0);
00780 
00781   if (dst) {
00782     if (dst->direction->handler && dst->direction->handler->on_link)
00783       dst->direction->handler->on_link(dst->direction->client_data, src, dst, target);
00784     return 0;
00785   }
00786 
00787   user = user_lookup_by_handle(target);
00788   if (!user || !(user->flags & USER_BOT)) {
00789     if (src->what == ENTITY_PARTYMEMBER) partymember_msg(src->user, &entity_me, _("Can't link there: No such bot."), -1);
00790     return -1;
00791   }
00792   if (user->flags & USER_LINKING_BOT || botnet_lookup(user->handle)) {
00793     if (src->what == ENTITY_PARTYMEMBER) partymember_msg(src->user, &entity_me, _("Can't link there: Already linked."), -1);
00794     return -2;
00795   }
00796   if (user_get_setting(user, NULL, "bot.type", &type)) type = "eggdrop";
00797   if (!user_get_setting(user, NULL, "bot.link-priority", &priority) && atoi(priority) < 0) {
00798     if (src->what == ENTITY_PARTYMEMBER) partymember_msg(src->user, &entity_me, _("Won't link there: Negative link priority."), -1);
00799     return -3;
00800   }
00801 
00802   user->flags |= USER_LINKING_BOT;
00803   ++linking_bots;
00804   if (!bind_check(BT_request_link, NULL, type, user, type)) {
00805     user->flags &= ~USER_LINKING_BOT;
00806     --linking_bots;
00807     if (src->what == ENTITY_PARTYMEMBER) partymember_msg(src->user, &entity_me, _("Can't link there: Module not loaded."), -1);
00808     return -4;
00809   }
00810 
00811   return 0;
00812 }

void botnet_link_failed ( user_t user,
const char *  reason 
)

Does some cleanup in case a connection attempt to a bot failed.

This function clears the USER_LINKING_BOT flag, logs some kind of message and runs the botnet_autolink() function.

Parameters:
user The user record of the bot that should have been linked.
reason Some kind of reason why it didn't work.

Definition at line 619 of file botnet.c.

References _, botnet_autolink(), user::flags, user::handle, linking_bots, LOG_MISC, putlog(), and USER_LINKING_BOT.

Referenced by botnet_delete(), got_version(), idx_on_delete(), idx_on_eof(), oldbotnet_on_delete(), oldbotnet_on_eof(), and oldbotnet_on_read().

00620 {
00621   putlog(LOG_MISC, "*", _("Failed to link to %s (%s)."), user->handle, reason);
00622   --linking_bots;
00623   user->flags &= ~USER_LINKING_BOT;
00624   if (!linking_bots) botnet_autolink();
00625 }

static int botnet_link_prio ( const void *  uid,
void *  userptr,
void *  param 
) [static]

callback function for the user walker.

This function is a helper function for botnet_autolink(). It is called by user_walk() for every user in the bots database. It links tries to link to every user with a given priority.

Parameters:
uid A pointer to the uid of the user. Ignored.
userptr A a pointer to the pointer to the user.
param A pointer to an int containing the priority to link to.
Returns:
Always 0 and never checked.

Definition at line 691 of file botnet.c.

References bot_entity, botnet_link(), botnet_lookup(), user::flags, user::handle, NULL, USER_BOT, user_get_setting(), USER_LINKED_BOT, and USER_LINKING_BOT.

Referenced by botnet_autolink().

00692 {
00693   char *prio;
00694   user_t *u = *(user_t **) userptr;
00695   int *priority = param;
00696   botnet_entity_t me = bot_entity((botnet_bot_t *) 0);
00697 
00698   if (!(u->flags & USER_BOT) || u->flags & (USER_LINKING_BOT | USER_LINKED_BOT)) return 0;
00699   if (botnet_lookup(u->handle) || user_get_setting(u, NULL, "bot.link-priority", &prio)) return 0;
00700 
00701   if (atoi(prio) == *priority) botnet_link(&me, NULL, u->handle);
00702 
00703   return 0;
00704 }

void botnet_link_success ( botnet_bot_t bot  ) 

Does some cleanup after the connection has been fully established.

This function clears the USER_LINKING_BOT flag and runs the botnet_autolink() function.

Parameters:
bot The bot that was linked.

Definition at line 636 of file botnet.c.

References botnet_autolink(), user::flags, linking_bots, botnet_bot::user, USER_LINKED_BOT, and USER_LINKING_BOT.

Referenced by got_endlink().

00637 {
00638   if (linking_bots > 0 && bot->user->flags & USER_LINKING_BOT) --linking_bots;
00639   bot->user->flags &= ~USER_LINKING_BOT;
00640   bot->user->flags |= USER_LINKED_BOT;
00641   if (!linking_bots) botnet_autolink();
00642 }

botnet_bot_t* botnet_lookup ( const char *  name  ) 

Find a bot by its name.

Parameters:
name The name of the bot to find
Returns:
The bot or NULL if no such bot exists

Definition at line 243 of file botnet.c.

References BOT_DELETED, botnet_bot::flags, hash_table_find(), and NULL.

Referenced by botnet_find_min(), botnet_link(), botnet_link_prio(), botnet_new(), get_entity(), got_away(), got_bcast(), got_botbroadcast(), got_botmsg(), got_chat(), got_join(), got_link(), got_motd(), got_nickchange(), got_nlinked(), got_part(), got_privmsg(), got_unlink(), got_unlinked(), got_versions(), got_who(), party_link(), party_unlink(), partymember_lookup(), and recving_login().

00244 {
00245   botnet_bot_t *bot = NULL;
00246 
00247   hash_table_find(bot_ht, name, &bot);
00248   if (bot && bot->flags & BOT_DELETED) return NULL;
00249   return bot;
00250 }

void botnet_member_join ( partychan_t chan,
partymember_t p,
int  linking 
)

Sends a partyline channel join out to the botnet.

This function simply calls the on_join callback for all directly linked bots except the one the event came from. It should only be called by exactly one function.

Parameters:
chan The partyline channel the user has joined.
p The user that has joined the channel.
linking True if the join is part of the linking process between two bots.
Warning:
If this function is referenced by any other function except partychan_join() it is a bug.

Definition at line 847 of file botnet.c.

References partymember::bot, BOT_DELETED, botnet_bot::client_data, botnet_bot::direction, botnet_bot::flags, botnet_bot::handler, botnet_bot::next_local, and botnet_handler_t::on_join.

Referenced by partychan_join().

00848 {
00849   botnet_bot_t *tmp;
00850 
00851   for (tmp = localbot_head; tmp; tmp = tmp->next_local) {
00852     if (tmp->flags & BOT_DELETED || (p->bot && tmp == p->bot->direction)) continue;
00853     if (tmp->handler && tmp->handler->on_join) tmp->handler->on_join(tmp->client_data, chan, p, linking);
00854   }
00855 }

void botnet_member_part ( partychan_t chan,
partymember_t p,
const char *  reason,
int  len 
)

Definition at line 880 of file botnet.c.

References partymember::bot, BOT_DELETED, botnet_bot::client_data, botnet_bot::direction, botnet_bot::flags, botnet_bot::handler, botnet_bot::next_local, and botnet_handler_t::on_part.

Referenced by partychan_part().

00881 {
00882   botnet_bot_t *tmp;
00883 
00884   for (tmp = localbot_head; tmp; tmp = tmp->next_local) {
00885     if (tmp->flags & BOT_DELETED || (p->bot && tmp == p->bot->direction)) continue;
00886     if (tmp->handler && tmp->handler->on_part) tmp->handler->on_part(tmp->client_data, chan, p, reason, len);
00887   }
00888 }

void botnet_member_quit ( partymember_t p,
const char *  reason,
int  len 
)

Definition at line 925 of file botnet.c.

References partymember::bot, BOT_DELETED, botnet_bot::client_data, botnet_bot::direction, botnet_bot::flags, botnet_bot::handler, botnet_bot::next_local, and botnet_handler_t::on_quit.

Referenced by partymember_delete().

00926 {
00927   botnet_bot_t *tmp;
00928 
00929   for (tmp = localbot_head; tmp; tmp = tmp->next_local) {
00930     if (tmp->flags & BOT_DELETED || (p->bot && tmp == p->bot->direction)) continue;
00931     if (tmp->handler && tmp->handler->on_quit) tmp->handler->on_quit(tmp->client_data, p, reason, len);
00932   }
00933 }

botnet_bot_t* botnet_new ( const char *  name,
user_t user,
botnet_bot_t uplink,
botnet_bot_t direction,
xml_node_t info,
botnet_handler_t handler,
void *  client_data,
event_owner_t owner,
int  netburst 
)

Adds a bot to the botnet.

Calling this function will add a bot to the net, inform the rest of the net about it, log it and trigger the link bind.

Parameters:
name The name of the bot.
user The user entry for this bot. NULL if it's not local.
uplink The uplink of this bot. NULL if it's local.
direction The bot we have to talk to to reach this bot. NULL for local bots, it'll be set to the bot itself.
handler Handler struct containing the functions to call to get stuff done. NULL if it's not local.
client_data Some data passed back to the callback functions.
owner Owner of this bot and it's callback functions.
netburst True if it's part of the syncing between two other linked bots, false if it's a real new link.
Returns:
A pointer to the new bot on success, NULL on error.
Todo:
Find a better way to log this. But for now LOG_MISC is good enough.

Definition at line 272 of file botnet.c.

References BAD_BOTNAME_CHARS, bind_check(), BOT_DELETED, botname, botnet_lookup(), botnet_bot::client_data, botnet_bot::direction, botnet_bot::flags, botnet_bot::handler, hash_table_insert(), botnet_bot::info, LOG_MISC, botnet_bot::name, nbots, botnet_bot::next, botnet_bot::next_local, NULL, botnet_handler_t::on_new_bot, botnet_bot::owner, botnet_bot::partys, botnet_bot::prev, botnet_bot::prev_local, putlog(), botnet_bot::uplink, botnet_bot::user, and xml_node_new().

Referenced by got_newbot(), got_nlinked(), got_version(), recving_login(), and sending_login().

00273 {
00274   const char *temp;
00275   botnet_bot_t *bot, *tmp;
00276 
00277   if (!uplink && (!user || !handler)) return 0;
00278   if ((uplink && !direction) || (!uplink && direction)) return 0;
00279   if (botnet_lookup(name)) return 0;
00280   if (!strcmp(botname, name)) return 0;
00281   for (temp = name; *temp; ++temp) if (*temp < 32 || strchr(BAD_BOTNAME_CHARS, *temp)) return 0;
00282 
00283   bot = malloc(sizeof(*bot));
00284   if (!direction) direction = bot;
00285 
00286   bot->name = strdup(name);
00287   bot->flags = 0;
00288   bot->user = user;
00289   bot->uplink = uplink;
00290   bot->direction = direction;
00291   bot->partys = NULL;
00292   bot->handler = handler;
00293   bot->client_data = client_data;
00294   bot->owner = owner;
00295   bot->info = info ? info : xml_node_new();
00296 
00297   hash_table_insert(bot_ht, bot->name, bot);
00298   
00299   bot->prev = 0;
00300   bot->next = bot_head;
00301   if (bot_head) bot_head->prev = bot;
00302   bot_head = bot;
00303 
00304   bot->prev_local = 0;
00305   if (!uplink) {
00306     bot->next_local = localbot_head;
00307     if (localbot_head) localbot_head->prev_local = bot;
00308     localbot_head = bot;
00309   } else {
00310     bot->next_local = 0;
00311   }
00312 
00313   ++nbots;
00314 
00315   for (tmp = localbot_head; tmp; tmp = tmp->next_local) {
00316     if (tmp->flags & BOT_DELETED || tmp == bot->direction) continue;
00317     if (tmp->handler && tmp->handler->on_new_bot) tmp->handler->on_new_bot(tmp->client_data, bot, netburst);
00318   }
00319 
00320   bind_check(BT_link, NULL, bot->name, bot);
00321 
00322   if (!netburst) {
00323     if (!bot->uplink) putlog(LOG_MISC, "*", "Linked to %s.", bot->name);
00324     else putlog(LOG_MISC, "*", "(%s) Linked to %s.", bot->uplink->name, bot->name);
00325   }
00326 
00327   return bot;
00328 }

static void botnet_really_delete ( botnet_bot_t bot  )  [static]

Completely delete a bot.

Unlike botnet_delete() this function doesn't call on_delete handlers or trigger binds. It simply removes the bot from the hash table, unlinks it from the bot_head and localbot_head lists and frees the allocated memory.

Parameters:
bot The bot to delete
Warning:
Should never be called on a bot that hasn't been deleted by botnet_delete() earlier.

Definition at line 403 of file botnet.c.

References BOT_DELETED, botnet_bot::flags, hash_table_remove(), botnet_bot::info, botnet_bot::name, nbots, botnet_bot::next, botnet_bot::next_local, NULL, botnet_bot::prev, botnet_bot::prev_local, botnet_bot::uplink, and xml_node_delete().

Referenced by botnet_cleanup().

00404 {
00405   if (!(bot->flags & BOT_DELETED)) --nbots;
00406 
00407   if (bot->prev) bot->prev->next = bot->next;
00408   else bot_head = bot->next;
00409   if (bot->next) bot->next->prev = bot->prev;
00410 
00411   if (!bot->uplink) {
00412     if (bot->prev_local) bot->prev_local->next_local = bot->next_local;
00413     else localbot_head = bot->next_local;
00414     if (bot->next_local) bot->next_local->prev_local = bot->prev_local;
00415   }
00416   hash_table_remove(bot_ht, bot->name, NULL);
00417 
00418   xml_node_delete(bot->info);
00419   free(bot->name);
00420   free(bot);
00421 }

static void botnet_recursive_delete ( botnet_bot_t bot,
botnet_bot_t root,
const char *  reason 
) [static]

Deletes a subtree of the botnet.

This function deletes a bot, all partymembers on this bot, all bots linked via this bot and all partymembers on any of these bots.

Parameters:
bot The bot to delete.
root The bot that was originally unlinked. Should ne the same as bot when it's originally called from another function.
reason Some text explaining the How and Why of the unlink.

Definition at line 435 of file botnet.c.

References bind_check(), BOT_DELETED, botnet_bot::client_data, user::flags, botnet_bot::flags, botnet_bot::name, nbots, botnet_bot::next, NULL, event_owner_b::on_delete, botnet_bot::owner, partymember_delete_by_bot(), botnet_bot::uplink, botnet_bot::user, and USER_LINKED_BOT.

Referenced by botnet_delete().

00436 {
00437   botnet_bot_t *tmp;
00438 
00439   if (bot->flags & BOT_DELETED) return;
00440 
00441   /* First delete all bots linked via this bot */
00442   for (tmp = bot_head; tmp; tmp = tmp->next) {
00443     if (tmp->flags & BOT_DELETED) continue;
00444     if (tmp->uplink == bot) botnet_recursive_delete(tmp, root, reason);
00445   }
00446 
00447   /* Then delete all partymembers on this bot */
00448   partymember_delete_by_bot(bot, root, reason);
00449 
00450   /* And finally this bot */
00451   bind_check(BT_disc, NULL, bot->name, bot, root, reason);
00452   bot->flags |= BOT_DELETED;
00453   if (bot->user) bot->user->flags &= ~USER_LINKED_BOT;
00454   if (bot->owner && bot->owner->on_delete) bot->owner->on_delete(bot->owner, bot->client_data);
00455   --nbots;
00456 }

static void botnet_recursive_replay_net ( botnet_bot_t dst,
botnet_bot_t start 
) [static]

For internal use by botnet_replay_net().

Warning:
Don't call this unless you're botnet_replay_net().

Definition at line 572 of file botnet.c.

References BOT_DELETED, partymember::channels, botnet_bot::client_data, botnet_bot::flags, partymember::flags, botnet_bot::handler, partymember::nchannels, botnet_bot::next, partymember::next_on_bot, botnet_handler_t::on_join, botnet_handler_t::on_login, botnet_handler_t::on_new_bot, PARTY_DELETED, partymember_get_local_head(), botnet_bot::partys, and botnet_bot::uplink.

Referenced by botnet_replay_net().

00573 {
00574   int i;
00575   botnet_bot_t *tmp;
00576   partymember_t *p;
00577 
00578   if (start && dst->handler->on_new_bot) dst->handler->on_new_bot(dst->client_data, start, 1);
00579   
00580   for (p = start ? start->partys : partymember_get_local_head(); p; p = p->next_on_bot) {
00581     if (p->flags & PARTY_DELETED) continue;
00582     if (dst->handler->on_login) dst->handler->on_login(dst->client_data, p);
00583     for (i = 0; i < p->nchannels; ++i) {
00584       if (dst->handler->on_join) dst->handler->on_join(dst->client_data, p->channels[i], p, 1);
00585     }
00586   }
00587 
00588   for (tmp = bot_head; tmp; tmp = tmp->next) {
00589     if (tmp->flags & BOT_DELETED || tmp == dst) continue;
00590     if (tmp->uplink == start) botnet_recursive_replay_net(dst, tmp);
00591   }
00592 }

void botnet_replay_net ( botnet_bot_t dst  ) 

Sends a replay of the current botnet to a bot.

This function calls the botnet_handler_t::on_new_bot and botnet_handler_t::on_join callbacks of a bot for every bot and partymember on the botnet. The callbacks are always called with the linking parameter true.

Parameters:
dst The bot to send it to.

Definition at line 604 of file botnet.c.

References botnet_recursive_replay_net(), and NULL.

Referenced by got_version(), recving_login(), and sending_login().

00605 {
00606   botnet_recursive_replay_net(dst, NULL);
00607 }

void botnet_set_info ( botnet_bot_t bot,
const char *  name,
const char *  value 
)

Definition at line 822 of file botnet.c.

References botnet_bot::info, and xml_node_set_str().

00823 {
00824   xml_node_set_str(value, bot->info, name, 0, (void *) 0);
00825 }

void botnet_set_info_int ( botnet_bot_t bot,
const char *  name,
int  value 
)

Definition at line 827 of file botnet.c.

References botnet_bot::info, and xml_node_set_int().

00828 {
00829   xml_node_set_int(value, bot->info, name, 0, (void *) 0);
00830 }

int botnet_set_name ( const char *  name  ) 

Set the botname of this bot.

This will change the botname of this bot on the fly. It will fail and report an error if there are any bots connected to the botnet or if someone's on the partyline.

Parameters:
name The new botname.
Returns:
0 on success or -1 on error.

Definition at line 202 of file botnet.c.

References botname, default_botname, nbots, and partymember_get_head().

Referenced by core_init().

00203 {
00204   if (bot_head || localbot_head || nbots || partymember_get_head()) return -1;
00205   if (botname != default_botname) free(botname);
00206   botname = strdup(name);
00207   return 0;
00208 }

void botnet_set_nick ( partymember_t p,
const char *  oldnick 
)

Definition at line 915 of file botnet.c.

References partymember::bot, BOT_DELETED, botnet_bot::client_data, botnet_bot::direction, botnet_bot::flags, botnet_bot::handler, botnet_bot::next_local, and botnet_handler_t::on_nick.

Referenced by partymember_set_nick().

00916 {
00917   botnet_bot_t *tmp;
00918 
00919   for (tmp = localbot_head; tmp; tmp = tmp->next_local) {
00920     if (tmp->flags & BOT_DELETED || (p->bot && tmp == p->bot->direction)) continue;
00921     if (tmp->handler && tmp->handler->on_nick) tmp->handler->on_nick(tmp->client_data, p, oldnick);
00922   }
00923 }

int botnet_shutdown ( void   ) 

Shuts the whole botnet stuff down.

Frees all memory, deletes the binds, ...

Returns:
Always 0

Definition at line 162 of file botnet.c.

References bind_table_del(), botname, botnet_clear_all(), default_botname, garbage_run(), hash_table_delete(), LOG_MISC, NULL, and putlog().

Referenced by eggdrop_shutdown().

00163 {
00164   int leaked;
00165 
00166   /* Since at this point no scripts or modules should be loaded,
00167    * there should be no botnet. But just to make sure ... */
00168 
00169   leaked = botnet_clear_all();
00170   if (leaked) putlog(LOG_MISC, "*", "Warning: Some botnet module leaked %d bots. Fix this!", leaked);
00171 
00172   bind_table_del(BT_request_link);
00173   bind_table_del(BT_link);
00174   bind_table_del(BT_disc);
00175   bind_table_del(BT_bot);
00176   bind_table_del(BT_extension);
00177 
00178   /* force a garbage run since we might have some partymembers 
00179    * marked as deleted and w/o a garbage_run we may not destroy
00180    * our hashtable */
00181   garbage_run();
00182 
00183   hash_table_delete(bot_ht);
00184   bot_ht = NULL;
00185 
00186   if (botname != default_botname) free(botname);
00187   return 0;
00188 }

int botnet_unlink ( botnet_entity_t from,
botnet_bot_t bot,
const char *  reason 
)

To request unlinking a bot.

This function requests the unlinking of a bot on the botnet. If the bot to unlink is not directly linked to this bot, the request is just sent on in the bots direction.

If the bot is directly linked, the link is broken and the unlinked event is sent on in all directions.

Parameters:
from Who did it.
bot The bot to get rid of.
reason Some kind of explanation.
Returns:
0 on success, -1 if the bot's uplink doesn't have an on_unlink handler, -2 if we don't want to unlink.
Todo:
Do some kind of check if we really want the unlink.

Definition at line 369 of file botnet.c.

References _, bot_entity, botnet_delete(), botnet_bot::client_data, botnet_bot::direction, entity_full_name, ENTITY_PARTYMEMBER, botnet_bot::handler, botnet_bot::name, botnet_handler_t::on_lost_bot, botnet_handler_t::on_unlink, partymember_msgf(), botnet_entity::user, and botnet_entity::what.

Referenced by got_unlink(), and party_unlink().

00370 {
00371   char obuf[512];
00372   botnet_entity_t me = bot_entity((botnet_bot_t *) 0);
00373 
00374   if (bot->direction != bot) {
00375     if (!bot->direction->handler || !bot->direction->handler->on_unlink) return -1;
00376     bot->direction->handler->on_unlink(bot->direction->client_data, from, bot, reason);
00377     return 0;
00378   }
00379 
00380   snprintf(obuf, sizeof(obuf), "%s (%s)", reason, entity_full_name(from));
00381 
00382   if (bot->handler && bot->handler->on_lost_bot) bot->handler->on_lost_bot(bot->client_data, bot, obuf);
00383   if (from->what == ENTITY_PARTYMEMBER) partymember_msgf(from->user, &me, _("Unlinked from %s."), bot->name);
00384   botnet_delete(bot, reason);
00385 
00386   return 0;
00387 }


Variable Documentation

Definition at line 47 of file botnet.c.

hash_table_t* bot_ht = NULL [static]

Definition at line 46 of file botnet.c.

char* botname [static]

bind_table_t* BT_bot [static]

Bind:
Triggered by a message coming from another bot in the botnet. The first word is the command and the rest becomes the text argument.
Name:
bot
Flags:
Ignored.
Match:
The command.
Parameters:
bot The bot the message is from.
string The command.
string The rest of the line, possibly nothing.
Note:
This bind is stackable.
Returns:
Any return value will be ignored.

Definition at line 126 of file botnet.c.

bind_table_t* BT_disc [static]

Bind:
This bind is triggered every time a bot is lost from the botnet. If a bot gets disconnected this bind is triggered for all bots behind the lost one first, beginning with the most distant bots. That means that for some bots this bind is triggered for, the uplink still exists in this bots database even though it has already been lost.
Name:
disc
Flags:
Ignored.
Match:
The lost bot's name.
Parameters:
bot The lost bot.
bot The bot that really got disconnected and caused the bots behind it to get lost.
string Some kind of reason for the disconnect.
Note:
This bind is stackable.
Returns:
Any return value will be ignored.

Definition at line 110 of file botnet.c.

Todo:
Document me

Definition at line 130 of file botnet.c.

bind_table_t* BT_link [static]

Bind:
This bind is triggered every time a new bot is somehow linked to the botnet. There is no way to determine if it happened because it was directly linked or because another bot was linked and introduced it.
Name:
link
Flags:
Ignored.
Match:
The new bot's name.
Parameters:
bot The new bot.
Note:
This bind is stackable.
Returns:
Any return value will be ignored.

Definition at line 91 of file botnet.c.

Bind:
This bind is triggered every time the bot wants to link to another bot for some reason.
Name:
request-link
Flags:
Ignored.
Match:
The bot's type.
Parameters:
user The user record of the bot to be linked.
string The type of the bot. (Same as the match.)
Note:
This bind is stackable and breakable.
Returns:
A function should return BIND_RET_BREAK if it tried to establish a link or 0 otherwise.

Definition at line 76 of file botnet.c.

char* default_botname = "eggdrop" [static]

Definition at line 44 of file botnet.c.

Referenced by botnet_init(), botnet_set_name(), and botnet_shutdown().

int linking_bots = 0 [static]

Number of bots that are currently in the process of being linked.

Definition at line 49 of file botnet.c.

Referenced by botnet_autolink(), botnet_find_min(), botnet_link(), botnet_link_failed(), and botnet_link_success().

Definition at line 47 of file botnet.c.

int nbots = 0 [static]

const char rcsid[] = "$Id: botnet.c,v 1.13 2007-09-13 22:20:55 sven Exp $" [static]

Definition at line 31 of file botnet.c.


Generated on Sun Nov 30 18:43:33 2008 for eggdrop1.9 by  doxygen 1.5.6