990c8e42c35eead086622113bf84a9e5ec7faa8b
[privoxy.git] / jbsockets.c
1 const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.53 2009/04/17 11:39:52 fabiankeil Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/jbsockets.c,v $
5  *
6  * Purpose     :  Contains wrappers for system-specific sockets code,
7  *                so that the rest of Junkbuster can be more
8  *                OS-independent.  Contains #ifdefs to make this work
9  *                on many platforms.
10  *
11  * Copyright   :  Written by and Copyright (C) 2001-2007 the SourceForge
12  *                Privoxy team. http://www.privoxy.org/
13  *
14  *                Based on the Internet Junkbuster originally written
15  *                by and Copyright (C) 1997 Anonymous Coders and 
16  *                Junkbusters Corporation.  http://www.junkbusters.com
17  *
18  *                This program is free software; you can redistribute it 
19  *                and/or modify it under the terms of the GNU General
20  *                Public License as published by the Free Software
21  *                Foundation; either version 2 of the License, or (at
22  *                your option) any later version.
23  *
24  *                This program is distributed in the hope that it will
25  *                be useful, but WITHOUT ANY WARRANTY; without even the
26  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
27  *                PARTICULAR PURPOSE.  See the GNU General Public
28  *                License for more details.
29  *
30  *                The GNU General Public License should be included with
31  *                this file.  If not, you can view it at
32  *                http://www.gnu.org/copyleft/gpl.html
33  *                or write to the Free Software Foundation, Inc., 59
34  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
35  *
36  * Revisions   :
37  *    $Log: jbsockets.c,v $
38  *    Revision 1.53  2009/04/17 11:39:52  fabiankeil
39  *    If the hostname is 'localhost' or not specified, request an AF_INET address.
40  *
41  *    Revision 1.52  2009/04/17 11:34:34  fabiankeil
42  *    Style cosmetics for the IPv6 code.
43  *
44  *    Revision 1.51  2009/04/17 11:27:49  fabiankeil
45  *    Petr Pisar's privoxy-3.0.12-ipv6-3.diff.
46  *
47  *    Revision 1.50  2008/12/20 14:53:55  fabiankeil
48  *    Add config option socket-timeout to control the time
49  *    Privoxy waits for data to arrive on a socket. Useful
50  *    in case of stale ssh tunnels or when fuzz-testing.
51  *
52  *    Revision 1.49  2008/11/10 17:03:57  fabiankeil
53  *    Fix a gcc44 warning and remove a now-obsolete cast.
54  *
55  *    Revision 1.48  2008/09/04 08:13:58  fabiankeil
56  *    Prepare for critical sections on Windows by adding a
57  *    layer of indirection before the pthread mutex functions.
58  *
59  *    Revision 1.47  2008/03/26 18:07:07  fabiankeil
60  *    Add hostname directive. Closes PR#1918189.
61  *
62  *    Revision 1.46  2008/03/21 11:13:57  fabiankeil
63  *    Only gather host information if it's actually needed.
64  *    Also move the code out of accept_connection() so it's less likely
65  *    to delay other incoming connections if the host is misconfigured.
66  *
67  *    Revision 1.45  2007/09/30 16:59:22  fabiankeil
68  *    Set the maximum listen() backlog to 128. Apparently SOMAXCONN is
69  *    neither high enough, nor a hard limit on mingw32. Again for BR#1795281.
70  *
71  *    Revision 1.44  2007/09/15 13:01:31  fabiankeil
72  *    Increase listen() backlog to SOMAXCONN (or 128) to decrease
73  *    chances of dropped connections under load. Problem reported
74  *    and fix suggested by nobody in BR#1795281.
75  *
76  *    Revision 1.43  2007/06/01 18:16:36  fabiankeil
77  *    Use the same mutex for gethostbyname() and gethostbyaddr() to prevent
78  *    deadlocks and crashes on OpenBSD and possibly other OS with neither
79  *    gethostbyname_r() nor gethostaddr_r(). Closes BR#1729174.
80  *    Thanks to Ralf Horstmann for report and solution.
81  *
82  *    Revision 1.42  2007/04/01 17:37:07  fabiankeil
83  *    - Add DNS retries for Solaris and other systems
84  *      whose gethostbyname_r version takes five arguments.
85  *    - Move maximum number of DNS retries into a macro.
86  *
87  *    Revision 1.41  2006/11/13 19:05:51  fabiankeil
88  *    Make pthread mutex locking more generic. Instead of
89  *    checking for OSX and OpenBSD, check for FEATURE_PTHREAD
90  *    and use mutex locking unless there is an _r function
91  *    available. Better safe than sorry.
92  *
93  *    Fixes "./configure --disable-pthread" and should result
94  *    in less threading-related problems on pthread-using platforms,
95  *    but it still doesn't fix BR#1122404.
96  *
97  *    Revision 1.40  2006/09/02 15:36:42  fabiankeil
98  *    Follow the OpenBSD port's lead and protect the resolve
99  *    functions on OpenBSD as well.
100  *
101  *    Revision 1.39  2006/08/03 02:46:41  david__schmidt
102  *    Incorporate Fabian Keil's patch work:\rhttp://www.fabiankeil.de/sourcecode/privoxy/
103  *
104  *    Revision 1.38  2006/07/18 14:48:46  david__schmidt
105  *    Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch)
106  *    with what was really the latest development (the v_3_0_branch branch)
107  *
108  *    Revision 1.35.2.8  2006/01/21 16:16:08  david__schmidt
109  *    Thanks to  Edward Carrel for his patch to modernize OSX's\rpthreads support.  See bug #1409623.
110  *
111  *    Revision 1.35.2.7  2005/05/07 21:50:55  david__schmidt
112  *    A few memory leaks plugged (mostly on error paths)
113  *
114  *    Revision 1.35.2.6  2003/12/17 16:34:40  oes
115  *    Cosmetics
116  *
117  *    Revision 1.35.2.5  2003/04/29 11:32:54  oes
118  *    Don't rely on h_addr being non-NULL after gethostbyname.
119  *    Works around an oddness in Max OSX and closes bug #724796
120  *
121  *    Revision 1.35.2.4  2003/04/04 12:40:20  oes
122  *    Made sure the errno set by bind, not close[socket] is used in
123  *    bind_port. Probably fixes bugs #713777, #705562.
124  *
125  *    Revision 1.35.2.3  2003/03/07 03:41:04  david__schmidt
126  *    Wrapping all *_r functions (the non-_r versions of them) with mutex semaphores for OSX.  Hopefully this will take care of all of those pesky crash reports.
127  *
128  *    Revision 1.35.2.2  2002/11/20 14:37:24  oes
129  *    Fixed Win32 error logging in bind_port.
130  *    Thanks to Oliver Stoeneberg for the hint.
131  *
132  *    Revision 1.35.2.1  2002/05/26 23:41:27  joergs
133  *    AmigaOS: Fixed wrong type of len in write_socket()
134  *
135  *    Revision 1.35  2002/04/26 15:50:04  joergs
136  *    AmigaOS: No socklen_t, added AMIGA to the systems using int instead.
137  *
138  *    Revision 1.34  2002/04/08 20:31:41  swa
139  *    fixed JB spelling
140  *
141  *    Revision 1.33  2002/04/03 16:02:18  gliptak
142  *    Correcting compile warning with older gcc
143  *
144  *    Revision 1.32  2002/03/31 17:18:59  jongfoster
145  *    Win32 only: Enabling STRICT to fix a VC++ compile warning.
146  *
147  *    Revision 1.31  2002/03/29 03:33:13  david__schmidt
148  *    Fix Mac OSX compiler warnings
149  *
150  *    Revision 1.30  2002/03/27 14:32:43  david__schmidt
151  *    More compiler warning message maintenance
152  *
153  *    Revision 1.29  2002/03/26 22:29:54  swa
154  *    we have a new homepage!
155  *
156  *    Revision 1.28  2002/03/24 13:25:43  swa
157  *    name change related issues
158  *
159  *    Revision 1.27  2002/03/13 00:27:05  jongfoster
160  *    Killing warnings
161  *
162  *    Revision 1.26  2002/03/11 22:07:02  david__schmidt
163  *    OS/2 port maintenance:
164  *    - Fixed EMX build - it had decayed a little
165  *    - Fixed inexplicable crash during FD_ZERO - must be due to a bad macro.
166  *      substituted a memset for now.
167  *
168  *    Revision 1.25  2002/03/09 20:03:52  jongfoster
169  *    - Making various functions return int rather than size_t.
170  *      (Undoing a recent change).  Since size_t is unsigned on
171  *      Windows, functions like read_socket that return -1 on
172  *      error cannot return a size_t.
173  *
174  *      THIS WAS A MAJOR BUG - it caused frequent, unpredictable
175  *      crashes, and also frequently caused JB to jump to 100%
176  *      CPU and stay there.  (Because it thought it had just
177  *      read ((unsigned)-1) == 4Gb of data...)
178  *
179  *    - The signature of write_socket has changed, it now simply
180  *      returns success=0/failure=nonzero.
181  *
182  *    - Trying to get rid of a few warnings --with-debug on
183  *      Windows, I've introduced a new type "jb_socket".  This is
184  *      used for the socket file descriptors.  On Windows, this
185  *      is SOCKET (a typedef for unsigned).  Everywhere else, it's
186  *      an int.  The error value can't be -1 any more, so it's
187  *      now JB_INVALID_SOCKET (which is -1 on UNIX, and in
188  *      Windows it maps to the #define INVALID_SOCKET.)
189  *
190  *    - The signature of bind_port has changed.
191  *
192  *    Revision 1.24  2002/03/07 03:51:36  oes
193  *     - Improved handling of failed DNS lookups
194  *     - Fixed compiler warnings etc
195  *
196  *    Revision 1.23  2002/03/05 00:36:01  jongfoster
197  *    Fixing bug 514988 - unable to restart Junkbuster
198  *
199  *    Revision 1.22  2002/03/04 02:08:02  david__schmidt
200  *    Enable web editing of actions file on OS/2 (it had been broken all this time!)
201  *
202  *    Revision 1.21  2002/01/09 14:32:33  oes
203  *    Added support for gethostbyname_r and gethostbyaddr_r.
204  *
205  *    Revision 1.20  2001/11/16 00:48:48  jongfoster
206  *    Enabling duplicate-socket detection for all platforms, not
207  *    just Win32.
208  *
209  *    Revision 1.19  2001/10/25 03:40:47  david__schmidt
210  *    Change in porting tactics: OS/2's EMX porting layer doesn't allow multiple
211  *    threads to call select() simultaneously.  So, it's time to do a real, live,
212  *    native OS/2 port.  See defines for __EMX__ (the porting layer) vs. __OS2__
213  *    (native). Both versions will work, but using __OS2__ offers multi-threading.
214  *
215  *    Revision 1.18  2001/09/21 23:02:02  david__schmidt
216  *    Cleaning up 2 compiler warnings on OS/2.
217  *
218  *    Revision 1.17  2001/09/13 20:11:46  jongfoster
219  *    Fixing 2 compiler warnings under Win32
220  *
221  *    Revision 1.16  2001/07/30 22:08:36  jongfoster
222  *    Tidying up #defines:
223  *    - All feature #defines are now of the form FEATURE_xxx
224  *    - Permanently turned off WIN_GUI_EDIT
225  *    - Permanently turned on WEBDAV and SPLIT_PROXY_ARGS
226  *
227  *    Revision 1.15  2001/07/29 17:40:43  jongfoster
228  *    Fixed compiler warning by adding a cast
229  *
230  *    Revision 1.14  2001/07/18 13:47:59  oes
231  *    Eliminated dirty hack for getsockbyname()
232  *
233  *    Revision 1.13  2001/07/15 13:56:57  jongfoster
234  *    Removing unused local variable.
235  *
236  *    Revision 1.12  2001/07/01 17:04:11  oes
237  *    Bugfix: accept_connection no longer uses the obsolete hstrerror() function
238  *
239  *    Revision 1.11  2001/06/29 21:45:41  oes
240  *    Indentation, CRLF->LF, Tab-> Space
241  *
242  *    Revision 1.10  2001/06/29 13:29:15  oes
243  *    - Added remote (server) host IP to csp->http->host_ip_addr_str
244  *    - Added detection of local socket IP and fqdn
245  *    - Removed logentry from cancelled commit
246  *
247  *    Revision 1.9  2001/06/07 23:06:09  jongfoster
248  *    The host parameter to connect_to() is now const.
249  *
250  *    Revision 1.8  2001/06/03 19:12:07  oes
251  *    filled comment
252  *
253  *    Revision 1.7  2001/05/28 16:14:00  jongfoster
254  *    Fixing bug in LOG_LEVEL_LOG
255  *
256  *    Revision 1.6  2001/05/26 17:28:32  jongfoster
257  *    Fixed LOG_LEVEL_LOG
258  *
259  *    Revision 1.5  2001/05/26 15:26:15  jongfoster
260  *    ACL feature now provides more security by immediately dropping
261  *    connections from untrusted hosts.
262  *
263  *    Revision 1.4  2001/05/26 00:37:42  jongfoster
264  *    Cosmetic indentation correction.
265  *
266  *    Revision 1.3  2001/05/25 21:57:54  jongfoster
267  *    Now gives a warning under Windows if you try to bind
268  *    it to a port that's already in use.
269  *
270  *    Revision 1.2  2001/05/17 23:01:01  oes
271  *     - Cleaned CRLF's from the sources and related files
272  *
273  *    Revision 1.1.1.1  2001/05/15 13:58:54  oes
274  *    Initial import of version 2.9.3 source tree
275  *
276  *
277  *********************************************************************/
278 \f
279
280 #include "config.h"
281
282 #include <stdlib.h>
283 #include <stdio.h>
284 #include <string.h>
285 #include <errno.h>
286 #include <fcntl.h>
287 #include <sys/types.h>
288
289 #ifdef _WIN32
290
291 #ifndef STRICT
292 #define STRICT
293 #endif
294 #include <windows.h>
295 #include <sys/timeb.h>
296 #include <io.h>
297
298 #else
299
300 #ifndef __OS2__
301 #include <unistd.h>
302 #endif
303 #include <sys/time.h>
304 #include <netinet/in.h>
305 #include <sys/ioctl.h>
306 #include <netdb.h>
307 #include <sys/socket.h>
308
309 #ifndef __BEOS__
310 #include <netinet/tcp.h>
311 #ifndef __OS2__
312 #include <arpa/inet.h>
313 #endif
314 #else
315 #include <socket.h>
316 #endif
317
318 #if defined(__EMX__) || defined (__OS2__)
319 #include <sys/select.h>  /* OS/2/EMX needs a little help with select */
320 #ifdef __OS2__
321 #include <nerrno.h>
322 #endif
323 #endif
324
325 #endif
326
327 #include "project.h"
328
329 #ifdef FEATURE_PTHREAD
330 #include "jcc.h"
331 /* jcc.h is for mutex semaphores only */
332 #endif /* def FEATURE_PTHREAD */
333
334 #include "jbsockets.h"
335 #include "filters.h"
336 #include "errlog.h"
337 #include "miscutil.h"
338
339 const char jbsockets_h_rcs[] = JBSOCKETS_H_VERSION;
340
341 /*
342  * Maximum number of gethostbyname(_r) retries in case of
343  * soft errors (TRY_AGAIN).
344  * XXX: Does it make sense to make this a config option?
345  */
346 #define MAX_DNS_RETRIES 10
347
348 #define MAX_LISTEN_BACKLOG 128
349
350
351 /*********************************************************************
352  *
353  * Function    :  connect_to
354  *
355  * Description :  Open a socket and connect to it.  Will check
356  *                that this is allowed according to ACL.
357  *
358  * Parameters  :
359  *          1  :  host = hostname to connect to
360  *          2  :  portnum = port to connent on (XXX: should be unsigned)
361  *          3  :  csp = Current client state (buffers, headers, etc...)
362  *                      Not modified, only used for source IP and ACL.
363  *
364  * Returns     :  JB_INVALID_SOCKET => failure, else it is the socket
365  *                file descriptor.
366  *
367  *********************************************************************/
368 #ifdef HAVE_RFC2553
369 /* Getaddrinfo implementation */
370 jb_socket connect_to(const char *host, int portnum, struct client_state *csp)
371 {
372    struct addrinfo hints, *result, *rp;
373    char service[6];
374    int retval;
375    jb_socket fd;
376    fd_set wfds;
377    struct timeval tv[1];
378 #if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA)
379    int   flags;
380 #endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */
381    int connect_failed;
382
383 #ifdef FEATURE_ACL
384    struct access_control_addr dst[1];
385 #endif /* def FEATURE_ACL */
386
387    retval = snprintf(service, sizeof(service), "%d", portnum);
388    if ((-1 == retval) || (sizeof(service) <= retval))
389    {
390       log_error(LOG_LEVEL_ERROR,
391          "Port number (%d) ASCII decimal representation doesn't fit into 6 bytes",
392          portnum);
393       csp->http->host_ip_addr_str = strdup("unknown");
394       return(JB_INVALID_SOCKET);
395    }
396
397    memset((char *)&hints, 0, sizeof(hints));
398    hints.ai_family = AF_UNSPEC;
399    hints.ai_socktype = SOCK_STREAM;
400    hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV; /* avoid service look-up */
401    if ((retval = getaddrinfo(host, service, &hints, &result)))
402    {
403       log_error(LOG_LEVEL_INFO,
404          "Can not resolve %s: %s", host, gai_strerror(retval));
405       csp->http->host_ip_addr_str = strdup("unknown");
406       return(JB_INVALID_SOCKET);
407    }
408
409    for (rp = result; rp != NULL; rp = rp->ai_next)
410    {
411
412 #ifdef FEATURE_ACL
413       memcpy(&dst->addr, rp->ai_addr, rp->ai_addrlen);
414
415       if (block_acl(dst, csp))
416       {
417 #ifdef __OS2__
418          errno = SOCEPERM;
419 #else
420          errno = EPERM;
421 #endif
422          continue;
423       }
424 #endif /* def FEATURE_ACL */
425
426       csp->http->host_ip_addr_str = malloc(NI_MAXHOST);
427       retval = getnameinfo(rp->ai_addr, rp->ai_addrlen,
428          csp->http->host_ip_addr_str, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
429       if (!csp->http->host_ip_addr_str || retval)
430       {
431          log_error(LOG_LEVEL_ERROR,
432             "Can not save csp->http->host_ip_addr_str: %s",
433             (csp->http->host_ip_addr_str) ?
434             gai_strerror(retval) : "Insufficient memory");
435          freez(csp->http->host_ip_addr_str);
436          continue;
437       }
438
439 #ifdef _WIN32
440       if ((fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) ==
441             JB_INVALID_SOCKET)
442 #else
443       if ((fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0)
444 #endif
445       {
446          continue;
447       }
448
449 #ifdef TCP_NODELAY
450       {  /* turn off TCP coalescence */
451          int mi = 1;
452          setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &mi, sizeof (int));
453       }
454 #endif /* def TCP_NODELAY */
455
456 #if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
457       if ((flags = fcntl(fd, F_GETFL, 0)) != -1)
458       {
459          flags |= O_NDELAY;
460          fcntl(fd, F_SETFL, flags);
461       }
462 #endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */
463
464       connect_failed = 0;
465       while (connect(fd, rp->ai_addr, rp->ai_addrlen) == JB_INVALID_SOCKET)
466       {
467 #ifdef _WIN32
468          if (errno == WSAEINPROGRESS)
469 #elif __OS2__
470          if (sock_errno() == EINPROGRESS)
471 #else /* ifndef _WIN32 */
472          if (errno == EINPROGRESS)
473 #endif /* ndef _WIN32 || __OS2__ */
474          {
475             break;
476          }
477
478 #ifdef __OS2__
479          if (sock_errno() != EINTR)
480 #else
481          if (errno != EINTR)
482 #endif /* __OS2__ */
483          {
484             close_socket(fd);
485             connect_failed = 1;
486             break;
487          }
488       }
489       if (connect_failed)
490       {
491          continue;
492       }
493
494 #if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
495       if (flags != -1)
496       {
497          flags &= ~O_NDELAY;
498          fcntl(fd, F_SETFL, flags);
499       }
500 #endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */
501
502       /* wait for connection to complete */
503       FD_ZERO(&wfds);
504       FD_SET(fd, &wfds);
505
506       tv->tv_sec  = 30;
507       tv->tv_usec = 0;
508
509       /* MS Windows uses int, not SOCKET, for the 1st arg of select(). Wierd! */
510       if (select((int)fd + 1, NULL, &wfds, NULL, tv) <= 0)
511       {
512          close_socket(fd);
513          continue;
514       }
515
516       break; /* for; Connection established; don't try other addresses */
517    }
518
519    freeaddrinfo(result);
520    if (!rp)
521    {
522       log_error(LOG_LEVEL_INFO,
523          "Could not connect to TCP/[%s]:%s", host, service);
524       return(JB_INVALID_SOCKET);
525    }
526    /*
527     * XXX: Current connection verification (EINPROGRESS && select()
528     * for writing) is not sufficient. E.g. on Linux-2.6.27 with glibc-2.6
529     * select returns socket ready for writing, however subsequential
530     * write(2) fails with ENOCONNECT. Read Linux connect(2) man page
531     * about non-blocking sockets.
532     * Thus we can't log here that the socket is connected.
533     */
534    /* log_error(LOG_LEVEL_INFO, "Connected to TCP/[%s]:%s", host, service); */
535
536    return(fd);
537
538 }
539
540 #else /* ndef HAVE_RFC2553 */
541 /* Pre-getaddrinfo implementation */
542
543 jb_socket connect_to(const char *host, int portnum, struct client_state *csp)
544 {
545    struct sockaddr_in inaddr;
546    jb_socket fd;
547    unsigned int addr;
548    fd_set wfds;
549    struct timeval tv[1];
550 #if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA)
551    int   flags;
552 #endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */
553
554 #ifdef FEATURE_ACL
555    struct access_control_addr dst[1];
556 #endif /* def FEATURE_ACL */
557
558    memset((char *)&inaddr, 0, sizeof inaddr);
559
560    if ((addr = resolve_hostname_to_ip(host)) == INADDR_NONE)
561    {
562       csp->http->host_ip_addr_str = strdup("unknown");
563       return(JB_INVALID_SOCKET);
564    }
565
566 #ifdef FEATURE_ACL
567    dst->addr = ntohl(addr);
568    dst->port = portnum;
569
570    if (block_acl(dst, csp))
571    {
572 #ifdef __OS2__
573       errno = SOCEPERM;
574 #else
575       errno = EPERM;
576 #endif
577       return(JB_INVALID_SOCKET);
578    }
579 #endif /* def FEATURE_ACL */
580
581    inaddr.sin_addr.s_addr = addr;
582    inaddr.sin_family      = AF_INET;
583    csp->http->host_ip_addr_str = strdup(inet_ntoa(inaddr.sin_addr));
584
585 #ifndef _WIN32
586    if (sizeof(inaddr.sin_port) == sizeof(short))
587 #endif /* ndef _WIN32 */
588    {
589       inaddr.sin_port = htons((unsigned short) portnum);
590    }
591 #ifndef _WIN32
592    else
593    {
594       inaddr.sin_port = htonl((unsigned long)portnum);
595    }
596 #endif /* ndef _WIN32 */
597
598 #ifdef _WIN32
599    if ((fd = socket(inaddr.sin_family, SOCK_STREAM, 0)) == JB_INVALID_SOCKET)
600 #else
601    if ((fd = socket(inaddr.sin_family, SOCK_STREAM, 0)) < 0)
602 #endif
603    {
604       return(JB_INVALID_SOCKET);
605    }
606
607 #ifdef TCP_NODELAY
608    {  /* turn off TCP coalescence */
609       int mi = 1;
610       setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &mi, sizeof (int));
611    }
612 #endif /* def TCP_NODELAY */
613
614 #if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
615    if ((flags = fcntl(fd, F_GETFL, 0)) != -1)
616    {
617       flags |= O_NDELAY;
618       fcntl(fd, F_SETFL, flags);
619    }
620 #endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */
621
622    while (connect(fd, (struct sockaddr *) & inaddr, sizeof inaddr) == JB_INVALID_SOCKET)
623    {
624 #ifdef _WIN32
625       if (errno == WSAEINPROGRESS)
626 #elif __OS2__ 
627       if (sock_errno() == EINPROGRESS)
628 #else /* ifndef _WIN32 */
629       if (errno == EINPROGRESS)
630 #endif /* ndef _WIN32 || __OS2__ */
631       {
632          break;
633       }
634
635 #ifdef __OS2__ 
636       if (sock_errno() != EINTR)
637 #else
638       if (errno != EINTR)
639 #endif /* __OS2__ */
640       {
641          close_socket(fd);
642          return(JB_INVALID_SOCKET);
643       }
644    }
645
646 #if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
647    if (flags != -1)
648    {
649       flags &= ~O_NDELAY;
650       fcntl(fd, F_SETFL, flags);
651    }
652 #endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */
653
654    /* wait for connection to complete */
655    FD_ZERO(&wfds);
656    FD_SET(fd, &wfds);
657
658    tv->tv_sec  = 30;
659    tv->tv_usec = 0;
660
661    /* MS Windows uses int, not SOCKET, for the 1st arg of select(). Wierd! */
662    if (select((int)fd + 1, NULL, &wfds, NULL, tv) <= 0)
663    {
664       close_socket(fd);
665       return(JB_INVALID_SOCKET);
666    }
667    return(fd);
668
669 }
670 #endif /* ndef HAVE_RFC2553 */
671
672
673 /*********************************************************************
674  *
675  * Function    :  write_socket
676  *
677  * Description :  Write the contents of buf (for n bytes) to socket fd.
678  *
679  * Parameters  :
680  *          1  :  fd = file descriptor (aka. handle) of socket to write to.
681  *          2  :  buf = pointer to data to be written.
682  *          3  :  len = length of data to be written to the socket "fd".
683  *
684  * Returns     :  0 on success (entire buffer sent).
685  *                nonzero on error.
686  *
687  *********************************************************************/
688 #ifdef AMIGA
689 int write_socket(jb_socket fd, const char *buf, ssize_t len)
690 #else
691 int write_socket(jb_socket fd, const char *buf, size_t len)
692 #endif
693 {
694    if (len == 0)
695    {
696       return 0;
697    }
698
699    if (len < 0) /* constant condition - size_t isn't ever negative */ 
700    {
701       return 1;
702    }
703
704    log_error(LOG_LEVEL_LOG, "%N", len, buf);
705
706 #if defined(_WIN32)
707    return (send(fd, buf, (int)len, 0) != (int)len);
708 #elif defined(__BEOS__) || defined(AMIGA)
709    return (send(fd, buf, len, 0) != len);
710 #elif defined(__OS2__)
711    /*
712     * Break the data up into SOCKET_SEND_MAX chunks for sending...
713     * OS/2 seemed to complain when the chunks were too large.
714     */
715 #define SOCKET_SEND_MAX 65000
716    {
717       int write_len = 0, send_len, send_rc = 0, i = 0;
718       while ((i < len) && (send_rc != -1))
719       {
720          if ((i + SOCKET_SEND_MAX) > len)
721             send_len = len - i;
722          else
723             send_len = SOCKET_SEND_MAX;
724          send_rc = send(fd,(char*)buf + i, send_len, 0);
725          if (send_rc == -1)
726             return 1;
727          i = i + send_len;
728       }
729       return 0;
730    }
731 #else
732    return (write(fd, buf, len) != len);
733 #endif
734
735 }
736
737
738 /*********************************************************************
739  *
740  * Function    :  read_socket
741  *
742  * Description :  Read from a TCP/IP socket in a platform independent way.
743  *
744  * Parameters  :
745  *          1  :  fd = file descriptor of the socket to read
746  *          2  :  buf = pointer to buffer where data will be written
747  *                Must be >= len bytes long.
748  *          3  :  len = maximum number of bytes to read
749  *
750  * Returns     :  On success, the number of bytes read is returned (zero
751  *                indicates end of file), and the file position is advanced
752  *                by this number.  It is not an error if this number is
753  *                smaller than the number of bytes requested; this may hap-
754  *                pen for example because fewer bytes are actually available
755  *                right now (maybe because we were close to end-of-file, or
756  *                because we are reading from a pipe, or from a terminal,
757  *                or because read() was interrupted by a signal).  On error,
758  *                -1 is returned, and errno is set appropriately.  In this
759  *                case it is left unspecified whether the file position (if
760  *                any) changes.
761  *
762  *********************************************************************/
763 int read_socket(jb_socket fd, char *buf, int len)
764 {
765    if (len <= 0)
766    {
767       return(0);
768    }
769
770 #if defined(_WIN32)
771    return(recv(fd, buf, len, 0));
772 #elif defined(__BEOS__) || defined(AMIGA) || defined(__OS2__)
773    return(recv(fd, buf, (size_t)len, 0));
774 #else
775    return(read(fd, buf, (size_t)len));
776 #endif
777 }
778
779
780 /*********************************************************************
781  *
782  * Function    :  data_is_available
783  *
784  * Description :  Waits for data to arrive on a socket.
785  *
786  * Parameters  :
787  *          1  :  fd = file descriptor of the socket to read
788  *          2  :  seconds_to_wait = number of seconds after which we give up.
789  *
790  * Returns     :  TRUE if data arrived in time,
791  *                FALSE otherwise.
792  *
793  *********************************************************************/
794 int data_is_available(jb_socket fd, int seconds_to_wait)
795 {
796    fd_set rfds;
797    struct timeval timeout;
798    int n;
799
800    memset(&timeout, 0, sizeof(timeout));
801    timeout.tv_sec = seconds_to_wait;
802
803 #ifdef __OS2__
804    /* Copy and pasted from jcc.c ... */
805    memset(&rfds, 0, sizeof(fd_set));
806 #else
807    FD_ZERO(&rfds);
808 #endif
809    FD_SET(fd, &rfds);
810
811    n = select(fd+1, &rfds, NULL, NULL, &timeout);
812
813    /*
814     * XXX: Do we care about the different error conditions?
815     */
816    return (n == 1);
817 }
818
819
820 /*********************************************************************
821  *
822  * Function    :  close_socket
823  *
824  * Description :  Closes a TCP/IP socket
825  *
826  * Parameters  :
827  *          1  :  fd = file descriptor of socket to be closed
828  *
829  * Returns     :  void
830  *
831  *********************************************************************/
832 void close_socket(jb_socket fd)
833 {
834 #if defined(_WIN32) || defined(__BEOS__)
835    closesocket(fd);
836 #elif defined(AMIGA)
837    CloseSocket(fd); 
838 #elif defined(__OS2__)
839    soclose(fd);
840 #else
841    close(fd);
842 #endif
843
844 }
845
846
847 /*********************************************************************
848  *
849  * Function    :  bind_port
850  *
851  * Description :  Call socket, set socket options, and listen.
852  *                Called by listen_loop to "boot up" our proxy address.
853  *
854  * Parameters  :
855  *          1  :  hostnam = TCP/IP address to bind/listen to
856  *          2  :  portnum = port to listen on
857  *          3  :  pfd = pointer used to return file descriptor.
858  *
859  * Returns     :  if success, returns 0 and sets *pfd.
860  *                if failure, returns -3 if address is in use,
861  *                                    -2 if address unresolvable,
862  *                                    -1 otherwise
863  *********************************************************************/
864 int bind_port(const char *hostnam, int portnum, jb_socket *pfd)
865 {
866 #ifdef HAVE_RFC2553
867    struct addrinfo hints;
868    struct addrinfo *result, *rp;
869    /*
870     * XXX: portnum should be a string to allow symbolic service
871     * names in the configuration file and to avoid the following
872     * int2string.
873     */
874    char servnam[6];
875    int retval;
876 #else
877    struct sockaddr_in inaddr;
878 #endif /* def HAVE_RFC2553 */
879    jb_socket fd;
880 #ifndef _WIN32
881    int one = 1;
882 #endif /* ndef _WIN32 */
883
884    *pfd = JB_INVALID_SOCKET;
885
886 #ifdef HAVE_RFC2553
887    retval = snprintf(servnam, sizeof(servnam), "%d", portnum);
888    if ((-1 == retval) || (sizeof(servnam) <= retval))
889    {
890       log_error(LOG_LEVEL_ERROR,
891          "Port number (%d) ASCII decimal representation doesn't fit into 6 bytes",
892          portnum);
893       return -1;
894    }
895
896    memset(&hints, 0, sizeof(struct addrinfo));
897    if ((hostnam == NULL) || !strcmpic(hostnam, "localhost"))
898    {
899       /*
900        * XXX: This is a hack. The right thing to do
901        * would be to bind to both AF_INET and AF_INET6.
902        * This will also fail if there is no AF_INET
903        * version available.
904        */
905       hints.ai_family = AF_INET;
906    }
907    else
908    {
909       hints.ai_family = AF_UNSPEC;
910    }
911    hints.ai_socktype = SOCK_STREAM;
912    hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
913    hints.ai_protocol = 0; /* Realy any stream protocol or TCP only */
914    hints.ai_canonname = NULL;
915    hints.ai_addr = NULL;
916    hints.ai_next = NULL;
917
918    if ((retval = getaddrinfo(hostnam, servnam, &hints, &result)))
919    {
920       log_error(LOG_LEVEL_ERROR,
921          "Can not resolve %s: %s", hostnam, gai_strerror(retval));
922       return -2;
923    }
924 #else
925    memset((char *)&inaddr, '\0', sizeof inaddr);
926
927    inaddr.sin_family      = AF_INET;
928    inaddr.sin_addr.s_addr = resolve_hostname_to_ip(hostnam);
929
930    if (inaddr.sin_addr.s_addr == INADDR_NONE)
931    {
932       return(-2);
933    }
934
935 #ifndef _WIN32
936    if (sizeof(inaddr.sin_port) == sizeof(short))
937 #endif /* ndef _WIN32 */
938    {
939       inaddr.sin_port = htons((unsigned short) portnum);
940    }
941 #ifndef _WIN32
942    else
943    {
944       inaddr.sin_port = htonl((unsigned long) portnum);
945    }
946 #endif /* ndef _WIN32 */
947 #endif /* def HAVE_RFC2553 */
948
949 #ifdef HAVE_RFC2553
950    for (rp = result; rp != NULL; rp = rp->ai_next)
951    {
952       fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
953 #else
954    fd = socket(AF_INET, SOCK_STREAM, 0);
955 #endif /* def HAVE_RFC2553 */
956
957 #ifdef _WIN32
958    if (fd == JB_INVALID_SOCKET)
959 #else
960    if (fd < 0)
961 #endif
962    {
963 #ifdef HAVE_RFC2553
964       continue;
965 #else
966       return(-1);
967 #endif
968    }
969
970 #ifndef _WIN32
971    /*
972     * This is not needed for Win32 - in fact, it stops
973     * duplicate instances of Privoxy from being caught.
974     *
975     * On UNIX, we assume the user is sensible enough not
976     * to start Privoxy multiple times on the same IP.
977     * Without this, stopping and restarting Privoxy
978     * from a script fails.
979     * Note: SO_REUSEADDR is meant to only take over
980     * sockets which are *not* in listen state in Linux,
981     * e.g. sockets in TIME_WAIT. YMMV.
982     */
983    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one));
984 #endif /* ndef _WIN32 */
985
986 #ifdef HAVE_RFC2553
987    if (bind(fd, rp->ai_addr, rp->ai_addrlen) < 0)
988 #else
989    if (bind(fd, (struct sockaddr *)&inaddr, sizeof(inaddr)) < 0)
990 #endif
991    {
992 #ifdef _WIN32
993       errno = WSAGetLastError();
994       if (errno == WSAEADDRINUSE)
995 #else
996       if (errno == EADDRINUSE)
997 #endif
998       {
999 #ifdef HAVE_RFC2553
1000          freeaddrinfo(result);
1001 #endif
1002          close_socket(fd);
1003          return(-3);
1004       }
1005       else
1006       {
1007          close_socket(fd);
1008 #ifndef HAVE_RFC2553
1009          return(-1);
1010       }
1011    }
1012 #else
1013       }
1014    }
1015    else
1016    {
1017       /* bind() succeeded, escape from for-loop */
1018       /*
1019        * XXX: Support multiple listening sockets (e.g. localhost
1020        * resolves to AF_INET and AF_INET6, but only the first address
1021        * is used
1022        */
1023       break;
1024    }
1025    }
1026
1027    freeaddrinfo(result);
1028    if (rp == NULL)
1029    {
1030       /* All bind()s failed */
1031       return(-1);
1032    }
1033 #endif /* ndef HAVE_RFC2553 */
1034
1035    while (listen(fd, MAX_LISTEN_BACKLOG) == -1)
1036    {
1037       if (errno != EINTR)
1038       {
1039          return(-1);
1040       }
1041    }
1042
1043    *pfd = fd;
1044    return 0;
1045
1046 }
1047
1048
1049 /*********************************************************************
1050  *
1051  * Function    :  get_host_information
1052  *
1053  * Description :  Determines the IP address the client used to
1054  *                reach us and the hostname associated with it.
1055  *
1056  *                XXX: Most of the code has been copy and pasted
1057  *                from accept_connection() and not all of the
1058  *                ifdefs paths have been tested afterwards.
1059  *
1060  * Parameters  :
1061  *          1  :  afd = File descriptor returned from accept().
1062  *          2  :  ip_address = Pointer to return the pointer to
1063  *                             the ip address string.
1064  *          3  :  hostname =   Pointer to return the pointer to
1065  *                             the hostname or NULL if the caller
1066  *                             isn't interested in it.
1067  *
1068  * Returns     :  void.
1069  *
1070  *********************************************************************/
1071 void get_host_information(jb_socket afd, char **ip_address, char **hostname)
1072 {
1073 #ifdef HAVE_RFC2553
1074    struct sockaddr_storage server;
1075    int retval;
1076 #else
1077    struct sockaddr_in server;
1078    struct hostent *host = NULL;
1079 #endif /* HAVE_RFC2553 */
1080 #if defined(_WIN32) || defined(__OS2__) || defined(__APPLE_CC__) || defined(AMIGA)
1081    /* according to accept_connection() this fixes a warning. */
1082    int s_length, s_length_provided;
1083 #else
1084    socklen_t s_length, s_length_provided;
1085 #endif
1086 #ifndef HAVE_RFC2553
1087 #if defined(HAVE_GETHOSTBYADDR_R_8_ARGS) ||  defined(HAVE_GETHOSTBYADDR_R_7_ARGS) || defined(HAVE_GETHOSTBYADDR_R_5_ARGS)
1088    struct hostent result;
1089 #if defined(HAVE_GETHOSTBYADDR_R_5_ARGS)
1090    struct hostent_data hdata;
1091 #else
1092    char hbuf[HOSTENT_BUFFER_SIZE];
1093    int thd_err;
1094 #endif /* def HAVE_GETHOSTBYADDR_R_5_ARGS */
1095 #endif /* def HAVE_GETHOSTBYADDR_R_(8|7|5)_ARGS */
1096 #endif /* ifndef HAVE_RFC2553 */
1097    s_length = s_length_provided = sizeof(server);
1098
1099    if (NULL != hostname)
1100    {
1101       *hostname = NULL;
1102    }
1103    *ip_address = NULL;
1104
1105    if (!getsockname(afd, (struct sockaddr *) &server, &s_length))
1106    {
1107       if (s_length > s_length_provided)
1108       {
1109          log_error(LOG_LEVEL_ERROR, "getsockname() truncated server address");
1110          return;
1111       }
1112 #ifdef HAVE_RFC2553
1113       *ip_address = malloc(NI_MAXHOST);
1114       retval = getnameinfo((struct sockaddr *) &server, s_length,
1115          *ip_address, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
1116       if (retval)
1117       {
1118          log_error(LOG_LEVEL_ERROR,
1119             "Unable to print my own IP address: %s", gai_strerror(retval));
1120          freez(*ip_address);
1121          return;
1122       }
1123 #else
1124       *ip_address = strdup(inet_ntoa(server.sin_addr));
1125 #endif /* HAVE_RFC2553 */
1126       if (NULL == hostname)
1127       {
1128          /*
1129           * We're done here, the caller isn't
1130           * interested in knowing the hostname.
1131           */
1132          return;
1133       }
1134
1135 #ifdef HAVE_RFC2553
1136       *hostname = malloc(NI_MAXHOST);
1137       retval = getnameinfo((struct sockaddr *) &server, s_length,
1138          *hostname, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
1139       if (retval)
1140       {
1141          log_error(LOG_LEVEL_ERROR,
1142             "Unable to resolve my own IP address: %s", gai_strerror(retval));
1143          freez(*hostname);
1144       }
1145 #else
1146 #if defined(HAVE_GETHOSTBYADDR_R_8_ARGS)
1147       gethostbyaddr_r((const char *)&server.sin_addr,
1148                       sizeof(server.sin_addr), AF_INET,
1149                       &result, hbuf, HOSTENT_BUFFER_SIZE,
1150                       &host, &thd_err);
1151 #elif defined(HAVE_GETHOSTBYADDR_R_7_ARGS)
1152       host = gethostbyaddr_r((const char *)&server.sin_addr,
1153                       sizeof(server.sin_addr), AF_INET,
1154                       &result, hbuf, HOSTENT_BUFFER_SIZE, &thd_err);
1155 #elif defined(HAVE_GETHOSTBYADDR_R_5_ARGS)
1156       if (0 == gethostbyaddr_r((const char *)&server.sin_addr,
1157                                sizeof(server.sin_addr), AF_INET,
1158                                &result, &hdata))
1159       {
1160          host = &result;
1161       }
1162       else
1163       {
1164          host = NULL;
1165       }
1166 #elif FEATURE_PTHREAD
1167       privoxy_mutex_lock(&resolver_mutex);
1168       host = gethostbyaddr((const char *)&server.sin_addr, 
1169                            sizeof(server.sin_addr), AF_INET);
1170       privoxy_mutex_unlock(&resolver_mutex);
1171 #else
1172       host = gethostbyaddr((const char *)&server.sin_addr, 
1173                            sizeof(server.sin_addr), AF_INET);
1174 #endif
1175       if (host == NULL)
1176       {
1177          log_error(LOG_LEVEL_ERROR, "Unable to get my own hostname: %E\n");
1178       }
1179       else
1180       {
1181          *hostname = strdup(host->h_name);
1182       }
1183 #endif /* else def HAVE_RFC2553 */
1184    }
1185
1186    return;
1187 }
1188
1189
1190 /*********************************************************************
1191  *
1192  * Function    :  accept_connection
1193  *
1194  * Description :  Accepts a connection on a socket.  Socket must have
1195  *                been created using bind_port().
1196  *
1197  * Parameters  :
1198  *          1  :  csp = Client state, cfd, ip_addr_str, and 
1199  *                ip_addr_long will be set by this routine.
1200  *          2  :  fd  = file descriptor returned from bind_port
1201  *
1202  * Returns     :  when a connection is accepted, it returns 1 (TRUE).
1203  *                On an error it returns 0 (FALSE).
1204  *
1205  *********************************************************************/
1206 int accept_connection(struct client_state * csp, jb_socket fd)
1207 {
1208 #ifdef HAVE_RFC2553
1209    /* XXX: client is stored directly into csp->tcp_addr */
1210 #define client (csp->tcp_addr)
1211    int retval;
1212 #else
1213    struct sockaddr_in client;
1214 #endif
1215    jb_socket afd;
1216 #if defined(_WIN32) || defined(__OS2__) || defined(__APPLE_CC__) || defined(AMIGA)
1217    /* Wierdness - fix a warning. */
1218    int c_length;
1219 #else
1220    socklen_t c_length;
1221 #endif
1222
1223    c_length = sizeof(client);
1224
1225 #ifdef _WIN32
1226    afd = accept (fd, (struct sockaddr *) &client, &c_length);
1227    if (afd == JB_INVALID_SOCKET)
1228    {
1229       return 0;
1230    }
1231 #else
1232    do
1233    {
1234       afd = accept (fd, (struct sockaddr *) &client, &c_length);
1235    } while (afd < 1 && errno == EINTR);
1236    if (afd < 0)
1237    {
1238       return 0;
1239    }
1240 #endif
1241
1242    csp->cfd = afd;
1243 #ifdef HAVE_RFC2553
1244    csp->ip_addr_str = malloc(NI_MAXHOST);
1245    retval = getnameinfo((struct sockaddr *) &client, c_length,
1246          csp->ip_addr_str, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
1247    if (!csp->ip_addr_str || retval)
1248    {
1249       log_error(LOG_LEVEL_ERROR, "Can not save csp->ip_addr_str: %s",
1250             (csp->ip_addr_str) ? gai_strerror(retval) : "Insuffcient memory");
1251       freez(csp->ip_addr_str);
1252    }
1253 #undef client
1254 #else
1255    csp->ip_addr_str  = strdup(inet_ntoa(client.sin_addr));
1256    csp->ip_addr_long = ntohl(client.sin_addr.s_addr);
1257 #endif /* def HAVE_RFC2553 */
1258
1259    return 1;
1260
1261 }
1262
1263
1264 /*********************************************************************
1265  *
1266  * Function    :  resolve_hostname_to_ip
1267  *
1268  * Description :  Resolve a hostname to an internet tcp/ip address.
1269  *                NULL or an empty string resolve to INADDR_ANY.
1270  *
1271  * Parameters  :
1272  *          1  :  host = hostname to resolve
1273  *
1274  * Returns     :  INADDR_NONE => failure, INADDR_ANY or tcp/ip address if succesful.
1275  *
1276  *********************************************************************/
1277 unsigned long resolve_hostname_to_ip(const char *host)
1278 {
1279    struct sockaddr_in inaddr;
1280    struct hostent *hostp;
1281    unsigned int dns_retries = 0;
1282 #if defined(HAVE_GETHOSTBYNAME_R_6_ARGS) || defined(HAVE_GETHOSTBYNAME_R_5_ARGS) || defined(HAVE_GETHOSTBYNAME_R_3_ARGS)
1283    struct hostent result;
1284 #if defined(HAVE_GETHOSTBYNAME_R_6_ARGS) || defined(HAVE_GETHOSTBYNAME_R_5_ARGS)
1285    char hbuf[HOSTENT_BUFFER_SIZE];
1286    int thd_err;
1287 #else /* defined(HAVE_GETHOSTBYNAME_R_3_ARGS) */
1288    struct hostent_data hdata;
1289 #endif /* def HAVE_GETHOSTBYNAME_R_(6|5)_ARGS */
1290 #endif /* def HAVE_GETHOSTBYNAME_R_(6|5|3)_ARGS */
1291
1292    if ((host == NULL) || (*host == '\0'))
1293    {
1294       return(INADDR_ANY);
1295    }
1296
1297    memset((char *) &inaddr, 0, sizeof inaddr);
1298
1299    if ((inaddr.sin_addr.s_addr = inet_addr(host)) == -1)
1300    {
1301 #if defined(HAVE_GETHOSTBYNAME_R_6_ARGS)
1302       while (gethostbyname_r(host, &result, hbuf,
1303                 HOSTENT_BUFFER_SIZE, &hostp, &thd_err)
1304              && (thd_err == TRY_AGAIN) && (dns_retries++ < MAX_DNS_RETRIES))
1305       {   
1306          log_error(LOG_LEVEL_ERROR,
1307             "Timeout #%u while trying to resolve %s. Trying again.",
1308             dns_retries, host);
1309       }
1310 #elif defined(HAVE_GETHOSTBYNAME_R_5_ARGS)
1311       while (NULL == (hostp = gethostbyname_r(host, &result,
1312                                  hbuf, HOSTENT_BUFFER_SIZE, &thd_err))
1313              && (thd_err == TRY_AGAIN) && (dns_retries++ < MAX_DNS_RETRIES))
1314       {   
1315          log_error(LOG_LEVEL_ERROR,
1316             "Timeout #%u while trying to resolve %s. Trying again.",
1317             dns_retries, host);
1318       }
1319 #elif defined(HAVE_GETHOSTBYNAME_R_3_ARGS)
1320       /*
1321        * XXX: Doesn't retry in case of soft errors.
1322        * Does this gethostbyname_r version set h_errno?
1323        */
1324       if (0 == gethostbyname_r(host, &result, &hdata))
1325       {
1326          hostp = &result;
1327       }
1328       else
1329       {
1330          hostp = NULL;
1331       }
1332 #elif FEATURE_PTHREAD
1333       privoxy_mutex_lock(&resolver_mutex);
1334       while (NULL == (hostp = gethostbyname(host))
1335              && (h_errno == TRY_AGAIN) && (dns_retries++ < MAX_DNS_RETRIES))
1336       {   
1337          log_error(LOG_LEVEL_ERROR,
1338             "Timeout #%u while trying to resolve %s. Trying again.",
1339             dns_retries, host);
1340       }
1341       privoxy_mutex_unlock(&resolver_mutex);
1342 #else
1343       while (NULL == (hostp = gethostbyname(host))
1344              && (h_errno == TRY_AGAIN) && (dns_retries++ < MAX_DNS_RETRIES))
1345       {
1346          log_error(LOG_LEVEL_ERROR,
1347             "Timeout #%u while trying to resolve %s. Trying again.",
1348             dns_retries, host);
1349       }
1350 #endif /* def HAVE_GETHOSTBYNAME_R_(6|5|3)_ARGS */
1351       /*
1352        * On Mac OSX, if a domain exists but doesn't have a type A
1353        * record associated with it, the h_addr member of the struct
1354        * hostent returned by gethostbyname is NULL, even if h_length
1355        * is 4. Therefore the second test below.
1356        */
1357       if (hostp == NULL || hostp->h_addr == NULL)
1358       {
1359          errno = EINVAL;
1360          log_error(LOG_LEVEL_ERROR, "could not resolve hostname %s", host);
1361          return(INADDR_NONE);
1362       }
1363       if (hostp->h_addrtype != AF_INET)
1364       {
1365 #ifdef _WIN32
1366          errno = WSAEPROTOTYPE;
1367 #else
1368          errno = EPROTOTYPE;
1369 #endif 
1370          log_error(LOG_LEVEL_ERROR, "hostname %s resolves to unknown address type.", host);
1371          return(INADDR_NONE);
1372       }
1373       memcpy(
1374          (char *) &inaddr.sin_addr,
1375          (char *) hostp->h_addr,
1376          sizeof(inaddr.sin_addr)
1377       );
1378    }
1379    return(inaddr.sin_addr.s_addr);
1380
1381 }
1382
1383
1384 /*
1385   Local Variables:
1386   tab-width: 3
1387   end:
1388 */