dnl Process this file with autoconf to produce a configure script.
dnl
-dnl $Id: configure.in,v 1.126 2009/03/21 10:45:06 fabiankeil Exp $
+dnl $Id: configure.in,v 1.127 2009/03/25 17:26:31 fabiankeil Exp $
dnl
dnl Written by and Copyright (C) 2001-2009 the
dnl Privoxy team. http://www.privoxy.org/
dnl Temple Place - Suite 330, Boston, MA 02111-1307, USA.
dnl
dnl $Log: configure.in,v $
+dnl Revision 1.127 2009/03/25 17:26:31 fabiankeil
+dnl And they are running again. Bump version to 3.0.13 UNRELEASED.
+dnl
dnl Revision 1.126 2009/03/21 10:45:06 fabiankeil
dnl Declare the code stable.
dnl
dnl AutoConf Initialization
dnl =================================================================
-AC_REVISION($Revision: 1.126 $)
+AC_REVISION($Revision: 1.127 $)
AC_INIT(jcc.c)
if test ! -f config.h.in; then
AC_TYPE_SIGNAL
dnl uncommenting does not work for swa. suse linux
dnl AC_FUNC_STAT
-AC_CHECK_FUNCS([access atexit getcwd gethostbyaddr gethostbyaddr_r gethostbyname gethostbyname_r gettimeofday inet_ntoa localtime_r memchr memmove memset poll putenv random regcomp select setlocale snprintf socket strchr strdup strerror strftime strlcat strlcpy strptime strstr strtoul timegm tzset])
+AC_CHECK_FUNCS([access atexit getaddrinfo getcwd gethostbyaddr gethostbyaddr_r gethostbyname gethostbyname_r getnameinfo gettimeofday inet_ntoa localtime_r memchr memmove memset poll putenv random regcomp select setlocale snprintf socket strchr strdup strerror strftime strlcat strlcpy strptime strstr strtoul timegm tzset])
dnl =================================================================
Purpose : Used with other docs and files only.
- $Id: p-config.sgml,v 2.42 2009/03/23 04:17:47 ler762 Exp $
+ $Id: p-config.sgml,v 2.43 2009/03/28 15:33:41 fabiankeil Exp $
Copyright (C) 2001-2009 Privoxy Developers http://www.privoxy.org/
See LICENSE.
Sample Configuration File for Privoxy v&p-version;
</title>
<para>
- $Id: p-config.sgml,v 2.42 2009/03/23 04:17:47 ler762 Exp $
+ $Id: p-config.sgml,v 2.43 2009/03/28 15:33:41 fabiankeil Exp $
</para>
<para>
Copyright (C) 2001-2009 Privoxy Developers http://www.privoxy.org/
<term>Effect if unset:</term>
<listitem>
<para>
- Bind to 127.0.0.1 (localhost), port 8118. This is suitable and recommended for
- home users who run <application>Privoxy</application> on the same machine as
- their browser.
+ Bind to 127.0.0.1 (IPv4 localhost), port 8118. This is suitable and
+ recommended for home users who run <application>Privoxy</application> on
+ the same machine as their browser.
</para>
</listitem>
</varlistentry>
serve requests from other machines (e.g. on your local network) as well, you
will need to override the default.
</para>
+ <para>
+ IPv6 address containing colons has to be quoted by brackets.
+ </para>
<para>
If you leave out the IP address, <application>Privoxy</application> will
bind to all interfaces (addresses) on your machine and may become reachable
<para>
<programlisting>
listen-address 192.168.0.1:8118
+</programlisting>
+ </para>
+ <para>
+ Suppose you are running <application>Privoxy</application> on IPv6 capable
+ machine and you want to listen on IPv6 loopback device:
+ </para>
+ <para>
+ <programlisting>
+ listen-address [::1]:8118
</programlisting>
</para>
</listitem>
<term>Type of value:</term>
<listitem>
<para>
- <replaceable class="parameter">src_addr</replaceable>[/<replaceable class="parameter">src_masklen</replaceable>]
- [<replaceable class="parameter">dst_addr</replaceable>[/<replaceable class="parameter">dst_masklen</replaceable>]]
+ <replaceable class="parameter">src_addr</replaceable>[:<replaceable class="parameter">port</replaceable>][/<replaceable class="parameter">src_masklen</replaceable>]
+ [<replaceable class="parameter">dst_addr</replaceable>[:<replaceable class="parameter">port</replaceable>][/<replaceable class="parameter">dst_masklen</replaceable>]]
</para>
<para>
Where <replaceable class="parameter">src_addr</replaceable> and
- <replaceable class="parameter">dst_addr</replaceable> are IP addresses in dotted decimal notation or valid
- DNS names, and <replaceable class="parameter">src_masklen</replaceable> and
+ <replaceable class="parameter">dst_addr</replaceable> are IPv4 addresses in dotted decimal notation or valid
+ DNS names, <replaceable class="parameter">port</replaceable> is port
+ number, and <replaceable class="parameter">src_masklen</replaceable> and
<replaceable class="parameter">dst_masklen</replaceable> are subnet masks in CIDR notation, i.e. integer
values from 2 to 30 representing the length (in bits) of the network address. The masks and the whole
destination part are optional.
</para>
+ <para>
+ If your system implements
+ <ulink url="http://tools.ietf.org/html/rfc3493">RFC 3493</ulink>, then
+ <replaceable class="parameter">src_addr</replaceable> and <replaceable
+ class="parameter">dst_addr</replaceable> can be IPv6 addresses delimeted by
+ brackets, <replaceable class="parameter">port</replaceable> can be number
+ or service name, and
+ <replaceable class="parameter">src_masklen</replaceable> and
+ <replaceable class="parameter">dst_masklen</replaceable> can be number
+ from 0 to 128.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term>Default value:</term>
<listitem>
<para><emphasis>Unset</emphasis></para>
+ <para>
+ No <replaceable class="parameter">port</replaceable> means match any port
+ and no <replaceable class="parameter">src_masklen</replaceable> or
+ no <replaceable class="parameter">src_masklen</replaceable> means exactly
+ given IP address (i.e. 32 for IPv4 and 128 for IPv6).
+ </para>
</listitem>
</varlistentry>
<varlistentry>
like <quote>*.org</quote> or partial domain names. If a DNS name resolves to multiple
IP addresses, only the first one is used.
</para>
+ <para>
+ Some systems allows IPv4 client to connect to IPv6 server socket.
+ Then the client's IPv4 address will be translated by system into
+ IPv6 address space with special prefix ::ffff/96 (so called IPv4
+ mapped IPv6 address). <application>Privoxy</application> can handle it
+ and maps such ACL addresses automatically.
+ </para>
<para>
Denying access to particular sites by ACL may have undesired side effects
if the site in question is hosted on a machine which also hosts other sites
deny-access 192.168.45.73 www.dirty-stuff.example.com
</screen>
</para>
+ <para>
+ Allow access from IPv4 network 192.0.2.0/24 even if listening on
+ IPv6 wild card address (where supported by operating system):
+ </para>
+ <para>
+ <programlisting>
+ permit-access 192.0.2.0/24
+</programlisting>
+ </para>
+ <para>
+ This is equivalent to the following line even if listening on IPv4
+ address (where supported by operating system):
+ </para>
+ <para>
+ <programlisting>
+ permit-access [::ffff:192.0.2.0]/120
+</programlisting>
+ </para>
</listitem>
</varlistentry>
</variablelist>
denote <quote>all URLs</quote>.
<replaceable class="parameter">http_parent</replaceable>[:<replaceable class="parameter">port</replaceable>]
is the DNS name or IP address of the parent HTTP proxy through which the requests should be forwarded,
- optionally followed by its listening port (default: 8080).
+ optionally followed by its listening port (default: 8000).
Use a single dot (<literal>.</literal>) to denote <quote>no forwarding</quote>.
</para>
</listitem>
If <replaceable class="parameter">http_parent</replaceable> is <quote>.</quote>, then requests are not
forwarded to another HTTP proxy but are made directly to the web servers.
</para>
+ <para>
+ <replaceable class="parameter">http_parent</replaceable> can be IPv6
+ numerical address (if
+ <ulink url="http://tools.ietf.org/html/rfc3493">RFC 3493</ulink> is
+ implemented). However not to clash with port delimiter, quote
+ whole IP address with brackets. On the other hand <replaceable
+ class="parameter">target_pattern</replaceable> containing IPv6 address
+ must be delimited by angle brackets (normal brackets are reserved for
+ regular expression already).
+ </para>
<para>
Multiple lines are OK, they are checked in sequence, and the last match wins.
</para>
forward .isp.example.net .
</screen>
</para>
+ <para>
+ Parent proxy specified by IPv6 address:
+ </para>
+ <para>
+ <programlisting>
+ foward / [2001:DB8::1]:8000
+</programlisting>
+ </para>
+ <para>
+ Suppose your parent proxy doesn't support IPv6:
+ </para>
+ <para>
+ <programlisting>
+ forward / parent-proxy.example.org:8000
+ forward ipv6-server.example.org .
+ forward <[2-3][0-9a-f][0-9a-f][0-9a-f]:*> .
+</programlisting>
+ </para>
</listitem>
</varlistentry>
</variablelist>
<para>
With <literal>forward-socks5</literal> the DNS resolution will happen on the remote server as well.
</para>
+ <para>
+ <replaceable class="parameter">socks_proxy</replaceable> and
+ <replaceable clss="parameter">http_parent</replaceable> can be IPv6
+ numerical address (if
+ <ulink url="http://tools.ietf.org/html/rfc3493">RFC 3493</ulink> is
+ implemented). However not to clash with port
+ delimiter, quote whole IP address with brackets. On the other
+ hand <replaceable class="parameter">target_pattern</replaceable> containing
+ IPv6 address must be delimited by angle brackets (normal brackets are
+ reserved for regular expression already). The only exception is SOCKS 4
+ version where only IPv4 is suppored.
+ </para>
<para>
If <replaceable class="parameter">http_parent</replaceable> is <quote>.</quote>, then requests are not
forwarded to another HTTP proxy but are made (HTTP-wise) directly to the web servers, albeit through
This file belongs into
ijbswa.sourceforge.net:/home/groups/i/ij/ijbswa/htdocs/
- $Id: user-manual.sgml,v 2.102 2009/03/15 19:31:36 fabiankeil Exp $
+ $Id: user-manual.sgml,v 2.103 2009/03/21 10:49:05 fabiankeil Exp $
Copyright (C) 2001-2009 Privoxy Developers http://www.privoxy.org/
See LICENSE.
</subscript>
</pubdate>
-<pubdate>$Id: user-manual.sgml,v 2.102 2009/03/15 19:31:36 fabiankeil Exp $</pubdate>
+<pubdate>$Id: user-manual.sgml,v 2.103 2009/03/21 10:49:05 fabiankeil Exp $</pubdate>
<!--
<para>
Generally, an URL pattern has the form
- <literal><domain>/<path></literal>, where both the
- <literal><domain></literal> and <literal><path></literal> are
- optional. (This is why the special <literal>/</literal> pattern matches all
- URLs). Note that the protocol portion of the URL pattern (e.g.
- <literal>http://</literal>) should <emphasis>not</emphasis> be included in
- the pattern. This is assumed already!
+ <literal><domain><port>/<path></literal>, where both the
+ <literal><domain></literal> and <literal><port></literal>
+ and <literal><path></literal> are optional. (This is why the special
+ <literal>/</literal> pattern matches all URLs). Note that the protocol
+ portion of the URL pattern (e.g. <literal>http://</literal>) should
+ <emphasis>not</emphasis> be included in the pattern. This is assumed already!
</para>
<para>
The pattern matching syntax is different for the domain and path parts of
<ulink url="http://en.wikipedia.org/wiki/Regular_expressions"><quote>Regular
Expressions</quote></ulink> (POSIX 1003.2).
</para>
+<para>
+ The port part of pattern is decimal port number preceeded by a colon
+ (<literal>:</literal>). If domain part contains numeric IPv6 address, you
+ will need to quote the domain part by angle brackets
+ (<literal><</literal>, <literal>></literal>).
+</para>
<variablelist>
<varlistentry>
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><literal>:8000/</literal></term>
+ <listitem>
+ <para>
+ Matches any URL pointing to TCP port 8000.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal><2001:db8::1>/</literal></term>
+ <listitem>
+ <para>
+ Matches any URL having <literal>2001:db8::1</literal> as a domain.
+ (Note that real URL uses plain brackets, not an angle brackets.)
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><literal>index.html</literal></term>
<listitem>
USA
$Log: user-manual.sgml,v $
+ Revision 2.103 2009/03/21 10:49:05 fabiankeil
+ Merge updated ChangeLog.
+
Revision 2.102 2009/03/15 19:31:36 fabiankeil
Update "What's New in this Release" section.
-const char filters_rcs[] = "$Id: filters.c,v 1.112 2009/03/01 18:28:23 fabiankeil Exp $";
+const char filters_rcs[] = "$Id: filters.c,v 1.113 2009/03/08 14:19:23 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/filters.c,v $
*
* Revisions :
* $Log: filters.c,v $
+ * Revision 1.113 2009/03/08 14:19:23 fabiankeil
+ * Fix justified (but harmless) compiler warnings
+ * on platforms where sizeof(int) < sizeof(long).
+ *
* Revision 1.112 2009/03/01 18:28:23 fabiankeil
* Help clang understand that we aren't dereferencing
* NULL pointers here.
#include <string.h>
#include <assert.h>
+#ifdef HAVE_GETADDRINFO
+#include <netdb.h>
+#include <sys/socket.h>
+#endif /* def HAVE_GETADDRINFO */
+
#ifndef _WIN32
#ifndef __OS2__
#include <unistd.h>
static jb_err prepare_for_filtering(struct client_state *csp);
#ifdef FEATURE_ACL
+#ifdef HAVE_GETADDRINFO
+/*********************************************************************
+ *
+ * Function : sockaddr_storage_to_ip
+ *
+ * Description : Access internal structure of sockaddr_storage
+ *
+ * Parameters :
+ * 1 : addr = socket address
+ * 2 : ip = IP address as array of octets in network order
+ * (it points into addr)
+ * 3 : len = length of IP address in octets
+ * 4 : port = port number in network order;
+ *
+ * Returns : 0 = no errror; otherwise
+ *
+ *********************************************************************/
+int sockaddr_storage_to_ip(const struct sockaddr_storage *addr, uint8_t **ip,
+ unsigned int *len, in_port_t **port)
+{
+ if (!addr)
+ {
+ return(-1);
+ }
+
+ switch (addr->ss_family)
+ {
+ case AF_INET:
+ if (len)
+ {
+ *len = 4;
+ }
+ if (ip)
+ {
+ *ip = (uint8_t *)
+ &(( (struct sockaddr_in *) addr)->sin_addr.s_addr);
+ }
+ if (port)
+ {
+ *port = &((struct sockaddr_in *) addr)->sin_port;
+ }
+ break;
+
+ case AF_INET6:
+ if (len)
+ {
+ *len = 16;
+ }
+ if (ip)
+ {
+ *ip = ( (struct sockaddr_in6 *) addr)->sin6_addr.s6_addr;
+ }
+ if (port)
+ {
+ *port = &((struct sockaddr_in6 *) addr)->sin6_port;
+ }
+ break;
+
+ default:
+ /* Unsupported address family */
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+/*********************************************************************
+ *
+ * Function : match_sockaddr
+ *
+ * Description : Check whether address matches network (IP address and port)
+ *
+ * Parameters :
+ * 1 : network = socket address of subnework
+ * 3 : netmask = network mask as socket address
+ * 2 : address = checked socket address against given network
+ *
+ * Returns : 0 = doesn't match; 1 = does match
+ *
+ *********************************************************************/
+int match_sockaddr(const struct sockaddr_storage *network,
+ const struct sockaddr_storage *netmask,
+ const struct sockaddr_storage *address)
+{
+ uint8_t *network_addr, *netmask_addr, *address_addr;
+ unsigned int addr_len;
+ in_port_t *network_port, *netmask_port, *address_port;
+ int i;
+
+ if (network->ss_family != netmask->ss_family)
+ {
+ /* This should never happen */
+ log_error(LOG_LEVEL_ERROR,
+ "Internal error at %s:%llu: network and netmask differ in family",
+ __FILE__, __LINE__);
+ return 0;
+ }
+
+ sockaddr_storage_to_ip(network, &network_addr, &addr_len, &network_port);
+ sockaddr_storage_to_ip(netmask, &netmask_addr, NULL, &netmask_port);
+ sockaddr_storage_to_ip(address, &address_addr, NULL, &address_port);
+
+ /* Check for family */
+ if (network->ss_family == AF_INET && address->ss_family == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(address_addr))
+ {
+ /* Map AF_INET6 V4MAPPED address into AF_INET */
+ address_addr += 12;
+ addr_len = 4;
+ }
+ else if (network->ss_family == AF_INET6 && address->ss_family == AF_INET &&
+ IN6_IS_ADDR_V4MAPPED(network_addr))
+ {
+ /* Map AF_INET6 V4MAPPED network into AF_INET */
+ network_addr += 12;
+ netmask_addr += 12;
+ addr_len = 4;
+ }
+ else if (network->ss_family != address->ss_family)
+ {
+ return 0;
+ }
+
+ /* XXX: Port check is signaled in netmask */
+ if (*netmask_port && *network_port != *address_port)
+ {
+ return 0;
+ }
+
+ /* TODO: Optimize by checking by words insted of octets */
+ for (i=0; i < addr_len && netmask_addr[i]; i++)
+ {
+ if ( (network_addr[i] & netmask_addr[i]) !=
+ (address_addr[i] & netmask_addr[i]) )
+ {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+#endif /* def HAVE_GETADDRINFO */
+
+
/*********************************************************************
*
* Function : block_acl
/* search the list */
while (acl != NULL)
{
- if ((csp->ip_addr_long & acl->src->mask) == acl->src->addr)
+ if (
+#ifdef HAVE_GETADDRINFO
+ match_sockaddr(&acl->src->addr, &acl->src->mask, &csp->tcp_addr)
+#else
+ (csp->ip_addr_long & acl->src->mask) == acl->src->addr
+#endif
+ )
{
if (dst == NULL)
{
return(0);
}
}
- else if ( ((dst->addr & acl->dst->mask) == acl->dst->addr)
- && ((dst->port == acl->dst->port) || (acl->dst->port == 0)))
+ else if (
+#ifdef HAVE_GETADDRINFO
+ /* XXX: Undefined acl->dst is full of zeros and should be
+ * considered as wildcard address.
+ * sockaddr_storage_to_ip() failes on such dst because of
+ * uknown sa_familly on glibc. However this test is not
+ * portable.
+ *
+ * So, we signal the acl->dst is wildcard in wildcard_dst.
+ */
+ acl->wildcard_dst ||
+ match_sockaddr(&acl->dst->addr, &acl->dst->mask, &dst->addr)
+#else
+ ((dst->addr & acl->dst->mask) == acl->dst->addr)
+ && ((dst->port == acl->dst->port) || (acl->dst->port == 0))
+#endif
+ )
{
if (acl->action == ACL_PERMIT)
{
int acl_addr(const char *aspec, struct access_control_addr *aca)
{
int i, masklength;
+#ifdef HAVE_GETADDRINFO
+ struct addrinfo hints, *result;
+ uint8_t *mask_data;
+ in_port_t *mask_port;
+ unsigned int addr_len;
+#else
long port;
+#endif /* def HAVE_GETADDRINFO */
char *p;
char *acl_spec = NULL;
+#ifdef HAVE_GETADDRINFO
+ /* FIXME: Depend on ai_family */
+ masklength = 128;
+#else
masklength = 32;
port = 0;
+#endif
/*
* Use a temporary acl spec copy so we can log
masklength = atoi(p);
}
- if ((masklength < 0) || (masklength > 32))
+ if ((masklength < 0) ||
+#ifdef HAVE_GETADDRINFO
+ (masklength > 128)
+#else
+ (masklength > 32)
+#endif
+ )
{
freez(acl_spec);
return(-1);
}
- if ((p = strchr(acl_spec, ':')) != NULL)
+ if (*acl_spec == '[' && NULL != (p = strchr(acl_spec, ']')))
+ {
+ *p = '\0';
+ memmove(acl_spec, acl_spec + 1, (size_t) (p - acl_spec));
+
+ if (*++p != ':')
+ {
+ p = NULL;
+ }
+ }
+ else
+ {
+ p = strchr(acl_spec, ':');
+ }
+
+#ifdef HAVE_GETADDRINFO
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ i = getaddrinfo(acl_spec, (p) ? ++p : NULL, &hints, &result);
+ freez(acl_spec);
+
+ if (i != 0)
+ {
+ log_error(LOG_LEVEL_ERROR, "Can not resolve [%s]:%s: %s", acl_spec, p,
+ gai_strerror(i));
+ return(-1);
+ }
+
+ /* TODO: Allow multihomed hostnames */
+ memcpy(&(aca->addr), result->ai_addr, result->ai_addrlen);
+ freeaddrinfo(result);
+#else
+ if (p != NULL)
{
char *endptr;
/* XXX: This will be logged as parse error. */
return(-1);
}
+#endif /* def HAVE_GETADDRINFO */
/* build the netmask */
+#ifdef HAVE_GETADDRINFO
+ /* Clip masklength according current family */
+ if (aca->addr.ss_family == AF_INET && masklength > 32)
+ {
+ masklength = 32;
+ }
+
+ aca->mask.ss_family = aca->addr.ss_family;
+ if (sockaddr_storage_to_ip(&aca->mask, &mask_data, &addr_len, &mask_port))
+ {
+ return(-1);
+ }
+
+ if (p)
+ {
+ /* Port number in ACL has been specified, check ports in future */
+ *mask_port = 1;
+ }
+
+ /* XXX: This could be optimized to operate on whole words instead of octets
+ * (128-bit CPU could do it in one iteration). */
+ /* Octets after prefix can be ommitted because of previous initialization
+ * to zeros. */
+ for (i=0; i < addr_len && masklength; i++)
+ {
+ if (masklength >= 8)
+ {
+ mask_data[i] = 0xFF;
+ masklength -= 8;
+ }
+ else
+ {
+ /* XXX: This assumes MSB of octet is on the left site. This should be
+ * true for all architectures or solved on link layer of OSI model. */
+ mask_data[i] = ~((1 << (8 - masklength)) - 1);
+ masklength = 0;
+ }
+ }
+
+#else
aca->mask = 0;
for (i=1; i <= masklength ; i++)
{
* (i.e. save on the network portion of the address).
*/
aca->addr = aca->addr & aca->mask;
+#endif /* def HAVE_GETADDRINFO */
return(0);
Local Variables:
tab-width: 3
end:
+
+ vim:softtabstop=3 shiftwidth=3
*/
-const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.49 2008/11/10 17:03:57 fabiankeil Exp $";
+const char jbsockets_rcs[] = "$Id: jbsockets.c,v 1.50 2008/12/20 14:53:55 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/jbsockets.c,v $
*
* Revisions :
* $Log: jbsockets.c,v $
+ * Revision 1.50 2008/12/20 14:53:55 fabiankeil
+ * Add config option socket-timeout to control the time
+ * Privoxy waits for data to arrive on a socket. Useful
+ * in case of stale ssh tunnels or when fuzz-testing.
+ *
* Revision 1.49 2008/11/10 17:03:57 fabiankeil
* Fix a gcc44 warning and remove a now-obsolete cast.
*
* file descriptor.
*
*********************************************************************/
+#ifdef HAVE_GETADDRINFO
+/* Getaddrinfo implementation */
+jb_socket connect_to(const char *host, int portnum, struct client_state *csp)
+{
+ struct addrinfo hints, *result, *rp;
+ char service[6];
+ int retval;
+ jb_socket fd;
+ fd_set wfds;
+ struct timeval tv[1];
+#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA)
+ int flags;
+#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) */
+ int connect_failed;
+
+#ifdef FEATURE_ACL
+ struct access_control_addr dst[1];
+#endif /* def FEATURE_ACL */
+
+ retval = snprintf(service, sizeof(service), "%d", portnum);
+ if (-1 == retval || sizeof(service) <= retval)
+ {
+ log_error(LOG_LEVEL_ERROR,
+ "Port number (%d) ASCII decimal representation doesn't fit into 6 bytes",
+ portnum);
+ csp->http->host_ip_addr_str = strdup("unknown");
+ return(JB_INVALID_SOCKET);
+ }
+
+ memset((char *)&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV; /* avoid service look-up */
+ if ((retval = getaddrinfo(host, service, &hints, &result)))
+ {
+ log_error(LOG_LEVEL_INFO,
+ "Can not resolve %s: %s", host, gai_strerror(retval));
+ csp->http->host_ip_addr_str = strdup("unknown");
+ return(JB_INVALID_SOCKET);
+ }
+
+ for (rp = result; rp != NULL; rp = rp->ai_next)
+ {
+
+#ifdef FEATURE_ACL
+ memcpy(&dst->addr, rp->ai_addr, rp->ai_addrlen);
+
+ if (block_acl(dst, csp))
+ {
+#ifdef __OS2__
+ errno = SOCEPERM;
+#else
+ errno = EPERM;
+#endif
+ continue;
+ }
+#endif /* def FEATURE_ACL */
+
+ csp->http->host_ip_addr_str = malloc(NI_MAXHOST);
+ retval = getnameinfo(rp->ai_addr, rp->ai_addrlen,
+ csp->http->host_ip_addr_str, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
+ if (!csp->http->host_ip_addr_str || retval)
+ {
+ log_error(LOG_LEVEL_ERROR, "Can not save csp->http->host_ip_addr_str: %s",
+ (csp->http->host_ip_addr_str) ? gai_strerror(retval) :
+ "Insufficient memory");
+ freez(csp->http->host_ip_addr_str);
+ continue;
+ }
+
+#ifdef _WIN32
+ if ((fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) ==
+ JB_INVALID_SOCKET)
+#else
+ if ((fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0)
+#endif
+ {
+ continue;
+ }
+
+#ifdef TCP_NODELAY
+ { /* turn off TCP coalescence */
+ int mi = 1;
+ setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &mi, sizeof (int));
+ }
+#endif /* def TCP_NODELAY */
+
+#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
+ if ((flags = fcntl(fd, F_GETFL, 0)) != -1)
+ {
+ flags |= O_NDELAY;
+ fcntl(fd, F_SETFL, flags);
+ }
+#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */
+
+ connect_failed = 0;
+ while (connect(fd, rp->ai_addr, rp->ai_addrlen) == JB_INVALID_SOCKET)
+ {
+#ifdef _WIN32
+ if (errno == WSAEINPROGRESS)
+#elif __OS2__
+ if (sock_errno() == EINPROGRESS)
+#else /* ifndef _WIN32 */
+ if (errno == EINPROGRESS)
+#endif /* ndef _WIN32 || __OS2__ */
+ {
+ break;
+ }
+
+#ifdef __OS2__
+ if (sock_errno() != EINTR)
+#else
+ if (errno != EINTR)
+#endif /* __OS2__ */
+ {
+ close_socket(fd);
+ connect_failed = 1;
+ break;
+ }
+ }
+ if (connect_failed)
+ {
+ continue;
+ }
+
+#if !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__)
+ if (flags != -1)
+ {
+ flags &= ~O_NDELAY;
+ fcntl(fd, F_SETFL, flags);
+ }
+#endif /* !defined(_WIN32) && !defined(__BEOS__) && !defined(AMIGA) && !defined(__OS2__) */
+
+ /* wait for connection to complete */
+ FD_ZERO(&wfds);
+ FD_SET(fd, &wfds);
+
+ tv->tv_sec = 30;
+ tv->tv_usec = 0;
+
+ /* MS Windows uses int, not SOCKET, for the 1st arg of select(). Wierd! */
+ if (select((int)fd + 1, NULL, &wfds, NULL, tv) <= 0)
+ {
+ close_socket(fd);
+ continue;
+ }
+
+ break; /* for; Connection established; don't try other addresses */
+ }
+
+ freeaddrinfo(result);
+ if (!rp)
+ {
+ log_error(LOG_LEVEL_INFO, "Could not connect to TCP/[%s]:%s", host, service);
+ return(JB_INVALID_SOCKET);
+ }
+ /* XXX: Current connection verification (EINPROGRESS && select() for
+ * writing) is not sufficient. E.g. on my Linux-2.6.27 with glibc-2.6
+ * select returns socket ready for writing, however subsequential write(2)
+ * fails with ENOCONNECT. Read Linux connect(2) man page about non-blocking
+ * sockets.
+ * Thus we can not log here the socket is connected. */
+ /*log_error(LOG_LEVEL_INFO, "Connected to TCP/[%s]:%s", host, service);*/
+
+ return(fd);
+
+}
+
+# else /* ndef HAVE_GETADDRINFO */
+/* Pre-getaddrinfo implementation */
+
jb_socket connect_to(const char *host, int portnum, struct client_state *csp)
{
struct sockaddr_in inaddr;
return(fd);
}
+#endif /* ndef HAVE_GETADDRINFO */
/*********************************************************************
*********************************************************************/
int bind_port(const char *hostnam, int portnum, jb_socket *pfd)
{
+#ifdef HAVE_GETADDRINFO
+ struct addrinfo hints;
+ struct addrinfo *result, *rp;
+ /* TODO: portnum shuld be string to allow symbolic service names in
+ * configuration and to avoid following int2string */
+ char servnam[6];
+ int retval;
+#else
struct sockaddr_in inaddr;
+#endif /* def HAVE_GETADDRINFO */
jb_socket fd;
#ifndef _WIN32
int one = 1;
*pfd = JB_INVALID_SOCKET;
+#ifdef HAVE_GETADDRINFO
+ retval = snprintf(servnam, sizeof(servnam), "%d", portnum);
+ if (-1 == retval || sizeof(servnam) <= retval)
+ {
+ log_error(LOG_LEVEL_ERROR,
+ "Port number (%d) ASCII decimal representation doesn't fit into 6 bytes",
+ portnum);
+ return -1;
+ }
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family=AF_UNSPEC;
+ hints.ai_socktype=SOCK_STREAM;
+ hints.ai_flags=AI_PASSIVE|AI_ADDRCONFIG;
+ hints.ai_protocol=0; /* Realy any stream protocol or TCP only */
+ hints.ai_canonname=NULL;
+ hints.ai_addr=NULL;
+ hints.ai_next=NULL;
+
+ if ((retval = getaddrinfo(hostnam, servnam, &hints, &result)))
+ {
+ log_error(LOG_LEVEL_ERROR,
+ "Can not resolve %s: %s", hostnam, gai_strerror(retval));
+ return -2;
+ }
+#else
memset((char *)&inaddr, '\0', sizeof inaddr);
inaddr.sin_family = AF_INET;
inaddr.sin_port = htonl((unsigned long) portnum);
}
#endif /* ndef _WIN32 */
+#endif /* def HAVE_GETADDRINFO */
+#ifdef HAVE_GETADDRINFO
+ for (rp = result; rp != NULL; rp = rp->ai_next)
+ {
+ fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+#else
fd = socket(AF_INET, SOCK_STREAM, 0);
+#endif /* def HAVE_GETADDRINFO */
#ifdef _WIN32
if (fd == JB_INVALID_SOCKET)
if (fd < 0)
#endif
{
+#ifdef HAVE_GETADDRINFO
+ continue;
+#else
return(-1);
+#endif
}
#ifndef _WIN32
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one));
#endif /* ndef _WIN32 */
+#ifdef HAVE_GETADDRINFO
+ if (bind(fd, rp->ai_addr, rp->ai_addrlen) < 0)
+#else
if (bind(fd, (struct sockaddr *)&inaddr, sizeof(inaddr)) < 0)
+#endif
{
#ifdef _WIN32
errno = WSAGetLastError();
if (errno == EADDRINUSE)
#endif
{
+#ifdef HAVE_GETADDRINFO
+ freeaddrinfo(result);
+#endif
close_socket(fd);
return(-3);
}
else
{
close_socket(fd);
+#ifndef HAVE_GETADDRINFO
return(-1);
}
}
+#else
+ }
+ }
+ else
+ /* bind() succeeded, escape from for-loop */
+ /* TODO: Support multiple listening sockets (e.g. localhost resolves to
+ * AF_INET and AF_INET6, but only fist address is used */
+ break;
+ }
+
+ freeaddrinfo(result);
+ if (rp == NULL)
+ {
+ /* All bind()s failed */
+ return(-1);
+ }
+#endif /* ndef HAVE_GETADDRINFO */
while (listen(fd, MAX_LISTEN_BACKLOG) == -1)
{
*********************************************************************/
void get_host_information(jb_socket afd, char **ip_address, char **hostname)
{
+#ifdef HAVE_GETNAMEINFO
+ struct sockaddr_storage server;
+ int retval;
+#else
struct sockaddr_in server;
struct hostent *host = NULL;
+#endif /* HAVE_GETNAMEINFO */
#if defined(_WIN32) || defined(__OS2__) || defined(__APPLE_CC__) || defined(AMIGA)
/* according to accept_connection() this fixes a warning. */
- int s_length;
+ int s_length, s_length_provided;
#else
- socklen_t s_length;
+ socklen_t s_length, s_length_provided;
#endif
+#ifndef HAVE_GETNAMEINFO
#if defined(HAVE_GETHOSTBYADDR_R_8_ARGS) || defined(HAVE_GETHOSTBYADDR_R_7_ARGS) || defined(HAVE_GETHOSTBYADDR_R_5_ARGS)
struct hostent result;
#if defined(HAVE_GETHOSTBYADDR_R_5_ARGS)
int thd_err;
#endif /* def HAVE_GETHOSTBYADDR_R_5_ARGS */
#endif /* def HAVE_GETHOSTBYADDR_R_(8|7|5)_ARGS */
- s_length = sizeof(server);
+#endif /* ifndef HAVE_GETNAMEINFO */
+ s_length = s_length_provided = sizeof(server);
if (NULL != hostname)
{
if (!getsockname(afd, (struct sockaddr *) &server, &s_length))
{
+ if (s_length > s_length_provided)
+ {
+ log_error(LOG_LEVEL_ERROR, "getsockname() truncated server address");
+ return;
+ }
+#ifdef HAVE_GETNAMEINFO
+ *ip_address = malloc(NI_MAXHOST);
+ if ((retval = getnameinfo((struct sockaddr *) &server, s_length,
+ *ip_address, NI_MAXHOST, NULL, 0, NI_NUMERICHOST))) {
+ log_error(LOG_LEVEL_ERROR, "Unable to print my own IP address: %s",
+ gai_strerror(retval));
+ freez(*ip_address);
+ return;
+ }
+#else
*ip_address = strdup(inet_ntoa(server.sin_addr));
-
+#endif /* HAVE_GETNAMEINFO */
if (NULL == hostname)
{
/*
*/
return;
}
+
+#ifdef HAVE_GETNAMEINFO
+ *hostname = malloc(NI_MAXHOST);
+ if ((retval = getnameinfo((struct sockaddr *) &server, s_length,
+ *hostname, NI_MAXHOST, NULL, 0, NI_NAMEREQD))) {
+ log_error(LOG_LEVEL_ERROR, "Unable to resolve my own IP address: %s",
+ gai_strerror(retval));
+ freez(*hostname);
+ }
+#else
#if defined(HAVE_GETHOSTBYADDR_R_8_ARGS)
gethostbyaddr_r((const char *)&server.sin_addr,
sizeof(server.sin_addr), AF_INET,
{
*hostname = strdup(host->h_name);
}
+#endif /* else def HAVE_GETNAMEINFO */
}
return;
*********************************************************************/
int accept_connection(struct client_state * csp, jb_socket fd)
{
+#ifdef HAVE_GETNAMEINFO
+ /* XXX: client is stored directly into csp->tcp_addr */
+#define client (csp->tcp_addr)
+ int retval;
+#else
struct sockaddr_in client;
+#endif
jb_socket afd;
#if defined(_WIN32) || defined(__OS2__) || defined(__APPLE_CC__) || defined(AMIGA)
/* Wierdness - fix a warning. */
#endif
csp->cfd = afd;
+#ifdef HAVE_GETNAMEINFO
+ csp->ip_addr_str = malloc(NI_MAXHOST);
+ retval = getnameinfo((struct sockaddr *) &client, c_length,
+ csp->ip_addr_str, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
+ if (!csp->ip_addr_str || retval)
+ {
+ log_error(LOG_LEVEL_ERROR, "Can not save csp->ip_addr_str: %s",
+ (csp->ip_addr_str) ? gai_strerror(retval) : "Insuffcient memory");
+ freez(csp->ip_addr_str);
+ }
+#undef client
+#else
csp->ip_addr_str = strdup(inet_ntoa(client.sin_addr));
csp->ip_addr_long = ntohl(client.sin_addr.s_addr);
+#endif /* def HAVE_GETNAMEINFO */
return 1;
Local Variables:
tab-width: 3
end:
+
+ vim:softtabstop=3 shiftwidth=3
*/
-const char jcc_rcs[] = "$Id: jcc.c,v 1.241 2009/04/11 10:37:23 fabiankeil Exp $";
+const char jcc_rcs[] = "$Id: jcc.c,v 1.242 2009/04/11 10:44:47 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/jcc.c,v $
*
* Revisions :
* $Log: jcc.c,v $
+ * Revision 1.242 2009/04/11 10:44:47 fabiankeil
+ * Update a comment. We're not in Kansas anymore.
+ *
* Revision 1.241 2009/04/11 10:37:23 fabiankeil
* When dropping connections due to ACL, don't leak csp->ip_addr_str.
*
if (fwd->forward_host)
{
- log_error(LOG_LEVEL_CONNECT, "via %s:%d to: %s",
+ log_error(LOG_LEVEL_CONNECT, "via [%s]:%d to: %s",
fwd->forward_host, fwd->forward_port, http->hostport);
}
else
Local Variables:
tab-width: 3
end:
+
+ vim:softtabstop=3 shiftwidth=3
*/
-const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.92 2009/03/18 20:43:19 fabiankeil Exp $";
+const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.93 2009/03/18 21:46:26 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/loadcfg.c,v $
*
* Revisions :
* $Log: loadcfg.c,v $
+ * Revision 1.93 2009/03/18 21:46:26 fabiankeil
+ * Revert the last commit as there's a better way.
+ *
* Revision 1.92 2009/03/18 20:43:19 fabiankeil
* Don't enable LOG_LEVEL_INFO by default and don't apply the user's
* debug settings until the logfile has been opened (if there is one).
* Set to defaults
*/
config->multi_threaded = 1;
- config->hport = HADDR_PORT;
config->buffer_limit = 4096 * 1024;
config->usermanual = strdup(USER_MANUAL_URL);
config->proxy_args = strdup("");
break;
}
}
+#ifdef HAVE_GETADDRINFO
+ else
+ {
+ cur_acl->wildcard_dst = 1;
+ }
+#endif /* def HAVE_GETADDRINFO */
/*
* Add it to the list. Note we reverse the list to get the
{
cur_fwd->forward_host = strdup(p);
- if (NULL != (p = strchr(cur_fwd->forward_host, ':')))
+ if (*cur_fwd->forward_host == '[' &&
+ NULL != (p = strchr(cur_fwd->forward_host, ']')))
+ {
+ *p++ = '\0';
+ memmove(cur_fwd->forward_host, cur_fwd->forward_host + 1,
+ (size_t) (p - cur_fwd->forward_host));
+ if (*p == ':')
+ {
+ cur_fwd->forward_port = atoi(++p);
+ }
+ }
+ else if (NULL != (p = strchr(cur_fwd->forward_host, ':')))
{
*p++ = '\0';
cur_fwd->forward_port = atoi(p);
{
cur_fwd->gateway_host = strdup(p);
- if (NULL != (p = strchr(cur_fwd->gateway_host, ':')))
+ if (*cur_fwd->gateway_host == '[' &&
+ NULL != (p = strchr(cur_fwd->gateway_host, ']')))
+ {
+ *p++ = '\0';
+ memmove(cur_fwd->gateway_host, cur_fwd->gateway_host + 1,
+ (size_t) (p - cur_fwd->gateway_host));
+ if (*p == ':')
+ {
+ cur_fwd->gateway_port = atoi(++p);
+ }
+ }
+ else if (NULL != (p = strchr(cur_fwd->gateway_host, ':')))
{
*p++ = '\0';
cur_fwd->gateway_port = atoi(p);
}
+
if (cur_fwd->gateway_port <= 0)
{
cur_fwd->gateway_port = 1080;
{
cur_fwd->forward_host = strdup(p);
- if (NULL != (p = strchr(cur_fwd->forward_host, ':')))
+ if (*cur_fwd->forward_host == '[' &&
+ NULL != (p = strchr(cur_fwd->forward_host, ']')))
+ {
+ *p++ = '\0';
+ memmove(cur_fwd->forward_host, cur_fwd->forward_host + 1,
+ (size_t) (p - cur_fwd->forward_host));
+ if (*p == ':')
+ {
+ cur_fwd->forward_port = atoi(++p);
+ }
+ }
+ else if (NULL != (p = strchr(cur_fwd->forward_host, ':')))
{
*p++ = '\0';
cur_fwd->forward_port = atoi(p);
cur_fwd->gateway_host = strdup(p);
- if (NULL != (p = strchr(cur_fwd->gateway_host, ':')))
+ if (*cur_fwd->gateway_host == '[' &&
+ NULL != (p = strchr(cur_fwd->gateway_host, ']')))
+ {
+ *p++ = '\0';
+ memmove(cur_fwd->gateway_host, cur_fwd->gateway_host + 1,
+ (size_t) (p - cur_fwd->gateway_host));
+ if (*p == ':')
+ {
+ cur_fwd->gateway_port = atoi(++p);
+ }
+ }
+ else if (NULL != (p = strchr(cur_fwd->gateway_host, ':')))
{
*p++ = '\0';
cur_fwd->gateway_port = atoi(p);
}
+
if (cur_fwd->gateway_port <= 0)
{
cur_fwd->gateway_port = 1080;
{
cur_fwd->forward_host = strdup(p);
- if (NULL != (p = strchr(cur_fwd->forward_host, ':')))
+ if (*cur_fwd->forward_host == '[' &&
+ NULL != (p = strchr(cur_fwd->forward_host, ']')))
+ {
+ *p++ = '\0';
+ memmove(cur_fwd->forward_host, cur_fwd->forward_host + 1,
+ (size_t) (p - cur_fwd->forward_host));
+ if (*p == ':')
+ {
+ cur_fwd->forward_port = atoi(++p);
+ }
+ }
+ else if (NULL != (p = strchr(cur_fwd->forward_host, ':')))
{
*p++ = '\0';
cur_fwd->forward_port = atoi(p);
break;
}
}
+#ifdef HAVE_GETADDRINFO
+ else
+ {
+ cur_acl->wildcard_dst = 1;
+ }
+#endif /* def HAVE_GETADDRINFO */
/*
* Add it to the list. Note we reverse the list to get the
if ( NULL != config->haddr )
{
- if (NULL != (p = strchr(config->haddr, ':')))
+ if (*config->haddr == '[' && NULL != (p = strchr(config->haddr, ']')) &&
+ p[1] == ':' && 0 < (config->hport = atoi(p + 2)))
{
- *p++ = '\0';
- if (*p)
- {
- config->hport = atoi(p);
- }
+ *p='\0';
+ memmove((void *) config->haddr, config->haddr + 1,
+ (size_t) (p - config->haddr));
}
-
- if (config->hport <= 0)
+ else if (NULL != (p = strchr(config->haddr, ':')) &&
+ 0 < (config->hport = atoi(p + 1)))
+ {
+ *p = '\0';
+ }
+ else
{
- *--p = ':';
log_error(LOG_LEVEL_FATAL, "invalid bind port spec %s", config->haddr);
/* Never get here - LOG_LEVEL_FATAL causes program exit */
}
Local Variables:
tab-width: 3
end:
+
+ vim:softtabstop=3 shiftwidth=3
*/
#ifndef PROJECT_H_INCLUDED
#define PROJECT_H_INCLUDED
/** Version string. */
-#define PROJECT_H_VERSION "$Id: project.h,v 1.128 2009/03/07 13:09:17 fabiankeil Exp $"
+#define PROJECT_H_VERSION "$Id: project.h,v 1.129 2009/03/08 14:12:51 fabiankeil Exp $"
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/project.h,v $
*
* Revisions :
* $Log: project.h,v $
+ * Revision 1.129 2009/03/08 14:12:51 fabiankeil
+ * All the CSP_FLAG_FOO bit masks should be unsigned ints.
+ *
* Revision 1.128 2009/03/07 13:09:17 fabiankeil
* Change csp->expected_content and_csp->expected_content_length from
* size_t to unsigned long long to reduce the likelihood of integer
/* Needed for pcre choice */
#include "config.h"
+#ifdef HAVE_GETADDRINFO
+/* Need for struct sockaddr_storage */
+#include <sys/socket.h>
+#endif
+
+
/*
* Include appropriate regular expression libraries.
* Note that pcrs and pcre (native) are needed for cgi
#define FOREVER 1
/**
- * Default IP address to listen on, as a string.
- * Set to "127.0.0.1".
+ * Default TCP/IP address to listen on, as a string.
+ * Set to "127.0.0.1:8118".
*/
-#define HADDR_DEFAULT "127.0.0.1"
-
-/**
- * Default port to listen on, as a number.
- * Set to 8118.
- */
-#define HADDR_PORT 8118
+#define HADDR_DEFAULT "127.0.0.1:8118"
/* Forward def for struct client_state */
/** Client PC's IP address, as reported by the accept() function.
As a string. */
char *ip_addr_str;
+#ifdef HAVE_GETADDRINFO
+ /** Client PC's TCP address, as reported by the accept() function.
+ As a sockaddr. */
+ struct sockaddr_storage tcp_addr;
+#else
/** Client PC's IP address, as reported by the accept() function.
As a number. */
unsigned long ip_addr_long;
+#endif /* def HAVE_GETADDRINFO */
/** The URL that was requested */
struct http_request http[1];
*/
struct access_control_addr
{
+#ifdef HAVE_GETADDRINFO
+ struct sockaddr_storage addr; /* <The TCP address in network order. */
+ struct sockaddr_storage mask; /* <The TCP mask in network order. */
+#else
unsigned long addr; /**< The IP address as an integer. */
unsigned long mask; /**< The network mask as an integer. */
unsigned long port; /**< The port number. */
+#endif /* HAVE_GETADDRINFO */
};
/**
{
struct access_control_addr src[1]; /**< Client IP address */
struct access_control_addr dst[1]; /**< Website or parent proxy IP address */
+#ifdef HAVE_GETADDRINFO
+ int wildcard_dst; /** < dst address is wildcard */
+#endif
short action; /**< ACL_PERMIT or ACL_DENY */
struct access_control_list *next; /**< The next entry in the ACL. */
Local Variables:
tab-width: 3
end:
+
+ vim:softtabstop=3 shiftwidth=3
*/
-const char urlmatch_rcs[] = "$Id: urlmatch.c,v 1.46 2009/02/11 19:31:32 fabiankeil Exp $";
+const char urlmatch_rcs[] = "$Id: urlmatch.c,v 1.47 2009/03/02 19:18:10 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/urlmatch.c,v $
*
* Revisions :
* $Log: urlmatch.c,v $
+ * Revision 1.47 2009/03/02 19:18:10 fabiankeil
+ * Streamline parse_http_request()'s prototype. As
+ * cparser pointed out it doesn't actually use csp.
+ *
* Revision 1.46 2009/02/11 19:31:32 fabiankeil
* Reject request lines that end with neither HTTP/1.0 nor HTTP/1.1.
*
host = buf;
}
+ /* Move after hostname before port number */
+ if (*host == '[')
+ {
+ /* Numeric IPv6 address delimited by brackets */
+ host++;
+ port = strchr(host, ']');
+
+ if (port == NULL)
+ {
+ /* Missing closing bracket */
+ freez(buf);
+ return JB_ERR_PARSE;
+ }
+
+ *port++='\0';
+
+ if (*port == '\0')
+ {
+ port = NULL;
+ }
+ else if (*port != ':')
+ {
+ /* Garbage after closing bracket */
+ freez(buf);
+ return JB_ERR_PARSE;
+ }
+ }
+ else
+ {
+ /* Plain non-escaped hostname */
+ port = strchr(host, ':');
+ }
+
/* check if url contains port */
- port = strchr(host, ':');
if (port != NULL)
{
/* Contains port */
*p = '\0';
}
- p = strchr(buf, ':');
+ /* XXX: IPv6 numeric hostname contains colons, thus we need to delimit the
+ * hostname before real port separator. Because brackets are used in
+ * hostname matching on lower layer, we can't use it. I decided to use
+ * angle brackets '<' '>' instead. */
+ if (buf[0] == '<' && NULL != (p = strchr(buf + 1, '>')))
+ {
+ *p++ = '\0';
+ buf++;
+
+ if (*p == '\0')
+ {
+ /* Only IPv6 address without port number */
+ p = NULL;
+ }
+ else if (*p != ':')
+ {
+ /* Garbage after address delimiter */
+ return JB_ERR_PARSE;
+ }
+ }
+ else
+ {
+ p = strchr(buf, ':');
+ }
+
if (NULL != p)
{
*p++ = '\0';
Local Variables:
tab-width: 3
end:
+
+ vim:softtabstop=3 shiftwidth=3
*/