/[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.41 - (hide annotations) (download) (as text)
Sun Aug 19 02:49:40 2001 UTC (17 years, 10 months ago) by drummer
Branch: MAIN
Changes since 1.40: +1 -32 lines
File MIME type: text/x-chdr
Removed unused hostnamefromip()

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23