You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by Dean Gaudet <dg...@hyperreal.org> on 1997/07/19 10:58:38 UTC
cvs commit: apache/src/modules/proxy mod_proxy.c mod_proxy.h proxy_ftp.c proxy_http.c proxy_util.c
dgaudet 97/07/19 01:58:37
Modified: htdocs/manual new_features_1_3.html
htdocs/manual/mod mod_proxy.html
src CHANGES
src/modules/proxy mod_proxy.c mod_proxy.h proxy_ftp.c
proxy_http.c proxy_util.c
Log:
NoProxy and ProxyDomain directives.
Submitted by: Martin Kraemer <Ma...@mch.sni.de>
Reviewed by: Dean Gaudet
Revision Changes Path
1.9 +4 -0 apache/htdocs/manual/new_features_1_3.html
Index: new_features_1_3.html
===================================================================
RCS file: /export/home/cvs/apache/htdocs/manual/new_features_1_3.html,v
retrieving revision 1.8
retrieving revision 1.9
diff -C3 -r1.8 -r1.9
*** new_features_1_3.html 1997/07/18 21:01:31 1.8
--- new_features_1_3.html 1997/07/19 08:58:31 1.9
***************
*** 105,110 ****
--- 105,114 ----
before any requests are handled. This allows the module to set up
anything that need to be done once per processes. For example,
connections to databases.
+
+ <li><strong><a href="mod/mod_proxy.html#noproxy">NoProxy</a></strong>
+ and <strong><a href="mod/mod_proxy.html#proxydomain">ProxyDomain</a>
+ </strong> directives added to proxy, useful for intranets.
</ul>
1.26 +148 -0 apache/htdocs/manual/mod/mod_proxy.html
Index: mod_proxy.html
===================================================================
RCS file: /export/home/cvs/apache/htdocs/manual/mod/mod_proxy.html,v
retrieving revision 1.25
retrieving revision 1.26
diff -C3 -r1.25 -r1.26
*** mod_proxy.html 1997/07/06 17:19:18 1.25
--- mod_proxy.html 1997/07/19 08:58:32 1.26
***************
*** 42,47 ****
--- 42,49 ----
<li><a href="#proxyremote">ProxyRemote</a>
<li><a href="#proxypass">ProxyPass</a>
<li><a href="#proxyblock">ProxyBlock</a>
+ <li><a href="#noproxy">NoProxy</a>
+ <li><a href="#proxydomain">ProxyDomain</a>
<li><a href="#cacheroot">CacheRoot</a>
<li><a href="#cachesize">CacheSize</a>
<li><a href="#cachemaxexpire">CacheMaxExpire</a>
***************
*** 150,155 ****
--- 152,284 ----
blocks connections to all sites.
+ <A name="noproxy"><h2>NoProxy</h2></A>
+ <strong>Syntax:</strong> NoProxy { <A HREF="#domain"><em><Domain></em></A>
+ | <A HREF="#subnet"><em><SubNet></em></A>
+ | <A HREF="#ipaddr"><em><IpAddr></em></A>
+ | <A HREF="#hostname"><em><Hostname></em></A>
+ } <br>
+ <strong>Context:</strong> server config<br>
+ <strong>Status:</strong> Base<br>
+ <strong>Module:</strong> mod_proxy<br>
+ <strong>Compatibility:</strong> NoProxy is only available in a patch to
+ Apache 1.2.1 and later.<p>
+
+ This directive is only useful for apache proxy servers within intranets.
+ The NoProxy directive specifies a list of subnets, IP addresses, hosts
+ and/or domains, separated by spaces. A request to a host which matches
+ one or more of these is always served directly, without forwarding to
+ the configured ProxyRemote proxy server(s).<br>Example:
+
+ <pre>
+ ProxyRemote * http://firewall.mycompany.com:81
+ NoProxy .mycompany.com 192.168.112.0/21
+ </pre>
+ The arguments to the NoProxy directive are one of the following type list:
+ <DL>
+ <!-- ===================== Domain ======================= -->
+ <A NAME="domain">
+ <DT><EM>Domain</EM>
+ <DD>A <EM>Domain</EM> is a partially qualified DNS domain name, preceded
+ by a period.
+ It represents a list of hosts which logically belong to the same DNS
+ domain or zone (i.e. the suffixes of the hostnames are all ending in
+ <EM>Domain</EM>).<BR>
+ Examples: <SAMP>.com</SAMP> <SAMP>.apache.org.</SAMP> <SAMP>.sni.de</SAMP><BR>
+ To distinguish <EM>Domain</EM>s from <A HREF="#hostname"><EM>Hostname</EM></A>s (both
+ syntactically and semantically; a DNS domain can have a DNS A record,
+ too!), <EM>Domain</EM>s are always written
+ with a leading period.<BR>
+ Note: Domain name comparisons are done without regard to the case,
+ and <EM>Domain</EM>s are always assumed to be anchored in the root
+ of the DNS tree, therefore two domains <SAMP>.MyDomain.com</SAMP> and
+ <SAMP>.mydomain.com.</SAMP> (note the trailing period) are
+ considered equal. Since a domain comparison does not involve a DNS
+ lookup, it is much more efficient than subnet comparison.
+
+ <!-- ===================== SubNet ======================= -->
+ <A NAME="subnet">
+ <DT><EM>SubNet</EM>
+ <DD>A <EM>SubNet</EM> is a partially qualified internet address in
+ numeric (dotted quad) form, optionally followed by a slash and the
+ netmask, specified as the number of significant bits in the
+ <EM>SubNet</EM>. It is used to represent a subnet of hosts which can
+ be reached over a common network interface. In the absence of the
+ explicit net mask it is assumed that omitted (or zero valued)
+ trailing digits specify the mask. (In this case, the netmask can
+ only be multiples of 8 bits wide.)<BR>
+ Examples:
+ <DL>
+ <DT><SAMP>192.168</SAMP> or <SAMP>192.168.0.0</SAMP>
+ <DD>the subnet 192.168.0.0 with a netmask of 16 valid bits
+ (sometimes used in the netmask form <SAMP>255.255.0.0</SAMP>)
+ <DT><SAMP>139.25.112.0/21</SAMP>
+ <DD>the subnet <SAMP>139.25.112.0/21</SAMP> with a netmask of 21
+ valid bits (also used in the form 255.255.248.0)
+ </DL>
+ As a degenerate case, a <EM>SubNet</EM> with 32 valid bits is the
+ equivalent to an <EM>IPAddr</EM>, while a <EM>SubNet</EM> with zero
+ valid bits (e.g., 0.0.0.0/0) is the same as the constant
+ <EM>_Default_</EM>, matching any IP address.
+
+ <!-- ===================== IPAddr ======================= -->
+ <A NAME="ipaddr">
+ <DT><EM>IPAddr</EM>
+ <DD>A <EM>IPAddr</EM> represents a fully qualified internet address in
+ numeric (dotted quad) form. Usually, this address represents a
+ host, but there need not necessarily be a DNS domain name
+ connected with the address.<BR>
+ Example: 139.25.113.10<BR>
+ Note: An <EM>IPAddr</EM> does not need to be resolved by the DNS system, so
+ it can result in more effective apache performance.<BR>
+ <p><strong>See Also:</strong>
+ <a href="../dns-caveats.html">DNS Issues</a></p>
+
+ <!-- ===================== Hostname ======================= -->
+ <A NAME="hostname">
+ <DT><EM>Hostname</EM>
+ <DD>A <EM>Hostname</EM> is a fully qualified DNS domain name which can
+ be resolved to one or more <A HREF="#ipaddr"><EM>IPAddrs</EM></A> via the DNS domain name service.
+ It represents a logical host (in contrast to <A HREF="#domain"><EM>Domain</EM></A>s, see
+ above) and must be resolvable to at least one <A HREF="#ipaddr"><EM>IPAddr</EM></A> (or
+ often to a list of hosts with different <A HREF="#ipaddr"><EM>IPAddr</EM></A>'s).<BR>
+ Examples: <SAMP>prep.ai.mit.edu</SAMP>
+ <SAMP>www.apache.org.</SAMP><BR>
+ Note: In many situations, it is more effective to specify an
+ <A HREF="#ipaddr"><EM>IPAddr</EM></A> in place of a <EM>Hostname</EM> since a DNS lookup
+ can be avoided. Name resolution in Apache can take a remarkable deal
+ of time when the connection to the name server uses a slow PPP
+ link.<BR>
+ Note: <EM>Hostname</EM> comparisons are done without regard to the case,
+ and <EM>Hostname</EM>s are always assumed to be anchored in the root
+ of the DNS tree, therefore two hosts <SAMP>WWW.MyDomain.com</SAMP>
+ and <SAMP>www.mydomain.com.</SAMP> (note the trailing period) are
+ considered equal.<BR>
+ <p><strong>See Also:</strong>
+ <a href="../dns-caveats.html">DNS Issues</a></p>
+ </DL>
+
+ <A name="proxydomain"><h2>ProxyDomain</h2></A>
+ <strong>Syntax:</strong> ProxyDomain <em><Domain></em><br>
+ <strong>Context:</strong> server config<br>
+ <strong>Status:</strong> Base<br>
+ <strong>Module:</strong> mod_proxy<br>
+ <strong>Compatibility:</strong> ProxyDomain is only available in a patch to
+ Apache 1.2.1 and later.<p>
+
+ This directive is only useful for apache proxy servers within intranets.
+ The ProxyDomain directive specifies the default domain which the apache
+ proxy server will belong to. If a request to a host without a domain name
+ is encountered, a redirection response to the same host
+ with the configured <em>Domain</em> appended will be generated.
+ <br>Example:
+
+ <pre>
+ ProxyRemote * http://firewall.mycompany.com:81
+ NoProxy .mycompany.com 192.168.112.0/21
+ ProxyDomain .mycompany.com
+ </pre>
+
<A name="cacheroot"><h2>CacheRoot</h2></A>
<strong>Syntax:</strong> CacheRoot <em><directory></em><br>
<strong>Context:</strong> server config<br>
***************
*** 299,304 ****
--- 428,434 ----
<li><a href="#startup">Why does Apache start more slowly when using the
proxy module?</a>
<li><a href="#socks">Can I use the Apache proxy module with my SOCKS proxy?</a>
+ <li><a href="#intranet">What other functions are useful for an intranet proxy server?</a>
</ul>
<h2><a name="access">Controlling access to your proxy</a></h2>
***************
*** 359,364 ****
--- 489,512 ----
Remember that you'll also have to grant access to your Apache proxy machine by
permitting connections on the appropriate ports in your SOCKS daemon's
configuration.<p>
+
+ <h2><a name="intranet">What other functions are useful for an intranet proxy server?</a></h2>
+
+ <p>An Apache proxy server situated in an intranet needs to forward external
+ requests through the company's firewall. However, when it has to access
+ resources within the intranet, it can bypass the firewall when accessing
+ hosts. The <A HREF="#noproxy">NoProxy</A> directive is useful for specifying
+ which hosts belong to the intranet and should be accessed directly.</p>
+
+ <p>Users within an intranet tend to omit the local domain name from their
+ WWW requests, thus requesting "http://somehost/" instead of
+ "http://somehost.my.dom.ain/". Some commercial proxy servers let them get
+ away with this and simply serve the request, implying a configured
+ local domain. When the <A HREF="#proxydomain">ProxyDomain</A> directive
+ is used and the server is <A HREF="#proxyrequests">configured for
+ proxy service</A>, Apache can return a redirect response and send the client
+ to the correct, fully qualified, server address. This is the preferred method
+ since the user's bookmark files will then contain fully qualified hosts.</p>
<!--#include virtual="footer.html" -->
</BODY>
1.346 +5 -0 apache/src/CHANGES
Index: CHANGES
===================================================================
RCS file: /export/home/cvs/apache/src/CHANGES,v
retrieving revision 1.345
retrieving revision 1.346
diff -C3 -r1.345 -r1.346
*** CHANGES 1997/07/19 06:20:42 1.345
--- CHANGES 1997/07/19 08:58:33 1.346
***************
*** 1,5 ****
--- 1,10 ----
Changes with Apache 1.3
+ *) Added NoProxy directive to avoid using ProxyRemote for selected
+ addresses. Added ProxyDomain directive to cause unqualified
+ names to be qualified by redirection.
+ [Martin Kraemer <Ma...@mch.sni.de>]
+
*) Support Proxy Authentication, and don't pass the Proxy-Authorize
header to the remote host in the proxy. [Sameer Parekh and
Wallace]
1.16 +182 -1 apache/src/modules/proxy/mod_proxy.c
Index: mod_proxy.c
===================================================================
RCS file: /export/home/cvs/apache/src/modules/proxy/mod_proxy.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -C3 -r1.15 -r1.16
*** mod_proxy.c 1997/07/17 22:28:01 1.15
--- mod_proxy.c 1997/07/19 08:58:34 1.16
***************
*** 51,56 ****
--- 51,57 ----
*/
#include "mod_proxy.h"
+ #include "http_log.h"
/* Some WWW schemes and their default ports; this is basically /etc/services */
/* This will become global when the protocol abstraction comes */
***************
*** 186,191 ****
--- 187,262 ----
}
+
+ /* Send a redirection if the request contains a hostname which is not */
+ /* fully qualified, i.e. doesn't have a domain name appended. Some proxy */
+ /* servers like Netscape's allow this and access hosts from the local */
+ /* domain in this case. I think it is better to redirect to a FQDN, since */
+ /* these will later be found in the bookmarks files. */
+ /* The "ProxyDomain" directive determines what domain will be appended */
+ int
+ proxy_needsdomain(request_rec *r, const char *url, const char *domain)
+ {
+ char *scheme = pstrdup (r->pool, url);
+ char *url_copy, *user = NULL, *password = NULL, *path, *err, *host;
+ int port = -1;
+
+ /* We only want to worry about GETs */
+ if (r->method_number != M_GET) return DECLINED;
+
+ /* Set url to the first char after "scheme://" */
+ if ((url_copy = strchr(scheme,':')) == NULL
+ || url_copy[1] != '/' || url_copy[2] != '/')
+ return DECLINED;
+
+ *url_copy++ = '\0'; /* delimit scheme, make url_copy point to "//", which is what proxy_canon_netloc expects */
+
+ /* Save the path - it will be re-appended for the redirection later */
+ path = strchr(&url_copy[2], '/');
+ if (path != NULL)
+ ++path; /* leading '/' will be overwritten by proxy_canon_netloc */
+ else
+ path = "";
+
+ /* Split request into user, password, host, port */
+ err = proxy_canon_netloc(r->pool, &url_copy, &user, &password, &host, &port);
+
+ if (err != NULL)
+ {
+ log_error(err, r->server);
+ return DECLINED;
+ }
+
+ /* If host does contain a dot already, or it is "localhost", decline */
+ if (strchr (host, '.') != NULL || strcasecmp(host, "localhost") == 0)
+ return DECLINED; /* host name has a dot already */
+ else
+ {
+ char *nuri;
+ char *ref = table_get(r->headers_in, "Referer");
+ char strport[10];
+
+ /* now, rebuild URL */
+ if (port == -1)
+ strcpy (strport, "");
+ else
+ ap_snprintf(strport, sizeof(strport), ":%d", port);
+
+ /* Reassemble the request, but insert the domain after the host name */
+ nuri = pstrcat(r->pool, scheme, "://", (user != NULL) ? user : "",
+ (password != NULL) ? ":" : "",
+ (password != NULL) ? password : "",
+ (user != NULL) ? "@" : "",
+ host, domain, strport, "/", path,
+ NULL);
+
+ table_set(r->headers_out, "Location", nuri);
+ log_error(pstrcat(r->pool, "Domain missing: ", r->uri, " sent to ", nuri,
+ ref ? " from " : NULL, ref, NULL), r->server);
+ return REDIRECT;
+ }
+ }
+
/* -------------------------------------------------------------- */
/* Invoke handler */
***************
*** 200,205 ****
--- 271,277 ----
struct proxy_remote *ents=(struct proxy_remote *)proxies->elts;
int i, rc;
struct cache_req *cr;
+ int direct_connect = 0;
if (strncmp(r->filename, "proxy:", 6) != 0) return DECLINED;
***************
*** 213,224 ****
rc = proxy_cache_check(r, url, &conf->cache, &cr);
if (rc != DECLINED) return rc;
*p = '\0';
scheme = pstrdup(r->pool, url);
*p = ':';
! /* firstly, try a proxy */
for (i=0; i < proxies->nelts; i++)
{
p = strchr(ents[i].scheme, ':'); /* is it a partial URL? */
--- 285,328 ----
rc = proxy_cache_check(r, url, &conf->cache, &cr);
if (rc != DECLINED) return rc;
+ /* If the host doesn't have a domain name, add one and redirect. */
+ if (conf->domain != NULL
+ && proxy_needsdomain(r, url, conf->domain) == REDIRECT)
+ return REDIRECT;
+
*p = '\0';
scheme = pstrdup(r->pool, url);
*p = ':';
! /* Check URI's destination host against NoProxy hosts */
! /* Bypass ProxyRemote server lookup if configured as NoProxy */
! /* we only know how to handle communication to a proxy via http */
! /*if (strcmp(scheme, "http") == 0)*/
! {
! int i;
! struct dirconn_entry *list=(struct dirconn_entry*)conf->dirconn->elts;
!
! /* if (*++p == '/' && *++p == '/') */
!
! for (direct_connect=i=0; i < conf->dirconn->nelts && !direct_connect; i++)
! {
! direct_connect = list[i].matcher (&list[i], r);
! /*log_error("URI and NoProxy:", r->server);*/
! /*log_error(r->uri, r->server);*/
! /*log_error(list[i].name, r->server);*/
! }
! #if DEBUGGING
! {
! char msg[256];
! sprintf (msg, (direct_connect)?"NoProxy for %s":"UseProxy for %s", r->uri);
! log_error(msg, r->server);
! }
! #endif
! }
!
! /* firstly, try a proxy, unless a NoProxy directive is active */
+ if (!direct_connect)
for (i=0; i < proxies->nelts; i++)
{
p = strchr(ents[i].scheme, ':'); /* is it a partial URL? */
***************
*** 264,270 ****
--- 368,376 ----
ps->proxies = make_array(p, 10, sizeof(struct proxy_remote));
ps->aliases = make_array(p, 10, sizeof(struct proxy_alias));
ps->noproxies = make_array(p, 10, sizeof(struct noproxy_entry));
+ ps->dirconn = make_array(p, 10, sizeof(struct dirconn_entry));
ps->nocaches = make_array(p, 10, sizeof(struct nocache_entry));
+ ps->domain = NULL;
ps->req = 0;
ps->cache.root = NULL;
***************
*** 366,371 ****
--- 472,548 ----
return NULL;
}
+ /* Similar to set_proxy_exclude(), but defining directly connected hosts,
+ * which should never be accessed via the configured ProxyRemote servers
+ */
+ static const char *
+ set_proxy_dirconn(cmd_parms *parms, void *dummy, char *arg)
+ {
+ server_rec *s = parms->server;
+ proxy_server_conf *conf =
+ get_module_config (s->module_config, &proxy_module);
+ struct dirconn_entry *New;
+ struct dirconn_entry *list=(struct dirconn_entry*)conf->dirconn->elts;
+ int found = 0;
+ int i;
+
+ /* Don't duplicate entries */
+ for (i=0; i < conf->dirconn->nelts; i++)
+ {
+ if (strcasecmp(arg, list[i].name) == 0)
+ found = 1;
+ }
+
+ if (!found)
+ {
+ New = push_array (conf->dirconn);
+ New->name = arg;
+
+ if (proxy_is_ipaddr(New))
+ {
+ #if DEBUGGING
+ fprintf(stderr,"Parsed addr %s\n", inet_ntoa(New->addr));
+ fprintf(stderr,"Parsed mask %s\n", inet_ntoa(New->mask));
+ #endif
+ }
+ else if (proxy_is_domainname(New))
+ {
+ str_tolower(New->name);
+ #if DEBUGGING
+ fprintf(stderr,"Parsed domain %s\n", New->name);
+ #endif
+ }
+ else if (proxy_is_hostname(New))
+ {
+ str_tolower(New->name);
+ #if DEBUGGING
+ fprintf(stderr,"Parsed host %s\n", New->name);
+ #endif
+ }
+ else
+ {
+ proxy_is_word(New);
+ #if DEBUGGING
+ fprintf(stderr,"Parsed word %s\n", New->name);
+ #endif
+ }
+ }
+ return NULL;
+ }
+
+ static const char *
+ set_proxy_domain(cmd_parms *parms, void *dummy, char *arg)
+ {
+ proxy_server_conf *psf =
+ get_module_config (parms->server->module_config, &proxy_module);
+
+ if (arg[0] != '.')
+ return "Domain name must start with a dot.";
+
+ psf->domain = arg;
+ return NULL;
+ }
+
static const char *
set_proxy_req(cmd_parms *parms, void *dummy, int flag)
{
***************
*** 519,524 ****
--- 696,705 ----
"a virtual path and a URL"},
{ "ProxyBlock", set_proxy_exclude, NULL, RSRC_CONF, ITERATE,
"A list of names, hosts or domains to which the proxy will not connect" },
+ { "NoProxy", set_proxy_dirconn, NULL, RSRC_CONF, ITERATE,
+ "A list of domains, hosts, or subnets to which the proxy will connect directly" },
+ { "ProxyDomain", set_proxy_domain, NULL, RSRC_CONF, TAKE1,
+ "The default intranet domain name (in absence of a domain in the URL)" },
{ "CacheRoot", set_cache_root, NULL, RSRC_CONF, TAKE1,
"The directory to store cache files"},
{ "CacheSize", set_cache_size, NULL, RSRC_CONF, TAKE1,
1.13 +13 -0 apache/src/modules/proxy/mod_proxy.h
Index: mod_proxy.h
===================================================================
RCS file: /export/home/cvs/apache/src/modules/proxy/mod_proxy.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -C3 -r1.12 -r1.13
*** mod_proxy.h 1997/06/15 19:22:47 1.12
--- mod_proxy.h 1997/07/19 08:58:35 1.13
***************
*** 151,156 ****
--- 151,163 ----
char *fake;
};
+ struct dirconn_entry {
+ char *name;
+ struct in_addr addr,mask;
+ struct hostent hostlist;
+ int (*matcher)(struct dirconn_entry *This, request_rec *r);
+ };
+
struct noproxy_entry {
char *name;
struct in_addr addr;
***************
*** 185,191 ****
--- 192,200 ----
array_header *proxies;
array_header *aliases;
array_header *noproxies;
+ array_header *dirconn;
array_header *nocaches;
+ char *domain; /* domain name to use in absence of a domain name in the request */
int req; /* true if proxy requests are enabled */
} proxy_server_conf;
***************
*** 269,274 ****
--- 278,287 ----
BUFF *proxy_cache_error(struct cache_req *r);
int proxyerror(request_rec *r, const char *message);
const char *proxy_host2addr(const char *host, struct hostent *reqhp);
+ int proxy_is_ipaddr(struct dirconn_entry *This);
+ int proxy_is_domainname(struct dirconn_entry *This);
+ int proxy_is_hostname(struct dirconn_entry *This);
+ int proxy_is_word(struct dirconn_entry *This);
int proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r);
int proxy_garbage_init(server_rec *, pool *);
1.24 +12 -0 apache/src/modules/proxy/proxy_ftp.c
Index: proxy_ftp.c
===================================================================
RCS file: /export/home/cvs/apache/src/modules/proxy/proxy_ftp.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -C3 -r1.23 -r1.24
*** proxy_ftp.c 1997/06/16 19:32:53 1.23
--- proxy_ftp.c 1997/07/19 08:58:35 1.24
***************
*** 508,513 ****
--- 508,524 ----
return SERVER_ERROR;
}
+ #ifdef SINIX_D_RESOLVER_BUG
+ { struct in_addr *ip_addr = (struct in_addr *) *server_hp.h_addr_list;
+
+ for ( ; ip_addr->s_addr != 0; ++ip_addr) {
+ memcpy(&server.sin_addr, ip_addr, sizeof(struct in_addr));
+ i = proxy_doconnect(sock, &server, r);
+ if (i == 0)
+ break;
+ }
+ }
+ #else
j = 0;
while (server_hp.h_addr_list[j] != NULL) {
memcpy(&server.sin_addr, server_hp.h_addr_list[j],
***************
*** 517,522 ****
--- 528,534 ----
break;
j++;
}
+ #endif
if (i == -1)
return proxyerror(r, "Could not connect to remote machine");
1.22 +12 -0 apache/src/modules/proxy/proxy_http.c
Index: proxy_http.c
===================================================================
RCS file: /export/home/cvs/apache/src/modules/proxy/proxy_http.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -C3 -r1.21 -r1.22
*** proxy_http.c 1997/07/19 06:20:49 1.21
--- proxy_http.c 1997/07/19 08:58:35 1.22
***************
*** 227,232 ****
--- 227,243 ----
note_cleanups_for_socket(pool, sock);
+ #ifdef SINIX_D_RESOLVER_BUG
+ { struct in_addr *ip_addr = (struct in_addr *) *server_hp.h_addr_list;
+
+ for ( ; ip_addr->s_addr != 0; ++ip_addr) {
+ memcpy(&server.sin_addr, ip_addr, sizeof(struct in_addr));
+ i = proxy_doconnect(sock, &server, r);
+ if (i == 0)
+ break;
+ }
+ }
+ #else
j = 0;
while (server_hp.h_addr_list[j] != NULL) {
memcpy(&server.sin_addr, server_hp.h_addr_list[j],
***************
*** 236,241 ****
--- 247,253 ----
break;
j++;
}
+ #endif
if (i == -1)
{
if (proxyhost != NULL) return DECLINED; /* try again another way */
1.20 +357 -0 apache/src/modules/proxy/proxy_util.c
Index: proxy_util.c
===================================================================
RCS file: /export/home/cvs/apache/src/modules/proxy/proxy_util.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -C3 -r1.19 -r1.20
*** proxy_util.c 1997/06/16 15:16:28 1.19
--- proxy_util.c 1997/07/19 08:58:35 1.20
***************
*** 56,61 ****
--- 56,67 ----
#include "http_main.h"
#include "md5.h"
#include "multithread.h"
+ #include "http_log.h"
+
+ static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r);
+ static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r);
+ static int proxy_match_hostname(struct dirconn_entry *This, request_rec *r);
+ static int proxy_match_word(struct dirconn_entry *This, request_rec *r);
/* already called in the knowledge that the characters are hex digits */
int
***************
*** 245,250 ****
--- 251,259 ----
return "Bad IP address in URL";
}
+ /* if (strchr(host,'.') == NULL && domain != NULL)
+ host = pstrcat(pool, host, domain, NULL);
+ */
*urlp = url;
*hostp = host;
***************
*** 796,801 ****
--- 805,1158 ----
}
memcpy(reqhp, hp, sizeof(struct hostent));
return NULL;
+ }
+
+ char *
+ proxy_get_host_of_request(request_rec *r)
+ {
+ char *url, *user = NULL, *password = NULL, *err, *host;
+ int port = -1;
+
+ if (r->hostname != NULL)
+ return r->hostname;
+
+ /* Set url to the first char after "scheme://" */
+ if ((url = strchr(r->uri,':')) == NULL
+ || url[1] != '/' || url[2] != '/')
+ return NULL;
+
+ url = pstrdup(r->pool, &url[1]); /* make it point to "//", which is what proxy_canon_netloc expects */
+
+ err = proxy_canon_netloc(r->pool, &url, &user, &password, &host, &port);
+
+ if (err != NULL)
+ log_error(err, r->server);
+
+ r->hostname = host;
+
+ return host; /* ought to return the port, too */
+ }
+
+ /* Return TRUE if addr represents an IP address (or an IP network address)*/
+ int
+ proxy_is_ipaddr(struct dirconn_entry *This)
+ {
+ const char *addr = This->name;
+ unsigned long ip_addr[4];
+ int i,quads;
+ unsigned long bits;
+
+ /* if the address is given with an explicit netmask, use that */
+ /* Due to a deficiency in inet_addr(), it is impossible to parse */
+ /* "partial" addresses (with less than 4 quads) correctly, i.e. */
+ /* 192.168.123 is parsed as 192.168.0.123, which is not what I want. */
+ /* I therefore have to parse the IP address manually: */
+ /*if (proxy_readmask(This->name, &This->addr.s_addr, &This->mask.s_addr) == 0)*/
+ /* addr and mask were set by proxy_readmask() */
+ /*return 1;*/
+
+ /* Parse IP addr manually, optionally allowing */
+ /* abbreviated net addresses like 192.168. */
+
+ /* quads = sscanf(what, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1],
+ &ip_addr[2], &ip_addr[3]);
+ commented out: use of strtok() allows arbitrary base, like in:
+ 139.25.113.10 == 0x8b.0x19.0x71.0x0a
+ (yes, inet_addr() can parse that, too!)
+ */
+
+ /* Iterate over up to 4 (dotted) quads. */
+ for (quads=0; quads<4 && *addr != '\0'; ++quads)
+ {
+ char *tmp;
+
+ if (*addr == '/' && quads > 0) /* netmask starts here. */
+ break;
+
+ if (!isdigit(*addr))
+ return 0; /* no digit at start of quad */
+
+ ip_addr[quads] = strtoul(addr, &tmp, 0);
+
+ if (tmp == addr) /* expected a digit, found something else */
+ return 0;
+
+ addr = tmp;
+
+ if (*addr == '.' && quads != 3)
+ ++addr; /* after the 4th quad, a dot would be illegal */
+ }
+
+ for (This->addr.s_addr = 0, i=0; i<quads; ++i)
+ This->addr.s_addr |= htonl(ip_addr[i] << (24 - 8*i));
+
+ if (addr[0] == '/' && isdigit(addr[1])) /* net mask follows: */
+ {
+ char *tmp;
+
+ ++addr;
+
+ bits = strtoul(addr, &tmp, 0);
+
+ if (tmp == addr) /* expected a digit, found something else */
+ return 0;
+
+ addr = tmp;
+
+ if (bits > 32) /* netmask must be between 0 and 32 */
+ return 0;
+
+ }
+ else
+ {
+ /* Determine (i.e., "guess") netmask by counting the */
+ /* number of trailing .0's; reduce #quads appropriately */
+ /* (so that 192.168.0.0 is equivalent to 192.168.) */
+ while (quads > 0 && ip_addr[quads-1] == 0)
+ --quads;
+
+ /* "IP Address should be given in dotted-quad form, optionally followed by a netmask (e.g., 192.168.111.0/24)"; */
+ if (quads < 1)
+ return 0;
+
+ /* every zero-byte counts as 8 zero-bits */
+ bits = 8*quads;
+
+ if (bits != 32) /* no warning for fully qualified IP address */
+ fprintf(stderr,"Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld\n",
+ inet_ntoa(This->addr), bits);
+ }
+
+ This->mask.s_addr = htonl(INADDR_NONE << (32 - bits));
+
+ if (*addr == '\0' && (This->addr.s_addr & ~This->mask.s_addr) != 0)
+ {
+ fprintf(stderr,"Warning: NetMask and IP-Addr disagree in %s/%ld\n",
+ inet_ntoa(This->addr), bits);
+ This->addr.s_addr &= This->mask.s_addr;
+ fprintf(stderr," Set to %s/%ld\n",
+ inet_ntoa(This->addr), bits);
+ }
+
+ if (*addr == '\0')
+ {
+ This->matcher = proxy_match_ipaddr;
+ return 1;
+ }
+ else
+ return (*addr == '\0'); /* okay iff we've parsed the whole string */
+ }
+
+ /* Return TRUE if addr represents an IP address (or an IP network address)*/
+ static int
+ proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r)
+ {
+ int i;
+ int ip_addr[4];
+ struct in_addr addr;
+ struct in_addr *ip_list;
+ const char *found;
+ const char *host = proxy_get_host_of_request(r);
+
+ memset (&addr, '\0', sizeof addr);
+ memset (ip_addr, '\0', sizeof ip_addr);
+
+ if ( 4 == sscanf(host, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1], &ip_addr[2], &ip_addr[3]))
+ {
+ for (addr.s_addr = 0, i=0; i<4; ++i)
+ addr.s_addr |= htonl(ip_addr[i] << (24 - 8*i));
+
+ if (This->addr.s_addr == (addr.s_addr & This->mask.s_addr))
+ {
+ #if DEBUGGING
+ fprintf(stderr,"1)IP-Match: %s[%s] <-> ", host, inet_ntoa(addr));
+ fprintf(stderr,"%s/", inet_ntoa(This->addr));
+ fprintf(stderr,"%s\n", inet_ntoa(This->mask));
+ #endif
+ return 1;
+ }
+ #if DEBUGGING
+ else
+ {
+ fprintf(stderr,"1)IP-NoMatch: %s[%s] <-> ", host, inet_ntoa(addr));
+ fprintf(stderr,"%s/", inet_ntoa(This->addr));
+ fprintf(stderr,"%s\n", inet_ntoa(This->mask));
+ }
+ #endif
+ }
+ else
+ {
+ struct hostent the_host;
+
+ memset (&the_host, '\0', sizeof the_host);
+ found = proxy_host2addr(host, &the_host);
+
+ if ( found != NULL )
+ {
+ #if DEBUGGING
+ fprintf(stderr,"2)IP-NoMatch: hostname=%s msg=%s\n", host, found);
+ #endif
+ return 0;
+ }
+
+ if (the_host.h_name != NULL)
+ found = the_host.h_name;
+ else
+ found = host;
+
+ /* Try to deal with multiple IP addr's for a host */
+ for (ip_list = (struct in_addr *) *the_host.h_addr_list; ip_list->s_addr != 0UL; ++ip_list)
+ if (This->addr.s_addr == (ip_list->s_addr & This->mask.s_addr))
+ {
+ #if DEBUGGING
+ fprintf(stderr,"3)IP-Match: %s[%s] <-> ", found, inet_ntoa(*ip_list));
+ fprintf(stderr,"%s/", inet_ntoa(This->addr));
+ fprintf(stderr,"%s\n", inet_ntoa(This->mask));
+ #endif
+ return 1;
+ }
+ #if DEBUGGING
+ else
+ {
+ fprintf(stderr,"3)IP-NoMatch: %s[%s] <-> ", found, inet_ntoa(*ip_list));
+ fprintf(stderr,"%s/", inet_ntoa(This->addr));
+ fprintf(stderr,"%s\n", inet_ntoa(This->mask));
+ }
+ #endif
+ }
+
+ /* Use net math to determine if a host lies in a subnet */
+ /*return This->addr.s_addr == (r->connection->remote_addr.sin_addr.s_addr & This->mask.s_addr);*/
+ return 0;
+ }
+
+ /* Return TRUE if addr represents a domain name */
+ int
+ proxy_is_domainname(struct dirconn_entry *This)
+ {
+ char *addr = This->name;
+ int i;
+
+ /* Domain name must start with a '.' */
+ if (addr[0] != '.')
+ return 0;
+
+ /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
+ for (i=0; isalnum(addr[i]) || addr[i]=='-' || addr[i]=='.'; ++i)
+ ;
+
+ if (addr[i] == ':')
+ {
+ fprintf(stderr,"@@@@ handle optional port in proxy_is_domainname()\n");
+ /* @@@@ handle optional port */
+ }
+
+ if (addr[i] != '\0')
+ return 0;
+
+ /* Strip trailing dots */
+ for (i=strlen(addr)-1; i>0 && addr[i] == '.'; --i)
+ addr[i] = '\0';
+
+ This->matcher = proxy_match_domainname;
+ return 1;
+ }
+
+ /* Return TRUE if host "host" is in domain "domain" */
+ static int
+ proxy_match_domainname(struct dirconn_entry *This, request_rec *r)
+ {
+ const char *host = proxy_get_host_of_request(r);
+ int d_len=strlen(This->name), h_len;
+
+ if (host == NULL) /* some error was logged already */
+ return 0;
+
+ h_len = strlen(host);
+
+ /* @@@ do this within the setup? */
+ /* Ignore trailing dots in domain comparison: */
+ while (d_len > 0 && This->name[d_len-1] == '.')
+ --d_len;
+ while (h_len > 0 && host[h_len-1] == '.')
+ --h_len;
+ return h_len > d_len
+ && strncasecmp(&host[h_len-d_len], This->name, d_len) == 0;
+ }
+
+ /* Return TRUE if addr represents a host name */
+ int
+ proxy_is_hostname(struct dirconn_entry *This)
+ {
+ char *addr = This->name;
+ int i;
+
+ /* Host names must not start with a '.' */
+ if (addr[0] == '.')
+ return 0;
+
+ /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
+ for (i=0; isalnum(addr[i]) || addr[i]=='-' || addr[i]=='.'; ++i)
+ ;
+
+ if (addr[i] == ':')
+ {
+ fprintf(stderr,"@@@@ handle optional port in proxy_is_hostname()\n");
+ /* @@@@ handle optional port */
+ }
+
+ if (addr[i] != '\0' || proxy_host2addr(addr, &This->hostlist) != NULL)
+ return 0;
+
+ /* Strip trailing dots */
+ for (i=strlen(addr)-1; i>0 && addr[i] == '.'; --i)
+ addr[i] = '\0';
+
+ This->matcher = proxy_match_hostname;
+ return 1;
+ }
+
+ /* Return TRUE if host "host" is equal to host2 "host2" */
+ static int
+ proxy_match_hostname(struct dirconn_entry *This, request_rec *r)
+ {
+ char *host = This->name;
+ char *host2 = proxy_get_host_of_request(r);
+ int h2_len=strlen(host2);
+ int h1_len=strlen(host);
+
+ #if 0
+ unsigned long *ip_list;
+
+ /* Try to deal with multiple IP addr's for a host */
+ for (ip_list = *This->hostlist.h_addr_list; *ip_list != 0UL; ++ip_list)
+ if (*ip_list == ?????????????)
+ return 1;
+ #endif
+
+ /* Ignore trailing dots in host2 comparison: */
+ while (h2_len > 0 && host2[h2_len-1] == '.')
+ --h2_len;
+ while (h1_len > 0 && host[h1_len-1] == '.')
+ --h1_len;
+ return h1_len == h2_len
+ && strncasecmp(host, host2, h1_len) == 0;
+ }
+
+ /* Return TRUE if addr is to be matched as a word */
+ int
+ proxy_is_word(struct dirconn_entry *This)
+ {
+ This->matcher = proxy_match_word;
+ return 1;
+ }
+
+ /* Return TRUE if string "str2" occurs literally in "str1" */
+ static int
+ proxy_match_word(struct dirconn_entry *This, request_rec *r)
+ {
+ char *host = proxy_get_host_of_request(r);
+ return host != NULL && strstr(host, This->name) != NULL;
}
int