]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/cache_cf.cc
Enable length configuration for pipeline_prefetch queue
[thirdparty/squid.git] / src / cache_cf.cc
index 931145f42bed551eac23be68550c1b729d5405cb..d340169518eb257fe0d77fe4b6d2059c96fb07a5 100644 (file)
@@ -180,6 +180,7 @@ static void parse_access_log(CustomLog ** customlog_definitions);
 static int check_null_access_log(CustomLog *customlog_definitions);
 static void dump_access_log(StoreEntry * entry, const char *name, CustomLog * definitions);
 static void free_access_log(CustomLog ** definitions);
+static bool setLogformat(CustomLog *cl, const char *name, const bool dieWhenMissing);
 
 static void update_maxobjsize(void);
 static void configDoConfigure(void);
@@ -277,30 +278,33 @@ self_destruct(void)
 static void
 update_maxobjsize(void)
 {
-    int i;
     int64_t ms = -1;
 
-    for (i = 0; i < Config.cacheSwap.n_configured; ++i) {
+    // determine the maximum size object that can be stored to disk
+    for (int i = 0; i < Config.cacheSwap.n_configured; ++i) {
         assert (Config.cacheSwap.swapDirs[i].getRaw());
 
-        if (dynamic_cast<SwapDir *>(Config.cacheSwap.swapDirs[i].getRaw())->
-                max_objsize > ms)
-            ms = dynamic_cast<SwapDir *>(Config.cacheSwap.swapDirs[i].getRaw())->max_objsize;
+        const int64_t storeMax = dynamic_cast<SwapDir *>(Config.cacheSwap.swapDirs[i].getRaw())->maxObjectSize();
+        if (ms < storeMax)
+            ms = storeMax;
     }
+
+    // Ensure that we do not discard objects which could be stored only in memory.
+    // It is governed by maximum_object_size_in_memory (for now)
+    // TODO: update this to check each in-memory location (SMP and local memory limits differ)
+    if (ms < static_cast<int64_t>(Config.Store.maxInMemObjSize))
+        ms = Config.Store.maxInMemObjSize;
+
     store_maxobjsize = ms;
 }
 
 static void
 SetConfigFilename(char const *file_name, bool is_pipe)
 {
-    cfg_filename = file_name;
-
-    char const *token;
-
     if (is_pipe)
         cfg_filename = file_name + 1;
-    else if ((token = strrchr(cfg_filename, '/')))
-        cfg_filename = token + 1;
+    else
+        cfg_filename = file_name;
 }
 
 static const char*
@@ -521,7 +525,7 @@ parseOneConfigFile(const char *file_name, unsigned int depth)
                 if ((token = strchr(new_file_name, '"')))
                     *token = '\0';
 
-                cfg_filename = new_file_name;
+                SetConfigFilename(new_file_name, false);
             }
 
             config_lineno = new_lineno;
@@ -591,7 +595,7 @@ parseOneConfigFile(const char *file_name, unsigned int depth)
         fclose(fp);
     }
 
-    cfg_filename = orig_cfg_filename;
+    SetConfigFilename(orig_cfg_filename, false);
     config_lineno = orig_config_lineno;
 
     xfree(tmp_line);
@@ -648,6 +652,7 @@ configDoConfigure(void)
     memConfigure();
     /* Sanity checks */
 
+    Config.cacheSwap.n_strands = 0; // no diskers by default
     if (Config.cacheSwap.swapDirs == NULL) {
         /* Memory-only cache probably in effect. */
         /* turn off the cache rebuild delays... */
@@ -679,7 +684,7 @@ configDoConfigure(void)
 
     if (Config.Announce.period > 0) {
         Config.onoff.announce = 1;
-    } else if (Config.Announce.period < 1) {
+    } else {
         Config.Announce.period = 86400 * 365;  /* one year */
         Config.onoff.announce = 0;
     }
@@ -701,6 +706,13 @@ configDoConfigure(void)
         }
     }
 
+    if (Config.Program.store_id) {
+        if (Config.storeIdChildren.n_max < 1) {
+            Config.storeIdChildren.n_max = 0;
+            wordlistDestroy(&Config.Program.store_id);
+        }
+    }
+
     if (Config.appendDomain)
         if (*Config.appendDomain != '.')
             fatal("append_domain must begin with a '.'");
