/[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.9 - (show annotations) (download) (as text)
Thu Dec 30 23:23:45 1999 UTC (19 years, 8 months ago) by guppy
Branch: MAIN
Changes since 1.8: +13 -14 lines
File MIME type: text/x-chdr
patches

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23