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 <fcntl.h>
00031 #include "main.h"
00032 #include <limits.h>
00033 #include <string.h>
00034 #include <netdb.h>
00035 #include <sys/socket.h>
00036 #if HAVE_SYS_SELECT_H
00037 # include <sys/select.h>
00038 #endif
00039 #include <netinet/in.h>
00040 #include <arpa/inet.h>
00041 #include <errno.h>
00042 #if HAVE_UNISTD_H
00043 # include <unistd.h>
00044 #endif
00045 #include <setjmp.h>
00046
00047 #ifndef HAVE_GETDTABLESIZE
00048 # ifdef FD_SETSIZE
00049 # define getdtablesize() FD_SETSIZE
00050 # else
00051 # define getdtablesize() 200
00052 # endif
00053 #endif
00054
00055 extern struct dcc_t *dcc;
00056 extern int backgrd, use_stderr, resolve_timeout, dcc_total;
00057 extern unsigned long otraffic_irc_today, otraffic_bn_today, otraffic_dcc_today,
00058 otraffic_filesys_today, otraffic_trans_today,
00059 otraffic_unknown_today;
00060
00061 char hostname[121] = "";
00062 char myip[121] = "";
00063 char firewall[121] = "";
00064 int firewallport = 1080;
00065 char botuser[21] = "eggdrop";
00066 int dcc_sanitycheck = 0;
00067
00068 sock_list *socklist = NULL;
00069 sigjmp_buf alarmret;
00070
00071
00072 #define PROXY_SOCKS 1
00073 #define PROXY_SUN 2
00074
00075
00076
00077
00078 IP my_atoul(char *s)
00079 {
00080 IP ret = 0;
00081
00082 while ((*s >= '0') && (*s <= '9')) {
00083 ret *= 10;
00084 ret += ((*s) - '0');
00085 s++;
00086 }
00087 return ret;
00088 }
00089
00090 int expmem_net()
00091 {
00092 int i, tot = 0;
00093 struct threaddata *td = threaddata();
00094
00095 for (i = 0; i < td->MAXSOCKS; i++) {
00096 if (!(td->socklist[i].flags & (SOCK_UNUSED | SOCK_TCL))) {
00097 if (td->socklist[i].handler.sock.inbuf != NULL)
00098 tot += strlen(td->socklist[i].handler.sock.inbuf) + 1;
00099 if (td->socklist[i].handler.sock.outbuf != NULL)
00100 tot += td->socklist[i].handler.sock.outbuflen;
00101 }
00102 }
00103 return tot;
00104 }
00105
00106
00107
00108 IP getmyip()
00109 {
00110 struct hostent *hp;
00111 char s[121];
00112 IP ip;
00113 struct in_addr *in;
00114 if (myip[0]) {
00115 if ((myip[strlen(myip) - 1] >= '0') && (myip[strlen(myip) - 1] <= '9'))
00116 return (IP) inet_addr(myip);
00117 }
00118
00119 if (hostname[0])
00120 hp = gethostbyname(hostname);
00121 else {
00122 gethostname(s, 120);
00123 hp = gethostbyname(s);
00124 }
00125 if (hp == NULL)
00126 fatal("Hostname self-lookup failed. Please set 'my-ip' in the config "
00127 "file.", 0);
00128 in = (struct in_addr *) (hp->h_addr_list[0]);
00129 ip = (IP) (in->s_addr);
00130 return ip;
00131 }
00132
00133 void neterror(char *s)
00134 {
00135 switch (errno) {
00136 case EADDRINUSE:
00137 strcpy(s, "Address already in use");
00138 break;
00139 case EADDRNOTAVAIL:
00140 strcpy(s, "Cannot assign requested address");
00141 break;
00142 case EAFNOSUPPORT:
00143 strcpy(s, "Address family not supported");
00144 break;
00145 case EALREADY:
00146 strcpy(s, "Socket already in use");
00147 break;
00148 case EBADF:
00149 strcpy(s, "Socket descriptor is bad");
00150 break;
00151 case ECONNREFUSED:
00152 strcpy(s, "Connection refused");
00153 break;
00154 case EFAULT:
00155 strcpy(s, "Bad address");
00156 break;
00157 case EINPROGRESS:
00158 strcpy(s, "Operation in progress");
00159 break;
00160 case EINTR:
00161 strcpy(s, "Timeout");
00162 break;
00163 case EINVAL:
00164 strcpy(s, "Invalid argument");
00165 break;
00166 case EISCONN:
00167 strcpy(s, "Socket already connected");
00168 break;
00169 case ENETUNREACH:
00170 strcpy(s, "Network unreachable");
00171 break;
00172 case ENOTSOCK:
00173 strcpy(s, "Socket operation on non-socket");
00174 break;
00175 case ETIMEDOUT:
00176 strcpy(s, "Connection timed out");
00177 break;
00178 case ENOTCONN:
00179 strcpy(s, "Socket is not connected");
00180 break;
00181 case EHOSTUNREACH:
00182 strcpy(s, "No route to host");
00183 break;
00184 case EPIPE:
00185 strcpy(s, "Broken pipe");
00186 break;
00187 #ifdef ECONNRESET
00188 case ECONNRESET:
00189 strcpy(s, "Connection reset by peer");
00190 break;
00191 #endif
00192 #ifdef EACCES
00193 case EACCES:
00194 strcpy(s, "Permission denied");
00195 break;
00196 #endif
00197 #ifdef EMFILE
00198 case EMFILE:
00199 strcpy(s, "Too many open files");
00200 break;
00201 #endif
00202 case 0:
00203 strcpy(s, "Error 0");
00204 break;
00205 default:
00206 sprintf(s, "Unforseen error %d", errno);
00207 break;
00208 }
00209 }
00210
00211
00212
00213
00214
00215
00216
00217 int sockoptions(int sock, int operation, int sock_options)
00218 {
00219 int i;
00220 struct threaddata *td = threaddata();
00221
00222 for (i = 0; i < td->MAXSOCKS; i++)
00223 if ((td->socklist[i].sock == sock) &&
00224 !(td->socklist[i].flags & SOCK_UNUSED)) {
00225 if (operation == EGG_OPTION_SET)
00226 td->socklist[i].flags |= sock_options;
00227 else if (operation == EGG_OPTION_UNSET)
00228 td->socklist[i].flags &= ~sock_options;
00229 else
00230 return -2;
00231 return 0;
00232 }
00233 return -1;
00234 }
00235
00236
00237
00238 int allocsock(int sock, int options)
00239 {
00240 int i;
00241 struct threaddata *td = threaddata();
00242
00243 for (i = 0; i < td->MAXSOCKS; i++) {
00244 if (td->socklist[i].flags & SOCK_UNUSED) {
00245
00246 td->socklist[i].handler.sock.inbuf = NULL;
00247 td->socklist[i].handler.sock.outbuf = NULL;
00248 td->socklist[i].handler.sock.inbuflen = 0;
00249 td->socklist[i].handler.sock.outbuflen = 0;
00250 td->socklist[i].flags = options;
00251 td->socklist[i].sock = sock;
00252 return i;
00253 }
00254 }
00255
00256 if (increase_socks_max())
00257 return -1;
00258 else
00259 return allocsock(sock, options);
00260 }
00261
00262
00263
00264
00265
00266 int alloctclsock(register int sock, int mask, Tcl_FileProc *proc, ClientData cd)
00267 {
00268 int f = -1;
00269 register int i;
00270 struct threaddata *td = threaddata();
00271
00272 for (i = 0; i < td->MAXSOCKS; i++) {
00273 if (td->socklist[i].flags & SOCK_UNUSED) {
00274 if (f == -1)
00275 f = i;
00276 } else if ((td->socklist[i].flags & SOCK_TCL) &&
00277 td->socklist[i].sock == sock) {
00278 f = i;
00279 break;
00280 }
00281 }
00282 if (f != -1) {
00283 td->socklist[f].sock = sock;
00284 td->socklist[f].flags = SOCK_TCL;
00285 td->socklist[f].handler.tclsock.mask = mask;
00286 td->socklist[f].handler.tclsock.proc = proc;
00287 td->socklist[f].handler.tclsock.cd = cd;
00288 return f;
00289 }
00290
00291 if (increase_socks_max())
00292 return -1;
00293 else
00294 return alloctclsock(sock, mask, proc, cd);
00295 }
00296
00297
00298
00299 void setsock(int sock, int options)
00300 {
00301 int i = allocsock(sock, options), parm;
00302 struct threaddata *td = threaddata();
00303
00304 if (i == -1) {
00305 putlog(LOG_MISC, "*", "Sockettable full.");
00306 return;
00307 }
00308 if (((sock != STDOUT) || backgrd) && !(td->socklist[i].flags & SOCK_NONSOCK)) {
00309 parm = 1;
00310 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *) &parm, sizeof(int));
00311
00312 parm = 0;
00313 setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &parm, sizeof(int));
00314 }
00315 if (options & SOCK_LISTEN) {
00316
00317 parm = 1;
00318 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &parm, sizeof(int));
00319 }
00320
00321 fcntl(sock, F_SETFL, O_NONBLOCK);
00322 }
00323
00324 int getsock(int options)
00325 {
00326 int sock = socket(AF_INET, SOCK_STREAM, 0);
00327
00328 if (sock >= 0)
00329 setsock(sock, options);
00330 else
00331 putlog(LOG_MISC, "*", "Warning: Can't create new socket!");
00332 return sock;
00333 }
00334
00335
00336
00337 void killsock(register int sock)
00338 {
00339 register int i;
00340 struct threaddata *td = threaddata();
00341
00342
00343 if (sock < 0)
00344 return;
00345
00346 for (i = 0; i < td->MAXSOCKS; i++) {
00347 if ((td->socklist[i].sock == sock) && !(td->socklist[i].flags & SOCK_UNUSED)) {
00348 if (!(td->socklist[i].flags & SOCK_TCL)) {
00349 close(td->socklist[i].sock);
00350 if (td->socklist[i].handler.sock.inbuf != NULL) {
00351 nfree(td->socklist[i].handler.sock.inbuf);
00352 td->socklist[i].handler.sock.inbuf = NULL;
00353 }
00354 if (td->socklist[i].handler.sock.outbuf != NULL) {
00355 nfree(td->socklist[i].handler.sock.outbuf);
00356 td->socklist[i].handler.sock.outbuf = NULL;
00357 td->socklist[i].handler.sock.outbuflen = 0;
00358 }
00359 }
00360 td->socklist[i].flags = SOCK_UNUSED;
00361 return;
00362 }
00363 }
00364 putlog(LOG_MISC, "*", "Warning: Attempt to kill un-allocated socket %d!", sock);
00365 }
00366
00367
00368
00369
00370
00371 void killtclsock(register int sock)
00372 {
00373 register int i;
00374 struct threaddata *td = threaddata();
00375
00376 if (sock < 0)
00377 return;
00378
00379 for (i = 0; i < td->MAXSOCKS; i++) {
00380 if ((td->socklist[i].flags & SOCK_TCL) && td->socklist[i].sock == sock) {
00381 td->socklist[i].flags = SOCK_UNUSED;
00382 return;
00383 }
00384 }
00385 }
00386
00387
00388
00389 static int proxy_connect(int sock, char *host, int port, int proxy)
00390 {
00391 unsigned char x[10];
00392 struct hostent *hp;
00393 char s[256];
00394 int i;
00395
00396
00397 if (proxy == PROXY_SOCKS) {
00398
00399 if (host[strlen(host) - 1] >= '0' && host[strlen(host) - 1] <= '9') {
00400 IP ip = ((IP) inet_addr(host));
00401 egg_memcpy(x, &ip, 4);
00402 } else {
00403
00404 if (!sigsetjmp(alarmret, 1)) {
00405 alarm(resolve_timeout);
00406 hp = gethostbyname(host);
00407 alarm(0);
00408 } else
00409 hp = NULL;
00410 if (hp == NULL) {
00411 killsock(sock);
00412 return -2;
00413 }
00414 egg_memcpy(x, hp->h_addr, hp->h_length);
00415 }
00416 for (i = 0; i < threaddata()->MAXSOCKS; i++)
00417 if (!(socklist[i].flags & SOCK_UNUSED) && socklist[i].sock == sock)
00418 socklist[i].flags |= SOCK_PROXYWAIT;
00419 egg_snprintf(s, sizeof s, "\004\001%c%c%c%c%c%c%s", (port >> 8) % 256,
00420 (port % 256), x[0], x[1], x[2], x[3], botuser);
00421 tputs(sock, s, strlen(botuser) + 9);
00422 } else if (proxy == PROXY_SUN) {
00423 egg_snprintf(s, sizeof s, "%s %d\n", host, port);
00424 tputs(sock, s, strlen(s));
00425 }
00426 return sock;
00427 }
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439 int open_telnet_raw(int sock, char *server, int sport)
00440 {
00441 struct sockaddr_in name;
00442 struct hostent *hp;
00443 char host[121];
00444 int i, port, rc;
00445 volatile int proxy;
00446
00447
00448 if (firewall[0]) {
00449 if (firewall[0] == '!') {
00450 proxy = PROXY_SUN;
00451 strcpy(host, &firewall[1]);
00452 } else {
00453 proxy = PROXY_SOCKS;
00454 strcpy(host, firewall);
00455 }
00456 port = firewallport;
00457 } else {
00458 proxy = 0;
00459 strcpy(host, server);
00460 port = sport;
00461 }
00462 egg_bzero((char *) &name, sizeof(struct sockaddr_in));
00463
00464 name.sin_family = AF_INET;
00465 name.sin_addr.s_addr = (myip[0] ? getmyip() : INADDR_ANY);
00466 if (bind(sock, (struct sockaddr *) &name, sizeof(name)) < 0) {
00467 killsock(sock);
00468 return -1;
00469 }
00470 egg_bzero((char *) &name, sizeof(struct sockaddr_in));
00471
00472 name.sin_family = AF_INET;
00473 name.sin_port = htons(port);
00474
00475 if ((host[strlen(host) - 1] >= '0') && (host[strlen(host) - 1] <= '9'))
00476 name.sin_addr.s_addr = inet_addr(host);
00477 else {
00478
00479 debug0("WARNING: open_telnet_raw() is about to block in gethostbyname()!");
00480 if (!sigsetjmp(alarmret, 1)) {
00481 alarm(resolve_timeout);
00482 hp = gethostbyname(host);
00483 alarm(0);
00484 } else
00485 hp = NULL;
00486 if (hp == NULL)
00487 return -2;
00488 egg_memcpy(&name.sin_addr, hp->h_addr, hp->h_length);
00489 name.sin_family = hp->h_addrtype;
00490 }
00491 for (i = 0; i < threaddata()->MAXSOCKS; i++) {
00492 if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == sock))
00493 socklist[i].flags = (socklist[i].flags & ~SOCK_VIRTUAL) | SOCK_CONNECT;
00494 }
00495 rc = connect(sock, (struct sockaddr *) &name, sizeof(struct sockaddr_in));
00496 if (rc < 0) {
00497 if (errno == EINPROGRESS) {
00498
00499 if (firewall[0])
00500 return proxy_connect(sock, server, sport, proxy);
00501 return sock;
00502 } else
00503 return -1;
00504 }
00505
00506 if (firewall[0])
00507 return proxy_connect(sock, server, sport, proxy);
00508 return sock;
00509 }
00510
00511
00512 int open_telnet(char *server, int port)
00513 {
00514 int sock = getsock(0), ret = open_telnet_raw(sock, server, port);
00515
00516 return ret;
00517 }
00518
00519
00520
00521
00522 int open_address_listen(IP addr, int *port)
00523 {
00524 int sock = 0;
00525 socklen_t addrlen;
00526 struct sockaddr_in name;
00527
00528 if (firewall[0]) {
00529
00530 putlog(LOG_MISC, "*", "Can't open a listen port (you are using a "
00531 "firewall).");
00532 return -1;
00533 }
00534
00535 if (getmyip() > 0) {
00536 sock = getsock(SOCK_LISTEN);
00537 if (sock < 1)
00538 return -1;
00539
00540 egg_bzero((char *) &name, sizeof(struct sockaddr_in));
00541 name.sin_family = AF_INET;
00542 name.sin_port = htons(*port);
00543 name.sin_addr.s_addr = addr;
00544 if (bind(sock, (struct sockaddr *) &name, sizeof(name)) < 0) {
00545 killsock(sock);
00546 return -1;
00547 }
00548
00549 addrlen = sizeof(name);
00550 if (getsockname(sock, (struct sockaddr *) &name, &addrlen) < 0) {
00551 killsock(sock);
00552 return -1;
00553 }
00554 *port = ntohs(name.sin_port);
00555 if (listen(sock, 1) < 0) {
00556 killsock(sock);
00557 return -1;
00558 }
00559 }
00560
00561 return sock;
00562 }
00563
00564
00565
00566
00567 inline int open_listen(int *port)
00568 {
00569 return open_address_listen(myip[0] ? getmyip() : INADDR_ANY, port);
00570 }
00571
00572
00573
00574
00575 char *iptostr(IP ip)
00576 {
00577 struct in_addr a;
00578
00579 a.s_addr = ip;
00580 return inet_ntoa(a);
00581 }
00582
00583
00584
00585
00586
00587 int answer(int sock, char *caller, unsigned long *ip, unsigned short *port,
00588 int binary)
00589 {
00590 int new_sock;
00591 socklen_t addrlen;
00592 struct sockaddr_in from;
00593
00594 addrlen = sizeof(struct sockaddr);
00595 new_sock = accept(sock, (struct sockaddr *) &from, &addrlen);
00596
00597 if (new_sock < 0)
00598 return -1;
00599 if (ip != NULL) {
00600 *ip = from.sin_addr.s_addr;
00601
00602 strncpyz(caller, iptostr(*ip), 121);
00603 *ip = ntohl(*ip);
00604 }
00605 if (port != NULL)
00606 *port = ntohs(from.sin_port);
00607
00608 setsock(new_sock, (binary ? SOCK_BINARY : 0));
00609 return new_sock;
00610 }
00611
00612
00613
00614 int open_telnet_dcc(int sock, char *server, char *port)
00615 {
00616 int p;
00617 unsigned long addr;
00618 char sv[500];
00619 unsigned char c[4];
00620
00621 if (port != NULL)
00622 p = atoi(port);
00623 else
00624 p = 2000;
00625 if (server != NULL)
00626 addr = my_atoul(server);
00627 else
00628 addr = 0L;
00629 if (addr < (1 << 24))
00630 return -3;
00631 c[0] = (addr >> 24) & 0xff;
00632 c[1] = (addr >> 16) & 0xff;
00633 c[2] = (addr >> 8) & 0xff;
00634 c[3] = addr & 0xff;
00635 sprintf(sv, "%u.%u.%u.%u", c[0], c[1], c[2], c[3]);
00636 p = open_telnet_raw(sock, sv, p);
00637 return p;
00638 }
00639
00640
00641
00642
00643
00644 int preparefdset(fd_set *fd, sock_list *slist, int slistmax, int tclonly, int tclmask)
00645 {
00646 int fdtmp, i, foundsocks = 0;
00647
00648 FD_ZERO(fd);
00649 for (i = 0; i < slistmax; i++) {
00650 if (!(slist[i].flags & (SOCK_UNUSED | SOCK_VIRTUAL))) {
00651 if ((slist[i].sock == STDOUT) && !backgrd)
00652 fdtmp = STDIN;
00653 else
00654 fdtmp = slist[i].sock;
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664 if (slist[i].flags & SOCK_TCL) {
00665 if (!(slist[i].handler.tclsock.mask & tclmask))
00666 continue;
00667 } else if (tclonly)
00668 continue;
00669 foundsocks = 1;
00670 FD_SET(fdtmp, fd);
00671 }
00672 }
00673 return foundsocks;
00674 }
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686 int sockread(char *s, int *len, sock_list *slist, int slistmax, int tclonly)
00687 {
00688 struct timeval t;
00689 fd_set fdr, fdw, fde;
00690 int fds, i, x, have_r, have_w, have_e;
00691 int grab = 511, tclsock = -1, events = 0;
00692 struct threaddata *td = threaddata();
00693
00694 fds = getdtablesize();
00695 #ifdef FD_SETSIZE
00696 if (fds > FD_SETSIZE)
00697 fds = FD_SETSIZE;
00698 #endif
00699
00700 have_r = preparefdset(&fdr, slist, slistmax, tclonly, TCL_READABLE);
00701 have_w = preparefdset(&fdw, slist, slistmax, 1, TCL_WRITABLE);
00702 have_e = preparefdset(&fde, slist, slistmax, 1, TCL_EXCEPTION);
00703
00704
00705 t.tv_sec = td->blocktime.tv_sec;
00706 t.tv_usec = td->blocktime.tv_usec;
00707
00708 x = select((SELECT_TYPE_ARG1) fds,
00709 SELECT_TYPE_ARG234 (have_r ? &fdr : NULL),
00710 SELECT_TYPE_ARG234 (have_w ? &fdw : NULL),
00711 SELECT_TYPE_ARG234 (have_e ? &fde : NULL),
00712 SELECT_TYPE_ARG5 &t);
00713 if (x > 0) {
00714
00715 for (i = 0; i < slistmax; i++) {
00716 if (!tclonly && ((!(slist[i].flags & (SOCK_UNUSED | SOCK_TCL))) &&
00717 ((FD_ISSET(slist[i].sock, &fdr)) ||
00718 ((slist[i].sock == STDOUT) && (!backgrd) &&
00719 (FD_ISSET(STDIN, &fdr)))))) {
00720 if (slist[i].flags & (SOCK_LISTEN | SOCK_CONNECT)) {
00721
00722
00723
00724 if (slist[i].flags & SOCK_PROXYWAIT)
00725
00726 grab = 10;
00727 else if (!(slist[i].flags & SOCK_STRONGCONN)) {
00728 debug1("net: connect! sock %d", slist[i].sock);
00729 s[0] = 0;
00730 *len = 0;
00731 return i;
00732 }
00733 } else if (slist[i].flags & SOCK_PASS) {
00734 s[0] = 0;
00735 *len = 0;
00736 return i;
00737 }
00738 errno = 0;
00739 if ((slist[i].sock == STDOUT) && !backgrd)
00740 x = read(STDIN, s, grab);
00741 else
00742 x = read(slist[i].sock, s, grab);
00743 if (x <= 0) {
00744 if (errno != EAGAIN) {
00745
00746
00747
00748 *len = slist[i].sock;
00749 slist[i].flags &= ~SOCK_CONNECT;
00750 debug1("net: eof!(read) socket %d", slist[i].sock);
00751 return -1;
00752 } else {
00753 debug3("sockread EAGAIN: %d %d (%s)", slist[i].sock, errno,
00754 strerror(errno));
00755 continue;
00756 }
00757 }
00758 s[x] = 0;
00759 *len = x;
00760 if (slist[i].flags & SOCK_PROXYWAIT) {
00761 debug2("net: socket: %d proxy errno: %d", slist[i].sock, s[1]);
00762 slist[i].flags &= ~(SOCK_CONNECT | SOCK_PROXYWAIT);
00763 switch (s[1]) {
00764 case 90:
00765 s[0] = 0;
00766 *len = 0;
00767 return i;
00768 case 91:
00769 errno = ECONNREFUSED;
00770 break;
00771 case 92:
00772 case 93:
00773
00774
00775
00776 errno = ENETUNREACH;
00777 break;
00778 }
00779 *len = slist[i].sock;
00780 return -1;
00781 }
00782 return i;
00783 } else if (tclsock == -1 && (slist[i].flags & SOCK_TCL)) {
00784 events = FD_ISSET(slist[i].sock, &fdr) ? TCL_READABLE : 0;
00785 events |= FD_ISSET(slist[i].sock, &fdw) ? TCL_WRITABLE : 0;
00786 events |= FD_ISSET(slist[i].sock, &fde) ? TCL_EXCEPTION : 0;
00787 events &= slist[i].handler.tclsock.mask;
00788 if (events)
00789 tclsock = i;
00790 }
00791 }
00792 } else if (x == -1)
00793 return -2;
00794 else if (!tclonly) {
00795 s[0] = 0;
00796 *len = 0;
00797 }
00798 if (tclsock != -1) {
00799 (*slist[tclsock].handler.tclsock.proc)(slist[tclsock].handler.tclsock.cd,
00800 events);
00801 return -5;
00802 }
00803 return -3;
00804 }
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829 int sockgets(char *s, int *len)
00830 {
00831 char xx[514], *p, *px;
00832 int ret, i, data = 0;
00833
00834 for (i = 0; i < threaddata()->MAXSOCKS; i++) {
00835
00836 if (!(socklist[i].flags & (SOCK_UNUSED | SOCK_TCL | SOCK_BUFFER)) &&
00837 (socklist[i].handler.sock.inbuf != NULL)) {
00838 if (!(socklist[i].flags & SOCK_BINARY)) {
00839
00840 p = strchr(socklist[i].handler.sock.inbuf, '\n');
00841 if (p == NULL)
00842 p = strchr(socklist[i].handler.sock.inbuf, '\r');
00843 if (p != NULL) {
00844 *p = 0;
00845 if (strlen(socklist[i].handler.sock.inbuf) > 510)
00846 socklist[i].handler.sock.inbuf[510] = 0;
00847 strcpy(s, socklist[i].handler.sock.inbuf);
00848 px = nmalloc(strlen(p + 1) + 1);
00849 strcpy(px, p + 1);
00850 nfree(socklist[i].handler.sock.inbuf);
00851 if (px[0])
00852 socklist[i].handler.sock.inbuf = px;
00853 else {
00854 nfree(px);
00855 socklist[i].handler.sock.inbuf = NULL;
00856 }
00857
00858 if (s[strlen(s) - 1] == '\r')
00859 s[strlen(s) - 1] = 0;
00860 *len = strlen(s);
00861 return socklist[i].sock;
00862 }
00863 } else {
00864
00865 if (socklist[i].handler.sock.inbuflen <= 510) {
00866 *len = socklist[i].handler.sock.inbuflen;
00867 egg_memcpy(s, socklist[i].handler.sock.inbuf, socklist[i].handler.sock.inbuflen);
00868 nfree(socklist[i].handler.sock.inbuf);
00869 socklist[i].handler.sock.inbuf = NULL;
00870 socklist[i].handler.sock.inbuflen = 0;
00871 } else {
00872
00873 *len = 510;
00874 egg_memcpy(s, socklist[i].handler.sock.inbuf, *len);
00875 egg_memcpy(socklist[i].handler.sock.inbuf, socklist[i].handler.sock.inbuf + *len, *len);
00876 socklist[i].handler.sock.inbuflen -= *len;
00877 socklist[i].handler.sock.inbuf = nrealloc(socklist[i].handler.sock.inbuf, socklist[i].handler.sock.inbuflen);
00878 }
00879 return socklist[i].sock;
00880 }
00881 }
00882
00883 if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].flags & SOCK_EOFD)) {
00884 s[0] = 0;
00885 *len = socklist[i].sock;
00886 return -1;
00887 }
00888 }
00889
00890 *len = 0;
00891 ret = sockread(xx, len, socklist, threaddata()->MAXSOCKS, 0);
00892 if (ret < 0) {
00893 s[0] = 0;
00894 return ret;
00895 }
00896
00897 if (socklist[ret].flags & SOCK_CONNECT) {
00898 if (socklist[ret].flags & SOCK_STRONGCONN) {
00899 socklist[ret].flags &= ~SOCK_STRONGCONN;
00900
00901 socklist[ret].handler.sock.inbuflen = *len;
00902 socklist[ret].handler.sock.inbuf = nmalloc(*len + 1);
00903
00904 egg_memcpy(socklist[ret].handler.sock.inbuf, xx, *len);
00905 socklist[ret].handler.sock.inbuf[*len] = 0;
00906 }
00907 socklist[ret].flags &= ~SOCK_CONNECT;
00908 s[0] = 0;
00909 return socklist[ret].sock;
00910 }
00911 if (socklist[ret].flags & SOCK_BINARY) {
00912 egg_memcpy(s, xx, *len);
00913 return socklist[ret].sock;
00914 }
00915 if (socklist[ret].flags & (SOCK_LISTEN | SOCK_PASS | SOCK_TCL)) {
00916 s[0] = 0;
00917 return socklist[ret].sock;
00918 }
00919 if (socklist[ret].flags & SOCK_BUFFER) {
00920 socklist[ret].handler.sock.inbuf = (char *) nrealloc(socklist[ret].handler.sock.inbuf,
00921 socklist[ret].handler.sock.inbuflen + *len + 1);
00922 egg_memcpy(socklist[ret].handler.sock.inbuf + socklist[ret].handler.sock.inbuflen, xx, *len);
00923 socklist[ret].handler.sock.inbuflen += *len;
00924
00925
00926 socklist[ret].handler.sock.inbuf[socklist[ret].handler.sock.inbuflen] = 0;
00927 return -4;
00928 }
00929
00930 if (socklist[ret].handler.sock.inbuf != NULL) {
00931 p = socklist[ret].handler.sock.inbuf;
00932 socklist[ret].handler.sock.inbuf = nmalloc(strlen(p) + strlen(xx) + 1);
00933 strcpy(socklist[ret].handler.sock.inbuf, p);
00934 strcat(socklist[ret].handler.sock.inbuf, xx);
00935 nfree(p);
00936 if (strlen(socklist[ret].handler.sock.inbuf) < 512) {
00937 strcpy(xx, socklist[ret].handler.sock.inbuf);
00938 nfree(socklist[ret].handler.sock.inbuf);
00939 socklist[ret].handler.sock.inbuf = NULL;
00940 socklist[ret].handler.sock.inbuflen = 0;
00941 } else {
00942 p = socklist[ret].handler.sock.inbuf;
00943 socklist[ret].handler.sock.inbuflen = strlen(p) - 510;
00944 socklist[ret].handler.sock.inbuf = nmalloc(socklist[ret].handler.sock.inbuflen + 1);
00945 strcpy(socklist[ret].handler.sock.inbuf, p + 510);
00946 *(p + 510) = 0;
00947 strcpy(xx, p);
00948 nfree(p);
00949
00950 }
00951 }
00952
00953 p = strchr(xx, '\n');
00954 if (p == NULL)
00955 p = strchr(xx, '\r');
00956 if (p != NULL) {
00957 *p = 0;
00958 strcpy(s, xx);
00959 memmove(xx, p + 1, strlen(p + 1) + 1);
00960 if (s[strlen(s) - 1] == '\r')
00961 s[strlen(s) - 1] = 0;
00962 data = 1;
00963
00964
00965 } else {
00966 s[0] = 0;
00967 if (strlen(xx) >= 510) {
00968
00969 strcpy(s, xx);
00970 xx[0] = 0;
00971 data = 1;
00972 }
00973 }
00974 *len = strlen(s);
00975
00976 if (!xx[0]) {
00977 if (data)
00978 return socklist[ret].sock;
00979 else
00980 return -3;
00981 }
00982
00983 if (socklist[ret].handler.sock.inbuf != NULL) {
00984 p = socklist[ret].handler.sock.inbuf;
00985 socklist[ret].handler.sock.inbuflen = strlen(p) + strlen(xx);
00986 socklist[ret].handler.sock.inbuf = nmalloc(socklist[ret].handler.sock.inbuflen + 1);
00987 strcpy(socklist[ret].handler.sock.inbuf, xx);
00988 strcat(socklist[ret].handler.sock.inbuf, p);
00989 nfree(p);
00990 } else {
00991 socklist[ret].handler.sock.inbuflen = strlen(xx);
00992 socklist[ret].handler.sock.inbuf = nmalloc(socklist[ret].handler.sock.inbuflen + 1);
00993 strcpy(socklist[ret].handler.sock.inbuf, xx);
00994 }
00995 if (data)
00996 return socklist[ret].sock;
00997 else
00998 return -3;
00999 }
01000
01001
01002
01003
01004
01005 void tputs(register int z, char *s, unsigned int len)
01006 {
01007 register int i, x, idx;
01008 char *p;
01009 static int inhere = 0;
01010
01011 if (z < 0)
01012 return;
01013
01014 if (((z == STDOUT) || (z == STDERR)) && (!backgrd || use_stderr)) {
01015 write(z, s, len);
01016 return;
01017 }
01018
01019 for (i = 0; i < threaddata()->MAXSOCKS; i++) {
01020 if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == z)) {
01021 for (idx = 0; idx < dcc_total; idx++) {
01022 if ((dcc[idx].sock == z) && dcc[idx].type && dcc[idx].type->name) {
01023 if (!strncmp(dcc[idx].type->name, "BOT", 3))
01024 otraffic_bn_today += len;
01025 else if (!strcmp(dcc[idx].type->name, "SERVER"))
01026 otraffic_irc_today += len;
01027 else if (!strncmp(dcc[idx].type->name, "CHAT", 4))
01028 otraffic_dcc_today += len;
01029 else if (!strncmp(dcc[idx].type->name, "FILES", 5))
01030 otraffic_filesys_today += len;
01031 else if (!strcmp(dcc[idx].type->name, "SEND"))
01032 otraffic_trans_today += len;
01033 else if (!strncmp(dcc[idx].type->name, "GET", 3))
01034 otraffic_trans_today += len;
01035 else
01036 otraffic_unknown_today += len;
01037 break;
01038 }
01039 }
01040
01041 if (socklist[i].handler.sock.outbuf != NULL) {
01042
01043 p = (char *) nrealloc(socklist[i].handler.sock.outbuf, socklist[i].handler.sock.outbuflen + len);
01044 egg_memcpy(p + socklist[i].handler.sock.outbuflen, s, len);
01045 socklist[i].handler.sock.outbuf = p;
01046 socklist[i].handler.sock.outbuflen += len;
01047 return;
01048 }
01049
01050 x = write(z, s, len);
01051 if (x == -1)
01052 x = 0;
01053 if (x < len) {
01054
01055 socklist[i].handler.sock.outbuf = nmalloc(len - x);
01056 egg_memcpy(socklist[i].handler.sock.outbuf, &s[x], len - x);
01057 socklist[i].handler.sock.outbuflen = len - x;
01058 }
01059 return;
01060 }
01061 }
01062
01063 if (!inhere) {
01064 inhere = 1;
01065
01066 putlog(LOG_MISC, "*", "!!! writing to nonexistent socket: %d", z);
01067 s[strlen(s) - 1] = 0;
01068 putlog(LOG_MISC, "*", "!-> '%s'", s);
01069
01070 inhere = 0;
01071 }
01072 }
01073
01074
01075
01076
01077 void dequeue_sockets()
01078 {
01079 int i, x;
01080
01081 int z = 0, fds;
01082 fd_set wfds;
01083 struct timeval tv;
01084
01085
01086 fds = getdtablesize();
01087
01088 #ifdef FD_SETSIZE
01089 if (fds > FD_SETSIZE)
01090 fds = FD_SETSIZE;
01091 #endif
01092 FD_ZERO(&wfds);
01093 tv.tv_sec = 0;
01094 tv.tv_usec = 0;
01095 for (i = 0; i < threaddata()->MAXSOCKS; i++) {
01096 if (!(socklist[i].flags & (SOCK_UNUSED | SOCK_TCL)) &&
01097 socklist[i].handler.sock.outbuf != NULL) {
01098 FD_SET(socklist[i].sock, &wfds);
01099 z = 1;
01100 }
01101 }
01102 if (!z)
01103 return;
01104
01105 select((SELECT_TYPE_ARG1) fds, SELECT_TYPE_ARG234 NULL,
01106 SELECT_TYPE_ARG234 &wfds, SELECT_TYPE_ARG234 NULL,
01107 SELECT_TYPE_ARG5 &tv);
01108
01109
01110
01111 for (i = 0; i < threaddata()->MAXSOCKS; i++) {
01112 if (!(socklist[i].flags & (SOCK_UNUSED | SOCK_TCL)) &&
01113 (socklist[i].handler.sock.outbuf != NULL) && (FD_ISSET(socklist[i].sock, &wfds))) {
01114
01115 errno = 0;
01116 x = write(socklist[i].sock, socklist[i].handler.sock.outbuf, socklist[i].handler.sock.outbuflen);
01117 if ((x < 0) && (errno != EAGAIN)
01118 #ifdef EBADSLT
01119 && (errno != EBADSLT)
01120 #endif
01121 #ifdef ENOTCONN
01122 && (errno != ENOTCONN)
01123 #endif
01124 ) {
01125
01126 debug3("net: eof!(write) socket %d (%s,%d)", socklist[i].sock,
01127 strerror(errno), errno);
01128 socklist[i].flags |= SOCK_EOFD;
01129 } else if (x == socklist[i].handler.sock.outbuflen) {
01130
01131 nfree(socklist[i].handler.sock.outbuf);
01132 socklist[i].handler.sock.outbuf = NULL;
01133 socklist[i].handler.sock.outbuflen = 0;
01134 } else if (x > 0) {
01135 char *p = socklist[i].handler.sock.outbuf;
01136
01137
01138 socklist[i].handler.sock.outbuf = nmalloc(socklist[i].handler.sock.outbuflen - x);
01139 egg_memcpy(socklist[i].handler.sock.outbuf, p + x, socklist[i].handler.sock.outbuflen - x);
01140 socklist[i].handler.sock.outbuflen -= x;
01141 nfree(p);
01142 } else {
01143 debug3("dequeue_sockets(): errno = %d (%s) on %d", errno,
01144 strerror(errno), socklist[i].sock);
01145 }
01146
01147
01148
01149 if (!socklist[i].handler.sock.outbuf) {
01150 int idx = findanyidx(socklist[i].sock);
01151
01152 if (idx > 0 && dcc[idx].type && dcc[idx].type->outdone)
01153 dcc[idx].type->outdone(idx);
01154 }
01155 }
01156 }
01157 }
01158
01159
01160
01161
01162
01163
01164 void tell_netdebug(int idx)
01165 {
01166 int i;
01167 char s[80];
01168
01169 dprintf(idx, "Open sockets:");
01170 for (i = 0; i < threaddata()->MAXSOCKS; i++) {
01171 if (!(socklist[i].flags & SOCK_UNUSED)) {
01172 sprintf(s, " %d", socklist[i].sock);
01173 if (socklist[i].flags & SOCK_BINARY)
01174 strcat(s, " (binary)");
01175 if (socklist[i].flags & SOCK_LISTEN)
01176 strcat(s, " (listen)");
01177 if (socklist[i].flags & SOCK_PASS)
01178 strcat(s, " (passed on)");
01179 if (socklist[i].flags & SOCK_CONNECT)
01180 strcat(s, " (connecting)");
01181 if (socklist[i].flags & SOCK_STRONGCONN)
01182 strcat(s, " (strong)");
01183 if (socklist[i].flags & SOCK_NONSOCK)
01184 strcat(s, " (file)");
01185 if (socklist[i].flags & SOCK_TCL)
01186 strcat(s, " (tcl)");
01187 if (!(socklist[i].flags & SOCK_TCL)) {
01188 if (socklist[i].handler.sock.inbuf != NULL)
01189 sprintf(&s[strlen(s)], " (inbuf: %04X)",
01190 (unsigned int) strlen(socklist[i].handler.sock.inbuf));
01191 if (socklist[i].handler.sock.outbuf != NULL)
01192 sprintf(&s[strlen(s)], " (outbuf: %06lX)", socklist[i].handler.sock.outbuflen);
01193 }
01194 strcat(s, ",");
01195 dprintf(idx, "%s", s);
01196 }
01197 }
01198 dprintf(idx, " done.\n");
01199 }
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209 int sanitycheck_dcc(char *nick, char *from, char *ipaddy, char *port)
01210 {
01211
01212
01213
01214
01215 char badaddress[16];
01216 IP ip = my_atoul(ipaddy);
01217 int prt = atoi(port);
01218
01219
01220 if (!dcc_sanitycheck)
01221 return 1;
01222
01223 if (prt < 1) {
01224 putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an impossible port of %u!",
01225 nick, from, prt);
01226 return 0;
01227 }
01228 sprintf(badaddress, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff,
01229 (ip >> 8) & 0xff, ip & 0xff);
01230 if (ip < (1 << 24)) {
01231 putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an impossible IP of %s!",
01232 nick, from, badaddress);
01233 return 0;
01234 }
01235 return 1;
01236 }
01237
01238 int hostsanitycheck_dcc(char *nick, char *from, IP ip, char *dnsname,
01239 char *prt)
01240 {
01241
01242
01243
01244 char hostn[256], badaddress[16];
01245
01246
01247 if (!dcc_sanitycheck)
01248 return 1;
01249 sprintf(badaddress, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff,
01250 (ip >> 8) & 0xff, ip & 0xff);
01251
01252
01253
01254
01255 strncpyz(hostn, extracthostname(from), sizeof hostn);
01256 if (!egg_strcasecmp(hostn, dnsname)) {
01257 putlog(LOG_DEBUG, "*", "DNS information for submitted IP checks out.");
01258 return 1;
01259 }
01260 if (!strcmp(badaddress, dnsname))
01261 putlog(LOG_MISC, "*", "ALERT: (%s!%s) sent a DCC request with bogus IP "
01262 "information of %s port %s. %s does not resolve to %s!", nick, from,
01263 badaddress, prt, from, badaddress);
01264 else
01265 return 1;
01266
01267 return 0;
01268 }
01269
01270
01271
01272
01273
01274
01275 int sock_has_data(int type, int sock)
01276 {
01277 int ret = 0, i;
01278
01279 for (i = 0; i < threaddata()->MAXSOCKS; i++)
01280 if (!(socklist[i].flags & SOCK_UNUSED) && socklist[i].sock == sock)
01281 break;
01282 if (i < threaddata()->MAXSOCKS) {
01283 switch (type) {
01284 case SOCK_DATA_OUTGOING:
01285 ret = (socklist[i].handler.sock.outbuf != NULL);
01286 break;
01287 case SOCK_DATA_INCOMING:
01288 ret = (socklist[i].handler.sock.inbuf != NULL);
01289 break;
01290 }
01291 } else
01292 debug1("sock_has_data: could not find socket #%d, returning false.", sock);
01293 return ret;
01294 }
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306 int flush_inbuf(int idx)
01307 {
01308 int i, len;
01309 char *inbuf;
01310
01311 Assert((idx >= 0) && (idx < dcc_total));
01312 for (i = 0; i < threaddata()->MAXSOCKS; i++) {
01313 if ((dcc[idx].sock == socklist[i].sock) &&
01314 !(socklist[i].flags & SOCK_UNUSED)) {
01315 len = socklist[i].handler.sock.inbuflen;
01316 if ((len > 0) && socklist[i].handler.sock.inbuf) {
01317 if (dcc[idx].type && dcc[idx].type->activity) {
01318 inbuf = socklist[i].handler.sock.inbuf;
01319 socklist[i].handler.sock.inbuf = NULL;
01320 dcc[idx].type->activity(idx, inbuf, len);
01321 nfree(inbuf);
01322 return len;
01323 } else
01324 return -2;
01325 } else
01326 return 0;
01327 }
01328 }
01329 return -1;
01330 }