00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <sys/stat.h>
00031 #include "main.h"
00032 #include <errno.h>
00033 #include "chan.h"
00034 #include "modules.h"
00035 #include "tandem.h"
00036
00037 extern struct dcc_t *dcc;
00038 extern int dcc_total, dcc_flood_thr, backgrd, copy_to_tmp, max_socks;
00039 extern char botnetnick[], version[];
00040 extern time_t now;
00041 extern sock_list *socklist;
00042
00043 char motdfile[121] = "text/motd";
00044 int connect_timeout = 15;
00045
00046
00047 int reserved_port_min = 0;
00048 int reserved_port_max = 0;
00049
00050 int max_dcc = 0;
00051
00052
00053
00054
00055
00056
00057
00058
00059 int increase_socks_max()
00060 {
00061 struct threaddata *td = threaddata();
00062 int osock = td->MAXSOCKS;
00063
00064 if (max_socks < 1)
00065 max_socks = 1;
00066
00067 if (td->MAXSOCKS == max_socks) {
00068 putlog(LOG_MISC, "*", "Maximum socket limit reached. Consider raising max-socks.");
00069 return -1;
00070 }
00071
00072 td->MAXSOCKS += 10;
00073 if (td->MAXSOCKS > max_socks)
00074 td->MAXSOCKS = max_socks;
00075
00076 if (td->socklist)
00077 td->socklist = nrealloc(td->socklist, sizeof(sock_list) * td->MAXSOCKS);
00078 else
00079 td->socklist = nmalloc(sizeof(sock_list) * td->MAXSOCKS);
00080 for (; osock < td->MAXSOCKS; osock++)
00081 td->socklist[osock].flags = SOCK_UNUSED;
00082
00083 if (td->mainthread) {
00084 max_dcc = td->MAXSOCKS - 10;
00085 if (max_dcc < 1)
00086 max_dcc = 1;
00087 if (dcc)
00088 dcc = nrealloc(dcc, sizeof(struct dcc_t) * max_dcc);
00089 else
00090 dcc = nmalloc(sizeof(struct dcc_t) * max_dcc);
00091 socklist = td->socklist;
00092 }
00093
00094 return 0;
00095 }
00096
00097 int expmem_dccutil()
00098 {
00099 int tot, i;
00100
00101 tot = sizeof(struct dcc_t) * max_dcc;
00102 tot += sizeof(sock_list) * threaddata()->MAXSOCKS;
00103
00104 for (i = 0; i < dcc_total; i++) {
00105 if (dcc[i].type && dcc[i].type->expmem)
00106 tot += dcc[i].type->expmem(dcc[i].u.other);
00107 }
00108 return tot;
00109 }
00110
00111 int findidx(int z)
00112 {
00113 int j;
00114
00115 for (j = 0; j < dcc_total; j++)
00116 if ((dcc[j].sock == z) && (dcc[j].type->flags & DCT_VALIDIDX))
00117 return j;
00118 return -1;
00119 }
00120
00121 int findanyidx(register int z)
00122 {
00123 register int j;
00124
00125 for (j = 0; j < dcc_total; j++)
00126 if (dcc[j].sock == z)
00127 return j;
00128 return -1;
00129 }
00130
00131
00132 char *add_cr(char *buf)
00133 {
00134 static char WBUF[1024];
00135 char *p, *q;
00136
00137 for (p = buf, q = WBUF; *p; p++, q++) {
00138 if (*p == '\n')
00139 *q++ = '\r';
00140 *q = *p;
00141 }
00142 *q = *p;
00143 return WBUF;
00144 }
00145
00146 extern void (*qserver) (int, char *, int);
00147
00148 void dprintf EGG_VARARGS_DEF(int, arg1)
00149 {
00150 static char buf[1024];
00151 char *format;
00152 int idx, len;
00153 va_list va;
00154
00155 idx = EGG_VARARGS_START(int, arg1, va);
00156 format = va_arg(va, char *);
00157
00158 egg_vsnprintf(buf, 1023, format, va);
00159 va_end(va);
00160
00161
00162
00163
00164
00165
00166
00167
00168 buf[sizeof(buf) - 1] = 0;
00169 len = strlen(buf);
00170
00171 if (idx < 0) {
00172 tputs(-idx, buf, len);
00173 } else if (idx > 0x7FF0) {
00174 switch (idx) {
00175 case DP_LOG:
00176 putlog(LOG_MISC, "*", "%s", buf);
00177 break;
00178 case DP_STDOUT:
00179 tputs(STDOUT, buf, len);
00180 break;
00181 case DP_STDERR:
00182 tputs(STDERR, buf, len);
00183 break;
00184 case DP_SERVER:
00185 case DP_HELP:
00186 case DP_MODE:
00187 case DP_MODE_NEXT:
00188 case DP_SERVER_NEXT:
00189 case DP_HELP_NEXT:
00190 qserver(idx, buf, len);
00191 break;
00192 }
00193 return;
00194 } else {
00195 if (len > 500) {
00196 buf[500] = 0;
00197 strcat(buf, "\n");
00198 len = 501;
00199 }
00200 if (dcc[idx].type && ((long) (dcc[idx].type->output) == 1)) {
00201 char *p = add_cr(buf);
00202
00203 tputs(dcc[idx].sock, p, strlen(p));
00204 } else if (dcc[idx].type && dcc[idx].type->output)
00205 dcc[idx].type->output(idx, buf, dcc[idx].u.other);
00206 else
00207 tputs(dcc[idx].sock, buf, len);
00208 }
00209 }
00210
00211 void chatout EGG_VARARGS_DEF(char *, arg1)
00212 {
00213 int i, len;
00214 char *format;
00215 char s[601];
00216 va_list va;
00217
00218 format = EGG_VARARGS_START(char *, arg1, va);
00219
00220 egg_vsnprintf(s, 511, format, va);
00221 va_end(va);
00222 len = strlen(s);
00223 if (len > 511)
00224 len = 511;
00225 s[len + 1] = 0;
00226
00227 for (i = 0; i < dcc_total; i++)
00228 if (dcc[i].type == &DCC_CHAT)
00229 if (dcc[i].u.chat->channel >= 0)
00230 dprintf(i, "%s", s);
00231
00232 }
00233
00234
00235
00236 void chanout_but EGG_VARARGS_DEF(int, arg1)
00237 {
00238 int i, x, chan, len;
00239 char *format;
00240 char s[601];
00241 va_list va;
00242
00243 x = EGG_VARARGS_START(int, arg1, va);
00244 chan = va_arg(va, int);
00245 format = va_arg(va, char *);
00246
00247 egg_vsnprintf(s, 511, format, va);
00248 va_end(va);
00249 len = strlen(s);
00250 if (len > 511)
00251 len = 511;
00252 s[len + 1] = 0;
00253
00254 for (i = 0; i < dcc_total; i++)
00255 if ((dcc[i].type == &DCC_CHAT) && (i != x))
00256 if (dcc[i].u.chat->channel == chan)
00257 dprintf(i, "%s", s);
00258
00259 }
00260
00261 void dcc_chatter(int idx)
00262 {
00263 int i, j;
00264 struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
00265
00266 get_user_flagrec(dcc[idx].user, &fr, NULL);
00267 show_motd(idx);
00268 i = dcc[idx].u.chat->channel;
00269 dcc[idx].u.chat->channel = 234567;
00270 j = dcc[idx].sock;
00271 strcpy(dcc[idx].u.chat->con_chan, "***");
00272 check_tcl_chon(dcc[idx].nick, dcc[idx].sock);
00273
00274 if ((idx >= dcc_total) || (dcc[idx].sock != j))
00275 return;
00276
00277 if (dcc[idx].type == &DCC_CHAT) {
00278 if (!strcmp(dcc[idx].u.chat->con_chan, "***"))
00279 strcpy(dcc[idx].u.chat->con_chan, "*");
00280 if (dcc[idx].u.chat->channel == 234567) {
00281
00282
00283
00284
00285 if (i == -2)
00286 i = 0;
00287 dcc[idx].u.chat->channel = i;
00288 if ((dcc[idx].u.chat->channel >= 0) &&
00289 (dcc[idx].u.chat->channel < GLOBAL_CHANS))
00290 botnet_send_join_idx(idx, -1);
00291 check_tcl_chjn(botnetnick, dcc[idx].nick, dcc[idx].u.chat->channel,
00292 geticon(idx), dcc[idx].sock, dcc[idx].host);
00293 }
00294
00295 if (!dcc[idx].u.chat->channel) {
00296 chanout_but(-1, 0, "*** %s joined the party line.\n", dcc[idx].nick);
00297 } else if (dcc[idx].u.chat->channel > 0) {
00298 chanout_but(-1, dcc[idx].u.chat->channel,
00299 "*** %s joined the channel.\n", dcc[idx].nick);
00300 }
00301 }
00302 }
00303
00304
00305 void killtransfer(int n)
00306 {
00307 int i, ok = 1;
00308
00309 if (dcc[n].type->flags & DCT_FILETRAN) {
00310 if (dcc[n].u.xfer->f) {
00311 fclose(dcc[n].u.xfer->f);
00312 dcc[n].u.xfer->f = NULL;
00313 }
00314 if (dcc[n].u.xfer->filename && copy_to_tmp) {
00315 for (i = 0; i < dcc_total; i++) {
00316 if ((i != n) && (dcc[i].type->flags & DCT_FILETRAN) &&
00317 (dcc[i].u.xfer->filename) &&
00318 (!strcmp(dcc[i].u.xfer->filename, dcc[n].u.xfer->filename))) {
00319 ok = 0;
00320 break;
00321 }
00322 }
00323 if (ok)
00324 unlink(dcc[n].u.xfer->filename);
00325 }
00326 }
00327 }
00328
00329
00330
00331
00332 void lostdcc(int n)
00333 {
00334
00335 if (n < 0 || n >= max_dcc)
00336 return;
00337
00338 if (dcc[n].type && dcc[n].type->kill)
00339 dcc[n].type->kill(n, dcc[n].u.other);
00340 else if (dcc[n].u.other)
00341 nfree(dcc[n].u.other);
00342 egg_bzero(&dcc[n], sizeof(struct dcc_t));
00343
00344 dcc[n].sock = -1;
00345 dcc[n].type = &DCC_LOST;
00346 }
00347
00348
00349
00350
00351
00352
00353
00354
00355 void removedcc(int n)
00356 {
00357 if (dcc[n].type && dcc[n].type->kill)
00358 dcc[n].type->kill(n, dcc[n].u.other);
00359 else if (dcc[n].u.other)
00360 nfree(dcc[n].u.other);
00361 dcc_total--;
00362 if (n < dcc_total)
00363 egg_memcpy(&dcc[n], &dcc[dcc_total], sizeof(struct dcc_t));
00364 else
00365 egg_bzero(&dcc[n], sizeof(struct dcc_t));
00366 }
00367
00368
00369
00370 void dcc_remove_lost(void)
00371 {
00372 int i;
00373
00374 for (i = 0; i < dcc_total; i++) {
00375 if (dcc[i].type == &DCC_LOST) {
00376 dcc[i].type = NULL;
00377 dcc[i].sock = -1;
00378 removedcc(i);
00379 i--;
00380 }
00381 }
00382 }
00383
00384
00385
00386
00387 void tell_dcc(int zidx)
00388 {
00389 int i, j;
00390 char other[160];
00391 char format[81];
00392 int nicklen;
00393
00394
00395 nicklen = 0;
00396 for (i = 0; i < dcc_total; i++) {
00397 if (strlen(dcc[i].nick) > nicklen)
00398 nicklen = strlen(dcc[i].nick);
00399 }
00400 if (nicklen < 9)
00401 nicklen = 9;
00402
00403 egg_snprintf(format, sizeof format, "%%-4s %%-8s %%-5s %%-%us %%-17s %%s\n",
00404 nicklen);
00405 dprintf(zidx, format, "SOCK", "ADDR", "PORT", "NICK", "HOST", "TYPE");
00406 dprintf(zidx, format, "----", "--------", "-----", "---------",
00407 "-----------------", "----");
00408
00409 egg_snprintf(format, sizeof format, "%%-4d %%08X %%5d %%-%us %%-17s %%s\n",
00410 nicklen);
00411
00412 for (i = 0; i < dcc_total; i++) {
00413 j = strlen(dcc[i].host);
00414 if (j > 17)
00415 j -= 17;
00416 else
00417 j = 0;
00418 if (dcc[i].type && dcc[i].type->display)
00419 dcc[i].type->display(i, other);
00420 else {
00421 sprintf(other, "?:%lX !! ERROR !!", (long) dcc[i].type);
00422 break;
00423 }
00424 dprintf(zidx, format, dcc[i].sock, dcc[i].addr, dcc[i].port, dcc[i].nick,
00425 dcc[i].host + j, other);
00426 }
00427 }
00428
00429
00430
00431 void not_away(int idx)
00432 {
00433 if (dcc[idx].u.chat->away == NULL) {
00434 dprintf(idx, "You weren't away!\n");
00435 return;
00436 }
00437 if (dcc[idx].u.chat->channel >= 0) {
00438 chanout_but(-1, dcc[idx].u.chat->channel,
00439 "*** %s is no longer away.\n", dcc[idx].nick);
00440 if (dcc[idx].u.chat->channel < GLOBAL_CHANS) {
00441 botnet_send_away(-1, botnetnick, dcc[idx].sock, NULL, idx);
00442 }
00443 }
00444 dprintf(idx, "You're not away any more.\n");
00445 nfree(dcc[idx].u.chat->away);
00446 dcc[idx].u.chat->away = NULL;
00447 check_tcl_away(botnetnick, dcc[idx].sock, NULL);
00448 }
00449
00450 void set_away(int idx, char *s)
00451 {
00452 if (s == NULL) {
00453 not_away(idx);
00454 return;
00455 }
00456 if (!s[0]) {
00457 not_away(idx);
00458 return;
00459 }
00460 if (dcc[idx].u.chat->away != NULL)
00461 nfree(dcc[idx].u.chat->away);
00462 dcc[idx].u.chat->away = nmalloc(strlen(s) + 1);
00463 strcpy(dcc[idx].u.chat->away, s);
00464 if (dcc[idx].u.chat->channel >= 0) {
00465 chanout_but(-1, dcc[idx].u.chat->channel,
00466 "*** %s is now away: %s\n", dcc[idx].nick, s);
00467 if (dcc[idx].u.chat->channel < GLOBAL_CHANS) {
00468 botnet_send_away(-1, botnetnick, dcc[idx].sock, s, idx);
00469 }
00470 }
00471 dprintf(idx, "You are now away.\n");
00472 check_tcl_away(botnetnick, dcc[idx].sock, s);
00473 }
00474
00475
00476
00477 void *_get_data_ptr(int size, char *file, int line)
00478 {
00479 char *p;
00480 #ifdef DEBUG_MEM
00481 char x[1024];
00482
00483 p = strrchr(file, '/');
00484 egg_snprintf(x, sizeof x, "dccutil.c:%s", p ? p + 1 : file);
00485 p = n_malloc(size, x, line);
00486 #else
00487 p = nmalloc(size);
00488 #endif
00489 egg_bzero(p, size);
00490 return p;
00491 }
00492
00493
00494
00495 void makepass(char *s)
00496 {
00497 int i;
00498
00499 i = 10 + randint(6);
00500 make_rand_str(s, i);
00501 }
00502
00503 void flush_lines(int idx, struct chat_info *ci)
00504 {
00505 int c = ci->line_count;
00506 struct msgq *p = ci->buffer, *o;
00507
00508 while (p && c < (ci->max_line)) {
00509 ci->current_lines--;
00510 tputs(dcc[idx].sock, p->msg, p->len);
00511 nfree(p->msg);
00512 o = p->next;
00513 nfree(p);
00514 p = o;
00515 c++;
00516 }
00517 if (p != NULL) {
00518 if (dcc[idx].status & STAT_TELNET)
00519 tputs(dcc[idx].sock, "[More]: ", 8);
00520 else
00521 tputs(dcc[idx].sock, "[More]\n", 7);
00522 }
00523 ci->buffer = p;
00524 ci->line_count = 0;
00525 }
00526
00527 int new_dcc(struct dcc_table *type, int xtra_size)
00528 {
00529 int i = dcc_total;
00530
00531 if (dcc_total == max_dcc && increase_socks_max())
00532 return -1;
00533 dcc_total++;
00534 egg_bzero((char *) &dcc[i], sizeof(struct dcc_t));
00535
00536 dcc[i].type = type;
00537 if (xtra_size) {
00538 dcc[i].u.other = nmalloc(xtra_size);
00539 egg_bzero(dcc[i].u.other, xtra_size);
00540 }
00541 return i;
00542 }
00543
00544
00545
00546 void changeover_dcc(int i, struct dcc_table *type, int xtra_size)
00547 {
00548
00549 if (dcc[i].type && dcc[i].type->kill)
00550 dcc[i].type->kill(i, dcc[i].u.other);
00551 else if (dcc[i].u.other) {
00552 nfree(dcc[i].u.other);
00553 dcc[i].u.other = NULL;
00554 }
00555
00556 dcc[i].type = type;
00557 if (xtra_size) {
00558 dcc[i].u.other = nmalloc(xtra_size);
00559 egg_bzero(dcc[i].u.other, xtra_size);
00560 }
00561 }
00562
00563 int detect_dcc_flood(time_t *timer, struct chat_info *chat, int idx)
00564 {
00565 time_t t;
00566
00567 if (!dcc_flood_thr)
00568 return 0;
00569 t = now;
00570 if (*timer != t) {
00571 *timer = t;
00572 chat->msgs_per_sec = 0;
00573 } else {
00574 chat->msgs_per_sec++;
00575 if (chat->msgs_per_sec > dcc_flood_thr) {
00576
00577 dprintf(idx, "*** FLOOD: %s.\n", IRC_GOODBYE);
00578
00579 if ((dcc[idx].type->flags & DCT_CHAT) && chat && (chat->channel >= 0)) {
00580 char x[1024];
00581
00582 egg_snprintf(x, sizeof x, DCC_FLOODBOOT, dcc[idx].nick);
00583 chanout_but(idx, chat->channel, "*** %s", x);
00584 if (chat->channel < GLOBAL_CHANS)
00585 botnet_send_part_idx(idx, x);
00586 }
00587 check_tcl_chof(dcc[idx].nick, dcc[idx].sock);
00588 if ((dcc[idx].sock != STDOUT) || backgrd) {
00589 killsock(dcc[idx].sock);
00590 lostdcc(idx);
00591 } else {
00592 dprintf(DP_STDOUT, "\n### SIMULATION RESET ###\n\n");
00593 dcc_chatter(idx);
00594 }
00595 return 1;
00596 }
00597 }
00598 return 0;
00599 }
00600
00601
00602
00603 void do_boot(int idx, char *by, char *reason)
00604 {
00605 int files = (dcc[idx].type != &DCC_CHAT);
00606
00607 dprintf(idx, DCC_BOOTED1);
00608 dprintf(idx, DCC_BOOTED2, files ? "file section" : "bot",
00609 by, reason[0] ? ": " : ".", reason);
00610
00611
00612
00613 if ((dcc[idx].type->flags & DCT_CHAT) && (dcc[idx].u.chat->channel >= 0)) {
00614 char x[1024];
00615
00616 egg_snprintf(x, sizeof x, DCC_BOOTED3, by, dcc[idx].nick,
00617 reason[0] ? ": " : "", reason);
00618 chanout_but(idx, dcc[idx].u.chat->channel, "*** %s.\n", x);
00619 if (dcc[idx].u.chat->channel < GLOBAL_CHANS)
00620 botnet_send_part_idx(idx, x);
00621 }
00622 check_tcl_chof(dcc[idx].nick, dcc[idx].sock);
00623 if ((dcc[idx].sock != STDOUT) || backgrd) {
00624 killsock(dcc[idx].sock);
00625 lostdcc(idx);
00626
00627 } else {
00628 dprintf(DP_STDOUT, "\n### SIMULATION RESET\n\n");
00629 dcc_chatter(idx);
00630 }
00631 return;
00632 }