From: hno <> Date: Sat, 22 Feb 2003 02:53:01 +0000 (+0000) Subject: Merge of http(s)_port and accelerator directive updates from rproxy X-Git-Tag: SQUID_3_0_PRE1~322 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3f38a55eeb138e3bfd7d9b67cbc982d167599837;p=thirdparty%2Fsquid.git Merge of http(s)_port and accelerator directive updates from rproxy - 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. --- diff --git a/src/IPInterception.cc b/src/IPInterception.cc index 93f61ea74d..1c5affcacd 100644 --- a/src/IPInterception.cc +++ b/src/IPInterception.cc @@ -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 @@ -78,23 +78,15 @@ #include #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 + diff --git a/src/IPInterception.h b/src/IPInterception.h index 38329a0dcf..d112968343 100644 --- a/src/IPInterception.h +++ b/src/IPInterception.h @@ -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 */ diff --git a/src/cache_cf.cc b/src/cache_cf.cc index e25d43fadd..20b416617e 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -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(); } diff --git a/src/cf.data.pre b/src/cf.data.pre index 0035c71a8c..192779044e 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -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 ----------------------------------------------------------------------------- diff --git a/src/client_side.cc b/src/client_side.cc index 2804199187..bce471e69a 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -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; } } diff --git a/src/client_side_request.cc b/src/client_side_request.cc index 2ccb244d07..f3ed03b4ae 100644 --- a/src/client_side_request.cc +++ b/src/client_side_request.cc @@ -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); diff --git a/src/forward.cc b/src/forward.cc index fbbb948511..4258505661 100644 --- a/src/forward.cc +++ b/src/forward.cc @@ -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; diff --git a/src/globals.h b/src/globals.h index f918df8fe2..3f5e076bb6 100644 --- a/src/globals.h +++ b/src/globals.h @@ -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 */ diff --git a/src/main.cc b/src/main.cc index c08637d751..38feda3a7f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -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); diff --git a/src/neighbors.cc b/src/neighbors.cc index 64f7348750..9dac74d60e 100644 --- a/src/neighbors.cc +++ b/src/neighbors.cc @@ -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); diff --git a/src/peer_select.cc b/src/peer_select.cc index 2d1388ce64..19bcb95b20 100644 --- a/src/peer_select.cc +++ b/src/peer_select.cc @@ -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)) { diff --git a/src/protos.h b/src/protos.h index 145c4a81a9..da446141c3 100644 --- a/src/protos.h +++ b/src/protos.h @@ -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); diff --git a/src/structs.h b/src/structs.h index 258f2309e3..e9f47ad52a 100644 --- a/src/structs.h +++ b/src/structs.h @@ -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 { diff --git a/src/tools.cc b/src/tools.cc index e206ea4007..00fbb99d87 100644 --- a/src/tools.cc +++ b/src/tools.cc @@ -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 */ diff --git a/src/typedefs.h b/src/typedefs.h index 23f3a84591..e35071bb24 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -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;