/[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.11 - (show annotations) (download) (as text)
Mon Jan 17 16:14:44 2000 UTC (19 years, 8 months ago) by per
Branch: MAIN
CVS Tags: eggdrop104030RC2, eggdrop10403RC1, eggdrop10402RC1, eggdrop10403, eggdrop10402
Changes since 1.10: +4 -8 lines
File MIME type: text/x-chdr
relayfix, extern_cleanup

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.10 2000/01/08 21:23:13 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
810 Context;
811 if (nick[0] == '*')
812 dprintf(idx, "%s\n", BOT_UNLINKALL);
813 for (i = 0; i < dcc_total; i++) {
814 if ((nick[0] == '*') || !strcasecmp(dcc[i].nick, nick)) {
815 if (dcc[i].type == &DCC_FORK_BOT) {
816 if (idx >= 0)
817 dprintf(idx, "%s: %s -> %s.\n", BOT_KILLLINKATTEMPT,
818 dcc[i].nick, dcc[i].host);
819 putlog(LOG_BOTS, "*", "%s: %s -> %s:%d",
820 BOT_KILLLINKATTEMPT, 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 if (dcc[i].type == &DCC_BOT_NEW) {
827 if (idx >= 0)
828 dprintf(idx, "%s %s.\n", BOT_ENDLINKATTEMPT,
829 dcc[i].nick);
830 putlog(LOG_BOTS, "*", "%s %s @ %s:%d",
831 "Stopped trying to link", dcc[i].nick,
832 dcc[i].host, dcc[i].port);
833 killsock(dcc[i].sock);
834 lostdcc(i);
835 if (nick[0] != '*')
836 return 1;
837 else
838 i--;
839 } else if (dcc[i].type == &DCC_BOT) {
840 char s[1024];
841
842 Context;
843
844 if (idx >= 0)
845 dprintf(idx, "%s %s.\n", BOT_BREAKLINK, dcc[i].nick);
846 else if ((idx == -3) && (b_status(i) & STAT_SHARE) && !share_unlinks)
847 return -1;
848 dprintf(i, "bye\n");
849 if (reason && reason[0]) {
850 simple_sprintf(s, "%s %s (%s)", BOT_UNLINKEDFROM,
851 dcc[i].nick, reason);
852 } else {
853 simple_sprintf(s, "%s %s", BOT_UNLINKEDFROM, dcc[i].nick);
854 }
855 chatout("*** %s\n", s);
856 botnet_send_unlinked(i, dcc[i].nick, s);
857 killsock(dcc[i].sock);
858 lostdcc(i);
859 if (nick[0] != '*')
860 return 1;
861 else
862 i--;
863 }
864 }
865 }
866 Context;
867 if ((idx >= 0) && (nick[0] != '*'))
868 dprintf(idx, "%s\n", BOT_NOTCONNECTED);
869 if (nick[0] == '*') {
870 dprintf(idx, "%s\n", BOT_WIPEBOTTABLE);
871 while (tandbot)
872 rembot(tandbot->bot);
873 while (parties) {
874 parties--;
875 /* Assert? */
876 if (party[i].chan >= 0)
877 check_tcl_chpt(party[i].bot, party[i].nick, party[i].sock,
878 party[i].chan);
879 }
880 strcpy(s, "killassoc &");
881 Tcl_Eval(interp, s);
882 }
883 return 0;
884 }
885
886 /* link to another bot */
887 int botlink(char *linker, int idx, char *nick)
888 {
889 struct bot_addr *bi;
890 struct userrec *u;
891 register int i;
892
893 Context;
894 u = get_user_by_handle(userlist, nick);
895 if (!u || !(u->flags & USER_BOT)) {
896 if (idx >= 0)
897 dprintf(idx, "%s %s\n", nick, BOT_BOTUNKNOWN);
898 } else if (!strcasecmp(nick, botnetnick)) {
899 if (idx >= 0)
900 dprintf(idx, "%s\n", BOT_CANTLINKMYSELF);
901 } else if (in_chain(nick) && (idx != -3)) {
902 if (idx >= 0)
903 dprintf(idx, "%s\n", BOT_ALREADYLINKED);
904 } else {
905 for (i = 0; i < dcc_total; i++)
906 if ((dcc[i].user == u) &&
907 ((dcc[i].type == &DCC_FORK_BOT) ||
908 (dcc[i].type == &DCC_BOT_NEW))) {
909 if (idx >= 0)
910 dprintf(idx, "%s\n", BOT_ALREADYLINKING);
911 return 0;
912 }
913 /* address to connect to is in 'info' */
914 bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
915 if (!bi || !strlen(bi->address) || !bi->telnet_port) {
916 if (idx >= 0) {
917 dprintf(idx, "%s '%s'.\n", BOT_NOTELNETADDY, nick);
918 dprintf(idx, "%s .chaddr %s %s\n",
919 MISC_USEFORMAT, nick, MISC_CHADDRFORMAT);
920 }
921 } else if (dcc_total == max_dcc) {
922 if (idx >= 0)
923 dprintf(idx, "%s\n", DCC_TOOMANYDCCS1);
924 } else {
925 Context;
926 correct_handle(nick);
927 i = new_dcc(&DCC_FORK_BOT, sizeof(struct bot_info));
928
929 dcc[i].port = bi->telnet_port;
930 strcpy(dcc[i].nick, nick);
931 strcpy(dcc[i].host, bi->address);
932 dcc[i].timeval = now;
933 strcpy(dcc[i].u.bot->linker, linker);
934 strcpy(dcc[i].u.bot->version, "(primitive bot)");
935 if (idx > -2)
936 putlog(LOG_BOTS, "*", "%s %s at %s:%d ...", BOT_LINKING, nick,
937 bi->address, bi->telnet_port);
938 dcc[i].u.bot->numver = idx;
939 dcc[i].timeval = now;
940 dcc[i].u.bot->port = dcc[i].port; /* remember where i started */
941 dcc[i].sock = getsock(SOCK_STRONGCONN);
942 dcc[i].user = u;
943 if (open_telnet_raw(dcc[i].sock, bi->address, dcc[i].port) < 0)
944 failed_link(i);
945 return 1;
946 }
947 }
948 return 0;
949 }
950
951 static void failed_tandem_relay(int idx)
952 {
953 int uidx = (-1), i;
954
955 Context;
956 for (i = 0; i < dcc_total; i++)
957 if ((dcc[i].type == &DCC_PRE_RELAY) &&
958 (dcc[i].u.relay->sock == dcc[idx].sock))
959 uidx = i;
960 if (uidx < 0) {
961 putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
962 dcc[idx].sock, dcc[idx].u.relay->sock);
963 killsock(dcc[idx].sock);
964 lostdcc(idx);
965 return;
966 }
967 if (dcc[idx].port >= dcc[idx].u.relay->port + 3) {
968 struct chat_info *ci = dcc[uidx].u.relay->chat;
969
970 dprintf(uidx, "%s %s.\n", BOT_CANTLINKTO, dcc[idx].nick);
971 nfree(dcc[uidx].u.relay);
972 dcc[uidx].u.chat = ci;
973 dcc[uidx].type = &DCC_CHAT;
974 dcc[uidx].status = dcc[uidx].u.relay->old_status;
975 killsock(dcc[idx].sock);
976 lostdcc(idx);
977 return;
978 }
979 killsock(dcc[idx].sock);
980 dcc[idx].sock = getsock(SOCK_STRONGCONN);
981 dcc[uidx].u.relay->sock = dcc[idx].sock;
982 dcc[idx].port++;
983 dcc[idx].timeval = now;
984 if (open_telnet_raw(dcc[idx].sock, dcc[idx].host, dcc[idx].port) < 0)
985 failed_tandem_relay(idx);
986 }
987
988 /* relay to another tandembot */
989 void tandem_relay(int idx, char *nick, register int i)
990 {
991 struct chat_info *ci;
992 struct userrec *u;
993 struct bot_addr *bi;
994
995 Context;
996 u = get_user_by_handle(userlist, nick);
997 if (!u || !(u->flags & USER_BOT)) {
998 dprintf(idx, "%s %s\n", nick, BOT_BOTUNKNOWN);
999 return;
1000 }
1001 if (!strcasecmp(nick, botnetnick)) {
1002 dprintf(idx, "%s\n", BOT_CANTRELAYMYSELF);
1003 return;
1004 }
1005 /* address to connect to is in 'info' */
1006 bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
1007 if (!bi) {
1008 dprintf(idx, "%s '%s'.\n", BOT_NOTELNETADDY, nick);
1009 dprintf(idx, "%s .chaddr %s %s\n",
1010 MISC_USEFORMAT, nick, MISC_CHADDRFORMAT);
1011
1012 return;
1013 }
1014 if (dcc_total == max_dcc) {
1015 dprintf(idx, "%s\n", DCC_TOOMANYDCCS1);
1016 return;
1017 }
1018 i = new_dcc(&DCC_FORK_RELAY, sizeof(struct relay_info));
1019 dcc[i].u.relay->chat = get_data_ptr(sizeof(struct chat_info));
1020
1021 dcc[i].port = bi->relay_port;
1022 dcc[i].u.relay->port = dcc[i].port;
1023 dcc[i].addr = 0L;
1024 strcpy(dcc[i].nick, nick);
1025 dcc[i].user = u;
1026 strcpy(dcc[i].host, bi->address);
1027 dcc[i].u.relay->chat->away = NULL;
1028 dcc[i].u.relay->old_status = dcc[i].status;
1029 dcc[i].status = 0;
1030 dcc[i].timeval = now;
1031 dcc[i].u.relay->chat->msgs_per_sec = 0;
1032 dcc[i].u.relay->chat->con_flags = 0;
1033 dcc[i].u.relay->chat->buffer = NULL;
1034 dcc[i].u.relay->chat->max_line = 0;
1035 dcc[i].u.relay->chat->line_count = 0;
1036 dcc[i].u.relay->chat->current_lines = 0;
1037 dprintf(idx, "%s %s @ %s:%d ...\n", BOT_CONNECTINGTO, nick,
1038 bi->address, bi->relay_port);
1039 dprintf(idx, "%s\n", BOT_BYEINFO1);
1040 ci = dcc[idx].u.chat;
1041 dcc[idx].u.relay = get_data_ptr(sizeof(struct relay_info));
1042
1043 dcc[idx].u.relay->chat = ci;
1044 dcc[idx].type = &DCC_PRE_RELAY;
1045 dcc[i].sock = getsock(SOCK_STRONGCONN);
1046 dcc[idx].u.relay->sock = dcc[i].sock;
1047 dcc[i].u.relay->sock = dcc[idx].sock;
1048 dcc[i].timeval = now;
1049 if (open_telnet_raw(dcc[i].sock, dcc[i].host, dcc[i].port) < 0)
1050 failed_tandem_relay(i);
1051 }
1052
1053 /* input from user before connect is ready */
1054 static void pre_relay(int idx, char *buf, register int i)
1055 {
1056 register int tidx = (-1);
1057
1058 Context;
1059 for (i = 0; i < dcc_total; i++)
1060 if ((dcc[i].type == &DCC_FORK_RELAY) &&
1061 (dcc[i].u.relay->sock == dcc[idx].sock))
1062 tidx = i;
1063 if (tidx < 0) {
1064 putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
1065 dcc[i].sock, dcc[i].u.relay->sock);
1066 killsock(dcc[i].sock);
1067 lostdcc(i);
1068 return;
1069 }
1070 Context;
1071 if (!strcasecmp(buf, "*bye*")) {
1072 /* disconnect */
1073 struct chat_info *ci = dcc[idx].u.relay->chat;
1074
1075 dprintf(idx, "%s %s.\n", BOT_ABORTRELAY1, dcc[tidx].nick);
1076 dprintf(idx, "%s %s.\n\n", BOT_ABORTRELAY2, botnetnick);
1077 putlog(LOG_MISC, "*", "%s %s -> %s", BOT_ABORTRELAY3, dcc[idx].nick,
1078 dcc[tidx].nick);
1079 nfree(dcc[idx].u.relay);
1080 dcc[idx].u.chat = ci;
1081 dcc[idx].status = dcc[idx].u.relay->old_status;
1082 dcc[idx].type = &DCC_CHAT;
1083 killsock(dcc[tidx].sock);
1084 lostdcc(tidx);
1085 return;
1086 }
1087 Context;
1088 }
1089
1090 /* user disconnected before her relay had finished connecting */
1091 static void failed_pre_relay(int idx)
1092 {
1093 register int tidx = (-1), i;
1094
1095 Context;
1096 for (i = 0; i < dcc_total; i++)
1097 if ((dcc[i].type == &DCC_FORK_RELAY) &&
1098 (dcc[i].u.relay->sock == dcc[idx].sock))
1099 tidx = i;
1100 if (tidx < 0) {
1101 putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
1102 dcc[i].sock, dcc[i].u.relay->sock);
1103 killsock(dcc[i].sock);
1104 lostdcc(i);
1105 return;
1106 }
1107 putlog(LOG_MISC, "*", "%s [%s]%s/%d", BOT_LOSTDCCUSER, dcc[idx].nick,
1108 dcc[idx].host, dcc[idx].port);
1109 putlog(LOG_MISC, "*", "(%s %s)", BOT_DROPPINGRELAY, dcc[tidx].nick);
1110 if ((dcc[tidx].sock != STDOUT) || backgrd) {
1111 if (idx > tidx) {
1112 int t = tidx;
1113
1114 tidx = idx;
1115 idx = t;
1116 }
1117 killsock(dcc[tidx].sock);
1118 lostdcc(tidx);
1119 } else {
1120 fatal("Lost my terminal??!?!?!", 0);
1121 }
1122 killsock(dcc[idx].sock);
1123 lostdcc(idx);
1124 }
1125
1126 static void cont_tandem_relay(int idx, char *buf, register int i)
1127 {
1128 register int uidx = (-1);
1129 struct relay_info *ri;
1130
1131 Context;
1132 for (i = 0; i < dcc_total; i++)
1133 if ((dcc[i].type == &DCC_PRE_RELAY) &&
1134 (dcc[i].u.relay->sock == dcc[idx].sock))
1135 uidx = i;
1136 if (uidx < 0) {
1137 putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
1138 dcc[i].sock, dcc[i].u.relay->sock);
1139 killsock(dcc[i].sock);
1140 lostdcc(i);
1141 return;
1142 }
1143 dcc[idx].type = &DCC_RELAY;
1144 dcc[idx].u.relay->sock = dcc[uidx].sock;
1145 dcc[uidx].u.relay->sock = dcc[idx].sock;
1146 dprintf(uidx, "%s %s ...\n", BOT_RELAYSUCCESS, dcc[idx].nick);
1147 dprintf(uidx, "%s\n\n", BOT_BYEINFO2);
1148 putlog(LOG_MISC, "*", "%s %s -> %s", BOT_RELAYLINK,
1149 dcc[uidx].nick, dcc[idx].nick);
1150 ri = dcc[uidx].u.relay; /* YEAH */
1151 dcc[uidx].type = &DCC_CHAT;
1152 dcc[uidx].u.chat = ri->chat;
1153 if (dcc[uidx].u.chat->channel >= 0) {
1154 chanout_but(-1, dcc[uidx].u.chat->channel, "*** %s %s\n",
1155 dcc[uidx].nick, BOT_PARTYLEFT);
1156 if (dcc[uidx].u.chat->channel < 100000)
1157 botnet_send_part_idx(uidx, NULL);
1158 check_tcl_chpt(botnetnick, dcc[uidx].nick, dcc[uidx].sock,
1159 dcc[uidx].u.chat->channel);
1160 }
1161 check_tcl_chof(dcc[uidx].nick, dcc[uidx].sock);
1162 dcc[uidx].type = &DCC_RELAYING;
1163 dcc[uidx].u.relay = ri;
1164 }
1165
1166 static void eof_dcc_relay(int idx)
1167 {
1168 register int j;
1169 struct chat_info *ci;
1170
1171 for (j = 0; dcc[j].sock != dcc[idx].u.relay->sock; j++);
1172 /* in case echo was off, turn it back on: */
1173 if (dcc[j].status & STAT_TELNET)
1174 dprintf(j, "\377\374\001\r\n");
1175 putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_ENDRELAY1, dcc[j].nick,
1176 dcc[idx].nick);
1177 dprintf(j, "\n\n*** %s %s\n", BOT_ENDRELAY2, botnetnick);
1178 ci = dcc[j].u.relay->chat;
1179 nfree(dcc[j].u.relay);
1180 dcc[j].u.chat = ci;
1181 dcc[j].type = &DCC_CHAT;
1182 if (dcc[j].u.chat->channel >= 0) {
1183 chanout_but(-1, dcc[j].u.chat->channel, "*** %s %s.\n",
1184 dcc[j].nick, BOT_PARTYREJOINED);
1185 Context;
1186 if (dcc[j].u.chat->channel < 100000)
1187 botnet_send_join_idx(j, -1);
1188 }
1189 dcc[j].status = dcc[j].u.relay->old_status;
1190 check_tcl_chon(dcc[j].nick, dcc[j].sock);
1191 check_tcl_chjn(botnetnick, dcc[j].nick, dcc[j].u.chat->channel,
1192 geticon(j), dcc[j].sock, dcc[j].host);
1193 killsock(dcc[idx].sock);
1194 lostdcc(idx);
1195 }
1196
1197 static void eof_dcc_relaying(int idx)
1198 {
1199 register int j, x = dcc[idx].u.relay->sock;
1200
1201 putlog(LOG_MISC, "*", "%s [%s]%s/%d", BOT_LOSTDCCUSER, dcc[idx].nick,
1202 dcc[idx].host, dcc[idx].port);
1203 killsock(dcc[idx].sock);
1204 lostdcc(idx);
1205 for (j = 0; (dcc[j].sock != x) || (dcc[j].type == &DCC_FORK_RELAY); j++);
1206 putlog(LOG_MISC, "*", "(%s %s)", BOT_DROPPEDRELAY, dcc[j].nick);
1207 killsock(dcc[j].sock);
1208 lostdcc(j); /* drop connection to the bot */
1209 }
1210
1211 static void dcc_relay(int idx, char *buf, int j)
1212 {
1213 unsigned char *p = (unsigned char *) buf;
1214 int mark;
1215
1216 for (j = 0; (dcc[j].sock != dcc[idx].u.relay->sock) ||
1217 (dcc[j].type != &DCC_RELAYING); j++);
1218 /* if redirecting to a non-telnet user, swallow telnet codes */
1219 if (!(dcc[j].status & STAT_TELNET)) {
1220 while (*p != 0) {
1221 while ((*p != 255) && (*p != 0))
1222 p++; /* search for IAC */
1223 if (*p == 255) {
1224 mark = 2;
1225 if (!*(p + 1))
1226 mark = 1; /* bogus */
1227 if ((*(p + 1) >= 251) || (*(p + 1) <= 254)) {
1228 mark = 3;
1229 if (!*(p + 2))
1230 mark = 2; /* bogus */
1231 }
1232 strcpy((char *) p, (char *) (p + mark));
1233 }
1234 }
1235 if (!buf[0])
1236 dprintf(-dcc[idx].u.relay->sock, " \n");
1237 else
1238 dprintf(-dcc[idx].u.relay->sock, "%s\n", buf);
1239 return;
1240 }
1241 /* telnet user */
1242 if (!buf[0])
1243 dprintf(-dcc[idx].u.relay->sock, " \r\n");
1244 else
1245 dprintf(-dcc[idx].u.relay->sock, "%s\r\n", buf);
1246 }
1247
1248 static void dcc_relaying(int idx, char *buf, int j)
1249 {
1250 struct chat_info *ci;
1251
1252 if (strcasecmp(buf, "*bye*")) {
1253 dprintf(-dcc[idx].u.relay->sock, "%s\n", buf);
1254 return;
1255 }
1256 for (j = 0; (dcc[j].sock != dcc[idx].u.relay->sock) ||
1257 (dcc[j].type != &DCC_RELAY); j++);
1258 /* in case echo was off, turn it back on: */
1259 if (dcc[idx].status & STAT_TELNET)
1260 dprintf(idx, "\377\374\001\r\n");
1261 dprintf(idx, "\n(%s %s.)\n", BOT_BREAKRELAY, dcc[j].nick);
1262 dprintf(idx, "%s %s.\n\n", BOT_ABORTRELAY2, botnetnick);
1263 putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_RELAYBROKEN,
1264 dcc[idx].nick, dcc[j].nick);
1265 if (dcc[idx].u.relay->chat->channel >= 0) {
1266 chanout_but(-1, dcc[idx].u.relay->chat->channel,
1267 "*** %s joined the party line.\n", dcc[idx].nick);
1268 Context;
1269 if (dcc[idx].u.relay->chat->channel < 100000)
1270 botnet_send_join_idx(idx, -1);
1271 }
1272 ci = dcc[idx].u.relay->chat;
1273 nfree(dcc[idx].u.relay);
1274 dcc[idx].u.chat = ci;
1275 dcc[idx].type = &DCC_CHAT;
1276 dcc[idx].status = dcc[idx].u.relay->old_status;
1277 check_tcl_chon(dcc[idx].nick, dcc[idx].sock);
1278 if (dcc[idx].u.chat->channel >= 0)
1279 check_tcl_chjn(botnetnick, dcc[idx].nick, dcc[idx].u.chat->channel,
1280 geticon(idx), dcc[idx].sock, dcc[idx].host);
1281 killsock(dcc[j].sock);
1282 lostdcc(j);
1283 }
1284
1285 static void display_relay(int i, char *other)
1286 {
1287 sprintf(other, "rela -> sock %d", dcc[i].u.relay->sock);
1288 }
1289
1290 static void display_relaying(int i, char *other)
1291 {
1292 sprintf(other, ">rly -> sock %d", dcc[i].u.relay->sock);
1293 }
1294
1295 static void display_tandem_relay(int i, char *other)
1296 {
1297 strcpy(other, "other rela");
1298 }
1299
1300 static void display_pre_relay(int i, char *other)
1301 {
1302 strcpy(other, "other >rly");
1303 }
1304
1305 static int expmem_relay(void *x)
1306 {
1307 register struct relay_info *p = (struct relay_info *) x;
1308 int tot = sizeof(struct relay_info);
1309
1310 if (p->chat)
1311 tot += DCC_CHAT.expmem(p->chat);
1312 return tot;
1313 }
1314
1315 static void kill_relay(int idx, void *x)
1316 {
1317 register struct relay_info *p = (struct relay_info *) x;
1318
1319 if (p->chat)
1320 DCC_CHAT.kill(idx, p->chat);
1321 nfree(p);
1322 }
1323
1324 struct dcc_table DCC_RELAY =
1325 {
1326 "RELAY",
1327 0, /* flags */
1328 eof_dcc_relay,
1329 dcc_relay,
1330 0,
1331 0,
1332 display_relay,
1333 expmem_relay,
1334 kill_relay,
1335 0
1336 };
1337
1338 static void out_relay(int idx, char *buf, void *x)
1339 {
1340 register struct relay_info *p = (struct relay_info *) x;
1341
1342 if (p && p->chat)
1343 DCC_CHAT.output(idx, buf, p->chat);
1344 else
1345 tputs(dcc[idx].sock, buf, strlen(buf));
1346 }
1347
1348 struct dcc_table DCC_RELAYING =
1349 {
1350 "RELAYING",
1351 0, /* flags */
1352 eof_dcc_relaying,
1353 dcc_relaying,
1354 0,
1355 0,
1356 display_relaying,
1357 expmem_relay,
1358 kill_relay,
1359 out_relay
1360 };
1361
1362 struct dcc_table DCC_FORK_RELAY =
1363 {
1364 "FORK_RELAY",
1365 0, /* flags */
1366 failed_tandem_relay,
1367 cont_tandem_relay,
1368 &connect_timeout,
1369 failed_tandem_relay,
1370 display_tandem_relay,
1371 expmem_relay,
1372 kill_relay,
1373 0
1374 };
1375
1376 struct dcc_table DCC_PRE_RELAY =
1377 {
1378 "PRE_RELAY",
1379 0, /* flags */
1380 failed_pre_relay,
1381 pre_relay,
1382 0,
1383 0,
1384 display_pre_relay,
1385 expmem_relay,
1386 kill_relay,
1387 0
1388 };
1389
1390 /* once a minute, send 'ping' to each bot -- no exceptions */
1391 void check_botnet_pings()
1392 {
1393 int i;
1394
1395 Context;
1396 for (i = 0; i < dcc_total; i++)
1397 if (dcc[i].type == &DCC_BOT)
1398 if (dcc[i].status & STAT_PINGED) {
1399 char s[1024];
1400
1401 putlog(LOG_BOTS, "*", "%s: %s", BOT_PINGTIMEOUT, dcc[i].nick);
1402 simple_sprintf(s, "%s: %s", BOT_PINGTIMEOUT, dcc[i].nick);
1403 chatout("*** %s\n", s);
1404 botnet_send_unlinked(i, dcc[i].nick, s);
1405 killsock(dcc[i].sock);
1406 lostdcc(i);
1407 }
1408 Context;
1409 for (i = 0; i < dcc_total; i++)
1410 if (dcc[i].type == &DCC_BOT) {
1411 botnet_send_ping(i);
1412 dcc[i].status |= STAT_PINGED;
1413 }
1414 Context;
1415 for (i = 0; i < dcc_total; i++)
1416 if ((dcc[i].type == &DCC_BOT) && (dcc[i].status & STAT_LEAF)) {
1417 tand_t *bot, *via = findbot(dcc[i].nick);
1418
1419 for (bot = tandbot; bot; bot = bot->next) {
1420 if ((via == bot->via) && (bot != via)) {
1421 /* not leaflike behavior */
1422 if (dcc[i].status & STAT_WARNED) {
1423 char s[1024];
1424
1425 putlog(LOG_BOTS, "*", "%s %s (%s).", BOT_DISCONNECTED,
1426 dcc[i].nick, BOT_BOTNOTLEAFLIKE);
1427 dprintf(i, "bye\n");
1428 simple_sprintf(s, "%s %s (%s)", BOT_DISCONNECTED, dcc[i].nick,
1429 BOT_BOTNOTLEAFLIKE);
1430 chatout("*** %s\n", s);
1431 botnet_send_unlinked(i, dcc[i].nick, s);
1432 killsock(dcc[i].sock);
1433 lostdcc(i);
1434 } else {
1435 botnet_send_reject(i, botnetnick, NULL, bot->bot,
1436 NULL, NULL);
1437 dcc[i].status |= STAT_WARNED;
1438 }
1439 } else
1440 dcc[i].status &= ~STAT_WARNED;
1441 }
1442 }
1443 Context;
1444 }
1445
1446 void zapfbot(int idx)
1447 {
1448 char s[1024];
1449
1450 simple_sprintf(s, "%s: %s", BOT_BOTDROPPED, dcc[idx].nick);
1451 chatout("*** %s\n", s);
1452 botnet_send_unlinked(idx, dcc[idx].nick, s);
1453 killsock(dcc[idx].sock);
1454 lostdcc(idx);
1455 }
1456
1457 void restart_chons()
1458 {
1459 int i;
1460
1461 /* dump party line members */
1462 Context;
1463 for (i = 0; i < dcc_total; i++) {
1464 if (dcc[i].type == &DCC_CHAT) {
1465 check_tcl_chon(dcc[i].nick, dcc[i].sock);
1466 check_tcl_chjn(botnetnick, dcc[i].nick, dcc[i].u.chat->channel,
1467 geticon(i), dcc[i].sock, dcc[i].host);
1468 }
1469 }
1470 for (i = 0; i < parties; i++) {
1471 check_tcl_chjn(party[i].bot, party[i].nick, party[i].chan,
1472 party[i].flag, party[i].sock, party[i].from);
1473 }
1474 Context;
1475 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23