/[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.46 - (hide annotations) (download) (as text)
Sat Oct 13 12:00:22 2001 UTC (18 years ago) by stdarg
Branch: MAIN
Changes since 1.45: +17 -4 lines
File MIME type: text/x-chdr
Added code for C-based microsecond-precision timers.
Made utimer and timer use the new timer stuff. (But utimers and timers don't work with it yet, either does killtimer + killutimer, maybe somebody else can update those :) or I'll do it later)
Added new tcl command, mutimer, to make a timer with a fractional second (i.e. mutimer 500000 hi == run 'hi' after 1/2 second)
Made net.c change the select() timeout based on the shortest timer.
Added a guard clause to lostdcc(n) to make sure n is valid.
When the socket table is reallocated, now the new sockets are marked SOCK_UNUSED (heh).
Fixed a typo in filesys.mod (mine) (looked up the wrong bind table)

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23