/[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.1.1.1 - (show annotations) (download) (as text) (vendor branch)
Wed Jun 23 19:51:26 1999 UTC (20 years, 2 months ago) by segfault
Branch: eggdev
CVS Tags: start
Changes since 1.1: +0 -0 lines
File MIME type: text/x-chdr
Eggdrop 1.3.28 CVS Code

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23