Fixed minor memory leak.
[privoxy.git] / jbsockets.c
1 const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.8 2001/06/03 11:03:48 oes 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 the SourceForge
12  *                IJBSWA team.  http://ijbswa.sourceforge.net
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.8  2001/06/03 11:03:48  oes
39  *    Makefile/in
40  *
41  *    introduced cgi.c
42  *
43  *    actions.c:
44  *
45  *    adapted to new enlist_unique arg format
46  *
47  *    conf loadcfg.c
48  *
49  *    introduced confdir option
50  *
51  *    filters.c filtrers.h
52  *
53  *     extracted-CGI relevant stuff
54  *
55  *    jbsockets.c
56  *
57  *     filled comment
58  *
59  *    jcc.c
60  *
61  *     support for new cgi mechansim
62  *
63  *    list.c list.h
64  *
65  *    functions for new list type: "map"
66  *    extended enlist_unique
67  *
68  *    miscutil.c .h
69  *    introduced bindup()
70  *
71  *    parsers.c parsers.h
72  *
73  *    deleted const struct interceptors
74  *
75  *    pcrs.c
76  *    added FIXME
77  *
78  *    project.h
79  *
80  *    added struct map
81  *    added struct http_response
82  *    changes struct interceptors to struct cgi_dispatcher
83  *    moved HTML stuff to cgi.h
84  *
85  *    re_filterfile:
86  *
87  *    changed
88  *
89  *    showargs.c
90  *    NO TIME LEFT
91  *
92  *    Revision 1.7  2001/05/28 16:14:00  jongfoster
93  *    Fixing bug in LOG_LEVEL_LOG
94  *
95  *    Revision 1.6  2001/05/26 17:28:32  jongfoster
96  *    Fixed LOG_LEVEL_LOG
97  *
98  *    Revision 1.5  2001/05/26 15:26:15  jongfoster
99  *    ACL feature now provides more security by immediately dropping
100  *    connections from untrusted hosts.
101  *
102  *    Revision 1.4  2001/05/26 00:37:42  jongfoster
103  *    Cosmetic indentation correction.
104  *
105  *    Revision 1.3  2001/05/25 21:57:54  jongfoster
106  *    Now gives a warning under Windows if you try to bind
107  *    it to a port that's already in use.
108  *
109  *    Revision 1.2  2001/05/17 23:01:01  oes
110  *     - Cleaned CRLF's from the sources and related files
111  *
112  *    Revision 1.1.1.1  2001/05/15 13:58:54  oes
113  *    Initial import of version 2.9.3 source tree
114  *
115  *
116  *********************************************************************/
117 \f
118
119 #include "config.h"
120
121 #include <stdlib.h>
122 #include <stdio.h>
123 #include <string.h>
124 #include <errno.h>
125 #include <fcntl.h>
126 #include <sys/types.h>
127
128 #ifdef _WIN32
129
130 #include <windows.h>
131 #include <sys/timeb.h>
132 #include <io.h>
133
134 #else
135
136 #include <unistd.h>
137 #include <sys/time.h>
138 #include <netinet/in.h>
139 #include <sys/ioctl.h>
140 #include <netdb.h>
141 #include <sys/socket.h>
142
143 #ifndef __BEOS__
144 #include <netinet/tcp.h>
145 #include <arpa/inet.h>
146 #else
147 #include <socket.h>
148 #endif
149
150 #endif
151
152 #include "project.h"
153 #include "jbsockets.h"
154 #include "filters.h"
155 #include "errlog.h"
156
157 const char jbsockets_h_rcs[] = JBSOCKETS_H_VERSION;
158
159
160 /*********************************************************************
161  *
162  * Function    :  connect_to
163  *
164  * Description :  Open a socket and connect to it.  Will check
165  *                that this is allowed according to ACL.
166  *
167  * Parameters  :
168  *          1  :  host = hostname to connect to
169  *          2  :  portnum = port to connent on
170  *          3  :  csp = Current client state (buffers, headers, etc...)
171  *                      Not modified, only used for source IP and ACL.
172  *
173  * Returns     :  -1 => failure, else it is the socket file descriptor.
174  *
175  *********************************************************************/
176 int connect_to(char *host, int portnum, struct client_state *csp)
177 {
178    struct sockaddr_in inaddr;
179    int   fd, addr;
180    fd_set wfds;
181    struct timeval tv[1];
182 #if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA)
183    int   flags;
184 #endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */
185
186 #ifdef ACL_FILES
187    struct access_control_addr dst[1];
188 #endif /* def ACL_FILES */
189
190    memset((char *)&inaddr, 0, sizeof inaddr);
191
192    if ((addr = resolve_hostname_to_ip(host)) == -1)
193    {
194       return(-1);
195    }
196
197 #ifdef ACL_FILES
198    dst->addr = ntohl(addr);
199    dst->port = portnum;
200
201    if (block_acl(dst, csp))
202    {
203       errno = EPERM;
204       return(-1);
205    }
206 #endif /* def ACL_FILES */
207
208    inaddr.sin_addr.s_addr = addr;
209    inaddr.sin_family      = AF_INET;
210
211    if (sizeof(inaddr.sin_port) == sizeof(short))
212    {
213       inaddr.sin_port = htons((short)portnum);
214    }
215    else
216    {
217       inaddr.sin_port = htonl(portnum);
218    }
219
220    if ((fd = socket(inaddr.sin_family, SOCK_STREAM, 0)) < 0)
221    {
222       return(-1);
223    }
224
225 #ifdef TCP_NODELAY
226    {  /* turn off TCP coalescence */
227       int mi = 1;
228       setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (char *) &mi, sizeof (int));
229    }
230 #endif /* def TCP_NODELAY */
231
232 #if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA)
233    if ((flags = fcntl(fd, F_GETFL, 0)) != -1)
234    {
235       flags |= O_NDELAY;
236       fcntl(fd, F_SETFL, flags);
237    }
238 #endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */
239
240    while (connect(fd, (struct sockaddr *) & inaddr, sizeof inaddr) == -1)
241    {
242 #ifdef _WIN32
243       if (errno == WSAEINPROGRESS)
244 #else /* ifndef _WIN32 */
245       if (errno == EINPROGRESS)
246 #endif /* ndef _WIN32 */
247       {
248          break;
249       }
250
251       if (errno != EINTR)
252       {
253          close_socket(fd);
254          return(-1);
255       }
256    }
257
258 #if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA)
259    if (flags != -1)
260    {
261       flags &= ~O_NDELAY;
262       fcntl(fd, F_SETFL, flags);
263    }
264 #endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */
265
266    /* wait for connection to complete */
267    FD_ZERO(&wfds);
268    FD_SET(fd, &wfds);
269
270    tv->tv_sec  = 30;
271    tv->tv_usec = 0;
272
273    if (select(fd + 1, NULL, &wfds, NULL, tv) <= 0)
274    {
275       close_socket(fd);
276       return(-1);
277    }
278    return(fd);
279
280 }
281
282
283 /*********************************************************************
284  *
285  * Function    :  write_socket
286  *
287  * Description :  Write the contents of buf (for n bytes) to socket fd.
288  *
289  * Parameters  :
290  *          1  :  fd = file descriptor (aka. handle) of socket to write to.
291  *          2  :  buf = pointer to data to be written.
292  *          3  :  len = length of data to be written to the socket "fd".
293  *
294  * Returns     :  Win32 & Unix: If no error occurs, returns the total number of
295  *                bytes sent, which can be less than the number
296  *                indicated by len. Otherwise, returns (-1).
297  *
298  *********************************************************************/
299 int write_socket(int fd, const char *buf, int len)
300 {
301    if (len <= 0)
302    {
303       return(0);
304    }
305
306    log_error(LOG_LEVEL_LOG, "%N", len, buf);
307
308 #if defined(_WIN32) || defined(__BEOS__) || defined(AMIGA)
309    return( send(fd, buf, len, 0));
310 #else
311    return( write(fd, buf, len));
312 #endif
313
314 }
315
316
317 /*********************************************************************
318  *
319  * Function    :  read_socket
320  *
321  * Description :  Read from a TCP/IP socket in a platform independent way.
322  *
323  * Parameters  :
324  *          1  :  fd = file descriptor of the socket to read
325  *          2  :  buf = pointer to buffer where data will be written
326  *                Must be >= len bytes long.
327  *          3  :  len = maximum number of bytes to read
328  *
329  * Returns     :  On success, the number of bytes read is returned (zero
330  *                indicates end of file), and the file position is advanced
331  *                by this number.  It is not an error if this number is
332  *                smaller than the number of bytes requested; this may hap-
333  *                pen for example because fewer bytes are actually available
334  *                right now (maybe because we were close to end-of-file, or
335  *                because we are reading from a pipe, or from a terminal),
336  *                or because read() was interrupted by a signal.  On error,
337  *                -1 is returned, and errno is set appropriately.  In this
338  *                case it is left unspecified whether the file position (if
339  *                any) changes.
340  *
341  *********************************************************************/
342 int read_socket(int fd, char *buf, int len)
343 {
344    if (len <= 0)
345    {
346       return(0);
347    }
348
349 #if defined(_WIN32) || defined(__BEOS__) || defined(AMIGA)
350    return( recv(fd, buf, len, 0));
351 #else
352    return( read(fd, buf, len));
353 #endif
354 }
355
356
357 /*********************************************************************
358  *
359  * Function    :  close_socket
360  *
361  * Description :  Closes a TCP/IP socket
362  *
363  * Parameters  :
364  *          1  :  fd = file descriptor of socket to be closed
365  *
366  * Returns     :  void
367  *
368  *********************************************************************/
369 void close_socket(int fd)
370 {
371 #if defined(_WIN32) || defined(__BEOS__)
372    closesocket(fd);
373 #elif defined(AMIGA)
374    CloseSocket(fd); 
375 #else
376    close(fd);
377 #endif
378
379 }
380
381
382 /*********************************************************************
383  *
384  * Function    :  bind_port
385  *
386  * Description :  Call socket, set socket options, and listen.
387  *                Called by listen_loop to "boot up" our proxy address.
388  *
389  * Parameters  :
390  *          1  :  hostnam = TCP/IP address to bind/listen to
391  *          2  :  portnum = port to listen on
392  *
393  * Returns     :  if success, return file descriptor
394  *                if failure, returns -2 if address is in use, otherwise -1
395  *
396  *********************************************************************/
397 int bind_port(const char *hostnam, int portnum)
398 {
399    struct sockaddr_in inaddr;
400    int fd;
401    int one = 1;
402
403    memset((char *)&inaddr, '\0', sizeof inaddr);
404
405    inaddr.sin_family      = AF_INET;
406    inaddr.sin_addr.s_addr = resolve_hostname_to_ip(hostnam);
407
408    if (sizeof(inaddr.sin_port) == sizeof(short))
409    {
410       inaddr.sin_port = htons((short)portnum);
411    }
412    else
413    {
414       inaddr.sin_port = htonl(portnum);
415    }
416
417    fd = socket(AF_INET, SOCK_STREAM, 0);
418
419    if (fd < 0)
420    {
421       return(-1);
422    }
423
424 #ifndef _WIN32
425    /*
426     * FIXME: This is not needed for Win32 - in fact, it stops
427     * duplicate instances of JunkBuster from being caught.
428     * Is this really needed under UNIX, or should it be taked out?
429     * -- Jon
430     */
431    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one));
432 #endif /* ndef _WIN32 */
433
434    if (bind (fd, (struct sockaddr *)&inaddr, sizeof(inaddr)) < 0)
435    {
436       close_socket (fd);
437 #ifdef _WIN32
438       if (errno == WSAEADDRINUSE)
439 #else
440       if (errno == EADDRINUSE)
441 #endif
442       {
443          return(-2);
444       }
445       else
446       {
447          return(-1);
448       }
449    }
450
451    while (listen(fd, 5) == -1)
452    {
453       if (errno != EINTR)
454       {
455          return(-1);
456       }
457    }
458
459    return fd;
460
461 }
462
463
464 /*********************************************************************
465  *
466  * Function    :  accept_connection
467  *
468  * Description :  Accepts a connection on a socket.  Socket must have
469  *                been created using bind_port().
470  *
471  * Parameters  :
472  *          1  :  csp = Client state, cfd, ip_addr_str, and 
473  *                ip_addr_long will be set by this routine.
474  *          2  :  fd  = file descriptor returned from bind_port
475  *
476  * Returns     :  when a connection is accepted, it returns 1 (TRUE).
477  *                On an error it returns 0 (FALSE).
478  *
479  *********************************************************************/
480 int accept_connection(struct client_state * csp, int fd)
481 {
482    struct sockaddr raddr;
483    struct sockaddr_in *rap = (struct sockaddr_in *) &raddr;
484    int   afd, raddrlen;
485
486    raddrlen = sizeof raddr;
487    do
488    {
489       afd = accept (fd, &raddr, &raddrlen);
490    } while (afd < 1 && errno == EINTR);
491
492    if (afd < 0)
493    {
494       return 0;
495    }
496
497    csp->cfd    = afd;
498    csp->ip_addr_str  = strdup(inet_ntoa(rap->sin_addr));
499    csp->ip_addr_long = ntohl(rap->sin_addr.s_addr);
500
501    return 1;
502 }
503
504
505 /*********************************************************************
506  *
507  * Function    :  resolve_hostname_to_ip
508  *
509  * Description :  Resolve a hostname to an internet tcp/ip address.
510  *                NULL or an empty string resolve to INADDR_ANY.
511  *
512  * Parameters  :
513  *          1  :  host = hostname to resolve
514  *
515  * Returns     :  -1 => failure, INADDR_ANY or tcp/ip address if succesful.
516  *
517  *********************************************************************/
518 int resolve_hostname_to_ip(const char *host)
519 {
520    struct sockaddr_in inaddr;
521    struct hostent *hostp;
522
523    if ((host == NULL) || (*host == '\0'))
524    {
525       return(INADDR_ANY);
526    }
527
528    memset((char *) &inaddr, 0, sizeof inaddr);
529
530    if ((inaddr.sin_addr.s_addr = inet_addr(host)) == -1)
531    {
532       if ((hostp = gethostbyname(host)) == NULL)
533       {
534          errno = EINVAL;
535          return(-1);
536       }
537       if (hostp->h_addrtype != AF_INET)
538       {
539 #ifdef _WIN32
540          errno = WSAEPROTOTYPE;
541 #else
542          errno = EPROTOTYPE;
543 #endif
544          return(-1);
545       }
546       memcpy(
547          (char *) &inaddr.sin_addr,
548          (char *) hostp->h_addr,
549          sizeof(inaddr.sin_addr)
550       );
551    }
552    return(inaddr.sin_addr.s_addr);
553
554 }
555
556
557 /*
558   Local Variables:
559   tab-width: 3
560   end:
561 */