#include "squid.h"
#include "anyp/PortCfg.h"
#include "comm.h"
-#if HAVE_LIMITS
-#include <limits>
-#endif
+#include "fatal.h"
#if USE_SSL
#include "ssl/support.h"
#endif
+#include <cstring>
+#if HAVE_LIMITS
+#include <limits>
+#endif
+
CBDATA_NAMESPACED_CLASS_INIT(AnyP, PortCfg);
int NHttpSockets = 0;
int HttpSockets[MAXTCPLISTENPORTS];
-AnyP::PortCfg::PortCfg(const char *aProtocol) :
+AnyP::PortCfg::PortCfg() :
next(NULL),
- protocol(xstrdup(aProtocol)),
+ transport(AnyP::PROTO_HTTP,1,1), // "Squid is an HTTP proxy", etc.
name(NULL),
defaultsite(NULL)
#if USE_SSL
safe_free(name);
safe_free(defaultsite);
- safe_free(protocol);
#if USE_SSL
safe_free(cert);
AnyP::PortCfg *
AnyP::PortCfg::clone() const
{
- AnyP::PortCfg *b = new AnyP::PortCfg(protocol);
-
+ AnyP::PortCfg *b = new AnyP::PortCfg();
b->s = s;
if (name)
b->name = xstrdup(name);
if (defaultsite)
b->defaultsite = xstrdup(defaultsite);
+ b->transport = transport;
b->flags = flags;
b->allow_direct = allow_direct;
b->vhost = vhost;
if (!signingCert) {
char buf[128];
- fatalf("No valid signing SSL certificate configured for %s_port %s", protocol, s.toUrl(buf, sizeof(buf)));
+ fatalf("No valid signing SSL certificate configured for %s_port %s", AnyP::ProtocolType_str[transport.protocol], s.toUrl(buf, sizeof(buf)));
}
if (!signPkey)
- debugs(3, DBG_IMPORTANT, "No SSL private key configured for " << protocol << "_port " << s);
+ debugs(3, DBG_IMPORTANT, "No SSL private key configured for " << AnyP::ProtocolType_str[transport.protocol] << "_port " << s);
Ssl::generateUntrustedCert(untrustedSigningCert, untrustedSignPkey,
signingCert, signPkey);
if (!untrustedSigningCert) {
char buf[128];
- fatalf("Unable to generate signing SSL certificate for untrusted sites for %s_port %s", protocol, s.toUrl(buf, sizeof(buf)));
+ fatalf("Unable to generate signing SSL certificate for untrusted sites for %s_port %s", AnyP::ProtocolType_str[transport.protocol], s.toUrl(buf, sizeof(buf)));
}
if (crlfile)
if (!staticSslContext) {
char buf[128];
- fatalf("%s_port %s initialization error", protocol, s.toUrl(buf, sizeof(buf)));
+ fatalf("%s_port %s initialization error", AnyP::ProtocolType_str[transport.protocol], s.toUrl(buf, sizeof(buf)));
}
}
#endif
+void
+AnyP::PortCfg::setTransport(const char *aProtocol)
+{
+ // HTTP/1.0 not supported because we are version 1.1 which contains a superset of 1.0
+ // and RFC 2616 requires us to upgrade 1.0 to 1.1
+
+ if (strcasecmp("http", aProtocol) != 0 || strcmp("HTTP/1.1", aProtocol) != 0)
+ transport = AnyP::ProtocolVersion(AnyP::PROTO_HTTP, 1,1);
+
+ else if (strcasecmp("https", aProtocol) != 0 || strcmp("HTTPS/1.1", aProtocol) != 0)
+ transport = AnyP::ProtocolVersion(AnyP::PROTO_HTTPS, 1,1);
+
+ else
+ fatalf("http(s)_port protocol=%s is not supported\n", aProtocol);
+}
#define SQUID_ANYP_PORTCFG_H
#include "anyp/forward.h"
+#include "anyp/ProtocolVersion.h"
#include "anyp/TrafficMode.h"
#include "comm/Connection.h"
class PortCfg
{
public:
- PortCfg(const char *aProtocol);
+ PortCfg();
~PortCfg();
AnyP::PortCfg *clone() const;
#if USE_SSL
void configureSslServerContext();
#endif
+ /**
+ * Set this ports transport type from a string representation.
+ * Unknown transport type representations will halt Squid.
+ * Supports: HTTP, HTTP/1.1, HTTPS, HTTPS/1.1.
+ */
+ void setTransport(const char *aProtocol);
+
PortCfg *next;
Ip::Address s;
- char *protocol; /* protocol name */
+ AnyP::ProtocolVersion transport; ///< transport protocol and version received by this port
char *name; /* visible name */
char *defaultsite; /* default web site */
inline std::ostream &
operator << (std::ostream &os, const AnyP::ProtocolVersion &v)
{
- return (os << AnyP::ProtocolType_str[v.protocol] << v.major << '.' << v.minor);
+ return (os << AnyP::ProtocolType_str[v.protocol] << '/' << v.major << '.' << v.minor);
}
#endif /* SQUID_ANYP_PROTOCOLVERSION_H */
#include "wordlist.h"
#include "neighbors.h"
#include "tools.h"
+#include "URLScheme.h"
/* wccp2 has its own conditional definitions */
#include "wccp2.h"
#if USE_ADAPTATION
s->name = xstrdup(token);
s->connection_auth_disabled = false;
+ const char *portType = URLScheme(s->transport.protocol).const_str();
+
if (*token == '[') {
/* [ipv6]:port */
host = token + 1;
t = strchr(host, ']');
if (!t) {
- debugs(3, DBG_CRITICAL, s->protocol << "_port: missing ']' on IPv6 address: " << token);
+ debugs(3, DBG_CRITICAL, "FATAL: " << portType << "_port: missing ']' on IPv6 address: " << token);
self_destruct();
}
*t = '\0';
++t;
if (*t != ':') {
- debugs(3, DBG_CRITICAL, s->protocol << "_port: missing Port in: " << token);
+ debugs(3, DBG_CRITICAL, "FATAL: " << portType << "_port: missing Port in: " << token);
self_destruct();
}
if (!Ip::EnableIpv6) {
- debugs(3, DBG_CRITICAL, "FATAL: " << s->protocol << "_port: IPv6 is not available.");
+ debugs(3, DBG_CRITICAL, "FATAL: " << portType << "_port: IPv6 is not available.");
self_destruct();
}
port = xatos(t + 1);
} else if (strtol(token, &junk, 10) && !*junk) {
port = xatos(token);
- debugs(3, 3, s->protocol << "_port: found Listen on Port: " << port);
+ debugs(3, 3, portType << "_port: found Listen on Port: " << port);
} else {
- debugs(3, DBG_CRITICAL, s->protocol << "_port: missing Port: " << token);
+ debugs(3, DBG_CRITICAL, "FATAL: " << portType << "_port: missing Port: " << token);
self_destruct();
}
if (port == 0 && host != NULL) {
- debugs(3, DBG_CRITICAL, s->protocol << "_port: Port cannot be 0: " << token);
+ debugs(3, DBG_CRITICAL, "FATAL: " << portType << "_port: Port cannot be 0: " << token);
self_destruct();
}
s->s.port(port);
if (!Ip::EnableIpv6)
s->s.setIPv4();
- debugs(3, 3, s->protocol << "_port: found Listen on wildcard address: *:" << s->s.port() );
+ debugs(3, 3, portType << "_port: found Listen on wildcard address: *:" << s->s.port());
} else if ( (s->s = host) ) { /* check/parse numeric IPA */
s->s.port(port);
if (!Ip::EnableIpv6)
s->s.setIPv4();
- debugs(3, 3, s->protocol << "_port: Listen on Host/IP: " << host << " --> " << s->s);
+ debugs(3, 3, portType << "_port: Listen on Host/IP: " << host << " --> " << s->s);
} else if ( s->s.GetHostByName(host) ) { /* check/parse for FQDN */
/* dont use ipcache */
s->defaultsite = xstrdup(host);
s->s.port(port);
if (!Ip::EnableIpv6)
s->s.setIPv4();
- debugs(3, 3, s->protocol << "_port: found Listen as Host " << s->defaultsite << " on IP: " << s->s);
+ debugs(3, 3, portType << "_port: found Listen as Host " << s->defaultsite << " on IP: " << s->s);
} else {
- debugs(3, DBG_CRITICAL, s->protocol << "_port: failed to resolve Host/IP: " << host);
+ debugs(3, DBG_CRITICAL, "FATAL: " << portType << "_port: failed to resolve Host/IP: " << host);
self_destruct();
}
}
debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: protocol option requires Acceleration mode flag.");
self_destruct();
}
- s->protocol = xstrdup(token + 9);
+ s->setTransport(token + 9);
} else if (strcmp(token, "allow-direct") == 0) {
if (!s->flags.accelSurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: allow-direct option requires Acceleration mode flag.");
void
add_http_port(char *portspec)
{
- AnyP::PortCfg *s = new AnyP::PortCfg("http_port");
+ AnyP::PortCfg *s = new AnyP::PortCfg();
+ s->setTransport("HTTP");
parsePortSpecification(s, portspec);
// we may need to merge better if the above returns a list with clones
assert(s->next == NULL);
return;
}
- AnyP::PortCfg *s = new AnyP::PortCfg(protocol);
+ AnyP::PortCfg *s = new AnyP::PortCfg();
+ s->setTransport(protocol);
parsePortSpecification(s, token);
/* parse options ... */
}
#if USE_SSL
- if (strcmp(protocol, "https") == 0) {
+ if (transport.protocol == AnyP::PROTO_HTTPS) {
/* ssl-bump on https_port configuration requires either tproxy or intercept, and vice versa */
const bool hijacked = s->flags.isIntercepted();
if (s->flags.tunnelSslBumping && !hijacked) {
// clone the port options from *s to *(s->next)
s->next = cbdataReference(s->clone());
s->next->s.setIPv4();
- debugs(3, 3, protocol << "_port: clone wildcard address for split-stack: " << s->s << " and " << s->next->s);
+ debugs(3, 3, URLScheme(s->transport.protocol) << "_port: clone wildcard address for split-stack: " << s->s << " and " << s->next->s);
}
while (*head)
if (s->defaultsite)
storeAppendPrintf(e, " defaultsite=%s", s->defaultsite);
- if (s->protocol && strcmp(s->protocol,"http") != 0)
- storeAppendPrintf(e, " protocol=%s", s->protocol);
+ // TODO: compare against prefix of 'n' instead of assuming http_port
+ if (s->transport.protocol != AnyP::PROTO_HTTP)
+ storeAppendPrintf(e, " protocol=%s", URLScheme(s->transport.protocol).const_str());
if (s->allow_direct)
storeAppendPrintf(e, " allow-direct");
strlen(host);
http->uri = (char *)xcalloc(url_sz, 1);
const char *protocol = switchedToHttps ?
- "https" : conn->port->protocol;
+ "https" : URLScheme(conn->port->transport.protocol).const_str();
snprintf(http->uri, url_sz, "%s://%s%s", protocol, host, url);
debugs(33, 5, "ACCEL VHOST REWRITE: '" << http->uri << "'");
} else if (conn->port->defaultsite /* && !vhost */) {
snprintf(vportStr, sizeof(vportStr),":%d",vport);
}
snprintf(http->uri, url_sz, "%s://%s%s%s",
- conn->port->protocol, conn->port->defaultsite, vportStr, url);
+ URLScheme(conn->port->transport.protocol).const_str(), conn->port->defaultsite, vportStr, url);
debugs(33, 5, "ACCEL DEFAULTSITE REWRITE: '" << http->uri <<"'");
} else if (vport > 0 /* && (!vhost || no Host:) */) {
debugs(33, 5, "ACCEL VPORT REWRITE: http_port IP + vport=" << vport);
http->uri = (char *)xcalloc(url_sz, 1);
http->getConn()->clientConnection->local.toHostStr(ipbuf,MAX_IPSTRLEN);
snprintf(http->uri, url_sz, "%s://%s:%d%s",
- http->getConn()->port->protocol,
+ URLScheme(conn->port->transport.protocol).const_str(),
ipbuf, vport, url);
debugs(33, 5, "ACCEL VPORT REWRITE: '" << http->uri << "'");
}
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);
+ snprintf(http->uri, url_sz, "%s://%s%s", URLScheme(conn->port->transport.protocol).const_str(), host, url);
debugs(33, 5, "TRANSPARENT HOST REWRITE: '" << http->uri <<"'");
} else {
/* Put the local socket IP address as the hostname. */
http->uri = (char *)xcalloc(url_sz, 1);
http->getConn()->clientConnection->local.toHostStr(ipbuf,MAX_IPSTRLEN);
snprintf(http->uri, url_sz, "%s://%s:%d%s",
- http->getConn()->port->protocol,
+ URLScheme(http->getConn()->port->transport.protocol).const_str(),
ipbuf, http->getConn()->clientConnection->local.port(), url);
debugs(33, 5, "TRANSPARENT REWRITE: '" << http->uri << "'");
}
/* deny CONNECT via accelerated ports */
if (*method_p == Http::METHOD_CONNECT && csd->port && csd->port->flags.accelSurrogate) {
- debugs(33, DBG_IMPORTANT, "WARNING: CONNECT method received on " << csd->port->protocol << " Accelerator port " << csd->port->s.port() );
+ debugs(33, DBG_IMPORTANT, "WARNING: CONNECT method received on " << csd->port->transport.protocol << " Accelerator port " << csd->port->s.port());
/* XXX need a way to say "this many character length string" */
debugs(33, DBG_IMPORTANT, "WARNING: for request: " << hp->buf);
hp->request_parse_status = Http::scMethodNotAllowed;