]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Merge of http(s)_port and accelerator directive updates from rproxy
authorhno <>
Sat, 22 Feb 2003 02:53:01 +0000 (02:53 +0000)
committerhno <>
Sat, 22 Feb 2003 02:53:01 +0000 (02:53 +0000)
 - The httpd_accel_* directives is now gone, replaced by http(s)_port
   options

 - The http(s)_port options has a list of new options for controlling
   the type and mode of port created with respect to

     - transparent proxying
     - plain acceleration
     - host header based acceleration
     - normal proxying (default)

 - To enforce a reasonable level of security in accelerators, accelerated
   requests are denied to go direct unless forced by always_direct.

15 files changed:
src/IPInterception.cc
src/IPInterception.h
src/cache_cf.cc
src/cf.data.pre
src/client_side.cc
src/client_side_request.cc
src/forward.cc
src/globals.h
src/main.cc
src/neighbors.cc
src/peer_select.cc
src/protos.h
src/structs.h
src/tools.cc
src/typedefs.h

index 93f61ea74de7cc61384a5642a0ac2624a34950a8..1c5affcacd5c2fcadefb5299af535155ba6d6bd7 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: IPInterception.cc,v 1.4 2003/01/23 00:37:13 robertc Exp $
+ * $Id: IPInterception.cc,v 1.5 2003/02/21 19:53:01 hno Exp $
  *
  * DEBUG: section 89    NAT / IP Interception 
  * AUTHOR: Robert Collins
 #include <linux/netfilter_ipv4.h>
 #endif
 
-void
-rewriteURIwithInterceptedDetails(char const *originalURL, char *uriBuffer, size_t bufferLength, int fd, struct sockaddr_in me, struct sockaddr_in peer, int vport)
-{
 #if IPF_TRANSPARENT
+int
+clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst)
+{
     struct natlookup natLookup;
     static int natfd = -1;
     static int siocgnatl_cmd = SIOCGNATL & 0xff;
     int x;
-#endif
-#if PF_TRANSPARENT
-    struct pfioc_natlook nl;
-    static int pffd = -1;
-#endif
-#if LINUX_NETFILTER
-    size_t sock_sz = sizeof(me);
-#endif
-#if IPF_TRANSPARENT
+
     natLookup.nl_inport = me.sin_port;
     natLookup.nl_outport = peer.sin_port;
     natLookup.nl_inip = me.sin_addr;
@@ -109,13 +101,11 @@ rewriteURIwithInterceptedDetails(char const *originalURL, char *uriBuffer, size_
        errno = save_errno;
     }
     if (natfd < 0) {
-       debug(89, 1) ("rewriteURIwithInterceptedDetails: NAT open failed: %s\n",
+       debug(50, 1) ("parseHttpRequest: NAT open failed: %s\n",
            xstrerror());
-       cbdataFree(context);
-       xfree(inbuf);
-       return rewriteURIwithInterceptedDetailsAbort(conn, "error:nat-open-failed");
+       return -1;
     }
-    /* 
+    /*
      * IP-Filter changed the type for SIOCGNATL between
      * 3.3 and 3.4.  It also changed the cmd value for
      * SIOCGNATL, so at least we can detect it.  We could
@@ -130,32 +120,51 @@ rewriteURIwithInterceptedDetails(char const *originalURL, char *uriBuffer, size_
     }
     if (x < 0) {
        if (errno != ESRCH) {
-           debug(89, 1) ("rewriteURIwithInterceptedDetails: NAT lookup failed: ioctl(SIOCGNATL)\n");
+           debug(50, 1) ("parseHttpRequest: NAT lookup failed: ioctl(SIOCGNATL)\n");
            close(natfd);
            natfd = -1;
-           cbdataFree(context);
-           xfree(inbuf);
-           return rewriteURIwithInterceptedDetailsAbort(conn,
-               "error:nat-lookup-failed");
-       } else
-           snprintf(uriBuffer, bufferLength, "http://%s:%d%s",
-               inet_ntoa(me.sin_addr), vport, originalURL);
+       }
+       return -1;
     } else {
-       if (vport_mode)
-           vport = ntohs(natLookup.nl_realport);
-       snprintf(uriBuffer, bufferLength, "http://%s:%d%s",
-           inet_ntoa(natLookup.nl_realip), vport, originalURL);
+       if (me.sin_addr.s_addr != natLookup.nl_realip.s_addr)
+           dst->sin_family = AF_INET;
+           dst->sin_port = natLookup.nl_realport;
+           dst->sin_addr = natLookup.nl_realip;
+           return 0;
+       } else {
+           return -1;
+       }
     }
+}
+#elif LINUX_NETFILTER
+int
+clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst)
+{
+    size_t sock_sz = sizeof(*dst);
+    memcpy(dst, &me, sizeof(*dst));
+    if (getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, dst, &sock_sz) != 0)
+       return -1;
+
+    debug(33, 5) ("clientNatLookup: addr = %s", inet_ntoa(dst->sin_addr));
+    if (me.sin_addr.s_addr != dst->sin_addr.s_addr)
+       return 0;
+    else
+       return -1;
+}
 #elif PF_TRANSPARENT
+int
+clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst)
+{
+    struct pfioc_natlook nl;
+    static int pffd = -1;
     if (pffd < 0)
        pffd = open("/dev/pf", O_RDWR);
     if (pffd < 0) {
-       debug(89, 1) ("rewriteURIwithInterceptedDetails: PF open failed: %s\n",
+       debug(50, 1) ("parseHttpRequest: PF open failed: %s\n",
            xstrerror());
-       cbdataFree(context);
-       xfree(inbuf);
-       return rewriteURIwithInterceptedDetailsAbort(conn, "error:pf-open-failed");
+       return -1;
     }
+    memset(dst, 0, sizeof(*dst));
     memset(&nl, 0, sizeof(struct pfioc_natlook));
     nl.saddr.v4.s_addr = peer.sin_addr.s_addr;
     nl.sport = peer.sin_port;
@@ -166,29 +175,28 @@ rewriteURIwithInterceptedDetails(char const *originalURL, char *uriBuffer, size_
     nl.direction = PF_OUT;
     if (ioctl(pffd, DIOCNATLOOK, &nl)) {
        if (errno != ENOENT) {
-           debug(89, 1) ("rewriteURIwithInterceptedDetails: PF lookup failed: ioctl(DIOCNATLOOK)\n");
+           debug(50, 1) ("parseHttpRequest: PF lookup failed: ioctl(DIOCNATLOOK)\n");
            close(pffd);
            pffd = -1;
-           cbdataFree(context);
-           xfree(inbuf);
-           return rewriteURIwithInterceptedDetailsAbort(conn,
-               "error:pf-lookup-failed");
-       } else
-           snprintf(uriBuffer, bufferLength, "http://%s:%d%s",
-               inet_ntoa(me.sin_addr), vport, originalURL);
-    } else
-       snprintf(uriBuffer, bufferLength, "http://%s:%d%s",
-           inet_ntoa(nl.rdaddr.v4), ntohs(nl.rdport), originalURL);
+       }
+       return -1;
+    } else {
+       int natted = me.sin_addr.s_addr != nt.rdaddr.v4.s_addr;
+       dst->sin_family = AF_INET;
+       dst->sin_port = nl.rdport;
+       dst->sin_addr = nl.rdaddr.v4;
+       if (natted)
+           return 0;
+       else
+           return -1;
+    }
+}
 #else
-#if LINUX_NETFILTER
-    /* If the call fails the address structure will be unchanged */
-    getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, &me, &sock_sz);
-    debug(89, 5) ("rewriteURIwithInterceptedDetails: addr = %s",
-       inet_ntoa(me.sin_addr));
-    if (vport_mode)
-       vport = (int) ntohs(me.sin_port);
-#endif
-    snprintf(uriBuffer, bufferLength, "http://%s:%d%s",
-       inet_ntoa(me.sin_addr), vport, originalURL);
-#endif
+int
+clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst)
+{
+    debug(33, 1) ("WARNING: transparent proxying not supported\n");
+    return -1;
 }
+#endif
+
index 38329a0dcfeef31a8a981a35122b28e09dce8f3e..d112968343e56d19d9b90a42be696fa584fc9433 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: IPInterception.h,v 1.4 2003/01/23 00:37:13 robertc Exp $
+ * $Id: IPInterception.h,v 1.5 2003/02/21 19:53:01 hno Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -34,7 +34,7 @@
 #ifndef SQUID_IPINTERCEPTION_H
 #define SQUID_IPINTERCEPTION_H
 
-SQUIDCEXTERN void
-     rewriteURIwithInterceptedDetails(char const *originalURL, char *uriBuffer, size_t bufferLength, int fd, struct sockaddr_in me, struct sockaddr_in peer, int vport);
+SQUIDCEXTERN int
+clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst);
 
 #endif /* SQUID_IPINTERCEPTION_H */
