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", |
1098 |
BOT_LOSTDCCUSER, dcc[idx].nick, |
1099 |
dcc[idx].host, dcc[idx].port); |
1100 |
putlog(LOG_MISC, "*", "(%s %s)", |
1101 |
BOT_DROPPINGRELAY, dcc[tidx].nick); |
1102 |
if ((dcc[tidx].sock != STDOUT) || backgrd) { |
1103 |
if (idx > tidx) { |
1104 |
int t = tidx; |
1105 |
|
1106 |
tidx = idx; |
1107 |
idx = t; |
1108 |
} |
1109 |
killsock(dcc[tidx].sock); |
1110 |
lostdcc(tidx); |
1111 |
} else { |
1112 |
fatal("Lost my terminal??!?!?!", 0); |
1113 |
} |
1114 |
killsock(dcc[idx].sock); |
1115 |
lostdcc(idx); |
1116 |
} |
1117 |
|
1118 |
static void cont_tandem_relay(int idx, char *buf, int i) |
1119 |
{ |
1120 |
int uidx = (-1); |
1121 |
struct relay_info *ri; |
1122 |
|
1123 |
context; |
1124 |
for (i = 0; i < dcc_total; i++) |
1125 |
if ((dcc[i].type == &DCC_PRE_RELAY) && |
1126 |
(dcc[i].u.relay->sock == dcc[idx].sock)) |
1127 |
uidx = i; |
1128 |
if (uidx < 0) { |
1129 |
putlog(LOG_MISC, "*", "%s %d -> %d", BOT_CANTFINDRELAYUSER, |
1130 |
dcc[i].sock, dcc[i].u.relay->sock); |
1131 |
killsock(dcc[i].sock); |
1132 |
lostdcc(i); |
1133 |
return; |
1134 |
} |
1135 |
dcc[idx].type = &DCC_RELAY; |
1136 |
dcc[idx].u.relay->sock = dcc[uidx].sock; |
1137 |
dcc[uidx].u.relay->sock = dcc[idx].sock; |
1138 |
dprintf(uidx, "%s %s ...\n", BOT_RELAYSUCCESS, dcc[idx].nick); |
1139 |
dprintf(uidx, "%s\n\n", BOT_BYEINFO2); |
1140 |
putlog(LOG_MISC, "*", "%s %s -> %s", BOT_RELAYLINK, |
1141 |
dcc[uidx].nick, dcc[idx].nick); |
1142 |
ri = dcc[uidx].u.relay; /* YEAH */ |
1143 |
dcc[uidx].type = &DCC_CHAT; |
1144 |
dcc[uidx].u.chat = ri->chat; |
1145 |
if (dcc[uidx].u.chat->channel >= 0) { |
1146 |
chanout_but(-1, dcc[uidx].u.chat->channel, "*** %s %s\n", |
1147 |
dcc[uidx].nick, BOT_PARTYLEFT); |
1148 |
if (dcc[uidx].u.chat->channel < 100000) |
1149 |
botnet_send_part_idx(uidx, NULL); |
1150 |
check_tcl_chpt(botnetnick, dcc[uidx].nick, dcc[uidx].sock, |
1151 |
dcc[uidx].u.chat->channel); |
1152 |
} |
1153 |
check_tcl_chof(dcc[uidx].nick, dcc[uidx].sock); |
1154 |
dcc[uidx].type = &DCC_RELAYING; |
1155 |
dcc[uidx].u.relay = ri; |
1156 |
} |
1157 |
|
1158 |
static void eof_dcc_relay(int idx) |
1159 |
{ |
1160 |
int j; |
1161 |
struct chat_info *ci; |
1162 |
|
1163 |
for (j = 0; dcc[j].sock != dcc[idx].u.relay->sock; j++); |
1164 |
/* in case echo was off, turn it back on: */ |
1165 |
if (dcc[j].status & STAT_TELNET) |
1166 |
dprintf(j, "\377\374\001\r\n"); |
1167 |
putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_ENDRELAY1, dcc[j].nick, |
1168 |
dcc[idx].nick); |
1169 |
dprintf(j, "\n\n*** %s %s\n", BOT_ENDRELAY2, botnetnick); |
1170 |
ci = dcc[j].u.relay->chat; |
1171 |
nfree(dcc[j].u.relay); |
1172 |
dcc[j].u.chat = ci; |
1173 |
dcc[j].type = &DCC_CHAT; |
1174 |
if (dcc[j].u.chat->channel >= 0) { |
1175 |
chanout_but(-1, dcc[j].u.chat->channel, "*** %s %s.\n", |
1176 |
dcc[j].nick, BOT_PARTYREJOINED); |
1177 |
context; |
1178 |
if (dcc[j].u.chat->channel < 100000) |
1179 |
botnet_send_join_idx(j, -1); |
1180 |
} |
1181 |
dcc[j].status = dcc[j].u.relay->old_status; |
1182 |
check_tcl_chon(dcc[j].nick, dcc[j].sock); |
1183 |
check_tcl_chjn(botnetnick, dcc[j].nick, dcc[j].u.chat->channel, |
1184 |
geticon(j), dcc[j].sock, dcc[j].host); |
1185 |
killsock(dcc[idx].sock); |
1186 |
lostdcc(idx); |
1187 |
} |
1188 |
|
1189 |
static void eof_dcc_relaying(int idx) |
1190 |
{ |
1191 |
int j, x = dcc[idx].u.relay->sock; |
1192 |
|
1193 |
putlog(LOG_MISC, "*", "%s [%s]%s/%d", BOT_LOSTDCCUSER, dcc[idx].nick, |
1194 |
dcc[idx].host, dcc[idx].port); |
1195 |
killsock(dcc[idx].sock); |
1196 |
lostdcc(idx); |
1197 |
for (j = 0; (dcc[j].sock != x) || (dcc[j].type == &DCC_FORK_RELAY) || |
1198 |
(dcc[j].type == &DCC_LOST); j++); |
1199 |
putlog(LOG_MISC, "*", "(%s %s)", BOT_DROPPEDRELAY, dcc[j].nick); |
1200 |
killsock(dcc[j].sock); |
1201 |
lostdcc(j); /* drop connection to the bot */ |
1202 |
} |
1203 |
|
1204 |
static void dcc_relay(int idx, char *buf, int j) |
1205 |
{ |
1206 |
unsigned char *p = (unsigned char *) buf; |
1207 |
int mark; |
1208 |
|
1209 |
for (j = 0; (dcc[j].sock != dcc[idx].u.relay->sock) || |
1210 |
(dcc[j].type != &DCC_RELAYING); j++); |
1211 |
/* if redirecting to a non-telnet user, swallow telnet codes */ |
1212 |
if (!(dcc[j].status & STAT_TELNET)) { |
1213 |
while (*p != 0) { |
1214 |
while ((*p != 255) && (*p != 0)) |
1215 |
p++; /* search for IAC */ |
1216 |
if (*p == 255) { |
1217 |
mark = 2; |
1218 |
if (!*(p + 1)) |
1219 |
mark = 1; /* bogus */ |
1220 |
if ((*(p + 1) >= 251) || (*(p + 1) <= 254)) { |
1221 |
mark = 3; |
1222 |
if (!*(p + 2)) |
1223 |
mark = 2; /* bogus */ |
1224 |
} |
1225 |
strcpy((char *) p, (char *) (p + mark)); |
1226 |
} |
1227 |
} |
1228 |
if (!buf[0]) |
1229 |
dprintf(-dcc[idx].u.relay->sock, " \n"); |
1230 |
else |
1231 |
dprintf(-dcc[idx].u.relay->sock, "%s\n", buf); |
1232 |
return; |
1233 |
} |
1234 |
/* telnet user */ |
1235 |
if (!buf[0]) |
1236 |
dprintf(-dcc[idx].u.relay->sock, " \r\n"); |
1237 |
else |
1238 |
dprintf(-dcc[idx].u.relay->sock, "%s\r\n", buf); |
1239 |
} |
1240 |
|
1241 |
static void dcc_relaying(int idx, char *buf, int j) |
1242 |
{ |
1243 |
struct chat_info *ci; |
1244 |
|
1245 |
if (strcasecmp(buf, "*bye*")) { |
1246 |
dprintf(-dcc[idx].u.relay->sock, "%s\n", buf); |
1247 |
return; |
1248 |
} |
1249 |
for (j = 0; (dcc[j].sock != dcc[idx].u.relay->sock) || |
1250 |
(dcc[j].type != &DCC_RELAY); j++); |
1251 |
/* in case echo was off, turn it back on: */ |
1252 |
if (dcc[idx].status & STAT_TELNET) |
1253 |
dprintf(idx, "\377\374\001\r\n"); |
1254 |
dprintf(idx, "\n(%s %s.)\n", BOT_BREAKRELAY, dcc[j].nick); |
1255 |
dprintf(idx, "%s %s.\n\n", BOT_ABORTRELAY2, botnetnick); |
1256 |
putlog(LOG_MISC, "*", "%s: %s -> %s", BOT_RELAYBROKEN, |
1257 |
dcc[idx].nick, dcc[j].nick); |
1258 |
if (dcc[idx].u.relay->chat->channel >= 0) { |
1259 |
chanout_but(-1, dcc[idx].u.relay->chat->channel, |
1260 |
"*** %s joined the party line.\n", dcc[idx].nick); |
1261 |
context; |
1262 |
if (dcc[idx].u.relay->chat->channel < 100000) |
1263 |
botnet_send_join_idx(idx, -1); |
1264 |
} |
1265 |
ci = dcc[idx].u.relay->chat; |
1266 |
nfree(dcc[idx].u.relay); |
1267 |
dcc[idx].u.chat = ci; |
1268 |
dcc[idx].type = &DCC_CHAT; |
1269 |
dcc[idx].status = dcc[idx].u.relay->old_status; |
1270 |
check_tcl_chon(dcc[idx].nick, dcc[idx].sock); |
1271 |
if (dcc[idx].u.chat->channel >= 0) |
1272 |
check_tcl_chjn(botnetnick, dcc[idx].nick, dcc[idx].u.chat->channel, |
1273 |
geticon(idx), dcc[idx].sock, dcc[idx].host); |
1274 |
killsock(dcc[j].sock); |
1275 |
lostdcc(j); |
1276 |
} |
1277 |
|
1278 |
static void display_relay(int i, char *other) |
1279 |
{ |
1280 |
sprintf(other, "rela -> sock %d", dcc[i].u.relay->sock); |
1281 |
} |
1282 |
|
1283 |
static void display_relaying(int i, char *other) |
1284 |
{ |
1285 |
sprintf(other, ">rly -> sock %d", dcc[i].u.relay->sock); |
1286 |
} |
1287 |
|
1288 |
static void display_tandem_relay(int i, char *other) |
1289 |
{ |
1290 |
strcpy(other, "other rela"); |
1291 |
} |
1292 |
|
1293 |
static void display_pre_relay(int i, char *other) |
1294 |
{ |
1295 |
strcpy(other, "other >rly"); |
1296 |
} |
1297 |
|
1298 |
static int expmem_relay(void *x) |
1299 |
{ |
1300 |
register struct relay_info *p = (struct relay_info *) x; |
1301 |
int tot = sizeof(struct relay_info); |
1302 |
|
1303 |
if (p->chat) |
1304 |
tot += DCC_CHAT.expmem(p->chat); |
1305 |
return tot; |
1306 |
} |
1307 |
|
1308 |
static void kill_relay(int idx, void *x) |
1309 |
{ |
1310 |
register struct relay_info *p = (struct relay_info *) x; |
1311 |
|
1312 |
if (p->chat) |
1313 |
DCC_CHAT.kill(idx, p->chat); |
1314 |
nfree(p); |
1315 |
} |
1316 |
|
1317 |
struct dcc_table DCC_RELAY = |
1318 |
{ |
1319 |
"RELAY", |
1320 |
0, /* flags */ |
1321 |
eof_dcc_relay, |
1322 |
dcc_relay, |
1323 |
0, |
1324 |
0, |
1325 |
display_relay, |
1326 |
expmem_relay, |
1327 |
kill_relay, |
1328 |
0 |
1329 |
}; |
1330 |
|
1331 |
static void out_relay(int idx, char *buf, void *x) |
1332 |
{ |
1333 |
register struct relay_info *p = (struct relay_info *) x; |
1334 |
|
1335 |
if (p && p->chat) |
1336 |
DCC_CHAT.output(idx, buf, p->chat); |
1337 |
else |
1338 |
tputs(dcc[idx].sock, buf, strlen(buf)); |
1339 |
} |
1340 |
|
1341 |
struct dcc_table DCC_RELAYING = |
1342 |
{ |
1343 |
"RELAYING", |
1344 |
0, /* flags */ |
1345 |
eof_dcc_relaying, |
1346 |
dcc_relaying, |
1347 |
0, |
1348 |
0, |
1349 |
display_relaying, |
1350 |
expmem_relay, |
1351 |
kill_relay, |
1352 |
out_relay |
1353 |
}; |
1354 |
|
1355 |
struct dcc_table DCC_FORK_RELAY = |
1356 |
{ |
1357 |
"FORK_RELAY", |
1358 |
0, /* flags */ |
1359 |
failed_tandem_relay, |
1360 |
cont_tandem_relay, |
1361 |
&connect_timeout, |
1362 |
failed_tandem_relay, |
1363 |
display_tandem_relay, |
1364 |
expmem_relay, |
1365 |
kill_relay, |
1366 |
0 |
1367 |
}; |
1368 |
|
1369 |
struct dcc_table DCC_PRE_RELAY = |
1370 |
{ |
1371 |
"PRE_RELAY", |
1372 |
0, /* flags */ |
1373 |
failed_pre_relay, |
1374 |
pre_relay, |
1375 |
0, |
1376 |
0, |
1377 |
display_pre_relay, |
1378 |
expmem_relay, |
1379 |
kill_relay, |
1380 |
0 |
1381 |
}; |
1382 |
|
1383 |
/* once a minute, send 'ping' to each bot -- no exceptions */ |
1384 |
void check_botnet_pings() |
1385 |
{ |
1386 |
int i; |
1387 |
|
1388 |
context; |
1389 |
for (i = 0; i < dcc_total; i++) |
1390 |
if (dcc[i].type == &DCC_BOT) |
1391 |
if (dcc[i].status & STAT_PINGED) { |
1392 |
char s[1024]; |
1393 |
|
1394 |
putlog(LOG_BOTS, "*", "%s: %s", BOT_PINGTIMEOUT, dcc[i].nick); |
1395 |
simple_sprintf(s, "%s: %s", BOT_PINGTIMEOUT, dcc[i].nick); |
1396 |
chatout("*** %s\n", s); |
1397 |
botnet_send_unlinked(i, dcc[i].nick, s); |
1398 |
killsock(dcc[i].sock); |
1399 |
lostdcc(i); |
1400 |
} |
1401 |
context; |
1402 |
for (i = 0; i < dcc_total; i++) |
1403 |
if (dcc[i].type == &DCC_BOT) { |
1404 |
botnet_send_ping(i); |
1405 |
dcc[i].status |= STAT_PINGED; |
1406 |
} |
1407 |
context; |
1408 |
for (i = 0; i < dcc_total; i++) |
1409 |
if ((dcc[i].type == &DCC_BOT) && (dcc[i].status & STAT_LEAF)) { |
1410 |
tand_t *bot, *via = findbot(dcc[i].nick); |
1411 |
|
1412 |
for (bot = tandbot; bot; bot = bot->next) { |
1413 |
if ((via == bot->via) && (bot != via)) { |
1414 |
/* not leaflike behavior */ |
1415 |
if (dcc[i].status & STAT_WARNED) { |
1416 |
char s[1024]; |
1417 |
|
1418 |
putlog(LOG_BOTS, "*", "%s %s (%s).", BOT_DISCONNECTED, |
1419 |
dcc[i].nick, BOT_BOTNOTLEAFLIKE); |
1420 |
dprintf(i, "bye\n"); |
1421 |
simple_sprintf(s, "%s %s (%s)", BOT_DISCONNECTED, dcc[i].nick, |
1422 |
BOT_BOTNOTLEAFLIKE); |
1423 |
chatout("*** %s\n", s); |
1424 |
botnet_send_unlinked(i, dcc[i].nick, s); |
1425 |
killsock(dcc[i].sock); |
1426 |
lostdcc(i); |
1427 |
} else { |
1428 |
botnet_send_reject(i, botnetnick, NULL, bot->bot, |
1429 |
NULL, NULL); |
1430 |
dcc[i].status |= STAT_WARNED; |
1431 |
} |
1432 |
} else |
1433 |
dcc[i].status &= ~STAT_WARNED; |
1434 |
} |
1435 |
} |
1436 |
context; |
1437 |
} |
1438 |
|
1439 |
void zapfbot(int idx) |
1440 |
{ |
1441 |
char s[1024]; |
1442 |
|
1443 |
simple_sprintf(s, "%s: %s", BOT_BOTDROPPED, dcc[idx].nick); |
1444 |
chatout("*** %s\n", s); |
1445 |
botnet_send_unlinked(idx, dcc[idx].nick, s); |
1446 |
killsock(dcc[idx].sock); |
1447 |
dcc[idx].sock = (long) dcc[idx].type; |
1448 |
dcc[idx].type = &DCC_LOST; |
1449 |
} |
1450 |
|
1451 |
void restart_chons() |
1452 |
{ |
1453 |
int i; |
1454 |
|
1455 |
/* dump party line members */ |
1456 |
context; |
1457 |
for (i = 0; i < dcc_total; i++) { |
1458 |
if (dcc[i].type == &DCC_CHAT) { |
1459 |
check_tcl_chon(dcc[i].nick, dcc[i].sock); |
1460 |
check_tcl_chjn(botnetnick, dcc[i].nick, dcc[i].u.chat->channel, |
1461 |
geticon(i), dcc[i].sock, dcc[i].host); |
1462 |
} |
1463 |
} |
1464 |
for (i = 0; i < parties; i++) { |
1465 |
check_tcl_chjn(party[i].bot, party[i].nick, party[i].chan, |
1466 |
party[i].flag, party[i].sock, party[i].from); |
1467 |
} |
1468 |
context; |
1469 |
} |