/[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.4 - (show annotations) (download) (as text)
Tue Oct 26 08:08:40 1999 UTC (20 years ago) by arthur2
Branch: MAIN
Changes since 1.3: +2 -4 lines
File MIME type: text/x-chdr
putlog-misc

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 if (party[i].chan >= 0)
343 check_tcl_chpt(bot, party[i].nick, party[i].sock, party[i].chan);
344 remparty(bot, party[i].sock);
345 i--;
346 }
347 }
348
349 /* remove every bot linked 'via' bot <x> */
350 void unvia(int idx, tand_t * who)
351 {
352 tand_t *bot, *bot2;
353
354 if (!who)
355 return; /* safety */
356 rempartybot(who->bot);
357 bot = tandbot;
358 while (bot) {
359 if (bot->uplink == who) {
360 unvia(idx, bot);
361 bot2 = bot->next;
362 rembot(bot->bot);
363 bot = bot2;
364 } else
365 bot = bot->next;
366 }
367 #ifndef NO_OLD_BOTNET
368 /* every bot unvia's bots behind anyway, so why send msg's for
369 * EVERY one? - will this break things?! */
370 tandout_but(idx, "unlinked %s\n", who->bot);
371 #endif
372 }
373
374 /* return index into dcc list of the bot that connects us to bot <x> */
375 int nextbot(char *who)
376 {
377 int j;
378 tand_t *bot = findbot(who);
379
380 if (!bot)
381 return -1;
382
383 for (j = 0; j < dcc_total; j++)
384 if (bot->via && !strcasecmp(bot->via->bot, dcc[j].nick) &&
385 (dcc[j].type == &DCC_BOT))
386 return j;
387 return -1; /* we're not connected to 'via' */
388 }
389
390 /* return name of the bot that is directly connected to bot X */
391 char *lastbot(char *who)
392 {
393 tand_t *bot = findbot(who);
394
395 if (!bot)
396 return "*";
397 else if (bot->uplink == (tand_t *) 1)
398 return botnetnick;
399 else
400 return bot->uplink->bot;
401 }
402
403 /* modern version of 'whom' (use local data) */
404 void answer_local_whom(int idx, int chan)
405 {
406 char c, idle[40], spaces2[33] = " ";
407 int i, len, len2;
408
409 context;
410 if (chan == (-1))
411 dprintf(idx, "%s (+: %s, *: %s)\n", BOT_BOTNETUSERS, BOT_PARTYLINE,
412 BOT_LOCALCHAN);
413 else if (chan > 0) {
414 simple_sprintf(idle, "assoc %d", chan);
415 if ((Tcl_Eval(interp, idle) != TCL_OK) || !interp->result[0])
416 dprintf(idx, "%s %s%d:\n", BOT_USERSONCHAN,
417 (chan < 100000) ? "" : "*", chan % 100000);
418 else
419 dprintf(idx, "%s '%s%s' (%s%d):\n", BOT_USERSONCHAN,
420 (chan < 100000) ? "" : "*", interp->result,
421 (chan < 100000) ? "" : "*", chan % 100000);
422 }
423 spaces[HANDLEN - 9] = 0;
424 dprintf(idx, " Nick %s Bot %s Host\n", spaces, spaces);
425 dprintf(idx, "----------%s ---------%s --------------------\n",
426 spaces, spaces);
427 spaces[HANDLEN - 9] = ' ';
428 for (i = 0; i < dcc_total; i++)
429 if (dcc[i].type == &DCC_CHAT) {
430 if ((chan == (-1)) || ((chan >= 0) && (dcc[i].u.chat->channel == chan))) {
431 c = geticon(i);
432 if (c == '-')
433 c = ' ';
434 if (now - dcc[i].timeval > 300) {
435 unsigned long days, hrs, mins;
436
437 days = (now - dcc[i].timeval) / 86400;
438 hrs = ((now - dcc[i].timeval) - (days * 86400)) / 3600;
439 mins = ((now - dcc[i].timeval) - (hrs * 3600)) / 60;
440 if (days > 0)
441 sprintf(idle, " [idle %lud%luh]", days, hrs);
442 else if (hrs > 0)
443 sprintf(idle, " [idle %luh%lum]", hrs, mins);
444 else
445 sprintf(idle, " [idle %lum]", mins);
446 } else
447 idle[0] = 0;
448 spaces[len = HANDLEN - strlen(dcc[i].nick)] = 0;
449 spaces2[len2 = HANDLEN - strlen(botnetnick)] = 0;
450 dprintf(idx, "%c%s%s %c %s%s %s%s\n", c, dcc[i].nick, spaces,
451 (dcc[i].u.chat->channel == 0) && (chan == (-1)) ? '+' :
452 (dcc[i].u.chat->channel > 100000) &&
453 (chan == (-1)) ? '*' : ' ',
454 botnetnick, spaces2, dcc[i].host, idle);
455 spaces[len] = ' ';
456 spaces2[len2] = ' ';
457 if (dcc[i].u.chat->away != NULL)
458 dprintf(idx, " AWAY: %s\n", dcc[i].u.chat->away);
459 }
460 }
461 for (i = 0; i < parties; i++) {
462 if ((chan == (-1)) || ((chan >= 0) && (party[i].chan == chan))) {
463 c = party[i].flag;
464 if (c == '-')
465 c = ' ';
466 if (party[i].timer == 0L)
467 strcpy(idle, " [idle?]");
468 else if (now - party[i].timer > 300) {
469 unsigned long days, hrs, mins;
470
471 days = (now - party[i].timer) / 86400;
472 hrs = ((now - party[i].timer) - (days * 86400)) / 3600;
473 mins = ((now - party[i].timer) - (hrs * 3600)) / 60;
474 if (days > 0)
475 sprintf(idle, " [idle %lud%luh]", days, hrs);
476 else if (hrs > 0)
477 sprintf(idle, " [idle %luh%lum]", hrs, mins);
478 else
479 sprintf(idle, " [idle %lum]", mins);
480 } else
481 idle[0] = 0;
482 spaces[len = HANDLEN - strlen(party[i].nick)] = 0;
483 spaces2[len2 = HANDLEN - strlen(party[i].bot)] = 0;
484 dprintf(idx, "%c%s%s %c %s%s %s%s\n", c, party[i].nick, spaces,
485 (party[i].chan == 0) && (chan == (-1)) ? '+' : ' ',
486 party[i].bot, spaces2, party[i].from, idle);
487 spaces[len] = ' ';
488 spaces2[len2] = ' ';
489 if (party[i].status & PLSTAT_AWAY)
490 dprintf(idx, " %s: %s\n", MISC_AWAY, safe_str(party[i].away));
491 }
492 }
493 }
494
495 /* show z a list of all bots connected */
496 void tell_bots(int idx)
497 {
498 char s[512];
499 int i;
500 tand_t *bot;
501
502 if (!tands) {
503 dprintf(idx, "%s\n", BOT_NOBOTSLINKED);
504 return;
505 }
506 strcpy(s, botnetnick);
507 i = strlen(botnetnick);
508
509 for (bot = tandbot; bot; bot = bot->next) {
510 if (i > (500 - HANDLEN)) {
511 dprintf(idx, "Bots: %s\n", s);
512 s[0] = 0;
513 i = 0;
514 }
515 if (i) {
516 s[i++] = ',';
517 s[i++] = ' ';
518 }
519 strcpy(s + i, bot->bot);
520 i += strlen(bot->bot);
521 }
522 if (s[0])
523 dprintf(idx, "Bots: %s\n", s);
524 dprintf(idx, "(%s: %d)\n", MISC_TOTAL, tands + 1);
525 }
526
527 /* show a simpleton bot tree */
528 void tell_bottree(int idx, int showver)
529 {
530 char s[161];
531 tand_t *last[20], *this, *bot, *bot2 = NULL;
532 int lev = 0, more = 1, mark[20], ok, cnt, i, imark;
533 char work[1024];
534 int tothops = 0;
535
536 if (tands == 0) {
537 dprintf(idx, "%s\n", BOT_NOBOTSLINKED);
538 return;
539 }
540 s[0] = 0;
541 i = 0;
542
543 for (bot = tandbot; bot; bot = bot->next)
544 if (!bot->uplink) {
545 if (i) {
546 s[i++] = ',';
547 s[i++] = ' ';
548 }
549 strcpy(s + i, bot->bot);
550 i += strlen(bot->bot);
551 }
552 if (s[0])
553 dprintf(idx, "(%s %s)\n", BOT_NOTRACEINFO, s);
554 if (showver)
555 dprintf(idx, "%s (%d.%d.%d.%d)\n", botnetnick,
556 egg_numver / 1000000,
557 egg_numver % 1000000 / 10000,
558 egg_numver % 10000 / 100,
559 egg_numver % 100);
560 else
561 dprintf(idx, "%s\n", botnetnick);
562 this = (tand_t *) 1;
563 work[0] = 0;
564 while (more) {
565 if (lev == 20) {
566 dprintf(idx, "\n%s\n", BOT_COMPLEXTREE);
567 return;
568 }
569 cnt = 0;
570 tothops += lev;
571 for (bot = tandbot; bot; bot = bot->next)
572 if (bot->uplink == this)
573 cnt++;
574 if (cnt) {
575 imark = 0;
576 for (i = 0; i < lev; i++) {
577 if (mark[i])
578 strcpy(work + imark, " | ");
579 else
580 strcpy(work + imark, " ");
581 imark += 5;
582 }
583 if (cnt > 1)
584 strcpy(work + imark, " |-");
585 else
586 strcpy(work + imark, " `-");
587 s[0] = 0;
588 bot = tandbot;
589 while (!s[0]) {
590 if (bot->uplink == this) {
591 if (bot->ver) {
592 i = sprintf(s, "%c%s", bot->share, bot->bot);
593 if (showver)
594 sprintf(s + i, " (%d.%d.%d.%d)",
595 bot->ver / 1000000,
596 bot->ver % 1000000 / 10000,
597 bot->ver % 10000 / 100,
598 bot->ver % 100);
599 } else {
600 sprintf(s, "-%s", bot->bot);
601 }
602 } else
603 bot = bot->next;
604 }
605 dprintf(idx, "%s%s\n", work, s);
606 if (cnt > 1)
607 mark[lev] = 1;
608 else
609 mark[lev] = 0;
610 work[0] = 0;
611 last[lev] = this;
612 this = bot;
613 lev++;
614 more = 1;
615 } else {
616 while (cnt == 0) {
617 /* no subtrees from here */
618 if (lev == 0) {
619 dprintf(idx, "(( tree error ))\n");
620 return;
621 }
622 ok = 0;
623 for (bot = tandbot; bot; bot = bot->next) {
624 if (bot->uplink == last[lev - 1]) {
625 if (this == bot)
626 ok = 1;
627 else if (ok) {
628 cnt++;
629 if (cnt == 1) {
630 bot2 = bot;
631 if (bot->ver) {
632 i = sprintf(s, "%c%s", bot->share, bot->bot);
633 if (showver)
634 sprintf(s + i, " (%d.%d.%d.%d)",
635 bot->ver / 1000000,
636 bot->ver % 1000000 / 10000,
637 bot->ver % 10000 / 100,
638 bot->ver % 100);
639 } else {
640 sprintf(s, "-%s", bot->bot);
641 }
642 }
643 }
644 }
645 }
646 if (cnt) {
647 imark = 0;
648 for (i = 1; i < lev; i++) {
649 if (mark[i - 1])
650 strcpy(work + imark, " | ");
651 else
652 strcpy(work + imark, " ");
653 imark += 5;
654 }
655 more = 1;
656 if (cnt > 1)
657 dprintf(idx, "%s |-%s\n", work, s);
658 else
659 dprintf(idx, "%s `-%s\n", work, s);
660 this = bot2;
661 work[0] = 0;
662 if (cnt > 1)
663 mark[lev - 1] = 1;
664 else
665 mark[lev - 1] = 0;
666 } else {
667 /* this was the last child */
668 lev--;
669 if (lev == 0) {
670 more = 0;
671 cnt = 999;
672 } else {
673 more = 1;
674 this = last[lev];
675 }
676 }
677 }
678 }
679 }
680 /* hop information: (9d) */
681 dprintf(idx, "Average hops: %3.1f, total bots: %d\n",
682 ((float) tothops) / ((float) tands), tands + 1);
683 }
684
685 /* dump list of links to a new bot */
686 void dump_links(int z)
687 {
688 int i, l;
689 char x[1024];
690 tand_t *bot;
691
692 context;
693 for (bot = tandbot; bot; bot = bot->next) {
694 char *p;
695
696 if (bot->uplink == (tand_t *) 1)
697 p = botnetnick;
698 else
699 p = bot->uplink->bot;
700 #ifndef NO_OLD_BOTNET
701 if (b_numver(z) < NEAT_BOTNET)
702 l = simple_sprintf(x, "nlinked %s %s %c%d\n", bot->bot,
703 p, bot->share, bot->ver);
704 else
705 #endif
706 l = simple_sprintf(x, "n %s %s %c%D\n", bot->bot, p,
707 bot->share, bot->ver);
708 tputs(dcc[z].sock, x, l);
709 }
710 context;
711 if (!(bot_flags(dcc[z].user) & BOT_ISOLATE)) {
712 /* dump party line members */
713 for (i = 0; i < dcc_total; i++) {
714 if (dcc[i].type == &DCC_CHAT) {
715 if ((dcc[i].u.chat->channel >= 0) &&
716 (dcc[i].u.chat->channel < 100000)) {
717 #ifndef NO_OLD_BOTNET
718 if (b_numver(z) < NEAT_BOTNET)
719 l = simple_sprintf(x, "join %s %s %d %c%d %s\n",
720 botnetnick, dcc[i].nick,
721 dcc[i].u.chat->channel, geticon(i),
722 dcc[i].sock, dcc[i].host);
723 else
724 #endif
725 l = simple_sprintf(x, "j !%s %s %D %c%D %s\n",
726 botnetnick, dcc[i].nick,
727 dcc[i].u.chat->channel, geticon(i),
728 dcc[i].sock, dcc[i].host);
729 tputs(dcc[z].sock, x, l);
730 #ifndef NO_OLD_BOTNET
731 if (b_numver(z) < NEAT_BOTNET) {
732 if (dcc[i].u.chat->away) {
733 l = simple_sprintf(x, "away %s %d %s\n", botnetnick,
734 dcc[i].sock, dcc[i].u.chat->away);
735 tputs(dcc[z].sock, x, l);
736 }
737 l = simple_sprintf(x, "idle %s %d %d\n", botnetnick,
738 dcc[i].sock, now - dcc[i].timeval);
739 } else
740 #endif
741 l = simple_sprintf(x, "i %s %D %D %s\n", botnetnick,
742 dcc[i].sock, now - dcc[i].timeval,
743 dcc[i].u.chat->away ? dcc[i].u.chat->away : "");
744 tputs(dcc[z].sock, x, l);
745 }
746 }
747 }
748 context;
749 for (i = 0; i < parties; i++) {
750 #ifndef NO_OLD_BOTNET
751 if (b_numver(z) < NEAT_BOTNET)
752 l = simple_sprintf(x, "join %s %s %d %c%d %s\n",
753 party[i].bot, party[i].nick,
754 party[i].chan, party[i].flag,
755 party[i].sock, party[i].from);
756 else
757 #endif
758 l = simple_sprintf(x, "j %s %s %D %c%D %s\n",
759 party[i].bot, party[i].nick,
760 party[i].chan, party[i].flag,
761 party[i].sock, party[i].from);
762 tputs(dcc[z].sock, x, l);
763 if ((party[i].status & PLSTAT_AWAY) || (party[i].timer != 0)) {
764 #ifndef NO_OLD_BOTNET
765 if (b_numver(z) < NEAT_BOTNET) {
766 if (party[i].status & PLSTAT_AWAY) {
767 l = simple_sprintf(x, "away %s %d %s\n", party[i].bot,
768 party[i].sock, party[i].away);
769 tputs(dcc[z].sock, x, l);
770 }
771 l = simple_sprintf(x, "idle %s %d %d\n", party[i].bot,
772 party[i].sock, now - party[i].timer);
773 } else
774 #endif
775 l = simple_sprintf(x, "i %s %D %D %s\n", party[i].bot,
776 party[i].sock, now - party[i].timer,
777 party[i].away ? party[i].away : "");
778 tputs(dcc[z].sock, x, l);
779 }
780 }
781 }
782 context;
783 }
784
785 int in_chain(char *who)
786 {
787 if (findbot(who))
788 return 1;
789 if (!strcasecmp(who, botnetnick))
790 return 1;
791 return 0;
792 }
793
794 /* break link with a tandembot */
795 int botunlink(int idx, char *nick, char *reason)
796 {
797 char s[20];
798 int i;
799
800 context;
801 if (nick[0] == '*')
802 dprintf(idx, "%s\n", BOT_UNLINKALL);
803 for (i = 0; i < dcc_total; i++) {
804 if ((nick[0] == '*') || !strcasecmp(dcc[i].nick, nick)) {
805 if (dcc[i].type == &DCC_FORK_BOT) {
806 if (idx >= 0)
807 dprintf(idx, "%s: %s -> %s.\n", BOT_KILLLINKATTEMPT,
808 dcc[i].nick, dcc[i].host);
809 putlog(LOG_BOTS, "*", "%s: %s -> %s:%d",
810 BOT_KILLLINKATTEMPT, dcc[i].nick,
811 dcc[i].host, dcc[i].port);
812 killsock(dcc[i].sock);
813 lostdcc(i);
814 if (nick[0] != '*')
815 return 1;
816 } else if (dcc[i].type == &DCC_BOT_NEW) {
817 if (idx >= 0)
818 dprintf(idx, "%s %s.\n", BOT_ENDLINKATTEMPT,
819 dcc[i].nick);
820 putlog(LOG_BOTS, "*", "%s %s @ %s:%d",
821 "Stopped trying to link", dcc[i].nick,
822 dcc[i].host, dcc[i].port);
823 killsock(dcc[i].sock);
824 lostdcc(i);
825 if (nick[0] != '*')
826 return 1;
827 else
828 i--;
829 } else if (dcc[i].type == &DCC_BOT) {
830 char s[1024];
831
832 context;
833
834 if (idx >= 0)
835 dprintf(idx, "%s %s.\n", BOT_BREAKLINK, dcc[i].nick);
836 else if ((idx == -3) && (b_status(i) & STAT_SHARE) && !share_unlinks)
837 return -1;
838 dprintf(i, "bye\n");
839 if (reason && reason[0]) {
840 simple_sprintf(s, "%s %s (%s)", BOT_UNLINKEDFROM,
841 dcc[i].nick, reason);
842 } else {
843 simple_sprintf(s, "%s %s", BOT_UNLINKEDFROM, dcc[i].nick);
844 }
845 chatout("*** %s\n", s);
846 botnet_send_unlinked(i, dcc[i].nick, s);
847 killsock(dcc[i].sock);
848 lostdcc(i);
849 if (nick[0] != '*')
850 return 1;
851 else
852 i--;
853 }
854 }
855 }
856 context;
857 if ((idx >= 0) && (nick[0] != '*'))
858 dprintf(idx, "%s\n", BOT_NOTCONNECTED);
859 if (nick[0] == '*') {
860 dprintf(idx, "%s\n", BOT_WIPEBOTTABLE);
861 while (tandbot)
862 rembot(tandbot->bot);
863 while (parties) {
864 parties--;
865 /* ASSERT? */
866 if (party[i].chan >= 0)
867 check_tcl_chpt(party[i].bot, party[i].nick, party[i].sock,
868 party[i].chan);
869 }
870 strcpy(s, "killassoc &");
871 Tcl_Eval(interp, s);
872 }
873 return 0;
874 }
875
876 /* link to another bot */
877 int botlink(char *linker, int idx, char *nick)
878 {
879 struct bot_addr *bi;
880 struct userrec *u;
881 int i;
882
883 context;
884 u = get_user_by_handle(userlist, nick);
885 if (!u || !(u->flags & USER_BOT)) {
886 if (idx >= 0)
887 dprintf(idx, "%s %s\n", nick, BOT_BOTUNKNOWN);
888 } else if (!strcasecmp(nick, botnetnick)) {
889 if (idx >= 0)
890 dprintf(idx, "%s\n", BOT_CANTLINKMYSELF);
891 } else if (in_chain(nick) && (idx != -3)) {
892 if (idx >= 0)
893 dprintf(idx, "%s\n", BOT_ALREADYLINKED);
894 } else {
895 for (i = 0; i < dcc_total; i++)
896 if ((dcc[i].user == u) &&
897 ((dcc[i].type == &DCC_FORK_BOT) ||
898 (dcc[i].type == &DCC_BOT_NEW))) {
899 if (idx >= 0)
900 dprintf(idx, "%s\n", BOT_ALREADYLINKING);
901 return 0;
902 }
903 /* address to connect to is in 'info' */
904 bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
905 if (!bi || !strlen(bi->address) || !bi->telnet_port) {
906 if (idx >= 0) {
907 dprintf(idx, "%s '%s'.\n", BOT_NOTELNETADDY, nick);
908 dprintf(idx, "%s .chaddr %s %s\n",
909 MISC_USEFORMAT, nick, MISC_CHADDRFORMAT);
910 }
911 } else if (dcc_total == max_dcc) {
912 if (idx >= 0)
913 dprintf(idx, "%s\n", DCC_TOOMANYDCCS1);
914 } else {
915 context;
916 correct_handle(nick);
917 i = new_dcc(&DCC_FORK_BOT, sizeof(struct bot_info));
918
919 dcc[i].port = bi->telnet_port;
920 strcpy(dcc[i].nick, nick);
921 strcpy(dcc[i].host, bi->address);
922 dcc[i].timeval = now;
923 strcpy(dcc[i].u.bot->linker, linker);
924 strcpy(dcc[i].u.bot->version, "(primitive bot)");
925 if (idx > -2)
926 putlog(LOG_BOTS, "*", "%s %s at %s:%d ...", BOT_LINKING, nick,
927 bi->address, bi->telnet_port);
928 dcc[i].u.bot->numver = idx;
929 dcc[i].timeval = now;
930 dcc[i].u.bot->port = dcc[i].port; /* remember where i started */
931 dcc[i].sock = getsock(SOCK_STRONGCONN);
932 dcc[i].user = u;
933 if (open_telnet_raw(dcc[i].sock, bi->address, dcc[i].port) >= 0)
934 return 1;
935 failed_link(i);
936 }
937 }
938 return 0;
939 }
940
941 static void failed_tandem_relay(int idx)
942 {
943 int uidx = (-1), i;
944
945 context;
946 for (i = 0; i < dcc_total; i++)
947 if ((dcc[i].type == &DCC_PRE_RELAY) &&
948 (dcc[i].u.relay->sock == dcc[idx].sock))
949 uidx = i;
950 if (uidx < 0) {
951 putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
952 dcc[idx].sock, dcc[idx].u.relay->sock);
953 killsock(dcc[idx].sock);
954 lostdcc(idx);
955 return;
956 }
957 if (dcc[idx].port >= dcc[idx].u.relay->port + 3) {
958 struct chat_info *ci = dcc[uidx].u.relay->chat;
959
960 dprintf(uidx, "%s %s.\n", BOT_CANTLINKTO, dcc[idx].nick);
961 nfree(dcc[uidx].u.relay);
962 dcc[uidx].u.chat = ci;
963 dcc[uidx].type = &DCC_CHAT;
964 dcc[uidx].status = dcc[uidx].u.relay->old_status;
965 killsock(dcc[idx].sock);
966 lostdcc(idx);
967 return;
968 }
969 killsock(dcc[idx].sock);
970 dcc[idx].sock = getsock(SOCK_STRONGCONN);
971 dcc[uidx].u.relay->sock = dcc[idx].sock;
972 dcc[idx].port++;
973 dcc[idx].timeval = now;
974 if (open_telnet_raw(dcc[idx].sock, dcc[idx].host, dcc[idx].port) < 0)
975 failed_tandem_relay(idx);
976 }
977
978 /* relay to another tandembot */
979 void tandem_relay(int idx, char *nick, int i)
980 {
981 struct chat_info *ci;
982 struct userrec *u;
983 struct bot_addr *bi;
984
985 context;
986 u = get_user_by_handle(userlist, nick);
987 if (!u || !(u->flags & USER_BOT)) {
988 dprintf(idx, "%s %s\n", nick, BOT_BOTUNKNOWN);
989 return;
990 }
991 if (!strcasecmp(nick, botnetnick)) {
992 dprintf(idx, "%s\n", BOT_CANTRELAYMYSELF);
993 return;
994 }
995 /* address to connect to is in 'info' */
996 bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u);
997 if (!bi) {
998 dprintf(idx, "%s '%s'.\n", BOT_NOTELNETADDY, nick);
999 dprintf(idx, "%s .chaddr %s %s\n",
1000 MISC_USEFORMAT, nick, MISC_CHADDRFORMAT);
1001
1002 return;
1003 }
1004 if (dcc_total == max_dcc) {
1005 dprintf(idx, "%s\n", DCC_TOOMANYDCCS1);
1006 return;
1007 }
1008 i = new_dcc(&DCC_FORK_RELAY, sizeof(struct relay_info));
1009 dcc[i].u.relay->chat = get_data_ptr(sizeof(struct chat_info));
1010
1011 dcc[i].port = bi->relay_port;
1012 dcc[i].u.relay->port = dcc[i].port;
1013 dcc[i].addr = 0L;
1014 strcpy(dcc[i].nick, nick);
1015 dcc[i].user = u;
1016 strcpy(dcc[i].host, bi->address);
1017 dcc[i].u.relay->chat->away = NULL;
1018 dcc[i].u.relay->old_status = dcc[i].status;
1019 dcc[i].status = 0;
1020 dcc[i].timeval = now;
1021 dcc[i].u.relay->chat->msgs_per_sec = 0;
1022 dcc[i].u.relay->chat->con_flags = 0;
1023 dcc[i].u.relay->chat->buffer = NULL;
1024 dcc[i].u.relay->chat->max_line = 0;
1025 dcc[i].u.relay->chat->line_count = 0;
1026 dcc[i].u.relay->chat->current_lines = 0;
1027 dprintf(idx, "%s %s @ %s:%d ...\n", BOT_CONNECTINGTO, nick,
1028 bi->address, bi->relay_port);
1029 dprintf(idx, "%s\n", BOT_BYEINFO1);
1030 ci = dcc[idx].u.chat;
1031 dcc[idx].u.relay = get_data_ptr(sizeof(struct relay_info));
1032
1033 dcc[idx].u.relay->chat = ci;
1034 dcc[idx].type = &DCC_PRE_RELAY;
1035 dcc[i].sock = getsock(SOCK_STRONGCONN);
1036 dcc[idx].u.relay->sock = dcc[i].sock;
1037 dcc[i].u.relay->sock = dcc[idx].sock;
1038 dcc[i].timeval = now;
1039 if (open_telnet_raw(dcc[i].sock, dcc[i].host, dcc[i].port) < 0)
1040 failed_tandem_relay(i);
1041 }
1042
1043 /* input from user before connect is ready */
1044 static void pre_relay(int idx, char *buf, int i)
1045 {
1046 int tidx = (-1);
1047
1048 context;
1049 for (i = 0; i < dcc_total; i++)
1050 if ((dcc[i].type == &DCC_FORK_RELAY) &&
1051 (dcc[i].u.relay->sock == dcc[idx].sock))
1052 tidx = i;
1053 if (tidx < 0) {
1054 putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
1055 dcc[i].sock, dcc[i].u.relay->sock);
1056 killsock(dcc[i].sock);
1057 lostdcc(i);
1058 return;
1059 }
1060 context;
1061 if (!strcasecmp(buf, "*bye*")) {
1062 /* disconnect */
1063 struct chat_info *ci = dcc[idx].u.relay->chat;
1064
1065 dprintf(idx, "%s %s.\n", BOT_ABORTRELAY1, dcc[tidx].nick);
1066 dprintf(idx, "%s %s.\n\n", BOT_ABORTRELAY2, botnetnick);
1067 putlog(LOG_MISC, "*", "%s %s -> %s", BOT_ABORTRELAY3, dcc[idx].nick,
1068 dcc[tidx].nick);
1069 nfree(dcc[idx].u.relay);
1070 dcc[idx].u.chat = ci;
1071 dcc[idx].status = dcc[idx].u.relay->old_status;
1072 dcc[idx].type = &DCC_CHAT;
1073 killsock(dcc[tidx].sock);
1074 lostdcc(tidx);
1075 return;
1076 }
1077 context;
1078 }
1079
1080 /* user disconnected before her relay had finished connecting */
1081 static void failed_pre_relay(int idx)
1082 {
1083 int tidx = (-1), i;
1084
1085 context;
1086 for (i = 0; i < dcc_total; i++)
1087 if ((dcc[i].type == &DCC_FORK_RELAY) &&
1088 (dcc[i].u.relay->sock == dcc[idx].sock))
1089 tidx = i;
1090 if (tidx < 0) {
1091 putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
1092 dcc[i].sock, dcc[i].u.relay->sock);
1093 killsock(dcc[i].sock);
1094 lostdcc(i);
1095 return;
1096 }
1097 putlog(LOG_MISC, "*", "%s [%s]%s/%d", BOT_LOSTDCCUSER, dcc[idx].nick,
1098 dcc[idx].host, dcc[idx].port);
1099 putlog(LOG_MISC, "*", "(%s %s)", BOT_DROPPINGRELAY, dcc[tidx].nick);
1100 if ((dcc[tidx].sock != STDOUT) || backgrd) {
1101 if (idx > tidx) {
1102 int t = tidx;
1103
1104 tidx = idx;
1105 idx = t;
1106 }
1107 killsock(dcc[tidx].sock);
1108 lostdcc(tidx);
1109 } else {
1110 fatal("Lost my terminal??!?!?!", 0);
1111 }
1112 killsock(dcc[idx].sock);
1113 lostdcc(idx);
1114 }
1115
1116 static void cont_tandem_relay(int idx, char *buf, int i)
1117 {
1118 int uidx = (-1);
1119 struct relay_info *ri;
1120
1121 context;
1122 for (i = 0; i < dcc_total; i++)
1123 if ((dcc[i].type == &DCC_PRE_RELAY) &&
1124 (dcc[i].u.relay->sock == dcc[idx].sock))
1125 uidx = i;
1126 if (uidx < 0) {
1127 putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER,
1128 dcc[i].sock, dcc[i].u.relay->sock);
1129 killsock(dcc[i].sock);
1130 lostdcc(i);
1131 return;
1132 }
1133 dcc[idx].type = &DCC_RELAY;
1134 dcc[idx].u.relay->sock = dcc[uidx].sock;
1135 dcc[uidx].u.relay->sock = dcc[idx].sock;
1136 dprintf(uidx, "%s %s ...\n", BOT_RELAYSUCCESS, dcc[idx].nick);
1137 dprintf(uidx, "%s\n\n", BOT_BYEINFO2);
1138 putlog(LOG_MISC, "*", "%s %s -> %s", BOT_RELAYLINK,
1139 dcc[uidx].nick, dcc[idx].nick);
1140 ri = dcc[uidx].u.relay; /* YEAH */
1141 dcc[uidx].type = &DCC_CHAT;
1142 dcc[uidx].u.chat = ri->chat;
1143 if (dcc[uidx].u.chat->channel >= 0) {
1144 chanout_but(-1, dcc[uidx].u.chat->channel, "*** %s %s\n",
1145 dcc[uidx].nick, BOT_PARTYLEFT);
1146 if (dcc[uidx].u.chat->channel < 100000)
1147 botnet_send_part_idx(uidx, NULL);
1148 check_tcl_chpt(botnetnick, dcc[uidx].nick, dcc[uidx].sock,
1149 dcc[uidx].u.chat->channel);
1150 }
1151 check_tcl_chof(dcc[uidx].nick, dcc[uidx].sock);
1152 dcc[uidx].type = &DCC_RELAYING;
1153 dcc[uidx].u.relay = ri;
1154 }
1155
1156 static void eof_dcc_relay(int idx)
1157 {
1158 int j;
1159 struct chat_info *ci;
1160
1161 for (j = 0; dcc[j].sock != dcc[idx].u.relay->sock; j++);
1162 /* in case echo was off, turn it back on: */
1163 if (dcc[j].status & STAT_TELNET)
1164 dprintf(j, "\377\374\001\r\n");
1165 putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_ENDRELAY1, dcc[j].nick,
1166 dcc[idx].nick);
1167 dprintf(j, "\n\n*** %s %s\n", BOT_ENDRELAY2, botnetnick);
1168 ci = dcc[j].u.relay->chat;
1169 nfree(dcc[j].u.relay);
1170 dcc[j].u.chat = ci;
1171 dcc[j].type = &DCC_CHAT;
1172 if (dcc[j].u.chat->channel >= 0) {
1173 chanout_but(-1, dcc[j].u.chat->channel, "*** %s %s.\n",
1174 dcc[j].nick, BOT_PARTYREJOINED);
1175 context;
1176 if (dcc[j].u.chat->channel < 100000)
1177 botnet_send_join_idx(j, -1);
1178 }
1179 dcc[j].status = dcc[j].u.relay->old_status;
1180 check_tcl_chon(dcc[j].nick, dcc[j].sock);
1181 check_tcl_chjn(botnetnick, dcc[j].nick, dcc[j].u.chat->channel,
1182 geticon(j), dcc[j].sock, dcc[j].host);
1183 killsock(dcc[idx].sock);
1184 lostdcc(idx);
1185 }
1186
1187 static void eof_dcc_relaying(int idx)
1188 {
1189 int j, x = dcc[idx].u.relay->sock;
1190
1191 putlog(LOG_MISC, "*", "%s [%s]%s/%d", BOT_LOSTDCCUSER, dcc[idx].nick,
1192 dcc[idx].host, dcc[idx].port);
1193 killsock(dcc[idx].sock);
1194 lostdcc(idx);
1195 for (j = 0; (dcc[j].sock != x) || (dcc[j].type == &DCC_FORK_RELAY) ||
1196 (dcc[j].type == &DCC_LOST); j++);
1197 putlog(LOG_MISC, "*", "(%s %s)", BOT_DROPPEDRELAY, dcc[j].nick);
1198 killsock(dcc[j].sock);
1199 lostdcc(j); /* drop connection to the bot */
1200 }
1201
1202 static void dcc_relay(int idx, char *buf, int j)
1203 {
1204 unsigned char *p = (unsigned char *) buf;
1205 int mark;
1206
1207 for (j = 0; (dcc[j].sock != dcc[idx].u.relay->sock) ||
1208 (dcc[j].type != &DCC_RELAYING); j++);
1209 /* if redirecting to a non-telnet user, swallow telnet codes */
1210 if (!(dcc[j].status & STAT_TELNET)) {
1211 while (*p != 0) {
1212 while ((*p != 255) && (*p != 0))
1213 p++; /* search for IAC */
1214 if (*p == 255) {
1215 mark = 2;
1216 if (!*(p + 1))
1217 mark = 1; /* bogus */
1218 if ((*(p + 1) >= 251) || (*(p + 1) <= 254)) {
1219 mark = 3;
1220 if (!*(p + 2))
1221 mark = 2; /* bogus */
1222 }
1223 strcpy((char *) p, (char *) (p + mark));
1224 }
1225 }
1226 if (!buf[0])
1227 dprintf(-dcc[idx].u.relay->sock, " \n");
1228 else
1229 dprintf(-dcc[idx].u.relay->sock, "%s\n", buf);
1230 return;
1231 }
1232 /* telnet user */
1233 if (!buf[0])
1234 dprintf(-dcc[idx].u.relay->sock, " \r\n");
1235 else
1236 dprintf(-dcc[idx].u.relay->sock, "%s\r\n", buf);
1237 }
1238
1239 static void dcc_relaying(int idx, char *buf, int j)
1240 {
1241 struct chat_info *ci;
1242
1243 if (strcasecmp(buf, "*bye*")) {
1244 dprintf(-dcc[idx].u.relay->sock, "%s\n", buf);
1245 return;
1246 }
1247 for (j = 0; (dcc[j].sock != dcc[idx].u.relay->sock) ||
1248 (dcc[j].type != &DCC_RELAY); j++);
1249 /* in case echo was off, turn it back on: */
1250 if (dcc[idx].status & STAT_TELNET)
1251 dprintf(idx, "\377\374\001\r\n");
1252 dprintf(idx, "\n(%s %s.)\n", BOT_BREAKRELAY, dcc[j].nick);
1253 dprintf(idx, "%s %s.\n\n", BOT_ABORTRELAY2, botnetnick);
1254 putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_RELAYBROKEN,
1255 dcc[idx].nick, dcc[j].nick);
1256 if (dcc[idx].u.relay->chat->channel >= 0) {
1257 chanout_but(-1, dcc[idx].u.relay->chat->channel,
1258 "*** %s joined the party line.\n", dcc[idx].nick);
1259 context;
1260 if (dcc[idx].u.relay->chat->channel < 100000)
1261 botnet_send_join_idx(idx, -1);
1262 }
1263 ci = dcc[idx].u.relay->chat;
1264 nfree(dcc[idx].u.relay);
1265 dcc[idx].u.chat = ci;
1266 dcc[idx].type = &DCC_CHAT;
1267 dcc[idx].status = dcc[idx].u.relay->old_status;
1268 check_tcl_chon(dcc[idx].nick, dcc[idx].sock);
1269 if (dcc[idx].u.chat->channel >= 0)
1270 check_tcl_chjn(botnetnick, dcc[idx].nick, dcc[idx].u.chat->channel,
1271 geticon(idx), dcc[idx].sock, dcc[idx].host);
1272 killsock(dcc[j].sock);
1273 lostdcc(j);
1274 }
1275
1276 static void display_relay(int i, char *other)
1277 {
1278 sprintf(other, "rela -> sock %d", dcc[i].u.relay->sock);
1279 }
1280
1281 static void display_relaying(int i, char *other)
1282 {
1283 sprintf(other, ">rly -> sock %d", dcc[i].u.relay->sock);
1284 }
1285
1286 static void display_tandem_relay(int i, char *other)
1287 {
1288 strcpy(other, "other rela");
1289 }
1290
1291 static void display_pre_relay(int i, char *other)
1292 {
1293 strcpy(other, "other >rly");
1294 }
1295
1296 static int expmem_relay(void *x)
1297 {
1298 register struct relay_info *p = (struct relay_info *) x;
1299 int tot = sizeof(struct relay_info);
1300
1301 if (p->chat)
1302 tot += DCC_CHAT.expmem(p->chat);
1303 return tot;
1304 }
1305
1306 static void kill_relay(int idx, void *x)
1307 {
1308 register struct relay_info *p = (struct relay_info *) x;
1309
1310 if (p->chat)
1311 DCC_CHAT.kill(idx, p->chat);
1312 nfree(p);
1313 }
1314
1315 struct dcc_table DCC_RELAY =
1316 {
1317 "RELAY",
1318 0, /* flags */
1319 eof_dcc_relay,
1320 dcc_relay,
1321 0,
1322 0,
1323 display_relay,
1324 expmem_relay,
1325 kill_relay,
1326 0
1327 };
1328
1329 static void out_relay(int idx, char *buf, void *x)
1330 {
1331 register struct relay_info *p = (struct relay_info *) x;
1332
1333 if (p && p->chat)
1334 DCC_CHAT.output(idx, buf, p->chat);
1335 else
1336 tputs(dcc[idx].sock, buf, strlen(buf));
1337 }
1338
1339 struct dcc_table DCC_RELAYING =
1340 {
1341 "RELAYING",
1342 0, /* flags */
1343 eof_dcc_relaying,
1344 dcc_relaying,
1345 0,
1346 0,
1347 display_relaying,
1348 expmem_relay,
1349 kill_relay,
1350 out_relay
1351 };
1352
1353 struct dcc_table DCC_FORK_RELAY =
1354 {
1355 "FORK_RELAY",
1356 0, /* flags */
1357 failed_tandem_relay,
1358 cont_tandem_relay,
1359 &connect_timeout,
1360 failed_tandem_relay,
1361 display_tandem_relay,
1362 expmem_relay,
1363 kill_relay,
1364 0
1365 };
1366
1367 struct dcc_table DCC_PRE_RELAY =
1368 {
1369 "PRE_RELAY",
1370 0, /* flags */
1371 failed_pre_relay,
1372 pre_relay,
1373 0,
1374 0,
1375 display_pre_relay,
1376 expmem_relay,
1377 kill_relay,
1378 0
1379 };
1380
1381 /* once a minute, send 'ping' to each bot -- no exceptions */
1382 void check_botnet_pings()
1383 {
1384 int i;
1385
1386 context;
1387 for (i = 0; i < dcc_total; i++)
1388 if (dcc[i].type == &DCC_BOT)
1389 if (dcc[i].status & STAT_PINGED) {
1390 char s[1024];
1391
1392 putlog(LOG_BOTS, "*", "%s: %s", BOT_PINGTIMEOUT, dcc[i].nick);
1393 simple_sprintf(s, "%s: %s", BOT_PINGTIMEOUT, dcc[i].nick);
1394 chatout("*** %s\n", s);
1395 botnet_send_unlinked(i, dcc[i].nick, s);
1396 killsock(dcc[i].sock);
1397 lostdcc(i);
1398 }
1399 context;
1400 for (i = 0; i < dcc_total; i++)
1401 if (dcc[i].type == &DCC_BOT) {
1402 botnet_send_ping(i);
1403 dcc[i].status |= STAT_PINGED;
1404 }
1405 context;
1406 for (i = 0; i < dcc_total; i++)
1407 if ((dcc[i].type == &DCC_BOT) && (dcc[i].status & STAT_LEAF)) {
1408 tand_t *bot, *via = findbot(dcc[i].nick);
1409
1410 for (bot = tandbot; bot; bot = bot->next) {
1411 if ((via == bot->via) && (bot != via)) {
1412 /* not leaflike behavior */
1413 if (dcc[i].status & STAT_WARNED) {
1414 char s[1024];
1415
1416 putlog(LOG_BOTS, "*", "%s %s (%s).", BOT_DISCONNECTED,
1417 dcc[i].nick, BOT_BOTNOTLEAFLIKE);
1418 dprintf(i, "bye\n");
1419 simple_sprintf(s, "%s %s (%s)", BOT_DISCONNECTED, dcc[i].nick,
1420 BOT_BOTNOTLEAFLIKE);
1421 chatout("*** %s\n", s);
1422 botnet_send_unlinked(i, dcc[i].nick, s);
1423 killsock(dcc[i].sock);
1424 lostdcc(i);
1425 } else {
1426 botnet_send_reject(i, botnetnick, NULL, bot->bot,
1427 NULL, NULL);
1428 dcc[i].status |= STAT_WARNED;
1429 }
1430 } else
1431 dcc[i].status &= ~STAT_WARNED;
1432 }
1433 }
1434 context;
1435 }
1436
1437 void zapfbot(int idx)
1438 {
1439 char s[1024];
1440
1441 simple_sprintf(s, "%s: %s", BOT_BOTDROPPED, dcc[idx].nick);
1442 chatout("*** %s\n", s);
1443 botnet_send_unlinked(idx, dcc[idx].nick, s);
1444 killsock(dcc[idx].sock);
1445 dcc[idx].sock = (long) dcc[idx].type;
1446 dcc[idx].type = &DCC_LOST;
1447 }
1448
1449 void restart_chons()
1450 {
1451 int i;
1452
1453 /* dump party line members */
1454 context;
1455 for (i = 0; i < dcc_total; i++) {
1456 if (dcc[i].type == &DCC_CHAT) {
1457 check_tcl_chon(dcc[i].nick, dcc[i].sock);
1458 check_tcl_chjn(botnetnick, dcc[i].nick, dcc[i].u.chat->channel,
1459 geticon(i), dcc[i].sock, dcc[i].host);
1460 }
1461 }
1462 for (i = 0; i < parties; i++) {
1463 check_tcl_chjn(party[i].bot, party[i].nick, party[i].chan,
1464 party[i].flag, party[i].sock, party[i].from);
1465 }
1466 context;
1467 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23