index e25d43fadd45036f301c67a7897d7c2d62058989..20b416617e3f9931ad42e20c77546b0ee4045e99 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: cache_cf.cc,v 1.432 2003/02/17 08:39:43 robertc Exp $
+ * $Id: cache_cf.cc,v 1.433 2003/02/21 19:53:01 hno Exp $
  *
  * DEBUG: section 3     Configuration File Parsing
  * AUTHOR: Harvest Derived
@@ -99,11 +99,17 @@ static void free_http_header_replace(header_mangler * header);
 static void parse_denyinfo(acl_deny_info_list ** var);
 static void dump_denyinfo(StoreEntry * entry, const char *name, acl_deny_info_list * var);
 static void free_denyinfo(acl_deny_info_list ** var);
+#if CURRENTLY_UNUSED
 static void parse_sockaddr_in_list(sockaddr_in_list **);
 static void dump_sockaddr_in_list(StoreEntry *, const char *, const sockaddr_in_list *);
 static void free_sockaddr_in_list(sockaddr_in_list **);
-#if 0
 static int check_null_sockaddr_in_list(const sockaddr_in_list *);
+#endif /* CURRENTLY_UNUSED */
+static void parse_http_port_list(http_port_list **);
+static void dump_http_port_list(StoreEntry *, const char *, const http_port_list *);
+static void free_http_port_list(http_port_list **);
+#if UNUSED_CODE
+static int check_null_http_port_list(const http_port_list *);
 #endif
 #if USE_SSL
 static void parse_https_port_list(https_port_list **);
@@ -354,7 +360,6 @@ parseConfigFile(const char *file_name)
 static void
 configDoConfigure(void)
 {
-    LOCAL_ARRAY(char, buf, BUFSIZ);
     memset(&Config2, '\0', sizeof(SquidConfig2));
     /* init memory as early as possible */
     memConfigure();
@@ -384,22 +389,12 @@ configDoConfigure(void)
            wordlistDestroy(&Config.Program.redirect);
        }
     }
-    if (Config.Accel.host) {
-       snprintf(buf, BUFSIZ, "http://%s:%d", Config.Accel.host, Config.Accel.port);
-       Config2.Accel.prefix = xstrdup(buf);
-       Config2.Accel.on = 1;
-    }
     if (Config.appendDomain)
        if (*Config.appendDomain != '.')
            fatal("append_domain must begin with a '.'");
     if (Config.errHtmlText == NULL)
        Config.errHtmlText = xstrdup(null_string);
     storeConfigure();
-    if (Config2.Accel.on && !strcmp(Config.Accel.host, "virtual")) {
-       vhost_mode = 1;
-       if (Config.Accel.port == 0)
-           vport_mode = 1;
-    }
     snprintf(ThisCache, sizeof(ThisCache), "%s (%s)",
        uniqueHostname(),
        full_appname_string);
@@ -2239,6 +2234,10 @@ parseNeighborType(const char *s)
     return PEER_SIBLING;
 }
 
+#if CURRENTLY_UNUSED
+/* This code was previously used by http_port. Left as it really should
+ * be used by icp_port and htcp_port
+ */
 void
 parse_sockaddr_in_list_token(sockaddr_in_list ** head, char *token)
 {
@@ -2308,51 +2307,193 @@ free_sockaddr_in_list(sockaddr_in_list ** head)
     }
 }
 
-#if 0
 static int
 check_null_sockaddr_in_list(const sockaddr_in_list * s)
 {
     return NULL == s;
 }
-#endif
+#endif /* CURRENTLY_UNUSED */
 
-#if USE_SSL
 static void
-parse_https_port_list(https_port_list ** head)
+parse_http_port_specification(http_port_list * s, char *token)
 {
-    char *token;
-    char *t;
-    char *host;
+    char *host = NULL;
     const struct hostent *hp;
-    unsigned short port;
-    https_port_list *s;
-    token = strtok(NULL, w_space);
-    if (!token)
-       self_destruct();
-    host = NULL;
-    port = 0;
+    unsigned short port = 0;
+    char *t;
     if ((t = strchr(token, ':'))) {
        /* host:port */
        host = token;
        *t = '\0';
-       port = (unsigned short) xatoi(t + 1);
+       port = (unsigned short) atoi(t + 1);
        if (0 == port)
            self_destruct();
-    } else if ((port = xatoi(token)) > 0) {
+    } else if ((port = atoi(token)) > 0) {
        /* port */
     } else {
        self_destruct();
     }
-    s = (https_port_list *)xcalloc(1, sizeof(*s));
     s->s.sin_port = htons(port);
     if (NULL == host)
        s->s.sin_addr = any_addr;
     else if (1 == safe_inet_addr(host, &s->s.sin_addr))
        (void) 0;
-    else if ((hp = gethostbyname(host)))       /* dont use ipcache */
+    else if ((hp = gethostbyname(host))) {
+       /* dont use ipcache */
        s->s.sin_addr = inaddrFromHostent(hp);
-    else
+       s->defaultsite = xstrdup(host);
+    } else
+       self_destruct();
+}
+
+static void
+parse_http_port_option(http_port_list * s, char *token)
+{
+    if (strncmp(token, "defaultsite=", 12) == 0) {
+       safe_free(s->defaultsite);
+       s->defaultsite = xstrdup(token + 12);
+       s->accel = 1;
+    } else if (strncmp(token, "name=", 5) == 0) {
+       safe_free(s->name);
+       s->name = xstrdup(token + 5);
+    } else if (strcmp(token, "transparent") == 0) {
+       s->transparent = 1;
+    } else if (strcmp(token, "vhost") == 0) {
+       s->vhost = 1;
+       s->accel = 1;
+    } else if (strcmp(token, "vport") == 0) {
+       s->vport = -1;
+       s->accel = 1;
+    } else if (strncmp(token, "vport=", 6) == 0) {
+       s->vport = atoi(token + 6);
+       s->accel = 1;
+    } else if (strncmp(token, "protocol=", 9) == 0) {
+       s->protocol = xstrdup(token + 9);
+       s->accel = 1;
+    } else if (strcmp(token, "accel") == 0) {
+       s->accel = 1;
+    } else {
+       self_destruct();
+    }
+}
+
+static void
+free_generic_http_port_data(http_port_list * s)
+{
+    safe_free(s->name);
+    safe_free(s->defaultsite);
+}
+
+static void
+cbdataFree_http_port(void *data)
+{
+    free_generic_http_port_data((http_port_list *)data);
+}
+
+
+static http_port_list *
+create_http_port(char *portspec)
+{
+    CBDATA_TYPE(http_port_list);
+    CBDATA_INIT_TYPE_FREECB(http_port_list, cbdataFree_http_port);
+
+    http_port_list *s = cbdataAlloc(http_port_list);
+    s->protocol = xstrdup("http");
+    parse_http_port_specification(s, portspec);
+    return s;
+}
+
+void
+add_http_port(char *portspec)
+{
+    http_port_list *s = create_http_port(portspec);
+    s->next = Config.Sockaddr.http;
+    Config.Sockaddr.http = s;
+}
+
+static void
+parse_http_port_list(http_port_list ** head)
+{
+    char *token = strtok(NULL, w_space);
+    if (!token)
        self_destruct();
+    http_port_list *s = create_http_port(token);
+    /* parse options ... */
+    while ((token = strtok(NULL, w_space))) {
+       parse_http_port_option(s, token);
+    }
+    while (*head)
+       head = &(*head)->next;
+    *head = s;
+}
+
+static void
+dump_generic_http_port(StoreEntry * e, const char *n, const http_port_list * s)
+{
+    storeAppendPrintf(e, "%s %s:%d",
+       n,
+       inet_ntoa(s->s.sin_addr),
+       ntohs(s->s.sin_port));
+    if (s->defaultsite)
+       storeAppendPrintf(e, " defaultsite=%s", s->defaultsite);
+    if (s->transparent)
+       storeAppendPrintf(e, " transparent");
+    if (s->vhost)
+       storeAppendPrintf(e, " vhost");
+    if (s->vport)
+       storeAppendPrintf(e, " vport");
+}
+static void
+dump_http_port_list(StoreEntry * e, const char *n, const http_port_list * s)
+{
+    while (s) {
+       dump_generic_http_port(e, n, s);
+       storeAppendPrintf(e, "\n");
+       s = s->next;
+    }
+}
+
+static void
+free_http_port_list(http_port_list ** head)
+{
+    http_port_list *s;
+    while ((s = *head) != NULL) {
+       *head = s->next;
+       cbdataFree(s);
+    }
+}
+
+#if UNUSED_CODE
+static int
+check_null_http_port_list(const http_port_list * s)
+{
+    return NULL == s;
+}
+#endif
+
+#if USE_SSL
+static void
+cbdataFree_https_port(void *data)
+{
+    https_port_list *s = (https_port_list *)data;
+    free_generic_http_port_data(&s->http);
+    safe_free(s->cert);
+    safe_free(s->key);
+}
+
+static void
+parse_https_port_list(https_port_list ** head)
+{
+    CBDATA_TYPE(https_port_list);
+    char *token;
+    https_port_list *s;
+    CBDATA_INIT_TYPE_FREECB(https_port_list, cbdataFree_https_port);
+    token = strtok(NULL, w_space);
+    if (!token)
+       self_destruct();
+    s = cbdataAlloc(https_port_list);
+    s->http.protocol = xstrdup("https");
+    parse_http_port_specification(&s->http, token);
     /* parse options ... */
     while ((token = strtok(NULL, w_space))) {
        if (strncmp(token, "cert=", 5) == 0) {
@@ -2382,14 +2523,14 @@ parse_https_port_list(https_port_list ** head)
            safe_free(s->sslflags);
            s->sslflags = xstrdup(token + 9);
        } else {
-           self_destruct();
+           parse_http_port_option(&s->http, token);
        }
     }
-    while (*head)
-       head = &(*head)->next;
     s->sslContext = sslCreateServerContext(s->cert, s->key, s->version, s->cipher, s->options, s->sslflags, s->clientca, s->cafile, s->capath);
     if (!s->sslContext)
        self_destruct();
+    while (*head)
+       head = (https_port_list **)&(*head)->http.next;
     *head = s;
 }
 
