/[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.26 - (hide annotations) (download) (as text)
Mon Oct 30 20:49:46 2000 UTC (18 years, 7 months ago) by fabian
Branch: MAIN
Changes since 1.25: +8 -9 lines
File MIME type: text/x-chdr
fabian: applied drummer's sun_firewall_fix patch (net.c.patch)

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23