@@ -763,6 +775,9 @@ configDoConfigure(void)
     if (Config.Program.redirect)
         requirePathnameExists("redirect_program", Config.Program.redirect->key);
 
+    if (Config.Program.store_id)
+        requirePathnameExists("store_id_program", Config.Program.store_id->key);
+
     requirePathnameExists("Icon Directory", Config.icons.directory);
 
     if (Config.errorDirectory)
@@ -950,6 +965,16 @@ configDoConfigure(void)
                (uint32_t)Config.maxRequestBufferSize, (uint32_t)Config.maxRequestHeaderSize);
     }
 
+    /*
+     * Disable client side request pipelining if client_persistent_connections OFF.
+     * Waste of resources queueing any pipelined requests when the first will close the connection.
+     */
+    if (Config.pipeline_max_prefetch > 0 && !Config.onoff.client_pconns) {
+        debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: pipeline_prefetch " << Config.pipeline_max_prefetch <<
+                   " requires client_persistent_connections ON. Forced pipeline_prefetch 0.");
+        Config.pipeline_max_prefetch = 0;
+    }
+
 #if USE_AUTH
     /*
      * disable client side request pipelining. There is a race with
@@ -958,12 +983,12 @@ configDoConfigure(void)
      * pipelining OFF, the client may fail to authenticate, but squid's
      * state will be preserved.
      */
-    if (Config.onoff.pipeline_prefetch) {
+    if (Config.pipeline_max_prefetch > 0) {
         Auth::Config *nego = Auth::Config::Find("Negotiate");
         Auth::Config *ntlm = Auth::Config::Find("NTLM");
         if ((nego && nego->active()) || (ntlm && ntlm->active())) {
-            debugs(3, DBG_IMPORTANT, "WARNING: pipeline_prefetch breaks NTLM and Negotiate authentication. Forced OFF.");
-            Config.onoff.pipeline_prefetch = 0;
+            debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: pipeline_prefetch breaks NTLM and Negotiate authentication. Forced pipeline_prefetch 0.");
+            Config.pipeline_max_prefetch = 0;
         }
     }
 #endif
@@ -1206,7 +1231,6 @@ parseBytesLineSigned(ssize_t * bptr, const char *units)
 }
 #endif
 
-#if USE_SSL
 /**
  * Parse bytes from a string.
  * Similar to the parseBytesLine function but parses the string value instead of
@@ -1242,7 +1266,6 @@ static void parseBytesOptionValue(size_t * bptr, const char *units, char const *
     if (static_cast<double>(*bptr) * 2 != (m * d / u) * 2)
         self_destruct();
 }
-#endif
 
 static size_t
 parseBytesUnits(const char *unit)
@@ -1899,8 +1922,10 @@ parse_cachedir(SquidConfig::_cacheSwap * swap)
 
     fs = find_fstype(type_str);
 
-    if (fs < 0)
-        self_destruct();
+    if (fs < 0) {
+        debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: This proxy does not support the '" << type_str << "' cache type. Ignoring.");
+        return;
+    }
 
     /* reconfigure existing dir */
 