@@ -2397,10 +2538,7 @@ static void
 dump_https_port_list(StoreEntry * e, const char *n, const https_port_list * s)
 {
     while (s) {
-       storeAppendPrintf(e, "%s %s:%d",
-           n,
-           inet_ntoa(s->s.sin_addr),
-           ntohs(s->s.sin_port));
+       dump_generic_http_port(e, n, &s->http);
        if (s->cert)
            storeAppendPrintf(e, " cert=%s", s->cert);
        if (s->key)
@@ -2418,7 +2556,7 @@ dump_https_port_list(StoreEntry * e, const char *n, const https_port_list * s)
        if (s->sslflags)
            storeAppendPrintf(e, " sslflags=%s", s->sslflags);
        storeAppendPrintf(e, "\n");
-       s = s->next;
+       s = (https_port_list *) s->http.next;
     }
 }
 
@@ -2427,10 +2565,8 @@ free_https_port_list(https_port_list ** head)
 {
     https_port_list *s;
     while ((s = *head) != NULL) {
-       *head = s->next;
-       safe_free(s->cert);
-       safe_free(s->key);
-       safe_free(s);
+       *head = (https_port_list *) s->http.next;
+       cbdataFree(s);
     }
 }
 
@@ -2447,7 +2583,6 @@ check_null_https_port_list(const https_port_list * s)
 void
 configFreeMemory(void)
 {
-    safe_free(Config2.Accel.prefix);
     free_all();
 }
 
index 0035c71a8c5dacfa72c2cf4d273620148a9130ed..192779044e10b8fb739f11b535b4cce8709b08f2 100644 (file)
@@ -1,6 +1,6 @@
 
 #
-# $Id: cf.data.pre,v 1.303 2003/02/16 20:53:34 hno Exp $
+# $Id: cf.data.pre,v 1.304 2003/02/21 19:53:01 hno Exp $
 #
 #
 # SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -54,13 +54,13 @@ COMMENT_START
 COMMENT_END
 
 NAME: http_port ascii_port
-TYPE: sockaddr_in_list
+TYPE: http_port_list
 DEFAULT: none
 LOC: Config.Sockaddr.http
 DOC_START
-       Usage:  port
-               hostname:port
-               1.2.3.4:port
+       Usage:  port [options]
+               hostname:port [options]
+               1.2.3.4:port [options]
 
        The socket addresses where Squid will listen for HTTP client
        requests.  You may specify multiple socket addresses.
@@ -80,11 +80,22 @@ DOC_START
 
        You may specify multiple socket addresses on multiple lines.
 
+       options are:
+               accel           Accelerator mode
+               transparent     Support for transparent proxies
+               vhost           Accelerator using Host directive
+               vport           Accelerator with IP virtual host support
+               vport=NN        As above, but uses specified port number
+                               rather than the http_port number.
+               defaultsite=xx  Main web site name for accelerators.
+                               also implies accel
+               protocol=       Protocol to reconstruct accelerated
+                               requests with. Defaults to http.
+
        If you run Squid on a dual-homed machine with an internal
        and an external interface then we recommend you to specify the
        internal address:port in http_port. This way Squid will only be
        visible on the internal address.
-
 NOCOMMENT_START
 # Squid normally listens to port 3128
 http_port 3128
@@ -111,6 +122,12 @@ DOC_START
                              
        Options:
 
+          defaultsite= The name of the https site presented on
+                       this port.
+
+          protocol=    Protocol to reconstruct accelerated requests
+                       with. Defaults to https.
+
           cert=        Path to SSL certificate (PEM format)
                
           key=         Path to SSL private key file (PEM format)
@@ -2680,90 +2697,6 @@ DOC_START
        message.
 DOC_END
 
-COMMENT_START
- HTTPD-ACCELERATOR OPTIONS
- -----------------------------------------------------------------------------
-COMMENT_END
-
-NAME: httpd_accel_host
-TYPE: string
-LOC: Config.Accel.host
-DEFAULT: none
-DOC_NONE
-
-NAME: httpd_accel_port
-TYPE: ushort
-LOC: Config.Accel.port
-DEFAULT: 80
-DOC_START
-       If you want to run Squid as an httpd accelerator, define the
-       host name and port number where the real HTTP server is.
-
-       If you want IP based virtual host support then specify the
-       hostname as "virtual". This will make Squid use the IP address
-       where it accepted the request as hostname in the URL.
-
-       If you want virtual port support then specify the port as "0".
-DOC_END
-
-NAME: httpd_accel_single_host
-COMMENT: on|off
-TYPE: onoff
-LOC: Config.Accel.single_host
-DEFAULT: off
-DOC_START
-       If you are running Squid as an accelerator and have a single backend
-       server then set this to on. This causes Squid to forward the request
-       to this server irregardles of what any redirectors or Host headers
-       says.
-
-       Leave this at off if you have multiple backend servers, and use a
-       redirector (or host table or private DNS) to map the requests to the
-       appropriate backend servers. Note that the mapping needs to be a
-       1-1 mapping between requested and backend (from redirector) domain
-       names or caching will fail, as cacing is performed using the
-       URL returned from the redirector.
-
-       See also redirect_rewrites_host_header.
-DOC_END
-
-NAME: httpd_accel_with_proxy
-COMMENT: on|off
-TYPE: onoff
-DEFAULT: off
-LOC: Config.onoff.accel_with_proxy
-DOC_START
-       If you want to use Squid as both a local httpd accelerator
-       and as a proxy, change this to 'on'. Note however that your
-       proxy users may have trouble to reach the accelerated domains
-       unless their browsers are configured not to use this proxy for
-       those domains (for example via the no_proxy browser configuration
-       setting)
-DOC_END
-
-NAME: httpd_accel_uses_host_header
-COMMENT: on|off
-TYPE: onoff
-DEFAULT: off
-LOC: opt_accel_uses_host
-DOC_START
-       HTTP/1.1 requests include a Host: header which is basically the
-       hostname from the URL.  The Host: header is used for domain based
-       virutal hosts. If your accelerator needs to provide domain based
-       virtual hosts on the same IP address then you will need to turn this
-       on.
-
-       Note that Squid does NOT check the value of the Host header matches
-       any of your accelerated server, so it may open a big security hole
-       unless you take care to set up access controls proper.  We recommend
-       that this option remain disabled unless you are sure of what you
-       are doing.
-
-       However, you will need to enable this option if you run Squid
-       as a transparent proxy.  Otherwise, virtual servers which
-       require the Host: header will not be properly cached.
-DOC_END
-
 COMMENT_START
  MISCELLANEOUS
  -----------------------------------------------------------------------------
index 2804199187a6a8d5df4a07ec658ef07bae5aa8a9..bce471e69a67771877eec44453ed1af560a0c456 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side.cc,v 1.622 2003/02/20 00:13:04 hno Exp $
+ * $Id: client_side.cc,v 1.623 2003/02/21 19:53:01 hno Exp $
  *
  * DEBUG: section 33    Client-side Routines
  * AUTHOR: Duane Wessels
