/[cvs]/eggdrop1.4/src/botnet.c
ViewVC logotype

Contents of /eggdrop1.4/src/botnet.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.12 - (show annotations) (download) (as text)
Mon May 22 18:37:30 2000 UTC (19 years, 3 months ago) by guppy
Branch: MAIN
Changes since 1.11: +15 -2 lines
File MIME type: text/x-chdr
added fabian's patches, including a small bugfix for the ghostbug workaround

1 /*
2 * botnet.c -- handles:
3 * keeping track of which bot's connected where in the chain
4 * dumping a list of bots or a bot tree to a user
5 * channel name associations on the party line
6 * rejecting a bot
7 * linking, unlinking, and relaying to another bot
8 * pinging the bots periodically and checking leaf status
9 *
10 * dprintf'ized, 28nov1995
11 *
12 * $Id: botnet.c,v 1.11 2000/01/17 16:14:44 per Exp $
13 */
14 /*
15 * Copyright (C) 1997 Robey Pointer
16 * Copyright (C) 1999, 2000 Eggheads
17 *
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 */
32
33 #include "main.h"
34 #include "tandem.h"
35
36 extern char spaces[], spaces2[];
37 extern int dcc_total, backgrd, connect_timeout, max_dcc, egg_numver;
38 extern struct userrec *userlist;
39 extern struct dcc_t *dcc;
40 extern time_t now;
41 extern Tcl_Interp *interp;
42
43 tand_t *tandbot; /* keep track of tandem bots on the botnet */
44 party_t *party; /* keep track of people on the botnet */
45 static int maxparty = 50; /* maximum space for party line members
46 * currently */
47 int tands = 0; /* number of bots on the botnet */
48 int parties = 0; /* number of people on the botnet */
49 char botnetnick[HANDLEN + 1] = ""; /* botnet nickname */
50 int share_unlinks = 0; /* allow remote unlinks of my sharebots ? */
51
52 int expmem_botnet()
53 {
54 int size = 0, i;
55 tand_t *bot;
56
57 for (bot = tandbot; bot; bot = bot->next)
58 size += sizeof(tand_t);
59 Context;
60 size += (maxparty * sizeof(party_t));
61 for (i = 0; i < parties; i++) {
62 if (party[i].away)
63 size += strlen(party[i].away) + 1;
64 if (party[i].from)
65 size += strlen(party[i].from) + 1;
66 }
67 return size;
68 }
69
70 void init_bots()
71 {
72 tandbot = NULL;
73 /* grab space for 50 bots for now -- expand later as needed */
74 maxparty = 50;
75 party = (party_t *) nmalloc(maxparty * sizeof(party_t));
76 }
77
78 tand_t *findbot(char *who)
79 {
80 tand_t *ptr = tandbot;
81
82 while (ptr) {
83 if (!strcasecmp(ptr->bot, who))
84 return ptr;
85 ptr = ptr->next;
86 }
87 return NULL;
88 }
89
90 /* add a tandem bot to our chain list */
91 void addbot(char *who, char *from, char *next, char flag, int vernum)
92 {
93 tand_t **ptr = &tandbot, *ptr2;
94
95 Context;
96 while (*ptr) {
97 if (!strcasecmp((*ptr)->bot, who))
98 putlog(LOG_BOTS, "*", "!!! Duplicate botnet bot entry!!");
99 ptr = &((*ptr)->next);
100 }
101 ptr2 = nmalloc(sizeof(tand_t));
102 strncpy(ptr2->bot, who, HANDLEN);
103 ptr2->bot[HANDLEN] = 0;
104 ptr2->share = flag;
105 ptr2->ver = vernum;
106 ptr2->next = *ptr;
107 *ptr = ptr2;
108 /* may be via itself */
109 ptr2->via = findbot(from);
110 if (!strcasecmp(next, botnetnick))
111 ptr2->uplink = (tand_t *) 1;
112 else
113 ptr2->uplink = findbot(next);
114 tands++;
115 }
116
117 void updatebot(int idx, char *who, char share, int vernum)
118 {
119 tand_t *ptr = findbot(who);
120
121 Context;
122 if (ptr) {
123 if (share)
124 ptr->share = share;
125 if (vernum)
126 ptr->ver = vernum;
127 botnet_send_update(idx, ptr);
128 }
129 }
130
131 /* for backward 1.0 compatibility: */
132 /* grab the (first) sock# for a user on another bot */
133 int partysock(char *bot, char *nick)
134 {
135 int i;
136
137 for (i = 0; i < parties; i++) {
138 if ((!strcasecmp(party[i].bot, bot)) &&
139 (!strcasecmp(party[i].nick, nick)))
140 return party[i].sock;
141 }
142 return 0;
143 }
144
145 /* new botnet member */
146 int addparty(char *bot, char *nick, int chan, char flag, int sock,
147 char *from, int *idx)
148 {
149 int i;
150
151 Context;
152 for (i = 0; i < parties; i++) {
153 /* just changing the channel of someone already on? */
154 if (!strcasecmp(party[i].bot, bot) &&
155 (party[i].sock == sock)) {
156 int oldchan = party[i].chan;
157
158 party[i].chan = chan;
159 party[i].timer = now;
160 if (from[0]) {
161 if (flag == ' ')
162 flag = '-';
163 party[i].flag = flag;
164 if (party[i].from)
165 nfree(party[i].from);
166 party[i].from = nmalloc(strlen(from) + 1);
167 strcpy(party[i].from, from);
168 }
169 *idx = i;
170 return oldchan;
171 }
172 }
173 /* new member */
174 if (parties == maxparty) {
175 maxparty += 50;
176 party = (party_t *) nrealloc((void *) party, maxparty * sizeof(party_t));
177 }
178 strncpy(party[parties].nick, nick, HANDLEN);
179 party[parties].nick[HANDLEN] = 0;
180 strncpy(party[parties].bot, bot, HANDLEN);
181 party[parties].bot[HANDLEN] = 0;
182 party[parties].chan = chan;
183 party[parties].sock = sock;
184 party[parties].status = 0;
185 party[parties].away = 0;
186 party[parties].timer = now; /* cope. */
187 if (from[0]) {
188 if (flag == ' ')
189 flag = '-';
190 party[parties].flag = flag;
191 party[parties].from = nmalloc(strlen(from) + 1);
192 strcpy(party[parties].from, from);
193 } else {
194 party[parties].flag = ' ';
195 party[parties].from = nmalloc(10);
196 strcpy(party[parties].from, "(unknown)");
197 }
198 *idx = parties;
199 parties++;
200 return -1;
201 }
202
203 /* alter status flags for remote party-line user */
204 void partystat(char *bot, int sock, int add, int rem)
205 {
206 int i;
207
208 for (i = 0; i < parties; i++) {
209 if ((!strcasecmp(party[i].bot, bot)) &&
210 (party[i].sock == sock)) {
211 party[i].status |= add;
212 party[i].status &= ~rem;
213 }
214 }
215 }
216
217 /* other bot is sharing idle info */
218 void partysetidle(char *bot, int sock, int secs)
219 {
220 int i;
221
222 for (i = 0; i < parties; i++) {
223 if ((!strcasecmp(party[i].bot, bot)) &&
224 (party[i].sock == sock)) {
225 party[i].timer = (now - (time_t) secs);
226 }
227 }
228 }
229
230 /* return someone's chat channel */
231 int getparty(char *bot, int sock)
232 {
233 int i;
234
235 for (i = 0; i < parties; i++) {
236 if (!strcasecmp(party[i].bot, bot) &&
237 (party[i].sock == sock)) {
238 return i;
239 }
240 }
241 return -1;
242 }
243
244 /* un-idle someone */
245 int partyidle(char *bot, char *nick)
246 {
247 int i, ok = 0;
248
249 for (i = 0; i < parties; i++) {
250 if ((!strcasecmp(party[i].bot, bot)) &&
251 (!strcasecmp(party[i].nick, nick))) {
252 party[i].timer = now;
253 ok = 1;
254 }
255 }
256 return ok;
257 }
258
259 /* change someone's nick */
260 int partynick(char *bot, int sock, char *nick)
261 {
262 char work[HANDLEN + 1];
263 int i;
264
265 for (i = 0; i < parties; i++) {
266 if (!strcasecmp(party[i].bot, bot) && (party[i].sock == sock)) {
267 strcpy(work, party[i].nick);
268 strncpy(party[i].nick, nick, HANDLEN);
269 party[i].nick[HANDLEN] = 0;
270 strcpy(nick, work);
271 return i;
272 }
273 }
274 return -1;
275 }
276
277 /* set away message */
278 void partyaway(char *bot, int sock, char *msg)
279 {
280 int i;
281
282 for (i = 0; i < parties; i++) {
283 if ((!strcasecmp(party[i].bot, bot)) &&
284 (party[i].sock == sock)) {
285 if (party[i].away)
286 nfree(party[i].away);
287 if (msg[0]) {
288 party[i].away = nmalloc(strlen(msg) + 1);
289 strcpy(party[i].away, msg);
290 } else
291 party[i].away = 0;
292 }
293 }
294 }
295
296 /* remove a tandem bot from the chain list */
297 void rembot(char *who)
298 {
299 tand_t **ptr = &tandbot, *ptr2;
300
301 Context;
302 while (*ptr) {
303 if (!strcasecmp((*ptr)->bot, who))
304 break;
305 ptr = &((*ptr)->next);
306 }
307 if (!*ptr)
308 /* may have just .unlink *'d */
309 return;
310 check_tcl_disc(who);
311
312 ptr2 = *ptr;
313 *ptr = ptr2->next;
314 nfree(ptr2);
315 tands--;
316 }
317
318 void remparty(char *bot, int sock)
319 {
320 int i;
321
322 Context;
323 for (i = 0; i < parties; i++)
324 if ((!strcasecmp(party[i].bot, bot)) &&
325 (party[i].sock == sock)) {
326 parties--;
327 if (party[i].from)
328 nfree(party[i].from);
329 if (party[i].away)
330 nfree(party[i].away);
331 if (i < parties) {
332 strcpy(party[i].bot, party[parties].bot);
333 strcpy(party[i].nick, party[parties].nick);
334 party[i].chan = party[parties].chan;
335 party[i].sock = party[parties].sock;
336 party[i].flag = party[parties].flag;
337 party[i].status = party[parties].status;
338 party[i].timer = party[parties].timer;
339 party[i].from = party[parties].from;
340 party[i].away = party[parties].away;
341 }
342 }
343 }
344
345 /* cancel every user that was on a certain bot */
346 void rempartybot(char *bot)
347 {
348 int i;
349
350 for (i = 0; i < parties; i++)
351 if (!strcasecmp(party[i].bot, bot)) {
352 if (party[i].chan >= 0)
353 check_tcl_chpt(bot, party[i].nick, party[i].sock, party[i].chan);
354 remparty(bot, party[i].sock);
355 i--;
356 }
357 }
358
359 /* remove every bot linked 'via' bot <x> */
360 void unvia(int idx, tand_t * who)
361 {
362 tand_t *bot, *bot2;
363
364 if (!who)
365 return; /* safety */
366 rempartybot(who->bot);
367 bot = tandbot;
368 while (bot) {
369 if (bot->uplink == who) {
370 unvia(idx, bot);
371 bot2 = bot->next;
372 rembot(bot->bot);
373 bot = bot2;
374 } else
375 bot = bot->next;
376 }
377 #ifndef NO_OLD_BOTNET
378 /* every bot unvia's bots behind anyway, so why send msg's for
379 * EVERY one? - will this break things?! */
380 tandout_but(idx, "unlinked %s\n", who->bot);
381 #endif
382 }
383
384 /* return index into dcc list of the bot that connects us to bot <x> */
385 int nextbot(char *who)
386 {
387 int j;
388 tand_t *bot = findbot(who);
389
390 if (!bot)
391 return -1;
392
393 for (j = 0; j < dcc_total; j++)
394 if (bot->via && !strcasecmp(bot->via->bot, dcc[j].nick) &&
395 (dcc[j].type == &DCC_BOT))
396 return j;
397 return -1; /* we're not connected to 'via' */
398 }
399
400 /* return name of the bot that is directly connected to bot X */
401 char *lastbot(char *who)
402 {
403 tand_t *bot = findbot(who);
404
405 if (!bot)
406 return "*";
407 else if (bot->uplink == (tand_t *) 1)
408 return botnetnick;
409 else
410 return bot->uplink->bot;
411 }
412
413 /* modern version of 'whom' (use local data) */
414 void answer_local_whom(int idx, int chan)
415 {
416 char c, idle[40], spaces2[33] = " ";
417 int i, len, len2;
418
419 Context;
420 if (chan == (-1))
421 dprintf(idx, "%s (+: %s, *: %s)\n", BOT_BOTNETUSERS, BOT_PARTYLINE,
422 BOT_LOCALCHAN);
423 else if (chan > 0) {
424 simple_sprintf(idle, "assoc %d", chan);
425 if ((Tcl_Eval(interp, idle) != TCL_OK) || !interp->result[0])
426 dprintf(idx, "%s %s%d:\n", BOT_USERSONCHAN,
427 (chan < 100000) ? "" : "*", chan % 100000);
428 else
429 dprintf(idx, "%s '%s%s' (%s%d):\n", BOT_USERSONCHAN,
430 (chan < 100000) ? "" : "*", interp->result,
431 (chan < 100000) ? "" : "*", chan % 100000);
432 }
433 spaces[HANDLEN - 9] = 0;
434 dprintf(idx, " Nick %s Bot %s Host\n", spaces, spaces);
435 dprintf(idx, "----------%s ---------%s --------------------\n",
436 spaces, spaces);
437 spaces[HANDLEN - 9] = ' ';
438 for (i = 0; i < dcc_total; i++)
439 if (dcc[i].type == &DCC_CHAT) {
440 if ((chan == (-1)) || ((chan >= 0) && (dcc[i].u.chat->channel == chan))) {
441 c = geticon(i);
442 if (c == '-')
443 c = ' ';
444 if (now - dcc[i].timeval > 300) {
445 unsigned long days, hrs, mins;
446
447 days = (now - dcc[i].timeval) / 86400;
448 hrs = ((now - dcc[i].timeval) - (days * 86400)) / 3600;
449 mins = ((now - dcc[i].timeval) - (hrs * 3600)) / 60;
450 if (days > 0)
451 sprintf(idle, " [idle %lud%luh]", days, hrs);
452 else if (hrs > 0)
453 sprintf(idle, " [idle %luh%lum]", hrs, mins);
454 else
455 sprintf(idle, " [idle %lum]", mins);
456 } else
457 idle[0] = 0;
458 spaces[len = HANDLEN - strlen(dcc[i].nick)] = 0;
459 spaces2[len2 = HANDLEN - strlen(botnetnick)] = 0;
460 dprintf(idx, "%c%s%s %c %s%s %s%s\n", c, dcc[i].nick, spaces,
461 (dcc[i].u.chat->channel == 0) && (chan == (-1)) ? '+' :
462 (dcc[i].u.chat->channel > 100000) &&
463 (chan == (-1)) ? '*' : ' ',
464 botnetnick, spaces2, dcc[i].host, idle);
465 spaces[len] = ' ';
466 spaces2[len2] = ' ';
467 if (dcc[i].u.chat->away != NULL)
468 dprintf(idx, " AWAY: %s\n", dcc[i].u.chat->away);
469 }
470 }
471 for (i = 0; i < parties; i++) {
472 if ((chan == (-1)) || ((chan >= 0) && (party[i].chan == chan))) {
473 c = party[i].flag;
474 if (c == '-')
475 c = ' ';
476 if (party[i].timer == 0L)
477 strcpy(idle, " [idle?]");
478 else if (now - party[i].timer > 300) {
479 unsigned long days, hrs, mins;
480
481 days = (now - party[i].timer) / 86400;
482 hrs = ((now - party[i].timer) - (days * 86400)) / 3600;
483 mins = ((now - party[i].timer) - (hrs * 3600)) / 60;
484 if (days > 0)
485 sprintf(idle, " [idle %lud%luh]", days, hrs);
486 else if (hrs > 0)
487 sprintf(idle, " [idle %luh%lum]", hrs, mins);
488 else
489 sprintf(idle, " [idle %lum]", mins);
490 } else
491 idle[0] = 0;
492 spaces[len = HANDLEN - strlen(party[i].nick)] = 0;
493 spaces2[len2 = HANDLEN - strlen(party[i].bot)] = 0;
494 dprintf(idx, "%c%s%s %c %s%s %s%s\n", c, party[i].nick, spaces,
495 (party[i].chan == 0) && (chan == (-1)) ? '+' : ' ',
496 party[i].bot, spaces2, party[i].from, idle);
497 spaces[len] = ' ';
498 spaces2[len2] = ' ';
499 if (party[i].status & PLSTAT_AWAY)
500 dprintf(idx, " %s: %s\n", MISC_AWAY, safe_str(party[i].away));
501 }
502 }
503 }
504
505 /* show z a list of all bots connected */
506 void tell_bots(int idx)
507 {
508 char s[512];
509 int i;
510 tand_t *bot;
511
512 if (!tands) {
513 dprintf(idx, "%s\n", BOT_NOBOTSLINKED);
514 return;
515 }
516 strcpy(s, botnetnick);
517 i = strlen(botnetnick);
518
519 for (bot = tandbot; bot; bot = bot->next) {
520 if (i > (500 - HANDLEN)) {
521 dprintf(idx, "Bots: %s\n", s);
522 s[0] = 0;
523 i = 0;
524 }
525 if (i) {
526 s[i++] = ',';
527 s[i++] = ' ';
528 }
529 strcpy(s + i, bot->bot);
530 i += strlen(bot->bot);
531 }
532 if (s[0])
533 dprintf(idx, "Bots: %s\n", s);
534 dprintf(idx, "(%s: %d)\n", MISC_TOTAL, tands + 1);
535 }
536
537 /* show a simpleton bot tree */
538 void tell_bottree(int idx, int showver)
539 {
540 char s[161];
541 tand_t *last[20], *this, *bot, *bot2 = NULL;
542 int lev = 0, more = 1, mark[20], ok, cnt, i, imark;
543 char work[1024];
544 int tothops = 0;
545
546 if (tands == 0) {
547 dprintf(idx, "%s\n", BOT_NOBOTSLINKED);
548 return;
549 }
550 s[0] = 0;
551 i = 0;
552
553 for (bot = tandbot; bot; bot = bot->next)
554 if (!bot->uplink) {
555 if (i) {
556 s[i++] = ',';
557 s[i++] = ' ';
558 }
559 strcpy(s + i, bot->bot);
560 i += strlen(bot->bot);
561 }
562 if (s[0])
563 dprintf(idx, "(%s %s)\n", BOT_NOTRACEINFO, s);
564 if (showver)
565 dprintf(idx, "%s (%d.%d.%d.%d)\n", botnetnick,
566 egg_numver / 1000000,
567 egg_numver % 1000000 / 10000,
568 egg_numver % 10000 / 100,
569 egg_numver % 100);
570 else
571 dprintf(idx, "%s\n", botnetnick);
572 this = (tand_t *) 1;
573 work[0] = 0;
574 while (more) {
575 if (lev == 20) {
576 dprintf(idx, "\n%s\n", BOT_COMPLEXTREE);
577 return;
578 }
579 cnt = 0;
580 tothops += lev;
581 for (bot = tandbot; bot; bot = bot->next)
582 if (bot->uplink == this)
583 cnt++;
584 if (cnt) {
585 imark = 0;
586 for (i = 0; i < lev; i++) {
587 if (mark[i])
588 strcpy(work + imark, " | ");
589 else
590 strcpy(work + imark, " ");
591 imark += 5;
592 }
593 if (cnt > 1)
594 strcpy(work + imark, " |-");
595 else
596 strcpy(work + imark, " `-");
597 s[0] = 0;
598 bot = tandbot;
599 while (!s[0]) {
600 if (bot->uplink == this) {
601 if (bot->ver) {
602 i = sprintf(s, "%c%s", bot->share, bot->bot);
603 if (showver)
604 sprintf(s + i, " (%d.%d.%d.%d)",
605 bot->ver / 1000000,
606 bot->ver % 1000000 / 10000,
607 bot->ver % 10000 / 100,
608 bot->ver % 100);
609 } else {
610 sprintf(s, "-%s", bot->bot);
611 }
612 } else
613 bot = bot->next;
614 }
615 dprintf(idx, "%s%s\n", work, s);
616 if (cnt > 1)
617 mark[lev] = 1;
618 else
619 mark[lev] = 0;
620 work[0] = 0;
621 last[lev] = this;
622 this = bot;
623 lev++;
624 more = 1;
625 } else {
626 while (cnt == 0) {
627 /* no subtrees from here */
628 if (lev == 0) {
629 dprintf(idx, "(( tree error ))\n");
630 return;
631 }
632 ok = 0;
633 for (bot = tandbot; bot; bot = bot->next) {
634 if (bot->uplink == last[lev - 1]) {
635 if (this == bot)
636 ok = 1;
637 else if (ok) {
638 cnt++;
639 if (cnt == 1) {
640 bot2 = bot;
641 if (bot->ver) {
642 i = sprintf(s, "%c%s", bot->share, bot->bot);
643 if (showver)
644 sprintf(s + i, " (%d.%d.%d.%d)",
645 bot->ver / 1000000,
646 bot->ver % 1000000 / 10000,
647 bot->ver % 10000 / 100,
648 bot->ver % 100);
649 } else {
650 sprintf(s, "-%s", bot->bot);
651 }
652 }
653 }
654 }
655 }
656 if (cnt) {
657 imark = 0;
658 for (i = 1; i < lev; i++) {
659 if (mark[i - 1])
660 strcpy(work + imark, " | ");
661 else
662 strcpy(work + imark, " ");
663 imark += 5;
664 }
665 more = 1;
666 if (cnt > 1)
667 dprintf(idx, "%s |-%s\n", work, s);
668 else
669 dprintf(idx, "%s `-%s\n", work, s);
670 this = bot2;
671 work[0] = 0;
672 if (cnt > 1)
673 mark[lev - 1] = 1;
674 else
675 mark[lev - 1] = 0;
676 } else {
677 /* this was the last child */
678 lev--;
679 if (lev == 0) {
680 more = 0;
681 cnt = 999;
682 } else {
683 more = 1;
684 this = last[lev];
685 }
686 }
687 }
688 }
689 }
690 /* hop information: (9d) */
691 dprintf(idx, "Average hops: %3.1f, total bots: %d\n",
692 ((float) tothops) / ((float) tands), tands + 1);
693 }
694
695 /* dump list of links to a new bot */
696 void dump_links(int z)
697 {
698 register int i, l;
699 char x[1024];
700 tand_t *bot;
701
702 Context;
703 for (bot = tandbot; bot; bot = bot->next) {
704 char *p;
705
706 if (bot->uplink == (tand_t *) 1)
707 p = botnetnick;
708 else
709 p = bot->uplink->bot;
710 #ifndef NO_OLD_BOTNET
711 if (b_numver(z) < NEAT_BOTNET)
712 l = simple_sprintf(x, "nlinked %s %s %c%d\n", bot->bot,
713 p, bot->share, bot->ver);
714 else
715 #endif
716 l = simple_sprintf(x, "n %s %s %c%D\n", bot->bot, p,
717 bot->share, bot->ver);
718 tputs(dcc[z].sock, x, l);
719 }
720 Context;
721 if (!(bot_flags(dcc[z].user) & BOT_ISOLATE)) {
722 /* dump party line members */
723 for (i = 0; i < dcc_total; i++) {
724 if (dcc[i].type == &DCC_CHAT) {
725 if ((dcc[i].u.chat->channel >= 0) &&
726 (dcc[i].u.chat->channel < 100000)) {
727 #ifndef NO_OLD_BOTNET
728 if (b_numver(z) < NEAT_BOTNET)
729 l = simple_sprintf(x, "join %s %s %d %c%d %s\n",
730 botnetnick, dcc[i].nick,
731 dcc[i].u.chat->channel, geticon(i),
732 dcc[i].sock, dcc[i].host);
733 else
734 #endif
735 l = simple_sprintf(x, "j !%s %s %D %c%D %s\n",
736 botnetnick, dcc[i].nick,
737 dcc[i].u.chat->channel, geticon(i),
738 dcc[i].sock, dcc[i].host);
739 tputs(dcc[z].sock, x, l);
740 #ifndef NO_OLD_BOTNET
741 if (b_numver(z) < NEAT_BOTNET) {
742 if (dcc[i].u.chat->away) {
743 l = simple_sprintf(x, "away %s %d %s\n", botnetnick,
744 dcc[i].sock, dcc[i].u.chat->away);
745 tputs(dcc[z].sock, x, l);
746 }
747 l = simple_sprintf(x, "idle %s %d %d\n", botnetnick,
748 dcc[i].sock, now - dcc[i].timeval);
749 } else
750 #endif
751 l = simple_sprintf(x, "i %s %D %D %s\n", botnetnick,
752 dcc[i].sock, now - dcc[i].timeval,
753 dcc[i].u.chat->away ? dcc[i].u.chat->away : "");
754 tputs(dcc[z].sock, x, l);
755 }
756 }
757 }
758 Context;
759 for (i = 0; i < parties; i++) {
760 #ifndef NO_OLD_BOTNET
761 if (b_numver(z) < NEAT_BOTNET)
762 l = simple_sprintf(x, "join %s %s %d %c%d %s\n",
763 party[i].bot, party[i].nick,
764 party[i].chan, party[i].flag,
765 party[i].sock, party[i].from);
766 else
767 #endif
768 l = simple_sprintf(x, "j %s %s %D %c%D %s\n",
769 party[i].bot, party[i].nick,
770 party[i].chan, party[i].flag,
771 party[i].sock, party[i].from);
772 tputs(dcc[z].sock, x, l);
773 if ((party[i].status & PLSTAT_AWAY) || (party[i].timer != 0)) {
774 #ifndef NO_OLD_BOTNET
775 if (b_numver(z) < NEAT_BOTNET) {
776 if (party[i].status & PLSTAT_AWAY) {
777 l = simple_sprintf(x, "away %s %d %s\n", party[i].bot,
778 party[i].sock, party[i].away);
779 tputs(dcc[z].sock, x, l);
780 }
781 l = simple_sprintf(x, "idle %s %d %d\n", party[i].bot,
782 party[i].sock, now - party[i].timer);
783 } else
784 #endif
785 l = simple_sprintf(x, "i %s %D %D %s\n", party[i].bot,
786 party[i].sock, now - party[i].timer,
787 party[i].away ? party[i].away : "");
788 tputs(dcc[z].sock, x, l);
789 }
790 }
791 }
792 Context;
793 }
794
795 int in_chain(char *who)
796 {
797 if (findbot(who))
798 return 1;
799 if (!strcasecmp(who, botnetnick))
800 return 1;
801 return 0;
802 }
803
804 /* break link with a tandembot */
805 int botunlink(int idx, char *nick, char *reason)
806 {
807 char s[20];
808 register int i;
809 tand_t *bot;
810
811 Context;
812 if (nick[0] == '*')
813 dprintf(idx, "%s\n", BOT_UNLINKALL);
814 for (i = 0; i < dcc_total; i++) {
815 if ((nick[0] == '*') || !strcasecmp(dcc[i].nick, nick)) {
816 if (dcc[i].type == &DCC_FORK_BOT) {
817 if (idx >= 0)
818 dprintf(idx, "%s: %s -> %s.\n", BOT_KILLLINKATTEMPT,
819 dcc[i].nick, dcc[i].host);
820 putlog(LOG_BOTS, "*", "%s: %s -> %s:%d",
821 BOT_KILLLINKATTEMPT, dcc[i].nick,
822 dcc[i].host, dcc[i].port);
823 killsock(dcc[i].sock);
824 lostdcc(i);
825 if (nick[0] != '*')
826 return 1;
827 } else if (dcc[i].type == &DCC_BOT_NEW) {
828 if (idx >= 0)
829 dprintf(idx, "%s %s.\n", BOT_ENDLINKATTEMPT,
830 dcc[i].nick);
831 putlog(LOG_BOTS, "*", "%s %s @ %s:%d",
832 "Stopped trying to link", dcc[i].nick,
833 dcc[i].host, dcc[i].port);
834 killsock(dcc[i].sock);
835 lostdcc(i);
836 if (nick[0] != '*')
837 return 1;
838 else
839 i--;
840 } else if (dcc[i].type == &DCC_BOT) {
841 char s[1024];
842
843 Context;
844
845 if (idx >= 0)
846 dprintf(idx, "%s %s.\n", BOT_BREAKLINK, dcc[i].nick);
847 else if ((idx == -3) && (b_status(i) & STAT_SHARE) && !share_unlinks)
848 return -1;
849 dprintf(i, "bye\n");
850 if (reason && reason[0]) {
851 simple_sprintf(s, "%s %s (%s)", BOT_UNLINKEDFROM,
852 dcc[i].nick, reason);
853 } else {
854 simple_sprintf(s, "%s %s", BOT_UNLINKEDFROM, dcc[i].nick);
855 }
856 chatout("*** %s\n", s);
857 botnet_send_unlinked(i, dcc[i].nick, s);
858 killsock(dcc[i].sock);
859 lostdcc(i);
860 if (nick[0] != '*')
861 return 1;
862 else
863 i--;
864 }
865 }
866 }
867 Context;
868 if ((idx >= 0) && (nick[0] != '*')) {
869 dprintf(idx, "%s\n", BOT_NOTCONNECTED);
870
871 /* The internal bot list is desynched from the dcc list
872 * sometimes. While we still search for the bug, provide
873 * an easy way to clear out those `ghost'-bots. -FK
874 */
875 bot = findbot(nick);
876 if (bot) {
877 dprintf(idx, "BUG: Found bot `%s' in internal bot list! Removing.\n",
878 nick);
879 rembot(bot->bot);
880 }
881 }
882 if (nick[0] == '*') {
883 dprintf(idx, "%s\n", BOT_WIPEBOTTABLE);
884 while (tandbot)
885 rembot(tandbot->bot);
886 while (parties) {
887 parties--;
888 /* Assert? */
889 if (party[i].chan >= 0)
890 check_tcl_chpt(party[i].bot, party[i].nick, party[i].sock,
891 party[i].chan);
892 }
893 strcpy(s, "killassoc &");
894 Tcl_Eval(interp, s);
895 }
896 return 0;
897 }
898
899 /* link to another bot */
900 int botlink(char *linker, int idx, char *nick)
901 {
902 struct bot_addr *bi;
903 struct userrec *u;
904 register int i;
905
906 Context;
907 u = get_user_by_handle(userlist, nick);
908 if (!u || !(u->flags & USER_BOT)) {
909 if (idx >= 0)
910 dprintf(idx, "%s %s\n", nick, BOT_BOTUNKNOWN);
911 } else if (!strcasecmp(nick, botnetnick)) {
912 if (idx >= 0)
913 dprintf(idx, "%s\n", BOT_CANTLINKMYSELF);
914 } else if (in_chain(nick) && (idx != -3)) {
915 if (idx >= 0)
916 dprintf(idx, "%s\n", BOT_ALREADYLINKED);
917 } else {
918 for (i = 0; i < dcc_total; i++)
919 if ((dcc[i].user == u) &&
920 ((dcc[i].type == &DCC_FORK_BOT) ||
921 (dcc[i].type == &DCC_BOT_NEW))) {
922 if (idx >= 0)
923 dprintf(idx, "%s\n", BOT_ALREADYLINKING);
924 return 0;
925 }
926 /* address to connect to is in 'info' */
927 bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
928 if (!bi || !strlen(bi->address) || !bi->telnet_port) {
929 if (idx >= 0) {
930 dprintf(idx, "%s '%s'.\n", BOT_NOTELNETADDY, nick);
931 dprintf(idx, "%s .chaddr %s %s\n",
932 MISC_USEFORMAT, nick, MISC_CHADDRFORMAT);
933 }
934 } else if (dcc_total == max_dcc) {
935 if (idx >= 0)
936 dprintf(idx, "%s\n", DCC_TOOMANYDCCS1);
937 } else {
938 Context;
939 correct_handle(nick);
940 i = new_dcc(&DCC_FORK_BOT, sizeof(struct bot_info));
941
942 dcc[i].port = bi->telnet_port;
943 strcpy(dcc[i].nick, nick);
944 strcpy(dcc[i].host, bi->address);
945 dcc[i].timeval = now;
946 strcpy(dcc[i].u.bot->linker, linker);
947 strcpy(dcc[i].u.bot->version, "(primitive bot)");
948 if (idx > -2)
949 putlog(LOG_BOTS, "*", "%s %s at %s:%d ...", BOT_LINKING, nick,
950 bi->address, bi->telnet_port);
951 dcc[i].u.bot->numver = idx;
952 dcc[i].timeval = now;
953 dcc[i].u.bot->port = dcc[i].port; /* remember where i started */
954 dcc[i].sock = getsock(SOCK_STRONGCONN);
955 dcc[i].user = u;
956 if (open_telnet_raw(dcc[i].sock, bi->address, dcc[i].port) < 0)
957 failed_link(i);
958 return 1;
959 }
960 }
961 return 0;
962 }
963
964 static void failed_tandem_relay(int idx)
965 {
966 int uidx = (-1), i;
967
968 Context;
969 for (i = 0; i < dcc_total; i++)
970 if ((dcc[i].type == &DCC_PRE_RELAY) &&
971 (dcc[i].u.relay->sock == dcc[idx].sock))
972 uidx = i;
973 if (uidx < 0) {
974 putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
975 dcc[idx].sock, dcc[idx].u.relay->sock);
976 killsock(dcc[idx].sock);
977 lostdcc(idx);
978 return;
979 }
980 if (dcc[idx].port >= dcc[idx].u.relay->port + 3) {
981 struct chat_info *ci = dcc[uidx].u.relay->chat;
982
983 dprintf(uidx, "%s %s.\n", BOT_CANTLINKTO, dcc[idx].nick);
984 nfree(dcc[uidx].u.relay);
985 dcc[uidx].u.chat = ci;
986 dcc[uidx].type = &DCC_CHAT;
987 dcc[uidx].status = dcc[uidx].u.relay->old_status;
988 killsock(dcc[idx].sock);
989 lostdcc(idx);
990 return;
991 }
992 killsock(dcc[idx].sock);
993 dcc[idx].sock = getsock(SOCK_STRONGCONN);
994 dcc[uidx].u.relay->sock = dcc[idx].sock;
995 dcc[idx].port++;
996 dcc[idx].timeval = now;
997 if (open_telnet_raw(dcc[idx].sock, dcc[idx].host, dcc[idx].port) < 0)
998 failed_tandem_relay(idx);
999 }
1000
1001 /* relay to another tandembot */
1002 void tandem_relay(int idx, char *nick, register int i)
1003 {
1004 struct chat_info *ci;
1005 struct userrec *u;
1006 struct bot_addr *bi;
1007
1008 Context;
1009 u = get_user_by_handle(userlist, nick);
1010 if (!u || !(u->flags & USER_BOT)) {
1011 dprintf(idx, "%s %s\n", nick, BOT_BOTUNKNOWN);
1012 return;
1013 }
1014 if (!strcasecmp(nick, botnetnick)) {
1015 dprintf(idx, "%s\n", BOT_CANTRELAYMYSELF);
1016 return;
1017 }
1018 /* address to connect to is in 'info' */
1019 bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
1020 if (!bi) {
1021 dprintf(idx, "%s '%s'.\n", BOT_NOTELNETADDY, nick);
1022 dprintf(idx, "%s .chaddr %s %s\n",
1023 MISC_USEFORMAT, nick, MISC_CHADDRFORMAT);
1024
1025 return;
1026 }
1027 if (dcc_total == max_dcc) {
1028 dprintf(idx, "%s\n", DCC_TOOMANYDCCS1);
1029 return;
1030 }
1031 i = new_dcc(&DCC_FORK_RELAY, sizeof(struct relay_info));
1032 dcc[i].u.relay->chat = get_data_ptr(sizeof(struct chat_info));
1033
1034 dcc[i].port = bi->relay_port;
1035 dcc[i].u.relay->port = dcc[i].port;
1036 dcc[i].addr = 0L;
1037 strcpy(dcc[i].nick, nick);
1038 dcc[i].user = u;
1039 strcpy(dcc[i].host, bi->address);
1040 dcc[i].u.relay->chat->away = NULL;
1041 dcc[i].u.relay->old_status = dcc[i].status;
1042 dcc[i].status = 0;
1043 dcc[i].timeval = now;
1044 dcc[i].u.relay->chat->msgs_per_sec = 0;
1045 dcc[i].u.relay->chat->con_flags = 0;
1046 dcc[i].u.relay->chat->buffer = NULL;
1047 dcc[i].u.relay->chat->max_line = 0;
1048 dcc[i].u.relay->chat->line_count = 0;
1049 dcc[i].u.relay->chat->current_lines = 0;
1050 dprintf(idx, "%s %s @ %s:%d ...\n", BOT_CONNECTINGTO, nick,
1051 bi->address, bi->relay_port);
1052 dprintf(idx, "%s\n", BOT_BYEINFO1);
1053 ci = dcc[idx].u.chat;
1054 dcc[idx].u.relay = get_data_ptr(sizeof(struct relay_info));
1055
1056 dcc[idx].u.relay->chat = ci;
1057 dcc[idx].type = &DCC_PRE_RELAY;
1058 dcc[i].sock = getsock(SOCK_STRONGCONN);
1059 dcc[idx].u.relay->sock = dcc[i].sock;
1060 dcc[i].u.relay->sock = dcc[idx].sock;
1061 dcc[i].timeval = now;
1062 if (open_telnet_raw(dcc[i].sock, dcc[i].host, dcc[i].port) < 0)
1063 failed_tandem_relay(i);
1064 }
1065
1066 /* input from user before connect is ready */
1067 static void pre_relay(int idx, char *buf, register int i)
1068 {
1069 register int tidx = (-1);
1070
1071 Context;
1072 for (i = 0; i < dcc_total; i++)
1073 if ((dcc[i].type == &DCC_FORK_RELAY) &&
1074 (dcc[i].u.relay->sock == dcc[idx].sock))
1075 tidx = i;
1076 if (tidx < 0) {
1077 putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
1078 dcc[i].sock, dcc[i].u.relay->sock);
1079 killsock(dcc[i].sock);
1080 lostdcc(i);
1081 return;
1082 }
1083 Context;
1084 if (!strcasecmp(buf, "*bye*")) {
1085 /* disconnect */
1086 struct chat_info *ci = dcc[idx].u.relay->chat;
1087
1088 dprintf(idx, "%s %s.\n", BOT_ABORTRELAY1, dcc[tidx].nick);
1089 dprintf(idx, "%s %s.\n\n", BOT_ABORTRELAY2, botnetnick);
1090 putlog(LOG_MISC, "*", "%s %s -> %s", BOT_ABORTRELAY3, dcc[idx].nick,
1091 dcc[tidx].nick);
1092 nfree(dcc[idx].u.relay);
1093 dcc[idx].u.chat = ci;
1094 dcc[idx].status = dcc[idx].u.relay->old_status;
1095 dcc[idx].type = &DCC_CHAT;
1096 killsock(dcc[tidx].sock);
1097 lostdcc(tidx);
1098 return;
1099 }
1100 Context;
1101 }
1102
1103 /* user disconnected before her relay had finished connecting */
1104 static void failed_pre_relay(int idx)
1105 {
1106 register int tidx = (-1), i;
1107
1108 Context;
1109 for (i = 0; i < dcc_total; i++)
1110 if ((dcc[i].type == &DCC_FORK_RELAY) &&
1111 (dcc[i].u.relay->sock == dcc[idx].sock))
1112 tidx = i;
1113 if (tidx < 0) {
1114 putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
1115 dcc[i].sock, dcc[i].u.relay->sock);
1116 killsock(dcc[i].sock);
1117 lostdcc(i);
1118 return;
1119 }
1120 putlog(LOG_MISC, "*", "%s [%s]%s/%d", BOT_LOSTDCCUSER, dcc[idx].nick,
1121 dcc[idx].host, dcc[idx].port);
1122 putlog(LOG_MISC, "*", "(%s %s)", BOT_DROPPINGRELAY, dcc[tidx].nick);
1123 if ((dcc[tidx].sock != STDOUT) || backgrd) {
1124 if (idx > tidx) {
1125 int t = tidx;
1126
1127 tidx = idx;
1128 idx = t;
1129 }
1130 killsock(dcc[tidx].sock);
1131 lostdcc(tidx);
1132 } else {
1133 fatal("Lost my terminal??!?!?!", 0);
1134 }
1135 killsock(dcc[idx].sock);
1136 lostdcc(idx);
1137 }
1138
1139 static void cont_tandem_relay(int idx, char *buf, register int i)
1140 {
1141 register int uidx = (-1);
1142 struct relay_info *ri;
1143
1144 Context;
1145 for (i = 0; i < dcc_total; i++)
1146 if ((dcc[i].type == &DCC_PRE_RELAY) &&
1147 (dcc[i].u.relay->sock == dcc[idx].sock))
1148 uidx = i;
1149 if (uidx < 0) {
1150 putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
1151 dcc[i].sock, dcc[i].u.relay->sock);
1152 killsock(dcc[i].sock);
1153 lostdcc(i);
1154 return;
1155 }
1156 dcc[idx].type = &DCC_RELAY;
1157 dcc[idx].u.relay->sock = dcc[uidx].sock;
1158 dcc[uidx].u.relay->sock = dcc[idx].sock;
1159 dprintf(uidx, "%s %s ...\n", BOT_RELAYSUCCESS, dcc[idx].nick);
1160 dprintf(uidx, "%s\n\n", BOT_BYEINFO2);
1161 putlog(LOG_MISC, "*", "%s %s -> %s", BOT_RELAYLINK,
1162 dcc[uidx].nick, dcc[idx].nick);
1163 ri = dcc[uidx].u.relay; /* YEAH */
1164 dcc[uidx].type = &DCC_CHAT;
1165 dcc[uidx].u.chat = ri->chat;
1166 if (dcc[uidx].u.chat->channel >= 0) {
1167 chanout_but(-1, dcc[uidx].u.chat->channel, "*** %s %s\n",
1168 dcc[uidx].nick, BOT_PARTYLEFT);
1169 if (dcc[uidx].u.chat->channel < 100000)
1170 botnet_send_part_idx(uidx, NULL);
1171 check_tcl_chpt(botnetnick, dcc[uidx].nick, dcc[uidx].sock,
1172 dcc[uidx].u.chat->channel);
1173 }
1174 check_tcl_chof(dcc[uidx].nick, dcc[uidx].sock);
1175 dcc[uidx].type = &DCC_RELAYING;
1176 dcc[uidx].u.relay = ri;
1177 }
1178
1179 static void eof_dcc_relay(int idx)
1180 {
1181 register int j;
1182 struct chat_info *ci;
1183
1184 for (j = 0; dcc[j].sock != dcc[idx].u.relay->sock; j++);
1185 /* in case echo was off, turn it back on: */
1186 if (dcc[j].status & STAT_TELNET)
1187 dprintf(j, "\377\374\001\r\n");
1188 putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_ENDRELAY1, dcc[j].nick,
1189 dcc[idx].nick);
1190 dprintf(j, "\n\n*** %s %s\n", BOT_ENDRELAY2, botnetnick);
1191 ci = dcc[j].u.relay->chat;
1192 nfree(dcc[j].u.relay);
1193 dcc[j].u.chat = ci;
1194 dcc[j].type = &DCC_CHAT;
1195 if (dcc[j].u.chat->channel >= 0) {
1196 chanout_but(-1, dcc[j].u.chat->channel, "*** %s %s.\n",
1197 dcc[j].nick, BOT_PARTYREJOINED);
1198 Context;
1199 if (dcc[j].u.chat->channel < 100000)
1200 botnet_send_join_idx(j, -1);
1201 }
1202 dcc[j].status = dcc[j].u.relay->old_status;
1203 check_tcl_chon(dcc[j].nick, dcc[j].sock);
1204 check_tcl_chjn(botnetnick, dcc[j].nick, dcc[j].u.chat->channel,
1205 geticon(j), dcc[j].sock, dcc[j].host);
1206 killsock(dcc[idx].sock);
1207 lostdcc(idx);
1208 }
1209
1210 static void eof_dcc_relaying(int idx)
1211 {
1212 register int j, x = dcc[idx].u.relay->sock;
1213
1214 putlog(LOG_MISC, "*", "%s [%s]%s/%d", BOT_LOSTDCCUSER, dcc[idx].nick,
1215 dcc[idx].host, dcc[idx].port);
1216 killsock(dcc[idx].sock);
1217 lostdcc(idx);
1218 for (j = 0; (dcc[j].sock != x) || (dcc[j].type == &DCC_FORK_RELAY); j++);
1219 putlog(LOG_MISC, "*", "(%s %s)", BOT_DROPPEDRELAY, dcc[j].nick);
1220 killsock(dcc[j].sock);
1221 lostdcc(j); /* drop connection to the bot */
1222 }
1223
1224 static void dcc_relay(int idx, char *buf, int j)
1225 {
1226 unsigned char *p = (unsigned char *) buf;
1227 int mark;
1228
1229 for (j = 0; (dcc[j].sock != dcc[idx].u.relay->sock) ||
1230 (dcc[j].type != &DCC_RELAYING); j++);
1231 /* if redirecting to a non-telnet user, swallow telnet codes */
1232 if (!(dcc[j].status & STAT_TELNET)) {
1233 while (*p != 0) {
1234 while ((*p != 255) && (*p != 0))
1235 p++; /* search for IAC */
1236 if (*p == 255) {
1237 mark = 2;
1238 if (!*(p + 1))
1239 mark = 1; /* bogus */
1240 if ((*(p + 1) >= 251) || (*(p + 1) <= 254)) {
1241 mark = 3;
1242 if (!*(p + 2))
1243 mark = 2; /* bogus */
1244 }
1245 strcpy((char *) p, (char *) (p + mark));
1246 }
1247 }
1248 if (!buf[0])
1249 dprintf(-dcc[idx].u.relay->sock, " \n");
1250 else
1251 dprintf(-dcc[idx].u.relay->sock, "%s\n", buf);
1252 return;
1253 }
1254 /* telnet user */
1255 if (!buf[0])
1256 dprintf(-dcc[idx].u.relay->sock, " \r\n");
1257 else
1258 dprintf(-dcc[idx].u.relay->sock, "%s\r\n", buf);
1259 }
1260
1261 static void dcc_relaying(int idx, char *buf, int j)
1262 {
1263 struct chat_info *ci;
1264
1265 if (strcasecmp(buf, "*bye*")) {
1266 dprintf(-dcc[idx].u.relay->sock, "%s\n", buf);
1267 return;
1268 }
1269 for (j = 0; (dcc[j].sock != dcc[idx].u.relay->sock) ||
1270 (dcc[j].type != &DCC_RELAY); j++);
1271 /* in case echo was off, turn it back on: */
1272 if (dcc[idx].status & STAT_TELNET)
1273 dprintf(idx, "\377\374\001\r\n");
1274 dprintf(idx, "\n(%s %s.)\n", BOT_BREAKRELAY, dcc[j].nick);
1275 dprintf(idx, "%s %s.\n\n", BOT_ABORTRELAY2, botnetnick);
1276 putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_RELAYBROKEN,
1277 dcc[idx].nick, dcc[j].nick);
1278 if (dcc[idx].u.relay->chat->channel >= 0) {
1279 chanout_but(-1, dcc[idx].u.relay->chat->channel,
1280 "*** %s joined the party line.\n", dcc[idx].nick);
1281 Context;
1282 if (dcc[idx].u.relay->chat->channel < 100000)
1283 botnet_send_join_idx(idx, -1);
1284 }
1285 ci = dcc[idx].u.relay->chat;
1286 nfree(dcc[idx].u.relay);
1287 dcc[idx].u.chat = ci;
1288 dcc[idx].type = &DCC_CHAT;
1289 dcc[idx].status = dcc[idx].u.relay->old_status;
1290 check_tcl_chon(dcc[idx].nick, dcc[idx].sock);
1291 if (dcc[idx].u.chat->channel >= 0)
1292 check_tcl_chjn(botnetnick, dcc[idx].nick, dcc[idx].u.chat->channel,
1293 geticon(idx), dcc[idx].sock, dcc[idx].host);
1294 killsock(dcc[j].sock);
1295 lostdcc(j);
1296 }
1297
1298 static void display_relay(int i, char *other)
1299 {
1300 sprintf(other, "rela -> sock %d", dcc[i].u.relay->sock);
1301 }
1302
1303 static void display_relaying(int i, char *other)
1304 {
1305 sprintf(other, ">rly -> sock %d", dcc[i].u.relay->sock);
1306 }
1307
1308 static void display_tandem_relay(int i, char *other)
1309 {
1310 strcpy(other, "other rela");
1311 }
1312
1313 static void display_pre_relay(int i, char *other)
1314 {
1315 strcpy(other, "other >rly");
1316 }
1317
1318 static int expmem_relay(void *x)
1319 {
1320 register struct relay_info *p = (struct relay_info *) x;
1321 int tot = sizeof(struct relay_info);
1322
1323 if (p->chat)
1324 tot += DCC_CHAT.expmem(p->chat);
1325 return tot;
1326 }
1327
1328 static void kill_relay(int idx, void *x)
1329 {
1330 register struct relay_info *p = (struct relay_info *) x;
1331
1332 if (p->chat)
1333 DCC_CHAT.kill(idx, p->chat);
1334 nfree(p);
1335 }
1336
1337 struct dcc_table DCC_RELAY =
1338 {
1339 "RELAY",
1340 0, /* flags */
1341 eof_dcc_relay,
1342 dcc_relay,
1343 0,
1344 0,
1345 display_relay,
1346 expmem_relay,
1347 kill_relay,
1348 0
1349 };
1350
1351 static void out_relay(int idx, char *buf, void *x)
1352 {
1353 register struct relay_info *p = (struct relay_info *) x;
1354
1355 if (p && p->chat)
1356 DCC_CHAT.output(idx, buf, p->chat);
1357 else
1358 tputs(dcc[idx].sock, buf, strlen(buf));
1359 }
1360
1361 struct dcc_table DCC_RELAYING =
1362 {
1363 "RELAYING",
1364 0, /* flags */
1365 eof_dcc_relaying,
1366 dcc_relaying,
1367 0,
1368 0,
1369 display_relaying,
1370 expmem_relay,
1371 kill_relay,
1372 out_relay
1373 };
1374
1375 struct dcc_table DCC_FORK_RELAY =
1376 {
1377 "FORK_RELAY",
1378 0, /* flags */
1379 failed_tandem_relay,
1380 cont_tandem_relay,
1381 &connect_timeout,
1382 failed_tandem_relay,
1383 display_tandem_relay,
1384 expmem_relay,
1385 kill_relay,
1386 0
1387 };
1388
1389 struct dcc_table DCC_PRE_RELAY =
1390 {
1391 "PRE_RELAY",
1392 0, /* flags */
1393 failed_pre_relay,
1394 pre_relay,
1395 0,
1396 0,
1397 display_pre_relay,
1398 expmem_relay,
1399 kill_relay,
1400 0
1401 };
1402
1403 /* once a minute, send 'ping' to each bot -- no exceptions */
1404 void check_botnet_pings()
1405 {
1406 int i;
1407
1408 Context;
1409 for (i = 0; i < dcc_total; i++)
1410 if (dcc[i].type == &DCC_BOT)
1411 if (dcc[i].status & STAT_PINGED) {
1412 char s[1024];
1413
1414 putlog(LOG_BOTS, "*", "%s: %s", BOT_PINGTIMEOUT, dcc[i].nick);
1415 simple_sprintf(s, "%s: %s", BOT_PINGTIMEOUT, dcc[i].nick);
1416 chatout("*** %s\n", s);
1417 botnet_send_unlinked(i, dcc[i].nick, s);
1418 killsock(dcc[i].sock);
1419 lostdcc(i);
1420 }
1421 Context;
1422 for (i = 0; i < dcc_total; i++)
1423 if (dcc[i].type == &DCC_BOT) {
1424 botnet_send_ping(i);
1425 dcc[i].status |= STAT_PINGED;
1426 }
1427 Context;
1428 for (i = 0; i < dcc_total; i++)
1429 if ((dcc[i].type == &DCC_BOT) && (dcc[i].status & STAT_LEAF)) {
1430 tand_t *bot, *via = findbot(dcc[i].nick);
1431
1432 for (bot = tandbot; bot; bot = bot->next) {
1433 if ((via == bot->via) && (bot != via)) {
1434 /* not leaflike behavior */
1435 if (dcc[i].status & STAT_WARNED) {
1436 char s[1024];
1437
1438 putlog(LOG_BOTS, "*", "%s %s (%s).", BOT_DISCONNECTED,
1439 dcc[i].nick, BOT_BOTNOTLEAFLIKE);
1440 dprintf(i, "bye\n");
1441 simple_sprintf(s, "%s %s (%s)", BOT_DISCONNECTED, dcc[i].nick,
1442 BOT_BOTNOTLEAFLIKE);
1443 chatout("*** %s\n", s);
1444 botnet_send_unlinked(i, dcc[i].nick, s);
1445 killsock(dcc[i].sock);
1446 lostdcc(i);
1447 } else {
1448 botnet_send_reject(i, botnetnick, NULL, bot->bot,
1449 NULL, NULL);
1450 dcc[i].status |= STAT_WARNED;
1451 }
1452 } else
1453 dcc[i].status &= ~STAT_WARNED;
1454 }
1455 }
1456 Context;
1457 }
1458
1459 void zapfbot(int idx)
1460 {
1461 char s[1024];
1462
1463 simple_sprintf(s, "%s: %s", BOT_BOTDROPPED, dcc[idx].nick);
1464 chatout("*** %s\n", s);
1465 botnet_send_unlinked(idx, dcc[idx].nick, s);
1466 killsock(dcc[idx].sock);
1467 lostdcc(idx);
1468 }
1469
1470 void restart_chons()
1471 {
1472 int i;
1473
1474 /* dump party line members */
1475 Context;
1476 for (i = 0; i < dcc_total; i++) {
1477 if (dcc[i].type == &DCC_CHAT) {
1478 check_tcl_chon(dcc[i].nick, dcc[i].sock);
1479 check_tcl_chjn(botnetnick, dcc[i].nick, dcc[i].u.chat->channel,
1480 geticon(i), dcc[i].sock, dcc[i].host);
1481 }
1482 }
1483 for (i = 0; i < parties; i++) {
1484 check_tcl_chjn(party[i].bot, party[i].nick, party[i].chan,
1485 party[i].flag, party[i].sock, party[i].from);
1486 }
1487 Context;
1488 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23