1 /*
2 * net.c -- handles:
3 * all raw network i/o
4 */
5 /*
6 * This is hereby released into the public domain.
7 * Robey Pointer, robey@netcom.com
8 *
9 * Changes after Feb 23, 1999 Copyright Eggheads Development Team
10 *
11 * Copyright (C) 1999 - 2021 Eggheads Development Team
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */
27
28 #include <fcntl.h>
29 #include "main.h"
30 #include <limits.h>
31 #include <string.h>
32 #include <netdb.h>
33 #include <sys/socket.h>
34 #if HAVE_SYS_SELECT_H
35 # include <sys/select.h>
36 #endif
37 #include <netinet/in.h>
38 #include <netinet/tcp.h>
39 #include <arpa/inet.h>
40 #include <errno.h>
41 #if HAVE_UNISTD_H
42 # include <unistd.h>
43 #endif
44 #include <setjmp.h>
45 #include "mod/server.mod/server.h"
46
47 #ifdef TLS
48 # include <openssl/err.h>
49 #endif
50
51 extern struct dcc_t *dcc;
52 extern int backgrd, use_stderr, resolve_timeout, dcc_total;
53 extern unsigned long otraffic_irc_today, otraffic_bn_today, otraffic_dcc_today,
54 otraffic_filesys_today, otraffic_trans_today,
55 otraffic_unknown_today;
56
57 char natip[121] = ""; /* Public IPv4 to report for systems behind NAT */
58 char listen_ip[121] = ""; /* IP (or hostname) for listening sockets */
59 char vhost[121] = ""; /* IPv4 vhost for outgoing connections */
60 #ifdef IPV6
61 char vhost6[121] = ""; /* IPv6 vhost for outgoing connections */
62 int pref_af = 0; /* Prefer IPv6 over IPv4? */
63 #endif
64 char firewall[121] = ""; /* Socks server for firewall. */
65 int firewallport = 1080; /* Default port of socks 4/5 firewalls. */
66 char botuser[USERLEN + 1] = "eggdrop"; /* Username of the user running the bot*/
67 int dcc_sanitycheck = 0; /* Do some sanity checking on dcc connections. */
68 sock_list *socklist = NULL; /* Enough to be safe. */
69 sigjmp_buf alarmret; /* Env buffer for alarm() returns. */
70
71 /* Types of proxies */
72 #define PROXY_SOCKS 1
73 #define PROXY_SUN 2
74
75
76 /* I need an UNSIGNED long for dcc type stuff
77 */
my_atoul(char * s)78 IP my_atoul(char *s)
79 {
80 IP ret = 0;
81
82 while ((*s >= '0') && (*s <= '9')) {
83 ret *= 10;
84 ret += ((*s) - '0');
85 s++;
86 }
87 return ret;
88 }
89
expmem_net()90 int expmem_net()
91 {
92 int i, tot = 0;
93 struct threaddata *td = threaddata();
94
95 for (i = 0; i < td->MAXSOCKS; i++) {
96 if (!(td->socklist[i].flags & (SOCK_UNUSED | SOCK_TCL))) {
97 if (td->socklist[i].handler.sock.inbuf != NULL)
98 tot += strlen(td->socklist[i].handler.sock.inbuf) + 1;
99 if (td->socklist[i].handler.sock.outbuf != NULL)
100 tot += td->socklist[i].handler.sock.outbuflen;
101 }
102 }
103 return tot;
104 }
105
106 /* Extract the IP address from a sockaddr struct and convert it
107 * to presentation format.
108 */
iptostr(struct sockaddr * sa)109 char *iptostr(struct sockaddr *sa)
110 {
111 #ifdef IPV6
112 static char s[INET6_ADDRSTRLEN] = "";
113 if (sa->sa_family == AF_INET6)
114 inet_ntop(AF_INET6, &((struct sockaddr_in6 *)sa)->sin6_addr,
115 s, sizeof s);
116 else
117 #else
118 static char s[INET_ADDRSTRLEN] = "";
119 #endif
120 inet_ntop(AF_INET, &((struct sockaddr_in *)sa)->sin_addr.s_addr, s,
121 sizeof s);
122 return s;
123 }
124
125 /* Fills in a sockname struct with the given server and port. If the string
126 * pointed by src isn't an IP address and allowres is not null, the function
127 * will assume it's a hostname and will attempt to resolve it. This is
128 * convenient, but you should use the async dns functions where possible, to
129 * avoid blocking the bot while the lookup is performed.
130 */
setsockname(sockname_t * addr,char * src,int port,int allowres)131 int setsockname(sockname_t *addr, char *src, int port, int allowres)
132 {
133 char *endptr, *src2 = src;;
134 long val;
135 IP ip;
136 struct hostent *hp;
137 volatile int af = AF_UNSPEC;
138 #ifdef IPV6
139 char ip2[INET6_ADDRSTRLEN];
140 int pref;
141 #else
142 char ip2[INET_ADDRSTRLEN];
143 int i, count;
144 #endif
145
146 /* DCC CHAT ip is expressed as integer but inet_pton() only accepts dotted
147 * addresses */
148 val = strtol(src, &endptr, 10);
149 if (val && !*endptr) {
150 ip = htonl(val);
151 if (inet_ntop(AF_INET, &ip, ip2, sizeof ip2)) {
152 debug2("net: setsockname(): ip %s -> %s", src, ip2);
153 src2 = ip2;
154 }
155 }
156 #ifdef IPV6
157 /* Clean start */
158 egg_bzero(addr, sizeof(sockname_t));
159 pref = pref_af ? AF_INET6 : AF_INET;
160 if (pref == AF_INET) {
161 if (inet_pton(AF_INET, src2, &addr->addr.s4.sin_addr) == 1)
162 af = AF_INET;
163 else if (inet_pton(AF_INET6, src2, &addr->addr.s6.sin6_addr) == 1)
164 af = AF_INET6;
165 else
166 af = AF_UNSPEC;
167 } else {
168 if (inet_pton(AF_INET6, src2, &addr->addr.s6.sin6_addr) == 1)
169 af = AF_INET6;
170 else if (inet_pton(AF_INET, src2, &addr->addr.s4.sin_addr) == 1)
171 af = AF_INET;
172 else
173 af = AF_UNSPEC;
174 }
175
176 if (af == AF_UNSPEC && allowres && *src) {
177 /* src is a hostname. Attempt to resolve it.. */
178 if (!sigsetjmp(alarmret, 1)) {
179 alarm(resolve_timeout);
180 hp = gethostbyname2(src, pref_af ? AF_INET6 : AF_INET);
181 if (!hp)
182 hp = gethostbyname2(src, pref_af ? AF_INET : AF_INET6);
183 alarm(0);
184 } else
185 hp = NULL;
186 if (hp) {
187 if (hp->h_addrtype == AF_INET)
188 memcpy(&addr->addr.s4.sin_addr, hp->h_addr_list[0], hp->h_length);
189 else
190 memcpy(&addr->addr.s6.sin6_addr, hp->h_addr_list[0], hp->h_length);
191 af = hp->h_addrtype;
192 }
193 }
194
195 addr->family = (af == AF_UNSPEC) ? pref : af;
196 addr->addr.sa.sa_family = addr->family;
197 if (addr->family == AF_INET6) {
198 addr->addrlen = sizeof(struct sockaddr_in6);
199 addr->addr.s6.sin6_port = htons(port);
200 addr->addr.s6.sin6_family = AF_INET6;
201 } else {
202 addr->addrlen = sizeof(struct sockaddr_in);
203 addr->addr.s4.sin_port = htons(port);
204 addr->addr.s4.sin_family = AF_INET;
205 }
206 #else
207 egg_bzero(addr, sizeof(sockname_t));
208
209 /* If it's not an IPv4 address, check if its IPv6 (so it can fail/error
210 * appropriately). If it's not, and allowres is 1, use gethostbyname()
211 * to try and resolve. If allowres is 0, return AF_UNSPEC to allow
212 * dns.mod to do it's thing.
213
214 * Also, because we can't be sure inet_pton exists on the system, we
215 * have to resort to hackishly counting :s to see if its IPv6 or not.
216 * Go internet.
217 */
218 if (!inet_pton(AF_INET, src2, &addr->addr.s4.sin_addr)) {
219 /* Boring way to count :s */
220 count = 0;
221 for (i = 0; src[i]; i++) {
222 if (src[i] == ':') {
223 count++;
224 if (count == 2)
225 break;
226 }
227 }
228 if (count > 1) {
229 putlog(LOG_MISC, "*", "ERROR: This looks like an IPv6 address, \
230 but this Eggdrop was not compiled with IPv6 support.");
231 af = AF_UNSPEC;
232 }
233 else if (allowres) {
234 /* src is a hostname. Attempt to resolve it.. */
235 if (!sigsetjmp(alarmret, 1)) {
236 alarm(resolve_timeout);
237 hp = gethostbyname(src);
238 alarm(0);
239 } else
240 hp = NULL;
241 if (hp) {
242 memcpy(&addr->addr.s4.sin_addr, hp->h_addr_list[0], hp->h_length);
243 af = hp->h_addrtype;
244 }
245 } else
246 af = AF_UNSPEC;
247 } else
248 af = AF_INET;
249
250 addr->family = addr->addr.s4.sin_family = AF_INET;
251 addr->addr.sa.sa_family = addr->family;
252 addr->addrlen = sizeof(struct sockaddr_in);
253 addr->addr.s4.sin_port = htons(port);
254 #endif
255 return af;
256 }
257
258 /* Get socket address to bind to for outbound connections
259 */
getvhost(sockname_t * addr,int af)260 void getvhost(sockname_t *addr, int af)
261 {
262 char *h = NULL;
263
264 if (af == AF_INET)
265 h = vhost;
266 #ifdef IPV6
267 else
268 h = vhost6;
269 #endif
270 if (!h || !h[0] || setsockname(addr, (h ? h : ""), 0, 1) != af)
271 setsockname(addr, (af == AF_INET ? "0.0.0.0" : "::"), 0, 0);
272 /* Remember this 'self-lookup failed' thingie?
273 I have good news - you won't see it again ;) */
274 }
275
276 /* Sets/Unsets options for a specific socket.
277 *
278 * Returns: 0 - on success
279 * -1 - socket not found
280 * -2 - illegal operation
281 */
sockoptions(int sock,int operation,int sock_options)282 int sockoptions(int sock, int operation, int sock_options)
283 {
284 int i;
285 struct threaddata *td = threaddata();
286
287 for (i = 0; i < td->MAXSOCKS; i++)
288 if ((td->socklist[i].sock == sock) &&
289 !(td->socklist[i].flags & SOCK_UNUSED)) {
290 if (operation == EGG_OPTION_SET)
291 td->socklist[i].flags |= sock_options;
292 else if (operation == EGG_OPTION_UNSET)
293 td->socklist[i].flags &= ~sock_options;
294 else
295 return -2;
296 return 0;
297 }
298 return -1;
299 }
300
301 /* Return a free entry in the socket entry
302 */
allocsock(int sock,int options)303 int allocsock(int sock, int options)
304 {
305 int i;
306 struct threaddata *td = threaddata();
307
308 for (i = 0; i < td->MAXSOCKS; i++) {
309 if (td->socklist[i].flags & SOCK_UNUSED) {
310 /* yay! there is table space */
311 td->socklist[i].handler.sock.inbuf = NULL;
312 td->socklist[i].handler.sock.outbuf = NULL;
313 td->socklist[i].handler.sock.inbuflen = 0;
314 td->socklist[i].handler.sock.outbuflen = 0;
315 td->socklist[i].flags = options;
316 td->socklist[i].sock = sock;
317 #ifdef TLS
318 td->socklist[i].ssl = 0;
319 #endif
320 return i;
321 }
322 }
323 /* Try again if enlarging socketlist works */
324 if (increase_socks_max())
325 return -1;
326 else
327 return allocsock(sock, options);
328 }
329
330 /* Return a free entry in the socket entry for a tcl socket
331 *
332 * alloctclsock() can be called by Tcl threads
333 */
alloctclsock(int sock,int mask,Tcl_FileProc * proc,ClientData cd)334 int alloctclsock(int sock, int mask, Tcl_FileProc *proc, ClientData cd)
335 {
336 int f = -1;
337 int i;
338 struct threaddata *td = threaddata();
339
340 for (i = 0; i < td->MAXSOCKS; i++) {
341 if (td->socklist[i].flags & SOCK_UNUSED) {
342 if (f == -1)
343 f = i;
344 } else if ((td->socklist[i].flags & SOCK_TCL) &&
345 td->socklist[i].sock == sock) {
346 f = i;
347 break;
348 }
349 }
350 if (f != -1) {
351 td->socklist[f].sock = sock;
352 td->socklist[f].flags = SOCK_TCL;
353 td->socklist[f].handler.tclsock.mask = mask;
354 td->socklist[f].handler.tclsock.proc = proc;
355 td->socklist[f].handler.tclsock.cd = cd;
356 return f;
357 }
358 /* Try again if enlarging socketlist works */
359 if (increase_socks_max())
360 return -1;
361 else
362 return alloctclsock(sock, mask, proc, cd);
363 }
364
365 /* Request a normal socket for i/o
366 */
setsock(int sock,int options)367 void setsock(int sock, int options)
368 {
369 int i = allocsock(sock, options), parm = 1;
370 struct threaddata *td = threaddata();
371 struct linger linger = {0};
372
373 if (i == -1) {
374 putlog(LOG_MISC, "*", "Sockettable full.");
375 return;
376 }
377 if (((sock != STDOUT) || backgrd) && !(td->socklist[i].flags & SOCK_NONSOCK)) {
378 if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &parm, sizeof parm))
379 debug2("net: setsock(): setsockopt() s %i level SOL_SOCKET optname SO_KEEPALIVE error %s", sock, strerror(errno));
380 if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(struct linger)))
381 debug2("net: setsock(): setsockopt() s %i level SOL_SOCKET optname SO_LINGER error %s", sock, strerror(errno));
382 /* Turn off Nagle's algorithm, see man tcp */
383 if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &parm, sizeof parm))
384 debug2("net: setsock(): setsockopt() s %i level IPPROTO_TCP optname TCP_NODELAY error %s", sock, strerror(errno));
385 }
386 if (options & SOCK_LISTEN) {
387 /* Tris says this lets us grab the same port again next time */
388 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &parm, sizeof parm))
389 debug2("net: setsock(): setsockopt() s %i level SOL_SOCKET optname SO_REUSEADDR error %s", sock, strerror(errno));
390 }
391 /* Yay async i/o ! */
392 if ((sock != STDOUT) || backgrd)
393 fcntl(sock, F_SETFL, O_NONBLOCK);
394 }
395
getsock(int af,int options)396 int getsock(int af, int options)
397 {
398 int sock = socket(af, SOCK_STREAM, 0);
399
400 if (sock >= 0)
401 setsock(sock, options);
402 else
403 putlog(LOG_MISC, "*", "Warning: Can't create new socket: %s!",
404 strerror(errno));
405 return sock;
406 }
407
408 /* Done with a socket
409 */
killsock(int sock)410 void killsock(int sock)
411 {
412 int i;
413 struct threaddata *td = threaddata();
414
415 /* Ignore invalid sockets. */
416 if (sock < 0)
417 return;
418
419 for (i = 0; i < td->MAXSOCKS; i++) {
420 if ((td->socklist[i].sock == sock) && !(td->socklist[i].flags & SOCK_UNUSED)) {
421 if (!(td->socklist[i].flags & SOCK_TCL)) { /* nothing to free for tclsocks */
422 #ifdef TLS
423 if (td->socklist[i].ssl) {
424 SSL_shutdown(td->socklist[i].ssl);
425 nfree(SSL_get_app_data(td->socklist[i].ssl));
426 SSL_free(td->socklist[i].ssl);
427 td->socklist[i].ssl = NULL;
428 }
429 #endif
430 close(td->socklist[i].sock);
431 if (td->socklist[i].handler.sock.inbuf != NULL) {
432 nfree(td->socklist[i].handler.sock.inbuf);
433 td->socklist[i].handler.sock.inbuf = NULL;
434 }
435 if (td->socklist[i].handler.sock.outbuf != NULL) {
436 nfree(td->socklist[i].handler.sock.outbuf);
437 td->socklist[i].handler.sock.outbuf = NULL;
438 td->socklist[i].handler.sock.outbuflen = 0;
439 }
440 }
441 td->socklist[i].flags = SOCK_UNUSED;
442 return;
443 }
444 }
445 putlog(LOG_MISC, "*", "Warning: Attempt to kill un-allocated socket %d!", sock);
446 }
447
448 /* Done with a tcl socket
449 *
450 * killtclsock() can be called by Tcl threads
451 */
killtclsock(int sock)452 void killtclsock(int sock)
453 {
454 int i;
455 struct threaddata *td = threaddata();
456
457 if (sock < 0)
458 return;
459
460 for (i = 0; i < td->MAXSOCKS; i++) {
461 if ((td->socklist[i].flags & SOCK_TCL) && td->socklist[i].sock == sock) {
462 td->socklist[i].flags = SOCK_UNUSED;
463 return;
464 }
465 }
466 }
467
468 /* Send connection request to proxy
469 */
proxy_connect(int sock,sockname_t * addr)470 static int proxy_connect(int sock, sockname_t *addr)
471 {
472 sockname_t name;
473 char host[121], s[256];
474 int i, port, proxy;
475
476 if (!firewall[0])
477 return -2;
478 #ifdef IPV6
479 if (addr->family == AF_INET6) {
480 putlog(LOG_MISC, "*", "Eggdrop doesn't support IPv6 connections "
481 "through proxies yet.");
482 return -1;
483 }
484 #endif
485 if (firewall[0] == '!') {
486 proxy = PROXY_SUN;
487 strlcpy(host, &firewall[1], sizeof host);
488 } else {
489 proxy = PROXY_SOCKS;
490 strcpy(host, firewall);
491 }
492 port = addr->addr.s4.sin_port;
493 setsockname(&name, host, firewallport, 1);
494 if (connect(sock, &name.addr.sa, name.addrlen) < 0 && errno != EINPROGRESS)
495 return -1;
496 if (proxy == PROXY_SOCKS) {
497 for (i = 0; i < threaddata()->MAXSOCKS; i++)
498 if (!(socklist[i].flags & SOCK_UNUSED) && socklist[i].sock == sock)
499 socklist[i].flags |= SOCK_PROXYWAIT; /* drummer */
500 memcpy(host, &addr->addr.s4.sin_addr.s_addr, 4);
501 egg_snprintf(s, sizeof s, "\004\001%c%c%c%c%c%c%s", port % 256,
502 (port >> 8) % 256, host[0], host[1], host[2], host[3], botuser);
503 tputs(sock, s, strlen(botuser) + 9); /* drummer */
504 } else if (proxy == PROXY_SUN) {
505 inet_ntop(AF_INET, &addr->addr.s4.sin_addr, host, sizeof host);
506 egg_snprintf(s, sizeof s, "%s %d\n", host, port);
507 tputs(sock, s, strlen(s)); /* drummer */
508 }
509 return sock;
510 }
511
512 /* FIXME: if we can break compatibility for 1.9 or 2.0, we can replace this
513 * workaround with an additional port parameter for functions in need
514 */
get_port_from_addr(const sockname_t * addr)515 static int get_port_from_addr(const sockname_t *addr)
516 {
517 #ifdef IPV6
518 return ntohs((addr->family == AF_INET) ? addr->addr.s4.sin_port : addr->addr.s6.sin6_port);
519 #else
520 return ntohs(addr->addr.s4.sin_port);
521 #endif
522 }
523
524 /* Starts a connection attempt through a socket
525 *
526 * The server address should be filled in addr by setsockname() or by the
527 * non-blocking dns functions and setsnport().
528 *
529 * returns < 0 if connection refused:
530 * -1 strerror() type error
531 */
open_telnet_raw(int sock,sockname_t * addr)532 int open_telnet_raw(int sock, sockname_t *addr)
533 {
534 sockname_t name;
535 socklen_t res_len;
536 fd_set sockset;
537 struct timeval tv;
538 int i, j, rc, res;
539
540 for (i = 0; i < dcc_total; i++)
541 if (dcc[i].sock == sock) { /* Got idx from sock ? */
542 #ifdef TLS
543 debug5("net: open_telnet_raw(): idx %i host %s ip %s port %i ssl %i",
544 i, dcc[i].host, iptostr(&addr->addr.sa), dcc[i].port, dcc[i].ssl);
545 #else
546 debug4("net: open_telnet_raw(): idx %i host %s ip %s port %i",
547 i, dcc[i].host, iptostr(&addr->addr.sa), dcc[i].port);
548 #endif
549 break;
550 }
551 getvhost(&name, addr->family);
552 if (bind(sock, &name.addr.sa, name.addrlen) < 0) {
553 return -1;
554 }
555 for (j = 0; j < threaddata()->MAXSOCKS; j++) {
556 if (!(socklist[j].flags & SOCK_UNUSED) && (socklist[j].sock == sock))
557 socklist[j].flags = (socklist[j].flags & ~SOCK_VIRTUAL) | SOCK_CONNECT;
558 }
559 if (addr->family == AF_INET && firewall[0])
560 return proxy_connect(sock, addr);
561 rc = connect(sock, &addr->addr.sa, addr->addrlen);
562 /* To minimize a proven race condition, call ident here (especially when
563 * rc < 0 and errno == EINPROGRESS)
564 */
565 if (dcc[i].status & STAT_SERV) {
566 check_tcl_event("ident");
567 }
568 if (rc < 0) {
569 if (errno == EINPROGRESS) {
570 /* Async connection... don't return socket descriptor
571 * until after we confirm if it was successful or not */
572 tv.tv_sec = 1;
573 tv.tv_usec = 0;
574 FD_ZERO(&sockset);
575 FD_SET(sock, &sockset);
576 select(sock + 1, &sockset, NULL, NULL, &tv);
577 res_len = sizeof(res);
578 getsockopt(sock, SOL_SOCKET, SO_ERROR, &res, &res_len);
579 if (res == EINPROGRESS) /* Operation now in progress */
580 return sock; /* This could probably fail somewhere */
581 if (res == ECONNREFUSED) { /* Connection refused */
582 debug2("net: attempted socket connection refused: %s:%i",
583 iptostr(&addr->addr.sa), get_port_from_addr(addr));
584 errno = res;
585 return -4;
586 }
587 if (res != 0) {
588 debug1("net: getsockopt error %d", res);
589 return -1;
590 }
591 return sock; /* async success! */
592 }
593 else {
594 return -1;
595 }
596 }
597 return sock;
598 }
599
600 /* Ordinary non-binary connection attempt
601 * Return values:
602 * >=0: connect successful, returned is the socket number
603 * -1: look at errno or use strerror()
604 * -2: lookup failed or server is not a valid IP string
605 * -3: could not allocate socket
606 * -4: connection failed
607 */
open_telnet(int idx,char * server,int port)608 int open_telnet(int idx, char *server, int port)
609 {
610 int ret;
611
612 ret = setsockname(&dcc[idx].sockname, server, port, 1);
613 if (ret == AF_UNSPEC)
614 return -2;
615 dcc[idx].port = port;
616 dcc[idx].sock = getsock(ret, 0);
617 if (dcc[idx].sock < 0)
618 return -3;
619 ret = open_telnet_raw(dcc[idx].sock, &dcc[idx].sockname);
620 if (ret < 0) {
621 if (findidx(dcc[idx].sock) >= 0) {
622 killsock(dcc[idx].sock);
623 }
624 }
625 return ret;
626 }
627
628 /* Returns a socket number for a listening socket that will accept any
629 * connection on the given address. The address can be filled in by
630 * setsockname().
631 */
open_address_listen(sockname_t * addr)632 int open_address_listen(sockname_t *addr)
633 {
634 int sock = 0;
635
636 sock = getsock(addr->family, SOCK_LISTEN);
637 if (sock < 0)
638 return -1;
639 #if defined IPV6 && IPV6_V6ONLY
640 if (addr->family == AF_INET6) {
641 int on = 0;
642 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &on, sizeof(on));
643 }
644 #endif
645 if (bind(sock, &addr->addr.sa, addr->addrlen) < 0) {
646 killsock(sock);
647 return -2;
648 }
649
650 if (getsockname(sock, &addr->addr.sa, &addr->addrlen) < 0) {
651 killsock(sock);
652 return -1;
653 }
654 if (listen(sock, 1) < 0) {
655 killsock(sock);
656 return -1;
657 }
658
659 return sock;
660 }
661
662 /* Returns a socket number for a listening socket that will accept any
663 * connection -- port # is returned in port
664 */
open_listen(int * port)665 int open_listen(int *port)
666 {
667 int sock;
668 sockname_t name;
669
670 (void) setsockname(&name, listen_ip, *port, 1);
671 sock = open_address_listen(&name);
672 if (name.addr.sa.sa_family == AF_INET)
673 *port = ntohs(name.addr.s4.sin_port);
674 #ifdef IPV6
675 else
676 *port = ntohs(name.addr.s6.sin6_port);
677 #endif
678 return sock;
679 }
680
681 /* Short routine to answer a connect received on a listening socket.
682 * Returned is the new socket.
683 * If port is not NULL, it points to an integer to hold the port number
684 * of the caller.
685 */
answer(int sock,sockname_t * caller,uint16_t * port,int binary)686 int answer(int sock, sockname_t *caller, uint16_t *port, int binary)
687 {
688 int new_sock;
689 caller->addrlen = sizeof(caller->addr);
690 new_sock = accept(sock, &caller->addr.sa, &caller->addrlen);
691
692 if (new_sock < 0)
693 return -1;
694
695 caller->family = caller->addr.sa.sa_family;
696 if (port) {
697 if (caller->family == AF_INET)
698 *port = ntohs(caller->addr.s4.sin_port);
699 #ifdef IPV6
700 else
701 *port = ntohs(caller->addr.s6.sin6_port);
702 #endif
703 }
704 setsock(new_sock, (binary ? SOCK_BINARY : 0));
705 return new_sock;
706 }
707
getdccaddr(sockname_t * addr,char * s,size_t l)708 int getdccaddr(sockname_t *addr, char *s, size_t l)
709 {
710 return getdccfamilyaddr(addr, s, l, AF_UNSPEC);
711 }
712
713 /* Get DCC compatible address for a client to connect (e.g. 1660944385)
714 * If addr is not NULL, it should point to the listening socket's address.
715 * Otherwise, this function will try to figure out the public address of the
716 * machine, using listen_ip and natip. If restrict_af is set, it will limit
717 * the possible IPs to the specified family. The result is a string usable
718 * for DCC requests
719 */
getdccfamilyaddr(sockname_t * addr,char * s,size_t l,int restrict_af)720 int getdccfamilyaddr(sockname_t *addr, char *s, size_t l, int restrict_af)
721 {
722 char h[121];
723 sockname_t name, *r = &name;
724 int af = AF_UNSPEC;
725 #ifdef IPV6
726 IP ip = 0;
727 #endif
728
729 if (addr)
730 r = addr;
731 else
732 setsockname(r, listen_ip, 0, 1);
733 if (
734 #ifdef IPV6
735 ((r->family == AF_INET6) &&
736 IN6_IS_ADDR_UNSPECIFIED(&r->addr.s6.sin6_addr)) ||
737 #endif
738 (r->family == AF_INET && !r->addr.s4.sin_addr.s_addr)) {
739 /* We can't send :: or 0.0.0.0 for dcc, so try
740 to figure out some real address */
741 #ifdef IPV6
742 /* If it's listening on an IPv6 :: address,
743 try using vhost6 as the source IP */
744 if (r->family == AF_INET6 && restrict_af != AF_INET) {
745 if (inet_pton(AF_INET6, vhost6, &r->addr.s6.sin6_addr) != 1) {
746 r = &name;
747 gethostname(h, sizeof h);
748 setsockname(r, h, 0, 1);
749 if (r->family == AF_INET) {
750 /* setsockname tries to resolve both ipv4 and ipv6. ipv4 dns
751 resolution comes later in precedence, so if we get an ipv4
752 back, reset it to the original addr struct and try
753 again */
754 if (addr) {
755 r = addr;
756 } else {
757 setsockname(r, listen_ip, 0, 1);
758 }
759 } else
760 af = AF_INET6;
761 }
762 }
763 #endif
764 /* If IPv6 didn't work or is disabled, or it's listening on an IPv4
765 0.0.0.0 address, try using vhost4 as the source */
766 if (!af
767 #ifdef IPV6
768 && restrict_af != AF_INET6
769 #endif
770 ) {
771 if (inet_pton(AF_INET, vhost, &r->addr.s4.sin_addr) != 1) {
772 /* And if THAT fails, try DNS resolution of hostname */
773 r = &name;
774 gethostname(h, sizeof h);
775 setsockname(r, h, 0, 1);
776 }
777 }
778 }
779
780 if (
781 #ifdef IPV6
782 ((r->family == AF_INET6) &&
783 IN6_IS_ADDR_UNSPECIFIED(&r->addr.s6.sin6_addr)) ||
784 ((r->family == AF_INET6) && (restrict_af == AF_INET)) ||
785 ((r->family == AF_INET) && (restrict_af == AF_INET6)) ||
786 #endif
787 (!natip[0] && (r->family == AF_INET) && !r->addr.s4.sin_addr.s_addr))
788 return 0;
789
790 #ifdef IPV6
791 if (r->family == AF_INET6) {
792 if (IN6_IS_ADDR_V4MAPPED(&r->addr.s6.sin6_addr) ||
793 IN6_IS_ADDR_UNSPECIFIED(&r->addr.s6.sin6_addr)) {
794 memcpy(&ip, r->addr.s6.sin6_addr.s6_addr + 12, sizeof ip);
795 egg_snprintf(s, l, "%lu", natip[0] ? iptolong(inet_addr(natip)) :
796 ntohl(ip));
797 } else
798 inet_ntop(AF_INET6, &r->addr.s6.sin6_addr, s, l);
799 } else
800 #endif
801 egg_snprintf(s, l, "%lu", natip[0] ? iptolong(inet_addr(natip)) :
802 ntohl(r->addr.s4.sin_addr.s_addr));
803 return 1;
804 }
805
806 /* Builds the fd_sets for select(). Eggdrop only cares about readable
807 * sockets, but tcl also cares for writable/exceptions.
808 * preparefdset() can be called by Tcl Threads
809 */
preparefdset(fd_set * fds,sock_list * slist,int slistmax,int tclonly,int tclmask)810 static int preparefdset(fd_set *fds, sock_list *slist, int slistmax, int tclonly, int tclmask)
811 {
812 int fd, i, nfds = 0;
813
814 FD_ZERO(fds);
815 for (i = 0; i < slistmax; i++) {
816 if (!(slist[i].flags & (SOCK_UNUSED | SOCK_VIRTUAL))) {
817 if ((slist[i].sock == STDOUT) && !backgrd)
818 fd = STDIN;
819 else
820 fd = slist[i].sock;
821 /*
822 * Looks like that having more than a call, in the same
823 * program, to the FD_SET macro, triggers a bug in gcc.
824 * SIGBUS crashing binaries used to be produced on a number
825 * (prolly all?) of 64 bits architectures.
826 * Make your best to avoid to make it happen again.
827 *
828 * ITE
829 */
830 if (slist[i].flags & SOCK_TCL) {
831 if (!(slist[i].handler.tclsock.mask & tclmask))
832 continue;
833 } else if (tclonly)
834 continue;
835 if (fd > nfds)
836 nfds = fd;
837 FD_SET(fd, fds);
838 }
839 }
840 return nfds;
841 }
842
843 /* A safer version of write() that deals with partial writes. */
safe_write(int fd,const void * buf,size_t count)844 void safe_write(int fd, const void *buf, size_t count)
845 {
846 const char *bytes = buf;
847 ssize_t ret;
848 static int inhere = 0;
849
850 do {
851 if ((ret = write(fd, bytes, count)) == -1 && errno != EINTR) {
852 if (!inhere) {
853 inhere = 1;
854 putlog(LOG_MISC, "*", "Unexpected write() failure on attempt to write %zd bytes to fd %d: %s.", count, fd, strerror(errno));
855 inhere = 0;
856 }
857 break;
858 }
859 } while ((bytes += ret, count -= ret));
860 }
861
862 /* Attempts to read from all sockets in slist (upper array boundary slistmax-1)
863 * fills s with up to 511 bytes if available, and returns the array index
864 * Also calls all handler procs for Tcl sockets
865 * sockread() can be called by Tcl threads
866 *
867 * on EOF: returns -1, with socket in len
868 * on socket error: returns -2
869 * if nothing is ready: returns -3
870 * tcl sockets busy: returns -5
871 */
sockread(char * s,int * len,sock_list * slist,int slistmax,int tclonly)872 int sockread(char *s, int *len, sock_list *slist, int slistmax, int tclonly)
873 {
874 struct timeval t;
875 fd_set fdr, fdw, fde;
876 int i, x, nfds_r, nfds_w, nfds_e;
877 int grab = 511, tclsock = -1, events = 0;
878 struct threaddata *td = threaddata();
879 int nfds;
880 #ifdef EGG_TDNS
881 int fd;
882 struct dns_thread_node *dtn, *dtn_prev;
883 #endif
884
885 nfds_r = preparefdset(&fdr, slist, slistmax, tclonly, TCL_READABLE);
886 #ifdef EGG_TDNS
887 for (dtn = dns_thread_head->next; dtn; dtn = dtn->next) {
888 fd = dtn->fildes[0];
889 FD_SET(fd, &fdr);
890 if (fd > nfds_r)
891 nfds_r = fd;
892 }
893 #endif
894 nfds_w = preparefdset(&fdw, slist, slistmax, 1, TCL_WRITABLE);
895 nfds_e = preparefdset(&fde, slist, slistmax, 1, TCL_EXCEPTION);
896
897 nfds = nfds_r;
898 if (nfds_w > nfds)
899 nfds = nfds_w;
900 if (nfds_e > nfds)
901 nfds = nfds_e;
902
903 /* select() may modify the timeval argument - copy it */
904 t.tv_sec = td->blocktime.tv_sec;
905 t.tv_usec = td->blocktime.tv_usec;
906
907 x = select((SELECT_TYPE_ARG1) nfds + 1,
908 SELECT_TYPE_ARG234 (nfds_r ? &fdr : NULL),
909 SELECT_TYPE_ARG234 (nfds_w ? &fdw : NULL),
910 SELECT_TYPE_ARG234 (nfds_e ? &fde : NULL),
911 SELECT_TYPE_ARG5 &t);
912 if (x == -1)
913 return -2; /* socket error */
914
915 for (i = 0; i < slistmax; i++) {
916 if (!tclonly && ((!(slist[i].flags & (SOCK_UNUSED | SOCK_TCL))) &&
917 ((FD_ISSET(slist[i].sock, &fdr)) ||
918 #ifdef TLS
919 (slist[i].ssl && (SSL_pending(slist[i].ssl) ||
920 !SSL_is_init_finished(slist[i].ssl))) ||
921 #endif
922 ((slist[i].sock == STDOUT) && (!backgrd) &&
923 (FD_ISSET(STDIN, &fdr)))))) {
924 if (slist[i].flags & (SOCK_LISTEN | SOCK_CONNECT)) {
925 /* Listening socket -- don't read, just return activity */
926 /* Same for connection attempt */
927 /* (for strong connections, require a read to succeed first) */
928 if (slist[i].flags & SOCK_PROXYWAIT) /* drummer */
929 /* Hang around to get the return code from proxy */
930 grab = 10;
931 #ifdef TLS
932 else if (!(slist[i].flags & SOCK_STRONGCONN) &&
933 (!(slist[i].ssl) || SSL_is_init_finished(slist[i].ssl))) {
934 #else
935 else if (!(slist[i].flags & SOCK_STRONGCONN)) {
936 #endif
937 debug1("net: connect! sock %d", slist[i].sock);
938 s[0] = 0;
939 *len = 0;
940 return i;
941 }
942 } else if (slist[i].flags & SOCK_PASS) {
943 s[0] = 0;
944 *len = 0;
945 return i;
946 }
947 errno = 0;
948 if ((slist[i].sock == STDOUT) && !backgrd)
949 x = read(STDIN, s, grab);
950 else
951 #ifdef TLS
952 {
953 if (slist[i].ssl) {
954 x = SSL_read(slist[i].ssl, s, grab);
955 if (x < 0) {
956 int err = SSL_get_error(slist[i].ssl, x);
957 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
958 errno = EAGAIN;
959 else if (err == SSL_ERROR_SYSCALL) {
960 debug0("net: sockread(): SSL_read() SSL_ERROR_SYSCALL");
961 putlog(LOG_MISC, "*", "NET: SSL read failed. Non-SSL connection?");
962 }
963 else
964 debug2("net: sockread(): SSL_read() error = %s (%i)",
965 ERR_error_string(ERR_get_error(), 0), err);
966 x = -1;
967 }
968 } else
969 x = read(slist[i].sock, s, grab);
970 }
971 #else
972 x = read(slist[i].sock, s, grab);
973 #endif
974 if (x <= 0) { /* eof */
975 if (errno != EAGAIN) { /* EAGAIN happens when the operation would
976 * block on a non-blocking socket, if the
977 * socket is going to die, it will die later,
978 * otherwise it will connect. */
979 *len = slist[i].sock;
980 slist[i].flags &= ~SOCK_CONNECT;
981 debug1("net: eof!(read) socket %d", slist[i].sock);
982 return -1;
983 } else {
984 debug3("sockread EAGAIN: %d %d (%s)", slist[i].sock, errno,
985 strerror(errno));
986 continue; /* EAGAIN */
987 }
988 }
989 s[x] = 0;
990 *len = x;
991 if (slist[i].flags & SOCK_PROXYWAIT) {
992 debug2("net: socket: %d proxy errno: %d", slist[i].sock, s[1]);
993 slist[i].flags &= ~(SOCK_CONNECT | SOCK_PROXYWAIT);
994 switch (s[1]) {
995 case 90: /* Success */
996 s[0] = 0;
997 *len = 0;
998 return i;
999 case 91: /* Failed */
1000 errno = ECONNREFUSED;
1001 break;
1002 case 92: /* No identd */
1003 case 93: /* Identd said wrong username */
1004 /* A better error message would be "socks misconfigured"
1005 * or "identd not working" but this is simplest.
1006 */
1007 errno = ENETUNREACH;
1008 break;
1009 }
1010 *len = slist[i].sock;
1011 return -1;
1012 }
1013 return i;
1014 } else if (tclsock == -1 && (slist[i].flags & SOCK_TCL)) {
1015 events = FD_ISSET(slist[i].sock, &fdr) ? TCL_READABLE : 0;
1016 events |= FD_ISSET(slist[i].sock, &fdw) ? TCL_WRITABLE : 0;
1017 events |= FD_ISSET(slist[i].sock, &fde) ? TCL_EXCEPTION : 0;
1018 events &= slist[i].handler.tclsock.mask;
1019 if (events)
1020 tclsock = i;
1021 }
1022 }
1023 if (!tclonly) {
1024 s[0] = 0;
1025 *len = 0;
1026 }
1027 if (tclsock != -1) {
1028 (*slist[tclsock].handler.tclsock.proc)(slist[tclsock].handler.tclsock.cd,
1029 events);
1030 return -5;
1031 }
1032 #ifdef EGG_TDNS
1033 dtn_prev = dns_thread_head;
1034 for (dtn = dtn_prev->next; dtn; dtn = dtn->next) {
1035 fd = dtn->fildes[0];
1036 if (FD_ISSET(fd, &fdr)) {
1037 if (dtn->type == DTN_TYPE_HOSTBYIP)
1038 call_hostbyip(&dtn->addr, dtn->host, dtn->ok);
1039 else
1040 call_ipbyhost(dtn->host, &dtn->addr, dtn->ok);
1041 close(dtn->fildes[0]);
1042 dtn_prev->next = dtn->next;
1043 nfree(dtn);
1044 dtn = dtn_prev;
1045 }
1046 dtn_prev = dtn;
1047 }
1048 #endif
1049 return -3;
1050 }
1051
1052 /* sockgets: buffer and read from sockets
1053 *
1054 * Attempts to read from all registered sockets for up to one second. if
1055 * after one second, no complete data has been received from any of the
1056 * sockets, 's' will be empty, 'len' will be 0, and sockgets will return -3.
1057 * if there is returnable data received from a socket, the data will be
1058 * in 's' (null-terminated if non-binary), the length will be returned
1059 * in len, and the socket number will be returned.
1060 * normal sockets have their input buffered, and each call to sockgets
1061 * will return one line terminated with a '\n'. binary sockets are not
1062 * buffered and return whatever coems in as soon as it arrives.
1063 * listening sockets will return an empty string when a connection comes in.
1064 * connecting sockets will return an empty string on a successful connect,
1065 * or EOF on a failed connect.
1066 * if an EOF is detected from any of the sockets, that socket number will be
1067 * put in len, and -1 will be returned.
1068 * the maximum length of the string returned is 512 (including null)
1069 *
1070 * Returns -4 if we handled something that shouldn't be handled by the
1071 * dcc functions. Simply ignore it.
1072 * Returns -5 if tcl sockets are busy but not eggdrop sockets.
1073 */
1074
1075 int sockgets(char *s, int *len)
1076 {
1077 char xx[RECVLINEMAX], *p, *px, *p2;
1078 int ret, i, data = 0;
1079 size_t len2;
1080
1081 for (i = 0; i < threaddata()->MAXSOCKS; i++) {
1082 /* Check for stored-up data waiting to be processed */
1083 if (!(socklist[i].flags & (SOCK_UNUSED | SOCK_TCL | SOCK_BUFFER)) &&
1084 (socklist[i].handler.sock.inbuf != NULL)) {
1085 if (!(socklist[i].flags & SOCK_BINARY)) {
1086 /* IRC messages are always lines of characters terminated with a CR-LF
1087 * (Carriage Return - Line Feed) pair.
1088 */
1089 p = strpbrk(socklist[i].handler.sock.inbuf, "\r\n");
1090 if (p != NULL) {
1091
1092 /* this function is used not only for irc connections. dont remove
1093 * empty lines for they could be important like for example for http
1094 * header termination.
1095 */
1096 p2 = p;
1097 if (*p == '\r')
1098 p++;
1099 if (*p == '\n')
1100 p++;
1101 *p2 = 0;
1102
1103 strlcpy(s, socklist[i].handler.sock.inbuf, RECVLINEMAX-1);
1104 if (*p) {
1105 len2 = strlen(p) + 1;
1106 px = nmalloc(len2);
1107 memcpy(px, p, len2);
1108 nfree(socklist[i].handler.sock.inbuf);
1109 socklist[i].handler.sock.inbuf = px;
1110 } else {
1111 nfree(socklist[i].handler.sock.inbuf);
1112 socklist[i].handler.sock.inbuf = NULL;
1113 }
1114 *len = strlen(s);
1115 return socklist[i].sock;
1116 }
1117 } else {
1118 /* Handling buffered binary data (must have been SOCK_BUFFER before). */
1119 if (socklist[i].handler.sock.inbuflen <= RECVLINEMAX-2) {
1120 *len = socklist[i].handler.sock.inbuflen;
1121 memcpy(s, socklist[i].handler.sock.inbuf, socklist[i].handler.sock.inbuflen);
1122 nfree(socklist[i].handler.sock.inbuf);
1123 socklist[i].handler.sock.inbuf = NULL;
1124 socklist[i].handler.sock.inbuflen = 0;
1125 } else {
1126 /* Split up into chunks of RECVLINEMAX-2 bytes. */
1127 *len = RECVLINEMAX-2;
1128 memcpy(s, socklist[i].handler.sock.inbuf, *len);
1129 memcpy(socklist[i].handler.sock.inbuf, socklist[i].handler.sock.inbuf + *len, *len);
1130 socklist[i].handler.sock.inbuflen -= *len;
1131 socklist[i].handler.sock.inbuf = nrealloc(socklist[i].handler.sock.inbuf, socklist[i].handler.sock.inbuflen);
1132 }
1133 return socklist[i].sock;
1134 }
1135 }
1136 /* Also check any sockets that might have EOF'd during write */
1137 if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].flags & SOCK_EOFD)) {
1138 s[0] = 0;
1139 *len = socklist[i].sock;
1140 return -1;
1141 }
1142 }
1143 /* No pent-up data of any worth -- down to business */
1144 *len = 0;
1145 ret = sockread(xx, len, socklist, threaddata()->MAXSOCKS, 0);
1146 if (ret < 0) {
1147 s[0] = 0;
1148 return ret;
1149 }
1150 /* sockread can return binary data while socket still has connectflag, process first */
1151 if (socklist[ret].flags & SOCK_BINARY && *len > 0) {
1152 socklist[ret].flags &= ~SOCK_CONNECT;
1153 memcpy(s, xx, *len);
1154 return socklist[ret].sock;
1155 }
1156 /* Binary, listening and passed on sockets don't get buffered. */
1157 if (socklist[ret].flags & SOCK_CONNECT) {
1158 if (socklist[ret].flags & SOCK_STRONGCONN) {
1159 socklist[ret].flags &= ~SOCK_STRONGCONN;
1160 /* Buffer any data that came in, for future read. */
1161 socklist[ret].handler.sock.inbuflen = *len;
1162 socklist[ret].handler.sock.inbuf = nmalloc(*len + 1);
1163 /* It might be binary data. You never know. */
1164 memcpy(socklist[ret].handler.sock.inbuf, xx, *len);
1165 socklist[ret].handler.sock.inbuf[*len] = 0;
1166 }
1167 socklist[ret].flags &= ~SOCK_CONNECT;
1168 s[0] = 0;
1169 return socklist[ret].sock;
1170 }
1171 if (socklist[ret].flags & (SOCK_LISTEN | SOCK_PASS | SOCK_TCL)) {
1172 s[0] = 0; /* for the dcc traffic counters in the mainloop */
1173 return socklist[ret].sock;
1174 }
1175 if (socklist[ret].flags & SOCK_BUFFER) {
1176 socklist[ret].handler.sock.inbuf = (char *) nrealloc(socklist[ret].handler.sock.inbuf,
1177 socklist[ret].handler.sock.inbuflen + *len + 1);
1178 memcpy(socklist[ret].handler.sock.inbuf + socklist[ret].handler.sock.inbuflen, xx, *len);
1179 socklist[ret].handler.sock.inbuflen += *len;
1180 /* We don't know whether it's binary data. Make sure normal strings
1181 * will be handled properly later on too. */
1182 socklist[ret].handler.sock.inbuf[socklist[ret].handler.sock.inbuflen] = 0;
1183 return -4; /* Ignore this one. */
1184 }
1185 /* Might be necessary to prepend stored-up data! */
1186 if (socklist[ret].handler.sock.inbuf != NULL) {
1187 p = socklist[ret].handler.sock.inbuf;
1188 socklist[ret].handler.sock.inbuf = nmalloc(strlen(p) + strlen(xx) + 1);
1189 strcpy(socklist[ret].handler.sock.inbuf, p);
1190 strcat(socklist[ret].handler.sock.inbuf, xx);
1191 nfree(p);
1192 if (strlen(socklist[ret].handler.sock.inbuf) < RECVLINEMAX) {
1193 strcpy(xx, socklist[ret].handler.sock.inbuf);
1194 nfree(socklist[ret].handler.sock.inbuf);
1195 socklist[ret].handler.sock.inbuf = NULL;
1196 socklist[ret].handler.sock.inbuflen = 0;
1197 } else {
1198 p = socklist[ret].handler.sock.inbuf;
1199 socklist[ret].handler.sock.inbuflen = strlen(p) - RECVLINEMAX-2;
1200 socklist[ret].handler.sock.inbuf = nmalloc(socklist[ret].handler.sock.inbuflen + 1);
1201 strcpy(socklist[ret].handler.sock.inbuf, p + RECVLINEMAX-2);
1202 *(p + RECVLINEMAX-2) = 0;
1203 strcpy(xx, p);
1204 nfree(p);
1205 /* (leave the rest to be post-pended later) */
1206 }
1207 }
1208 /* Look for EOL marker; if it's there, i have something to show */
1209 for (p = xx; *p != 0 ; p++) {
1210 if ((*p == '\r') || (*p == '\n')) {
1211 memcpy(s, xx, p - xx);
1212 s[p - xx] = 0;
1213 for (p++; (*p == '\r') || (*p == '\n'); p++);
1214 memmove(xx, p, strlen(p) + 1);
1215 data = 1; /* DCC_CHAT may now need to process a blank line */
1216 break;
1217 }
1218 }
1219 /* NO! */
1220 /* if (!s[0]) strcpy(s," "); */
1221 if (!data) {
1222 s[0] = 0;
1223 if (strlen(xx) >= RECVLINEMAX-2) {
1224 /* String is too long, so just insert fake \n */
1225 strcpy(s, xx);
1226 xx[0] = 0;
1227 data = 1;
1228 }
1229 }
1230 *len = strlen(s);
1231 /* Anything left that needs to be saved? */
1232 if (!xx[0]) {
1233 if (data)
1234 return socklist[ret].sock;
1235 else
1236 return -3;
1237 }
1238 /* Prepend old data back */
1239 if (socklist[ret].handler.sock.inbuf != NULL) {
1240 p = socklist[ret].handler.sock.inbuf;
1241 socklist[ret].handler.sock.inbuflen = strlen(p) + strlen(xx);
1242 socklist[ret].handler.sock.inbuf = nmalloc(socklist[ret].handler.sock.inbuflen + 1);
1243 strcpy(socklist[ret].handler.sock.inbuf, xx);
1244 strcat(socklist[ret].handler.sock.inbuf, p);
1245 nfree(p);
1246 } else {
1247 socklist[ret].handler.sock.inbuflen = strlen(xx);
1248 len2 = socklist[ret].handler.sock.inbuflen + 1;
1249 socklist[ret].handler.sock.inbuf = nmalloc(len2);
1250 memcpy(socklist[ret].handler.sock.inbuf, xx, len2);
1251 }
1252 if (data)
1253 return socklist[ret].sock;
1254 else
1255 return -3;
1256 }
1257
1258 /* Dump something to a socket
1259 *
1260 * NOTE: Do NOT put Contexts in here if you want DEBUG to be meaningful!!
1261 */
1262 void tputs(int z, char *s, unsigned int len)
1263 {
1264 int i, x, idx;
1265 char *p;
1266 static int inhere = 0;
1267
1268 if (z < 0) /* um... HELLO?! sanity check please! */
1269 return;
1270
1271 if (((z == STDOUT) || (z == STDERR)) && (!backgrd || use_stderr)) {
1272 safe_write(z, s, len);
1273 return;
1274 }
1275
1276 for (i = 0; i < threaddata()->MAXSOCKS; i++) {
1277 if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == z)) {
1278 for (idx = 0; idx < dcc_total; idx++) {
1279 if ((dcc[idx].sock == z) && dcc[idx].type && dcc[idx].type->name) {
1280 if (!strncmp(dcc[idx].type->name, "BOT", 3))
1281 otraffic_bn_today += len;
1282 else if (!strcmp(dcc[idx].type->name, "SERVER"))
1283 otraffic_irc_today += len;
1284 else if (!strncmp(dcc[idx].type->name, "CHAT", 4))
1285 otraffic_dcc_today += len;
1286 else if (!strncmp(dcc[idx].type->name, "FILES", 5))
1287 otraffic_filesys_today += len;
1288 else if (!strcmp(dcc[idx].type->name, "SEND"))
1289 otraffic_trans_today += len;
1290 else if (!strcmp(dcc[idx].type->name, "FORK_SEND"))
1291 otraffic_trans_today += len;
1292 else if (!strncmp(dcc[idx].type->name, "GET", 3))
1293 otraffic_trans_today += len;
1294 else
1295 otraffic_unknown_today += len;
1296 break;
1297 }
1298 }
1299
1300 if (socklist[i].handler.sock.outbuf != NULL) {
1301 /* Already queueing: just add it */
1302 p = (char *) nrealloc(socklist[i].handler.sock.outbuf, socklist[i].handler.sock.outbuflen + len);
1303 memcpy(p + socklist[i].handler.sock.outbuflen, s, len);
1304 socklist[i].handler.sock.outbuf = p;
1305 socklist[i].handler.sock.outbuflen += len;
1306 return;
1307 }
1308 #ifdef TLS
1309 if (socklist[i].ssl) {
1310 x = SSL_write(socklist[i].ssl, s, len);
1311 if (x < 0) {
1312 int err = SSL_get_error(socklist[i].ssl, x);
1313 if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ)
1314 errno = EAGAIN;
1315 else if (!inhere) { /* Out there, somewhere */
1316 inhere = 1;
1317 debug1("tputs(): SSL error = %s",
1318 ERR_error_string(ERR_get_error(), 0));
1319 inhere = 0;
1320 }
1321 x = -1;
1322 }
1323 } else /* not ssl, use regular write() */
1324 #endif
1325 /* Try. */
1326 x = write(z, s, len);
1327 if (x == -1)
1328 x = 0;
1329 if (x < len) {
1330 /* Socket is full, queue it */
1331 socklist[i].handler.sock.outbuf = nmalloc(len - x);
1332 memcpy(socklist[i].handler.sock.outbuf, &s[x], len - x);
1333 socklist[i].handler.sock.outbuflen = len - x;
1334 }
1335 return;
1336 }
1337 }
1338 /* Make sure we don't cause a crash by looping here */
1339 if (!inhere) {
1340 inhere = 1;
1341
1342 putlog(LOG_MISC, "*", "!!! writing to nonexistent socket: %d", z);
1343 s[strlen(s) - 1] = 0;
1344 putlog(LOG_MISC, "*", "!-> '%s'", s);
1345
1346 inhere = 0;
1347 }
1348 }
1349
1350 /* tputs might queue data for sockets, let's dump as much of it as
1351 * possible.
1352 */
1353 void dequeue_sockets()
1354 {
1355 int i, x;
1356 int z = 0;
1357 fd_set wfds;
1358 struct timeval tv;
1359 int nfds = 0;
1360
1361 /* ^-- start poptix test code, this should avoid writes to sockets not ready to be written to. */
1362
1363 FD_ZERO(&wfds);
1364 tv.tv_sec = 0;
1365 tv.tv_usec = 0; /* we only want to see if it's ready for writing, no need to actually wait.. */
1366 for (i = 0; i < threaddata()->MAXSOCKS; i++)
1367 if (!(socklist[i].flags & (SOCK_UNUSED | SOCK_TCL)) &&
1368 (socklist[i].handler.sock.outbuf != NULL)) {
1369 if (socklist[i].sock > nfds)
1370 nfds = socklist[i].sock;
1371 FD_SET(socklist[i].sock, &wfds);
1372 z = 1;
1373 }
1374 if (!z)
1375 return; /* nothing to write */
1376
1377 select((SELECT_TYPE_ARG1) nfds + 1, SELECT_TYPE_ARG234 NULL,
1378 SELECT_TYPE_ARG234 &wfds, SELECT_TYPE_ARG234 NULL,
1379 SELECT_TYPE_ARG5 &tv);
1380
1381 /* end poptix */
1382
1383 for (i = 0; i < threaddata()->MAXSOCKS; i++) {
1384 if (!(socklist[i].flags & (SOCK_UNUSED | SOCK_TCL)) &&
1385 (socklist[i].handler.sock.outbuf != NULL) && (FD_ISSET(socklist[i].sock, &wfds))) {
1386 /* Trick tputs into doing the work */
1387 errno = 0;
1388 #ifdef TLS
1389 if (socklist[i].ssl) {
1390 x = SSL_write(socklist[i].ssl, socklist[i].handler.sock.outbuf,
1391 socklist[i].handler.sock.outbuflen);
1392 if (x < 0) {
1393 int err = SSL_get_error(socklist[i].ssl, x);
1394 if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ)
1395 errno = EAGAIN;
1396 else
1397 debug1("dequeue_sockets(): SSL error = %s",
1398 ERR_error_string(ERR_get_error(), 0));
1399 x = -1;
1400 }
1401 } else
1402 #endif
1403 x = write(socklist[i].sock, socklist[i].handler.sock.outbuf,
1404 socklist[i].handler.sock.outbuflen);
1405 if ((x < 0) && (errno != EAGAIN)
1406 #ifdef EBADSLT
1407 && (errno != EBADSLT)
1408 #endif
1409 #ifdef ENOTCONN
1410 && (errno != ENOTCONN)
1411 #endif
1412 ) {
1413 /* This detects an EOF during writing */
1414 debug3("net: eof!(write) socket %d (%s,%d)", socklist[i].sock,
1415 strerror(errno), errno);
1416 socklist[i].flags |= SOCK_EOFD;
1417 } else if (x == socklist[i].handler.sock.outbuflen) {
1418 /* If the whole buffer was sent, nuke it */
1419 nfree(socklist[i].handler.sock.outbuf);
1420 socklist[i].handler.sock.outbuf = NULL;
1421 socklist[i].handler.sock.outbuflen = 0;
1422 } else if (x > 0) {
1423 char *p = socklist[i].handler.sock.outbuf;
1424
1425 /* This removes any sent bytes from the beginning of the buffer */
1426 socklist[i].handler.sock.outbuf =
1427 nmalloc(socklist[i].handler.sock.outbuflen - x);
1428 memcpy(socklist[i].handler.sock.outbuf, p + x,
1429 socklist[i].handler.sock.outbuflen - x);
1430 socklist[i].handler.sock.outbuflen -= x;
1431 nfree(p);
1432 } else {
1433 debug3("dequeue_sockets(): errno = %d (%s) on %d", errno,
1434 strerror(errno), socklist[i].sock);
1435 }
1436 /* All queued data was sent. Call handler if one exists and the
1437 * dcc entry wants it.
1438 */
1439 if (!socklist[i].handler.sock.outbuf) {
1440 int idx = findanyidx(socklist[i].sock);
1441
1442 if (idx > 0 && dcc[idx].type && dcc[idx].type->outdone)
1443 dcc[idx].type->outdone(idx);
1444 }
1445 }
1446 }
1447 }
1448
1449
1450 /*
1451 * Debugging stuff
1452 */
1453
1454 void tell_netdebug(int idx)
1455 {
1456 int i;
1457 char s[80];
1458
1459 dprintf(idx, "Open sockets:");
1460 for (i = 0; i < threaddata()->MAXSOCKS; i++) {
1461 if (!(socklist[i].flags & SOCK_UNUSED)) {
1462 sprintf(s, " %d", socklist[i].sock);
1463 if (socklist[i].flags & SOCK_BINARY)
1464 strcat(s, " (binary)");
1465 if (socklist[i].flags & SOCK_LISTEN)
1466 strcat(s, " (listen)");
1467 if (socklist[i].flags & SOCK_PASS)
1468 strcat(s, " (passed on)");
1469 if (socklist[i].flags & SOCK_CONNECT)
1470 strcat(s, " (connecting)");
1471 if (socklist[i].flags & SOCK_STRONGCONN)
1472 strcat(s, " (strong)");
1473 if (socklist[i].flags & SOCK_NONSOCK)
1474 strcat(s, " (file)");
1475 #ifdef TLS
1476 if (socklist[i].ssl)
1477 strcat(s, " (TLS)");
1478 #endif
1479 if (socklist[i].flags & SOCK_TCL)
1480 strcat(s, " (tcl)");
1481 if (!(socklist[i].flags & SOCK_TCL)) {
1482 if (socklist[i].handler.sock.inbuf != NULL)
1483 sprintf(&s[strlen(s)], " (inbuf: %04X)",
1484 (unsigned int) strlen(socklist[i].handler.sock.inbuf));
1485 if (socklist[i].handler.sock.outbuf != NULL)
1486 sprintf(&s[strlen(s)], " (outbuf: %06lX)", socklist[i].handler.sock.outbuflen);
1487 }
1488 strcat(s, ",");
1489 dprintf(idx, "%s", s);
1490 }
1491 }
1492 dprintf(idx, " done.\n");
1493 }
1494
1495 /* Security-flavoured sanity checking on DCC connections of all sorts can be
1496 * done with this routine. Feed it the proper information from your DCC
1497 * before you attempt the connection, and this will make an attempt at
1498 * figuring out if the connection is really that person, or someone screwing
1499 * around. It's not foolproof, but anything that fails this check probably
1500 * isn't going to work anyway due to masquerading firewalls, NAT routers,
1501 * or bugs in mIRC.
1502 */
1503 int sanitycheck_dcc(char *nick, char *from, char *ipaddy, char *port)
1504 {
1505 /* According to the latest RFC, the clients SHOULD be able to handle
1506 * DNS names that are up to 255 characters long. This is not broken.
1507 */
1508
1509 #ifdef IPV6
1510 char badaddress[INET6_ADDRSTRLEN];
1511 sockname_t name;
1512 IP ip = 0;
1513 #else
1514 char badaddress[INET_ADDRSTRLEN];
1515 IP ip = my_atoul(ipaddy);
1516 #endif
1517 int prt = atoi(port);
1518
1519 /* It is disabled HERE so we only have to check in *one* spot! */
1520 if (!dcc_sanitycheck)
1521 return 1;
1522
1523 if (prt < 1) {
1524 putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an impossible port of %u!",
1525 nick, from, prt);
1526 return 0;
1527 }
1528 #ifdef IPV6
1529 if (strchr(ipaddy, ':')) {
1530 if (inet_pton(AF_INET6, ipaddy, &name.addr.s6.sin6_addr) != 1) {
1531 putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an invalid IPv6 "
1532 "address of %s!", nick, from, ipaddy);
1533 return 0;
1534 }
1535 if (IN6_IS_ADDR_V4MAPPED(&name.addr.s6.sin6_addr)) {
1536 memcpy(&ip, name.addr.s6.sin6_addr.s6_addr + 12, sizeof ip);
1537 ip = ntohl(ip);
1538 }
1539 }
1540 #endif
1541 if (ip && inet_ntop(AF_INET, &ip, badaddress, sizeof badaddress) &&
1542 (ip < (1 << 24))) {
1543 putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an impossible IP of %s!",
1544 nick, from, badaddress);
1545 return 0;
1546 }
1547 return 1;
1548 }
1549
1550 int hostsanitycheck_dcc(char *nick, char *from, sockname_t *ip, char *dnsname,
1551 char *prt)
1552 {
1553 char badaddress[INET6_ADDRSTRLEN];
1554
1555 /* According to the latest RFC, the clients SHOULD be able to handle
1556 * DNS names that are up to 255 characters long. This is not broken.
1557 */
1558 char hostn[256];
1559
1560 /* It is disabled HERE so we only have to check in *one* spot! */
1561 if (!dcc_sanitycheck)
1562 return 1;
1563 strcpy(badaddress, iptostr(&ip->addr.sa));
1564 /* These should pad like crazy with zeros, since 120 bytes or so is
1565 * where the routines providing our data currently lose interest. I'm
1566 * using the n-variant in case someone changes that...
1567 */
1568 strlcpy(hostn, extracthostname(from), sizeof hostn);
1569 if (!strcasecmp(hostn, dnsname)) {
1570 putlog(LOG_DEBUG, "*", "DNS information for submitted IP checks out.");
1571 return 1;
1572 }
1573 if (!strcmp(badaddress, dnsname))
1574 putlog(LOG_MISC, "*", "ALERT: (%s!%s) sent a DCC request with bogus IP "
1575 "information of %s port %s. %s does not resolve to %s!", nick, from,
1576 badaddress, prt, from, badaddress);
1577 else
1578 return 1; /* <- usually happens when we have
1579 * a user with an unresolved hostmask! */
1580 return 0;
1581 }
1582
1583 /* Checks whether the referenced socket has data queued.
1584 *
1585 * Returns true if the incoming/outgoing (depending on 'type') queues
1586 * contain data, otherwise false.
1587 */
1588 int sock_has_data(int type, int sock)
1589 {
1590 int ret = 0, i;
1591
1592 for (i = 0; i < threaddata()->MAXSOCKS; i++)
1593 if (!(socklist[i].flags & SOCK_UNUSED) && socklist[i].sock == sock)
1594 break;
1595 if (i < threaddata()->MAXSOCKS) {
1596 switch (type) {
1597 case SOCK_DATA_OUTGOING:
1598 ret = (socklist[i].handler.sock.outbuf != NULL);
1599 break;
1600 case SOCK_DATA_INCOMING:
1601 ret = (socklist[i].handler.sock.inbuf != NULL);
1602 break;
1603 }
1604 } else
1605 debug1("sock_has_data: could not find socket #%d, returning false.", sock);
1606 return ret;
1607 }
1608
1609 /* flush_inbuf():
1610 * checks if there's data in the incoming buffer of an connection
1611 * and flushes the buffer if possible
1612 *
1613 * returns: -1 if the dcc entry wasn't found
1614 * -2 if dcc[idx].type->activity doesn't exist and the data couldn't
1615 * be handled
1616 * 0 if buffer was empty
1617 * otherwise length of flushed buffer
1618 */
1619 int flush_inbuf(int idx)
1620 {
1621 int i, len;
1622 char *inbuf;
1623
1624 Assert((idx >= 0) && (idx < dcc_total));
1625 for (i = 0; i < threaddata()->MAXSOCKS; i++) {
1626 if ((dcc[idx].sock == socklist[i].sock) &&
1627 !(socklist[i].flags & SOCK_UNUSED)) {
1628 len = socklist[i].handler.sock.inbuflen;
1629 if ((len > 0) && socklist[i].handler.sock.inbuf) {
1630 if (dcc[idx].type && dcc[idx].type->activity) {
1631 inbuf = socklist[i].handler.sock.inbuf;
1632 socklist[i].handler.sock.inbuf = NULL;
1633 dcc[idx].type->activity(idx, inbuf, len);
1634 nfree(inbuf);
1635 return len;
1636 } else
1637 return -2;
1638 } else
1639 return 0;
1640 }
1641 }
1642 return -1;
1643 }
1644
1645 /* Find sock in socklist.
1646 *
1647 * Returns index in socklist or -1 if not found.
1648 */
1649 int findsock(int sock)
1650 {
1651 int i;
1652 struct threaddata *td = threaddata();
1653
1654 for (i = 0; i < td->MAXSOCKS; i++)
1655 if (td->socklist[i].sock == sock)
1656 break;
1657 if (i == td->MAXSOCKS)
1658 return -1;
1659 return i;
1660 }
1661
1662 /* Trace on my-ip and my-hostname variable to handle transition into vhost4/vhost6/listen-addr.
1663 */
1664 char *traced_myiphostname(ClientData cd, Tcl_Interp *irp, EGG_CONST char *name1, EGG_CONST char *name2, int flags)
1665 {
1666 const char *value;
1667
1668 if (flags & TCL_INTERP_DESTROYED)
1669 return NULL;
1670 /* Recover trace in case of unset. */
1671 if (flags & TCL_TRACE_DESTROYED) {
1672 Tcl_TraceVar2(irp, name1, name2, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, traced_myiphostname, cd);
1673 return NULL;
1674 }
1675
1676 value = Tcl_GetVar2(irp, name1, name2, TCL_GLOBAL_ONLY);
1677 strlcpy(vhost, value, sizeof vhost);
1678 strlcpy(listen_ip, value, sizeof listen_ip);
1679 putlog(LOG_MISC, "*", "WARNING: You are using the DEPRECATED variable '%s' in your config file.\n", name1);
1680 putlog(LOG_MISC, "*", " To prevent future incompatibility, please use the vhost4/listen-addr variables instead.\n");
1681 putlog(LOG_MISC, "*", " More information on this subject can be found in the eggdrop/doc/IPV6 file, or\n");
1682 putlog(LOG_MISC, "*", " in the comments above those settings in the example eggdrop.conf that is included with Eggdrop.\n");
1683 return NULL;
1684 }
1685