00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "main.h"
00032 #include "tandem.h"
00033
00034 extern int dcc_total, backgrd, connect_timeout, max_dcc, egg_numver;
00035 extern struct userrec *userlist;
00036 extern struct dcc_t *dcc;
00037 extern time_t now;
00038 extern Tcl_Interp *interp;
00039
00040 tand_t *tandbot;
00041 party_t *party;
00042 static int maxparty = 50;
00043 int tands = 0;
00044 int parties = 0;
00045 char botnetnick[HANDLEN + 1] = "";
00046 int share_unlinks = 0;
00047
00048
00049 int expmem_botnet()
00050 {
00051 int size = 0, i;
00052 tand_t *bot;
00053
00054 for (bot = tandbot; bot; bot = bot->next)
00055 size += sizeof(tand_t);
00056 size += (maxparty * sizeof(party_t));
00057 for (i = 0; i < parties; i++) {
00058 if (party[i].away)
00059 size += strlen(party[i].away) + 1;
00060 if (party[i].from)
00061 size += strlen(party[i].from) + 1;
00062 }
00063 return size;
00064 }
00065
00066 void init_bots()
00067 {
00068 tandbot = NULL;
00069
00070 maxparty = 50;
00071 party = nmalloc(maxparty * sizeof(*party));
00072 }
00073
00074 tand_t *findbot(char *who)
00075 {
00076 tand_t *ptr;
00077
00078 for (ptr = tandbot; ptr; ptr = ptr->next)
00079 if (!egg_strcasecmp(ptr->bot, who))
00080 return ptr;
00081 return NULL;
00082 }
00083
00084
00085
00086 void addbot(char *who, char *from, char *next, char flag, int vernum)
00087 {
00088 tand_t **ptr = &tandbot, *ptr2;
00089
00090 while (*ptr) {
00091 if (!egg_strcasecmp((*ptr)->bot, who))
00092 putlog(LOG_BOTS, "*", "!!! Duplicate botnet bot entry!!");
00093 ptr = &((*ptr)->next);
00094 }
00095 ptr2 = nmalloc(sizeof(tand_t));
00096 strncpy(ptr2->bot, who, HANDLEN);
00097 ptr2->bot[HANDLEN] = 0;
00098 ptr2->share = flag;
00099 ptr2->ver = vernum;
00100 ptr2->next = *ptr;
00101 *ptr = ptr2;
00102
00103 ptr2->via = findbot(from);
00104 if (!egg_strcasecmp(next, botnetnick))
00105 ptr2->uplink = (tand_t *) 1;
00106 else
00107 ptr2->uplink = findbot(next);
00108 tands++;
00109 }
00110
00111 void updatebot(int idx, char *who, char share, int vernum)
00112 {
00113 tand_t *ptr = findbot(who);
00114
00115 if (ptr) {
00116 if (share)
00117 ptr->share = share;
00118 if (vernum)
00119 ptr->ver = vernum;
00120 botnet_send_update(idx, ptr);
00121 }
00122 }
00123
00124
00125
00126
00127 int partysock(char *bot, char *nick)
00128 {
00129 int i;
00130
00131 for (i = 0; i < parties; i++) {
00132 if ((!egg_strcasecmp(party[i].bot, bot)) &&
00133 (!egg_strcasecmp(party[i].nick, nick)))
00134 return party[i].sock;
00135 }
00136 return 0;
00137 }
00138
00139
00140
00141 int addparty(char *bot, char *nick, int chan, char flag, int sock,
00142 char *from, int *idx)
00143 {
00144 int i;
00145
00146 for (i = 0; i < parties; i++) {
00147
00148 if (!egg_strcasecmp(party[i].bot, bot) && (party[i].sock == sock)) {
00149 int oldchan = party[i].chan;
00150
00151 party[i].chan = chan;
00152 party[i].timer = now;
00153 if (from[0]) {
00154 if (flag == ' ')
00155 flag = '-';
00156 party[i].flag = flag;
00157 if (party[i].from)
00158 nfree(party[i].from);
00159 party[i].from = nmalloc(strlen(from) + 1);
00160 strcpy(party[i].from, from);
00161 }
00162 *idx = i;
00163 return oldchan;
00164 }
00165 }
00166
00167 if (parties == maxparty) {
00168 maxparty += 50;
00169 party = (party_t *) nrealloc((void *) party, maxparty * sizeof(party_t));
00170 }
00171 strncpy(party[parties].nick, nick, HANDLEN);
00172 party[parties].nick[HANDLEN] = 0;
00173 strncpy(party[parties].bot, bot, HANDLEN);
00174 party[parties].bot[HANDLEN] = 0;
00175 party[parties].chan = chan;
00176 party[parties].sock = sock;
00177 party[parties].status = 0;
00178 party[parties].away = 0;
00179 party[parties].timer = now;
00180 if (from[0]) {
00181 if (flag == ' ')
00182 flag = '-';
00183 party[parties].flag = flag;
00184 party[parties].from = nmalloc(strlen(from) + 1);
00185 strcpy(party[parties].from, from);
00186 } else {
00187 party[parties].flag = ' ';
00188 party[parties].from = nmalloc(10);
00189 strcpy(party[parties].from, "(unknown)");
00190 }
00191 *idx = parties;
00192 parties++;
00193 return -1;
00194 }
00195
00196
00197
00198 void partystat(char *bot, int sock, int add, int rem)
00199 {
00200 int i;
00201
00202 for (i = 0; i < parties; i++) {
00203 if ((!egg_strcasecmp(party[i].bot, bot)) && (party[i].sock == sock)) {
00204 party[i].status |= add;
00205 party[i].status &= ~rem;
00206 }
00207 }
00208 }
00209
00210
00211
00212 void partysetidle(char *bot, int sock, int secs)
00213 {
00214 int i;
00215
00216 for (i = 0; i < parties; i++) {
00217 if ((!egg_strcasecmp(party[i].bot, bot)) && (party[i].sock == sock)) {
00218 party[i].timer = (now - (time_t) secs);
00219 }
00220 }
00221 }
00222
00223
00224
00225 int getparty(char *bot, int sock)
00226 {
00227 int i;
00228
00229 for (i = 0; i < parties; i++) {
00230 if (!egg_strcasecmp(party[i].bot, bot) && (party[i].sock == sock)) {
00231 return i;
00232 }
00233 }
00234 return -1;
00235 }
00236
00237
00238
00239 int partyidle(char *bot, char *nick)
00240 {
00241 int i, ok = 0;
00242
00243 for (i = 0; i < parties; i++) {
00244 if ((!egg_strcasecmp(party[i].bot, bot)) &&
00245 (!egg_strcasecmp(party[i].nick, nick))) {
00246 party[i].timer = now;
00247 ok = 1;
00248 }
00249 }
00250 return ok;
00251 }
00252
00253
00254
00255 int partynick(char *bot, int sock, char *nick)
00256 {
00257 char work[HANDLEN + 1];
00258 int i;
00259
00260 for (i = 0; i < parties; i++) {
00261 if (!egg_strcasecmp(party[i].bot, bot) && (party[i].sock == sock)) {
00262 strcpy(work, party[i].nick);
00263 strncpy(party[i].nick, nick, HANDLEN);
00264 party[i].nick[HANDLEN] = 0;
00265 strcpy(nick, work);
00266 return i;
00267 }
00268 }
00269 return -1;
00270 }
00271
00272
00273
00274 void partyaway(char *bot, int sock, char *msg)
00275 {
00276 int i;
00277
00278 for (i = 0; i < parties; i++) {
00279 if ((!egg_strcasecmp(party[i].bot, bot)) && (party[i].sock == sock)) {
00280 if (party[i].away)
00281 nfree(party[i].away);
00282 if (msg[0]) {
00283 party[i].away = nmalloc(strlen(msg) + 1);
00284 strcpy(party[i].away, msg);
00285 } else
00286 party[i].away = 0;
00287 }
00288 }
00289 }
00290
00291
00292 void rembot(char *whoin)
00293 {
00294 tand_t **ptr = &tandbot, *ptr2;
00295 struct userrec *u;
00296 char *who = NULL;
00297 size_t len = 0;
00298
00299
00300 len = strlen(whoin);
00301 who = nmalloc(len + 1);
00302 strncpyz(who, whoin, len + 1);
00303
00304 while (*ptr) {
00305 if (!egg_strcasecmp((*ptr)->bot, who))
00306 break;
00307 ptr = &((*ptr)->next);
00308 }
00309 if (!*ptr) {
00310
00311 nfree(who);
00312 return;
00313 }
00314 check_tcl_disc(who);
00315
00316 u = get_user_by_handle(userlist, who);
00317 if (u != NULL)
00318 touch_laston(u, "unlinked", now);
00319
00320 ptr2 = *ptr;
00321 *ptr = ptr2->next;
00322 nfree(ptr2);
00323 tands--;
00324
00325 dupwait_notify(who);
00326 nfree(who);
00327 }
00328
00329 void remparty(char *bot, int sock)
00330 {
00331 int i;
00332
00333 for (i = 0; i < parties; i++)
00334 if ((!egg_strcasecmp(party[i].bot, bot)) && (party[i].sock == sock)) {
00335 parties--;
00336 if (party[i].from)
00337 nfree(party[i].from);
00338 if (party[i].away)
00339 nfree(party[i].away);
00340 if (i < parties) {
00341 strcpy(party[i].bot, party[parties].bot);
00342 strcpy(party[i].nick, party[parties].nick);
00343 party[i].chan = party[parties].chan;
00344 party[i].sock = party[parties].sock;
00345 party[i].flag = party[parties].flag;
00346 party[i].status = party[parties].status;
00347 party[i].timer = party[parties].timer;
00348 party[i].from = party[parties].from;
00349 party[i].away = party[parties].away;
00350 }
00351 }
00352 }
00353
00354
00355
00356 void rempartybot(char *bot)
00357 {
00358 int i;
00359
00360 for (i = 0; i < parties; i++)
00361 if (!egg_strcasecmp(party[i].bot, bot)) {
00362 if (party[i].chan >= 0)
00363 check_tcl_chpt(bot, party[i].nick, party[i].sock, party[i].chan);
00364 remparty(bot, party[i].sock);
00365 i--;
00366 }
00367 }
00368
00369
00370
00371 void unvia(int idx, tand_t *who)
00372 {
00373 tand_t *bot, *bot2;
00374
00375 if (!who)
00376 return;
00377 rempartybot(who->bot);
00378 bot = tandbot;
00379 while (bot) {
00380 if (bot->uplink == who) {
00381 unvia(idx, bot);
00382 bot2 = bot->next;
00383 rembot(bot->bot);
00384 bot = bot2;
00385 } else
00386 bot = bot->next;
00387 }
00388 #ifndef NO_OLD_BOTNET
00389
00390
00391
00392 tandout_but(idx, "unlinked %s\n", who->bot);
00393 #endif
00394 }
00395
00396
00397
00398 int nextbot(char *who)
00399 {
00400 int j;
00401 tand_t *bot = findbot(who);
00402
00403 if (!bot)
00404 return -1;
00405
00406 for (j = 0; j < dcc_total; j++)
00407 if (bot->via && !egg_strcasecmp(bot->via->bot, dcc[j].nick) &&
00408 (dcc[j].type == &DCC_BOT))
00409 return j;
00410 return -1;
00411 }
00412
00413
00414
00415 char *lastbot(char *who)
00416 {
00417 tand_t *bot = findbot(who);
00418
00419 if (!bot)
00420 return "*";
00421 else if (bot->uplink == (tand_t *) 1)
00422 return botnetnick;
00423 else
00424 return bot->uplink->bot;
00425 }
00426
00427
00428
00429 void answer_local_whom(int idx, int chan)
00430 {
00431 char format[81];
00432 char c, idle[40];
00433 int i, t, nicklen, botnicklen, total = 0;
00434
00435 if (chan == -1)
00436 dprintf(idx, "%s (+: %s, *: %s)\n", BOT_BOTNETUSERS, BOT_PARTYLINE,
00437 BOT_LOCALCHAN);
00438 else if (chan > 0) {
00439 simple_sprintf(idle, "assoc %d", chan);
00440 if ((Tcl_Eval(interp, idle) != TCL_OK) || tcl_resultempty())
00441 dprintf(idx, "%s %s%d:\n", BOT_USERSONCHAN,
00442 (chan < GLOBAL_CHANS) ? "" : "*", chan % GLOBAL_CHANS);
00443 else
00444 dprintf(idx, "%s '%s%s' (%s%d):\n", BOT_USERSONCHAN,
00445 (chan < GLOBAL_CHANS) ? "" : "*", tcl_resultstring(),
00446 (chan < GLOBAL_CHANS) ? "" : "*", chan % GLOBAL_CHANS);
00447 }
00448
00449 nicklen = botnicklen = 0;
00450 for (i = 0; i < dcc_total; i++)
00451 if (dcc[i].type == &DCC_CHAT) {
00452 if ((chan == -1) || ((chan >= 0) && (dcc[i].u.chat->channel == chan))) {
00453 t = strlen(dcc[i].nick);
00454 if (t > nicklen)
00455 nicklen = t;
00456 t = strlen(botnetnick);
00457 if (t > botnicklen)
00458 botnicklen = t;
00459 }
00460 }
00461 for (i = 0; i < parties; i++) {
00462 if ((chan == -1) || ((chan >= 0) && (party[i].chan == chan))) {
00463 t = strlen(party[i].nick);
00464 if (t > nicklen)
00465 nicklen = t;
00466 t = strlen(party[i].bot);
00467 if (t > botnicklen)
00468 botnicklen = t;
00469 }
00470 }
00471 if (nicklen < 9)
00472 nicklen = 9;
00473 if (botnicklen < 9)
00474 botnicklen = 9;
00475
00476 egg_snprintf(format, sizeof format, "%%-%us %%-%us %%s\n",
00477 nicklen, botnicklen);
00478 dprintf(idx, format, " Nick", " Bot", " Host");
00479 dprintf(idx, format, "----------", "---------", "--------------------");
00480 egg_snprintf(format, sizeof format, "%%c%%-%us %%c %%-%us %%s%%s\n",
00481 nicklen, botnicklen);
00482 for (i = 0; i < dcc_total; i++)
00483 if (dcc[i].type == &DCC_CHAT) {
00484 if ((chan == -1) || ((chan >= 0) && (dcc[i].u.chat->channel == chan))) {
00485 c = geticon(i);
00486 if (c == '-')
00487 c = ' ';
00488 if (now - dcc[i].timeval > 300) {
00489 unsigned long days, hrs, mins;
00490
00491 days = (now - dcc[i].timeval) / 86400;
00492 hrs = ((now - dcc[i].timeval) - (days * 86400)) / 3600;
00493 mins = ((now - dcc[i].timeval) - (hrs * 3600)) / 60;
00494 if (days > 0)
00495 sprintf(idle, " [idle %lud%luh]", days, hrs);
00496 else if (hrs > 0)
00497 sprintf(idle, " [idle %luh%lum]", hrs, mins);
00498 else
00499 sprintf(idle, " [idle %lum]", mins);
00500 } else
00501 idle[0] = 0;
00502 total++;
00503 dprintf(idx, format, c, dcc[i].nick,
00504 (dcc[i].u.chat->channel == 0) && (chan == -1) ? '+' :
00505 (dcc[i].u.chat->channel >= GLOBAL_CHANS) &&
00506 (chan == -1) ? '*' : ' ', botnetnick, dcc[i].host, idle);
00507 if (dcc[i].u.chat->away != NULL)
00508 dprintf(idx, " AWAY: %s\n", dcc[i].u.chat->away);
00509 }
00510 }
00511 for (i = 0; i < parties; i++) {
00512 if ((chan == -1) || ((chan >= 0) && (party[i].chan == chan))) {
00513 c = party[i].flag;
00514 if (c == '-')
00515 c = ' ';
00516 if (party[i].timer == 0L)
00517 strcpy(idle, " [idle?]");
00518 else if (now - party[i].timer > 300) {
00519 unsigned long days, hrs, mins;
00520
00521 days = (now - party[i].timer) / 86400;
00522 hrs = ((now - party[i].timer) - (days * 86400)) / 3600;
00523 mins = ((now - party[i].timer) - (hrs * 3600)) / 60;
00524 if (days > 0)
00525 sprintf(idle, " [idle %lud%luh]", days, hrs);
00526 else if (hrs > 0)
00527 sprintf(idle, " [idle %luh%lum]", hrs, mins);
00528 else
00529 sprintf(idle, " [idle %lum]", mins);
00530 } else
00531 idle[0] = 0;
00532 total++;
00533 dprintf(idx, format, c, party[i].nick,
00534 (party[i].chan == 0) && (chan == -1) ? '+' : ' ',
00535 party[i].bot, party[i].from, idle);
00536 if (party[i].status & PLSTAT_AWAY)
00537 dprintf(idx, " %s: %s\n", MISC_AWAY,
00538 party[i].away ? party[i].away : "");
00539 }
00540 }
00541 dprintf(idx, "Total users: %d\n", total);
00542 }
00543
00544
00545
00546 void tell_bots(int idx)
00547 {
00548 char s[512];
00549 int i;
00550 tand_t *bot;
00551
00552 if (!tands) {
00553 dprintf(idx, "%s\n", BOT_NOBOTSLINKED);
00554 return;
00555 }
00556 strcpy(s, botnetnick);
00557 i = strlen(botnetnick);
00558
00559 for (bot = tandbot; bot; bot = bot->next) {
00560 if (i > (500 - HANDLEN)) {
00561 dprintf(idx, "Bots: %s\n", s);
00562 s[0] = 0;
00563 i = 0;
00564 }
00565 if (i) {
00566 s[i++] = ',';
00567 s[i++] = ' ';
00568 }
00569 strcpy(s + i, bot->bot);
00570 i += strlen(bot->bot);
00571 }
00572 if (s[0])
00573 dprintf(idx, "Bots: %s\n", s);
00574 dprintf(idx, "%s: %d\n", MISC_TOTAL, tands + 1);
00575 }
00576
00577
00578
00579 void tell_bottree(int idx, int showver)
00580 {
00581 char s[161];
00582 tand_t *last[20], *this, *bot, *bot2 = NULL;
00583 int lev = 0, more = 1, mark[20], ok, cnt, i, imark;
00584 char work[1024];
00585 int tothops = 0;
00586
00587 if (tands == 0) {
00588 dprintf(idx, "%s\n", BOT_NOBOTSLINKED);
00589 return;
00590 }
00591 s[0] = 0;
00592 i = 0;
00593
00594 for (bot = tandbot; bot; bot = bot->next)
00595 if (!bot->uplink) {
00596 if (i) {
00597 s[i++] = ',';
00598 s[i++] = ' ';
00599 }
00600 strcpy(s + i, bot->bot);
00601 i += strlen(bot->bot);
00602 }
00603 if (s[0])
00604 dprintf(idx, "(%s %s)\n", BOT_NOTRACEINFO, s);
00605 if (showver)
00606 dprintf(idx, "%s (%d.%d.%d.%d)\n", botnetnick,
00607 egg_numver / 1000000,
00608 egg_numver % 1000000 / 10000,
00609 egg_numver % 10000 / 100, egg_numver % 100);
00610 else
00611 dprintf(idx, "%s\n", botnetnick);
00612 this = (tand_t *) 1;
00613 work[0] = 0;
00614 while (more) {
00615 if (lev == 20) {
00616 dprintf(idx, "\n%s\n", BOT_COMPLEXTREE);
00617 return;
00618 }
00619 cnt = 0;
00620 tothops += lev;
00621 for (bot = tandbot; bot; bot = bot->next)
00622 if (bot->uplink == this)
00623 cnt++;
00624 if (cnt) {
00625 imark = 0;
00626 for (i = 0; i < lev; i++) {
00627 if (mark[i])
00628 strcpy(work + imark, " | ");
00629 else
00630 strcpy(work + imark, " ");
00631 imark += 5;
00632 }
00633 if (cnt > 1)
00634 strcpy(work + imark, " |-");
00635 else
00636 strcpy(work + imark, " `-");
00637 s[0] = 0;
00638 bot = tandbot;
00639 while (!s[0]) {
00640 if (bot->uplink == this) {
00641 if (bot->ver) {
00642 i = sprintf(s, "%c%s", bot->share, bot->bot);
00643 if (showver)
00644 sprintf(s + i, " (%d.%d.%d.%d)",
00645 bot->ver / 1000000,
00646 bot->ver % 1000000 / 10000,
00647 bot->ver % 10000 / 100, bot->ver % 100);
00648 } else
00649 sprintf(s, "-%s", bot->bot);
00650 } else
00651 bot = bot->next;
00652 }
00653 dprintf(idx, "%s%s\n", work, s);
00654 if (cnt > 1)
00655 mark[lev] = 1;
00656 else
00657 mark[lev] = 0;
00658 work[0] = 0;
00659 last[lev] = this;
00660 this = bot;
00661 lev++;
00662 more = 1;
00663 } else {
00664 while (cnt == 0) {
00665
00666 if (lev == 0) {
00667 dprintf(idx, "(( tree error ))\n");
00668 return;
00669 }
00670 ok = 0;
00671 for (bot = tandbot; bot; bot = bot->next) {
00672 if (bot->uplink == last[lev - 1]) {
00673 if (this == bot)
00674 ok = 1;
00675 else if (ok) {
00676 cnt++;
00677 if (cnt == 1) {
00678 bot2 = bot;
00679 if (bot->ver) {
00680 i = sprintf(s, "%c%s", bot->share, bot->bot);
00681 if (showver)
00682 sprintf(s + i, " (%d.%d.%d.%d)",
00683 bot->ver / 1000000,
00684 bot->ver % 1000000 / 10000,
00685 bot->ver % 10000 / 100, bot->ver % 100);
00686 } else
00687 sprintf(s, "-%s", bot->bot);
00688 }
00689 }
00690 }
00691 }
00692 if (cnt) {
00693 imark = 0;
00694 for (i = 1; i < lev; i++) {
00695 if (mark[i - 1])
00696 strcpy(work + imark, " | ");
00697 else
00698 strcpy(work + imark, " ");
00699 imark += 5;
00700 }
00701 more = 1;
00702 if (cnt > 1)
00703 dprintf(idx, "%s |-%s\n", work, s);
00704 else
00705 dprintf(idx, "%s `-%s\n", work, s);
00706 this = bot2;
00707 work[0] = 0;
00708 if (cnt > 1)
00709 mark[lev - 1] = 1;
00710 else
00711 mark[lev - 1] = 0;
00712 } else {
00713
00714 lev--;
00715 if (lev == 0) {
00716 more = 0;
00717 cnt = 999;
00718 } else {
00719 more = 1;
00720 this = last[lev];
00721 }
00722 }
00723 }
00724 }
00725 }
00726
00727 dprintf(idx, "Average hops: %3.1f, total bots: %d\n",
00728 ((float) tothops) / ((float) tands), tands + 1);
00729 }
00730
00731
00732
00733 void dump_links(int z)
00734 {
00735 register int i, l;
00736 char x[1024];
00737 tand_t *bot;
00738
00739 for (bot = tandbot; bot; bot = bot->next) {
00740 char *p;
00741
00742 if (bot->uplink == (tand_t *) 1)
00743 p = botnetnick;
00744 else
00745 p = bot->uplink->bot;
00746 #ifndef NO_OLD_BOTNET
00747 if (b_numver(z) < NEAT_BOTNET)
00748 l = simple_sprintf(x, "nlinked %s %s %c%d\n", bot->bot,
00749 p, bot->share, bot->ver);
00750 else
00751 #endif
00752 l = simple_sprintf(x, "n %s %s %c%D\n", bot->bot, p,
00753 bot->share, bot->ver);
00754 tputs(dcc[z].sock, x, l);
00755 }
00756 if (!(bot_flags(dcc[z].user) & BOT_ISOLATE)) {
00757
00758 for (i = 0; i < dcc_total; i++) {
00759 if (dcc[i].type == &DCC_CHAT) {
00760 if ((dcc[i].u.chat->channel >= 0) &&
00761 (dcc[i].u.chat->channel < GLOBAL_CHANS)) {
00762 #ifndef NO_OLD_BOTNET
00763 if (b_numver(z) < NEAT_BOTNET)
00764 l = simple_sprintf(x, "join %s %s %d %c%d %s\n",
00765 botnetnick, dcc[i].nick,
00766 dcc[i].u.chat->channel, geticon(i),
00767 dcc[i].sock, dcc[i].host);
00768 else
00769 #endif
00770 l = simple_sprintf(x, "j !%s %s %D %c%D %s\n",
00771 botnetnick, dcc[i].nick,
00772 dcc[i].u.chat->channel, geticon(i),
00773 dcc[i].sock, dcc[i].host);
00774 tputs(dcc[z].sock, x, l);
00775 #ifndef NO_OLD_BOTNET
00776 if (b_numver(z) < NEAT_BOTNET) {
00777 if (dcc[i].u.chat->away) {
00778 l = simple_sprintf(x, "away %s %d %s\n", botnetnick,
00779 dcc[i].sock, dcc[i].u.chat->away);
00780 tputs(dcc[z].sock, x, l);
00781 }
00782 l = simple_sprintf(x, "idle %s %d %d\n", botnetnick,
00783 dcc[i].sock, now - dcc[i].timeval);
00784 } else
00785 #endif
00786 l = simple_sprintf(x, "i %s %D %D %s\n", botnetnick,
00787 dcc[i].sock, now - dcc[i].timeval,
00788 dcc[i].u.chat->away ? dcc[i].u.chat->away : "");
00789 tputs(dcc[z].sock, x, l);
00790 }
00791 }
00792 }
00793 for (i = 0; i < parties; i++) {
00794 #ifndef NO_OLD_BOTNET
00795 if (b_numver(z) < NEAT_BOTNET)
00796 l = simple_sprintf(x, "join %s %s %d %c%d %s\n",
00797 party[i].bot, party[i].nick,
00798 party[i].chan, party[i].flag,
00799 party[i].sock, party[i].from);
00800 else
00801 #endif
00802 l = simple_sprintf(x, "j %s %s %D %c%D %s\n",
00803 party[i].bot, party[i].nick,
00804 party[i].chan, party[i].flag,
00805 party[i].sock, party[i].from);
00806 tputs(dcc[z].sock, x, l);
00807 if ((party[i].status & PLSTAT_AWAY) || (party[i].timer != 0)) {
00808 #ifndef NO_OLD_BOTNET
00809 if (b_numver(z) < NEAT_BOTNET) {
00810 if (party[i].status & PLSTAT_AWAY) {
00811 l = simple_sprintf(x, "away %s %d %s\n", party[i].bot,
00812 party[i].sock, party[i].away);
00813 tputs(dcc[z].sock, x, l);
00814 }
00815 l = simple_sprintf(x, "idle %s %d %d\n", party[i].bot,
00816 party[i].sock, now - party[i].timer);
00817 } else
00818 #endif
00819 l = simple_sprintf(x, "i %s %D %D %s\n", party[i].bot,
00820 party[i].sock, now - party[i].timer,
00821 party[i].away ? party[i].away : "");
00822 tputs(dcc[z].sock, x, l);
00823 }
00824 }
00825 }
00826 }
00827
00828 int in_chain(char *who)
00829 {
00830 if (findbot(who))
00831 return 1;
00832 if (!egg_strcasecmp(who, botnetnick))
00833 return 1;
00834 return 0;
00835 }
00836
00837 int bots_in_subtree(tand_t *bot)
00838 {
00839 int nr = 1;
00840 tand_t *b;
00841
00842 if (!bot)
00843 return 0;
00844 for (b = tandbot; b; b = b->next) {
00845 if (b->bot && (b->uplink == bot)) {
00846 nr += bots_in_subtree(b);
00847 }
00848 }
00849 return nr;
00850 }
00851
00852 int users_in_subtree(tand_t *bot)
00853 {
00854 int i, nr;
00855 tand_t *b;
00856
00857 nr = 0;
00858 if (!bot)
00859 return 0;
00860 for (i = 0; i < parties; i++)
00861 if (!egg_strcasecmp(party[i].bot, bot->bot))
00862 nr++;
00863 for (b = tandbot; b; b = b->next)
00864 if (b->bot && (b->uplink == bot))
00865 nr += users_in_subtree(b);
00866 return nr;
00867 }
00868
00869
00870
00871 int botunlink(int idx, char *nick, char *reason, char *from)
00872 {
00873 char s[20];
00874 register int i;
00875 int bots, users;
00876 tand_t *bot;
00877
00878 if (nick[0] == '*')
00879 dprintf(idx, "%s\n", BOT_UNLINKALL);
00880 for (i = 0; i < dcc_total; i++) {
00881 if ((nick[0] == '*') || !egg_strcasecmp(dcc[i].nick, nick)) {
00882 if (dcc[i].type == &DCC_FORK_BOT) {
00883 if (idx >= 0)
00884 dprintf(idx, "%s: %s -> %s.\n", BOT_KILLLINKATTEMPT,
00885 dcc[i].nick, dcc[i].host);
00886 putlog(LOG_BOTS, "*", "%s: %s -> %s:%d",
00887 BOT_KILLLINKATTEMPT, dcc[i].nick, dcc[i].host, dcc[i].port);
00888 killsock(dcc[i].sock);
00889 lostdcc(i);
00890 if (nick[0] != '*')
00891 return 1;
00892 } else if (dcc[i].type == &DCC_BOT_NEW) {
00893 if (idx >= 0)
00894 dprintf(idx, "%s %s.\n", BOT_ENDLINKATTEMPT, dcc[i].nick);
00895 putlog(LOG_BOTS, "*", "%s %s @ %s:%d",
00896 "Stopped trying to link", dcc[i].nick, dcc[i].host, dcc[i].port);
00897 killsock(dcc[i].sock);
00898 lostdcc(i);
00899 if (nick[0] != '*')
00900 return 1;
00901 } else if (dcc[i].type == &DCC_BOT) {
00902 char s[1024];
00903
00904 if (idx >= 0)
00905 dprintf(idx, "%s %s.\n", BOT_BREAKLINK, dcc[i].nick);
00906 else if ((idx == -3) && (b_status(i) & STAT_SHARE) && !share_unlinks)
00907 return -1;
00908 bot = findbot(dcc[i].nick);
00909 bots = bots_in_subtree(bot);
00910 users = users_in_subtree(bot);
00911 if (reason && reason[0]) {
00912 simple_sprintf(s, "%s %s (%s (%s)) (lost %d bot%s and %d user%s)",
00913 BOT_UNLINKEDFROM, dcc[i].nick, reason, from, bots,
00914 (bots != 1) ? "s" : "", users, (users != 1) ?
00915 "s" : "");
00916 dprintf(i, "bye %s\n", reason);
00917 } else {
00918 simple_sprintf(s, "%s %s (%s) (lost %d bot%s and %d user%s)",
00919 BOT_UNLINKEDFROM, dcc[i].nick, from, bots,
00920 (bots != 1) ? "s" : "", users,
00921 (users != 1) ? "s" : "");
00922 dprintf(i, "bye No reason\n");
00923 }
00924 chatout("*** %s\n", s);
00925 botnet_send_unlinked(i, dcc[i].nick, s);
00926 killsock(dcc[i].sock);
00927 lostdcc(i);
00928 if (nick[0] != '*')
00929 return 1;
00930 }
00931 }
00932 }
00933 if (idx >= 0 && nick[0] != '*')
00934 dprintf(idx, "%s\n", BOT_NOTCONNECTED);
00935 if (nick[0] != '*') {
00936 bot = findbot(nick);
00937 if (bot) {
00938
00939
00940
00941
00942 char *ghost = "BUG!!: Found bot `%s' in internal bot list, but it\n"
00943 " shouldn't have been there! Removing.\n"
00944 " This is a known bug we haven't fixed yet. If this\n"
00945 " bot is the newest eggdrop version available and you\n"
00946 " know a *reliable* way to reproduce the bug, please\n"
00947 " contact us - we need your help!\n";
00948 if (idx >= 0)
00949 dprintf(idx, ghost, nick);
00950 else
00951 putlog(LOG_MISC, "*", ghost, nick);
00952 rembot(bot->bot);
00953 return 1;
00954 }
00955 }
00956 if (nick[0] == '*') {
00957 dprintf(idx, "%s\n", BOT_WIPEBOTTABLE);
00958 while (tandbot)
00959 rembot(tandbot->bot);
00960 while (parties) {
00961 parties--;
00962
00963 if (party[i].chan >= 0)
00964 check_tcl_chpt(party[i].bot, party[i].nick, party[i].sock,
00965 party[i].chan);
00966 }
00967 strcpy(s, "killassoc &");
00968 Tcl_Eval(interp, s);
00969 }
00970 return 0;
00971 }
00972
00973 static void botlink_resolve_success(int);
00974 static void botlink_resolve_failure(int);
00975
00976
00977
00978 int botlink(char *linker, int idx, char *nick)
00979 {
00980 struct bot_addr *bi;
00981 struct userrec *u;
00982 register int i;
00983
00984 u = get_user_by_handle(userlist, nick);
00985 if (!u || !(u->flags & USER_BOT)) {
00986 if (idx >= 0)
00987 dprintf(idx, "%s %s\n", nick, BOT_BOTUNKNOWN);
00988 } else if (!egg_strcasecmp(nick, botnetnick)) {
00989 if (idx >= 0)
00990 dprintf(idx, "%s\n", BOT_CANTLINKMYSELF);
00991 } else if (in_chain(nick) && (idx != -3)) {
00992 if (idx >= 0)
00993 dprintf(idx, "%s\n", BOT_ALREADYLINKED);
00994 } else {
00995 for (i = 0; i < dcc_total; i++)
00996 if ((dcc[i].user == u) &&
00997 ((dcc[i].type == &DCC_FORK_BOT) || (dcc[i].type == &DCC_BOT_NEW))) {
00998 if (idx >= 0)
00999 dprintf(idx, "%s\n", BOT_ALREADYLINKING);
01000 return 0;
01001 }
01002
01003 bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
01004 if (!bi || !strlen(bi->address) || !bi->telnet_port ||
01005 (bi->telnet_port <= 0)) {
01006 if (idx >= 0) {
01007 dprintf(idx, "%s '%s'.\n", BOT_NOTELNETADDY, nick);
01008 dprintf(idx, "%s .chaddr %s %s\n",
01009 MISC_USEFORMAT, nick, MISC_CHADDRFORMAT);
01010 }
01011 } else if (dcc_total == max_dcc && increase_socks_max()) {
01012 if (idx >= 0)
01013 dprintf(idx, "%s\n", DCC_TOOMANYDCCS1);
01014 } else {
01015 correct_handle(nick);
01016
01017 if (idx > -2)
01018 putlog(LOG_BOTS, "*", "%s %s at %s:%d ...", BOT_LINKING, nick,
01019 bi->address, bi->telnet_port);
01020
01021 i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
01022 dcc[i].timeval = now;
01023 dcc[i].port = bi->telnet_port;
01024 dcc[i].user = u;
01025 strcpy(dcc[i].nick, nick);
01026 strcpy(dcc[i].host, bi->address);
01027 dcc[i].u.dns->ibuf = idx;
01028 dcc[i].u.dns->cptr = get_data_ptr(strlen(linker) + 1);
01029 strcpy(dcc[i].u.dns->cptr, linker);
01030 dcc[i].u.dns->host = get_data_ptr(strlen(dcc[i].host) + 1);
01031 strcpy(dcc[i].u.dns->host, dcc[i].host);
01032 dcc[i].u.dns->dns_success = botlink_resolve_success;
01033 dcc[i].u.dns->dns_failure = botlink_resolve_failure;
01034 dcc[i].u.dns->dns_type = RES_IPBYHOST;
01035 dcc[i].u.dns->type = &DCC_FORK_BOT;
01036 dcc_dnsipbyhost(bi->address);
01037 return 1;
01038 }
01039 }
01040 return 0;
01041 }
01042
01043 static void botlink_resolve_failure(int i)
01044 {
01045 char s[81];
01046
01047 putlog(LOG_BOTS, "*", DCC_LINKFAIL, dcc[i].nick);
01048 strcpy(s, dcc[i].nick);
01049 nfree(dcc[i].u.dns->cptr);
01050 lostdcc(i);
01051 autolink_cycle(s);
01052 }
01053
01054 static void botlink_resolve_success(int i)
01055 {
01056 int idx = dcc[i].u.dns->ibuf;
01057 char *linker = dcc[i].u.dns->cptr;
01058
01059 dcc[i].addr = dcc[i].u.dns->ip;
01060 changeover_dcc(i, &DCC_FORK_BOT, sizeof(struct bot_info));
01061 dcc[i].timeval = now;
01062 strcpy(dcc[i].u.bot->linker, linker);
01063 strcpy(dcc[i].u.bot->version, "(primitive bot)");
01064 dcc[i].u.bot->numver = idx;
01065 dcc[i].u.bot->port = dcc[i].port;
01066 dcc[i].sock = getsock(SOCK_STRONGCONN);
01067 nfree(linker);
01068 if (dcc[i].sock < 0 ||
01069 open_telnet_raw(dcc[i].sock, iptostr(htonl(dcc[i].addr)),
01070 dcc[i].port) < 0)
01071 failed_link(i);
01072 }
01073
01074 static void failed_tandem_relay(int idx)
01075 {
01076 int uidx = -1, i;
01077
01078 for (i = 0; i < dcc_total; i++)
01079 if ((dcc[i].type == &DCC_PRE_RELAY) &&
01080 (dcc[i].u.relay->sock == dcc[idx].sock))
01081 uidx = i;
01082 if (uidx < 0) {
01083 putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
01084 dcc[idx].sock, dcc[idx].u.relay->sock);
01085 killsock(dcc[idx].sock);
01086 lostdcc(idx);
01087 return;
01088 }
01089 if (dcc[idx].port >= dcc[idx].u.relay->port + 3) {
01090 struct chat_info *ci = dcc[uidx].u.relay->chat;
01091
01092 dprintf(uidx, "%s %s.\n", BOT_CANTLINKTO, dcc[idx].nick);
01093 dcc[uidx].status = dcc[uidx].u.relay->old_status;
01094 nfree(dcc[uidx].u.relay);
01095 dcc[uidx].u.chat = ci;
01096 dcc[uidx].type = &DCC_CHAT;
01097 killsock(dcc[idx].sock);
01098 lostdcc(idx);
01099 return;
01100 }
01101 killsock(dcc[idx].sock);
01102 dcc[idx].sock = getsock(SOCK_STRONGCONN);
01103 dcc[uidx].u.relay->sock = dcc[idx].sock;
01104 dcc[idx].port++;
01105 dcc[idx].timeval = now;
01106 if (dcc[idx].sock < 0 ||
01107 open_telnet_raw(dcc[idx].sock, dcc[idx].addr ?
01108 iptostr(htonl(dcc[idx].addr)) :
01109 dcc[idx].host, dcc[idx].port) < 0)
01110 failed_tandem_relay(idx);
01111 }
01112
01113
01114 static void tandem_relay_resolve_failure(int);
01115 static void tandem_relay_resolve_success(int);
01116
01117
01118
01119 void tandem_relay(int idx, char *nick, register int i)
01120 {
01121 struct userrec *u;
01122 struct bot_addr *bi;
01123 struct chat_info *ci;
01124
01125 u = get_user_by_handle(userlist, nick);
01126 if (!u || !(u->flags & USER_BOT)) {
01127 dprintf(idx, "%s %s\n", nick, BOT_BOTUNKNOWN);
01128 return;
01129 }
01130 if (!egg_strcasecmp(nick, botnetnick)) {
01131 dprintf(idx, "%s\n", BOT_CANTRELAYMYSELF);
01132 return;
01133 }
01134
01135 bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
01136 if (!bi || !strlen(bi->address) || !bi->relay_port || (bi->relay_port <= 0)) {
01137 dprintf(idx, "%s '%s'.\n", BOT_NOTELNETADDY, nick);
01138 dprintf(idx, "%s .chaddr %s %s\n", MISC_USEFORMAT, nick,
01139 MISC_CHADDRFORMAT);
01140 return;
01141 }
01142 i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
01143 if (i < 0) {
01144 dprintf(idx, "%s\n", DCC_TOOMANYDCCS1);
01145 return;
01146 }
01147
01148 dcc[i].sock = getsock(SOCK_STRONGCONN | SOCK_VIRTUAL);
01149 if (dcc[i].sock < 0) {
01150 lostdcc(i);
01151 dprintf(idx, "%s\n", MISC_NOFREESOCK);
01152 return;
01153 }
01154
01155 dcc[i].port = bi->relay_port;
01156 dcc[i].addr = 0L;
01157 strcpy(dcc[i].nick, nick);
01158 dcc[i].user = u;
01159 strcpy(dcc[i].host, bi->address);
01160 dprintf(idx, "%s %s @ %s:%d ...\n", BOT_CONNECTINGTO, nick,
01161 bi->address, bi->relay_port);
01162 dprintf(idx, "%s\n", BOT_BYEINFO1);
01163 dcc[idx].type = &DCC_PRE_RELAY;
01164 ci = dcc[idx].u.chat;
01165 dcc[idx].u.relay = get_data_ptr(sizeof(struct relay_info));
01166 dcc[idx].u.relay->chat = ci;
01167 dcc[idx].u.relay->old_status = dcc[idx].status;
01168 dcc[idx].u.relay->sock = dcc[i].sock;
01169 dcc[i].timeval = now;
01170 dcc[i].u.dns->ibuf = dcc[idx].sock;
01171 dcc[i].u.dns->host = get_data_ptr(strlen(bi->address) + 1);
01172 strcpy(dcc[i].u.dns->host, bi->address);
01173 dcc[i].u.dns->dns_success = tandem_relay_resolve_success;
01174 dcc[i].u.dns->dns_failure = tandem_relay_resolve_failure;
01175 dcc[i].u.dns->dns_type = RES_IPBYHOST;
01176 dcc[i].u.dns->type = &DCC_FORK_RELAY;
01177 dcc_dnsipbyhost(bi->address);
01178 }
01179
01180 static void tandem_relay_resolve_failure(int idx)
01181 {
01182 struct chat_info *ci;
01183 register int uidx = -1, i;
01184
01185 for (i = 0; i < dcc_total; i++)
01186 if ((dcc[i].type == &DCC_PRE_RELAY) &&
01187 (dcc[i].u.relay->sock == dcc[idx].sock)) {
01188 uidx = i;
01189 break;
01190 }
01191 if (uidx < 0) {
01192 putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
01193 dcc[idx].sock, dcc[idx].u.relay->sock);
01194 killsock(dcc[idx].sock);
01195 lostdcc(idx);
01196 return;
01197 }
01198 ci = dcc[uidx].u.relay->chat;
01199 dprintf(uidx, "%s %s.\n", BOT_CANTLINKTO, dcc[idx].nick);
01200 dcc[uidx].status = dcc[uidx].u.relay->old_status;
01201 nfree(dcc[uidx].u.relay);
01202 dcc[uidx].u.chat = ci;
01203 dcc[uidx].type = &DCC_CHAT;
01204 killsock(dcc[idx].sock);
01205 lostdcc(idx);
01206 }
01207
01208 static void tandem_relay_resolve_success(int i)
01209 {
01210 int sock = dcc[i].u.dns->ibuf;
01211
01212 dcc[i].addr = dcc[i].u.dns->ip;
01213 changeover_dcc(i, &DCC_FORK_RELAY, sizeof(struct relay_info));
01214 dcc[i].u.relay->chat = get_data_ptr(sizeof(struct chat_info));
01215
01216 dcc[i].u.relay->sock = sock;
01217 dcc[i].u.relay->port = dcc[i].port;
01218 dcc[i].u.relay->chat->away = NULL;
01219 dcc[i].u.relay->chat->msgs_per_sec = 0;
01220 dcc[i].u.relay->chat->con_flags = 0;
01221 dcc[i].u.relay->chat->buffer = NULL;
01222 dcc[i].u.relay->chat->max_line = 0;
01223 dcc[i].u.relay->chat->line_count = 0;
01224 dcc[i].u.relay->chat->current_lines = 0;
01225 dcc[i].timeval = now;
01226 if (open_telnet_raw(dcc[i].sock, iptostr(htonl(dcc[i].addr)),
01227 dcc[i].port) < 0)
01228 failed_tandem_relay(i);
01229 }
01230
01231
01232
01233 static void pre_relay(int idx, char *buf, register int i)
01234 {
01235 register int tidx = -1;
01236
01237 for (i = 0; i < dcc_total; i++)
01238 if ((dcc[i].type == &DCC_FORK_RELAY) &&
01239 (dcc[i].u.relay->sock == dcc[idx].sock)) {
01240 tidx = i;
01241 break;
01242 }
01243 if (tidx < 0) {
01244
01245 for (i = 0; i < dcc_total; i++)
01246 if ((dcc[i].type == &DCC_DNSWAIT) &&
01247 (dcc[i].sock == dcc[idx].u.relay->sock)) {
01248 tidx = i;
01249 break;
01250 }
01251 }
01252 if (tidx < 0) {
01253 putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
01254 dcc[idx].sock, dcc[idx].u.relay->sock);
01255 killsock(dcc[idx].sock);
01256 lostdcc(idx);
01257 return;
01258 }
01259 if (!egg_strcasecmp(buf, "*bye*")) {
01260
01261 struct chat_info *ci = dcc[idx].u.relay->chat;
01262
01263 dprintf(idx, "%s %s.\n", BOT_ABORTRELAY1, dcc[tidx].nick);
01264 dprintf(idx, "%s %s.\n\n", BOT_ABORTRELAY2, botnetnick);
01265 putlog(LOG_MISC, "*", "%s %s -> %s", BOT_ABORTRELAY3, dcc[idx].nick,
01266 dcc[tidx].nick);
01267 dcc[idx].status = dcc[idx].u.relay->old_status;
01268 nfree(dcc[idx].u.relay);
01269 dcc[idx].u.chat = ci;
01270 dcc[idx].type = &DCC_CHAT;
01271 killsock(dcc[tidx].sock);
01272 lostdcc(tidx);
01273 return;
01274 }
01275 }
01276
01277
01278
01279 static void failed_pre_relay(int idx)
01280 {
01281 register int tidx = -1, i;
01282
01283 for (i = 0; i < dcc_total; i++)
01284 if ((dcc[i].type == &DCC_FORK_RELAY) &&
01285 (dcc[i].u.relay->sock == dcc[idx].sock)) {
01286 tidx = i;
01287 break;
01288 }
01289 if (tidx < 0) {
01290
01291 for (i = 0; i < dcc_total; i++)
01292 if ((dcc[i].type == &DCC_DNSWAIT) &&
01293 (dcc[i].sock == dcc[idx].u.relay->sock)) {
01294 tidx = i;
01295 break;
01296 }
01297 }
01298 if (tidx < 0) {
01299 putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
01300 dcc[idx].sock, dcc[idx].u.relay->sock);
01301 killsock(dcc[idx].sock);
01302 lostdcc(idx);
01303 return;
01304 }
01305 putlog(LOG_MISC, "*", "%s [%s]%s/%d", BOT_LOSTDCCUSER, dcc[idx].nick,
01306 dcc[idx].host, dcc[idx].port);
01307 putlog(LOG_MISC, "*", "(%s %s)", BOT_DROPPINGRELAY, dcc[tidx].nick);
01308 if ((dcc[tidx].sock != STDOUT) || backgrd) {
01309 if (idx > tidx) {
01310 int t = tidx;
01311
01312 tidx = idx;
01313 idx = t;
01314 }
01315 killsock(dcc[tidx].sock);
01316 lostdcc(tidx);
01317 } else
01318 fatal("Lost my terminal?!", 0);
01319 killsock(dcc[idx].sock);
01320 lostdcc(idx);
01321 }
01322
01323 static void cont_tandem_relay(int idx, char *buf, register int i)
01324 {
01325 register int uidx = -1;
01326 struct relay_info *ri;
01327
01328 for (i = 0; i < dcc_total; i++)
01329 if ((dcc[i].type == &DCC_PRE_RELAY) &&
01330 (dcc[i].u.relay->sock == dcc[idx].sock))
01331 uidx = i;
01332 if (uidx < 0) {
01333 putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
01334 dcc[i].sock, dcc[i].u.relay->sock);
01335 killsock(dcc[i].sock);
01336 lostdcc(i);
01337 return;
01338 }
01339 dcc[idx].type = &DCC_RELAY;
01340 dcc[idx].u.relay->sock = dcc[uidx].sock;
01341 dcc[uidx].u.relay->sock = dcc[idx].sock;
01342 dprintf(uidx, "%s %s ...\n", BOT_RELAYSUCCESS, dcc[idx].nick);
01343 dprintf(uidx, "%s\n\n", BOT_BYEINFO2);
01344 putlog(LOG_MISC, "*", "%s %s -> %s", BOT_RELAYLINK,
01345 dcc[uidx].nick, dcc[idx].nick);
01346 ri = dcc[uidx].u.relay;
01347 dcc[uidx].type = &DCC_CHAT;
01348 dcc[uidx].u.chat = ri->chat;
01349 if (dcc[uidx].u.chat->channel >= 0) {
01350 chanout_but(-1, dcc[uidx].u.chat->channel, "*** %s %s\n",
01351 dcc[uidx].nick, BOT_PARTYLEFT);
01352 if (dcc[uidx].u.chat->channel < GLOBAL_CHANS)
01353 botnet_send_part_idx(uidx, NULL);
01354 check_tcl_chpt(botnetnick, dcc[uidx].nick, dcc[uidx].sock,
01355 dcc[uidx].u.chat->channel);
01356 }
01357 check_tcl_chof(dcc[uidx].nick, dcc[uidx].sock);
01358 dcc[uidx].type = &DCC_RELAYING;
01359 dcc[uidx].u.relay = ri;
01360 }
01361
01362 static void eof_dcc_relay(int idx)
01363 {
01364 register int j;
01365 struct chat_info *ci;
01366
01367 for (j = 0; j < dcc_total; j++)
01368 if (dcc[j].sock == dcc[idx].u.relay->sock)
01369 break;
01370 if (j == dcc_total) {
01371 killsock(dcc[idx].sock);
01372 lostdcc(idx);
01373 return;
01374 }
01375 dcc[j].status = dcc[j].u.relay->old_status;
01376
01377 if (dcc[j].status & STAT_TELNET)
01378 dprintf(j, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n");
01379 putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_ENDRELAY1, dcc[j].nick,
01380 dcc[idx].nick);
01381 dprintf(j, "\n\n*** %s %s\n", BOT_ENDRELAY2, botnetnick);
01382 ci = dcc[j].u.relay->chat;
01383 nfree(dcc[j].u.relay);
01384 dcc[j].u.chat = ci;
01385 dcc[j].type = &DCC_CHAT;
01386 if (dcc[j].u.chat->channel >= 0) {
01387 chanout_but(-1, dcc[j].u.chat->channel, "*** %s %s.\n",
01388 dcc[j].nick, BOT_PARTYREJOINED);
01389 if (dcc[j].u.chat->channel < GLOBAL_CHANS)
01390 botnet_send_join_idx(j, -1);
01391 }
01392 check_tcl_chon(dcc[j].nick, dcc[j].sock);
01393 check_tcl_chjn(botnetnick, dcc[j].nick, dcc[j].u.chat->channel,
01394 geticon(j), dcc[j].sock, dcc[j].host);
01395 killsock(dcc[idx].sock);
01396 lostdcc(idx);
01397 }
01398
01399 static void eof_dcc_relaying(int idx)
01400 {
01401 register int j, x = dcc[idx].u.relay->sock;
01402
01403 putlog(LOG_MISC, "*", "%s [%s]%s/%d", BOT_LOSTDCCUSER, dcc[idx].nick,
01404 dcc[idx].host, dcc[idx].port);
01405 killsock(dcc[idx].sock);
01406 lostdcc(idx);
01407 for (j = 0; (dcc[j].sock != x) || (dcc[j].type == &DCC_FORK_RELAY); j++);
01408 putlog(LOG_MISC, "*", "(%s %s)", BOT_DROPPEDRELAY, dcc[j].nick);
01409 killsock(dcc[j].sock);
01410 lostdcc(j);
01411 }
01412
01413 static void dcc_relay(int idx, char *buf, int j)
01414 {
01415 unsigned char *p = (unsigned char *) buf;
01416 int mark;
01417
01418 for (j = 0; dcc[j].sock != dcc[idx].u.relay->sock ||
01419 dcc[j].type != &DCC_RELAYING; j++);
01420
01421
01422 if (!(dcc[j].status & STAT_TELNET)) {
01423 while (*p != 0) {
01424 while (*p != 255 && (*p != '\033' || *(p + 1) != '[') && *p != '\r' && *p)
01425 p++;
01426 if (*p == 255) {
01427 mark = 2;
01428 if (!*(p + 1))
01429 mark = 1;
01430 if ((*(p + 1) >= 251) || (*(p + 1) <= 254)) {
01431 mark = 3;
01432 if (!*(p + 2))
01433 mark = 2;
01434 }
01435 strcpy((char *) p, (char *) (p + mark));
01436 } else if (*p == '\033') {
01437 unsigned char *e;
01438
01439
01440 for (e = p + 2; *e != 'm' && *e; e++);
01441 strcpy((char *) p, (char *) (e + 1));
01442 } else if (*p == '\r')
01443 strcpy((char *) p, (char *) (p + 1));
01444 }
01445 if (!buf[0])
01446 dprintf(-dcc[idx].u.relay->sock, " \n");
01447 else
01448 dprintf(-dcc[idx].u.relay->sock, "%s\n", buf);
01449 return;
01450 }
01451
01452 if (!buf[0])
01453 dprintf(-dcc[idx].u.relay->sock, " \r\n");
01454 else
01455 dprintf(-dcc[idx].u.relay->sock, "%s\r\n", buf);
01456 }
01457
01458 static void dcc_relaying(int idx, char *buf, int j)
01459 {
01460 struct chat_info *ci;
01461
01462 if (egg_strcasecmp(buf, "*bye*")) {
01463 dprintf(-dcc[idx].u.relay->sock, "%s\n", buf);
01464 return;
01465 }
01466 for (j = 0; (dcc[j].sock != dcc[idx].u.relay->sock) ||
01467 (dcc[j].type != &DCC_RELAY); j++);
01468 dcc[idx].status = dcc[idx].u.relay->old_status;
01469
01470 if (dcc[idx].status & STAT_TELNET)
01471 dprintf(idx, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n");
01472 dprintf(idx, "\n(%s %s.)\n", BOT_BREAKRELAY, dcc[j].nick);
01473 dprintf(idx, "%s %s.\n\n", BOT_ABORTRELAY2, botnetnick);
01474 putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_RELAYBROKEN,
01475 dcc[idx].nick, dcc[j].nick);
01476 if (dcc[idx].u.relay->chat->channel >= 0) {
01477 chanout_but(-1, dcc[idx].u.relay->chat->channel,
01478 "*** %s joined the party line.\n", dcc[idx].nick);
01479 if (dcc[idx].u.relay->chat->channel < GLOBAL_CHANS)
01480 botnet_send_join_idx(idx, -1);
01481 }
01482 ci = dcc[idx].u.relay->chat;
01483 nfree(dcc[idx].u.relay);
01484 dcc[idx].u.chat = ci;
01485 dcc[idx].type = &DCC_CHAT;
01486 check_tcl_chon(dcc[idx].nick, dcc[idx].sock);
01487 if (dcc[idx].u.chat->channel >= 0)
01488 check_tcl_chjn(botnetnick, dcc[idx].nick, dcc[idx].u.chat->channel,
01489 geticon(idx), dcc[idx].sock, dcc[idx].host);
01490 killsock(dcc[j].sock);
01491 lostdcc(j);
01492 }
01493
01494 static void display_relay(int i, char *other)
01495 {
01496 sprintf(other, "rela -> sock %d", dcc[i].u.relay->sock);
01497 }
01498
01499 static void display_relaying(int i, char *other)
01500 {
01501 sprintf(other, ">rly -> sock %d", dcc[i].u.relay->sock);
01502 }
01503
01504 static void display_tandem_relay(int i, char *other)
01505 {
01506 strcpy(other, "other rela");
01507 }
01508
01509 static void display_pre_relay(int i, char *other)
01510 {
01511 strcpy(other, "other >rly");
01512 }
01513
01514 static int expmem_relay(void *x)
01515 {
01516 register struct relay_info *p = (struct relay_info *) x;
01517 int tot = sizeof(struct relay_info);
01518
01519 if (p->chat)
01520 tot += DCC_CHAT.expmem(p->chat);
01521 return tot;
01522 }
01523
01524 static void kill_relay(int idx, void *x)
01525 {
01526 register struct relay_info *p = (struct relay_info *) x;
01527
01528 if (p->chat)
01529 DCC_CHAT.kill(idx, p->chat);
01530 nfree(p);
01531 }
01532
01533 struct dcc_table DCC_RELAY = {
01534 "RELAY",
01535 0,
01536 eof_dcc_relay,
01537 dcc_relay,
01538 NULL,
01539 NULL,
01540 display_relay,
01541 expmem_relay,
01542 kill_relay,
01543 NULL
01544 };
01545
01546 static void out_relay(int idx, char *buf, void *x)
01547 {
01548 register struct relay_info *p = (struct relay_info *) x;
01549
01550 if (p && p->chat)
01551 DCC_CHAT.output(idx, buf, p->chat);
01552 else
01553 tputs(dcc[idx].sock, buf, strlen(buf));
01554 }
01555
01556 struct dcc_table DCC_RELAYING = {
01557 "RELAYING",
01558 0,
01559 eof_dcc_relaying,
01560 dcc_relaying,
01561 NULL,
01562 NULL,
01563 display_relaying,
01564 expmem_relay,
01565 kill_relay,
01566 out_relay
01567 };
01568
01569 struct dcc_table DCC_FORK_RELAY = {
01570 "FORK_RELAY",
01571 0,
01572 failed_tandem_relay,
01573 cont_tandem_relay,
01574 &connect_timeout,
01575 failed_tandem_relay,
01576 display_tandem_relay,
01577 expmem_relay,
01578 kill_relay,
01579 NULL
01580 };
01581
01582 struct dcc_table DCC_PRE_RELAY = {
01583 "PRE_RELAY",
01584 0,
01585 failed_pre_relay,
01586 pre_relay,
01587 NULL,
01588 NULL,
01589 display_pre_relay,
01590 expmem_relay,
01591 kill_relay,
01592 NULL
01593 };
01594
01595
01596
01597 void check_botnet_pings()
01598 {
01599 int i;
01600 int bots, users;
01601 tand_t *bot;
01602
01603 for (i = 0; i < dcc_total; i++)
01604 if (dcc[i].type == &DCC_BOT)
01605 if (dcc[i].status & STAT_PINGED) {
01606 char s[1024];
01607
01608 putlog(LOG_BOTS, "*", "%s: %s", BOT_PINGTIMEOUT, dcc[i].nick);
01609 bot = findbot(dcc[i].nick);
01610 bots = bots_in_subtree(bot);
01611 users = users_in_subtree(bot);
01612 simple_sprintf(s, "%s: %s (lost %d bot%s and %d user%s)",
01613 BOT_PINGTIMEOUT, dcc[i].nick, bots,
01614 (bots != 1) ? "s" : "", users, (users != 1) ? "s" : "");
01615 chatout("*** %s\n", s);
01616 botnet_send_unlinked(i, dcc[i].nick, s);
01617 killsock(dcc[i].sock);
01618 lostdcc(i);
01619 }
01620 for (i = 0; i < dcc_total; i++)
01621 if (dcc[i].type == &DCC_BOT) {
01622 botnet_send_ping(i);
01623 dcc[i].status |= STAT_PINGED;
01624 }
01625 for (i = 0; i < dcc_total; i++)
01626 if ((dcc[i].type == &DCC_BOT) && (dcc[i].status & STAT_LEAF)) {
01627 tand_t *bot, *via = findbot(dcc[i].nick);
01628
01629 for (bot = tandbot; bot; bot = bot->next) {
01630 if ((via == bot->via) && (bot != via)) {
01631
01632 if (dcc[i].status & STAT_WARNED) {
01633 char s[1024];
01634
01635 putlog(LOG_BOTS, "*", "%s %s (%s).", BOT_DISCONNECTED,
01636 dcc[i].nick, BOT_BOTNOTLEAFLIKE);
01637 dprintf(i, "bye %s\n", BOT_BOTNOTLEAFLIKE);
01638 bot = findbot(dcc[i].nick);
01639 bots = bots_in_subtree(bot);
01640 users = users_in_subtree(bot);
01641 simple_sprintf(s, "%s %s (%s) (lost %d bot%s and %d user%s)",
01642 BOT_DISCONNECTED, dcc[i].nick, BOT_BOTNOTLEAFLIKE,
01643 bots, (bots != 1) ? "s" : "", users, (users != 1) ?
01644 "s" : "");
01645 chatout("*** %s\n", s);
01646 botnet_send_unlinked(i, dcc[i].nick, s);
01647 killsock(dcc[i].sock);
01648 lostdcc(i);
01649 } else {
01650 botnet_send_reject(i, botnetnick, NULL, bot->bot, NULL, NULL);
01651 dcc[i].status |= STAT_WARNED;
01652 }
01653 } else
01654 dcc[i].status &= ~STAT_WARNED;
01655 }
01656 }
01657 }
01658
01659 void zapfbot(int idx)
01660 {
01661 char s[1024];
01662 int bots, users;
01663 tand_t *bot;
01664
01665 bot = findbot(dcc[idx].nick);
01666 bots = bots_in_subtree(bot);
01667 users = users_in_subtree(bot);
01668 simple_sprintf(s, "%s: %s (lost %d bot%s and %d user%s)", BOT_BOTDROPPED,
01669 dcc[idx].nick, bots, (bots != 1) ? "s" : "", users,
01670 (users != 1) ? "s" : "");
01671 chatout("*** %s\n", s);
01672 botnet_send_unlinked(idx, dcc[idx].nick, s);
01673 killsock(dcc[idx].sock);
01674 lostdcc(idx);
01675 }
01676
01677 void restart_chons()
01678 {
01679 int i;
01680
01681
01682 for (i = 0; i < dcc_total; i++) {
01683 if (dcc[i].type == &DCC_CHAT) {
01684 check_tcl_chon(dcc[i].nick, dcc[i].sock);
01685 check_tcl_chjn(botnetnick, dcc[i].nick, dcc[i].u.chat->channel,
01686 geticon(i), dcc[i].sock, dcc[i].host);
01687 }
01688 }
01689 for (i = 0; i < parties; i++) {
01690 check_tcl_chjn(party[i].bot, party[i].nick, party[i].chan,
01691 party[i].flag, party[i].sock, party[i].from);
01692 }
01693 }