/[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.63 - (hide annotations) (download) (as text)
Fri Sep 20 02:06:25 2002 UTC (16 years, 9 months ago) by stdarg
Branch: MAIN
Changes since 1.62: +1 -2 lines
File MIME type: text/x-chdr
* Moved several things from the core into libegg
* Server module uses new network code
* Lots of stuff removed from the server module, like flood stuff, which should go into a new module
* Moved some things from irc module to server module (mostly bind stuff, like pub)
* Not everything works right now, but I wanted to get it into cvs in case my computer dies a horrible death. I'm going to combine irc/server (mostly) and make a new one for all the default protection stuff.
* Right now server messages are not queued. I thought the code was pretty much beyond repair. The new queueing code will hopefully be more maintainable.
* I'm not sure I added/removed all the files necessary! Let me know if it doesn't compile for you.

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23