@@ -177,16 +177,14 @@ static void connReadNextRequest(ConnStateData * conn);
 static void ClientSocketContextPushDeferredIfNeeded(ClientSocketContext * deferredRequest, ConnStateData * conn);
 static void clientUpdateSocketStats(log_type logType, size_t size);
 
-static ClientSocketContext *clientCheckRequestLineIsParseable(char *inbuf, size_t req_sz, ConnStateData * conn);
 static ClientSocketContext *clientParseRequestMethod(char *inbuf, method_t * method_p, ConnStateData * conn);
 static char *skipLeadingSpace(char *aString);
 static char *findTrailingHTTPVersion(char *uriAndHTTPVersion);
+#if UNUSED_CODE
 static void trimTrailingSpaces(char *aString, size_t len);
-static ClientSocketContext *parseURIandHTTPVersion(char **url_p, http_version_t * http_ver_p, ConnStateData * conn);
+#endif
+static ClientSocketContext *parseURIandHTTPVersion(char **url_p, http_version_t * http_ver_p, ConnStateData * conn, char *http_version_str);
 static void setLogUri(clientHttpRequest * http, char const *uri);
-static void prepareInternalUrl(clientHttpRequest * http, char *url);
-static void prepareForwardProxyUrl(clientHttpRequest * http, char *url);
-static void prepareAcceleratedUrl(clientHttpRequest * http, char *url, char *req_hdr);
 static int connGetAvailableBufferLength(ConnStateData const *conn);
 static void connMakeSpaceAvailable(ConnStateData * conn);
 static void connAddContextToQueue(ConnStateData * conn, ClientSocketContext * context);
@@ -196,7 +194,7 @@ static int connFinishedWithConn(ConnStateData * conn, int size);
 static void connNoteUseOfBuffer(ConnStateData * conn, size_t byteCount);
 static int connKeepReadingIncompleteRequest(ConnStateData * conn);
 static void connCancelIncompleteRequests(ConnStateData * conn);
-static ConnStateData *connStateCreate(struct sockaddr_in *peer, struct sockaddr_in *me, int fd);
+static ConnStateData *connStateCreate(struct sockaddr_in *peer, struct sockaddr_in *me, int fd, http_port_list *port);
 static int connAreAllContextsForThisConnection(ConnStateData * connState);
 static void connFreeAllContexts(ConnStateData * connState);
 
@@ -1288,23 +1286,13 @@ parseHttpRequestAbort(ConnStateData * conn, const char *uri)
     return context;
 }
 
