/*
- * $Id: cache_cf.cc,v 1.544 2008/03/04 12:00:36 amosjeffries Exp $
+ * $Id$
*
* DEBUG: section 3 Configuration File Parsing
* AUTHOR: Harvest Derived
*/
#include "squid.h"
-#include "authenticate.h"
#include "ProtoPort.h"
#include "HttpRequestMethod.h"
-#include "AuthConfig.h"
-#include "AuthScheme.h"
+#include "auth/Config.h"
+#include "auth/Scheme.h"
#include "CacheManager.h"
#include "Store.h"
#include "SwapDir.h"
#include "ConfigParser.h"
-#include "ACL.h"
+#include "acl/Acl.h"
+#include "acl/MethodData.h"
+#include "acl/Gadgets.h"
#include "StoreFileSystem.h"
#include "Parsing.h"
#include "MemBuf.h"
#include "wordlist.h"
+#include "ident/Config.h"
#include "ip/IpIntercept.h"
#if HAVE_GLOB_H
#include "snmp.h"
#endif
#if USE_SQUID_ESI
-#include "ESIParser.h"
+#include "esi/Parser.h"
#endif
#if USE_ADAPTATION
#include "adaptation/Config.h"
static void parse_adaptation_service_set_type();
+static void parse_adaptation_service_chain_type();
static void parse_adaptation_access_type();
#endif
#if ICAP_CLIENT
-#include "ICAP/ICAPConfig.h"
+#include "adaptation/icap/Config.h"
-static void parse_icap_service_type(ICAPConfig *);
-static void dump_icap_service_type(StoreEntry *, const char *, const ICAPConfig &);
-static void free_icap_service_type(ICAPConfig *);
+static void parse_icap_service_type(Adaptation::Icap::Config *);
+static void dump_icap_service_type(StoreEntry *, const char *, const Adaptation::Icap::Config &);
+static void free_icap_service_type(Adaptation::Icap::Config *);
static void parse_icap_class_type();
static void parse_icap_access_type();
#endif
#if USE_ECAP
-#include "eCAP/Config.h"
-static void parse_ecap_service_type(Ecap::Config *);
-static void dump_ecap_service_type(StoreEntry *, const char *, const Ecap::Config &);
-static void free_ecap_service_type(Ecap::Config *);
+#include "adaptation/ecap/Config.h"
+static void parse_ecap_service_type(Adaptation::Ecap::Config *);
+static void dump_ecap_service_type(StoreEntry *, const char *, const Adaptation::Ecap::Config &);
+static void free_ecap_service_type(Adaptation::Ecap::Config *);
#endif
CBDATA_TYPE(peer);
static void free_denyinfo(acl_deny_info_list ** var);
#if USE_WCCPv2
-static void parse_IPAddress_list(IPAddress_list **);
-static void dump_IPAddress_list(StoreEntry *, const char *, const IPAddress_list *);
-static void free_IPAddress_list(IPAddress_list **);
+static void parse_IpAddress_list(IpAddress_list **);
+static void dump_IpAddress_list(StoreEntry *, const char *, const IpAddress_list *);
+static void free_IpAddress_list(IpAddress_list **);
#if CURRENTLY_UNUSED
-static int check_null_IPAddress_list(const IPAddress_list *);
+static int check_null_IpAddress_list(const IpAddress_list *);
#endif /* CURRENTLY_UNUSED */
#endif /* USE_WCCPv2 */
configFreeMemory();
+ ACLMethodData::ThePurgeCount = 0;
default_all();
err_count = parseOneConfigFile(file_name, 0);
if (!Config.chroot_dir) {
leave_suid();
setUmask(Config.umask);
- _db_init(Config.Log.log, Config.debugOptions);
+ _db_init(Debug::cache_log, Debug::debugOptions);
enter_suid();
}
memConfigure();
/* Sanity checks */
+ if (Debug::rotateNumber < 0) {
+ Debug::rotateNumber = Config.Log.rotateNumber;
+ }
+
#if SIZEOF_OFF_T <= 4
if (Config.Store.maxObjectSize > 0x7FFF0000) {
debugs(3, 0, "WARNING: This Squid binary can not handle files larger than 2GB. Limiting maximum_object_size to just below 2GB");
else
Config.appendDomainLen = 0;
- safe_free(debug_options)
- debug_options = xstrdup(Config.debugOptions);
-
if (Config.retry.maxtries > 10)
fatal("maximum_single_addr_tries cannot be larger than 10");
break;
}
+ for (R = Config.Refresh; R; R = R->next) {
+ if (!R->flags.ignore_must_revalidate)
+ continue;
+ debugs(22, 1, "WARNING: use of 'ignore-must-revalidate' in 'refresh_pattern' violates HTTP");
+ break;
+ }
+
for (R = Config.Refresh; R; R = R->next) {
if (!R->flags.ignore_private)
continue;
#endif
- if (aclPurgeMethodInUse(Config.accessList.http))
- Config2.onoff.enable_purge = 1;
+ // we enable runtime PURGE checks if there is at least one PURGE method ACL
+ // TODO: replace with a dedicated "purge" ACL option?
+ Config2.onoff.enable_purge = (ACLMethodData::ThePurgeCount > 0);
Config2.onoff.mangle_request_headers = httpReqHdrManglersConfigured();
if (!strncasecmp(unit, B_GBYTES_STR, strlen(B_GBYTES_STR)))
return 1 << 30;
- debugs(3, 1, "parseBytesUnits: unknown bytes unit '" << unit << "'");
+ debugs(3, DBG_CRITICAL, "WARNING: Unknown bytes unit '" << unit << "'");
return 0;
}
}
static void
-dump_address(StoreEntry * entry, const char *name, IPAddress &addr)
+dump_address(StoreEntry * entry, const char *name, IpAddress &addr)
{
char buf[MAX_IPSTRLEN];
storeAppendPrintf(entry, "%s %s\n", name, addr.NtoA(buf,MAX_IPSTRLEN) );
}
static void
-parse_address(IPAddress *addr)
+parse_address(IpAddress *addr)
{
char *token = strtok(NULL, w_space);
}
static void
-free_address(IPAddress *addr)
+free_address(IpAddress *addr)
{
addr->SetEmpty();
}
for (i = 0; i < swap->n_configured; i++) {
assert (swap->swapDirs[i].getRaw());
- if ((strcasecmp(path_str, dynamic_cast<SwapDir *>(swap->swapDirs[i].getRaw())->path)
- ) == 0) {
+ if ((strcasecmp(path_str, dynamic_cast<SwapDir *>(swap->swapDirs[i].getRaw())->path)) == 0) {
/* this is specific to on-fs Stores. The right
* way to handle this is probably to have a mapping
* from paths to stores, and have on-fs stores
}
/* new cache_dir */
- assert(swap->n_configured < 63); /* 7 bits, signed */
+ if (swap->n_configured > 63) {
+ /* 7 bits, signed */
+ debugs(3, DBG_CRITICAL, "WARNING: There is a fixed maximum of 63 cache_dir entries Squid can handle.");
+ debugs(3, DBG_CRITICAL, "WARNING: '" << path_str << "' is one to many.");
+ self_destruct();
+ return;
+ }
allocate_new_swapdir(swap);
}
}
+/**
+ * utility function to prevent getservbyname() being called with a numeric value
+ * on Windows at least it returns garage results.
+ */
+static bool
+isUnsignedNumeric(const char *str, size_t len)
+{
+ if (len < 1) return false;
+
+ for (; len >0 && *str; str++, len--) {
+ if (! isdigit(*str))
+ return false;
+ }
+ return true;
+}
+
/**
\param proto 'tcp' or 'udp' for protocol
\returns Port the named service is supposed to be listening on.
return 0; /* NEVER REACHED */
}
/** Returns either the service port number from /etc/services */
- port = getservbyname(token, proto);
+ if ( !isUnsignedNumeric(token, strlen(token)) )
+ port = getservbyname(token, proto);
if (port != NULL) {
return ntohs((u_short)port->s_port);
}
rfc1738_unescape(p->login);
} else if (!strncasecmp(token, "connect-timeout=", 16)) {
p->connect_timeout = xatoi(token + 16);
+ } else if (!strncasecmp(token, "connect-fail-limit=", 19)) {
+ p->connect_fail_limit = xatoi(token + 19);
#if USE_CACHE_DIGESTS
-
} else if (!strncasecmp(token, "digest-url=", 11)) {
p->digest_url = xstrdup(token + 11);
#endif
if (p->weight < 1)
p->weight = 1;
+ if (p->connect_fail_limit < 1)
+ p->connect_fail_limit = 1;
+
p->icp.version = ICP_VERSION_CURRENT;
p->test_fd = -1;
if (head->flags.ignore_no_store)
storeAppendPrintf(entry, " ignore-no-store");
+ if (head->flags.ignore_must_revalidate)
+ storeAppendPrintf(entry, " ignore-must-revalidate");
+
if (head->flags.ignore_private)
storeAppendPrintf(entry, " ignore-private");
int ignore_reload = 0;
int ignore_no_cache = 0;
int ignore_no_store = 0;
+ int ignore_must_revalidate = 0;
int ignore_private = 0;
int ignore_auth = 0;
#endif
ignore_no_cache = 1;
else if (!strcmp(token, "ignore-no-store"))
ignore_no_store = 1;
+ else if (!strcmp(token, "ignore-must-revalidate"))
+ ignore_must_revalidate = 1;
else if (!strcmp(token, "ignore-private"))
ignore_private = 1;
else if (!strcmp(token, "ignore-auth"))
if (ignore_no_store)
t->flags.ignore_no_store = 1;
+ if (ignore_must_revalidate)
+ t->flags.ignore_must_revalidate = 1;
+
if (ignore_private)
t->flags.ignore_private = 1;
*var = 0;
}
-#if UNUSED_CODE
static void
dump_size_t(StoreEntry * entry, const char *name, size_t var)
{
storeAppendPrintf(entry, "%s %d\n", name, (int) var);
}
-#endif
static void
dump_b_size_t(StoreEntry * entry, const char *name, size_t var)
storeAppendPrintf(entry, "%s %"PRId64" %s\n", name, var, B_KBYTES_STR);
}
-#if UNUSED_CODE
static void
parse_size_t(size_t * var)
{
i = GetInteger();
*var = (size_t) i;
}
-#endif
static void
parse_b_size_t(size_t * var)
storeAppendPrintf(entry, "\n");
}
+static void
+free_memcachemode(SquidConfig * config)
+{
+ return;
+}
+
+static void
+parse_memcachemode(SquidConfig * config)
+{
+ char *token = strtok(NULL, w_space);
+ if (!token)
+ self_destruct();
+
+ if (strcmp(token, "always") == 0) {
+ Config.onoff.memory_cache_first = 1;
+ Config.onoff.memory_cache_disk = 1;
+ } else if (strcmp(token, "disk") == 0) {
+ Config.onoff.memory_cache_first = 0;
+ Config.onoff.memory_cache_disk = 1;
+ } else if (strncmp(token, "net", 3) == 0) {
+ Config.onoff.memory_cache_first = 1;
+ Config.onoff.memory_cache_disk = 0;
+ } else if (strcmp(token, "never") == 0) {
+ Config.onoff.memory_cache_first = 0;
+ Config.onoff.memory_cache_disk = 0;
+ } else
+ self_destruct();
+}
+
+static void
+dump_memcachemode(StoreEntry * entry, const char *name, SquidConfig &config)
+{
+ storeAppendPrintf(entry, "%s ", name);
+ if (Config.onoff.memory_cache_first && Config.onoff.memory_cache_disk)
+ storeAppendPrintf(entry, "always");
+ else if (!Config.onoff.memory_cache_first && Config.onoff.memory_cache_disk)
+ storeAppendPrintf(entry, "disk");
+ else if (Config.onoff.memory_cache_first && !Config.onoff.memory_cache_disk)
+ storeAppendPrintf(entry, "network");
+ else if (!Config.onoff.memory_cache_first && !Config.onoff.memory_cache_disk)
+ storeAppendPrintf(entry, "none");
+ storeAppendPrintf(entry, "\n");
+}
+
#include "cf_parser.h"
peer_t
#if USE_WCCPv2
void
-parse_IPAddress_list_token(IPAddress_list ** head, char *token)
+parse_IpAddress_list_token(IpAddress_list ** head, char *token)
{
char *t;
char *host;
char *tmp;
- IPAddress ipa;
+ IpAddress ipa;
unsigned short port;
- IPAddress_list *s;
+ IpAddress_list *s;
host = NULL;
port = 0;
while (*head)
head = &(*head)->next;
- s = static_cast<IPAddress_list *>(xcalloc(1, sizeof(*s)));
+ s = static_cast<IpAddress_list *>(xcalloc(1, sizeof(*s)));
s->s = ipa;
*head = s;
}
static void
-parse_IPAddress_list(IPAddress_list ** head)
+parse_IpAddress_list(IpAddress_list ** head)
{
char *token;
while ((token = strtok(NULL, w_space))) {
- parse_IPAddress_list_token(head, token);
+ parse_IpAddress_list_token(head, token);
}
}
static void
-dump_IPAddress_list(StoreEntry * e, const char *n, const IPAddress_list * s)
+dump_IpAddress_list(StoreEntry * e, const char *n, const IpAddress_list * s)
{
char ntoabuf[MAX_IPSTRLEN];
}
static void
-free_IPAddress_list(IPAddress_list ** head)
+free_IpAddress_list(IpAddress_list ** head)
{
if (*head) delete *head;
*head = NULL;
* be used by icp_port and htcp_port
*/
static int
-check_null_IPAddress_list(const IPAdress_list * s)
+check_null_IpAddress_list(const IpAddress_list * s)
{
return NULL == s;
}
if (NULL == host) {
s->s.SetAnyAddr();
s->s.SetPort(port);
- debugs(3, 3, "http(s)_port: found Listen on wildcard address: " << s->s);
+ debugs(3, 3, "http(s)_port: found Listen on wildcard address: *:" << s->s.GetPort() );
} else if ( s->s = host ) { /* check/parse numeric IPA */
s->s.SetPort(port);
debugs(3, 3, "http(s)_port: Listen on Host/IP: " << host << " --> " << s->s);
s->accel = 1;
} else if (strcmp(token, "accel") == 0) {
s->accel = 1;
+ } else if (strcmp(token, "allow-direct") == 0) {
+ s->allow_direct = 1;
} else if (strcmp(token, "no-connection-auth") == 0) {
s->connection_auth_disabled = true;
} else if (strcmp(token, "connection-auth=off") == 0) {
add_http_port(char *portspec)
{
http_port_list *s = create_http_port(portspec);
+ // we may need to merge better of the above returns a list with clones
+ assert(s->next == NULL);
s->next = Config.Sockaddr.http;
Config.Sockaddr.http = s;
}
+#if IPV6_SPECIAL_SPLITSTACK
+http_port_list *
+clone_http_port_list(http_port_list *a)
+{
+ http_port_list *b = new http_port_list(a->protocol);
+
+ b->s = a->s;
+ if (a->name)
+ b->name = xstrdup(a->name);
+ if (a->defaultsite)
+ b->defaultsite = xstrdup(a->defaultsite);
+
+ b->intercepted = a->intercepted;
+ b->spoof_client_ip = a->spoof_client_ip;
+ b->accel = a->accel;
+ b->allow_direct = a->allow_direct;
+ b->vhost = a->vhost;
+ b->sslBump = a->sslBump;
+ b->vport = a->vport;
+ b->connection_auth_disabled = a->connection_auth_disabled;
+ b->disable_pmtu_discovery = a->disable_pmtu_discovery;
+
+ memcpy( &(b->tcp_keepalive), &(a->tcp_keepalive), sizeof(a->tcp_keepalive));
+
+#if 0
+ // AYJ: 2009-07-18: for now SSL does not clone. Configure separate ports with IPs and SSL settings
+
+#if USE_SSL
+ // XXX: temporary hack to ease move of SSL options to http_port
+ http_port_list &http;
+
+ char *cert;
+ char *key;
+ int version;
+ char *cipher;
+ char *options;
+ char *clientca;
+ char *cafile;
+ char *capath;
+ char *crlfile;
+ char *dhfile;
+ char *sslflags;
+ char *sslcontext;
+ SSL_CTX *sslContext;
+#endif
+
+#endif /*0*/
+
+ return b;
+}
+#endif
+
static void
parse_http_port_list(http_port_list ** head)
{
parse_http_port_option(s, token);
}
+#if IPV6_SPECIAL_SPLITSTACK
+ if (s->s.IsAnyAddr()) {
+ // clone the port options from *s to *(s->next)
+ s->next = clone_http_port_list(s);
+ s->next->s.SetIPv4();
+ debugs(3, 3, "http(s)_port: clone wildcard address for split-stack: " << s->s << " and " << s->next->s);
+ }
+#endif
+
while (*head)
head = &(*head)->next;
if (s->tcp_keepalive.enabled) {
if (s->tcp_keepalive.idle || s->tcp_keepalive.interval || s->tcp_keepalive.timeout) {
- storeAppendPrintf(e, " tcp_keepalive=%d,%d,%d", s->tcp_keepalive.idle, s->tcp_keepalive.interval, s->tcp_keepalive.timeout);
+ storeAppendPrintf(e, " tcpkeepalive=%d,%d,%d", s->tcp_keepalive.idle, s->tcp_keepalive.interval, s->tcp_keepalive.timeout);
} else {
- storeAppendPrintf(e, " tcp_keepalive");
+ storeAppendPrintf(e, " tcpkeepalive");
}
}
cl->type = CLF_SQUID;
} else if (strcmp(logdef_name, "common") == 0) {
cl->type = CLF_COMMON;
+#if ICAP_CLIENT
+ } else if (strcmp(logdef_name, "icap_squid") == 0) {
+ cl->type = CLF_ICAP_SQUID;
+#endif
} else {
debugs(3, 0, "Log format '" << logdef_name << "' is not defined");
self_destruct();
case CLF_COMMON:
storeAppendPrintf(entry, "%s squid", log->filename);
break;
-
+#if ICAP_CLIENT
+ case CLF_ICAP_SQUID:
+ storeAppendPrintf(entry, "%s icap_squid", log->filename);
+ break;
+#endif
case CLF_AUTO:
if (log->aclList)
while (*definitions) {
logformat *format = *definitions;
*definitions = format->next;
+ safe_free(format->name);
accessLogFreeLogFormat(&format->format);
xfree(format);
}
Adaptation::Config::ParseServiceSet();
}
+static void
+parse_adaptation_service_chain_type()
+{
+ Adaptation::Config::ParseServiceChain();
+}
+
static void
parse_adaptation_access_type()
{
#if ICAP_CLIENT
static void
-parse_icap_service_type(ICAPConfig * cfg)
+parse_icap_service_type(Adaptation::Icap::Config * cfg)
{
cfg->parseService();
}
static void
-free_icap_service_type(ICAPConfig * cfg)
+free_icap_service_type(Adaptation::Icap::Config * cfg)
{
cfg->freeService();
}
static void
-dump_icap_service_type(StoreEntry * entry, const char *name, const ICAPConfig &cfg)
+dump_icap_service_type(StoreEntry * entry, const char *name, const Adaptation::Icap::Config &cfg)
{
cfg.dumpService(entry, name);
}
#if USE_ECAP
static void
-parse_ecap_service_type(Ecap::Config * cfg)
+parse_ecap_service_type(Adaptation::Ecap::Config * cfg)
{
cfg->parseService();
}
static void
-free_ecap_service_type(Ecap::Config * cfg)
+free_ecap_service_type(Adaptation::Ecap::Config * cfg)
{
cfg->freeService();
}
static void
-dump_ecap_service_type(StoreEntry * entry, const char *name, const Ecap::Config &cfg)
+dump_ecap_service_type(StoreEntry * entry, const char *name, const Adaptation::Ecap::Config &cfg)
{
cfg.dumpService(entry, name);
}