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

Annotation of /eggdrop1.9/src/botnet.c

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


Revision 1.34 - (hide annotations) (download) (as text)
Fri Jun 1 22:03:15 2001 UTC (18 years, 5 months ago) by guppy
Branch: MAIN
Changes since 1.33: +3 -3 lines
File MIME type: text/x-chdr
here is sup's patch to fix .relay and .chaddr

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23