/[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.38 - (hide annotations) (download) (as text)
Mon Aug 13 14:51:12 2001 UTC (18 years, 2 months ago) by guppy
Branch: MAIN
Changes since 1.37: +1 -70 lines
File MIME type: text/x-chdr
Removed dcc-sanitycheck since it was half commented out as "FIXME" -- also, in the day and age of IRC bouncers and socks5 connections, etc .. more and more people are hiding behind another machine and this setting wouldn't allow them to dcc chat into bots if turned on. As for security concerns with people being able to redirect a bot to connect elsewhere .. they cannot redirect the bot to connect to a port below 1024 -- dw had a suggestion ... if the ip being sent in the dcc is known, let them dcc chat into the bot .. I like this suggestion, what about the others?

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.38 * $Id: net.c,v 1.37 2001/08/08 14:06:00 drummer 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 drummer 1.33 #include "adns/adns.h"
30    
31 segfault 1.1 #if !HAVE_GETDTABLESIZE
32 fabian 1.16 # ifdef FD_SETSIZE
33     # define getdtablesize() FD_SETSIZE
34     # else
35     # define getdtablesize() 200
36     # endif
37 segfault 1.1 #endif
38    
39 drummer 1.33 #ifndef IN6_IS_ADDR_V4MAPPED
40     # define IN6_IS_ADDR_V4MAPPED(a) \
41     ((((uint32_t *) (a))[0] == 0) && (((uint32_t *) (a))[1] == 0) && \
42     (((uint32_t *) (a))[2] == htonl (0xffff)))
43     #endif
44    
45 fabian 1.16 extern struct dcc_t *dcc;
46 guppy 1.28 extern int backgrd, use_stderr, resolve_timeout, dcc_total;
47     extern unsigned long otraffic_irc_today, otraffic_bn_today,
48 fabian 1.16 otraffic_dcc_today, otraffic_filesys_today,
49     otraffic_trans_today, otraffic_unknown_today;
50 drummer 1.33 extern char natip[];
51 fabian 1.16
52     char hostname[121] = ""; /* Hostname can be specified in the config
53     file */
54     char myip[121] = ""; /* IP can be specified in the config file */
55 drummer 1.33 char myip6[121] = ""; /* IP6 can be specified in the config file */
56 fabian 1.16 char firewall[121] = ""; /* Socks server for firewall */
57     int firewallport = 1080; /* Default port of Sock4/5 firewalls */
58     char botuser[21] = "eggdrop"; /* Username of the user running the bot */
59     sock_list *socklist = NULL; /* Enough to be safe */
60     int MAXSOCKS = 0;
61     jmp_buf alarmret; /* Env buffer for alarm() returns */
62 segfault 1.1
63 drummer 1.33 adns_state ads;
64    
65 fabian 1.16 /* Types of proxy */
66 segfault 1.1 #define PROXY_SOCKS 1
67     #define PROXY_SUN 2
68    
69    
70 fabian 1.16 /* I need an UNSIGNED long for dcc type stuff
71     */
72 segfault 1.1 IP my_atoul(char *s)
73     {
74     IP ret = 0;
75    
76     while ((*s >= '0') && (*s <= '9')) {
77     ret *= 10;
78     ret += ((*s) - '0');
79     s++;
80     }
81     return ret;
82     }
83    
84 fabian 1.16 /* Initialize the socklist
85     */
86 segfault 1.1 void init_net()
87     {
88     int i;
89    
90     for (i = 0; i < MAXSOCKS; i++) {
91     socklist[i].flags = SOCK_UNUSED;
92     }
93 drummer 1.33
94     /* init ADNS */
95     i = adns_init(&ads, adns_if_noautosys, 0);
96     if (i)
97     fatal(adns_strerror(i), 0);
98 segfault 1.1 }
99    
100     int expmem_net()
101     {
102     int i, tot = 0;
103    
104     for (i = 0; i < MAXSOCKS; i++) {
105     if (!(socklist[i].flags & SOCK_UNUSED)) {
106     if (socklist[i].inbuf != NULL)
107     tot += strlen(socklist[i].inbuf) + 1;
108     if (socklist[i].outbuf != NULL)
109     tot += socklist[i].outbuflen;
110     }
111     }
112     return tot;
113     }
114    
115 fabian 1.16 /* Get my ip number
116     */
117 segfault 1.1 IP getmyip()
118     {
119     struct hostent *hp;
120     char s[121];
121     IP ip;
122     struct in_addr *in;
123    
124 fabian 1.16 /* Could be pre-defined */
125 segfault 1.1 if (myip[0]) {
126     if ((myip[strlen(myip) - 1] >= '0') && (myip[strlen(myip) - 1] <= '9'))
127     return (IP) inet_addr(myip);
128     }
129 fabian 1.16 /* Also could be pre-defined */
130 segfault 1.1 if (hostname[0])
131     hp = gethostbyname(hostname);
132     else {
133     gethostname(s, 120);
134     hp = gethostbyname(s);
135     }
136     if (hp == NULL)
137     fatal("Hostname self-lookup failed.", 0);
138     in = (struct in_addr *) (hp->h_addr_list[0]);
139     ip = (IP) (in->s_addr);
140     return ip;
141     }
142    
143 drummer 1.33 #ifdef IPV6
144     struct in6_addr getmyip6()
145     {
146     struct in6_addr ip;
147    
148     /* Could be pre-defined */
149     if (myip6[0])
150     egg_inet_pton(AF_INET6, myip6, &ip);
151     else {
152     /* get system's default IPv6 ip -- FIXME!! */
153     /* there is know way?! - drummer */
154     ip = in6addr_any;
155     }
156     return ip;
157     }
158    
159     struct in6_addr ipv4to6(IP a)
160     {
161     struct in6_addr ip;
162     if (a == INADDR_ANY)
163     return in6addr_any;
164     else {
165     ((uint32_t *)&ip)[0] = 0;
166     ((uint32_t *)&ip)[1] = 0;
167     ((uint16_t *)&ip)[4] = 0;
168     ((uint16_t *)&ip)[5] = 0xffff;
169     ((uint32_t *)&ip)[3] = a;
170     }
171     return ip;
172     }
173    
174     #endif
175    
176 segfault 1.1 void neterror(char *s)
177     {
178     switch (errno) {
179     case EADDRINUSE:
180     strcpy(s, "Address already in use");
181     break;
182     case EADDRNOTAVAIL:
183     strcpy(s, "Address invalid on remote machine");
184     break;
185     case EAFNOSUPPORT:
186     strcpy(s, "Address family not supported");
187     break;
188     case EALREADY:
189     strcpy(s, "Socket already in use");
190     break;
191     case EBADF:
192     strcpy(s, "Socket descriptor is bad");
193     break;
194     case ECONNREFUSED:
195     strcpy(s, "Connection refused");
196     break;
197     case EFAULT:
198     strcpy(s, "Namespace segment violation");
199     break;
200     case EINPROGRESS:
201     strcpy(s, "Operation in progress");
202     break;
203     case EINTR:
204     strcpy(s, "Timeout");
205     break;
206     case EINVAL:
207     strcpy(s, "Invalid namespace");
208     break;
209     case EISCONN:
210     strcpy(s, "Socket already connected");
211     break;
212     case ENETUNREACH:
213     strcpy(s, "Network unreachable");
214     break;
215     case ENOTSOCK:
216     strcpy(s, "File descriptor, not a socket");
217     break;
218     case ETIMEDOUT:
219     strcpy(s, "Connection timed out");
220     break;
221     case ENOTCONN:
222     strcpy(s, "Socket is not connected");
223     break;
224     case EHOSTUNREACH:
225     strcpy(s, "Host is unreachable");
226     break;
227     case EPIPE:
228     strcpy(s, "Broken pipe");
229     break;
230     #ifdef ECONNRESET
231     case ECONNRESET:
232     strcpy(s, "Connection reset by peer");
233     break;
234     #endif
235     #ifdef EACCES
236     case EACCES:
237     strcpy(s, "Permission denied");
238     break;
239     #endif
240     case 0:
241     strcpy(s, "Error 0");
242     break;
243     default:
244     sprintf(s, "Unforseen error %d", errno);
245     break;
246     }
247     }
248    
249 fabian 1.25 /* Sets/Unsets options for a specific socket.
250     *
251     * Returns: 0 - on success
252     * -1 - socket not found
253     * -2 - illegal operation
254     */
255     int sockoptions(int sock, int operation, int sock_options)
256     {
257     int i;
258    
259     for (i = 0; i < MAXSOCKS; i++)
260 poptix 1.30 if ((socklist[i].sock == sock) && !(socklist[i].flags & SOCK_UNUSED)) {
261 fabian 1.25 if (operation == EGG_OPTION_SET)
262     socklist[i].flags |= sock_options;
263     else if (operation == EGG_OPTION_UNSET)
264     socklist[i].flags &= ~sock_options;
265     else
266     return -2;
267     return 0;
268     }
269     return -1;
270     }
271    
272 fabian 1.16 /* Return a free entry in the socket entry
273     */
274 fabian 1.3 int allocsock(int sock, int options)
275 segfault 1.1 {
276     int i;
277    
278     for (i = 0; i < MAXSOCKS; i++) {
279     if (socklist[i].flags & SOCK_UNUSED) {
280     /* yay! there is table space */
281     socklist[i].inbuf = socklist[i].outbuf = NULL;
282 fabian 1.25 socklist[i].inbuflen = socklist[i].outbuflen = 0;
283 segfault 1.1 socklist[i].flags = options;
284     socklist[i].sock = sock;
285 fabian 1.3 return i;
286     }
287     }
288     fatal("Socket table is full!", 0);
289 fabian 1.16 return -1; /* Never reached */
290 fabian 1.3 }
291    
292 fabian 1.16 /* Request a normal socket for i/o
293     */
294 fabian 1.3 void setsock(int sock, int options)
295     {
296     int i = allocsock(sock, options);
297     int parm;
298    
299 fabian 1.16 if (((sock != STDOUT) || backgrd) &&
300     !(socklist[i].flags & SOCK_NONSOCK)) {
301     parm = 1;
302 fabian 1.3 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *) &parm, sizeof(int));
303 segfault 1.1
304 fabian 1.16 parm = 0;
305     setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &parm, sizeof(int));
306     }
307     if (options & SOCK_LISTEN) {
308     /* Tris says this lets us grab the same port again next time */
309     parm = 1;
310     setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &parm, sizeof(int));
311     }
312     /* Yay async i/o ! */
313     fcntl(sock, F_SETFL, O_NONBLOCK);
314 segfault 1.1 }
315    
316     int getsock(int options)
317     {
318 drummer 1.33 #ifdef IPV6
319     int sock = socket(AF_INET6, SOCK_STREAM, 0);
320     #else
321 segfault 1.1 int sock = socket(AF_INET, SOCK_STREAM, 0);
322 drummer 1.33 #endif
323 segfault 1.1
324 fabian 1.24 if (sock >= 0)
325     setsock(sock, options);
326     else
327     putlog(LOG_MISC, "*", "Warning: Can't create new socket!");
328 segfault 1.1 return sock;
329     }
330    
331 fabian 1.16 /* Done with a socket
332     */
333 fabian 1.24 void killsock(register int sock)
334 segfault 1.1 {
335 fabian 1.24 register int i;
336 segfault 1.1
337 fabian 1.24 /* Ignore invalid sockets. */
338     if (sock < 0)
339     return;
340 segfault 1.1 for (i = 0; i < MAXSOCKS; i++) {
341 fabian 1.2 if ((socklist[i].sock == sock) && !(socklist[i].flags & SOCK_UNUSED)) {
342 segfault 1.1 close(socklist[i].sock);
343     if (socklist[i].inbuf != NULL) {
344     nfree(socklist[i].inbuf);
345     socklist[i].inbuf = NULL;
346     }
347     if (socklist[i].outbuf != NULL) {
348     nfree(socklist[i].outbuf);
349     socklist[i].outbuf = NULL;
350     socklist[i].outbuflen = 0;
351     }
352     socklist[i].flags = SOCK_UNUSED;
353     return;
354     }
355     }
356     putlog(LOG_MISC, "*", "Attempt to kill un-allocated socket %d !!", sock);
357     }
358    
359 fabian 1.16 /* Send connection request to proxy
360     */
361 segfault 1.1 static int proxy_connect(int sock, char *host, int port, int proxy)
362     {
363     unsigned char x[10];
364     struct hostent *hp;
365 fabian 1.26 char s[256];
366 segfault 1.1 int i;
367    
368     /* socks proxy */
369     if (proxy == PROXY_SOCKS) {
370     /* numeric IP? */
371 fabian 1.26 if (host[strlen(host) - 1] >= '0' && host[strlen(host) - 1] <= '9') {
372 segfault 1.1 IP ip = ((IP) inet_addr(host)); /* drummer */
373 fabian 1.18 egg_memcpy(x, &ip, 4); /* Beige@Efnet */
374 segfault 1.1 } else {
375     /* no, must be host.domain */
376     if (!setjmp(alarmret)) {
377     alarm(resolve_timeout);
378     hp = gethostbyname(host);
379     alarm(0);
380     } else {
381     hp = NULL;
382     }
383     if (hp == NULL) {
384     killsock(sock);
385     return -2;
386     }
387 fabian 1.18 egg_memcpy(x, hp->h_addr, hp->h_length);
388 segfault 1.1 }
389 drummer 1.37 for (i = 0; i < MAXSOCKS; i++)
390     if (!(socklist[i].flags & SOCK_UNUSED) && socklist[i].sock == sock)
391     socklist[i].flags |= SOCK_PROXYWAIT; /* drummer */
392 fabian 1.26 egg_snprintf(s, sizeof s, "\004\001%c%c%c%c%c%c%s", (port >> 8) % 256,
393     (port % 256), x[0], x[1], x[2], x[3], botuser);
394 segfault 1.1 tputs(sock, s, strlen(botuser) + 9); /* drummer */
395     } else if (proxy == PROXY_SUN) {
396 drummer 1.37 egg_snprintf(s, sizeof s, "%s %d\n", host, port);
397 segfault 1.1 tputs(sock, s, strlen(s)); /* drummer */
398     }
399     return sock;
400     }
401    
402 fabian 1.16 /* Starts a connection attempt to a socket
403 fabian 1.11 *
404 fabian 1.3 * If given a normal hostname, this will be resolved to the corresponding
405     * IP address first. PLEASE try to use the non-blocking dns functions
406     * instead and then call this function with the IP address to avoid blocking.
407 fabian 1.11 *
408 segfault 1.1 * returns <0 if connection refused:
409     * -1 neterror() type error
410 fabian 1.16 * -2 can't resolve hostname
411     */
412 segfault 1.1 int open_telnet_raw(int sock, char *server, int sport)
413     {
414 drummer 1.33 #ifdef IPV6
415     struct sockaddr_in6 name, vname;
416     #else
417     struct sockaddr_in name, vname;
418     #endif
419 segfault 1.1 struct hostent *hp;
420     char host[121];
421     int i, port;
422     volatile int proxy;
423    
424 drummer 1.33 debug2("|NET| open_telnet_raw: %s %d", server, sport);
425    
426 segfault 1.1 /* firewall? use socks */
427     if (firewall[0]) {
428     if (firewall[0] == '!') {
429     proxy = PROXY_SUN;
430     strcpy(host, &firewall[1]);
431     } else {
432     proxy = PROXY_SOCKS;
433     strcpy(host, firewall);
434     }
435     port = firewallport;
436     } else {
437     proxy = 0;
438     strcpy(host, server);
439     port = sport;
440     }
441    
442 drummer 1.33 egg_bzero((char *) &name, sizeof name);
443     #ifdef IPV6
444     name.sin6_family = AF_INET6;
445     name.sin6_port = htons(port);
446     #else
447 segfault 1.1 name.sin_family = AF_INET;
448 drummer 1.33 name.sin_port = htons(port);
449     #endif
450    
451     if (!setjmp(alarmret)) {
452     char *p;
453     int type;
454    
455     alarm(resolve_timeout);
456 segfault 1.1
457 drummer 1.33 if (!egg_strncasecmp("ipv6%", host, 5)) {
458     type = AF_INET6;
459     p = host + 5;
460     debug1("|NET| checking only AAAA record for %s", p);
461     } else if (!egg_strncasecmp("ipv4%", host, 5)) {
462     type = AF_INET;
463     p = host + 5;
464     debug1("|NET| checking only A record for %s", p);
465     } else {
466     type = AF_INET; /* af_preferred */
467     p = host;
468     }
469 segfault 1.1 alarm(resolve_timeout);
470 drummer 1.33 #ifndef IPV6
471     hp = gethostbyname(p);
472     #else
473     hp = gethostbyname2(p, type);
474     if (!hp && (p == host))
475     hp = gethostbyname2(p, (type == AF_INET6 ? AF_INET : AF_INET6));
476     #endif
477 segfault 1.1 alarm(0);
478 drummer 1.33 } else {
479 segfault 1.1 hp = NULL;
480 drummer 1.33 }
481     if (hp == NULL)
482 segfault 1.1 return -2;
483 drummer 1.33
484     #ifndef IPV6
485     egg_memcpy(&name.sin_addr, hp->h_addr, hp->h_length);
486     name.sin_family = hp->h_addrtype;
487     #else
488     if (hp->h_addrtype == AF_INET6)
489     egg_memcpy(&name.sin6_addr, hp->h_addr, hp->h_length);
490     else if (hp->h_addrtype == AF_INET)
491     name.sin6_addr = ipv4to6(*((unsigned int*) hp->h_addr));
492     else
493     return -123; /* panic :P */
494     name.sin6_family = AF_INET6;
495     #endif
496    
497     egg_bzero((char *) &vname, sizeof vname);
498     #ifndef IPV6
499     vname.sin_family = AF_INET;
500     vname.sin_addr.s_addr = (myip[0] ? getmyip() : INADDR_ANY);
501     #else
502     vname.sin6_family = AF_INET6;
503 drummer 1.35 if (IN6_IS_ADDR_V4MAPPED(&name.sin6_addr))
504 drummer 1.33 vname.sin6_addr = ipv4to6(myip[0] ? getmyip() : INADDR_ANY);
505     else
506     vname.sin6_addr = (myip6[0] ? getmyip6() : in6addr_any);
507     #endif
508     if (bind(sock, (struct sockaddr *) &vname, sizeof vname) < 0)
509     return -1;
510    
511 segfault 1.1 for (i = 0; i < MAXSOCKS; i++) {
512     if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == sock))
513 fabian 1.17 socklist[i].flags = (socklist[i].flags & ~SOCK_VIRTUAL) | SOCK_CONNECT;
514 segfault 1.1 }
515 drummer 1.33 if (connect(sock, (struct sockaddr *) &name, (sizeof name)) < 0) {
516 segfault 1.1 if (errno == EINPROGRESS) {
517 fabian 1.16 /* Firewall? announce connect attempt to proxy */
518 segfault 1.1 if (firewall[0])
519     return proxy_connect(sock, server, sport, proxy);
520     return sock; /* async success! */
521 fabian 1.4 } else
522 segfault 1.1 return -1;
523     }
524 fabian 1.16 /* Synchronous? :/ */
525 segfault 1.1 if (firewall[0])
526     return proxy_connect(sock, server, sport, proxy);
527     return sock;
528     }
529    
530 fabian 1.16 /* Ordinary non-binary connection attempt */
531 segfault 1.1 int open_telnet(char *server, int port)
532     {
533 fabian 1.4 int sock = getsock(0),
534     ret = open_telnet_raw(sock, server, port);
535    
536     if (ret < 0)
537     killsock(sock);
538     return ret;
539 segfault 1.1 }
540    
541 fabian 1.16 /* Returns a socket number for a listening socket that will accept any
542 fabian 1.19 * connection on a certain address -- port # is returned in port
543 drummer 1.33 * "" means on any address
544 fabian 1.16 */
545 drummer 1.33 int open_address_listen(char *addr, int *port)
546 segfault 1.1 {
547 fabian 1.13 int sock;
548     unsigned int addrlen;
549 drummer 1.33 #ifdef IPV6
550     struct sockaddr_in6 name;
551     #else
552 segfault 1.1 struct sockaddr_in name;
553 drummer 1.33 #endif
554 segfault 1.1
555     if (firewall[0]) {
556     /* FIXME: can't do listen port thru firewall yet */
557 fabian 1.6 putlog(LOG_MISC, "*", "!! Cant open a listen port (you are using a firewall)");
558 segfault 1.1 return -1;
559     }
560 fabian 1.24
561 segfault 1.1 sock = getsock(SOCK_LISTEN);
562 fabian 1.24 if (sock < 1)
563     return -1;
564 drummer 1.33
565     debug2("|NET| open_address_listen(\"%s\", %d)", addr, *port);
566 fabian 1.24
567 drummer 1.33 egg_bzero((char *) &name, sizeof name);
568     #ifdef IPV6
569     name.sin6_family = AF_INET6;
570     name.sin6_port = htons(*port); /* 0 = just assign us a port */
571     if (!addr[0])
572     name.sin6_addr = in6addr_any;
573     else if (!egg_inet_pton(AF_INET6, addr, &name.sin6_addr)) {
574     struct in_addr a4;
575     if (egg_inet_aton(addr, &a4))
576     name.sin6_addr = ipv4to6(a4.s_addr);
577     else
578     name.sin6_addr = in6addr_any;
579     }
580     #else
581 segfault 1.1 name.sin_family = AF_INET;
582 fabian 1.19 name.sin_port = htons(*port); /* 0 = just assign us a port */
583 drummer 1.33 if (addr[0])
584     egg_inet_aton(addr, &name.sin_addr);
585     else
586     name.sin_addr.s_addr = INADDR_ANY;
587     #endif
588     if (bind(sock, (struct sockaddr *) &name, sizeof name) < 0) {
589 segfault 1.1 killsock(sock);
590 guppy 1.29 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT)
591     return -2;
592     else
593     return -1;
594 segfault 1.1 }
595     /* what port are we on? */
596 drummer 1.33 addrlen = sizeof name;
597 segfault 1.1 if (getsockname(sock, (struct sockaddr *) &name, &addrlen) < 0) {
598     killsock(sock);
599     return -1;
600     }
601 drummer 1.33 #ifdef IPV6
602     *port = ntohs(name.sin6_port);
603     #else
604 fabian 1.19 *port = ntohs(name.sin_port);
605 drummer 1.33 #endif
606 segfault 1.1 if (listen(sock, 1) < 0) {
607     killsock(sock);
608     return -1;
609     }
610     return sock;
611 fabian 1.19 }
612    
613     /* Returns a socket number for a listening socket that will accept any
614     * connection -- port # is returned in port
615     */
616 drummer 1.33 inline int open_listen(int *port, int af)
617 fabian 1.19 {
618 drummer 1.33 if (af == AF_INET)
619     return open_address_listen(myip, port);
620     #ifdef IPV6
621     else if (af == AF_INET6)
622     return open_address_listen(myip6, port);
623     #endif
624     else
625     return -1;
626 segfault 1.1 }
627    
628 fabian 1.3 /* Given a network-style IP address, returns the hostname. The hostname
629     * will be in the "##.##.##.##" format if there was an error.
630     *
631     * NOTE: This function is depreciated. Try using the async dns approach
632 fabian 1.16 * instead.
633     */
634 segfault 1.1 char *hostnamefromip(unsigned long ip)
635     {
636     struct hostent *hp;
637     unsigned long addr = ip;
638     unsigned char *p;
639 fabian 1.3 static char s[UHOSTLEN];
640 segfault 1.1
641     if (!setjmp(alarmret)) {
642     alarm(resolve_timeout);
643     hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
644     alarm(0);
645     } else {
646     hp = NULL;
647     }
648     if (hp == NULL) {
649     p = (unsigned char *) &addr;
650     sprintf(s, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
651     return s;
652     }
653 guppy 1.27 strncpyz(s, hp->h_name, sizeof s);
654 segfault 1.1 return s;
655     }
656    
657 fabian 1.5 /* Returns the given network byte order IP address in the
658 fabian 1.16 * dotted format - "##.##.##.##"
659 drummer 1.33 * (it's IPv4 only, and it's okey - drummer)
660 fabian 1.16 */
661 fabian 1.3 char *iptostr(IP ip)
662     {
663     struct in_addr a;
664    
665     a.s_addr = ip;
666     return inet_ntoa(a);
667     }
668    
669 drummer 1.33 char *getlocaladdr(int sock)
670     {
671     static char buf[ADDRLEN];
672     #ifdef IPV6
673     struct sockaddr_in6 sa;
674     #else
675     struct sockaddr_in sa;
676     #endif
677     int len = sizeof sa;
678    
679     if (sock == -1) { /* assuming IPv4... */
680     sprintf(buf, "%lu", (unsigned long int)
681     ntohl(natip[0] ? inet_addr(natip) : getmyip()));
682     return buf;
683     }
684    
685     if (getsockname(sock, (struct sockaddr*) &sa, &len) == -1) {
686     debug1("|NET| getsockname() failed for sock %d", sock);
687     return 0;
688     }
689     #ifdef IPV6
690     if (IN6_IS_ADDR_V4MAPPED(&sa.sin6_addr))
691     sprintf(buf, "%lu",
692 drummer 1.34 (unsigned long int) ntohl(((uint32_t *)&sa.sin6_addr)[3]));
693 drummer 1.33 else
694     egg_inet_ntop(AF_INET6, &(sa.sin6_addr), buf, sizeof buf);
695     #else
696 drummer 1.36 sprintf(buf, "%lu", (unsigned long int) ntohl(sa.sin_addr.s_addr));
697 drummer 1.33 #endif
698     return buf;
699     }
700    
701 fabian 1.16 /* Short routine to answer a connect received on a socket made previously
702 segfault 1.1 * by open_listen ... returns hostname of the caller & the new socket
703 fabian 1.16 * does NOT dispose of old "public" socket!
704     */
705 drummer 1.33 int answer(int sock, char *caller, char *ip, unsigned short *port,
706 fabian 1.16 int binary)
707 segfault 1.1 {
708 fabian 1.13 int new_sock;
709     unsigned int addrlen;
710 drummer 1.33 #ifdef IPV6
711     struct sockaddr_in6 from;
712     #else
713 segfault 1.1 struct sockaddr_in from;
714 drummer 1.33 #endif
715 fabian 1.25
716 drummer 1.33 addrlen = sizeof from;
717 segfault 1.1 new_sock = accept(sock, (struct sockaddr *) &from, &addrlen);
718     if (new_sock < 0)
719     return -1;
720     if (ip != NULL) {
721 drummer 1.33 #ifdef IPV6
722 drummer 1.35 if (IN6_IS_ADDR_V4MAPPED(&from.sin6_addr))
723 drummer 1.34 egg_inet_ntop(AF_INET, &(((uint32_t *)&from.sin6_addr)[3]), ip, ADDRMAX);
724 drummer 1.33 else
725     egg_inet_ntop(AF_INET6, &(from.sin6_addr), ip, ADDRMAX);
726     #else
727     egg_inet_ntop(AF_INET, &(from.sin_addr.s_addr), ip, ADDRMAX);
728     #endif
729 fabian 1.16 /* This is now done asynchronously. We now only provide the IP address.
730     *
731 fabian 1.3 * strncpy(caller, hostnamefromip(*ip), 120);
732     */
733 drummer 1.33 strncpyz(caller, ip, 121);
734 segfault 1.1 }
735     if (port != NULL)
736 drummer 1.33 #ifdef IPV6
737     *port = ntohs(from.sin6_port);
738     #else
739 fabian 1.21 *port = ntohs(from.sin_port);
740 drummer 1.33 #endif
741 fabian 1.16 /* Set up all the normal socket crap */
742 segfault 1.1 setsock(new_sock, (binary ? SOCK_BINARY : 0));
743     return new_sock;
744     }
745    
746 fabian 1.16 /* Like open_telnet, but uses server & port specifications of dcc
747     */
748 segfault 1.1 int open_telnet_dcc(int sock, char *server, char *port)
749     {
750     int p;
751 drummer 1.33 struct in_addr ia;
752 segfault 1.1
753 drummer 1.33 debug2("|NET| open_telnet_dcc: %s %s", server, port);
754 segfault 1.1 if (port != NULL)
755     p = atoi(port);
756     else
757 drummer 1.33 return -3;
758     if (server == NULL)
759     return -3;
760     /* fix the IPv4 IP format (ie: 167772161 -> 10.0.0.1) */
761     if (egg_inet_aton(server, &ia))
762     return open_telnet_raw(sock, inet_ntoa(ia), p);
763 segfault 1.1 else
764 drummer 1.33 return open_telnet_raw(sock, server, p);
765     }
766    
767     void egg_dns_gotanswer(int status, adns_answer *aw, char *origname)
768     {
769     char name[UHOSTLEN];
770    
771     if (!aw) {
772     debug0("|DNS| egg_dns_gotanswer: ANSWER IS NULL!");
773     return;
774     }
775     if (!origname) {
776     debug0("|DNS| egg_dns_gotanswer: origname is NULL!");
777     return;
778     }
779    
780     debug2("|DNS| egg_dns_gotanswer: status=%d adns_answer=%x", status, (int)aw);
781     status = 0;
782     if ((aw->type == adns_r_addr)
783     #ifdef IPV6
784     || (aw->type == adns_r_addr6)
785     #endif
786     ) {
787     if ((aw->status == adns_s_ok) && (aw->nrrs > 0)) {
788     adns_rr_addr *rrp = aw->rrs.untyped;
789     if (rrp->addr.sa.sa_family == AF_INET) {
790     egg_inet_ntop(AF_INET, &(rrp->addr.inet.sin_addr), name, UHOSTLEN-1);
791     status = 1;
792     #ifdef IPV6
793     } else if (rrp->addr.sa.sa_family == AF_INET6) {
794     egg_inet_ntop(AF_INET6, &(rrp->addr.inet6.sin6_addr), name, UHOSTLEN-1);
795     status = 1;
796     #endif
797     }
798     #ifdef IPV6
799     } else if ((aw->type == adns_r_addr /* af_preferred */) &&
800     egg_strncasecmp(origname, "ipv6%", 5) &&
801     egg_strncasecmp(origname, "ipv4%", 5)) {
802     adns_query q6;
803     char *orign2 = (char*) nmalloc(strlen(origname) + 1);
804     strcpy(orign2, origname);
805     /* ...it may be AAAA */
806     debug1("|DNS| egg_dns_gotanswer: A failed, checking for AAAA (%s)", origname);
807     adns_submit(ads, origname, adns_r_addr6, 0, orign2, &q6);
808     status = -1;
809     #endif
810     }
811     if (status == 0)
812     strcpy(name, "0.0.0.0");
813     if (status >= 0) {
814     debug3("|DNS| egg_dns_gotanswer: (ipbyhost) host: %s ip: %s status: %d", origname, name, status);
815     call_ipbyhost(origname, name, status);
816     }
817     } else if ((aw->type == adns_r_ptr_ip6) || (aw->type == adns_r_ptr)) {
818     if ((aw->status == adns_s_ok) && (aw->nrrs > 0)) {
819     if (aw->rrs.str) {
820     strncpyz(name, *(aw->rrs.str), UHOSTLEN);
821     status = 1;
822     }
823     }
824     if (!status) {
825     if (origname)
826     strncpyz(name, origname, UHOSTLEN);
827     else
828     strcpy(name, "error");
829     }
830     debug3("|DNS| egg_dns_gotanswer: (hostbyip) ip: %s host: %s status: %d", origname, name, status);
831     call_hostbyip(origname, name, status);
832     } else
833     debug0("|DNS| egg_dns_gotanswer: got unknow type of answer ?!");
834     nfree(origname);
835     }
836    
837     void egg_dns_checkall()
838     {
839     adns_query q, r;
840     adns_answer *answer;
841     char *origname;
842    
843     adns_forallqueries_begin(ads);
844     while ((q = adns_forallqueries_next(ads, (void **)&r)) != NULL) {
845     switch (adns_check(ads, &q, &answer, (void **)&origname)) {
846     case 0: /* ok */
847     egg_dns_gotanswer(1, answer, origname);
848     break;
849     case EAGAIN: /* Go into the queue again */
850     break;
851     default: /* failed */
852     egg_dns_gotanswer(0, answer, origname);
853     break;
854     }
855     }
856 segfault 1.1 }
857    
858 fabian 1.16 /* Attempts to read from all the sockets in socklist
859 segfault 1.1 * fills s with up to 511 bytes if available, and returns the array index
860 fabian 1.16 *
861     * on EOF: returns -1, with socket in len
862     * on socket error: returns -2
863     * if nothing is ready: returns -3
864     */
865 segfault 1.1 static int sockread(char *s, int *len)
866     {
867 drummer 1.33 fd_set fd, fdw, fde;
868 segfault 1.1 int fds, i, x;
869 drummer 1.33 struct timeval t, tnow;
870     struct timeval *pt = &t;
871 segfault 1.1 int grab = 511;
872    
873     fds = getdtablesize();
874     #ifdef FD_SETSIZE
875     if (fds > FD_SETSIZE)
876 fabian 1.16 fds = FD_SETSIZE; /* Fixes YET ANOTHER freebsd bug!!! */
877 segfault 1.1 #endif
878     /* timeout: 1 sec */
879     t.tv_sec = 1;
880     t.tv_usec = 0;
881     FD_ZERO(&fd);
882 fabian 1.17
883 segfault 1.1 for (i = 0; i < MAXSOCKS; i++)
884 fabian 1.17 if (!(socklist[i].flags & (SOCK_UNUSED | SOCK_VIRTUAL))) {
885 segfault 1.1 if ((socklist[i].sock == STDOUT) && !backgrd)
886     FD_SET(STDIN, &fd);
887     else
888     FD_SET(socklist[i].sock, &fd);
889     }
890 drummer 1.33 tnow.tv_sec = time(NULL);
891     tnow.tv_usec = 0;
892     adns_beforeselect(ads, &fds, &fd, &fdw, &fde, &pt, 0, &tnow);
893 segfault 1.1 #ifdef HPUX_HACKS
894     #ifndef HPUX10_HACKS
895     x = select(fds, (int *) &fd, (int *) NULL, (int *) NULL, &t);
896     #else
897     x = select(fds, &fd, NULL, NULL, &t);
898     #endif
899     #else
900     x = select(fds, &fd, NULL, NULL, &t);
901     #endif
902 drummer 1.33 tnow.tv_sec = time(NULL);
903     tnow.tv_usec = 0;
904     adns_afterselect(ads, fds, &fd, &fdw, &fde, &tnow);
905    
906     /* dns stuff */
907     egg_dns_checkall();
908    
909 segfault 1.1 if (x > 0) {
910 fabian 1.16 /* Something happened */
911 segfault 1.1 for (i = 0; i < MAXSOCKS; i++) {
912     if ((!(socklist[i].flags & SOCK_UNUSED)) &&
913     ((FD_ISSET(socklist[i].sock, &fd)) ||
914     ((socklist[i].sock == STDOUT) && (!backgrd) &&
915     (FD_ISSET(STDIN, &fd))))) {
916     if (socklist[i].flags & (SOCK_LISTEN | SOCK_CONNECT)) {
917 fabian 1.16 /* Listening socket -- don't read, just return activity */
918     /* Same for connection attempt */
919 segfault 1.1 /* (for strong connections, require a read to succeed first) */
920     if (socklist[i].flags & SOCK_PROXYWAIT) { /* drummer */
921 fabian 1.16 /* Hang around to get the return code from proxy */
922 segfault 1.1 grab = 10;
923     } else if (!(socklist[i].flags & SOCK_STRONGCONN)) {
924     debug1("net: connect! sock %d", socklist[i].sock);
925     s[0] = 0;
926     *len = 0;
927     return i;
928     }
929 fabian 1.3 } else if (socklist[i].flags & SOCK_PASS) {
930     s[0] = 0;
931     *len = 0;
932     return i;
933 segfault 1.1 }
934     if ((socklist[i].sock == STDOUT) && !backgrd)
935     x = read(STDIN, s, grab);
936     else
937     x = read(socklist[i].sock, s, grab);
938     if (x <= 0) { /* eof */
939 guppy 1.31 if (errno == EAGAIN) {
940 segfault 1.1 s[0] = 0;
941     *len = 0;
942     return -3;
943     }
944     *len = socklist[i].sock;
945     socklist[i].flags &= ~SOCK_CONNECT;
946     debug1("net: eof!(read) socket %d", socklist[i].sock);
947     return -1;
948     }
949     s[x] = 0;
950     *len = x;
951     if (socklist[i].flags & SOCK_PROXYWAIT) {
952     debug2("net: socket: %d proxy errno: %d", socklist[i].sock, s[1]);
953     socklist[i].flags &= ~(SOCK_CONNECT | SOCK_PROXYWAIT);
954     switch (s[1]) {
955 fabian 1.16 case 90: /* Success */
956 segfault 1.1 s[0] = 0;
957     *len = 0;
958     return i;
959 fabian 1.16 case 91: /* Failed */
960 segfault 1.1 errno = ECONNREFUSED;
961     break;
962 fabian 1.16 case 92: /* No identd */
963     case 93: /* Identd said wrong username */
964     /* A better error message would be "socks misconfigured"
965     * or "identd not working" but this is simplest.
966     */
967 segfault 1.1 errno = ENETUNREACH;
968     break;
969     }
970     *len = socklist[i].sock;
971     return -1;
972     }
973     return i;
974     }
975     }
976     } else if (x == -1)
977     return -2; /* socket error */
978     else {
979     s[0] = 0;
980     *len = 0;
981     }
982     return -3;
983     }
984    
985     /* sockgets: buffer and read from sockets
986     *
987 fabian 1.16 * Attempts to read from all registered sockets for up to one second. if
988 segfault 1.1 * after one second, no complete data has been received from any of the
989     * sockets, 's' will be empty, 'len' will be 0, and sockgets will return -3.
990     * if there is returnable data received from a socket, the data will be
991     * in 's' (null-terminated if non-binary), the length will be returned
992     * in len, and the socket number will be returned.
993     * normal sockets have their input buffered, and each call to sockgets
994     * will return one line terminated with a '\n'. binary sockets are not
995     * buffered and return whatever coems in as soon as it arrives.
996     * listening sockets will return an empty string when a connection comes in.
997     * connecting sockets will return an empty string on a successful connect,
998     * or EOF on a failed connect.
999     * if an EOF is detected from any of the sockets, that socket number will be
1000     * put in len, and -1 will be returned.
1001     * the maximum length of the string returned is 512 (including null)
1002 fabian 1.25 *
1003     * Returns -4 if we handled something that shouldn't be handled by the
1004     * dcc functions. Simply ignore it.
1005 segfault 1.1 */
1006    
1007     int sockgets(char *s, int *len)
1008     {
1009     char xx[514], *p, *px;
1010     int ret, i, data = 0;
1011    
1012     for (i = 0; i < MAXSOCKS; i++) {
1013 fabian 1.16 /* Check for stored-up data waiting to be processed */
1014 fabian 1.25 if (!(socklist[i].flags & SOCK_UNUSED) &&
1015     !(socklist[i].flags & SOCK_BUFFER) && (socklist[i].inbuf != NULL)) {
1016     if (!(socklist[i].flags & SOCK_BINARY)) {
1017     /* look for \r too cos windows can't follow RFCs */
1018     p = strchr(socklist[i].inbuf, '\n');
1019     if (p == NULL)
1020     p = strchr(socklist[i].inbuf, '\r');
1021     if (p != NULL) {
1022     *p = 0;
1023     if (strlen(socklist[i].inbuf) > 510)
1024     socklist[i].inbuf[510] = 0;
1025     strcpy(s, socklist[i].inbuf);
1026     px = (char *) nmalloc(strlen(p + 1) + 1);
1027     strcpy(px, p + 1);
1028     nfree(socklist[i].inbuf);
1029     if (px[0])
1030     socklist[i].inbuf = px;
1031     else {
1032     nfree(px);
1033     socklist[i].inbuf = NULL;
1034     }
1035     /* Strip CR if this was CR/LF combo */
1036     if (s[strlen(s) - 1] == '\r')
1037     s[strlen(s) - 1] = 0;
1038     *len = strlen(s);
1039     return socklist[i].sock;
1040     }
1041     } else {
1042     /* Handling buffered binary data (must have been SOCK_BUFFER before). */
1043     if (socklist[i].inbuflen <= 510) {
1044     *len = socklist[i].inbuflen;
1045     egg_memcpy(s, socklist[i].inbuf, socklist[i].inbuflen);
1046     nfree(socklist[i].inbuf);
1047 poptix 1.30 socklist[i].inbuf = NULL;
1048 fabian 1.25 socklist[i].inbuflen = 0;
1049     } else {
1050     /* Split up into chunks of 510 bytes. */
1051     *len = 510;
1052     egg_memcpy(s, socklist[i].inbuf, *len);
1053     egg_memcpy(socklist[i].inbuf, socklist[i].inbuf + *len, *len);
1054     socklist[i].inbuflen -= *len;
1055     socklist[i].inbuf = nrealloc(socklist[i].inbuf,
1056     socklist[i].inbuflen);
1057 segfault 1.1 }
1058     return socklist[i].sock;
1059     }
1060     }
1061 fabian 1.16 /* Also check any sockets that might have EOF'd during write */
1062 segfault 1.1 if (!(socklist[i].flags & SOCK_UNUSED)
1063     && (socklist[i].flags & SOCK_EOFD)) {
1064     s[0] = 0;
1065     *len = socklist[i].sock;
1066     return -1;
1067     }
1068     }
1069 fabian 1.16 /* No pent-up data of any worth -- down to business */
1070 segfault 1.1 *len = 0;
1071     ret = sockread(xx, len);
1072     if (ret < 0) {
1073     s[0] = 0;
1074     return ret;
1075     }
1076 fabian 1.16 /* Binary, listening and passed on sockets don't get buffered. */
1077 segfault 1.1 if (socklist[ret].flags & SOCK_CONNECT) {
1078     if (socklist[ret].flags & SOCK_STRONGCONN) {
1079     socklist[ret].flags &= ~SOCK_STRONGCONN;
1080 fabian 1.25 /* Buffer any data that came in, for future read. */
1081     socklist[ret].inbuflen = *len;
1082     socklist[ret].inbuf = (char *) nmalloc(*len + 1);
1083     /* It might be binary data. You never know. */
1084     egg_memcpy(socklist[ret].inbuf, xx, *len);
1085     socklist[ret].inbuf[*len] = 0;
1086 segfault 1.1 }
1087     socklist[ret].flags &= ~SOCK_CONNECT;
1088     s[0] = 0;
1089     return socklist[ret].sock;
1090     }
1091     if (socklist[ret].flags & SOCK_BINARY) {
1092 fabian 1.18 egg_memcpy(s, xx, *len);
1093 segfault 1.1 return socklist[ret].sock;
1094     }
1095 fabian 1.3 if ((socklist[ret].flags & SOCK_LISTEN) ||
1096     (socklist[ret].flags & SOCK_PASS))
1097 segfault 1.1 return socklist[ret].sock;
1098 fabian 1.25 if (socklist[ret].flags & SOCK_BUFFER) {
1099     socklist[ret].inbuf = (char *) nrealloc(socklist[ret].inbuf,
1100     socklist[ret].inbuflen + *len + 1);
1101     egg_memcpy(socklist[ret].inbuf + socklist[ret].inbuflen, xx, *len);
1102     socklist[ret].inbuflen += *len;
1103     /* We don't know whether it's binary data. Make sure normal strings
1104     will be handled properly later on too. */
1105     socklist[ret].inbuf[socklist[ret].inbuflen] = 0;
1106     return -4; /* Ignore this one. */
1107     }
1108 fabian 1.16 /* Might be necessary to prepend stored-up data! */
1109 segfault 1.1 if (socklist[ret].inbuf != NULL) {
1110     p = socklist[ret].inbuf;
1111     socklist[ret].inbuf = (char *) nmalloc(strlen(p) + strlen(xx) + 1);
1112     strcpy(socklist[ret].inbuf, p);
1113     strcat(socklist[ret].inbuf, xx);
1114     nfree(p);
1115     if (strlen(socklist[ret].inbuf) < 512) {
1116     strcpy(xx, socklist[ret].inbuf);
1117     nfree(socklist[ret].inbuf);
1118     socklist[ret].inbuf = NULL;
1119 fabian 1.25 socklist[ret].inbuflen = 0;
1120 segfault 1.1 } else {
1121     p = socklist[ret].inbuf;
1122 fabian 1.25 socklist[ret].inbuflen = strlen(p) - 510;
1123     socklist[ret].inbuf = (char *) nmalloc(socklist[ret].inbuflen + 1);
1124 segfault 1.1 strcpy(socklist[ret].inbuf, p + 510);
1125     *(p + 510) = 0;
1126     strcpy(xx, p);
1127     nfree(p);
1128     /* (leave the rest to be post-pended later) */
1129     }
1130     }
1131 fabian 1.16 /* Look for EOL marker; if it's there, i have something to show */
1132 segfault 1.1 p = strchr(xx, '\n');
1133     if (p == NULL)
1134     p = strchr(xx, '\r');
1135     if (p != NULL) {
1136     *p = 0;
1137     strcpy(s, xx);
1138     strcpy(xx, p + 1);
1139     if (s[strlen(s) - 1] == '\r')
1140     s[strlen(s) - 1] = 0;
1141     data = 1; /* DCC_CHAT may now need to process a
1142 fabian 1.16 blank line */
1143 segfault 1.1 /* NO! */
1144     /* if (!s[0]) strcpy(s," "); */
1145     } else {
1146     s[0] = 0;
1147     if (strlen(xx) >= 510) {
1148 fabian 1.16 /* String is too long, so just insert fake \n */
1149 segfault 1.1 strcpy(s, xx);
1150     xx[0] = 0;
1151     data = 1;
1152     }
1153     }
1154     *len = strlen(s);
1155 fabian 1.16 /* Anything left that needs to be saved? */
1156 segfault 1.1 if (!xx[0]) {
1157     if (data)
1158     return socklist[ret].sock;
1159     else
1160     return -3;
1161     }
1162 fabian 1.16 /* Prepend old data back */
1163 segfault 1.1 if (socklist[ret].inbuf != NULL) {
1164     p = socklist[ret].inbuf;
1165 fabian 1.25 socklist[ret].inbuflen = strlen(p) + strlen(xx);
1166     socklist[ret].inbuf = (char *) nmalloc(socklist[ret].inbuflen + 1);
1167 segfault 1.1 strcpy(socklist[ret].inbuf, xx);
1168     strcat(socklist[ret].inbuf, p);
1169     nfree(p);
1170     } else {
1171 fabian 1.25 socklist[ret].inbuflen = strlen(xx);
1172     socklist[ret].inbuf = (char *) nmalloc(socklist[ret].inbuflen + 1);
1173 segfault 1.1 strcpy(socklist[ret].inbuf, xx);
1174     }
1175     if (data) {
1176     return socklist[ret].sock;
1177     } else {
1178     return -3;
1179     }
1180     }
1181    
1182 fabian 1.16 /* Dump something to a socket
1183     *
1184     * NOTE: Do NOT put Contexts in here if you want DEBUG to be meaningful!!
1185     */
1186 fabian 1.12 void tputs(register int z, char *s, unsigned int len)
1187 segfault 1.1 {
1188 fabian 1.12 register int i, x, idx;
1189 segfault 1.1 char *p;
1190 fabian 1.12 static int inhere = 0;
1191 segfault 1.1
1192     if (z < 0)
1193     return; /* um... HELLO?! sanity check please! */
1194     if (((z == STDOUT) || (z == STDERR)) && (!backgrd || use_stderr)) {
1195     write(z, s, len);
1196     return;
1197     }
1198     for (i = 0; i < MAXSOCKS; i++) {
1199     if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == z)) {
1200 fabian 1.10 for (idx = 0; idx < dcc_total; idx++) {
1201     if (dcc[idx].sock == z) {
1202     if (dcc[idx].type) {
1203     if (dcc[idx].type->name) {
1204     if (!strncmp(dcc[idx].type->name, "BOT", 3)) {
1205     otraffic_bn_today += len;
1206     break;
1207     } else if (!strcmp(dcc[idx].type->name, "SERVER")) {
1208     otraffic_irc_today += len;
1209     break;
1210     } else if (!strncmp(dcc[idx].type->name, "CHAT", 4)) {
1211     otraffic_dcc_today += len;
1212     break;
1213     } else if (!strncmp(dcc[idx].type->name, "FILES", 5)) {
1214     otraffic_filesys_today += len;
1215     break;
1216     } else if (!strcmp(dcc[idx].type->name, "SEND")) {
1217     otraffic_trans_today += len;
1218     break;
1219     } else if (!strncmp(dcc[idx].type->name, "GET", 3)) {
1220     otraffic_trans_today += len;
1221     break;
1222     } else {
1223     otraffic_unknown_today += len;
1224     break;
1225     }
1226     }
1227     }
1228     }
1229     }
1230    
1231 drummer 1.37 if (socklist[i].outbuf != NULL) {
1232     /* Already queueing: just add it */
1233 segfault 1.1 p = (char *) nrealloc(socklist[i].outbuf, socklist[i].outbuflen + len);
1234 fabian 1.18 egg_memcpy(p + socklist[i].outbuflen, s, len);
1235 segfault 1.1 socklist[i].outbuf = p;
1236     socklist[i].outbuflen += len;
1237     return;
1238     }
1239 fabian 1.16 /* Try. */
1240 segfault 1.1 x = write(z, s, len);
1241     if (x == (-1))
1242     x = 0;
1243     if (x < len) {
1244 fabian 1.16 /* Socket is full, queue it */
1245 segfault 1.1 socklist[i].outbuf = (char *) nmalloc(len - x);
1246 fabian 1.18 egg_memcpy(socklist[i].outbuf, &s[x], len - x);
1247 segfault 1.1 socklist[i].outbuflen = len - x;
1248     }
1249     return;
1250     }
1251     }
1252 fabian 1.12 /* Make sure we don't cause a crash by looping here */
1253     if (!inhere) {
1254     inhere = 1;
1255 fabian 1.16
1256 fabian 1.12 putlog(LOG_MISC, "*", "!!! writing to nonexistent socket: %d", z);
1257     s[strlen(s) - 1] = 0;
1258     putlog(LOG_MISC, "*", "!-> '%s'", s);
1259 fabian 1.16
1260 fabian 1.12 inhere = 0;
1261     }
1262 segfault 1.1 }
1263    
1264     /* tputs might queue data for sockets, let's dump as much of it as
1265 fabian 1.16 * possible.
1266     */
1267 segfault 1.1 void dequeue_sockets()
1268     {
1269     int i, x;
1270    
1271     for (i = 0; i < MAXSOCKS; i++) {
1272 drummer 1.37 if (!(socklist[i].flags & SOCK_UNUSED) &&
1273 fabian 1.22 socklist[i].outbuf != NULL) {
1274 fabian 1.16 /* Trick tputs into doing the work */
1275 segfault 1.1 x = write(socklist[i].sock, socklist[i].outbuf,
1276     socklist[i].outbuflen);
1277     if ((x < 0) && (errno != EAGAIN)
1278     #ifdef EBADSLT
1279     && (errno != EBADSLT)
1280     #endif
1281     #ifdef ENOTCONN
1282     && (errno != ENOTCONN)
1283     #endif
1284     ) {
1285 fabian 1.16 /* This detects an EOF during writing */
1286 segfault 1.1 debug3("net: eof!(write) socket %d (%s,%d)", socklist[i].sock,
1287     strerror(errno), errno);
1288     socklist[i].flags |= SOCK_EOFD;
1289     } else if (x == socklist[i].outbuflen) {
1290 fabian 1.16 /* If the whole buffer was sent, nuke it */
1291 segfault 1.1 nfree(socklist[i].outbuf);
1292     socklist[i].outbuf = NULL;
1293     socklist[i].outbuflen = 0;
1294     } else if (x > 0) {
1295     char *p = socklist[i].outbuf;
1296    
1297 fabian 1.16 /* This removes any sent bytes from the beginning of the buffer */
1298 segfault 1.1 socklist[i].outbuf = (char *) nmalloc(socklist[i].outbuflen - x);
1299 fabian 1.18 egg_memcpy(socklist[i].outbuf, p + x, socklist[i].outbuflen - x);
1300 segfault 1.1 socklist[i].outbuflen -= x;
1301     nfree(p);
1302     }
1303 fabian 1.15
1304     /* All queued data was sent. Call handler if one exists and the
1305     * dcc entry wants it.
1306     */
1307     if (!socklist[i].outbuf) {
1308     int idx = findanyidx(socklist[i].sock);
1309    
1310 fabian 1.22 if (idx > 0 && dcc[idx].type && dcc[idx].type->outdone)
1311 fabian 1.15 dcc[idx].type->outdone(idx);
1312     }
1313 segfault 1.1 }
1314     }
1315     }
1316 fabian 1.16
1317 segfault 1.1
1318 fabian 1.16 /*
1319     * Debugging stuff
1320     */
1321 segfault 1.1
1322     void tell_netdebug(int idx)
1323     {
1324     int i;
1325     char s[80];
1326    
1327     dprintf(idx, "Open sockets:");
1328     for (i = 0; i < MAXSOCKS; i++) {
1329     if (!(socklist[i].flags & SOCK_UNUSED)) {
1330     sprintf(s, " %d", socklist[i].sock);
1331     if (socklist[i].flags & SOCK_BINARY)
1332     strcat(s, " (binary)");
1333     if (socklist[i].flags & SOCK_LISTEN)
1334     strcat(s, " (listen)");
1335 fabian 1.3 if (socklist[i].flags & SOCK_PASS)
1336     strcat(s, " (passed on)");
1337 segfault 1.1 if (socklist[i].flags & SOCK_CONNECT)
1338     strcat(s, " (connecting)");
1339     if (socklist[i].flags & SOCK_STRONGCONN)
1340     strcat(s, " (strong)");
1341     if (socklist[i].flags & SOCK_NONSOCK)
1342     strcat(s, " (file)");
1343     if (socklist[i].inbuf != NULL)
1344     sprintf(&s[strlen(s)], " (inbuf: %04X)", strlen(socklist[i].inbuf));
1345     if (socklist[i].outbuf != NULL)
1346     sprintf(&s[strlen(s)], " (outbuf: %06lX)", socklist[i].outbuflen);
1347     strcat(s, ",");
1348     dprintf(idx, "%s", s);
1349     }
1350     }
1351     dprintf(idx, " done.\n");
1352 fabian 1.15 }
1353    
1354     /* Checks wether the referenced socket has data queued.
1355     *
1356     * Returns true if the incoming/outgoing (depending on 'type') queues
1357     * contain data, otherwise false.
1358     */
1359     int sock_has_data(int type, int sock)
1360     {
1361     int ret = 0, i;
1362    
1363     for (i = 0; i < MAXSOCKS; i++)
1364 fabian 1.22 if (!(socklist[i].flags & SOCK_UNUSED) && socklist[i].sock == sock)
1365 fabian 1.15 break;
1366     if (i < MAXSOCKS) {
1367     switch (type) {
1368     case SOCK_DATA_OUTGOING:
1369     ret = (socklist[i].outbuf != NULL);
1370     break;
1371     case SOCK_DATA_INCOMING:
1372     ret = (socklist[i].inbuf != NULL);
1373     break;
1374     }
1375 fabian 1.22 } else
1376     debug1("sock_has_data: could not find socket #%d, returning false.", sock);
1377 fabian 1.15 return ret;
1378 poptix 1.30 }
1379    
1380     /* flush_inbuf():
1381     * checks if there's data in the incoming buffer of an connection
1382     * and flushs the buffer if possible
1383     *
1384     * returns: -1 if the dcc entry wasn't found
1385     * -2 if dcc[idx].type->activity doesn't exist and the data couldn't
1386     * be handled
1387     * 0 if buffer was empty
1388     * otherwise length of flushed buffer
1389     */
1390     int flush_inbuf(int idx)
1391     {
1392     int i, len;
1393     char *inbuf;
1394    
1395     Assert((idx >= 0) && (idx < dcc_total));
1396     for (i = 0; i < MAXSOCKS; i++) {
1397     if ((dcc[idx].sock == socklist[i].sock)
1398     && !(socklist[i].flags & SOCK_UNUSED)) {
1399     len = socklist[i].inbuflen;
1400     if ((len > 0) && socklist[i].inbuf) {
1401     if (dcc[idx].type && dcc[idx].type->activity) {
1402     inbuf = socklist[i].inbuf;
1403     socklist[i].inbuf = NULL;
1404     dcc[idx].type->activity(idx, inbuf, len);
1405     nfree(inbuf);
1406     return len;
1407     } else
1408     return -2;
1409     } else
1410     return 0;
1411     }
1412     }
1413     return -1;
1414 segfault 1.1 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23