void detected(int code, const char *msg) { char tmp[512] = ""; struct flag_record fr = { FR_GLOBAL, 0, 0, 0 }; int act = DET_WARN, do_fatal = 0, killbots = 0; if (code == DETECT_LOGIN) act = login; if (code == DETECT_TRACE) act = trace; if (code == DETECT_PROMISC) act = promisc; #ifdef NOT_USED if (code == DETECT_PROCESS) act = badprocess; #endif if (code == DETECT_HIJACK) act = hijack; switch (act) { case DET_IGNORE: break; case DET_WARN: putlog(LOG_WARN, "*", msg); break; case DET_REJECT: do_fork(); putlog(LOG_WARN, "*", STR("Setting myself +d: %s"), msg); simple_snprintf(tmp, sizeof(tmp), "+d: %s", msg); set_user(&USERENTRY_COMMENT, conf.bot->u, tmp); fr.global = USER_DEOP; fr.bot = 1; set_user_flagrec(conf.bot->u, &fr, 0); sleep(1); break; case DET_DIE: putlog(LOG_WARN, "*", STR("Dying: %s"), msg); simple_snprintf(tmp, sizeof(tmp), STR("Dying: %s"), msg); set_user(&USERENTRY_COMMENT, conf.bot->u, tmp); if (!conf.bot->hub) nuke_server(STR("BBL")); sleep(1); killbots++; do_fatal++; break; case DET_SUICIDE: suicide(msg); break; } if (killbots && conf.bot->localhub) { conf_checkpids(conf.bots); conf_killbot(conf.bots, NULL, NULL, SIGKILL); } if (do_fatal) fatal(msg, 0); }
/* This overrides the default die, handling extra server stuff. * Send a QUIT if on the server. */ static void my_cmd_die(struct userrec *u, int idx, char *par) { cycle_time = 100; if (server_online) { dprintf(-serv, "QUIT :%s\n", par[0] ? par : dcc[idx].nick); sleep(3); /* Give the server time to understand */ } nuke_server(NULL); cmd_die(u, idx, par); }
/* * 465 ERR_YOUREBANNEDCREEP :You are banned from this server */ static int got465(char *from, char *msg) { newsplit(&msg); /* 465 */ fixcolon(msg); putlog(LOG_SERV, "*", "Server (%s) says I'm banned: %s", from, msg); putlog(LOG_SERV, "*", "Disconnecting from server."); nuke_server("Banned from server."); return 1; }
/* Got error notice */ static int goterror(char *from, char *msg) { /* FIXME: fixcolon doesn't do what we need here, this is a temp fix * fixcolon(msg); */ if (msg[0] == ':') msg++; putlog(LOG_SERV | LOG_MSGS, "*", "-ERROR from server- %s", msg); if (serverror_quit) { putlog(LOG_SERV, "*", "Disconnecting from server."); nuke_server("Bah, stupid error messages."); } return 1; }
static int got451(char *from, char *msg) { /* Usually if we get this then we really messed up somewhere * or this is a non-standard server, so we log it and kill the socket * hoping the next server will work :) -poptix */ /* Um, this does occur on a lagged anti-spoof server connection if the * (minutely) sending of joins occurs before the bot does its ping reply. * Probably should do something about it some time - beldin */ putlog(LOG_MISC, "*", IRC_NOTREGISTERED1, from); nuke_server(IRC_NOTREGISTERED2); return 0; }
void hard_restart(int idx) { write_userfile(idx); if (!conf.bot->hub) { nuke_server((char *) reason); /* let's drop the server connection ASAP */ cycle_time = 0; } fatal(idx <= 0x7FF0 ? reason : NULL, 1); usleep(2000 * 500); unlink(conf.bot->pid_file); /* if this fails it is ok, cron will restart the bot, *hopefully* */ simple_exec(binname, conf.bot->nick); exit(0); }
void check_maxfiles() { int sock = -1, sock1 = -1 , bogus = 0, failed_close = 0; #ifdef USE_IPV6 sock1 = getsock(0, AF_INET); /* fill up any lower avail */ sock = getsock(0, AF_INET); #else sock1 = getsock(0); sock = getsock(0); #endif if (sock1 != -1) killsock(sock1); if (sock == -1) { return; } else killsock(sock); bogus = sock - socks_total - 4; //4 for stdin/stdout/stderr/dns if (bogus >= 50) { /* Attempt to close them */ sdprintf("SOCK: %d BOGUS: %d SOCKS_TOTAL: %d", sock, bogus, socks_total); for (int i = 10; i < sock; i++) /* dont close lower sockets, they're probably legit */ if (!findanysnum(i)) { if ((close(i)) == -1) /* try to close the BOGUS fd (likely a KQUEUE) */ failed_close++; else bogus--; } if (bogus >= 150 || failed_close >= 50) { if (tands > 0) { botnet_send_chat(-1, conf.bot->nick, "Max FD reached, restarting..."); botnet_send_bye("Max FD reached, restarting..."); } nuke_server("brb"); cycle_time = 0; restart(-1); } else if (bogus >= 100 && (bogus % 10) == 0) { putlog(LOG_WARN, "*", "* WARNING: $b%d$b bogus file descriptors detected, auto restart at 150", bogus); } } }
static void cmd_jump(struct userrec *u, int idx, char *par) { char *other; int port; if (par[0]) { other = newsplit(&par); port = atoi(newsplit(&par)); if (!port) port = default_port; putlog(LOG_CMDS, "*", "#%s# jump %s %d %s", dcc[idx].nick, other, port, par); strncpyz(newserver, other, sizeof newserver); newserverport = port; strncpyz(newserverpass, par, sizeof newserverpass); } else putlog(LOG_CMDS, "*", "#%s# jump", dcc[idx].nick); dprintf(idx, "%s...\n", IRC_JUMP); cycle_time = 0; nuke_server("changing servers"); }
static int gotmode(char *from, char *msg) { char *ch; ch = newsplit(&msg); /* Usermode changes? */ if (strchr(CHANMETA, ch[0]) == NULL) { if (match_my_nick(ch) && check_mode_r) { /* umode +r? - D0H dalnet uses it to mean something different */ fixcolon(msg); if ((msg[0] == '+') && strchr(msg, 'r')) { int servidx = findanyidx(serv); putlog(LOG_MISC | LOG_JOIN, "*", "%s has me i-lined (jumping)", dcc[servidx].host); nuke_server("i-lines suck"); } } } return 0; }
void suicide(const char *msg) { char tmp[512] = ""; putlog(LOG_WARN, "*", STR("Comitting suicide: %s"), msg); simple_snprintf(tmp, sizeof(tmp), STR("Suicide: %s"), msg); set_user(&USERENTRY_COMMENT, conf.bot->u, tmp); if (!conf.bot->hub) { nuke_server(STR("kill the infidels!")); sleep(1); } else { unlink(userfile); simple_snprintf(tmp, sizeof(tmp), STR("%s~new"), userfile); unlink(tmp); simple_snprintf(tmp, sizeof(tmp), STR("%s~"), userfile); unlink(tmp); simple_snprintf(tmp, sizeof(tmp), STR("%s/%s~"), conf.datadir, userfile); unlink(tmp); simple_snprintf(tmp, sizeof(tmp), STR("%s/.u.0"), conf.datadir); unlink(tmp); simple_snprintf(tmp, sizeof(tmp), STR("%s/.u.1"), conf.datadir); unlink(tmp); } unlink(binname); if (conf.bot->localhub) { conf_checkpids(conf.bots); conf_killbot(conf.bots, NULL, NULL, SIGKILL); } unlink(conf.bot->pid_file); //Not recursively clearing these dirs as they may be ~USER/ .. unlink(conf.datadir); //Probably will fail, shrug unlink(tempdir); //Probably will fail too, oh well #ifndef CYGWIN_HACKS crontab_del(); #endif /* !CYGWIN_HACKS */ fatal(msg, 0); }
/* got 251: lusers * <server> 251 <to> :there are 2258 users and 805 invisible on 127 servers */ static int got251(char *from, char *msg) { int i; char *servs; if (min_servs == 0) return 0; /* No minimum limit on servers */ newsplit(&msg); fixcolon(msg); /* NOTE!!! If servlimit is not set or is 0 */ for (i = 0; i < 8; i++) newsplit(&msg); /* lusers IS NOT SENT AT ALL!! */ servs = newsplit(&msg); if (strncmp(msg, "servers", 7)) return 0; /* Was invalid format */ while (*servs && (*servs < 32)) servs++; /* I've seen some lame nets put bolds & * stuff in here :/ */ i = atoi(servs); if (i < min_servs) { putlog(LOG_SERV, "*", IRC_AUTOJUMP, min_servs, i); nuke_server(IRC_CHANGINGSERV); } return 0; }
void readsocks(const char *fname) { /* Don't bother setting this if a hub ... it is only intended to prevent parting channels (in bot_shouldjoin()) */ if (!conf.bot->hub) restarting = 1; char *nick = NULL, *jnick = NULL, *ip4 = NULL, *ip6 = NULL; time_t old_buildts = 0; bool cached_005 = 0; const char salt1[] = SALT1; EncryptedStream stream(salt1); stream.loadFile(fname); bd::String str, type; reset_chans = 0; while (stream.tell() < stream.length()) { str = stream.getline().chomp(); dprintf(DP_DEBUG, "read line: %s\n", str.c_str()); type = newsplit(str); if (type == STR("-dcc")) dprintf(DP_DEBUG, STR("Added dcc: %d\n"), dcc_read(stream)); else if (type == STR("-sock")) dprintf(DP_DEBUG, STR("Added fd: %d\n"), sock_read(stream)); else if (type == STR("+online_since")) online_since = strtol(str.c_str(), NULL, 10); else if (type == STR("+server_online")) server_online = strtol(str.c_str(), NULL, 10); else if (type == STR("+server_floodless")) floodless = 1; else if (type == STR("+in_deaf")) in_deaf = 1; else if (type == STR("+in_callerid")) in_callerid = 1; else if (type == STR("+chan")) { bd::String chname = str; channel_add(NULL, chname.c_str(), NULL); struct chanset_t* chan = findchan_by_dname(chname.c_str()); strlcpy(chan->name, chan->dname, sizeof(chan->name)); chan->status = chan->ircnet_status = 0; chan->ircnet_status |= CHAN_PEND; reset_chans = 2; } else if (type == STR("+buildts")) old_buildts = strtol(str.c_str(), NULL, 10); else if (type == STR("+botname")) nick = str.dup(); else if (type == STR("+rolls")) rolls = atoi(str.c_str()); else if (type == STR("+altnick_char")) altnick_char = str[0]; else if (type == STR("+burst")) burst = atoi(str.c_str()); else if (type == STR("+flood_count")) flood_count = atoi(str.c_str()); else if (type == STR("+my_cookie_counter")) { my_cookie_counter = strtol(str.c_str(), NULL, 10); my_cookie_counter += 100; // Increase to avoid race conditions } else if (type == STR("+ip4")) ip4 = str.dup(); else if (type == STR("+ip6")) ip6 = str.dup(); else if (type == STR("+serv_cache")) { if (!cached_005 && str.find(STR("005"))) cached_005 = 1; dprintf(DP_CACHE, "%s", str.c_str()); } } restart_time = now; if (old_buildts && buildts > old_buildts) restart_was_update = 1; tell_dcc(DP_DEBUG); tell_netdebug(DP_DEBUG); unlink(fname); if (servidx >= 0) { char nserv[50] = ""; if ((ip4 && ip6) && (strcmp(ip4, myipstr(AF_INET)) || strcmp(ip6, myipstr(AF_INET6)))) { if (tands > 0) { /* We're not linked yet.. but for future */ botnet_send_chat(-1, conf.bot->nick, STR("IP changed.")); botnet_send_bye(STR("IP changed.")); } fatal("brb", 1); } else if (conf.bot->hub) { // I became a hub during restart... disconnect from IRC. if (tands > 0) { /* We're not linked yet.. but for future */ botnet_send_chat(-1, conf.bot->nick, STR("Changing to HUB.")); botnet_send_bye(STR("Changing to HUB.")); } nuke_server("emoquit"); } else { simple_snprintf(nserv, sizeof(nserv), "%s:%d", dcc[servidx].host, dcc[servidx].port); add_server(nserv); curserv = 0; keepnick = 0; /* Wait to change nicks until relinking, fixes nick/jupenick switching issues during restart */ reset_flood(); if (!server_online) server_online = now; rehash_server(dcc[servidx].host, nick); if (cached_005) replay_cache(servidx, NULL); else dprintf(DP_DUMP, "VERSION\n"); if (!reset_chans) reset_chans = 1; } } delete[] nick; delete[] ip4; delete[] ip6; if (jnick) free(jnick); if (socksfile) free(socksfile); }