/[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.28 - (hide annotations) (download) (as text)
Sat Dec 23 06:11:34 2000 UTC (18 years, 6 months ago) by guppy
Branch: MAIN
Changes since 1.27: +3 -3 lines
File MIME type: text/x-chdr
ITE's trafficfix patch (slightly modified to fix a compiler warning and a problem in net.c dealing with extern)

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23