Lines 11-16
Link Here
|
11 |
* Copyright : Written by and Copyright (C) 2001 the SourceForge |
11 |
* Copyright : Written by and Copyright (C) 2001 the SourceForge |
12 |
* Privoxy team. http://www.privoxy.org/ |
12 |
* Privoxy team. http://www.privoxy.org/ |
13 |
* |
13 |
* |
|
|
14 |
* Modified by Lionel Elie Mamane <lionel@mamane.lu> |
15 |
* for IPv6 support on 8-9 December 2002, 24 January 2003, |
16 |
* 13 February 2003. |
17 |
* |
14 |
* Based on the Internet Junkbuster originally written |
18 |
* Based on the Internet Junkbuster originally written |
15 |
* by and Copyright (C) 1997 Anonymous Coders and |
19 |
* by and Copyright (C) 1997 Anonymous Coders and |
16 |
* Junkbusters Corporation. http://www.junkbusters.com |
20 |
* Junkbusters Corporation. http://www.junkbusters.com |
Lines 275-280
Link Here
|
275 |
#include "jbsockets.h" |
279 |
#include "jbsockets.h" |
276 |
#include "filters.h" |
280 |
#include "filters.h" |
277 |
#include "errlog.h" |
281 |
#include "errlog.h" |
|
|
282 |
#include "addrlist.h" |
278 |
|
283 |
|
279 |
const char jbsockets_h_rcs[] = JBSOCKETS_H_VERSION; |
284 |
const char jbsockets_h_rcs[] = JBSOCKETS_H_VERSION; |
280 |
|
285 |
|
Lines 287-427
Link Here
|
287 |
* that this is allowed according to ACL. |
292 |
* that this is allowed according to ACL. |
288 |
* |
293 |
* |
289 |
* Parameters : |
294 |
* Parameters : |
290 |
* 1 : host = hostname to connect to |
295 |
* 0 : host = hostname to connect to |
291 |
* 2 : portnum = port to connent on |
296 |
* 1 : port = port to connect on, as string |
|
|
297 |
* 2 : portnum = port to connect on, as integer |
292 |
* 3 : csp = Current client state (buffers, headers, etc...) |
298 |
* 3 : csp = Current client state (buffers, headers, etc...) |
293 |
* Not modified, only used for source IP and ACL. |
|
|
294 |
* |
299 |
* |
295 |
* Returns : JB_INVALID_SOCKET => failure, else it is the socket |
300 |
* Returns : JB_INVALID_SOCKET => failure, else it is the socket |
296 |
* file descriptor. |
301 |
* file descriptor. |
297 |
* |
302 |
* |
298 |
*********************************************************************/ |
303 |
*********************************************************************/ |
299 |
jb_socket connect_to(const char *host, int portnum, struct client_state *csp) |
304 |
jb_socket connect_to_one_ip(struct sockaddr_storage *addr, size_t addrlen, const char *host, unsigned long portnum, struct client_state *csp) |
300 |
{ |
305 |
{ |
301 |
struct sockaddr_in inaddr; |
|
|
302 |
jb_socket fd; |
303 |
int addr; |
304 |
fd_set wfds; |
305 |
struct timeval tv[1]; |
306 |
#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) |
307 |
int flags; |
308 |
#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */ |
309 |
|
310 |
#ifdef FEATURE_ACL |
306 |
#ifdef FEATURE_ACL |
311 |
struct access_control_addr dst[1]; |
307 |
if (csp) |
312 |
#endif /* def FEATURE_ACL */ |
|
|
313 |
|
314 |
memset((char *)&inaddr, 0, sizeof inaddr); |
315 |
|
316 |
if ((addr = resolve_hostname_to_ip(host)) == INADDR_NONE) |
317 |
{ |
308 |
{ |
318 |
csp->http->host_ip_addr_str = strdup("unknown"); |
309 |
struct access_control_addr dst[1]; |
319 |
return(JB_INVALID_SOCKET); |
310 |
char hostname[NI_MAXHOST]; |
320 |
} |
311 |
char port[NI_MAXSERV]; |
|
|
312 |
if (getnameinfo((struct sockaddr*)addr, addrlen, hostname, NI_MAXHOST, |
313 |
port, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV) != 0) |
314 |
{ |
315 |
log_error(LOG_LEVEL_ERROR, "connect: Could not get string address and port back from sockaddr because %E"); |
316 |
strncpy(hostname,"unknown",NI_MAXHOST); |
317 |
strncpy(port,"unknown",NI_MAXSERV); |
318 |
} |
321 |
|
319 |
|
322 |
#ifdef FEATURE_ACL |
320 |
csp->http->host_ip_addr_str = strdup(hostname); |
323 |
dst->addr = ntohl((unsigned long) addr); |
|
|
324 |
dst->port = portnum; |
325 |
|
321 |
|
326 |
if (block_acl(dst, csp)) |
322 |
dst->addr = *addr; |
327 |
{ |
323 |
dst->addrlen = addrlen; |
|
|
324 |
dst->port = portnum; |
325 |
|
326 |
if (block_acl(dst, csp)) |
327 |
{ |
328 |
#ifdef __OS2__ |
328 |
#ifdef __OS2__ |
329 |
errno = SOCEPERM; |
329 |
errno = SOCEPERM; |
330 |
#else |
330 |
#else |
331 |
errno = EPERM; |
331 |
errno = EPERM; |
332 |
#endif |
332 |
#endif |
333 |
return(JB_INVALID_SOCKET); |
333 |
return(JB_INVALID_SOCKET); |
334 |
} |
334 |
} |
335 |
#endif /* def FEATURE_ACL */ |
|
|
336 |
|
335 |
|
337 |
inaddr.sin_addr.s_addr = addr; |
|
|
338 |
inaddr.sin_family = AF_INET; |
339 |
csp->http->host_ip_addr_str = strdup(inet_ntoa(inaddr.sin_addr)); |
340 |
|
336 |
|
341 |
#ifndef _WIN32 |
|
|
342 |
if (sizeof(inaddr.sin_port) == sizeof(short)) |
343 |
#endif /* ndef _WIN32 */ |
344 |
{ |
345 |
inaddr.sin_port = htons((unsigned short) portnum); |
346 |
} |
337 |
} |
347 |
#ifndef _WIN32 |
338 |
#endif /* def FEATURE_ACL */ |
348 |
else |
339 |
|
349 |
{ |
340 |
{ |
350 |
inaddr.sin_port = htonl((unsigned long)portnum); |
341 |
jb_socket fd; |
351 |
} |
|
|
352 |
#endif /* ndef _WIN32 */ |
353 |
|
342 |
|
354 |
#ifdef _WIN32 |
343 |
#ifdef _WIN32 |
355 |
if ((fd = socket(inaddr.sin_family, SOCK_STREAM, 0)) == JB_INVALID_SOCKET) |
344 |
if ((fd = socket(addr->ss_family, SOCK_STREAM, 0)) == JB_INVALID_SOCKET) |
356 |
#else |
345 |
#else |
357 |
if ((fd = socket(inaddr.sin_family, SOCK_STREAM, 0)) < 0) |
346 |
if ((fd = socket(addr->ss_family, SOCK_STREAM, 6)) < 0) |
358 |
#endif |
347 |
#endif |
359 |
{ |
348 |
{ |
360 |
return(JB_INVALID_SOCKET); |
349 |
return(JB_INVALID_SOCKET); |
361 |
} |
350 |
} |
362 |
|
351 |
|
363 |
#ifdef TCP_NODELAY |
352 |
#ifdef TCP_NODELAY |
364 |
{ /* turn off TCP coalescence */ |
353 |
{ /* turn off TCP coalescence */ |
365 |
int mi = 1; |
354 |
int mi = 1; |
366 |
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &mi, sizeof (int)); |
355 |
setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (char *) &mi, sizeof (int)); |
367 |
} |
356 |
} |
368 |
#endif /* def TCP_NODELAY */ |
357 |
#endif /* def TCP_NODELAY */ |
369 |
|
358 |
|
370 |
#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) |
359 |
#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) |
371 |
if ((flags = fcntl(fd, F_GETFL, 0)) != -1) |
360 |
{ |
372 |
{ |
361 |
int flags; |
373 |
flags |= O_NDELAY; |
362 |
|
374 |
fcntl(fd, F_SETFL, flags); |
363 |
if ((flags = fcntl(fd, F_GETFL, 0)) != -1) |
375 |
} |
364 |
{ |
|
|
365 |
flags |= O_NDELAY; |
366 |
fcntl(fd, F_SETFL, flags); |
367 |
} |
368 |
} |
376 |
#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */ |
369 |
#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */ |
377 |
|
370 |
|
378 |
while (connect(fd, (struct sockaddr *) & inaddr, sizeof inaddr) == JB_INVALID_SOCKET) |
371 |
while (connect(fd, (struct sockaddr *) addr, addrlen) == JB_INVALID_SOCKET) |
379 |
{ |
372 |
{ |
380 |
#ifdef _WIN32 |
373 |
#ifdef _WIN32 |
381 |
if (errno == WSAEINPROGRESS) |
374 |
if (errno == WSAEINPROGRESS) |
382 |
#elif __OS2__ |
375 |
#elif __OS2__ |
383 |
if (sock_errno() == EINPROGRESS) |
376 |
if (sock_errno() == EINPROGRESS) |
384 |
#else /* ifndef _WIN32 */ |
377 |
#else /* ifndef _WIN32 */ |
385 |
if (errno == EINPROGRESS) |
378 |
if (errno == EINPROGRESS) |
386 |
#endif /* ndef _WIN32 || __OS2__ */ |
379 |
#endif /* ndef _WIN32 || __OS2__ */ |
387 |
{ |
380 |
{ |
388 |
break; |
381 |
break; |
389 |
} |
382 |
} |
390 |
|
383 |
|
391 |
#ifdef __OS2__ |
384 |
#ifdef __OS2__ |
392 |
if (sock_errno() != EINTR) |
385 |
if (sock_errno() != EINTR) |
393 |
#else |
386 |
#else |
394 |
if (errno != EINTR) |
387 |
if (errno != EINTR) |
395 |
#endif /* __OS2__ */ |
388 |
#endif /* __OS2__ */ |
|
|
389 |
{ |
390 |
close_socket(fd); |
391 |
return(JB_INVALID_SOCKET); |
392 |
} |
393 |
} |
394 |
|
395 |
#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) |
396 |
{ |
396 |
{ |
397 |
close_socket(fd); |
397 |
int flags; |
398 |
return(JB_INVALID_SOCKET); |
398 |
if ((flags = fcntl(fd, F_GETFL, 0)) != -1) |
|
|
399 |
{ |
400 |
flags &= ~O_NDELAY; |
401 |
fcntl(fd, F_SETFL, flags); |
402 |
} |
399 |
} |
403 |
} |
400 |
} |
404 |
#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */ |
401 |
|
405 |
|
|
|
406 |
{ |
407 |
fd_set wfds; |
408 |
struct timeval tv[1]; |
409 |
|
410 |
/* wait for connection to complete */ |
411 |
FD_ZERO(&wfds); |
412 |
FD_SET(fd, &wfds); |
413 |
|
414 |
tv->tv_sec = 30; |
415 |
tv->tv_usec = 0; |
416 |
|
417 |
/* MS Windows uses int, not SOCKET, for the 1st arg of select(). Wierd! */ |
418 |
if (select((int)fd + 1, NULL, &wfds, NULL, tv) <= 0) |
419 |
{ |
420 |
close_socket(fd); |
421 |
return(JB_INVALID_SOCKET); |
422 |
} |
402 |
#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) |
423 |
#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) |
403 |
if (flags != -1) |
424 |
else |
404 |
{ |
425 |
{ |
405 |
flags &= ~O_NDELAY; |
426 |
int connect_result; |
406 |
fcntl(fd, F_SETFL, flags); |
427 |
socklen_t connect_result_len = sizeof connect_result; |
407 |
} |
428 |
|
|
|
429 |
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &connect_result, &connect_result_len) != 0) |
430 |
{ |
431 |
log_error(LOG_LEVEL_ERROR, "Could not determine whether connection to %s port %d was successful because %E. Assuming failure.", |
432 |
csp->http->host_ip_addr_str, portnum); |
433 |
close_socket(fd); |
434 |
return(JB_INVALID_SOCKET); |
435 |
} |
436 |
else if( connect_result != 0 ) |
437 |
{ |
438 |
log_error(LOG_LEVEL_CONNECT, "Connection to %s port %d failed because %s.", |
439 |
csp->http->host_ip_addr_str, portnum, strerror(connect_result)); |
440 |
close_socket(fd); |
441 |
return(JB_INVALID_SOCKET); |
442 |
} |
443 |
} |
408 |
#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */ |
444 |
#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */ |
|
|
445 |
} |
446 |
return(fd); |
447 |
} |
448 |
} |
409 |
|
449 |
|
410 |
/* wait for connection to complete */ |
450 |
jb_socket connect_to(const char *host, const char *port, unsigned long portnum, int pf, struct client_state *csp) |
411 |
FD_ZERO(&wfds); |
451 |
{ |
412 |
FD_SET(fd, &wfds); |
452 |
jb_socket fd = JB_INVALID_SOCKET; |
|
|
453 |
struct sockaddr_storage addr; |
454 |
addr_list *addrs, *addrs_to_try; |
413 |
|
455 |
|
414 |
tv->tv_sec = 30; |
456 |
addrs = resolve_hostname_to_ip(host,port,pf); |
415 |
tv->tv_usec = 0; |
|
|
416 |
|
457 |
|
417 |
/* MS Windows uses int, not SOCKET, for the 1st arg of select(). Wierd! */ |
458 |
if (is_nil_addr_list(addrs)) |
418 |
if (select((int)fd + 1, NULL, &wfds, NULL, tv) <= 0) |
|
|
419 |
{ |
459 |
{ |
420 |
close_socket(fd); |
460 |
errno = EINVAL; |
421 |
return(JB_INVALID_SOCKET); |
461 |
return fd; |
|
|
462 |
} |
463 |
|
464 |
for(addrs_to_try=addrs; |
465 |
!is_nil_addr_list(addrs_to_try); |
466 |
addrs_to_try = tail_addr_list(addrs_to_try)) |
467 |
{ |
468 |
size_t addrlen; |
469 |
memset((char *)&addr, 0, sizeof addr); |
470 |
cpy_head_addr_list(addrs_to_try, &addr,&addrlen); |
471 |
fd = connect_to_one_ip(&addr, addrlen, host, portnum, csp); |
472 |
if (fd != JB_INVALID_SOCKET) |
473 |
break; |
422 |
} |
474 |
} |
423 |
return(fd); |
|
|
424 |
|
475 |
|
|
|
476 |
if (fd == JB_INVALID_SOCKET) |
477 |
{ |
478 |
csp->http->host_ip_addr_str = strdup("unknown"); |
479 |
} |
480 |
|
481 |
destroy_addr_list(addrs); |
482 |
return fd; |
425 |
} |
483 |
} |
426 |
|
484 |
|
427 |
|
485 |
|
Lines 561-615
Link Here
|
561 |
|
619 |
|
562 |
/********************************************************************* |
620 |
/********************************************************************* |
563 |
* |
621 |
* |
564 |
* Function : bind_port |
622 |
* Function : bind_port_one_ip |
565 |
* |
623 |
* |
566 |
* Description : Call socket, set socket options, and listen. |
624 |
* Description : Call socket, set socket options, and listen. |
567 |
* Called by listen_loop to "boot up" our proxy address. |
|
|
568 |
* |
625 |
* |
569 |
* Parameters : |
626 |
* Parameters : |
570 |
* 1 : hostnam = TCP/IP address to bind/listen to |
627 |
* 0 : addr = TCP/IP address and port to bind/listen to |
571 |
* 2 : portnum = port to listen on |
628 |
* 1 : fds = jb_socket_set where the new socket should go |
572 |
* 3 : pfd = pointer used to return file descriptor. |
|
|
573 |
* |
629 |
* |
574 |
* Returns : if success, returns 0 and sets *pfd. |
630 |
* Returns : if success returns 0 and adds sockets to fds. |
575 |
* if failure, returns -3 if address is in use, |
631 |
* if failure, returns -3 if address is in use, |
576 |
* -2 if address unresolvable, |
632 |
* -2 if memory error |
577 |
* -1 otherwise |
633 |
* -1 otherwise |
578 |
*********************************************************************/ |
634 |
*********************************************************************/ |
579 |
int bind_port(const char *hostnam, int portnum, jb_socket *pfd) |
635 |
int bind_port_one_ip(struct sockaddr *addr, const socklen_t addr_len, jb_socket_set *fds) |
580 |
{ |
636 |
{ |
581 |
struct sockaddr_in inaddr; |
|
|
582 |
jb_socket fd; |
637 |
jb_socket fd; |
|
|
638 |
int flags; |
583 |
#ifndef _WIN32 |
639 |
#ifndef _WIN32 |
584 |
int one = 1; |
640 |
int one = 1; |
585 |
#endif /* ndef _WIN32 */ |
641 |
#endif /* ndef _WIN32 */ |
586 |
|
642 |
|
587 |
*pfd = JB_INVALID_SOCKET; |
643 |
fd = JB_INVALID_SOCKET; |
588 |
|
|
|
589 |
memset((char *)&inaddr, '\0', sizeof inaddr); |
590 |
|
591 |
inaddr.sin_family = AF_INET; |
592 |
inaddr.sin_addr.s_addr = resolve_hostname_to_ip(hostnam); |
593 |
|
594 |
if (inaddr.sin_addr.s_addr == INADDR_NONE) |
595 |
{ |
596 |
return(-2); |
597 |
} |
598 |
|
599 |
#ifndef _WIN32 |
600 |
if (sizeof(inaddr.sin_port) == sizeof(short)) |
601 |
#endif /* ndef _WIN32 */ |
602 |
{ |
603 |
inaddr.sin_port = htons((unsigned short) portnum); |
604 |
} |
605 |
#ifndef _WIN32 |
606 |
else |
607 |
{ |
608 |
inaddr.sin_port = htonl((unsigned long) portnum); |
609 |
} |
610 |
#endif /* ndef _WIN32 */ |
611 |
|
644 |
|
612 |
fd = socket(AF_INET, SOCK_STREAM, 0); |
645 |
fd = socket(addr->sa_family, SOCK_STREAM, 6); |
613 |
|
646 |
|
614 |
#ifdef _WIN32 |
647 |
#ifdef _WIN32 |
615 |
if (fd == JB_INVALID_SOCKET) |
648 |
if (fd == JB_INVALID_SOCKET) |
Lines 635-642
Link Here
|
635 |
*/ |
668 |
*/ |
636 |
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)); |
669 |
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)); |
637 |
#endif /* ndef _WIN32 */ |
670 |
#endif /* ndef _WIN32 */ |
638 |
|
671 |
/* As we are now listening on more than one socket, |
639 |
if (bind(fd, (struct sockaddr *)&inaddr, sizeof(inaddr)) < 0) |
672 |
* this is important: The only way to be sure accept |
|
|
673 |
* won't block!! |
674 |
*/ |
675 |
if ((flags = fcntl(fd, F_GETFL, 0)) != -1) |
676 |
{ |
677 |
flags |= O_NONBLOCK; |
678 |
fcntl(fd, F_SETFL, flags); |
679 |
} |
680 |
|
681 |
if (bind (fd, addr, addr_len) < 0) |
640 |
{ |
682 |
{ |
641 |
#ifdef _WIN32 |
683 |
#ifdef _WIN32 |
642 |
errno = WSAGetLastError(); |
684 |
errno = WSAGetLastError(); |
Lines 655-661
Link Here
|
655 |
} |
697 |
} |
656 |
} |
698 |
} |
657 |
|
699 |
|
658 |
while (listen(fd, 5) == -1) |
700 |
while (listen(fd, 25) == -1) |
659 |
{ |
701 |
{ |
660 |
if (errno != EINTR) |
702 |
if (errno != EINTR) |
661 |
{ |
703 |
{ |
Lines 663-669
Link Here
|
663 |
} |
705 |
} |
664 |
} |
706 |
} |
665 |
|
707 |
|
666 |
*pfd = fd; |
708 |
if (jb_socket_set_add(fds,fd) != 0) |
|
|
709 |
{ |
710 |
close_socket(fd); |
711 |
return -2; |
712 |
} |
667 |
return 0; |
713 |
return 0; |
668 |
|
714 |
|
669 |
} |
715 |
} |
Lines 671-676
Link Here
|
671 |
|
717 |
|
672 |
/********************************************************************* |
718 |
/********************************************************************* |
673 |
* |
719 |
* |
|
|
720 |
* Function : bind_port |
721 |
* |
722 |
* Description : Call bind_port_one_ip on all addresses host resolves to |
723 |
* Called by listen_loop to "boot up" our proxy address. |
724 |
* |
725 |
* Parameters : |
726 |
* 0 : host = TCP/IP hostname to bind/listen to |
727 |
* 1 : port = port to listen to, as string |
728 |
* 2 : fds = socket set the sockets should be added to |
729 |
* |
730 |
* Returns : if success on at least one address resolving from hostnam, |
731 |
* returns 0 and adds sockets to fds. |
732 |
* if failure, returns non-zero |
733 |
*********************************************************************/ |
734 |
int bind_port(const char *host, const char *port, int pf, jb_socket_set *fds) |
735 |
{ |
736 |
int result; |
737 |
int failure = 1; |
738 |
struct sockaddr_storage addr; |
739 |
struct sockaddr * const addr_addr = (struct sockaddr *)&addr; |
740 |
addr_list *addrs, *addrs_to_try; |
741 |
|
742 |
const char * const log_host = (host != NULL) ? host : "ADDR_ANY"; |
743 |
|
744 |
addrs = resolve_hostname_to_ip(host,port,pf); |
745 |
|
746 |
if (is_nil_addr_list(addrs)) |
747 |
log_error(LOG_LEVEL_ERROR, "can't bind to %s:%s: " |
748 |
"Name resolution didn't give any address", |
749 |
log_host, port); |
750 |
|
751 |
log_error(LOG_LEVEL_INFO, "Binding to %s:%s...", log_host, port); |
752 |
|
753 |
for(addrs_to_try=addrs; |
754 |
!is_nil_addr_list(addrs_to_try); |
755 |
addrs_to_try = tail_addr_list(addrs_to_try)) |
756 |
{ |
757 |
char numeric_hostname[NI_MAXHOST]; |
758 |
char numeric_port[NI_MAXSERV]; |
759 |
size_t addrlen; |
760 |
memset((char *)addr_addr, 0, sizeof addr); |
761 |
cpy_head_addr_list(addrs_to_try, &addr, &addrlen); |
762 |
result = getnameinfo(addr_addr, addrlen, numeric_hostname, NI_MAXHOST, |
763 |
numeric_port, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV); |
764 |
if (result != 0) |
765 |
{ |
766 |
log_error(LOG_LEVEL_ERROR, "bind: Could not get string address and port back from sockaddr because %E"); |
767 |
strncpy(numeric_hostname,"unknown",NI_MAXHOST); |
768 |
strncpy(numeric_port,"unknown",NI_MAXSERV); |
769 |
} |
770 |
result = bind_port_one_ip(addr_addr, addrlen, fds); |
771 |
if( result == 0 ) |
772 |
{ |
773 |
failure = 0; |
774 |
log_error(LOG_LEVEL_INFO, "Successfully bound to %s:%s", numeric_hostname, numeric_port); |
775 |
} |
776 |
else |
777 |
{ |
778 |
switch(result) |
779 |
{ |
780 |
case -3 : |
781 |
log_error(LOG_LEVEL_ERROR, "can't bind to %s:%s (%s:%s): " |
782 |
"There may be another Privoxy or some other " |
783 |
"proxy running on port %s", |
784 |
log_host, port, numeric_hostname, numeric_port, numeric_port); |
785 |
break; |
786 |
case -2 : |
787 |
log_error(LOG_LEVEL_ERROR, "can't bind to %s:%s (%s:%s): " |
788 |
"Out of memory", |
789 |
log_host, port, numeric_hostname, numeric_port); |
790 |
break; |
791 |
default : |
792 |
log_error(LOG_LEVEL_ERROR, "can't bind to %s:%s: because %E", |
793 |
log_host, numeric_port); |
794 |
} |
795 |
} |
796 |
} |
797 |
|
798 |
destroy_addr_list(addrs); |
799 |
return failure; |
800 |
} |
801 |
|
802 |
|
803 |
/********************************************************************* |
804 |
* |
674 |
* Function : accept_connection |
805 |
* Function : accept_connection |
675 |
* |
806 |
* |
676 |
* Description : Accepts a connection on a socket. Socket must have |
807 |
* Description : Accepts a connection on a socket. Socket must have |
Lines 687-694
Link Here
|
687 |
*********************************************************************/ |
818 |
*********************************************************************/ |
688 |
int accept_connection(struct client_state * csp, jb_socket fd) |
819 |
int accept_connection(struct client_state * csp, jb_socket fd) |
689 |
{ |
820 |
{ |
690 |
struct sockaddr_in client, server; |
821 |
struct sockaddr_storage client, server; |
691 |
struct hostent *host = NULL; |
|
|
692 |
jb_socket afd; |
822 |
jb_socket afd; |
693 |
#if defined(_WIN32) || defined(__OS2__) || defined(__APPLE_CC__) || defined(AMIGA) |
823 |
#if defined(_WIN32) || defined(__OS2__) || defined(__APPLE_CC__) || defined(AMIGA) |
694 |
/* Wierdness - fix a warning. */ |
824 |
/* Wierdness - fix a warning. */ |
Lines 696-710
Link Here
|
696 |
#else |
826 |
#else |
697 |
socklen_t c_length, s_length; |
827 |
socklen_t c_length, s_length; |
698 |
#endif |
828 |
#endif |
699 |
#if defined(HAVE_GETHOSTBYADDR_R_8_ARGS) || defined(HAVE_GETHOSTBYADDR_R_7_ARGS) || defined(HAVE_GETHOSTBYADDR_R_5_ARGS) |
829 |
int flags; |
700 |
struct hostent result; |
|
|
701 |
#if defined(HAVE_GETHOSTBYADDR_R_5_ARGS) |
702 |
struct hostent_data hdata; |
703 |
#else |
704 |
char hbuf[HOSTENT_BUFFER_SIZE]; |
705 |
int thd_err; |
706 |
#endif /* def HAVE_GETHOSTBYADDR_R_5_ARGS */ |
707 |
#endif /* def HAVE_GETHOSTBYADDR_R_(8|7|5)_ARGS */ |
708 |
|
830 |
|
709 |
c_length = s_length = sizeof(client); |
831 |
c_length = s_length = sizeof(client); |
710 |
|
832 |
|
Lines 724-729
Link Here
|
724 |
return 0; |
846 |
return 0; |
725 |
} |
847 |
} |
726 |
#endif |
848 |
#endif |
|
|
849 |
/* If we inherited O_NONBLOCK from the listening fd, unset it */ |
850 |
if ((flags = fcntl(fd, F_GETFL, 0)) != -1) |
851 |
{ |
852 |
flags &= ~O_NONBLOCK; |
853 |
fcntl(fd, F_SETFL, flags); |
854 |
} |
727 |
|
855 |
|
728 |
/* |
856 |
/* |
729 |
* Determine the IP-Adress that the client used to reach us |
857 |
* Determine the IP-Adress that the client used to reach us |
Lines 731-779
Link Here
|
731 |
*/ |
859 |
*/ |
732 |
if (!getsockname(afd, (struct sockaddr *) &server, &s_length)) |
860 |
if (!getsockname(afd, (struct sockaddr *) &server, &s_length)) |
733 |
{ |
861 |
{ |
734 |
csp->my_ip_addr_str = strdup(inet_ntoa(server.sin_addr)); |
862 |
char hostname[NI_MAXHOST]; |
735 |
#if defined(HAVE_GETHOSTBYADDR_R_8_ARGS) |
863 |
char port[NI_MAXSERV]; |
736 |
gethostbyaddr_r((const char *)&server.sin_addr, |
864 |
|
737 |
sizeof(server.sin_addr), AF_INET, |
865 |
if (getnameinfo((struct sockaddr *)&server, s_length, hostname, NI_MAXHOST, |
738 |
&result, hbuf, HOSTENT_BUFFER_SIZE, |
866 |
port, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV) != 0) |
739 |
&host, &thd_err); |
|
|
740 |
#elif defined(HAVE_GETHOSTBYADDR_R_7_ARGS) |
741 |
host = gethostbyaddr_r((const char *)&server.sin_addr, |
742 |
sizeof(server.sin_addr), AF_INET, |
743 |
&result, hbuf, HOSTENT_BUFFER_SIZE, &thd_err); |
744 |
#elif defined(HAVE_GETHOSTBYADDR_R_5_ARGS) |
745 |
if (0 == gethostbyaddr_r((const char *)&server.sin_addr, |
746 |
sizeof(server.sin_addr), AF_INET, |
747 |
&result, &hdata)) |
748 |
{ |
867 |
{ |
749 |
host = &result; |
868 |
log_error(LOG_LEVEL_ERROR, "accept: Could not get string address and port back from server sockaddr because %E"); |
|
|
869 |
strncpy(hostname,"unknown IP",NI_MAXHOST); |
870 |
strncpy(port,"unknown port",NI_MAXSERV); |
750 |
} |
871 |
} |
751 |
else |
872 |
csp->my_ip_addr_str = strdup(hostname); |
|
|
873 |
csp->my_port_str = strdup(port); |
874 |
|
875 |
if (getnameinfo((struct sockaddr *)&server, s_length, hostname, NI_MAXHOST, NULL, 0, NI_NAMEREQD) != 0) |
752 |
{ |
876 |
{ |
753 |
host = NULL; |
877 |
log_error(LOG_LEVEL_ERROR, "accept: Could not get my own hostname because %E"); |
|
|
878 |
strncpy(hostname,"unknown host",NI_MAXHOST); |
754 |
} |
879 |
} |
755 |
#elif FEATURE_PTHREAD |
880 |
csp->my_hostname = strdup(hostname); |
756 |
pthread_mutex_lock(&gethostbyaddr_mutex); |
881 |
} |
757 |
host = gethostbyaddr((const char *)&server.sin_addr, |
882 |
else |
758 |
sizeof(server.sin_addr), AF_INET); |
883 |
{ |
759 |
pthread_mutex_unlock(&gethostbyaddr_mutex); |
884 |
log_error(LOG_LEVEL_ERROR, "accept: Could not get sockaddr from socket fd because %E"); |
760 |
#else |
885 |
} |
761 |
host = gethostbyaddr((const char *)&server.sin_addr, |
886 |
|
762 |
sizeof(server.sin_addr), AF_INET); |
887 |
csp->cfd = afd; |
763 |
#endif |
888 |
{ |
764 |
if (host == NULL) |
889 |
char hostname[NI_MAXHOST]; |
|
|
890 |
|
891 |
if (getnameinfo((struct sockaddr *)&client, c_length, hostname, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) != 0) |
765 |
{ |
892 |
{ |
766 |
log_error(LOG_LEVEL_ERROR, "Unable to get my own hostname: %E\n"); |
893 |
log_error(LOG_LEVEL_ERROR, "accept: Could not get client IP address string because %E"); |
|
|
894 |
strncpy(hostname,"unknown IP",NI_MAXHOST); |
767 |
} |
895 |
} |
768 |
else |
896 |
csp->my_ip_addr_str = strdup(hostname); |
|
|
897 |
|
898 |
if (getnameinfo((struct sockaddr *)&server, s_length, hostname, NI_MAXHOST, NULL, 0, 0) != 0) |
769 |
{ |
899 |
{ |
770 |
csp->my_hostname = strdup(host->h_name); |
900 |
log_error(LOG_LEVEL_ERROR, "accept: Could not get my own hostname because %E"); |
|
|
901 |
strncpy(hostname,"unknown host",NI_MAXHOST); |
771 |
} |
902 |
} |
|
|
903 |
csp->ip_addr_str = strdup(hostname); |
772 |
} |
904 |
} |
773 |
|
905 |
csp->ip_addr_addr = client; |
774 |
csp->cfd = afd; |
|
|
775 |
csp->ip_addr_str = strdup(inet_ntoa(client.sin_addr)); |
776 |
csp->ip_addr_long = ntohl(client.sin_addr.s_addr); |
777 |
|
906 |
|
778 |
return 1; |
907 |
return 1; |
779 |
|
908 |
|
Lines 784-891
Link Here
|
784 |
* |
913 |
* |
785 |
* Function : resolve_hostname_to_ip |
914 |
* Function : resolve_hostname_to_ip |
786 |
* |
915 |
* |
787 |
* Description : Resolve a hostname to an internet tcp/ip address. |
916 |
* Description : Resolve a hostname to a list of internet tcp/ip addresses. |
788 |
* NULL or an empty string resolve to INADDR_ANY. |
|
|
789 |
* |
917 |
* |
790 |
* Parameters : |
918 |
* Parameters : |
791 |
* 1 : host = hostname to resolve |
919 |
* 0 : host = hostname to resolve |
|
|
920 |
* 1 : result = where to store the result |
921 |
* 2 : pf = preferred address family. PF_UNSPEC for no preference (recommended). |
792 |
* |
922 |
* |
793 |
* Returns : INADDR_NONE => failure, INADDR_ANY or tcp/ip address if succesful. |
923 |
* Returns : A (possibly empty) list of adresses |
794 |
* |
924 |
* |
795 |
*********************************************************************/ |
925 |
*********************************************************************/ |
796 |
unsigned long resolve_hostname_to_ip(const char *host) |
926 |
addr_list *resolve_hostname_to_ip(const char *host, const char *port, int pf) |
797 |
{ |
927 |
{ |
798 |
struct sockaddr_in inaddr; |
928 |
/* TODO |
799 |
struct hostent *hostp; |
929 |
* Do all supported platforms have "getaddrinfo"? |
|
|
930 |
*/ |
931 |
|
932 |
struct addrinfo hints, *res0; |
933 |
int result; |
800 |
unsigned int dns_retries = 0; |
934 |
unsigned int dns_retries = 0; |
801 |
#if defined(HAVE_GETHOSTBYNAME_R_6_ARGS) || defined(HAVE_GETHOSTBYNAME_R_5_ARGS) || defined(HAVE_GETHOSTBYNAME_R_3_ARGS) |
|
|
802 |
struct hostent result; |
803 |
#if defined(HAVE_GETHOSTBYNAME_R_6_ARGS) || defined(HAVE_GETHOSTBYNAME_R_5_ARGS) |
804 |
char hbuf[HOSTENT_BUFFER_SIZE]; |
805 |
int thd_err; |
806 |
#else /* defined(HAVE_GETHOSTBYNAME_R_3_ARGS) */ |
807 |
struct hostent_data hdata; |
808 |
#endif /* def HAVE_GETHOSTBYNAME_R_(6|5)_ARGS */ |
809 |
#endif /* def HAVE_GETHOSTBYNAME_R_(6|5|3)_ARGS */ |
810 |
|
935 |
|
811 |
if ((host == NULL) || (*host == '\0')) |
936 |
memset(&hints, 0, sizeof(hints)); |
812 |
{ |
937 |
hints.ai_family = pf; |
813 |
return(INADDR_ANY); |
938 |
hints.ai_socktype = SOCK_STREAM; |
814 |
} |
939 |
|
815 |
|
940 |
while ((result = getaddrinfo(host, port, &hints, &res0)) |
816 |
memset((char *) &inaddr, 0, sizeof inaddr); |
941 |
&& (result == EAI_AGAIN) && (dns_retries++ < 10)) { |
817 |
|
942 |
log_error(LOG_LEVEL_ERROR, "Timeout #%u while trying to resolve %s. Trying again.", |
818 |
if ((inaddr.sin_addr.s_addr = inet_addr(host)) == -1) |
943 |
dns_retries, host); |
819 |
{ |
|
|
820 |
#if defined(HAVE_GETHOSTBYNAME_R_6_ARGS) |
821 |
while ( gethostbyname_r(host, &result, hbuf, |
822 |
HOSTENT_BUFFER_SIZE, &hostp, &thd_err) |
823 |
&& (thd_err == TRY_AGAIN) && (dns_retries++ < 10) ) |
824 |
{ |
825 |
log_error(LOG_LEVEL_ERROR, "Timeout #%u while trying to resolve %s. Trying again.", |
826 |
dns_retries, host); |
827 |
} |
828 |
#elif defined(HAVE_GETHOSTBYNAME_R_5_ARGS) |
829 |
hostp = gethostbyname_r(host, &result, hbuf, |
830 |
HOSTENT_BUFFER_SIZE, &thd_err); |
831 |
#elif defined(HAVE_GETHOSTBYNAME_R_3_ARGS) |
832 |
if (0 == gethostbyname_r(host, &result, &hdata)) |
833 |
{ |
834 |
hostp = &result; |
835 |
} |
836 |
else |
837 |
{ |
838 |
hostp = NULL; |
839 |
} |
840 |
#elif FEATURE_PTHREAD |
841 |
pthread_mutex_lock(&gethostbyname_mutex); |
842 |
while ( NULL == (hostp = gethostbyname(host)) |
843 |
&& (h_errno == TRY_AGAIN) && (dns_retries++ < 10) ) |
844 |
{ |
845 |
log_error(LOG_LEVEL_ERROR, "Timeout #%u while trying to resolve %s. Trying again.", |
846 |
dns_retries, host); |
847 |
} |
848 |
pthread_mutex_unlock(&gethostbyname_mutex); |
849 |
#else |
850 |
while ( NULL == (hostp = gethostbyname(host)) |
851 |
&& (h_errno == TRY_AGAIN) && (dns_retries++ < 10) ) |
852 |
{ |
853 |
log_error(LOG_LEVEL_ERROR, "Timeout #%u while trying to resolve %s. Trying again.", |
854 |
dns_retries, host); |
855 |
} |
856 |
#endif /* def HAVE_GETHOSTBYNAME_R_(6|5|3)_ARGS */ |
857 |
/* |
858 |
* On Mac OSX, if a domain exists but doesn't have a type A |
859 |
* record associated with it, the h_addr member of the struct |
860 |
* hostent returned by gethostbyname is NULL, even if h_length |
861 |
* is 4. Therefore the second test below. |
862 |
*/ |
863 |
if (hostp == NULL || hostp->h_addr == NULL) |
864 |
{ |
865 |
errno = EINVAL; |
866 |
log_error(LOG_LEVEL_ERROR, "could not resolve hostname %s", host); |
867 |
return(INADDR_NONE); |
868 |
} |
869 |
if (hostp->h_addrtype != AF_INET) |
870 |
{ |
871 |
#ifdef _WIN32 |
872 |
errno = WSAEPROTOTYPE; |
873 |
#else |
874 |
errno = EPROTOTYPE; |
875 |
#endif |
876 |
log_error(LOG_LEVEL_ERROR, "hostname %s resolves to unknown address type.", host); |
877 |
return(INADDR_NONE); |
878 |
} |
879 |
memcpy( |
880 |
(char *) &inaddr.sin_addr, |
881 |
(char *) hostp->h_addr, |
882 |
sizeof(inaddr.sin_addr) |
883 |
); |
884 |
} |
944 |
} |
885 |
return(inaddr.sin_addr.s_addr); |
945 |
if ( result != 0 ) |
886 |
|
946 |
{ |
887 |
} |
947 |
log_error(LOG_LEVEL_ERROR, "could not resolve hostname %s because %s", host,gai_strerror(result)); |
888 |
|
948 |
if (result == EAI_SYSTEM) |
|
|
949 |
log_error(LOG_LEVEL_ERROR, "The system error is %E"); |
950 |
return NULL; |
951 |
} |
952 |
else |
953 |
if (res0==0) |
954 |
log_error(LOG_LEVEL_ERROR, "Problem in resolving hostname %s: succeeded, but no information returned", host); |
955 |
|
956 |
return res0; |
957 |
} |
889 |
|
958 |
|
890 |
/* |
959 |
/* |
891 |
Local Variables: |
960 |
Local Variables: |