@@ -2121,29 +2146,29 @@ parse_peer(CachePeer ** head)
     p->connection_auth = 2;    /* auto */
 
     while ((token = strtok(NULL, w_space))) {
-        if (!strcasecmp(token, "proxy-only")) {
+        if (!strcmp(token, "proxy-only")) {
             p->options.proxy_only = true;
-        } else if (!strcasecmp(token, "no-query")) {
+        } else if (!strcmp(token, "no-query")) {
             p->options.no_query = true;
-        } else if (!strcasecmp(token, "background-ping")) {
+        } else if (!strcmp(token, "background-ping")) {
             p->options.background_ping = true;
-        } else if (!strcasecmp(token, "no-digest")) {
+        } else if (!strcmp(token, "no-digest")) {
             p->options.no_digest = true;
-        } else if (!strcasecmp(token, "no-tproxy")) {
+        } else if (!strcmp(token, "no-tproxy")) {
             p->options.no_tproxy = true;
-        } else if (!strcasecmp(token, "multicast-responder")) {
+        } else if (!strcmp(token, "multicast-responder")) {
             p->options.mcast_responder = true;
 #if PEER_MULTICAST_SIBLINGS
-        } else if (!strcasecmp(token, "multicast-siblings")) {
+        } else if (!strcmp(token, "multicast-siblings")) {
             p->options.mcast_siblings = true;
 #endif
-        } else if (!strncasecmp(token, "weight=", 7)) {
+        } else if (!strncmp(token, "weight=", 7)) {
             p->weight = xatoi(token + 7);
-        } else if (!strncasecmp(token, "basetime=", 9)) {
+        } else if (!strncmp(token, "basetime=", 9)) {
             p->basetime = xatoi(token + 9);
-        } else if (!strcasecmp(token, "closest-only")) {
+        } else if (!strcmp(token, "closest-only")) {
             p->options.closest_only = true;
-        } else if (!strncasecmp(token, "ttl=", 4)) {
+        } else if (!strncmp(token, "ttl=", 4)) {
             p->mcast.ttl = xatoi(token + 4);
 
             if (p->mcast.ttl < 0)
@@ -2151,16 +2176,16 @@ parse_peer(CachePeer ** head)
 
             if (p->mcast.ttl > 128)
                 p->mcast.ttl = 128;
-        } else if (!strcasecmp(token, "default")) {
+        } else if (!strcmp(token, "default")) {
             p->options.default_parent = true;
-        } else if (!strcasecmp(token, "round-robin")) {
+        } else if (!strcmp(token, "round-robin")) {
             p->options.roundrobin = true;
-        } else if (!strcasecmp(token, "weighted-round-robin")) {
+        } else if (!strcmp(token, "weighted-round-robin")) {
             p->options.weighted_roundrobin = true;
 #if USE_HTCP
-        } else if (!strcasecmp(token, "htcp")) {
+        } else if (!strcmp(token, "htcp")) {
             p->options.htcp = true;
-        } else if (!strncasecmp(token, "htcp=", 5) || !strncasecmp(token, "htcp-", 5)) {
+        } else if (!strncmp(token, "htcp=", 5) || !strncmp(token, "htcp-", 5)) {
             /* Note: The htcp- form is deprecated, replaced by htcp= */
             p->options.htcp = true;
             char *tmp = xstrdup(token+5);
@@ -2171,19 +2196,19 @@ parse_peer(CachePeer ** head)
                     *nextmode = '\0';
                     ++nextmode;
                 }
-                if (!strcasecmp(mode, "no-clr")) {
+                if (!strcmp(mode, "no-clr")) {
                     if (p->options.htcp_only_clr)
                         fatalf("parse_peer: can't set htcp-no-clr and htcp-only-clr simultaneously");
                     p->options.htcp_no_clr = true;
-                } else if (!strcasecmp(mode, "no-purge-clr")) {
+                } else if (!strcmp(mode, "no-purge-clr")) {
                     p->options.htcp_no_purge_clr = true;
-                } else if (!strcasecmp(mode, "only-clr")) {
+                } else if (!strcmp(mode, "only-clr")) {
                     if (p->options.htcp_no_clr)
                         fatalf("parse_peer: can't set htcp no-clr and only-clr simultaneously");
                     p->options.htcp_only_clr = true;
-                } else if (!strcasecmp(mode, "forward-clr")) {
+                } else if (!strcmp(mode, "forward-clr")) {
                     p->options.htcp_forward_clr = true;
-                } else if (!strcasecmp(mode, "oldsquid")) {
+                } else if (!strcmp(mode, "oldsquid")) {
                     p->options.htcp_oldsquid = true;
                 } else {
                     fatalf("invalid HTCP mode '%s'", mode);
@@ -2191,15 +2216,15 @@ parse_peer(CachePeer ** head)
             }
             safe_free(tmp);
 #endif
-        } else if (!strcasecmp(token, "no-netdb-exchange")) {
+        } else if (!strcmp(token, "no-netdb-exchange")) {
             p->options.no_netdb_exchange = true;
 
-        } else if (!strcasecmp(token, "carp")) {
+        } else if (!strcmp(token, "carp")) {
             if (p->type != PEER_PARENT)
                 fatalf("parse_peer: non-parent carp peer %s/%d\n", p->host, p->http_port);
 
             p->options.carp = true;
-        } else if (!strncasecmp(token, "carp-key=", 9)) {
+        } else if (!strncmp(token, "carp-key=", 9)) {
             if (p->options.carp != true)
                 fatalf("parse_peer: carp-key specified on non-carp peer %s/%d\n", p->host, p->http_port);
             p->options.carp_key.set = true;
@@ -2207,21 +2232,21 @@ parse_peer(CachePeer ** head)
             for (; key; key = nextkey) {
                 nextkey=strchr(key,',');
                 if (nextkey) ++nextkey; // skip the comma, any
-                if (0==strncasecmp(key,"scheme",6)) {
+                if (0==strncmp(key,"scheme",6)) {
                     p->options.carp_key.scheme = true;
-                } else if (0==strncasecmp(key,"host",4)) {
+                } else if (0==strncmp(key,"host",4)) {
                     p->options.carp_key.host = true;
-                } else if (0==strncasecmp(key,"port",4)) {
+                } else if (0==strncmp(key,"port",4)) {
                     p->options.carp_key.port = true;
-                } else if (0==strncasecmp(key,"path",4)) {
+                } else if (0==strncmp(key,"path",4)) {
                     p->options.carp_key.path = true;
-                } else if (0==strncasecmp(key,"params",6)) {
+                } else if (0==strncmp(key,"params",6)) {
                     p->options.carp_key.params = true;
                 } else {
                     fatalf("invalid carp-key '%s'",key);
                 }
             }
-        } else if (!strcasecmp(token, "userhash")) {
+        } else if (!strcmp(token, "userhash")) {
 #if USE_AUTH
             if (p->type != PEER_PARENT)
                 fatalf("parse_peer: non-parent userhash peer %s/%d\n", p->host, p->http_port);
@@ -2230,42 +2255,42 @@ parse_peer(CachePeer ** head)
 #else
             fatalf("parse_peer: userhash requires authentication. peer %s/%d\n", p->host, p->http_port);
 #endif
-        } else if (!strcasecmp(token, "sourcehash")) {
+        } else if (!strcmp(token, "sourcehash")) {
             if (p->type != PEER_PARENT)
                 fatalf("parse_peer: non-parent sourcehash peer %s/%d\n", p->host, p->http_port);
 
             p->options.sourcehash = true;
 
-        } else if (!strcasecmp(token, "no-delay")) {
+        } else if (!strcmp(token, "no-delay")) {
 #if USE_DELAY_POOLS
             p->options.no_delay = true;
 #else
             debugs(0, DBG_CRITICAL, "WARNING: cache_peer option 'no-delay' requires --enable-delay-pools");
 #endif
-        } else if (!strncasecmp(token, "login=", 6)) {
+        } else if (!strncmp(token, "login=", 6)) {
             p->login = xstrdup(token + 6);
             rfc1738_unescape(p->login);
-        } else if (!strncasecmp(token, "connect-timeout=", 16)) {
+        } else if (!strncmp(token, "connect-timeout=", 16)) {
             p->connect_timeout = xatoi(token + 16);
-        } else if (!strncasecmp(token, "connect-fail-limit=", 19)) {
+        } else if (!strncmp(token, "connect-fail-limit=", 19)) {
             p->connect_fail_limit = xatoi(token + 19);
 #if USE_CACHE_DIGESTS
-        } else if (!strncasecmp(token, "digest-url=", 11)) {
+        } else if (!strncmp(token, "digest-url=", 11)) {
             p->digest_url = xstrdup(token + 11);
 #endif
 
-        } else if (!strcasecmp(token, "allow-miss")) {
+        } else if (!strcmp(token, "allow-miss")) {
             p->options.allow_miss = true;
-        } else if (!strncasecmp(token, "max-conn=", 9)) {
+        } else if (!strncmp(token, "max-conn=", 9)) {
             p->max_conn = xatoi(token + 9);
-        } else if (!strcasecmp(token, "originserver")) {
+        } else if (!strcmp(token, "originserver")) {
             p->options.originserver = true;
-        } else if (!strncasecmp(token, "name=", 5)) {
+        } else if (!strncmp(token, "name=", 5)) {
             safe_free(p->name);
 
             if (token[5])
                 p->name = xstrdup(token + 5);
-        } else if (!strncasecmp(token, "forceddomain=", 13)) {
+        } else if (!strncmp(token, "forceddomain=", 13)) {
             safe_free(p->domain);
 
             if (token[13])
@@ -2320,9 +2345,11 @@ parse_peer(CachePeer ** head)
             p->connection_auth = 1;
         } else if (strcmp(token, "connection-auth=auto") == 0) {
             p->connection_auth = 2;
+        } else if (token[0] == '#') {
+            // start of a text comment. stop reading this line.
+            break;
         } else {
-            debugs(3, DBG_CRITICAL, "parse_peer: token='" << token << "'");
-            self_destruct();
+            debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: Ignoring unknown cache_peer option '" << token << "'");
         }
     }
 
@@ -2613,14 +2640,14 @@ parse_onoff(int *var)
     if (token == NULL)
         self_destruct();
 
-    if (!strcasecmp(token, "on")) {
+    if (!strcmp(token, "on")) {
         *var = 1;
-    } else if (!strcasecmp(token, "enable")) {
+    } else if (!strcmp(token, "enable")) {
         debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: 'enable' is deprecated. Please update to use 'on'.");
         *var = 1;
-    } else if (!strcasecmp(token, "off")) {
+    } else if (!strcmp(token, "off")) {
         *var = 0;
-    } else if (!strcasecmp(token, "disable")) {
+    } else if (!strcmp(token, "disable")) {
         debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: 'disable' is deprecated. Please update to use 'off'.");
         *var = 0;
     } else {
@@ -2654,16 +2681,16 @@ parse_tristate(int *var)
     if (token == NULL)
         self_destruct();
 
-    if (!strcasecmp(token, "on")) {
+    if (!strcmp(token, "on")) {
         *var = 1;
-    } else if (!strcasecmp(token, "enable")) {
+    } else if (!strcmp(token, "enable")) {
         debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: 'enable' is deprecated. Please update to use value 'on'.");
         *var = 1;
-    } else if (!strcasecmp(token, "warn")) {
+    } else if (!strcmp(token, "warn")) {
         *var = -1;
-    } else if (!strcasecmp(token, "off")) {
+    } else if (!strcmp(token, "off")) {
         *var = 0;
-    } else if (!strcasecmp(token, "disable")) {
+    } else if (!strcmp(token, "disable")) {
         debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: 'disable' is deprecated. Please update to use value 'off'.");
         *var = 0;
     } else {
@@ -2674,6 +2701,29 @@ parse_tristate(int *var)
 
 #define free_tristate free_int
 
+void
+parse_pipelinePrefetch(int *var)
+{
+    char *token = ConfigParser::strtokFile();
+
+    if (token == NULL)
+        self_destruct();
+
+    if (!strcmp(token, "on")) {
+        debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: 'pipeline_prefetch on' is deprecated. Please update to use 1 (or a higher number).");
+        *var = 1;
+    } else if (!strcmp(token, "off")) {
+        debugs(0, DBG_PARSE_NOTE(2), "WARNING: 'pipeline_prefetch off' is deprecated. Please update to use '0'.");
+        *var = 0;
+    } else {
+        ConfigParser::strtokFileUndo();
+        parse_int(var);
+    }
+}
+
+#define free_pipelinePrefetch free_int
+#define dump_pipelinePrefetch dump_int
+
 static void
 dump_refreshpattern(StoreEntry * entry, const char *name, RefreshPattern * head)
 {
@@ -3249,15 +3299,15 @@ parse_uri_whitespace(int *var)
     if (token == NULL)
         self_destruct();
 
-    if (!strcasecmp(token, "strip"))
+    if (!strcmp(token, "strip"))
         *var = URI_WHITESPACE_STRIP;
-    else if (!strcasecmp(token, "deny"))
+    else if (!strcmp(token, "deny"))
         *var = URI_WHITESPACE_DENY;
-    else if (!strcasecmp(token, "allow"))
+    else if (!strcmp(token, "allow"))
         *var = URI_WHITESPACE_ALLOW;
-    else if (!strcasecmp(token, "encode"))
+    else if (!strcmp(token, "encode"))
         *var = URI_WHITESPACE_ENCODE;
-    else if (!strcasecmp(token, "chop"))
+    else if (!strcmp(token, "chop"))
         *var = URI_WHITESPACE_CHOP;
     else {
         debugs(0, DBG_PARSE_NOTE(2), "ERROR: Invalid option '" << token << "': 'uri_whitespace' accepts 'strip', 'deny', 'allow', 'encode', and 'chop'.");
@@ -3399,19 +3449,19 @@ dump_memcachemode(StoreEntry * entry, const char *name, SquidConfig &config)
 peer_t
 parseNeighborType(const char *s)
 {
-    if (!strcasecmp(s, "parent"))
+    if (!strcmp(s, "parent"))
         return PEER_PARENT;
 
-    if (!strcasecmp(s, "neighbor"))
+    if (!strcmp(s, "neighbor"))
         return PEER_SIBLING;
 
-    if (!strcasecmp(s, "neighbour"))
+    if (!strcmp(s, "neighbour"))
         return PEER_SIBLING;
 
-    if (!strcasecmp(s, "sibling"))
+    if (!strcmp(s, "sibling"))
         return PEER_SIBLING;
 
-    if (!strcasecmp(s, "multicast"))
+    if (!strcmp(s, "multicast"))
         return PEER_MULTICAST;
 
     debugs(15, DBG_CRITICAL, "WARNING: Unknown neighbor type: " << s);
@@ -3561,7 +3611,7 @@ parse_port_option(AnyP::PortCfg * s, char *token)
             self_destruct();
         }
         s->flags.accelSurrogate = true;
-        s->vhost = 1;
+        s->vhost = true;
     } else if (strcmp(token, "transparent") == 0 || strcmp(token, "intercept") == 0) {
         if (s->flags.accelSurrogate || s->flags.tproxyIntercept) {
             debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: Intercept mode requires its own interception port. It cannot be shared with other modes.");
@@ -3588,8 +3638,7 @@ parse_port_option(AnyP::PortCfg * s, char *token)
         s->flags.tproxyIntercept = true;
         Ip::Interceptor.StartTransparency();
         /* Log information regarding the port modes under transparency. */
-        debugs(3, DBG_IMPORTANT, "Starting IP Spoofing on port " << s->s);
-        debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (IP spoofing enabled)");
+        debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (TPROXY enabled)");
 
         if (!Ip::Interceptor.ProbeForTproxy(s->s)) {
             debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: TPROXY support in the system does not work.");
@@ -3608,12 +3657,12 @@ parse_port_option(AnyP::PortCfg * s, char *token)
             debugs(3, DBG_CRITICAL, "WARNING: http(s)_port: vhost option is deprecated. Use 'accel' mode flag instead.");
         }
         s->flags.accelSurrogate = true;
-        s->vhost = 1;
+        s->vhost = true;
     } else if (strcmp(token, "no-vhost") == 0) {
         if (!s->flags.accelSurrogate) {
             debugs(3, DBG_IMPORTANT, "ERROR: http(s)_port: no-vhost option requires Acceleration mode flag.");
         }
-        s->vhost = 0;
+        s->vhost = false;
     } else if (strcmp(token, "vport") == 0) {
         if (!s->flags.accelSurrogate) {
             debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: vport option requires Acceleration mode flag.");
@@ -3637,12 +3686,12 @@ parse_port_option(AnyP::PortCfg * s, char *token)
             debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: allow-direct option requires Acceleration mode flag.");
             self_destruct();
         }
-        s->allow_direct = 1;
+        s->allow_direct = true;
     } else if (strcmp(token, "act-as-origin") == 0) {
         if (!s->flags.accelSurrogate) {
             debugs(3, DBG_IMPORTANT, "ERROR: http(s)_port: act-as-origin option requires Acceleration mode flag.");
         } else
-            s->actAsOrigin = 1;
+            s->actAsOrigin = true;
     } else if (strcmp(token, "ignore-cc") == 0) {
 #if !USE_HTTP_VIOLATIONS
         if (!s->flags.accelSurrogate) {
@@ -3650,7 +3699,7 @@ parse_port_option(AnyP::PortCfg * s, char *token)
             self_destruct();
         }
 #endif
-        s->ignore_cc = 1;
+        s->ignore_cc = true;
     } else if (strncmp(token, "name=", 5) == 0) {
         safe_free(s->name);
         s->name = xstrdup(token + 5);
@@ -3663,11 +3712,11 @@ parse_port_option(AnyP::PortCfg * s, char *token)
     } else if (strcmp(token, "connection-auth=on") == 0) {
         s->connection_auth_disabled = false;
     } else if (strncmp(token, "disable-pmtu-discovery=", 23) == 0) {
-        if (!strcasecmp(token + 23, "off"))
+        if (!strcmp(token + 23, "off"))
             s->disable_pmtu_discovery = DISABLE_PMTU_OFF;
-        else if (!strcasecmp(token + 23, "transparent"))
+        else if (!strcmp(token + 23, "transparent"))
             s->disable_pmtu_discovery = DISABLE_PMTU_TRANSPARENT;
-        else if (!strcasecmp(token + 23, "always"))
+        else if (!strcmp(token + 23, "always"))
             s->disable_pmtu_discovery = DISABLE_PMTU_ALWAYS;
         else
             self_destruct();
@@ -3677,24 +3726,23 @@ parse_port_option(AnyP::PortCfg * s, char *token)
             self_destruct();
         }
     } else if (strcmp(token, "tcpkeepalive") == 0) {
-        s->tcp_keepalive.enabled = 1;
+        s->tcp_keepalive.enabled = true;
     } else if (strncmp(token, "tcpkeepalive=", 13) == 0) {
         char *t = token + 13;
-        s->tcp_keepalive.enabled = 1;
-        s->tcp_keepalive.idle = xatoui(t);
+        s->tcp_keepalive.enabled = true;
+        s->tcp_keepalive.idle = xatoui(t,',');
         t = strchr(t, ',');
         if (t) {
             ++t;
-            s->tcp_keepalive.interval = xatoui(t);
+            s->tcp_keepalive.interval = xatoui(t,',');
             t = strchr(t, ',');
         }
         if (t) {
             ++t;
             s->tcp_keepalive.timeout = xatoui(t);
-            // t = strchr(t, ','); // not really needed, left in as documentation
         }
 #if USE_SSL
-    } else if (strcasecmp(token, "sslBump") == 0) {
+    } else if (strcmp(token, "sslBump") == 0) {
         debugs(3, DBG_CRITICAL, "WARNING: '" << token << "' is deprecated " <<
                "in http_port. Use 'ssl-bump' instead.");
         s->flags.tunnelSslBumping = true;
@@ -3794,7 +3842,7 @@ parsePortCfg(AnyP::PortCfg ** head, const char *optionName)
     }
 
 #if USE_SSL
-    if (strcasecmp(protocol, "https") == 0) {
+    if (strcmp(protocol, "https") == 0) {
         /* 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) {
@@ -4006,14 +4054,39 @@ strtokFile(void)
 
 #include "AccessLogEntry.h"
 
+/**
+ * We support several access_log configuration styles:
+ *
+ * #1: Deprecated ancient style without an explicit logging module:
+ * access_log /var/log/access.log
+ *
+ * #2: The "none" logging module (i.e., no logging [of matching transactions]):
+ * access_log none [acl ...]
+ *
+ * #3: Configurable logging module without named options:
+ * Logformat or the first ACL name, whichever comes first, may not contain '='.
+ * If no explicit logformat name is given, the first ACL name, if any,
+ * should not be an existing logformat name or it will be treated as such.
+ * access_log module:place [logformat_name] [acl ...]
+ *
+ * #4: Configurable logging module with name=value options such as logformat=x:
+ * The first ACL name may not contain '='.
+ * access_log module:place [option ...] [acl ...]
+ *
+ */
 static void
 parse_access_log(CustomLog ** logs)
 {
-    const char *filename, *logdef_name;
-
     CustomLog *cl = (CustomLog *)xcalloc(1, sizeof(*cl));
 
-    if ((filename = strtok(NULL, w_space)) == NULL) {
+    // default buffer size and fatal settings
+    cl->bufferSize = 8*MAX_URL;
+    cl->fatal = true;
+
+    /* determine configuration style */
+
+    const char *filename = strtok(NULL, w_space);
+    if (!filename) {
         self_destruct();
         return;
     }
@@ -4027,12 +4100,72 @@ parse_access_log(CustomLog ** logs)
         return;
     }
 
-    if ((logdef_name = strtok(NULL, w_space)) == NULL)
-        logdef_name = "squid";
+    cl->filename = xstrdup(filename);
+    cl->type = Log::Format::CLF_UNKNOWN;
+
+    const char *token = ConfigParser::strtokFile();
+    if (!token) { // style #1
+        // no options to deal with
+    } else if (!strchr(token, '=')) { // style #3
+        // if logformat name is not recognized,
+        // put back the token; it must be an ACL name
+        if (!setLogformat(cl, token, false))
+            ConfigParser::strtokFileUndo();
+    } else { // style #4
+        do {
+            if (strncasecmp(token, "on-error=", 9) == 0) {
+                if (strncasecmp(token+9, "die", 3) == 0) {
+                    cl->fatal = true;
+                } else if (strncasecmp(token+9, "drop", 4) == 0) {
+                    cl->fatal = false;
+                } else {
+                    debugs(3, DBG_CRITICAL, "Unknown value for on-error '" <<
+                           token << "' expected 'drop' or 'die'");
+                    self_destruct();
+                }
+            } else if (strncasecmp(token, "buffer-size=", 12) == 0) {
+                parseBytesOptionValue(&cl->bufferSize, B_BYTES_STR, token+12);
+            } else if (strncasecmp(token, "logformat=", 10) == 0) {
+                setLogformat(cl, token+10, true);
+            } else if (!strchr(token, '=')) {
+                // put back the token; it must be an ACL name
+                ConfigParser::strtokFileUndo();
+                break; // done with name=value options, now to ACLs
+            } else {
+                debugs(3, DBG_CRITICAL, "Unknown access_log option " << token);
+                self_destruct();
+            }
+        } while ((token = ConfigParser::strtokFile()) != NULL);
+    }
+
+    // set format if it has not been specified explicitly
+    if (cl->type == Log::Format::CLF_UNKNOWN)
+        setLogformat(cl, "squid", true);
 
-    debugs(3, 9, "Log definition name '" << logdef_name << "' file '" << filename << "'");
+    aclParseAclList(LegacyParser, &cl->aclList);
 
-    cl->filename = xstrdup(filename);
+    while (*logs)
+        logs = &(*logs)->next;
+
+    *logs = cl;
+}
+
+/// sets CustomLog::type and, if needed, CustomLog::lf
+/// returns false iff there is no named log format
+static bool
+setLogformat(CustomLog *cl, const char *logdef_name, const bool dieWhenMissing)
+{
+    assert(cl);
+    assert(logdef_name);
+
+    debugs(3, 9, "possible " << cl->filename << " logformat: " << logdef_name);
+
+    if (cl->type != Log::Format::CLF_UNKNOWN) {
+        debugs(3, DBG_CRITICAL, "Second logformat name in one access_log: " <<
+               logdef_name << " " << cl->type << " ? " << Log::Format::CLF_NONE);
+        self_destruct();
+        return false;
+    }
 
     /* look for the definition pointer corresponding to this name */
     Format::Format *lf = Log::TheConfig.logformats;
@@ -4066,18 +4199,15 @@ parse_access_log(CustomLog ** logs)
         cl->type = Log::Format::CLF_USERAGENT;
     } else if (strcmp(logdef_name, "referrer") == 0) {
         cl->type = Log::Format::CLF_REFERER;
-    } else {
+    } else if (dieWhenMissing) {
         debugs(3, DBG_CRITICAL, "Log format '" << logdef_name << "' is not defined");
         self_destruct();
-        return;
+        return false;
+    } else {
+        return false;
     }
 
-    aclParseAclList(LegacyParser, &cl->aclList);
-
-    while (*logs)
-        logs = &(*logs)->next;
-
-    *logs = cl;
+    return true;
 }
 
 static int