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

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

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


Revision 1.9 - (hide annotations) (download) (as text)
Sat Dec 11 18:58:03 1999 UTC (19 years, 11 months ago) by fabian
Branch: MAIN
Changes since 1.8: +16 -16 lines
File MIME type: text/x-chdr
tothwolf's remove-context-bloat patch

1 segfault 1.1 /*
2     * net.c -- handles:
3     * all raw network i/o
4     *
5     * This is hereby released into the public domain.
6     * Robey Pointer, robey@netcom.com
7     */
8    
9     #include "main.h"
10     #include <limits.h>
11     #include <string.h>
12     #include <netdb.h>
13     #include <sys/socket.h>
14     #if HAVE_SYS_SELECT_H
15     #include <sys/select.h>
16     #endif
17     #include <netinet/in.h>
18     #include <arpa/inet.h> /* is this really necessary? */
19     #include <errno.h>
20     #if HAVE_UNISTD_H
21     #include <unistd.h>
22     #endif
23     #include <fcntl.h>
24     #include <setjmp.h>
25    
26     #if !HAVE_GETDTABLESIZE
27     #ifdef FD_SETSIZE
28     #define getdtablesize() FD_SETSIZE
29     #else
30     #define getdtablesize() 200
31     #endif
32     #endif
33    
34     extern int backgrd;
35     extern int use_stderr;
36     extern int resolve_timeout;
37    
38     char hostname[121] = ""; /* hostname can be specified in the config
39     * file */
40     char myip[121] = ""; /* IP can be specified in the config file */
41     char firewall[121] = ""; /* socks server for firewall */
42     int firewallport = 1080; /* default port of Sock4/5 firewalls */
43     char botuser[21] = "eggdrop"; /* username of the user running the bot */
44     int dcc_sanitycheck = 0; /* we should do some sanity checking on dcc
45     * connections. */
46     sock_list *socklist = 0; /* enough to be safe */
47     int MAXSOCKS = 0;
48    
49     /* types of proxy */
50     #define PROXY_SOCKS 1
51     #define PROXY_SUN 2
52    
53     jmp_buf alarmret; /* env buffer for alarm() returns */
54    
55     /* i need an UNSIGNED long for dcc type stuff */
56     IP my_atoul(char *s)
57     {
58     IP ret = 0;
59    
60     while ((*s >= '0') && (*s <= '9')) {
61     ret *= 10;
62     ret += ((*s) - '0');
63     s++;
64     }
65     return ret;
66     }
67    
68     /* i read somewhere that memcpy() is broken on some machines */
69     /* it's easy to replace, so i'm not gonna take any chances, because
70     * it's pretty important that it work correctly here */
71     void my_memcpy(char *dest, char *src, int len)
72     {
73     while (len--)
74     *dest++ = *src++;
75     }
76    
77     #ifndef HAVE_BZERO
78     /* bzero() is bsd-only, so here's one for non-bsd systems */
79     void bzero(char *dest, int len)
80     {
81     while (len--)
82     *dest++ = 0;
83     }
84     #endif
85    
86     /* initialize the socklist */
87     void init_net()
88     {
89     int i;
90    
91     for (i = 0; i < MAXSOCKS; i++) {
92     socklist[i].flags = SOCK_UNUSED;
93     }
94     }
95    
96     int expmem_net()
97     {
98     int i, tot = 0;
99    
100 fabian 1.9 Context;
101 segfault 1.1 for (i = 0; i < MAXSOCKS; i++) {
102     if (!(socklist[i].flags & SOCK_UNUSED)) {
103     if (socklist[i].inbuf != NULL)
104     tot += strlen(socklist[i].inbuf) + 1;
105     if (socklist[i].outbuf != NULL)
106     tot += socklist[i].outbuflen;
107     }
108     }
109     return tot;
110     }
111    
112     /* get my ip number */
113     IP getmyip()
114     {
115     struct hostent *hp;
116     char s[121];
117     IP ip;
118     struct in_addr *in;
119    
120     /* could be pre-defined */
121     if (myip[0]) {
122     if ((myip[strlen(myip) - 1] >= '0') && (myip[strlen(myip) - 1] <= '9'))
123     return (IP) inet_addr(myip);
124     }
125     /* also could be pre-defined */
126     if (hostname[0])
127     hp = gethostbyname(hostname);
128     else {
129     gethostname(s, 120);
130     hp = gethostbyname(s);
131     }
132     if (hp == NULL)
133     fatal("Hostname self-lookup failed.", 0);
134     in = (struct in_addr *) (hp->h_addr_list[0]);
135     ip = (IP) (in->s_addr);
136     return ip;
137     }
138    
139     void neterror(char *s)
140     {
141     switch (errno) {
142     case EADDRINUSE:
143     strcpy(s, "Address already in use");
144     break;
145     case EADDRNOTAVAIL:
146     strcpy(s, "Address invalid on remote machine");
147     break;
148     case EAFNOSUPPORT:
149     strcpy(s, "Address family not supported");
150     break;
151     case EALREADY:
152     strcpy(s, "Socket already in use");
153     break;
154     case EBADF:
155     strcpy(s, "Socket descriptor is bad");
156     break;
157     case ECONNREFUSED:
158     strcpy(s, "Connection refused");
159     break;
160     case EFAULT:
161     strcpy(s, "Namespace segment violation");
162     break;
163     case EINPROGRESS:
164     strcpy(s, "Operation in progress");
165     break;
166     case EINTR:
167     strcpy(s, "Timeout");
168     break;
169     case EINVAL:
170     strcpy(s, "Invalid namespace");
171     break;
172     case EISCONN:
173     strcpy(s, "Socket already connected");
174     break;
175     case ENETUNREACH:
176     strcpy(s, "Network unreachable");
177     break;
178     case ENOTSOCK:
179     strcpy(s, "File descriptor, not a socket");
180     break;
181     case ETIMEDOUT:
182     strcpy(s, "Connection timed out");
183     break;
184     case ENOTCONN:
185     strcpy(s, "Socket is not connected");
186     break;
187     case EHOSTUNREACH:
188     strcpy(s, "Host is unreachable");
189     break;
190     case EPIPE:
191     strcpy(s, "Broken pipe");
192     break;
193     #ifdef ECONNRESET
194     case ECONNRESET:
195     strcpy(s, "Connection reset by peer");
196     break;
197     #endif
198     #ifdef EACCES
199     case EACCES:
200     strcpy(s, "Permission denied");
201     break;
202     #endif
203     case 0:
204     strcpy(s, "Error 0");
205     break;
206     default:
207     sprintf(s, "Unforseen error %d", errno);
208     break;
209     }
210     }
211    
212 fabian 1.3 /* return a free entry in the socket entry */
213     int allocsock(int sock, int options)
214 segfault 1.1 {
215     int i;
216    
217 fabian 1.9 Context;
218 segfault 1.1 for (i = 0; i < MAXSOCKS; i++) {
219     if (socklist[i].flags & SOCK_UNUSED) {
220     /* yay! there is table space */
221     socklist[i].inbuf = socklist[i].outbuf = NULL;
222     socklist[i].outbuflen = 0;
223     socklist[i].flags = options;
224     socklist[i].sock = sock;
225 fabian 1.3 return i;
226     }
227     }
228     fatal("Socket table is full!", 0);
229     return -1; /* never reached */
230     }
231    
232     /* request a normal socket for i/o */
233     void setsock(int sock, int options)
234     {
235     int i = allocsock(sock, options);
236     int parm;
237    
238 segfault 1.1 if (((sock != STDOUT) || backgrd) &&
239     !(socklist[i].flags & SOCK_NONSOCK)) {
240     parm = 1;
241 fabian 1.3 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *) &parm, sizeof(int));
242 segfault 1.1
243     parm = 0;
244     setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &parm, sizeof(int));
245     }
246     if (options & SOCK_LISTEN) {
247     /* Tris says this lets us grab the same port again next time */
248     parm = 1;
249     setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &parm,
250     sizeof(int));
251     }
252     /* yay async i/o ! */
253     fcntl(sock, F_SETFL, O_NONBLOCK);
254     }
255    
256     int getsock(int options)
257     {
258     int sock = socket(AF_INET, SOCK_STREAM, 0);
259    
260     if (sock < 0)
261     fatal("Can't open a socket at all!", 0);
262     setsock(sock, options);
263     return sock;
264     }
265    
266     /* done with a socket */
267     void killsock(int sock)
268     {
269     int i;
270    
271     for (i = 0; i < MAXSOCKS; i++) {
272 fabian 1.2 if ((socklist[i].sock == sock) && !(socklist[i].flags & SOCK_UNUSED)) {
273 segfault 1.1 close(socklist[i].sock);
274     if (socklist[i].inbuf != NULL) {
275     nfree(socklist[i].inbuf);
276     socklist[i].inbuf = NULL;
277     }
278     if (socklist[i].outbuf != NULL) {
279     nfree(socklist[i].outbuf);
280     socklist[i].outbuf = NULL;
281     socklist[i].outbuflen = 0;
282     }
283     socklist[i].flags = SOCK_UNUSED;
284     return;
285     }
286     }
287     putlog(LOG_MISC, "*", "Attempt to kill un-allocated socket %d !!", sock);
288     }
289    
290     /* send connection request to proxy */
291     static int proxy_connect(int sock, char *host, int port, int proxy)
292     {
293     unsigned char x[10];
294     struct hostent *hp;
295     char s[30];
296     int i;
297    
298     /* socks proxy */
299     if (proxy == PROXY_SOCKS) {
300     /* numeric IP? */
301     if ((host[strlen(host) - 1] >= '0') && (host[strlen(host) - 1] <= '9')) {
302     IP ip = ((IP) inet_addr(host)); /* drummer */
303     my_memcpy((char *) x, (char *) &ip, 4); /* Beige@Efnet */
304     } else {
305     /* no, must be host.domain */
306     if (!setjmp(alarmret)) {
307     alarm(resolve_timeout);
308     hp = gethostbyname(host);
309     alarm(0);
310     } else {
311     hp = NULL;
312     }
313     if (hp == NULL) {
314     killsock(sock);
315     return -2;
316     }
317     my_memcpy((char *) x, (char *) hp->h_addr, hp->h_length);
318     }
319     for (i = 0; i < MAXSOCKS; i++) {
320     if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == sock))
321     socklist[i].flags |= SOCK_PROXYWAIT; /* drummer */
322     }
323     sprintf(s, "\004\001%c%c%c%c%c%c%s", (port >> 8) % 256, (port % 256),
324     x[0], x[1], x[2], x[3], botuser);
325     tputs(sock, s, strlen(botuser) + 9); /* drummer */
326     } else if (proxy == PROXY_SUN) {
327     sprintf(s, "%s %d\n", host, port);
328     tputs(sock, s, strlen(s)); /* drummer */
329     }
330     return sock;
331     }
332    
333     /* starts a connection attempt to a socket
334 fabian 1.3 *
335     * If given a normal hostname, this will be resolved to the corresponding
336     * IP address first. PLEASE try to use the non-blocking dns functions
337     * instead and then call this function with the IP address to avoid blocking.
338     *
339 segfault 1.1 * returns <0 if connection refused:
340     * -1 neterror() type error
341     * -2 can't resolve hostname */
342     int open_telnet_raw(int sock, char *server, int sport)
343     {
344     struct sockaddr_in name;
345     struct hostent *hp;
346     char host[121];
347     int i, port;
348     volatile int proxy;
349    
350     /* firewall? use socks */
351     if (firewall[0]) {
352     if (firewall[0] == '!') {
353     proxy = PROXY_SUN;
354     strcpy(host, &firewall[1]);
355     } else {
356     proxy = PROXY_SOCKS;
357     strcpy(host, firewall);
358     }
359     port = firewallport;
360     } else {
361     proxy = 0;
362     strcpy(host, server);
363     port = sport;
364     }
365     /* patch by tris for multi-hosted machines: */
366     bzero((char *) &name, sizeof(struct sockaddr_in));
367    
368     name.sin_family = AF_INET;
369     name.sin_addr.s_addr = (myip[0] ? getmyip() : INADDR_ANY);
370 fabian 1.4 if (bind(sock, (struct sockaddr *) &name, sizeof(name)) < 0)
371 segfault 1.1 return -1;
372     bzero((char *) &name, sizeof(struct sockaddr_in));
373    
374     name.sin_family = AF_INET;
375     name.sin_port = my_htons(port);
376     /* numeric IP? */
377     if ((host[strlen(host) - 1] >= '0') && (host[strlen(host) - 1] <= '9'))
378     name.sin_addr.s_addr = inet_addr(host);
379     else {
380     /* no, must be host.domain */
381 fabian 1.3 debug0("Warning: open_telnet_raw() is about to block in gethostbyname()!");
382 segfault 1.1 if (!setjmp(alarmret)) {
383     alarm(resolve_timeout);
384     hp = gethostbyname(host);
385     alarm(0);
386     } else {
387     hp = NULL;
388     }
389 fabian 1.4 if (hp == NULL)
390 segfault 1.1 return -2;
391     my_memcpy((char *) &name.sin_addr, hp->h_addr, hp->h_length);
392     name.sin_family = hp->h_addrtype;
393     }
394     for (i = 0; i < MAXSOCKS; i++) {
395     if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == sock))
396     socklist[i].flags |= SOCK_CONNECT;
397     }
398     if (connect(sock, (struct sockaddr *) &name,
399     sizeof(struct sockaddr_in)) < 0) {
400     if (errno == EINPROGRESS) {
401     /* firewall? announce connect attempt to proxy */
402     if (firewall[0])
403     return proxy_connect(sock, server, sport, proxy);
404     return sock; /* async success! */
405 fabian 1.4 } else
406 segfault 1.1 return -1;
407     }
408     /* synchronous? :/ */
409     if (firewall[0])
410     return proxy_connect(sock, server, sport, proxy);
411     return sock;
412     }
413    
414     /* ordinary non-binary connection attempt */
415     int open_telnet(char *server, int port)
416     {
417 fabian 1.4 int sock = getsock(0),
418     ret = open_telnet_raw(sock, server, port);
419    
420     if (ret < 0)
421     killsock(sock);
422     return ret;
423 segfault 1.1 }
424    
425     /* returns a socket number for a listening socket that will accept any
426     * connection -- port # is returned in port */
427     int open_listen(int *port)
428     {
429     int sock, addrlen;
430     struct sockaddr_in name;
431    
432     if (firewall[0]) {
433     /* FIXME: can't do listen port thru firewall yet */
434 fabian 1.6 putlog(LOG_MISC, "*", "!! Cant open a listen port (you are using a firewall)");
435 segfault 1.1 return -1;
436     }
437     sock = getsock(SOCK_LISTEN);
438     bzero((char *) &name, sizeof(struct sockaddr_in));
439    
440     name.sin_family = AF_INET;
441     name.sin_port = my_htons(*port); /* 0 = just assign us a port */
442     name.sin_addr.s_addr = (myip[0] ? getmyip() : INADDR_ANY);
443     if (bind(sock, (struct sockaddr *) &name, sizeof(name)) < 0) {
444     killsock(sock);
445     return -1;
446     }
447     /* what port are we on? */
448     addrlen = sizeof(name);
449     if (getsockname(sock, (struct sockaddr *) &name, &addrlen) < 0) {
450     killsock(sock);
451     return -1;
452     }
453     *port = my_ntohs(name.sin_port);
454     if (listen(sock, 1) < 0) {
455     killsock(sock);
456     return -1;
457     }
458     return sock;
459     }
460    
461 fabian 1.3 /* Given a network-style IP address, returns the hostname. The hostname
462     * will be in the "##.##.##.##" format if there was an error.
463     *
464     * NOTE: This function is depreciated. Try using the async dns approach
465     * instead. */
466 segfault 1.1 char *hostnamefromip(unsigned long ip)
467     {
468     struct hostent *hp;
469     unsigned long addr = ip;
470     unsigned char *p;
471 fabian 1.3 static char s[UHOSTLEN];
472 segfault 1.1
473     if (!setjmp(alarmret)) {
474     alarm(resolve_timeout);
475     hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
476     alarm(0);
477     } else {
478     hp = NULL;
479     }
480     if (hp == NULL) {
481     p = (unsigned char *) &addr;
482     sprintf(s, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
483     return s;
484     }
485 fabian 1.3 strncpy(s, hp->h_name, UHOSTLEN - 1);
486     s[UHOSTLEN - 1] = 0;
487 segfault 1.1 return s;
488     }
489    
490 fabian 1.5 /* Returns the given network byte order IP address in the
491     * dotted format - "##.##.##.##" */
492 fabian 1.3 char *iptostr(IP ip)
493     {
494     struct in_addr a;
495    
496     a.s_addr = ip;
497     return inet_ntoa(a);
498     }
499    
500 segfault 1.1 /* short routine to answer a connect received on a socket made previously
501     * by open_listen ... returns hostname of the caller & the new socket
502     * does NOT dispose of old "public" socket! */
503     int answer(int sock, char *caller, unsigned long *ip,
504     unsigned short *port, int binary)
505     {
506     int new_sock, addrlen;
507     struct sockaddr_in from;
508 fabian 1.8 addrlen = sizeof(struct sockaddr);
509 fabian 1.3
510 segfault 1.1 new_sock = accept(sock, (struct sockaddr *) &from, &addrlen);
511     if (new_sock < 0)
512     return -1;
513     if (ip != NULL) {
514     *ip = from.sin_addr.s_addr;
515 fabian 1.3 /* This is now done asynchronously. Instead, we just provide the
516     * IP address.
517     * strncpy(caller, hostnamefromip(*ip), 120);
518     */
519     strncpy(caller, iptostr(*ip), 120);
520 segfault 1.1 caller[120] = 0;
521     *ip = my_ntohl(*ip);
522     }
523     if (port != NULL)
524     *port = my_ntohs(from.sin_port);
525     /* set up all the normal socket crap */
526     setsock(new_sock, (binary ? SOCK_BINARY : 0));
527     return new_sock;
528     }
529    
530     /* like open_telnet, but uses server & port specifications of dcc */
531     int open_telnet_dcc(int sock, char *server, char *port)
532     {
533     int p;
534     unsigned long addr;
535     char sv[121];
536     unsigned char c[4];
537    
538     if (port != NULL)
539     p = atoi(port);
540     else
541     p = 2000;
542     if (server != NULL)
543     addr = my_atoul(server);
544     else
545     addr = 0L;
546     if (addr < (1 << 24))
547     return -3; /* fake address */
548     c[0] = (addr >> 24) & 0xff;
549     c[1] = (addr >> 16) & 0xff;
550     c[2] = (addr >> 8) & 0xff;
551     c[3] = addr & 0xff;
552     sprintf(sv, "%u.%u.%u.%u", c[0], c[1], c[2], c[3]);
553     /* strcpy(sv,hostnamefromip(addr)); */
554     p = open_telnet_raw(sock, sv, p);
555     return p;
556     }
557    
558     /* all new replacements for mtgets/mtread */
559    
560     /* attempts to read from all the sockets in socklist
561     * fills s with up to 511 bytes if available, and returns the array index
562     * on EOF, returns -1, with socket in len
563     * on socket error, returns -2
564     * if nothing is ready, returns -3 */
565     static int sockread(char *s, int *len)
566     {
567     fd_set fd;
568     int fds, i, x;
569     struct timeval t;
570     int grab = 511;
571    
572     fds = getdtablesize();
573     #ifdef FD_SETSIZE
574     if (fds > FD_SETSIZE)
575     fds = FD_SETSIZE; /* fixes YET ANOTHER freebsd bug!!! */
576     #endif
577     /* timeout: 1 sec */
578     t.tv_sec = 1;
579     t.tv_usec = 0;
580     FD_ZERO(&fd);
581     for (i = 0; i < MAXSOCKS; i++)
582     if (!(socklist[i].flags & SOCK_UNUSED)) {
583     if ((socklist[i].sock == STDOUT) && !backgrd)
584     FD_SET(STDIN, &fd);
585     else
586     FD_SET(socklist[i].sock, &fd);
587     }
588     #ifdef HPUX_HACKS
589     #ifndef HPUX10_HACKS
590     x = select(fds, (int *) &fd, (int *) NULL, (int *) NULL, &t);
591     #else
592     x = select(fds, &fd, NULL, NULL, &t);
593     #endif
594     #else
595     x = select(fds, &fd, NULL, NULL, &t);
596     #endif
597     if (x > 0) {
598     /* something happened */
599     for (i = 0; i < MAXSOCKS; i++) {
600     if ((!(socklist[i].flags & SOCK_UNUSED)) &&
601     ((FD_ISSET(socklist[i].sock, &fd)) ||
602     ((socklist[i].sock == STDOUT) && (!backgrd) &&
603     (FD_ISSET(STDIN, &fd))))) {
604     if (socklist[i].flags & (SOCK_LISTEN | SOCK_CONNECT)) {
605     /* listening socket -- don't read, just return activity */
606     /* same for connection attempt */
607     /* (for strong connections, require a read to succeed first) */
608     if (socklist[i].flags & SOCK_PROXYWAIT) { /* drummer */
609     /* hang around to get the return code from proxy */
610     grab = 10;
611     } else if (!(socklist[i].flags & SOCK_STRONGCONN)) {
612     debug1("net: connect! sock %d", socklist[i].sock);
613     s[0] = 0;
614     *len = 0;
615     return i;
616     }
617 fabian 1.3 } else if (socklist[i].flags & SOCK_PASS) {
618     s[0] = 0;
619     *len = 0;
620     return i;
621 segfault 1.1 }
622     if ((socklist[i].sock == STDOUT) && !backgrd)
623     x = read(STDIN, s, grab);
624     else
625     x = read(socklist[i].sock, s, grab);
626     if (x <= 0) { /* eof */
627     if (x == EAGAIN) {
628     s[0] = 0;
629     *len = 0;
630     return -3;
631     }
632     *len = socklist[i].sock;
633     socklist[i].flags &= ~SOCK_CONNECT;
634     debug1("net: eof!(read) socket %d", socklist[i].sock);
635     return -1;
636     }
637     s[x] = 0;
638     *len = x;
639     if (socklist[i].flags & SOCK_PROXYWAIT) {
640     debug2("net: socket: %d proxy errno: %d", socklist[i].sock, s[1]);
641     socklist[i].flags &= ~(SOCK_CONNECT | SOCK_PROXYWAIT);
642     switch (s[1]) {
643     case 90: /* success */
644     s[0] = 0;
645     *len = 0;
646     return i;
647     case 91: /* failed */
648     errno = ECONNREFUSED;
649     break;
650     case 92: /* no identd */
651     case 93: /* identd said wrong username */
652     errno = ENETUNREACH;
653     break;
654     /* a better error message would be "socks misconfigured" */
655     /* or "identd not working" but this is simplest */
656     }
657     *len = socklist[i].sock;
658     return -1;
659     }
660     return i;
661     }
662     }
663     } else if (x == -1)
664     return -2; /* socket error */
665     else {
666     s[0] = 0;
667     *len = 0;
668     }
669     return -3;
670     }
671    
672     /* sockgets: buffer and read from sockets
673     *
674     * attempts to read from all registered sockets for up to one second. if
675     * after one second, no complete data has been received from any of the
676     * sockets, 's' will be empty, 'len' will be 0, and sockgets will return -3.
677     * if there is returnable data received from a socket, the data will be
678     * in 's' (null-terminated if non-binary), the length will be returned
679     * in len, and the socket number will be returned.
680     * normal sockets have their input buffered, and each call to sockgets
681     * will return one line terminated with a '\n'. binary sockets are not
682     * buffered and return whatever coems in as soon as it arrives.
683     * listening sockets will return an empty string when a connection comes in.
684     * connecting sockets will return an empty string on a successful connect,
685     * or EOF on a failed connect.
686     * if an EOF is detected from any of the sockets, that socket number will be
687     * put in len, and -1 will be returned.
688     * the maximum length of the string returned is 512 (including null)
689     */
690    
691     int sockgets(char *s, int *len)
692     {
693     char xx[514], *p, *px;
694     int ret, i, data = 0;
695    
696 fabian 1.9 Context;
697 segfault 1.1 for (i = 0; i < MAXSOCKS; i++) {
698     /* check for stored-up data waiting to be processed */
699     if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].inbuf != NULL)) {
700     /* look for \r too cos windows can't follow RFCs */
701     p = strchr(socklist[i].inbuf, '\n');
702     if (p == NULL)
703     p = strchr(socklist[i].inbuf, '\r');
704     if (p != NULL) {
705     *p = 0;
706     if (strlen(socklist[i].inbuf) > 510)
707     socklist[i].inbuf[510] = 0;
708     strcpy(s, socklist[i].inbuf);
709     px = (char *) nmalloc(strlen(p + 1) + 1);
710     strcpy(px, p + 1);
711     nfree(socklist[i].inbuf);
712     if (px[0])
713     socklist[i].inbuf = px;
714     else {
715     nfree(px);
716     socklist[i].inbuf = NULL;
717     }
718     /* strip CR if this was CR/LF combo */
719     if (s[strlen(s) - 1] == '\r')
720     s[strlen(s) - 1] = 0;
721     *len = strlen(s);
722     return socklist[i].sock;
723     }
724     }
725     /* also check any sockets that might have EOF'd during write */
726     if (!(socklist[i].flags & SOCK_UNUSED)
727     && (socklist[i].flags & SOCK_EOFD)) {
728 fabian 1.9 Context;
729 segfault 1.1 s[0] = 0;
730     *len = socklist[i].sock;
731     return -1;
732     }
733     }
734     /* no pent-up data of any worth -- down to business */
735 fabian 1.9 Context;
736 segfault 1.1 *len = 0;
737     ret = sockread(xx, len);
738     if (ret < 0) {
739     s[0] = 0;
740     return ret;
741     }
742     /* binary and listening sockets don't get buffered */
743 fabian 1.3 /* passed on sockets don't get buffered either (Fabian)*/
744 segfault 1.1 if (socklist[ret].flags & SOCK_CONNECT) {
745     if (socklist[ret].flags & SOCK_STRONGCONN) {
746     socklist[ret].flags &= ~SOCK_STRONGCONN;
747     /* buffer any data that came in, for future read */
748     socklist[ret].inbuf = (char *) nmalloc(strlen(xx) + 1);
749     strcpy(socklist[ret].inbuf, xx);
750     }
751     socklist[ret].flags &= ~SOCK_CONNECT;
752     s[0] = 0;
753     return socklist[ret].sock;
754     }
755     if (socklist[ret].flags & SOCK_BINARY) {
756     my_memcpy(s, xx, *len);
757     return socklist[ret].sock;
758     }
759 fabian 1.3 if ((socklist[ret].flags & SOCK_LISTEN) ||
760     (socklist[ret].flags & SOCK_PASS))
761 segfault 1.1 return socklist[ret].sock;
762 fabian 1.9 Context;
763 segfault 1.1 /* might be necessary to prepend stored-up data! */
764     if (socklist[ret].inbuf != NULL) {
765     p = socklist[ret].inbuf;
766     socklist[ret].inbuf = (char *) nmalloc(strlen(p) + strlen(xx) + 1);
767     strcpy(socklist[ret].inbuf, p);
768     strcat(socklist[ret].inbuf, xx);
769     nfree(p);
770     if (strlen(socklist[ret].inbuf) < 512) {
771     strcpy(xx, socklist[ret].inbuf);
772     nfree(socklist[ret].inbuf);
773     socklist[ret].inbuf = NULL;
774     } else {
775     p = socklist[ret].inbuf;
776     socklist[ret].inbuf = (char *) nmalloc(strlen(p) - 509);
777     strcpy(socklist[ret].inbuf, p + 510);
778     *(p + 510) = 0;
779     strcpy(xx, p);
780     nfree(p);
781     /* (leave the rest to be post-pended later) */
782     }
783     }
784 fabian 1.9 Context;
785 segfault 1.1 /* look for EOL marker; if it's there, i have something to show */
786     p = strchr(xx, '\n');
787     if (p == NULL)
788     p = strchr(xx, '\r');
789     if (p != NULL) {
790     *p = 0;
791     strcpy(s, xx);
792     strcpy(xx, p + 1);
793     if (s[strlen(s) - 1] == '\r')
794     s[strlen(s) - 1] = 0;
795     data = 1; /* DCC_CHAT may now need to process a
796     * blank line */
797     /* NO! */
798     /* if (!s[0]) strcpy(s," "); */
799     } else {
800     s[0] = 0;
801     if (strlen(xx) >= 510) {
802     /* string is too long, so just insert fake \n */
803     strcpy(s, xx);
804     xx[0] = 0;
805     data = 1;
806     }
807     }
808 fabian 1.9 Context;
809 segfault 1.1 *len = strlen(s);
810     /* anything left that needs to be saved? */
811     if (!xx[0]) {
812     if (data)
813     return socklist[ret].sock;
814     else
815     return -3;
816     }
817 fabian 1.9 Context;
818 segfault 1.1 /* prepend old data back */
819     if (socklist[ret].inbuf != NULL) {
820 fabian 1.9 Context;
821 segfault 1.1 p = socklist[ret].inbuf;
822     socklist[ret].inbuf = (char *) nmalloc(strlen(p) + strlen(xx) + 1);
823     strcpy(socklist[ret].inbuf, xx);
824     strcat(socklist[ret].inbuf, p);
825     nfree(p);
826     } else {
827 fabian 1.9 Context;
828 segfault 1.1 socklist[ret].inbuf = (char *) nmalloc(strlen(xx) + 1);
829     strcpy(socklist[ret].inbuf, xx);
830     }
831 fabian 1.9 Context;
832 segfault 1.1 if (data) {
833 fabian 1.9 Context;
834 segfault 1.1 return socklist[ret].sock;
835     } else {
836 fabian 1.9 Context;
837 segfault 1.1 return -3;
838     }
839     }
840    
841     /* dump something to a socket */
842     /* DO NOT PUT CONTEXTS IN HERE IF YOU WANT DEBUG TO BE MEANINGFUL!!! */
843     void tputs(int z, char *s, unsigned int len)
844     {
845     int i, x;
846     char *p;
847    
848     if (z < 0)
849     return; /* um... HELLO?! sanity check please! */
850     if (((z == STDOUT) || (z == STDERR)) && (!backgrd || use_stderr)) {
851     write(z, s, len);
852     return;
853     }
854     for (i = 0; i < MAXSOCKS; i++) {
855     if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == z)) {
856     if (socklist[i].outbuf != NULL) {
857     /* already queueing: just add it */
858     p = (char *) nrealloc(socklist[i].outbuf, socklist[i].outbuflen + len);
859     my_memcpy(p + socklist[i].outbuflen, s, len);
860     socklist[i].outbuf = p;
861     socklist[i].outbuflen += len;
862     return;
863     }
864     /* try. */
865     x = write(z, s, len);
866     if (x == (-1))
867     x = 0;
868     if (x < len) {
869     /* socket is full, queue it */
870     socklist[i].outbuf = (char *) nmalloc(len - x);
871     my_memcpy(socklist[i].outbuf, &s[x], len - x);
872     socklist[i].outbuflen = len - x;
873     }
874     return;
875     }
876     }
877     putlog(LOG_MISC, "*", "!!! writing to nonexistent socket: %d", z);
878     s[strlen(s) - 1] = 0;
879     putlog(LOG_MISC, "*", "!-> '%s'", s);
880     }
881    
882     /* tputs might queue data for sockets, let's dump as much of it as
883     * possible */
884     void dequeue_sockets()
885     {
886     int i, x;
887    
888     for (i = 0; i < MAXSOCKS; i++) {
889     if (!(socklist[i].flags & SOCK_UNUSED) &&
890     (socklist[i].outbuf != NULL)) {
891     /* trick tputs into doing the work */
892     x = write(socklist[i].sock, socklist[i].outbuf,
893     socklist[i].outbuflen);
894     if ((x < 0) && (errno != EAGAIN)
895     #ifdef EBADSLT
896     && (errno != EBADSLT)
897     #endif
898     #ifdef ENOTCONN
899     && (errno != ENOTCONN)
900     #endif
901     ) {
902     /* this detects an EOF during writing */
903     debug3("net: eof!(write) socket %d (%s,%d)", socklist[i].sock,
904     strerror(errno), errno);
905     socklist[i].flags |= SOCK_EOFD;
906     } else if (x == socklist[i].outbuflen) {
907     /* if the whole buffer was sent, nuke it */
908     nfree(socklist[i].outbuf);
909     socklist[i].outbuf = NULL;
910     socklist[i].outbuflen = 0;
911     } else if (x > 0) {
912     char *p = socklist[i].outbuf;
913    
914     /* this removes any sent bytes from the beginning of the buffer */
915     socklist[i].outbuf = (char *) nmalloc(socklist[i].outbuflen - x);
916     my_memcpy(socklist[i].outbuf, p + x, socklist[i].outbuflen - x);
917     socklist[i].outbuflen -= x;
918     nfree(p);
919     }
920     }
921     }
922     }
923    
924     /* DEBUGGING STUFF */
925    
926     void tell_netdebug(int idx)
927     {
928     int i;
929     char s[80];
930    
931     dprintf(idx, "Open sockets:");
932     for (i = 0; i < MAXSOCKS; i++) {
933     if (!(socklist[i].flags & SOCK_UNUSED)) {
934     sprintf(s, " %d", socklist[i].sock);
935     if (socklist[i].flags & SOCK_BINARY)
936     strcat(s, " (binary)");
937     if (socklist[i].flags & SOCK_LISTEN)
938     strcat(s, " (listen)");
939 fabian 1.3 if (socklist[i].flags & SOCK_PASS)
940     strcat(s, " (passed on)");
941 segfault 1.1 if (socklist[i].flags & SOCK_CONNECT)
942     strcat(s, " (connecting)");
943     if (socklist[i].flags & SOCK_STRONGCONN)
944     strcat(s, " (strong)");
945     if (socklist[i].flags & SOCK_NONSOCK)
946     strcat(s, " (file)");
947     if (socklist[i].inbuf != NULL)
948     sprintf(&s[strlen(s)], " (inbuf: %04X)", strlen(socklist[i].inbuf));
949     if (socklist[i].outbuf != NULL)
950     sprintf(&s[strlen(s)], " (outbuf: %06lX)", socklist[i].outbuflen);
951     strcat(s, ",");
952     dprintf(idx, "%s", s);
953     }
954     }
955     dprintf(idx, " done.\n");
956     }
957    
958     /* Security-flavoured sanity checking on DCC connections of all sorts can be
959     * done with this routine. Feed it the proper information from your DCC
960     * before you attempt the connection, and this will make an attempt at
961     * figuring out if the connection is really that person, or someone screwing
962     * around. It's not foolproof, but anything that fails this check probably
963     * isn't going to work anyway due to masquerading firewalls, NAT routers,
964     * or bugs in mIRC. */
965     int sanitycheck_dcc(char *nick, char *from, char *ipaddy, char *port)
966     {
967     /* According to the latest RFC, the clients SHOULD be able to handle
968     * DNS names that are up to 255 characters long. This is not broken. */
969 fabian 1.3 char badaddress[16];
970 segfault 1.1 IP ip = my_atoul(ipaddy);
971     int prt = atoi(port);
972    
973     /* It is disabled HERE so we only have to check in *one* spot! */
974     if (!dcc_sanitycheck)
975     return 1;
976 fabian 1.9 Context; /* This should be pretty solid, but
977 segfault 1.1 * something _might_ break. */
978     if (prt < 1) {
979     putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an impossible port of %u!",
980     nick, from, prt);
981     return 0;
982     }
983 fabian 1.3 sprintf(badaddress, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff,
984     (ip >> 8) & 0xff, ip & 0xff);
985 segfault 1.1 if (ip < (1 << 24)) {
986     putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an impossible IP of %s!",
987     nick, from, badaddress);
988     return 0;
989     }
990 fabian 1.3 return 1;
991     }
992    
993     int hostsanitycheck_dcc(char *nick, char *from, IP ip, char *dnsname,
994     char *prt)
995     {
996     /* According to the latest RFC, the clients SHOULD be able to handle
997     * DNS names that are up to 255 characters long. This is not broken. */
998     char hostname[256], badaddress[16];
999    
1000     /* It is disabled HERE so we only have to check in *one* spot! */
1001     if (!dcc_sanitycheck)
1002     return 1;
1003 fabian 1.9 Context; /* This should be pretty solid, but
1004 fabian 1.3 * something _might_ break. */
1005     sprintf(badaddress, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff,
1006     (ip >> 8) & 0xff, ip & 0xff);
1007 segfault 1.1 /* These should pad like crazy with zeros, since 120 bytes or so is
1008     * where the routines providing our data currently lose interest. I'm
1009     * using the n-variant in case someone changes that... */
1010 fabian 1.7 strncpy(hostname, extracthostname(from), 255);
1011     hostname[255] = 0;
1012 segfault 1.1 if (!strcasecmp(hostname, dnsname)) {
1013     putlog(LOG_DEBUG, "*", "DNS information for submitted IP checks out.");
1014     return 1;
1015     }
1016     if (!strcmp(badaddress, dnsname))
1017     putlog(LOG_MISC, "*", "ALERT: (%s!%s) sent a DCC request with bogus IP information of %s port %u!",
1018     nick, from, badaddress, prt);
1019     else
1020     return 1; /* <- usually happens when we have
1021     a user with an unresolved hostmask! */
1022     return 0;
1023     }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23