-ClientSocketContext *
-clientCheckRequestLineIsParseable(char *inbuf, size_t req_sz, ConnStateData * conn)
-{
-    if (strlen(inbuf) != req_sz) {
-       debug(33, 1) ("clientCheckRequestLineIsParseable: Requestheader contains NULL characters\n");
-       return parseHttpRequestAbort(conn, "error:invalid-request");
-    }
-    return NULL;
-}
-
 ClientSocketContext *
 clientParseRequestMethod(char *inbuf, method_t * method_p, ConnStateData * conn)
 {
     char *mstr = NULL;
     if ((mstr = strtok(inbuf, "\t ")) == NULL) {
        debug(33, 1) ("clientParseRequestMethod: Can't get request method\n");
-       return parseHttpRequestAbort(conn, "error:invalid-request-method");
+       return parseHttpRequestAbort(conn, "error:invalid-request");
     }
     *method_p = urlParseMethod(mstr);
     if (*method_p == METHOD_NONE) {
@@ -1324,19 +1312,25 @@ skipLeadingSpace(char *aString)
     return result;
 }
 
-char *
+static char *
 findTrailingHTTPVersion(char *uriAndHTTPVersion)
 {
-    char *token = uriAndHTTPVersion + strlen(uriAndHTTPVersion);
-    assert(*token == '\0');
-    while (token > uriAndHTTPVersion) {
-       --token;
-       if (xisspace(*token) && !strncmp(token + 1, "HTTP/", 5))
-           return token + 1;
+    char *token;
+    
+    for (token = strchr(uriAndHTTPVersion, '\n'); token > uriAndHTTPVersion; token--) {
+       if (*token == '\n' || *token == '\r')
+           continue;
+       if (xisspace(*token)) {
+           if (strncasecmp(token + 1, "HTTP/", 5) == 0)
+               return token + 1;
+           else
+               break;
+       }
     }
-    return uriAndHTTPVersion;
+    return NULL;
 }
 
+#if UNUSED_CODE
 void
 trimTrailingSpaces(char *aString, size_t len)
 {
@@ -1344,52 +1338,58 @@ trimTrailingSpaces(char *aString, size_t len)
     while (endPointer > aString && xisspace(*endPointer))
        *(endPointer--) = '\0';
 }
+#endif
 
-ClientSocketContext *
+static ClientSocketContext *
 parseURIandHTTPVersion(char **url_p, http_version_t * http_ver_p,
-    ConnStateData * conn)
+    ConnStateData * conn, char *http_version_str)
 {
     char *url;
-    char *token;
-    /* look for URL+HTTP/x.x */
+    char *t;
+    /* look for URL (strtok initiated by clientParseRequestMethod) */
     if ((url = strtok(NULL, "\n")) == NULL) {
        debug(33, 1) ("parseHttpRequest: Missing URL\n");
        return parseHttpRequestAbort(conn, "error:missing-url");
     }
     url = skipLeadingSpace(url);
-    token = findTrailingHTTPVersion(url);
-    trimTrailingSpaces(url, token - url - 1);
 
+    if (!*url || (http_version_str && http_version_str <= url+1)) {
+       debug(33, 1) ("parseHttpRequest: Missing URL\n");
+       return parseHttpRequestAbort(conn, "error:missing-url");
+    }
+    /* Terminate URL just before HTTP version (or at end of line) */
+    if (http_version_str)
+       http_version_str[-1] = '\0';
+    else {
+       t = url + strlen(url) - 1;
+       while (t > url && *t == '\r')
+           *t-- = '\0';
+    }
     debug(33, 5) ("parseHttpRequest: URI is '%s'\n", url);
     *url_p = url;
-    if (token == NULL) {
-       debug(33, 3) ("parseHttpRequest: Missing HTTP identifier\n");
-#if RELAXED_HTTP_PARSER
-       httpBuildVersion(http_ver_p, 0, 9);     /* wild guess */
-#else
-       return parseHttpRequestAbort(conn, "error:missing-http-ident");
-#endif
-    } else {
-       if (sscanf(token + 5, "%d.%d", &http_ver_p->major,
+    if (http_version_str) {
+       if (sscanf(http_version_str + 5, "%d.%d", &http_ver_p->major,
                &http_ver_p->minor) != 2) {
            debug(33, 3) ("parseHttpRequest: Invalid HTTP identifier.\n");
            return parseHttpRequestAbort(conn, "error:invalid-http-ident");
        }
        debug(33, 6) ("parseHttpRequest: Client HTTP version %d.%d.\n",
            http_ver_p->major, http_ver_p->minor);
+    } else {
+       httpBuildVersion(http_ver_p, 0, 9);     /* wild guess */
     }
     return NULL;
 }
 
 /* Utility function to perform part of request parsing */
 static ClientSocketContext *
-clientParseHttpRequestLine(char *inbuf, size_t req_sz, ConnStateData * conn,
-    method_t * method_p, char **url_p, http_version_t * http_ver_p)
+clientParseHttpRequestLine(char *reqline, ConnStateData * conn,
+    method_t * method_p, char **url_p, http_version_t * http_ver_p, char * http_version_str)
 {
     ClientSocketContext *result = NULL;
-    if ((result = clientCheckRequestLineIsParseable(inbuf, req_sz, conn))
-       || (result = clientParseRequestMethod(inbuf, method_p, conn))
-       || (result = parseURIandHTTPVersion(url_p, http_ver_p, conn)))
+    /* XXX: This sequence relies on strtok() */
+    if ((result = clientParseRequestMethod(reqline, method_p, conn))
+           || (result = parseURIandHTTPVersion(url_p, http_ver_p, conn, http_version_str)))
        return result;
 
     return NULL;
@@ -1405,84 +1405,102 @@ setLogUri(clientHttpRequest * http, char const *uri)
        http->log_uri = xstrndup(rfc1738_escape_unescaped(uri), MAX_URL);
 }
 
-void
-prepareInternalUrl(clientHttpRequest * http, char *url)
-{
-    http->uri = xstrdup(internalLocalUri(NULL, url));
-    http->flags.internal = 1;
-    http->flags.accel = 1;
-}
+static void
+prepareAcceleratedURL(ConnStateData * conn, clientHttpRequest *http, char *url, const char *req_hdr) {
+    int vhost = conn->port->vhost;
+    int vport = conn->port->vport;
+    char *host;
 
-void
-prepareForwardProxyUrl(clientHttpRequest * http, char *url)
-{
-    size_t url_sz;
-    /* URL may be rewritten later, so make extra room */
-    url_sz = strlen(url) + Config.appendDomainLen + 5;
-    http->uri = (char *)xcalloc(url_sz, 1);
-    strcpy(http->uri, url);
-    http->flags.accel = 0;
-}
+    http->flags.accel = 1;
 
-void
-prepareAcceleratedUrl(clientHttpRequest * http, char *url, char *req_hdr)
-{
-    size_t url_sz;
-    char *t;
-    /* prepend the accel prefix */
-    if (opt_accel_uses_host && (t = mime_get_header(req_hdr, "Host"))) {
-       int vport;
-       char *q;
-       const char *protocol_name = "http";
-       if (vport_mode)
-           vport = (int) ntohs(http->conn->me.sin_port);
-       else
-           vport = (int) Config.Accel.port;
-       /* If a Host: header was specified, use it to build the URL 
-        * instead of the one in the Config file. */
-       /*
-        * XXX Use of the Host: header here opens a potential
-        * security hole.  There are no checks that the Host: value
-        * corresponds to one of your servers.  It might, for example,
-        * refer to www.playboy.com.  The 'dst' and/or 'dst_domain' ACL 
-        * types should be used to prevent httpd-accelerators 
-        * handling requests for non-local servers */
-       strtok(t, " /;@");
-       if ((q = strchr(t, ':'))) {
-           *q++ = '\0';
-           if (vport_mode)
-               vport = atoi(q);
-       }
-       url_sz = strlen(url) + 32 + Config.appendDomainLen + strlen(t);
-       http->uri = (char *)xcalloc(url_sz, 1);
+    /* BUG: Squid cannot deal with '*' URLs (RFC2616 5.1.2) */
 
-#if SSL_FORWARDING_NOT_YET_DONE
-       if (Config.Sockaddr.https->s.sin_port == http->conn->me.sin_port) {
-           protocol_name = "https";
-           vport = ntohs(http->conn->me.sin_port);
-       }
+    if (*url != '/') {
+       if (conn->port->vhost)
+           return; /* already in good shape */
+       /* else we need to ignore the host name */
+       url = strstr(url, "//");
+#if SHOULD_REJECT_UNKNOWN_URLS
+       if (!url)
+           return parseHttpRequestAbort(conn, "error:invalid-request");
 #endif
+       if (url)
+           url = strchr(url + 2, '/');
+       if (!url)
+           url = (char *) "/";
+    }
+
+    if (internalCheck(url)) {
+       /* prepend our name & port */
+       http->uri = xstrdup(internalLocalUri(NULL, url));
+       http->flags.internal = 1;
+    } else if (vhost && (host = mime_get_header(req_hdr, "Host")) != NULL) {
+       int url_sz = strlen(url) + 32 + Config.appendDomainLen +
+           strlen(host);
+       http->uri = (char *)xcalloc(url_sz, 1);
+       snprintf(http->uri, url_sz, "%s://%s%s",
+               conn->port->protocol, host, url);
+       debug(33, 5) ("ACCEL VHOST REWRITE: '%s'\n", http->uri);
+    } else if (conn->port->defaultsite) {
+       int url_sz = strlen(url) + 32 + Config.appendDomainLen +
+           strlen(conn->port->defaultsite);
+       http->uri = (char *)xcalloc(url_sz, 1);
+       snprintf(http->uri, url_sz, "%s://%s%s",
+               conn->port->protocol, conn->port->defaultsite, url);
+       debug(33, 5) ("ACCEL DEFAULTSITE REWRITE: '%s'\n", http->uri);
+    } else if (vport == -1) {
+       /* Put the local socket IP address as the hostname.  */
+       int url_sz = strlen(url) + 32 + Config.appendDomainLen;
+       http->uri = (char *)xcalloc(url_sz, 1);
+       snprintf(http->uri, url_sz, "%s://%s:%d%s",
+               http->conn->port->protocol,
+               inet_ntoa(http->conn->me.sin_addr),
+               ntohs(http->conn->me.sin_port), url);
+       debug(33, 5) ("ACCEL VPORT REWRITE: '%s'\n", http->uri);
+    } else if (vport > 0) {
+       /* Put the local socket IP address as the hostname, but static port  */
+       int url_sz = strlen(url) + 32 + Config.appendDomainLen;
+       http->uri = (char *)xcalloc(url_sz, 1);
        snprintf(http->uri, url_sz, "%s://%s:%d%s",
-           protocol_name, t, vport, url);
-    } else if (vhost_mode) {
-       int vport;
-       /* Put the local socket IP address as the hostname */
-       url_sz = strlen(url) + 32 + Config.appendDomainLen;
+               http->conn->port->protocol,
+               inet_ntoa(http->conn->me.sin_addr),
+               vport, url);
+       debug(33, 5) ("ACCEL VPORT REWRITE: '%s'\n", http->uri);
+    }
+}
+
+static void
+prepareTransparentURL(ConnStateData * conn, clientHttpRequest *http, char *url, const char *req_hdr) {
+    char *host;
+
+    http->flags.accel = 1;
+
+    if (*url != '/')
+       return; /* already in good shape */
+
+    /* BUG: Squid cannot deal with '*' URLs (RFC2616 5.1.2) */
+
+    if (internalCheck(url)) {
+       /* prepend our name & port */
+       http->uri = xstrdup(internalLocalUri(NULL, url));
+       http->flags.internal = 1;
+    } else if ((host = mime_get_header(req_hdr, "Host")) != NULL) {
+       int url_sz = strlen(url) + 32 + Config.appendDomainLen +
+           strlen(host);
        http->uri = (char *)xcalloc(url_sz, 1);
-       if (vport_mode)
-           vport = (int) ntohs(http->conn->me.sin_port);
-       else
-           vport = (int) Config.Accel.port;
-       rewriteURIwithInterceptedDetails(url, http->uri, url_sz, http->conn->fd,
-           http->conn->me, http->conn->peer, vport);
-       debug(33, 5) ("VHOST REWRITE: '%s'\n", http->uri);
+       snprintf(http->uri, url_sz, "%s://%s%s",
+               conn->port->protocol, host, url);
+       debug(33, 5) ("TRANSPARENT HOST REWRITE: '%s'\n", http->uri);
     } else {
-       url_sz = strlen(Config2.Accel.prefix) + strlen(url) +
-           Config.appendDomainLen + 1;
+       /* Put the local socket IP address as the hostname.  */
+       int url_sz = strlen(url) + 32 + Config.appendDomainLen;
        http->uri = (char *)xcalloc(url_sz, 1);
-       snprintf(http->uri, url_sz, "%s%s", Config2.Accel.prefix, url);
+       snprintf(http->uri, url_sz, "%s://%s:%d%s",
+               http->conn->port->protocol,
+               inet_ntoa(http->conn->me.sin_addr),
+               ntohs(http->conn->me.sin_port), url);
+       debug(33, 5) ("TRANSPARENT REWRITE: '%s'\n", http->uri);
     }
-    http->flags.accel = 1;
 }
 
 /*
@@ -1501,6 +1519,7 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p,
     char *inbuf = NULL;
     char *url = NULL;
     char *req_hdr = NULL;
+    char *t;
     http_version_t http_ver;
     char *end;
     size_t header_sz;          /* size of headers, not including first line */
@@ -1509,25 +1528,49 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p,
     clientHttpRequest *http;
     ClientSocketContext *result;
     StoreIOBuffer tempBuffer;
+    char *http_version;
 
     /* pre-set these values to make aborting simpler */
     *prefix_p = NULL;
     *method_p = METHOD_NONE;
 
-    if ((req_sz = headersEnd(conn->in.buf, conn->in.notYetUsed)) == 0) {
-       debug(33, 5) ("Incomplete request, waiting for end of headers\n");
+    /* Read the HTTP message. HTTP/0.9 is detected by the absence of a HTTP signature */
+    if ((t = (char *)memchr(conn->in.buf, '\n', conn->in.notYetUsed)) == NULL) {
+       debug(33, 5) ("Incomplete request, waiting for end of request line\n");
        return NULL;
     }
+    *req_line_sz_p = t - conn->in.buf + 1;
+    http_version = findTrailingHTTPVersion(conn->in.buf);
+    if (http_version) {
+       if ((req_sz = headersEnd(conn->in.buf, conn->in.notYetUsed)) == 0) {
+           debug(33, 5) ("Incomplete request, waiting for end of headers\n");
+           return NULL;
+       }
+    } else {
+       debug(33, 3) ("parseHttpRequest: Missing HTTP identifier\n");
+       req_sz = t - conn->in.buf + 1;  /* HTTP/0.9 requests */
+    }
+
     assert(req_sz <= conn->in.notYetUsed);
     /* Use memcpy, not strdup! */
     inbuf = (char *)xmalloc(req_sz + 1);
     xmemcpy(inbuf, conn->in.buf, req_sz);
     *(inbuf + req_sz) = '\0';
+    /* and adjust http_version to point into the new copy */
+    if (http_version)
+       http_version = inbuf + (http_version - conn->in.buf);
+
+    /* Barf on NULL characters in the headers */
+    if (strlen(inbuf) != req_sz) {
+       debug(33, 1) ("parseHttpRequest: Requestheader contains NULL characters\n");
+#if TRY_TO_IGNORE_THIS
+       return parseHttpRequestAbort(conn, "error:invalid-request");
+#endif
+    }
 
     /* Is there a legitimate first line to the headers ? */
-    if ((result =
-           clientParseHttpRequestLine(inbuf, req_sz, conn, method_p, &url,
-               &http_ver))) {
+    if ((result = clientParseHttpRequestLine(inbuf, conn, method_p, &url,
+                       &http_ver, http_version))) {
        /* something wrong, abort */
        xfree(inbuf);
        return result;
@@ -1536,20 +1579,13 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p,
      * Process headers after request line
      * TODO: Use httpRequestParse here.
      */
-    req_hdr = strtok(NULL, null_string);
-    header_sz = req_sz - (req_hdr - inbuf);
-    if (0 == header_sz) {
-       debug(33, 3) ("parseHttpRequest: header_sz == 0\n");
-       xfree(inbuf);
-       return NULL;
-    }
-    assert(header_sz > 0);
+    req_hdr = inbuf + *req_line_sz_p;
+    header_sz = req_sz - *req_line_sz_p;
     debug(33, 3) ("parseHttpRequest: req_hdr = {%s}\n", req_hdr);
     end = req_hdr + header_sz;
     debug(33, 3) ("parseHttpRequest: end = {%s}\n", end);
 
     prefix_sz = end - inbuf;
-    *req_line_sz_p = req_hdr - inbuf;
     debug(33, 3) ("parseHttpRequest: prefix_sz = %d, req_line_sz = %d\n",
        (int) prefix_sz, (int) *req_line_sz_p);
     assert(prefix_sz <= conn->in.notYetUsed);
@@ -1570,26 +1606,35 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p,
     *(*prefix_p + prefix_sz) = '\0';
     dlinkAdd(http, &http->active, &ClientActiveRequests);
 
-    /* XXX this function is still way to long. here is a natural point for further simplification */
-
     debug(33, 5) ("parseHttpRequest: Request Header is\n%s\n",
        (*prefix_p) + *req_line_sz_p);
+
 #if THIS_VIOLATES_HTTP_SPECS_ON_URL_TRANSFORMATION
     if ((t = strchr(url, '#')))        /* remove HTML anchors */
        *t = '\0';
 #endif
 
-    if (internalCheck(url))
-       prepareInternalUrl(http, url);
-    else if (Config2.Accel.on && *url == '/')
-       prepareAcceleratedUrl(http, url, req_hdr);
-    else
-       prepareForwardProxyUrl(http, url);
+    /* Rewrite the URL in transparent or accelerator mode */
+    if (conn->transparent) {
+       prepareTransparentURL(conn, http, url, req_hdr);
+    } else if (conn->port->accel) {
+       prepareAcceleratedURL(conn, http, url, req_hdr);
+    }
+
+    if (!http->uri) {
+       /* No special rewrites have been applied above, use the
+        * requested url. may be rewritten later, so make extra room */
+       int url_sz = strlen(url) + Config.appendDomainLen + 5;
+       http->uri = (char *)xcalloc(url_sz, 1);
+       strcpy(http->uri, url);
+    }
+    
     setLogUri(http, http->uri);
     debug(33, 5) ("parseHttpRequest: Complete request received\n");
     xfree(inbuf);
     result->flags.parsed_ok = 1;
     return result;
+
 }
 
 static int
@@ -1778,7 +1823,8 @@ clientProcessRequest(ConnStateData *conn, ClientSocketContext *context, method_t
     /* compile headers */
     /* we should skip request line! */
     if (!httpRequestParseHeader(request, prefix + req_line_sz))
-        debug(33, 1) ("Failed to parse request headers: %s\n%s\n",
+       if (http->http_ver.major >= 1)
+           debug(33, 1) ("Failed to parse request headers: %s\n%s\n",
                       http->uri, prefix);
     /* continue anyway? */
 
@@ -2059,12 +2105,15 @@ clientProcessBody(ConnStateData * conn)
        conn->body.buf = NULL;
        conn->body.bufsize = 0;
        /* Remember that we have touched the body, not restartable */
-       if (request != NULL)
+       if (request != NULL) {
            request->flags.body_sent = 1;
+           conn->body.request = NULL;
+       }
        /* Invoke callback function */
        callback(buf, size, cbdata);
-       if (request != NULL)
+       if (request != NULL) {
            requestUnlink(request);     /* Linked in clientReadBody */
+       }
        debug(33, 2) ("clientProcessBody: end fd=%d size=%lu body_size=%lu in.notYetUsed=%lu cb=%p req=%p\n",
            conn->fd, (unsigned long int)size, (unsigned long int) conn->body.size_left,
            (unsigned long) conn->in.notYetUsed, callback, request);
@@ -2203,7 +2252,7 @@ httpAcceptDefer(int fdunused, void *dataunused)
 }
 
 ConnStateData *
-connStateCreate(struct sockaddr_in *peer, struct sockaddr_in *me, int fd)
+connStateCreate(struct sockaddr_in *peer, struct sockaddr_in *me, int fd, http_port_list *port)
 {
     ConnStateData *result = cbdataAlloc(ConnStateData);
     result->peer = *peer;
@@ -2212,6 +2261,14 @@ connStateCreate(struct sockaddr_in *peer, struct sockaddr_in *me, int fd)
     result->me = *me;
     result->fd = fd;
     result->in.buf = (char *)memAllocBuf(CLIENT_REQ_BUF_SZ, &result->in.allocatedSize);
+    result->port = cbdataReference(port);
+    if (port->transparent) {
+       struct sockaddr_in dst;
+       if (clientNatLookup(fd, *me, *peer, &dst) == 0) {
+           result->me = dst; /* XXX This should be moved to another field */
+           result->transparent = 1;
+       }
+    }
     result->flags.readMoreRequests = 1;
     return result;
 }
@@ -2221,7 +2278,7 @@ void
 httpAccept(int sock, int newfd, ConnectionDetail *details,
   comm_err_t flag, int xerrno, void *data)
 {
-    int *N = &incoming_sockets_accepted;
+    http_port_list *s = (http_port_list *)data;
     ConnStateData *connState = NULL;
 
     if (flag == COMM_ERR_CLOSING) {
@@ -2229,7 +2286,7 @@ httpAccept(int sock, int newfd, ConnectionDetail *details,
     }
 
     /* kick off another one for later */
-    comm_accept(sock, httpAccept, NULL);
+    comm_accept(sock, httpAccept, data);
 
     /* XXX we're not considering httpAcceptDefer yet! */
 
@@ -2241,7 +2298,9 @@ httpAccept(int sock, int newfd, ConnectionDetail *details,
        }
        
        debug(33, 4) ("httpAccept: FD %d: accepted\n", newfd);
-       connState = connStateCreate(&details->peer, &details->me, newfd);
+       fd_note(newfd, "client http connect");
+       connState = connStateCreate(&details->peer, &details->me, newfd, s);
+       connState->port = cbdataReference(s);
        comm_add_close_handler(newfd, connStateFree, connState);
        if (Config.onoff.log_fqdn)
            fqdncache_gethostbyaddr(details->peer.sin_addr, FQDN_LOOKUP_IF_MISS);
@@ -2257,8 +2316,7 @@ httpAccept(int sock, int newfd, ConnectionDetail *details,
        clientReadSomeData(connState);
        commSetDefer(newfd, clientReadDefer, connState);
        clientdbEstablished(details->peer.sin_addr, 1);
-       assert(N);
-       (*N)++;
+       incoming_sockets_accepted++;
 }
 
 #if USE_SSL
@@ -2308,20 +2366,13 @@ clientNegotiateSSL(int fd, void *data)
     clientReadSomeData(conn);
 }
 
-struct _https_port_data {
-    SSL_CTX *sslContext;
-};
-typedef struct _https_port_data https_port_data;
-CBDATA_TYPE(https_port_data);
-
 /* handle a new HTTPS connection */
 static void
 httpsAccept(int sock, int newfd, ConnectionDetail *details,
   comm_err_t flag, int xerrno, void *data)
 {
-    int *N = &incoming_sockets_accepted;
-    https_port_data *https_port = (https_port_data *)data;
-    SSL_CTX *sslContext = https_port->sslContext;
+    https_port_list *s = (https_port_list *)data;
+    SSL_CTX *sslContext = s->sslContext;
     ConnStateData *connState = NULL;
     SSL *ssl;
     int ssl_error;
@@ -2349,9 +2400,10 @@ httpsAccept(int sock, int newfd, ConnectionDetail *details,
     fd_table[newfd].read_method = &ssl_read_method;
     fd_table[newfd].write_method = &ssl_write_method;
     debug(50, 5) ("httpsAccept: FD %d accepted, starting SSL negotiation.\n", newfd);
+    fd_note(newfd, "client https connect");
     
-    connState = connStateCreate(&details->peer, &details->me, newfd);
-    /* XXX account connState->in.buf */
+    connState = connStateCreate(&details->peer, &details->me, newfd, (http_port_list *)s);
+    connState->port = (http_port_list *)cbdataReference(s);
     comm_add_close_handler(newfd, connStateFree, connState);
     if (Config.onoff.log_fqdn)
        fqdncache_gethostbyaddr(details->peer.sin_addr, FQDN_LOOKUP_IF_MISS);
@@ -2367,7 +2419,7 @@ httpsAccept(int sock, int newfd, ConnectionDetail *details,
     commSetSelect(newfd, COMM_SELECT_READ, clientNegotiateSSL, connState, 0);
     commSetDefer(newfd, clientReadDefer, connState);
     clientdbEstablished(details->peer.sin_addr, 1);
-    (*N)++;
+    incoming_sockets_accepted++;
 }
 
 #endif /* USE_SSL */
@@ -2376,7 +2428,7 @@ httpsAccept(int sock, int newfd, ConnectionDetail *details,
 static void
 clientHttpConnectionsOpen(void)
 {
-    sockaddr_in_list *s;
+    http_port_list *s;
     int fd;
     for (s = Config.Sockaddr.http; s; s = s->next) {
        if (MAXHTTPPORTS == NHttpSockets) {
@@ -2393,7 +2445,7 @@ clientHttpConnectionsOpen(void)
        if (fd < 0)
            continue;
        comm_listen(fd);
-       comm_accept(fd, httpAccept, NULL);
+       comm_accept(fd, httpAccept, s);
        /*
         * We need to set a defer handler here so that we don't
         * peg the CPU with select() when we hit the FD limit.
@@ -2410,9 +2462,8 @@ static void
 clientHttpsConnectionsOpen(void)
 {
     https_port_list *s;
-    https_port_data *https_port;
     int fd;
-    for (s = Config.Sockaddr.https; s; s = s->next) {
+    for (s = Config.Sockaddr.https; s; s = (https_port_list *)s->http.next) {
        if (MAXHTTPPORTS == NHttpSockets) {
            debug(1, 1) ("WARNING: You have too many 'https_port' lines.\n");
            debug(1, 1) ("         The limit is %d\n", MAXHTTPPORTS);
@@ -2421,19 +2472,16 @@ clientHttpsConnectionsOpen(void)
        enter_suid();
        fd = comm_open(SOCK_STREAM,
            0,
-           s->s.sin_addr,
-           ntohs(s->s.sin_port), COMM_NONBLOCKING, "HTTPS Socket");
+           s->http.s.sin_addr,
+           ntohs(s->http.s.sin_port), COMM_NONBLOCKING, "HTTPS Socket");
        leave_suid();
        if (fd < 0)
            continue;
-       CBDATA_INIT_TYPE(https_port_data);
-       https_port = cbdataAlloc(https_port_data);
-       https_port->sslContext = s->sslContext;
        comm_listen(fd);
-       comm_accept(fd, httpsAccept, https_port);
+       comm_accept(fd, httpsAccept, s);
        commSetDefer(fd, httpAcceptDefer, NULL);
        debug(1, 1) ("Accepting HTTPS connections at %s, port %d, FD %d.\n",
-           inet_ntoa(s->s.sin_addr), (int) ntohs(s->s.sin_port), fd);
+           inet_ntoa(s->http.s.sin_addr), (int) ntohs(s->http.s.sin_port), fd);
        HttpSockets[NHttpSockets++] = fd;
     }
 }
index 2ccb244d0709717f69926a41c2c2c15df29f2512..f3ed03b4aebbdad7cb6c927f4ff0abd7f6a6675e 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side_request.cc,v 1.16 2003/02/13 08:07:47 robertc Exp $
+ * $Id: client_side_request.cc,v 1.17 2003/02/21 19:53:01 hno Exp $
  * 
  * DEBUG: section 85    Client-side Request Routines
  * AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c)
@@ -107,7 +107,6 @@ ClientRequestContext::deleteSelf() const
 
 /* Local functions */
 /* other */
-static int checkAccelOnly(clientHttpRequest *);
 static void clientAccessCheckDone(int, void *);
 static int clientCachable(clientHttpRequest * http);
 static int clientHierarchical(clientHttpRequest * http);
@@ -312,38 +311,11 @@ clientBeginRequest(method_t method, char const *url, CSCB * streamcallback,
     return 0;
 }
 
-static int
-checkAccelOnly(clientHttpRequest * http)
-{
-    /*
-     * return TRUE if someone makes a proxy request to us and we are in
-     * httpd-accel only mode
-     */
-    if (!Config2.Accel.on)
-       return 0;
-    if (Config.onoff.accel_with_proxy)
-       return 0;
-    if (http->request->protocol == PROTO_CACHEOBJ)
-       return 0;
-    if (http->flags.accel)
-       return 0;
-    if (http->request->method == METHOD_PURGE)
-       return 0;
-    return 1;
-}
-
 /* This is the entry point for external users of the client_side routines */
 void
 clientAccessCheck(ClientHttpRequest *http)
 {
     ClientRequestContext *context = new ClientRequestContext(http);
-    if (checkAccelOnly(http)) {
-       /* deny proxy requests in accel_only mode */
-       debug(85,
-           1) ("clientAccessCheck: proxy request denied in accel_only mode\n");
-       clientAccessCheckDone(ACCESS_DENIED, context);
-       return;
-    }
     context->acl_checklist =
        clientAclChecklistCreate(Config.accessList.http, http);
     context->acl_checklist->nonBlockingCheck(clientAccessCheckDone, context);
@@ -667,7 +639,7 @@ clientRedirectDone(void *data, char *result)
        new_request->client_addr = old_request->client_addr;
        new_request->my_addr = old_request->my_addr;
        new_request->my_port = old_request->my_port;
-       new_request->flags.redirected = 1;
+       new_request->flags = old_request->flags;
        if (old_request->auth_user_request) {
            new_request->auth_user_request = old_request->auth_user_request;
            authenticateAuthUserRequestLock(new_request->auth_user_request);
index fbbb948511625aeed48d976121f035d1ff0df8c0..4258505661e3b79b3223fc81a460490f7e12f0fd 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: forward.cc,v 1.95 2003/02/15 00:15:51 hno Exp $
+ * $Id: forward.cc,v 1.96 2003/02/21 19:53:01 hno Exp $
  *
  * DEBUG: section 17    Request Forwarding
  * AUTHOR: Duane Wessels
@@ -436,12 +436,6 @@ fwdConnectStart(void *data)
        port = fs->_peer->http_port;
        ctimeout = fs->_peer->connect_timeout > 0 ? fs->_peer->connect_timeout
            : Config.Timeout.peer_connect;
-    } else if (fwdState->request->flags.accelerated &&
-       !fwdState->request->flags.internalclient &&
-       Config.Accel.single_host && Config.Accel.host) {
-       host = Config.Accel.host;
-       port = Config.Accel.port;
-       ctimeout = Config.Timeout.connect;
     } else {
        host = fwdState->request->host;
        port = fwdState->request->port;
index f918df8fe269c4cb12a73622af57633e3d30988a..3f5e076bb6cc7a38131b7ccabc60cdeaf30b5bb5 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: globals.h,v 1.118 2003/01/23 00:37:21 robertc Exp $
+ * $Id: globals.h,v 1.119 2003/02/21 19:53:01 hno Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -100,8 +100,6 @@ extern int theInSnmpConnection;     /* -1 */
 extern int theOutSnmpConnection;       /* -1 */
 extern char *snmp_agentinfo;
 #endif
-extern int vhost_mode;         /* 0 */
-extern int vport_mode;         /* 0 */
 extern int n_disk_objects;     /* 0 */
 extern iostats IOStats;
 extern struct _acl_deny_info_list *DenyInfoList;       /* NULL */
index c08637d7516e01a53aa09f8e0901640959bf7ce1..38feda3a7ffb75b407dbc2262225c0eee5699230 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: main.cc,v 1.366 2003/02/15 18:13:35 hno Exp $
+ * $Id: main.cc,v 1.367 2003/02/21 19:53:01 hno Exp $
  *
  * DEBUG: section 1     Startup and Main Loop
  * AUTHOR: Harvest Derived
@@ -137,7 +137,14 @@ mainParseOptions(int argc, char *argv[])
            opt_store_doublecheck = 1;
            break;
        case 'V':
-           vhost_mode = 1;
+           if (Config.Sockaddr.http)
+               Config.Sockaddr.http->vhost = 1;
+#if USE_SSL
+           else if (Config.Sockaddr.https)
+               Config.Sockaddr.https->http.vhost = 1;
+#endif
+           else
+               fatal("No http_port specified\n");
            break;
        case 'X':
            /* force full debugging */
@@ -147,7 +154,7 @@ mainParseOptions(int argc, char *argv[])
            opt_reload_hit_only = 1;
            break;
        case 'a':
-           parse_sockaddr_in_list_token(&Config.Sockaddr.http, optarg);
+           add_http_port(optarg);
            break;
        case 'd':
            opt_debug_stderr = atoi(optarg);
index 64f73487500b1fac0989c57e565244be7f63a131..9dac74d60e5b93493ee5232d57970f43d86a74f4 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: neighbors.cc,v 1.315 2003/02/15 18:13:36 hno Exp $
+ * $Id: neighbors.cc,v 1.316 2003/02/21 19:53:02 hno Exp $
  *
  * DEBUG: section 15    Neighbor Routines
  * AUTHOR: Harvest Derived
@@ -421,7 +421,7 @@ neighbors_init(void)
        if (getsockname(fd, (struct sockaddr *) &name, &len) < 0)
            debug(15, 1) ("getsockname(%d,%p,%p) failed.\n", fd, &name, &len);
        for (thisPeer = Config.peers; thisPeer; thisPeer = next) {
-           sockaddr_in_list *s;
+           http_port_list *s;
            next = thisPeer->next;
            if (0 != strcmp(thisPeer->host, me))
                continue;
@@ -1120,7 +1120,7 @@ peerProbeConnect(peer * p)
     int fd;
     if (p->test_fd != -1)
        return;                 /* probe already running */
-    if (squid_curtime - p->stats.last_connect_probe < Config.Timeout.connect)
+    if (squid_curtime - p->stats.last_connect_probe < 1)
        return;                 /* don't probe to often */
     fd = comm_open(SOCK_STREAM, 0, getOutgoingAddr(NULL),
        0, COMM_NONBLOCKING, p->host);
index 2d1388ce64ffda1a3705c0c00bc6739543ca3409..19bcb95b207256abe6457c5c3302521f10bf9cdc 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: peer_select.cc,v 1.127 2003/02/13 08:07:48 robertc Exp $
+ * $Id: peer_select.cc,v 1.128 2003/02/21 19:53:02 hno Exp $
  *
  * DEBUG: section 44    Peer Selection Algorithm
  * AUTHOR: Duane Wessels
@@ -266,6 +266,8 @@ peerSelectFoo(ps_state * ps)
            return;
        } else if (ps->never_direct > 0) {
            ps->direct = DIRECT_NO;
+       } else if (request->flags.accelerated) {
+           ps->direct = DIRECT_NO;
        } else if (request->flags.loopdetect) {
            ps->direct = DIRECT_YES;
        } else if (peerCheckNetdbDirect(ps)) {
index 145c4a81a982786afb3de5a98e01ff040cde9301..da446141c30e19eb4e4725bda68439ff2efb16e9 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: protos.h,v 1.466 2003/02/15 18:13:36 hno Exp $
+ * $Id: protos.h,v 1.467 2003/02/21 19:53:02 hno Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -67,6 +67,8 @@ SQUIDCEXTERN void wordlistCat(const wordlist *, MemBuf * mb);
 SQUIDCEXTERN void allocate_new_swapdir(cacheSwap *);
 SQUIDCEXTERN void self_destruct(void);
 SQUIDCEXTERN int GetInteger(void);
+SQUIDCEXTERN void add_http_port(char *portspec);
+
 
 /* extra functions from cache_cf.c useful for lib modules */
 SQUIDCEXTERN void parse_int(int *var);
index 258f2309e3b2af4f01a10f7f34f7fa30d8acdc66..e9f47ad52a46436e65dee8e5cd91658bcc13582d 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: structs.h,v 1.450 2003/02/17 07:01:37 robertc Exp $
+ * $Id: structs.h,v 1.451 2003/02/21 19:53:02 hno Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -162,10 +162,21 @@ struct _sockaddr_in_list {
     sockaddr_in_list *next;
 };
 
+struct _http_port_list {
+    http_port_list *next;
+    struct sockaddr_in s;
+    char *protocol;            /* protocol name */
+    char *name;                        /* visible name */
+    char *defaultsite;         /* default web site */
+    unsigned int transparent:1;        /* transparent proxy */
+    unsigned int accel:1;      /* HTTP accelerator */
+    unsigned int vhost:1;      /* uses host header */
+    int vport;                 /* virtual port support, -1 for dynamic, >0 static*/
+};
+
 #if USE_SSL
 struct _https_port_list {
-    https_port_list *next;
-    struct sockaddr_in s;
+    http_port_list http;       /* must be first */
     char *cert;
     char *key;
     int version;
@@ -254,7 +265,7 @@ struct _SquidConfig {
 #endif
     } Port;
     struct {
-       sockaddr_in_list *http;
+       http_port_list *http;
 #if USE_SSL
        https_port_list *https;
 #endif
@@ -313,11 +324,6 @@ struct _SquidConfig {
     time_t authenticateGCInterval;
     time_t authenticateTTL;
     time_t authenticateIpTTL;
-    struct {
-       int single_host;
-       char *host;
-       u_short port;
-    } Accel;
     char *appendDomain;
     size_t appendDomainLen;
     char *debugOptions;
@@ -391,7 +397,6 @@ struct _SquidConfig {
        int log_mime_hdrs;
        int log_fqdn;
        int announce;
-       int accel_with_proxy;
        int mem_pools;
        int test_reachability;
        int half_closed_clients;
@@ -531,10 +536,6 @@ struct _SquidConfig {
 };
 
 struct _SquidConfig2 {
-    struct {
-       char *prefix;
-       int on;
-    } Accel;
     struct {
        int enable_purge;
     } onoff;
@@ -808,6 +809,8 @@ struct _ConnStateData {
        int readMoreRequests:1;
     } flags;
     bool reading;
+    http_port_list *port;
+    int transparent;
 };
 
 struct _ipcache_addrs {
index e206ea4007e1b3da60d4614595066a90a47314b9..00fbb99d87bab0710e4308aca85c8deb788aa643 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: tools.cc,v 1.231 2003/02/08 02:32:53 robertc Exp $
+ * $Id: tools.cc,v 1.232 2003/02/21 19:53:02 hno Exp $
  *
  * DEBUG: section 21    Misc Functions
  * AUTHOR: Harvest Derived
@@ -455,7 +455,7 @@ getMyHostname(void)
        memcpy(&sa, &Config.Sockaddr.http->s.sin_addr, sizeof(sa));
 #if USE_SSL
     if (Config.Sockaddr.https && sa.s_addr == any_addr.s_addr)
-       memcpy(&sa, &Config.Sockaddr.https->s.sin_addr, sizeof(sa));
+       memcpy(&sa, &Config.Sockaddr.https->http.s.sin_addr, sizeof(sa));
 #endif
     /*
      * If the first http_port address has a specific address, try a
@@ -1006,7 +1006,7 @@ getMyPort(void)
        return ntohs(Config.Sockaddr.http->s.sin_port);
 #if USE_SSL
     if (Config.Sockaddr.https)
-       return ntohs(Config.Sockaddr.https->s.sin_port);
+       return ntohs(Config.Sockaddr.https->http.s.sin_port);
 #endif
     fatal("No port defined");
     return 0;                  /* NOT REACHED */
index 23f3a84591b34062acdd758f81729e80a374ba68..e35071bb24c6899a0649aa9493eddc550d62a5bc 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: typedefs.h,v 1.151 2003/02/14 13:59:50 robertc Exp $
+ * $Id: typedefs.h,v 1.152 2003/02/21 19:53:02 hno Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -71,6 +71,7 @@ typedef struct _intrange intrange;
 typedef struct _ushortlist ushortlist;
 typedef struct _relist relist;
 typedef struct _sockaddr_in_list sockaddr_in_list;
+typedef struct _http_port_list http_port_list;
 typedef struct _https_port_list https_port_list;
 typedef struct _SquidConfig SquidConfig;
 typedef struct _SquidConfig2 SquidConfig2;