1 |
segfault |
1.1 |
/* |
2 |
|
|
* net.c -- handles: |
3 |
|
|
* all raw network i/o |
4 |
|
|
* |
5 |
|
|
* This is hereby released into the public domain. |
6 |
|
|
* Robey Pointer, robey@netcom.com |
7 |
|
|
*/ |
8 |
|
|
|
9 |
|
|
#include "main.h" |
10 |
|
|
#include <limits.h> |
11 |
|
|
#include <string.h> |
12 |
|
|
#include <netdb.h> |
13 |
|
|
#include <sys/socket.h> |
14 |
|
|
#if HAVE_SYS_SELECT_H |
15 |
|
|
#include <sys/select.h> |
16 |
|
|
#endif |
17 |
|
|
#include <netinet/in.h> |
18 |
|
|
#include <arpa/inet.h> /* is this really necessary? */ |
19 |
|
|
#include <errno.h> |
20 |
|
|
#if HAVE_UNISTD_H |
21 |
|
|
#include <unistd.h> |
22 |
|
|
#endif |
23 |
|
|
#include <fcntl.h> |
24 |
|
|
#include <setjmp.h> |
25 |
|
|
|
26 |
|
|
#if !HAVE_GETDTABLESIZE |
27 |
|
|
#ifdef FD_SETSIZE |
28 |
|
|
#define getdtablesize() FD_SETSIZE |
29 |
|
|
#else |
30 |
|
|
#define getdtablesize() 200 |
31 |
|
|
#endif |
32 |
|
|
#endif |
33 |
|
|
|
34 |
|
|
extern int backgrd; |
35 |
|
|
extern int use_stderr; |
36 |
|
|
extern int resolve_timeout; |
37 |
|
|
|
38 |
|
|
char hostname[121] = ""; /* hostname can be specified in the config |
39 |
|
|
* file */ |
40 |
|
|
char myip[121] = ""; /* IP can be specified in the config file */ |
41 |
|
|
char firewall[121] = ""; /* socks server for firewall */ |
42 |
|
|
int firewallport = 1080; /* default port of Sock4/5 firewalls */ |
43 |
|
|
char botuser[21] = "eggdrop"; /* username of the user running the bot */ |
44 |
|
|
int dcc_sanitycheck = 0; /* we should do some sanity checking on dcc |
45 |
|
|
* connections. */ |
46 |
|
|
sock_list *socklist = 0; /* enough to be safe */ |
47 |
|
|
int MAXSOCKS = 0; |
48 |
|
|
|
49 |
|
|
/* types of proxy */ |
50 |
|
|
#define PROXY_SOCKS 1 |
51 |
|
|
#define PROXY_SUN 2 |
52 |
|
|
|
53 |
|
|
jmp_buf alarmret; /* env buffer for alarm() returns */ |
54 |
|
|
|
55 |
|
|
/* i need an UNSIGNED long for dcc type stuff */ |
56 |
|
|
IP my_atoul(char *s) |
57 |
|
|
{ |
58 |
|
|
IP ret = 0; |
59 |
|
|
|
60 |
|
|
while ((*s >= '0') && (*s <= '9')) { |
61 |
|
|
ret *= 10; |
62 |
|
|
ret += ((*s) - '0'); |
63 |
|
|
s++; |
64 |
|
|
} |
65 |
|
|
return ret; |
66 |
|
|
} |
67 |
|
|
|
68 |
|
|
#define my_ntohs(sh) swap_short(sh) |
69 |
|
|
#define my_htons(sh) swap_short(sh) |
70 |
|
|
#define my_ntohl(ln) swap_long(ln) |
71 |
|
|
#define my_htonl(ln) swap_long(ln) |
72 |
|
|
|
73 |
|
|
/* i read somewhere that memcpy() is broken on some machines */ |
74 |
|
|
/* it's easy to replace, so i'm not gonna take any chances, because |
75 |
|
|
* it's pretty important that it work correctly here */ |
76 |
|
|
void my_memcpy(char *dest, char *src, int len) |
77 |
|
|
{ |
78 |
|
|
while (len--) |
79 |
|
|
*dest++ = *src++; |
80 |
|
|
} |
81 |
|
|
|
82 |
|
|
#ifndef HAVE_BZERO |
83 |
|
|
/* bzero() is bsd-only, so here's one for non-bsd systems */ |
84 |
|
|
void bzero(char *dest, int len) |
85 |
|
|
{ |
86 |
|
|
while (len--) |
87 |
|
|
*dest++ = 0; |
88 |
|
|
} |
89 |
|
|
#endif |
90 |
|
|
|
91 |
|
|
/* initialize the socklist */ |
92 |
|
|
void init_net() |
93 |
|
|
{ |
94 |
|
|
int i; |
95 |
|
|
|
96 |
|
|
for (i = 0; i < MAXSOCKS; i++) { |
97 |
|
|
socklist[i].flags = SOCK_UNUSED; |
98 |
|
|
} |
99 |
|
|
} |
100 |
|
|
|
101 |
|
|
int expmem_net() |
102 |
|
|
{ |
103 |
|
|
int i, tot = 0; |
104 |
|
|
|
105 |
|
|
context; |
106 |
|
|
for (i = 0; i < MAXSOCKS; i++) { |
107 |
|
|
if (!(socklist[i].flags & SOCK_UNUSED)) { |
108 |
|
|
if (socklist[i].inbuf != NULL) |
109 |
|
|
tot += strlen(socklist[i].inbuf) + 1; |
110 |
|
|
if (socklist[i].outbuf != NULL) |
111 |
|
|
tot += socklist[i].outbuflen; |
112 |
|
|
} |
113 |
|
|
} |
114 |
|
|
return tot; |
115 |
|
|
} |
116 |
|
|
|
117 |
|
|
/* get my ip number */ |
118 |
|
|
IP getmyip() |
119 |
|
|
{ |
120 |
|
|
struct hostent *hp; |
121 |
|
|
char s[121]; |
122 |
|
|
IP ip; |
123 |
|
|
struct in_addr *in; |
124 |
|
|
|
125 |
|
|
/* could be pre-defined */ |
126 |
|
|
if (myip[0]) { |
127 |
|
|
if ((myip[strlen(myip) - 1] >= '0') && (myip[strlen(myip) - 1] <= '9')) |
128 |
|
|
return (IP) inet_addr(myip); |
129 |
|
|
} |
130 |
|
|
/* also could be pre-defined */ |
131 |
|
|
if (hostname[0]) |
132 |
|
|
hp = gethostbyname(hostname); |
133 |
|
|
else { |
134 |
|
|
gethostname(s, 120); |
135 |
|
|
hp = gethostbyname(s); |
136 |
|
|
} |
137 |
|
|
if (hp == NULL) |
138 |
|
|
fatal("Hostname self-lookup failed.", 0); |
139 |
|
|
in = (struct in_addr *) (hp->h_addr_list[0]); |
140 |
|
|
ip = (IP) (in->s_addr); |
141 |
|
|
return ip; |
142 |
|
|
} |
143 |
|
|
|
144 |
|
|
void neterror(char *s) |
145 |
|
|
{ |
146 |
|
|
switch (errno) { |
147 |
|
|
case EADDRINUSE: |
148 |
|
|
strcpy(s, "Address already in use"); |
149 |
|
|
break; |
150 |
|
|
case EADDRNOTAVAIL: |
151 |
|
|
strcpy(s, "Address invalid on remote machine"); |
152 |
|
|
break; |
153 |
|
|
case EAFNOSUPPORT: |
154 |
|
|
strcpy(s, "Address family not supported"); |
155 |
|
|
break; |
156 |
|
|
case EALREADY: |
157 |
|
|
strcpy(s, "Socket already in use"); |
158 |
|
|
break; |
159 |
|
|
case EBADF: |
160 |
|
|
strcpy(s, "Socket descriptor is bad"); |
161 |
|
|
break; |
162 |
|
|
case ECONNREFUSED: |
163 |
|
|
strcpy(s, "Connection refused"); |
164 |
|
|
break; |
165 |
|
|
case EFAULT: |
166 |
|
|
strcpy(s, "Namespace segment violation"); |
167 |
|
|
break; |
168 |
|
|
case EINPROGRESS: |
169 |
|
|
strcpy(s, "Operation in progress"); |
170 |
|
|
break; |
171 |
|
|
case EINTR: |
172 |
|
|
strcpy(s, "Timeout"); |
173 |
|
|
break; |
174 |
|
|
case EINVAL: |
175 |
|
|
strcpy(s, "Invalid namespace"); |
176 |
|
|
break; |
177 |
|
|
case EISCONN: |
178 |
|
|
strcpy(s, "Socket already connected"); |
179 |
|
|
break; |
180 |
|
|
case ENETUNREACH: |
181 |
|
|
strcpy(s, "Network unreachable"); |
182 |
|
|
break; |
183 |
|
|
case ENOTSOCK: |
184 |
|
|
strcpy(s, "File descriptor, not a socket"); |
185 |
|
|
break; |
186 |
|
|
case ETIMEDOUT: |
187 |
|
|
strcpy(s, "Connection timed out"); |
188 |
|
|
break; |
189 |
|
|
case ENOTCONN: |
190 |
|
|
strcpy(s, "Socket is not connected"); |
191 |
|
|
break; |
192 |
|
|
case EHOSTUNREACH: |
193 |
|
|
strcpy(s, "Host is unreachable"); |
194 |
|
|
break; |
195 |
|
|
case EPIPE: |
196 |
|
|
strcpy(s, "Broken pipe"); |
197 |
|
|
break; |
198 |
|
|
#ifdef ECONNRESET |
199 |
|
|
case ECONNRESET: |
200 |
|
|
strcpy(s, "Connection reset by peer"); |
201 |
|
|
break; |
202 |
|
|
#endif |
203 |
|
|
#ifdef EACCES |
204 |
|
|
case EACCES: |
205 |
|
|
strcpy(s, "Permission denied"); |
206 |
|
|
break; |
207 |
|
|
#endif |
208 |
|
|
case 0: |
209 |
|
|
strcpy(s, "Error 0"); |
210 |
|
|
break; |
211 |
|
|
default: |
212 |
|
|
sprintf(s, "Unforseen error %d", errno); |
213 |
|
|
break; |
214 |
|
|
} |
215 |
|
|
} |
216 |
|
|
|
217 |
|
|
/* request a normal socket for i/o */ |
218 |
|
|
void setsock(int sock, int options) |
219 |
|
|
{ |
220 |
|
|
int i; |
221 |
|
|
int parm; |
222 |
|
|
|
223 |
|
|
for (i = 0; i < MAXSOCKS; i++) { |
224 |
|
|
if (socklist[i].flags & SOCK_UNUSED) { |
225 |
|
|
/* yay! there is table space */ |
226 |
|
|
socklist[i].inbuf = socklist[i].outbuf = NULL; |
227 |
|
|
socklist[i].outbuflen = 0; |
228 |
|
|
socklist[i].flags = options; |
229 |
|
|
socklist[i].sock = sock; |
230 |
|
|
if (((sock != STDOUT) || backgrd) && |
231 |
|
|
!(socklist[i].flags & SOCK_NONSOCK)) { |
232 |
|
|
parm = 1; |
233 |
|
|
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *) &parm, |
234 |
|
|
sizeof(int)); |
235 |
|
|
|
236 |
|
|
parm = 0; |
237 |
|
|
setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &parm, sizeof(int)); |
238 |
|
|
} |
239 |
|
|
if (options & SOCK_LISTEN) { |
240 |
|
|
/* Tris says this lets us grab the same port again next time */ |
241 |
|
|
parm = 1; |
242 |
|
|
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &parm, |
243 |
|
|
sizeof(int)); |
244 |
|
|
} |
245 |
|
|
/* yay async i/o ! */ |
246 |
|
|
fcntl(sock, F_SETFL, O_NONBLOCK); |
247 |
|
|
return; |
248 |
|
|
} |
249 |
|
|
} |
250 |
|
|
fatal("Socket table is full!", 0); |
251 |
|
|
} |
252 |
|
|
|
253 |
|
|
int getsock(int options) |
254 |
|
|
{ |
255 |
|
|
int sock = socket(AF_INET, SOCK_STREAM, 0); |
256 |
|
|
|
257 |
|
|
if (sock < 0) |
258 |
|
|
fatal("Can't open a socket at all!", 0); |
259 |
|
|
setsock(sock, options); |
260 |
|
|
return sock; |
261 |
|
|
} |
262 |
|
|
|
263 |
|
|
/* done with a socket */ |
264 |
|
|
void killsock(int sock) |
265 |
|
|
{ |
266 |
|
|
int i; |
267 |
|
|
|
268 |
|
|
for (i = 0; i < MAXSOCKS; i++) { |
269 |
|
|
if (socklist[i].sock == sock) { |
270 |
|
|
close(socklist[i].sock); |
271 |
|
|
if (socklist[i].inbuf != NULL) { |
272 |
|
|
nfree(socklist[i].inbuf); |
273 |
|
|
socklist[i].inbuf = NULL; |
274 |
|
|
} |
275 |
|
|
if (socklist[i].outbuf != NULL) { |
276 |
|
|
nfree(socklist[i].outbuf); |
277 |
|
|
socklist[i].outbuf = NULL; |
278 |
|
|
socklist[i].outbuflen = 0; |
279 |
|
|
} |
280 |
|
|
socklist[i].flags = SOCK_UNUSED; |
281 |
|
|
return; |
282 |
|
|
} |
283 |
|
|
} |
284 |
|
|
putlog(LOG_MISC, "*", "Attempt to kill un-allocated socket %d !!", sock); |
285 |
|
|
} |
286 |
|
|
|
287 |
|
|
/* send connection request to proxy */ |
288 |
|
|
static int proxy_connect(int sock, char *host, int port, int proxy) |
289 |
|
|
{ |
290 |
|
|
unsigned char x[10]; |
291 |
|
|
struct hostent *hp; |
292 |
|
|
char s[30]; |
293 |
poptix |
1.4 |
int i; |
294 |
segfault |
1.1 |
|
295 |
|
|
/* socks proxy */ |
296 |
|
|
if (proxy == PROXY_SOCKS) { |
297 |
|
|
/* numeric IP? */ |
298 |
|
|
if ((host[strlen(host) - 1] >= '0') && (host[strlen(host) - 1] <= '9')) { |
299 |
guppy |
1.2 |
IP ip = ((IP) inet_addr(host)); /* drummer */ |
300 |
segfault |
1.1 |
my_memcpy((char *) x, (char *) &ip, 4); /* Beige@Efnet */ |
301 |
|
|
} else { |
302 |
|
|
/* no, must be host.domain */ |
303 |
|
|
if (!setjmp(alarmret)) { |
304 |
|
|
alarm(resolve_timeout); |
305 |
|
|
hp = gethostbyname(host); |
306 |
|
|
alarm(0); |
307 |
|
|
} else { |
308 |
|
|
hp = NULL; |
309 |
|
|
} |
310 |
|
|
if (hp == NULL) { |
311 |
|
|
killsock(sock); |
312 |
|
|
return -2; |
313 |
|
|
} |
314 |
|
|
my_memcpy((char *) x, (char *) hp->h_addr, hp->h_length); |
315 |
|
|
} |
316 |
poptix |
1.4 |
for (i = 0; i < MAXSOCKS; i++) { |
317 |
|
|
if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == sock)) |
318 |
|
|
socklist[i].flags |= SOCK_PROXYWAIT; /* drummer */ |
319 |
|
|
} |
320 |
segfault |
1.1 |
sprintf(s, "\004\001%c%c%c%c%c%c%s", (port >> 8) % 256, (port % 256), |
321 |
|
|
x[0], x[1], x[2], x[3], botuser); |
322 |
guppy |
1.5 |
tputs(sock, s, strlen(botuser) + 9); /* drummer */ |
323 |
segfault |
1.1 |
} else if (proxy == PROXY_SUN) { |
324 |
|
|
sprintf(s, "%s %d\n", host, port); |
325 |
guppy |
1.5 |
tputs(sock, s, strlen(s)); /* drummer */ |
326 |
segfault |
1.1 |
} |
327 |
|
|
return sock; |
328 |
|
|
} |
329 |
|
|
|
330 |
|
|
/* starts a connection attempt to a socket |
331 |
|
|
* returns <0 if connection refused: |
332 |
|
|
* -1 neterror() type error |
333 |
|
|
* -2 can't resolve hostname */ |
334 |
|
|
int open_telnet_raw(int sock, char *server, int sport) |
335 |
|
|
{ |
336 |
|
|
struct sockaddr_in name; |
337 |
|
|
struct hostent *hp; |
338 |
|
|
char host[121]; |
339 |
|
|
int i, port; |
340 |
|
|
volatile int proxy; |
341 |
|
|
|
342 |
|
|
/* firewall? use socks */ |
343 |
|
|
if (firewall[0]) { |
344 |
|
|
if (firewall[0] == '!') { |
345 |
|
|
proxy = PROXY_SUN; |
346 |
|
|
strcpy(host, &firewall[1]); |
347 |
|
|
} else { |
348 |
|
|
proxy = PROXY_SOCKS; |
349 |
|
|
strcpy(host, firewall); |
350 |
|
|
} |
351 |
|
|
port = firewallport; |
352 |
|
|
} else { |
353 |
|
|
proxy = 0; |
354 |
|
|
strcpy(host, server); |
355 |
|
|
port = sport; |
356 |
|
|
} |
357 |
|
|
/* patch by tris for multi-hosted machines: */ |
358 |
|
|
bzero((char *) &name, sizeof(struct sockaddr_in)); |
359 |
|
|
|
360 |
|
|
name.sin_family = AF_INET; |
361 |
|
|
name.sin_addr.s_addr = (myip[0] ? getmyip() : INADDR_ANY); |
362 |
|
|
if (bind(sock, (struct sockaddr *) &name, sizeof(name)) < 0) { |
363 |
|
|
killsock(sock); |
364 |
|
|
return -1; |
365 |
|
|
} |
366 |
|
|
bzero((char *) &name, sizeof(struct sockaddr_in)); |
367 |
|
|
|
368 |
|
|
name.sin_family = AF_INET; |
369 |
|
|
name.sin_port = my_htons(port); |
370 |
|
|
/* numeric IP? */ |
371 |
|
|
if ((host[strlen(host) - 1] >= '0') && (host[strlen(host) - 1] <= '9')) |
372 |
|
|
name.sin_addr.s_addr = inet_addr(host); |
373 |
|
|
else { |
374 |
|
|
/* no, must be host.domain */ |
375 |
|
|
if (!setjmp(alarmret)) { |
376 |
|
|
alarm(resolve_timeout); |
377 |
|
|
hp = gethostbyname(host); |
378 |
|
|
alarm(0); |
379 |
|
|
} else { |
380 |
|
|
hp = NULL; |
381 |
|
|
} |
382 |
|
|
if (hp == NULL) { |
383 |
|
|
killsock(sock); |
384 |
|
|
return -2; |
385 |
|
|
} |
386 |
|
|
my_memcpy((char *) &name.sin_addr, hp->h_addr, hp->h_length); |
387 |
|
|
name.sin_family = hp->h_addrtype; |
388 |
|
|
} |
389 |
|
|
for (i = 0; i < MAXSOCKS; i++) { |
390 |
|
|
if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == sock)) |
391 |
|
|
socklist[i].flags |= SOCK_CONNECT; |
392 |
|
|
} |
393 |
|
|
if (connect(sock, (struct sockaddr *) &name, |
394 |
|
|
sizeof(struct sockaddr_in)) < 0) { |
395 |
|
|
if (errno == EINPROGRESS) { |
396 |
|
|
/* firewall? announce connect attempt to proxy */ |
397 |
|
|
if (firewall[0]) |
398 |
|
|
return proxy_connect(sock, server, sport, proxy); |
399 |
|
|
return sock; /* async success! */ |
400 |
|
|
} else { |
401 |
|
|
killsock(sock); |
402 |
|
|
return -1; |
403 |
|
|
} |
404 |
|
|
} |
405 |
|
|
/* synchronous? :/ */ |
406 |
|
|
if (firewall[0]) |
407 |
|
|
return proxy_connect(sock, server, sport, proxy); |
408 |
|
|
return sock; |
409 |
|
|
} |
410 |
|
|
|
411 |
|
|
/* ordinary non-binary connection attempt */ |
412 |
|
|
int open_telnet(char *server, int port) |
413 |
|
|
{ |
414 |
|
|
return open_telnet_raw(getsock(0), server, port); |
415 |
|
|
} |
416 |
|
|
|
417 |
|
|
/* returns a socket number for a listening socket that will accept any |
418 |
|
|
* connection -- port # is returned in port */ |
419 |
|
|
int open_listen(int *port) |
420 |
|
|
{ |
421 |
|
|
int sock, addrlen; |
422 |
|
|
struct sockaddr_in name; |
423 |
|
|
|
424 |
|
|
if (firewall[0]) { |
425 |
|
|
/* FIXME: can't do listen port thru firewall yet */ |
426 |
|
|
putlog(LOG_ALL, "*", "!! Cant open a listen port (you are using a firewall)\n"); |
427 |
|
|
return -1; |
428 |
|
|
} |
429 |
|
|
sock = getsock(SOCK_LISTEN); |
430 |
|
|
bzero((char *) &name, sizeof(struct sockaddr_in)); |
431 |
|
|
|
432 |
|
|
name.sin_family = AF_INET; |
433 |
|
|
name.sin_port = my_htons(*port); /* 0 = just assign us a port */ |
434 |
|
|
name.sin_addr.s_addr = (myip[0] ? getmyip() : INADDR_ANY); |
435 |
|
|
if (bind(sock, (struct sockaddr *) &name, sizeof(name)) < 0) { |
436 |
|
|
killsock(sock); |
437 |
|
|
return -1; |
438 |
|
|
} |
439 |
|
|
/* what port are we on? */ |
440 |
|
|
addrlen = sizeof(name); |
441 |
|
|
if (getsockname(sock, (struct sockaddr *) &name, &addrlen) < 0) { |
442 |
|
|
killsock(sock); |
443 |
|
|
return -1; |
444 |
|
|
} |
445 |
|
|
*port = my_ntohs(name.sin_port); |
446 |
|
|
if (listen(sock, 1) < 0) { |
447 |
|
|
killsock(sock); |
448 |
|
|
return -1; |
449 |
|
|
} |
450 |
|
|
return sock; |
451 |
|
|
} |
452 |
|
|
|
453 |
|
|
/* given network-style IP address, return hostname */ |
454 |
|
|
/* hostname will be "##.##.##.##" format if there was an error */ |
455 |
|
|
char *hostnamefromip(unsigned long ip) |
456 |
|
|
{ |
457 |
|
|
struct hostent *hp; |
458 |
|
|
unsigned long addr = ip; |
459 |
|
|
unsigned char *p; |
460 |
|
|
static char s[121]; |
461 |
|
|
|
462 |
|
|
if (!setjmp(alarmret)) { |
463 |
|
|
alarm(resolve_timeout); |
464 |
|
|
hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET); |
465 |
|
|
alarm(0); |
466 |
|
|
} else { |
467 |
|
|
hp = NULL; |
468 |
|
|
} |
469 |
|
|
if (hp == NULL) { |
470 |
|
|
p = (unsigned char *) &addr; |
471 |
|
|
sprintf(s, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]); |
472 |
|
|
return s; |
473 |
|
|
} |
474 |
|
|
strncpy(s, hp->h_name, 120); |
475 |
|
|
s[120] = 0; |
476 |
|
|
return s; |
477 |
|
|
} |
478 |
|
|
|
479 |
|
|
/* short routine to answer a connect received on a socket made previously |
480 |
|
|
* by open_listen ... returns hostname of the caller & the new socket |
481 |
|
|
* does NOT dispose of old "public" socket! */ |
482 |
|
|
int answer(int sock, char *caller, unsigned long *ip, |
483 |
|
|
unsigned short *port, int binary) |
484 |
|
|
{ |
485 |
|
|
int new_sock, addrlen; |
486 |
|
|
struct sockaddr_in from; |
487 |
|
|
addrlen = sizeof(struct sockaddr); |
488 |
|
|
|
489 |
|
|
new_sock = accept(sock, (struct sockaddr *) &from, &addrlen); |
490 |
|
|
if (new_sock < 0) |
491 |
|
|
return -1; |
492 |
|
|
if (ip != NULL) { |
493 |
|
|
*ip = from.sin_addr.s_addr; |
494 |
|
|
strncpy(caller, hostnamefromip(*ip), 120); |
495 |
|
|
caller[120] = 0; |
496 |
|
|
*ip = my_ntohl(*ip); |
497 |
|
|
} |
498 |
|
|
if (port != NULL) |
499 |
|
|
*port = my_ntohs(from.sin_port); |
500 |
|
|
/* set up all the normal socket crap */ |
501 |
|
|
setsock(new_sock, (binary ? SOCK_BINARY : 0)); |
502 |
|
|
return new_sock; |
503 |
|
|
} |
504 |
|
|
|
505 |
|
|
/* like open_telnet, but uses server & port specifications of dcc */ |
506 |
|
|
int open_telnet_dcc(int sock, char *server, char *port) |
507 |
|
|
{ |
508 |
|
|
int p; |
509 |
|
|
unsigned long addr; |
510 |
|
|
char sv[121]; |
511 |
|
|
unsigned char c[4]; |
512 |
|
|
|
513 |
|
|
if (port != NULL) |
514 |
|
|
p = atoi(port); |
515 |
|
|
else |
516 |
|
|
p = 2000; |
517 |
|
|
if (server != NULL) |
518 |
|
|
addr = my_atoul(server); |
519 |
|
|
else |
520 |
|
|
addr = 0L; |
521 |
|
|
if (addr < (1 << 24)) |
522 |
|
|
return -3; /* fake address */ |
523 |
|
|
c[0] = (addr >> 24) & 0xff; |
524 |
|
|
c[1] = (addr >> 16) & 0xff; |
525 |
|
|
c[2] = (addr >> 8) & 0xff; |
526 |
|
|
c[3] = addr & 0xff; |
527 |
|
|
sprintf(sv, "%u.%u.%u.%u", c[0], c[1], c[2], c[3]); |
528 |
|
|
/* strcpy(sv,hostnamefromip(addr)); */ |
529 |
|
|
p = open_telnet_raw(sock, sv, p); |
530 |
|
|
return p; |
531 |
|
|
} |
532 |
|
|
|
533 |
|
|
/* all new replacements for mtgets/mtread */ |
534 |
|
|
|
535 |
|
|
/* attempts to read from all the sockets in socklist |
536 |
|
|
* fills s with up to 511 bytes if available, and returns the array index |
537 |
|
|
* on EOF, returns -1, with socket in len |
538 |
|
|
* on socket error, returns -2 |
539 |
|
|
* if nothing is ready, returns -3 */ |
540 |
|
|
static int sockread(char *s, int *len) |
541 |
|
|
{ |
542 |
|
|
fd_set fd; |
543 |
|
|
int fds, i, x; |
544 |
|
|
struct timeval t; |
545 |
|
|
int grab = 511; |
546 |
|
|
|
547 |
|
|
fds = getdtablesize(); |
548 |
|
|
#ifdef FD_SETSIZE |
549 |
|
|
if (fds > FD_SETSIZE) |
550 |
|
|
fds = FD_SETSIZE; /* fixes YET ANOTHER freebsd bug!!! */ |
551 |
|
|
#endif |
552 |
|
|
/* timeout: 1 sec */ |
553 |
|
|
t.tv_sec = 1; |
554 |
|
|
t.tv_usec = 0; |
555 |
|
|
FD_ZERO(&fd); |
556 |
|
|
for (i = 0; i < MAXSOCKS; i++) |
557 |
|
|
if (!(socklist[i].flags & SOCK_UNUSED)) { |
558 |
|
|
if ((socklist[i].sock == STDOUT) && !backgrd) |
559 |
|
|
FD_SET(STDIN, &fd); |
560 |
|
|
else |
561 |
|
|
FD_SET(socklist[i].sock, &fd); |
562 |
|
|
} |
563 |
|
|
#ifdef HPUX_HACKS |
564 |
|
|
#ifndef HPUX10_HACKS |
565 |
|
|
x = select(fds, (int *) &fd, (int *) NULL, (int *) NULL, &t); |
566 |
|
|
#else |
567 |
|
|
x = select(fds, &fd, NULL, NULL, &t); |
568 |
|
|
#endif |
569 |
|
|
#else |
570 |
|
|
x = select(fds, &fd, NULL, NULL, &t); |
571 |
|
|
#endif |
572 |
|
|
if (x > 0) { |
573 |
|
|
/* something happened */ |
574 |
|
|
for (i = 0; i < MAXSOCKS; i++) { |
575 |
|
|
if ((!(socklist[i].flags & SOCK_UNUSED)) && |
576 |
|
|
((FD_ISSET(socklist[i].sock, &fd)) || |
577 |
|
|
((socklist[i].sock == STDOUT) && (!backgrd) && |
578 |
|
|
(FD_ISSET(STDIN, &fd))))) { |
579 |
|
|
if (socklist[i].flags & (SOCK_LISTEN | SOCK_CONNECT)) { |
580 |
|
|
/* listening socket -- don't read, just return activity */ |
581 |
|
|
/* same for connection attempt */ |
582 |
|
|
/* (for strong connections, require a read to succeed first) */ |
583 |
poptix |
1.4 |
if (socklist[i].flags & SOCK_PROXYWAIT) { /* drummer */ |
584 |
segfault |
1.1 |
/* hang around to get the return code from proxy */ |
585 |
guppy |
1.5 |
grab = 10; |
586 |
segfault |
1.1 |
} else if (!(socklist[i].flags & SOCK_STRONGCONN)) { |
587 |
|
|
debug1("net: connect! sock %d", socklist[i].sock); |
588 |
|
|
s[0] = 0; |
589 |
|
|
*len = 0; |
590 |
|
|
return i; |
591 |
|
|
} |
592 |
|
|
} |
593 |
|
|
if ((socklist[i].sock == STDOUT) && !backgrd) |
594 |
|
|
x = read(STDIN, s, grab); |
595 |
|
|
else |
596 |
|
|
x = read(socklist[i].sock, s, grab); |
597 |
|
|
if (x <= 0) { /* eof */ |
598 |
|
|
if (x == EAGAIN) { |
599 |
|
|
s[0] = 0; |
600 |
|
|
*len = 0; |
601 |
|
|
return -3; |
602 |
|
|
} |
603 |
|
|
*len = socklist[i].sock; |
604 |
|
|
socklist[i].flags &= ~SOCK_CONNECT; |
605 |
|
|
debug1("net: eof!(read) socket %d", socklist[i].sock); |
606 |
|
|
return -1; |
607 |
|
|
} |
608 |
|
|
s[x] = 0; |
609 |
|
|
*len = x; |
610 |
poptix |
1.4 |
if (socklist[i].flags & SOCK_PROXYWAIT) { |
611 |
|
|
debug2("net: socket: %d proxy errno: %d", socklist[i].sock, s[1]); |
612 |
|
|
socklist[i].flags &= ~(SOCK_CONNECT | SOCK_PROXYWAIT); |
613 |
segfault |
1.1 |
switch (s[1]) { |
614 |
|
|
case 90: /* success */ |
615 |
|
|
s[0] = 0; |
616 |
|
|
*len = 0; |
617 |
|
|
return i; |
618 |
|
|
case 91: /* failed */ |
619 |
|
|
errno = ECONNREFUSED; |
620 |
|
|
break; |
621 |
|
|
case 92: /* no identd */ |
622 |
|
|
case 93: /* identd said wrong username */ |
623 |
|
|
errno = ENETUNREACH; |
624 |
|
|
break; |
625 |
|
|
/* a better error message would be "socks misconfigured" */ |
626 |
|
|
/* or "identd not working" but this is simplest */ |
627 |
|
|
} |
628 |
|
|
*len = socklist[i].sock; |
629 |
|
|
return -1; |
630 |
|
|
} |
631 |
|
|
return i; |
632 |
|
|
} |
633 |
|
|
} |
634 |
|
|
} else if (x == -1) |
635 |
|
|
return -2; /* socket error */ |
636 |
|
|
else { |
637 |
|
|
s[0] = 0; |
638 |
|
|
*len = 0; |
639 |
|
|
} |
640 |
|
|
return -3; |
641 |
|
|
} |
642 |
|
|
|
643 |
|
|
/* sockgets: buffer and read from sockets |
644 |
|
|
* |
645 |
|
|
* attempts to read from all registered sockets for up to one second. if |
646 |
|
|
* after one second, no complete data has been received from any of the |
647 |
|
|
* sockets, 's' will be empty, 'len' will be 0, and sockgets will return -3. |
648 |
|
|
* if there is returnable data received from a socket, the data will be |
649 |
|
|
* in 's' (null-terminated if non-binary), the length will be returned |
650 |
|
|
* in len, and the socket number will be returned. |
651 |
|
|
* normal sockets have their input buffered, and each call to sockgets |
652 |
|
|
* will return one line terminated with a '\n'. binary sockets are not |
653 |
|
|
* buffered and return whatever coems in as soon as it arrives. |
654 |
|
|
* listening sockets will return an empty string when a connection comes in. |
655 |
|
|
* connecting sockets will return an empty string on a successful connect, |
656 |
|
|
* or EOF on a failed connect. |
657 |
|
|
* if an EOF is detected from any of the sockets, that socket number will be |
658 |
|
|
* put in len, and -1 will be returned. |
659 |
|
|
* the maximum length of the string returned is 512 (including null) |
660 |
|
|
*/ |
661 |
|
|
|
662 |
|
|
int sockgets(char *s, int *len) |
663 |
|
|
{ |
664 |
|
|
char xx[514], *p, *px; |
665 |
|
|
int ret, i, data = 0; |
666 |
|
|
|
667 |
|
|
context; |
668 |
|
|
for (i = 0; i < MAXSOCKS; i++) { |
669 |
|
|
/* check for stored-up data waiting to be processed */ |
670 |
|
|
if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].inbuf != NULL)) { |
671 |
|
|
/* look for \r too cos windows can't follow RFCs */ |
672 |
|
|
p = strchr(socklist[i].inbuf, '\n'); |
673 |
|
|
if (p == NULL) |
674 |
|
|
p = strchr(socklist[i].inbuf, '\r'); |
675 |
|
|
if (p != NULL) { |
676 |
|
|
*p = 0; |
677 |
|
|
if (strlen(socklist[i].inbuf) > 510) |
678 |
|
|
socklist[i].inbuf[510] = 0; |
679 |
|
|
strcpy(s, socklist[i].inbuf); |
680 |
|
|
px = (char *) nmalloc(strlen(p + 1) + 1); |
681 |
|
|
strcpy(px, p + 1); |
682 |
|
|
nfree(socklist[i].inbuf); |
683 |
|
|
if (px[0]) |
684 |
|
|
socklist[i].inbuf = px; |
685 |
|
|
else { |
686 |
|
|
nfree(px); |
687 |
|
|
socklist[i].inbuf = NULL; |
688 |
|
|
} |
689 |
|
|
/* strip CR if this was CR/LF combo */ |
690 |
|
|
if (s[strlen(s) - 1] == '\r') |
691 |
|
|
s[strlen(s) - 1] = 0; |
692 |
|
|
*len = strlen(s); |
693 |
|
|
return socklist[i].sock; |
694 |
|
|
} |
695 |
|
|
} |
696 |
|
|
/* also check any sockets that might have EOF'd during write */ |
697 |
|
|
if (!(socklist[i].flags & SOCK_UNUSED) |
698 |
|
|
&& (socklist[i].flags & SOCK_EOFD)) { |
699 |
|
|
context; |
700 |
|
|
s[0] = 0; |
701 |
|
|
*len = socklist[i].sock; |
702 |
|
|
return -1; |
703 |
|
|
} |
704 |
|
|
} |
705 |
|
|
/* no pent-up data of any worth -- down to business */ |
706 |
|
|
context; |
707 |
|
|
*len = 0; |
708 |
|
|
ret = sockread(xx, len); |
709 |
|
|
if (ret < 0) { |
710 |
|
|
s[0] = 0; |
711 |
|
|
return ret; |
712 |
|
|
} |
713 |
|
|
/* binary and listening sockets don't get buffered */ |
714 |
|
|
if (socklist[ret].flags & SOCK_CONNECT) { |
715 |
|
|
if (socklist[ret].flags & SOCK_STRONGCONN) { |
716 |
|
|
socklist[ret].flags &= ~SOCK_STRONGCONN; |
717 |
|
|
/* buffer any data that came in, for future read */ |
718 |
|
|
socklist[ret].inbuf = (char *) nmalloc(strlen(xx) + 1); |
719 |
|
|
strcpy(socklist[ret].inbuf, xx); |
720 |
|
|
} |
721 |
|
|
socklist[ret].flags &= ~SOCK_CONNECT; |
722 |
|
|
s[0] = 0; |
723 |
|
|
return socklist[ret].sock; |
724 |
|
|
} |
725 |
|
|
if (socklist[ret].flags & SOCK_BINARY) { |
726 |
|
|
my_memcpy(s, xx, *len); |
727 |
|
|
return socklist[ret].sock; |
728 |
|
|
} |
729 |
|
|
if (socklist[ret].flags & SOCK_LISTEN) |
730 |
|
|
return socklist[ret].sock; |
731 |
|
|
context; |
732 |
|
|
/* might be necessary to prepend stored-up data! */ |
733 |
|
|
if (socklist[ret].inbuf != NULL) { |
734 |
|
|
p = socklist[ret].inbuf; |
735 |
|
|
socklist[ret].inbuf = (char *) nmalloc(strlen(p) + strlen(xx) + 1); |
736 |
|
|
strcpy(socklist[ret].inbuf, p); |
737 |
|
|
strcat(socklist[ret].inbuf, xx); |
738 |
|
|
nfree(p); |
739 |
|
|
if (strlen(socklist[ret].inbuf) < 512) { |
740 |
|
|
strcpy(xx, socklist[ret].inbuf); |
741 |
|
|
nfree(socklist[ret].inbuf); |
742 |
|
|
socklist[ret].inbuf = NULL; |
743 |
|
|
} else { |
744 |
|
|
p = socklist[ret].inbuf; |
745 |
|
|
socklist[ret].inbuf = (char *) nmalloc(strlen(p) - 509); |
746 |
|
|
strcpy(socklist[ret].inbuf, p + 510); |
747 |
|
|
*(p + 510) = 0; |
748 |
|
|
strcpy(xx, p); |
749 |
|
|
nfree(p); |
750 |
|
|
/* (leave the rest to be post-pended later) */ |
751 |
|
|
} |
752 |
|
|
} |
753 |
|
|
context; |
754 |
|
|
/* look for EOL marker; if it's there, i have something to show */ |
755 |
|
|
p = strchr(xx, '\n'); |
756 |
|
|
if (p == NULL) |
757 |
|
|
p = strchr(xx, '\r'); |
758 |
|
|
if (p != NULL) { |
759 |
|
|
*p = 0; |
760 |
|
|
strcpy(s, xx); |
761 |
|
|
strcpy(xx, p + 1); |
762 |
|
|
if (s[strlen(s) - 1] == '\r') |
763 |
|
|
s[strlen(s) - 1] = 0; |
764 |
|
|
data = 1; /* DCC_CHAT may now need to process a |
765 |
|
|
* blank line */ |
766 |
|
|
/* NO! */ |
767 |
|
|
/* if (!s[0]) strcpy(s," "); */ |
768 |
|
|
} else { |
769 |
|
|
s[0] = 0; |
770 |
|
|
if (strlen(xx) >= 510) { |
771 |
|
|
/* string is too long, so just insert fake \n */ |
772 |
|
|
strcpy(s, xx); |
773 |
|
|
xx[0] = 0; |
774 |
|
|
data = 1; |
775 |
|
|
} |
776 |
|
|
} |
777 |
|
|
context; |
778 |
|
|
*len = strlen(s); |
779 |
|
|
/* anything left that needs to be saved? */ |
780 |
|
|
if (!xx[0]) { |
781 |
|
|
if (data) |
782 |
|
|
return socklist[ret].sock; |
783 |
|
|
else |
784 |
|
|
return -3; |
785 |
|
|
} |
786 |
|
|
context; |
787 |
|
|
/* prepend old data back */ |
788 |
|
|
if (socklist[ret].inbuf != NULL) { |
789 |
|
|
contextnote("dw's bug"); |
790 |
|
|
p = socklist[ret].inbuf; |
791 |
|
|
socklist[ret].inbuf = (char *) nmalloc(strlen(p) + strlen(xx) + 1); |
792 |
|
|
strcpy(socklist[ret].inbuf, xx); |
793 |
|
|
strcat(socklist[ret].inbuf, p); |
794 |
|
|
nfree(p); |
795 |
|
|
} else { |
796 |
|
|
contextnote("dw's bug"); |
797 |
|
|
socklist[ret].inbuf = (char *) nmalloc(strlen(xx) + 1); |
798 |
|
|
strcpy(socklist[ret].inbuf, xx); |
799 |
|
|
} |
800 |
|
|
contextnote("dw's bug"); |
801 |
|
|
if (data) { |
802 |
|
|
contextnote("dw's bug"); |
803 |
|
|
return socklist[ret].sock; |
804 |
|
|
} else { |
805 |
|
|
contextnote("dw's bug"); |
806 |
|
|
return -3; |
807 |
|
|
} |
808 |
|
|
} |
809 |
|
|
|
810 |
|
|
/* dump something to a socket */ |
811 |
|
|
/* DO NOT PUT CONTEXTS IN HERE IF YOU WANT DEBUG TO BE MEANINGFUL!!! */ |
812 |
|
|
void tputs(int z, char *s, unsigned int len) |
813 |
|
|
{ |
814 |
|
|
int i, x; |
815 |
|
|
char *p; |
816 |
|
|
|
817 |
|
|
if (z < 0) |
818 |
|
|
return; /* um... HELLO?! sanity check please! */ |
819 |
|
|
if (((z == STDOUT) || (z == STDERR)) && (!backgrd || use_stderr)) { |
820 |
|
|
write(z, s, len); |
821 |
|
|
return; |
822 |
|
|
} |
823 |
|
|
for (i = 0; i < MAXSOCKS; i++) { |
824 |
|
|
if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == z)) { |
825 |
guppy |
1.5 |
if (socklist[i].outbuf != NULL) { |
826 |
|
|
/* already queueing: just add it */ |
827 |
|
|
p = (char *) nrealloc(socklist[i].outbuf, socklist[i].outbuflen + len); |
828 |
segfault |
1.1 |
my_memcpy(p + socklist[i].outbuflen, s, len); |
829 |
|
|
socklist[i].outbuf = p; |
830 |
|
|
socklist[i].outbuflen += len; |
831 |
|
|
return; |
832 |
|
|
} |
833 |
|
|
/* try. */ |
834 |
|
|
x = write(z, s, len); |
835 |
|
|
if (x == (-1)) |
836 |
|
|
x = 0; |
837 |
|
|
if (x < len) { |
838 |
|
|
/* socket is full, queue it */ |
839 |
|
|
socklist[i].outbuf = (char *) nmalloc(len - x); |
840 |
|
|
my_memcpy(socklist[i].outbuf, &s[x], len - x); |
841 |
|
|
socklist[i].outbuflen = len - x; |
842 |
|
|
} |
843 |
|
|
return; |
844 |
|
|
} |
845 |
|
|
} |
846 |
|
|
putlog(LOG_MISC, "*", "!!! writing to nonexistent socket: %d", z); |
847 |
|
|
s[strlen(s) - 1] = 0; |
848 |
|
|
putlog(LOG_MISC, "*", "!-> '%s'", s); |
849 |
|
|
} |
850 |
|
|
|
851 |
|
|
/* tputs might queue data for sockets, let's dump as much of it as |
852 |
|
|
* possible */ |
853 |
|
|
void dequeue_sockets() |
854 |
|
|
{ |
855 |
|
|
int i, x; |
856 |
|
|
|
857 |
guppy |
1.5 |
for (i = 0; i < MAXSOCKS; i++) { |
858 |
|
|
if (!(socklist[i].flags & SOCK_UNUSED) && |
859 |
segfault |
1.1 |
(socklist[i].outbuf != NULL)) { |
860 |
|
|
/* trick tputs into doing the work */ |
861 |
|
|
x = write(socklist[i].sock, socklist[i].outbuf, |
862 |
|
|
socklist[i].outbuflen); |
863 |
|
|
if ((x < 0) && (errno != EAGAIN) |
864 |
|
|
#ifdef EBADSLT |
865 |
|
|
&& (errno != EBADSLT) |
866 |
|
|
#endif |
867 |
|
|
#ifdef ENOTCONN |
868 |
|
|
&& (errno != ENOTCONN) |
869 |
|
|
#endif |
870 |
|
|
) { |
871 |
|
|
/* this detects an EOF during writing */ |
872 |
|
|
debug3("net: eof!(write) socket %d (%s,%d)", socklist[i].sock, |
873 |
|
|
strerror(errno), errno); |
874 |
|
|
socklist[i].flags |= SOCK_EOFD; |
875 |
|
|
} else if (x == socklist[i].outbuflen) { |
876 |
|
|
/* if the whole buffer was sent, nuke it */ |
877 |
|
|
nfree(socklist[i].outbuf); |
878 |
|
|
socklist[i].outbuf = NULL; |
879 |
|
|
socklist[i].outbuflen = 0; |
880 |
|
|
} else if (x > 0) { |
881 |
|
|
char *p = socklist[i].outbuf; |
882 |
|
|
|
883 |
|
|
/* this removes any sent bytes from the beginning of the buffer */ |
884 |
|
|
socklist[i].outbuf = (char *) nmalloc(socklist[i].outbuflen - x); |
885 |
|
|
my_memcpy(socklist[i].outbuf, p + x, socklist[i].outbuflen - x); |
886 |
|
|
socklist[i].outbuflen -= x; |
887 |
|
|
nfree(p); |
888 |
|
|
} |
889 |
|
|
} |
890 |
|
|
} |
891 |
|
|
} |
892 |
|
|
|
893 |
|
|
/* DEBUGGING STUFF */ |
894 |
|
|
|
895 |
|
|
void tell_netdebug(int idx) |
896 |
|
|
{ |
897 |
|
|
int i; |
898 |
|
|
char s[80]; |
899 |
|
|
|
900 |
|
|
dprintf(idx, "Open sockets:"); |
901 |
|
|
for (i = 0; i < MAXSOCKS; i++) { |
902 |
|
|
if (!(socklist[i].flags & SOCK_UNUSED)) { |
903 |
|
|
sprintf(s, " %d", socklist[i].sock); |
904 |
|
|
if (socklist[i].flags & SOCK_BINARY) |
905 |
|
|
strcat(s, " (binary)"); |
906 |
|
|
if (socklist[i].flags & SOCK_LISTEN) |
907 |
|
|
strcat(s, " (listen)"); |
908 |
|
|
if (socklist[i].flags & SOCK_CONNECT) |
909 |
|
|
strcat(s, " (connecting)"); |
910 |
|
|
if (socklist[i].flags & SOCK_STRONGCONN) |
911 |
|
|
strcat(s, " (strong)"); |
912 |
|
|
if (socklist[i].flags & SOCK_NONSOCK) |
913 |
|
|
strcat(s, " (file)"); |
914 |
|
|
if (socklist[i].inbuf != NULL) |
915 |
|
|
sprintf(&s[strlen(s)], " (inbuf: %04X)", strlen(socklist[i].inbuf)); |
916 |
|
|
if (socklist[i].outbuf != NULL) |
917 |
|
|
sprintf(&s[strlen(s)], " (outbuf: %06lX)", socklist[i].outbuflen); |
918 |
|
|
strcat(s, ","); |
919 |
|
|
dprintf(idx, "%s", s); |
920 |
|
|
} |
921 |
|
|
} |
922 |
|
|
dprintf(idx, " done.\n"); |
923 |
|
|
} |
924 |
|
|
|
925 |
|
|
/* Security-flavoured sanity checking on DCC connections of all sorts can be |
926 |
|
|
* done with this routine. Feed it the proper information from your DCC |
927 |
|
|
* before you attempt the connection, and this will make an attempt at |
928 |
|
|
* figuring out if the connection is really that person, or someone screwing |
929 |
|
|
* around. It's not foolproof, but anything that fails this check probably |
930 |
|
|
* isn't going to work anyway due to masquerading firewalls, NAT routers, |
931 |
|
|
* or bugs in mIRC. */ |
932 |
|
|
int sanitycheck_dcc(char *nick, char *from, char *ipaddy, char *port) |
933 |
|
|
{ |
934 |
|
|
/* According to the latest RFC, the clients SHOULD be able to handle |
935 |
|
|
* DNS names that are up to 255 characters long. This is not broken. */ |
936 |
|
|
char hostname[256], dnsname[256], badaddress[16]; |
937 |
|
|
IP ip = my_atoul(ipaddy); |
938 |
|
|
int prt = atoi(port); |
939 |
|
|
|
940 |
|
|
/* It is disabled HERE so we only have to check in *one* spot! */ |
941 |
|
|
if (!dcc_sanitycheck) |
942 |
|
|
return 1; |
943 |
|
|
context; /* This should be pretty solid, but |
944 |
|
|
* something _might_ break. */ |
945 |
|
|
sprintf(badaddress, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff, |
946 |
|
|
(ip >> 8) & 0xff, ip & 0xff); |
947 |
|
|
if (prt < 1) { |
948 |
|
|
putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an impossible port of %u!", |
949 |
|
|
nick, from, prt); |
950 |
|
|
return 0; |
951 |
|
|
} |
952 |
|
|
if (ip < (1 << 24)) { |
953 |
|
|
putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an impossible IP of %s!", |
954 |
|
|
nick, from, badaddress); |
955 |
|
|
return 0; |
956 |
|
|
} |
957 |
|
|
/* These should pad like crazy with zeros, since 120 bytes or so is |
958 |
|
|
* where the routines providing our data currently lose interest. I'm |
959 |
|
|
* using the n-variant in case someone changes that... */ |
960 |
|
|
strncpy(hostname, extracthostname(from), 256); |
961 |
|
|
strncpy(dnsname, hostnamefromip(my_htonl(ip)), 256); |
962 |
|
|
if (!strcasecmp(hostname, dnsname)) { |
963 |
|
|
putlog(LOG_DEBUG, "*", "DNS information for submitted IP checks out."); |
964 |
|
|
return 1; |
965 |
|
|
} |
966 |
|
|
if (!strcmp(badaddress, dnsname)) |
967 |
|
|
putlog(LOG_MISC, "*", "ALERT: (%s!%s) sent a DCC request with bogus IP information of %s port %u!", |
968 |
|
|
nick, from, badaddress, prt); |
969 |
|
|
else |
970 |
segfault |
1.3 |
return 1; /* <- usually happens when we have |
971 |
|
|
a user with an unresolved hostmask! */ |
972 |
segfault |
1.1 |
return 0; |
973 |
|
|
} |