Squid Web Cache v8/master
Loading...
Searching...
No Matches
cache_cf.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9/* DEBUG: section 03 Configuration File Parsing */
10
11#include "squid.h"
12#include "acl/Acl.h"
13#include "acl/AclDenyInfoList.h"
14#include "acl/AclSizeLimit.h"
15#include "acl/Address.h"
16#include "acl/Gadgets.h"
17#include "acl/MethodData.h"
18#include "acl/Node.h"
19#include "acl/Tree.h"
20#include "anyp/PortCfg.h"
21#include "anyp/UriScheme.h"
22#include "auth/Config.h"
23#include "auth/Scheme.h"
24#include "AuthReg.h"
25#include "base/CharacterSet.h"
26#include "base/PackableStream.h"
28#include "cache_cf.h"
29#include "CachePeer.h"
30#include "CachePeers.h"
31#include "compat/netdb.h"
32#include "compat/socket.h"
33#include "ConfigOption.h"
34#include "ConfigParser.h"
35#include "CpuAffinityMap.h"
36#include "debug/Messages.h"
37#include "DiskIO/DiskIOModule.h"
38#include "eui/Config.h"
39#include "ExternalACL.h"
40#include "format/Format.h"
41#include "fqdncache.h"
42#include "ftp/Elements.h"
43#include "globals.h"
44#include "HeaderMangling.h"
46#include "icmp/IcmpConfig.h"
47#include "ip/Intercept.h"
48#include "ip/NfMarkConfig.h"
49#include "ip/QosConfig.h"
50#include "ip/tools.h"
51#include "ipc/Kids.h"
52#include "log/Config.h"
53#include "log/CustomLog.h"
54#include "MemBuf.h"
55#include "MessageDelayPools.h"
57#include "mgr/Registration.h"
58#include "neighbors.h"
60#include "Parsing.h"
61#include "pconn.h"
62#include "PeerDigest.h"
63#include "PeerPoolMgr.h"
64#include "redirect.h"
65#include "RefreshPattern.h"
66#include "rfc1738.h"
67#include "sbuf/List.h"
68#include "sbuf/Stream.h"
69#include "SquidConfig.h"
70#include "SquidString.h"
71#include "ssl/ProxyCerts.h"
72#include "Store.h"
73#include "store/Disks.h"
74#include "tools.h"
75#include "util.h"
76#include "wordlist.h"
77/* wccp2 has its own conditional definitions */
78#include "wccp2.h"
79#if USE_ADAPTATION
80#include "adaptation/Config.h"
81#endif
82#if ICAP_CLIENT
84#endif
85#if USE_ECAP
87#endif
88#if USE_OPENSSL
89#include "ssl/Config.h"
90#include "ssl/support.h"
91#endif
92#if SQUID_SNMP
93#include "snmp.h"
94#endif
95
96#include <algorithm>
97#if HAVE_GLOB_H
98#include <glob.h>
99#endif
100#include <chrono>
101#include <limits>
102#include <list>
103#if HAVE_PWD_H
104#include <pwd.h>
105#endif
106#if HAVE_GRP_H
107#include <grp.h>
108#endif
109#if HAVE_SYS_STAT_H
110#include <sys/stat.h>
111#endif
112
113#if USE_OPENSSL
114#include "ssl/gadgets.h"
115#endif
116
117#if USE_ADAPTATION
120static void parse_adaptation_access_type();
121#endif
122
123#if ICAP_CLIENT
125static void dump_icap_service_type(StoreEntry *, const char *, const Adaptation::Icap::Config &);
127static void parse_icap_class_type();
128static void parse_icap_access_type();
129
131static void dump_icap_service_failure_limit(StoreEntry *, const char *, const Adaptation::Icap::Config &);
133#endif
134
135#if USE_ECAP
137static void dump_ecap_service_type(StoreEntry *, const char *, const Adaptation::Ecap::Config &);
139#endif
140
141static peer_t parseNeighborType(const char *s);
142
143static const char *const T_NANOSECOND_STR = "nanosecond";
144static const char *const T_MICROSECOND_STR = "microsecond";
145static const char *const T_MILLISECOND_STR = "millisecond";
146static const char *const T_SECOND_STR = "second";
147static const char *const T_MINUTE_STR = "minute";
148static const char *const T_HOUR_STR = "hour";
149static const char *const T_DAY_STR = "day";
150static const char *const T_WEEK_STR = "week";
151static const char *const T_FORTNIGHT_STR = "fortnight";
152static const char *const T_MONTH_STR = "month";
153static const char *const T_YEAR_STR = "year";
154static const char *const T_DECADE_STR = "decade";
155
156static const char *const B_BYTES_STR = "bytes";
157static const char *const B_KBYTES_STR = "KB";
158static const char *const B_MBYTES_STR = "MB";
159static const char *const B_GBYTES_STR = "GB";
160
161// std::chrono::years requires C++20. Do our own rough calculation for now.
162static const double HoursPerYear = 24*365.2522;
163
164static void parse_cache_log_message(DebugMessages **messages);
165static void dump_cache_log_message(StoreEntry *entry, const char *name, const DebugMessages *messages);
166static void free_cache_log_message(DebugMessages **messages);
167
168static void parse_access_log(CustomLog ** customlog_definitions);
169static int check_null_access_log(CustomLog *customlog_definitions);
170static void dump_access_log(StoreEntry * entry, const char *name, CustomLog * definitions);
171static void free_access_log(CustomLog ** definitions);
172
173static void configDoConfigure(void);
175static void parse_u_short(unsigned short * var);
176static void parse_string(char **);
177static void default_all(void);
178static void defaults_if_none(void);
179static void defaults_postscriptum(void);
180static int parse_line(char *);
181static void parse_obsolete(const char *);
182static void parseBytesLine(size_t * bptr, const char *units);
183static void parseBytesLineSigned(ssize_t * bptr, const char *units);
184static size_t parseBytesUnits(const char *unit);
185static void free_all(void);
186void requirePathnameExists(const char *name, const char *path);
188#if USE_HTTP_VIOLATIONS
189static void free_HeaderManglers(HeaderManglers **pm);
190static void dump_http_header_access(StoreEntry * entry, const char *name, const HeaderManglers *manglers);
191static void parse_http_header_access(HeaderManglers **manglers);
192#define free_http_header_access free_HeaderManglers
193static void dump_http_header_replace(StoreEntry * entry, const char *name, const HeaderManglers *manglers);
194static void parse_http_header_replace(HeaderManglers **manglers);
195#define free_http_header_replace free_HeaderManglers
196#endif
197static void dump_HeaderWithAclList(StoreEntry * entry, const char *name, HeaderWithAclList *headers);
198static void parse_HeaderWithAclList(HeaderWithAclList **header);
199static void free_HeaderWithAclList(HeaderWithAclList **header);
200static void parse_note(Notes *);
201static void dump_note(StoreEntry *, const char *, Notes &);
202static void free_note(Notes *);
203static void parse_denyinfo(AclDenyInfoList ** var);
204static void dump_denyinfo(StoreEntry * entry, const char *name, AclDenyInfoList * var);
205static void free_denyinfo(AclDenyInfoList ** var);
206
207#if USE_WCCPv2
209static void dump_IpAddress_list(StoreEntry *, const char *, const Ip::Address_list *);
211#if CURRENTLY_UNUSED
212static int check_null_IpAddress_list(const Ip::Address_list *);
213#endif /* CURRENTLY_UNUSED */
214#endif /* USE_WCCPv2 */
215
216static void parsePortCfg(AnyP::PortCfgPointer *, const char *protocol);
217#define parse_PortCfg(l) parsePortCfg((l), token)
218static void dump_PortCfg(StoreEntry *, const char *, const AnyP::PortCfgPointer &);
219#define free_PortCfg(h) *(h)=NULL
220
221#if USE_OPENSSL
222static void parse_sslproxy_cert_sign(sslproxy_cert_sign **cert_sign);
223static void dump_sslproxy_cert_sign(StoreEntry *entry, const char *name, sslproxy_cert_sign *cert_sign);
224static void free_sslproxy_cert_sign(sslproxy_cert_sign **cert_sign);
225static void parse_sslproxy_cert_adapt(sslproxy_cert_adapt **cert_adapt);
226static void dump_sslproxy_cert_adapt(StoreEntry *entry, const char *name, sslproxy_cert_adapt *cert_adapt);
227static void free_sslproxy_cert_adapt(sslproxy_cert_adapt **cert_adapt);
228static void parse_sslproxy_ssl_bump(acl_access **ssl_bump);
229static void dump_sslproxy_ssl_bump(StoreEntry *entry, const char *name, acl_access *ssl_bump);
230static void free_sslproxy_ssl_bump(acl_access **ssl_bump);
231#endif /* USE_OPENSSL */
232
233static void parse_ftp_epsv(acl_access **ftp_epsv);
234static void dump_ftp_epsv(StoreEntry *entry, const char *name, acl_access *ftp_epsv);
235static void free_ftp_epsv(acl_access **ftp_epsv);
236
237static void parse_b_size_t(size_t * var);
238static void parse_b_int64_t(int64_t * var);
239
240static void parse_CpuAffinityMap(CpuAffinityMap **const cpuAffinityMap);
241static void dump_CpuAffinityMap(StoreEntry *const entry, const char *const name, const CpuAffinityMap *const cpuAffinityMap);
242static void free_CpuAffinityMap(CpuAffinityMap **const cpuAffinityMap);
243
247
248static int parseOneConfigFile(const char *file_name, unsigned int depth);
249
250static void parse_configuration_includes_quoted_values(bool *recognizeQuotedValues);
251static void dump_configuration_includes_quoted_values(StoreEntry *const entry, const char *const name, bool recognizeQuotedValues);
252static void free_configuration_includes_quoted_values(bool *recognizeQuotedValues);
253static void parse_on_unsupported_protocol(acl_access **access);
254static void dump_on_unsupported_protocol(StoreEntry *entry, const char *name, acl_access *access);
255static void free_on_unsupported_protocol(acl_access **access);
256static void ParseAclWithAction(acl_access **access, const Acl::Answer &action, const char *desc, Acl::Node *acl = nullptr);
258static void dump_http_upgrade_request_protocols(StoreEntry *entry, const char *name, HttpUpgradeProtocolAccess *protoGuards);
260
261/*
262 * LegacyParser is a parser for legacy code that uses the global
263 * approach. This is static so that it is only exposed to cache_cf.
264 * Other modules needing access to a ConfigParser should have it
265 * provided to them in their parserFOO methods.
266 */
268
269const char *cfg_directive = nullptr;
270const char *cfg_filename = nullptr;
273
274void
276{
278}
279
280static void
281SetConfigFilename(char const *file_name, bool is_pipe)
282{
283 if (is_pipe)
284 cfg_filename = file_name + 1;
285 else
286 cfg_filename = file_name;
287}
288
295static bool
296IsSpace(const char ch)
297{
298 return CharacterSet::WSP[ch];
299}
300
301static const char*
302skip_ws(const char* s)
303{
304 while (IsSpace(*s))
305 ++s;
306
307 return s;
308}
309
310static int
311parseManyConfigFiles(char* files, int depth)
312{
313 int error_count = 0;
314 char* saveptr = nullptr;
315#if HAVE_GLOB
316 char *path;
317 glob_t globbuf;
318 int i;
319 memset(&globbuf, 0, sizeof(globbuf));
320 for (path = strwordtok(files, &saveptr); path; path = strwordtok(nullptr, &saveptr)) {
321 if (glob(path, globbuf.gl_pathc ? GLOB_APPEND : 0, nullptr, &globbuf) != 0) {
322 int xerrno = errno;
323 fatalf("Unable to find configuration file: %s: %s", path, xstrerr(xerrno));
324 }
325 }
326 for (i = 0; i < (int)globbuf.gl_pathc; ++i) {
327 error_count += parseOneConfigFile(globbuf.gl_pathv[i], depth);
328 }
329 globfree(&globbuf);
330#else
331 char* file = strwordtok(files, &saveptr);
332 while (file != NULL) {
333 error_count += parseOneConfigFile(file, depth);
334 file = strwordtok(nullptr, &saveptr);
335 }
336#endif /* HAVE_GLOB */
337 return error_count;
338}
339
340static void
341ReplaceSubstr(char*& str, int& len, unsigned substrIdx, unsigned substrLen, const char* newSubstr)
342{
343 assert(str != nullptr);
344 assert(newSubstr != nullptr);
345
346 unsigned newSubstrLen = strlen(newSubstr);
347 if (newSubstrLen > substrLen)
348 str = (char*)realloc(str, len - substrLen + newSubstrLen + 1);
349
350 // move tail part including zero
351 memmove(str + substrIdx + newSubstrLen, str + substrIdx + substrLen, len - substrIdx - substrLen + 1);
352 // copy new substring in place
353 memcpy(str + substrIdx, newSubstr, newSubstrLen);
354
355 len = strlen(str);
356}
357
358static void
359SubstituteMacro(char*& line, int& len, const char* macroName, const char* substStr)
360{
361 assert(line != nullptr);
362 assert(macroName != nullptr);
363 assert(substStr != nullptr);
364 unsigned macroNameLen = strlen(macroName);
365 while (const char* macroPos = strstr(line, macroName)) // we would replace all occurrences
366 ReplaceSubstr(line, len, macroPos - line, macroNameLen, substStr);
367}
368
369static void
370ProcessMacros(char*& line, int& len)
371{
372 SubstituteMacro(line, len, "${service_name}", service_name.c_str());
373 SubstituteMacro(line, len, "${process_name}", TheKidName.c_str());
374 SubstituteMacro(line, len, "${process_number}", xitoa(KidIdentifier));
375}
376
377static void
379{
380 assert(str != nullptr);
381 unsigned i = strlen(str);
382 while ((i > 0) && IsSpace(str[i - 1]))
383 --i;
384 str[i] = '\0';
385}
386
387static const char*
388FindStatement(const char* line, const char* statement)
389{
390 assert(line != nullptr);
391 assert(statement != nullptr);
392
393 const char* str = skip_ws(line);
394 unsigned len = strlen(statement);
395 if (strncmp(str, statement, len) == 0) {
396 str += len;
397 if (*str == '\0')
398 return str;
399 else if (IsSpace(*str))
400 return skip_ws(str);
401 }
402
403 return nullptr;
404}
405
406static bool
407StrToInt(const char* str, long& number)
408{
409 assert(str != nullptr);
410
411 char* end;
412 number = strtol(str, &end, 0);
413
414 return (end != str) && (*end == '\0'); // returns true if string contains nothing except number
415}
416
417static bool
418EvalBoolExpr(const char* expr)
419{
420 assert(expr != nullptr);
421 if (strcmp(expr, "true") == 0) {
422 return true;
423 } else if (strcmp(expr, "false") == 0) {
424 return false;
425 } else if (const char* equation = strchr(expr, '=')) {
426 const char* rvalue = skip_ws(equation + 1);
427 char* lvalue = (char*)xmalloc(equation - expr + 1);
428 xstrncpy(lvalue, expr, equation - expr + 1);
429 trim_trailing_ws(lvalue);
430
431 long number1;
432 if (!StrToInt(lvalue, number1))
433 fatalf("String is not a integer number: '%s'\n", lvalue);
434 long number2;
435 if (!StrToInt(rvalue, number2))
436 fatalf("String is not a integer number: '%s'\n", rvalue);
437
438 xfree(lvalue);
439 return number1 == number2;
440 }
441 fatalf("Unable to evaluate expression '%s'\n", expr);
442 return false; // this place cannot be reached
443}
444
445static int
446parseOneConfigFile(const char *file_name, unsigned int depth)
447{
448 FILE *fp = nullptr;
449 const char *orig_cfg_filename = cfg_filename;
450 const int orig_config_lineno = config_lineno;
451 char *token = nullptr;
452 char *tmp_line = nullptr;
453 int tmp_line_len = 0;
454 int err_count = 0;
455 int is_pipe = 0;
456
457 debugs(3, Important(68), "Processing Configuration File: " << file_name << " (depth " << depth << ")");
458 if (depth > 16) {
459 fatalf("WARNING: can't include %s: includes are nested too deeply (>16)!\n", file_name);
460 return 1;
461 }
462
463 if (file_name[0] == '!' || file_name[0] == '|') {
464 fp = popen(file_name + 1, "r");
465 is_pipe = 1;
466 } else {
467 fp = fopen(file_name, "r");
468 }
469
470 if (!fp) {
471 int xerrno = errno;
472 fatalf("Unable to open configuration file: %s: %s", file_name, xstrerr(xerrno));
473 }
474
475#if _SQUID_WINDOWS_
476 setmode(fileno(fp), O_TEXT);
477#endif
478
479 SetConfigFilename(file_name, bool(is_pipe));
480
481 memset(config_input_line, '\0', BUFSIZ);
482
483 config_lineno = 0;
484
485 std::vector<bool> if_states;
486 while (fgets(config_input_line, BUFSIZ, fp)) {
488
489 if ((token = strchr(config_input_line, '\n')))
490 *token = '\0';
491
492 if ((token = strchr(config_input_line, '\r')))
493 *token = '\0';
494
495 // strip any prefix whitespace off the line.
496 const char *p = skip_ws(config_input_line);
497 if (config_input_line != p)
498 memmove(config_input_line, p, strlen(p)+1);
499
500 if (strncmp(config_input_line, "#line ", 6) == 0) {
501 static char new_file_name[1024];
502 static char *file;
503 static char new_lineno;
504 token = config_input_line + 6;
505 new_lineno = strtol(token, &file, 0) - 1;
506
507 if (file == token)
508 continue; /* Not a valid #line directive, may be a comment */
509
510 while (*file && IsSpace(*file))
511 ++file;
512
513 if (*file) {
514 if (*file != '"')
515 continue; /* Not a valid #line directive, may be a comment */
516
517 xstrncpy(new_file_name, file + 1, sizeof(new_file_name));
518
519 if ((token = strchr(new_file_name, '"')))
520 *token = '\0';
521
522 SetConfigFilename(new_file_name, false);
523 }
524
525 config_lineno = new_lineno;
526 }
527
528 if (config_input_line[0] == '#')
529 continue;
530
531 if (config_input_line[0] == '\0')
532 continue;
533
534 const char* append = tmp_line_len ? skip_ws(config_input_line) : config_input_line;
535
536 size_t append_len = strlen(append);
537
538 tmp_line = (char*)xrealloc(tmp_line, tmp_line_len + append_len + 1);
539
540 strcpy(tmp_line + tmp_line_len, append);
541
542 tmp_line_len += append_len;
543
544 if (tmp_line[tmp_line_len-1] == '\\') {
545 debugs(3, 5, "parseConfigFile: tmp_line='" << tmp_line << "'");
546 tmp_line[--tmp_line_len] = '\0';
547 continue;
548 }
549
550 trim_trailing_ws(tmp_line);
551 ProcessMacros(tmp_line, tmp_line_len);
552 debugs(3, (opt_parse_cfg_only?1:5), "Processing: " << tmp_line);
553
554 if (const char* expr = FindStatement(tmp_line, "if")) {
555 if_states.push_back(EvalBoolExpr(expr)); // store last if-statement meaning
556 } else if (FindStatement(tmp_line, "endif")) {
557 if (!if_states.empty())
558 if_states.pop_back(); // remove last if-statement meaning
559 else
560 fatalf("'endif' without 'if'\n");
561 } else if (FindStatement(tmp_line, "else")) {
562 if (!if_states.empty())
563 if_states.back() = !if_states.back();
564 else
565 fatalf("'else' without 'if'\n");
566 } else if (if_states.empty() || if_states.back()) { // test last if-statement meaning if present
567 /* Handle includes here */
568 if (tmp_line_len >= 9 && strncmp(tmp_line, "include", 7) == 0 && IsSpace(tmp_line[7])) {
569 err_count += parseManyConfigFiles(tmp_line + 8, depth + 1);
570 } else {
571 try {
572 if (!parse_line(tmp_line)) {
573 debugs(3, DBG_CRITICAL, "ERROR: unrecognized directive near '" << tmp_line << "'" <<
574 Debug::Extra << "directive location: " << ConfigParser::CurrentLocation());
575 ++err_count;
576 }
577 } catch (...) {
578 // fatal for now
579 debugs(3, DBG_CRITICAL, "ERROR: configuration failure: " << CurrentException);
581 }
582 }
583 }
584
585 safe_free(tmp_line);
586 tmp_line_len = 0;
587
588 }
589 if (!if_states.empty())
590 fatalf("if-statement without 'endif'\n");
591
592 if (is_pipe) {
593 int ret = pclose(fp);
594
595 if (ret != 0)
596 fatalf("parseConfigFile: '%s' failed with exit code %d\n", file_name, ret);
597 } else {
598 fclose(fp);
599 }
600
601 SetConfigFilename(orig_cfg_filename, false);
602 config_lineno = orig_config_lineno;
603
604 xfree(tmp_line);
605 return err_count;
606}
607
608void
610{
611 debugs(5, 4, MYNAME);
612
614
616 default_all();
617
618 const auto unrecognizedDirectives = parseOneConfigFile(ConfigFile, 0);
619
621
623
624 if (unrecognizedDirectives)
625 throw TextException(ToSBuf("Found ", unrecognizedDirectives, " unrecognized directive(s)"), Here());
626
627 /*
628 * We must call configDoConfigure() before leave_suid() because
629 * configDoConfigure() is where we turn username strings into
630 * uid values.
631 */
633
634 if (opt_send_signal == -1) {
635 Mgr::RegisterAction("config",
636 "Current Squid Configuration",
638 1, 1);
639 }
640}
641
642/*
643 * The templated functions below are essentially ConfigParser methods. They are
644 * not implemented as such because our generated code calling them is the only
645 * code that can instantiate implementations for each T -- we cannot place these
646 * definitions into ConfigParser.cc unless cf_parser.cci is moved there.
647 */
648
649// TODO: When adding Ts incompatible with this trivial API and implementation,
650// replace both with a ConfigParser-maintained table of seen directives.
652template <typename T>
653static bool
654SawDirective(const T &raw)
655{
656 return bool(raw);
657}
658
661template <typename T>
662static void
664{
665 if (SawDirective(raw))
667
668 // TODO: parser.openDirective(directiveName);
669 Must(!raw);
671 Must(raw);
672 parser.closeDirective();
673}
674
677template <typename T>
678static void
679DumpDirective(const T &raw, StoreEntry *entry, const char *name)
680{
681 if (!SawDirective(raw))
682 return; // not configured
683
684 entry->append(name, strlen(name));
685 SBufStream os;
687 const auto buf = os.buf();
688 if (buf.length()) {
689 entry->append(" ", 1);
690 entry->append(buf.rawContent(), buf.length());
691 }
692 entry->append("\n", 1);
693}
694
696template <typename T>
697static void
699{
701
702 // While the implementation may change, there is no way to avoid zeroing.
703 // Even migration to a proper SquidConfig class would not help: While
704 // ordinary destructors do not need to zero data members, a SquidConfig
705 // destructor would have to zero to protect any SquidConfig::x destruction
706 // code from accidentally dereferencing an already destroyed Config.y.
707 static_assert(std::is_trivial<T>::value, "SquidConfig member is trivial");
708 memset(&raw, 0, sizeof(raw));
709}
710
711static void
713{
714 Config2.clear();
715 /* init memory as early as possible */
716 memConfigure();
717 /* Sanity checks */
718
719 if (Debug::rotateNumber < 0) {
721 }
722
723#if SIZEOF_OFF_T <= 4
724 if (Config.Store.maxObjectSize > 0x7FFF0000) {
725 debugs(3, DBG_CRITICAL, "WARNING: This Squid binary can not handle files larger than 2GB. Limiting maximum_object_size to just below 2GB");
726 Config.Store.maxObjectSize = 0x7FFF0000;
727 }
728#endif
729
732 else
733 visible_appname_string = (char const *)APP_FULLNAME;
734
735 if (Config.Program.redirect) {
736 if (Config.redirectChildren.n_max < 1) {
739 }
740 }
741
742 if (Config.Program.store_id) {
743 if (Config.storeIdChildren.n_max < 1) {
746 }
747 }
748
750 if (*Config.appendDomain != '.')
751 fatal("append_domain must begin with a '.'");
752
753 if (Config.errHtmlText == nullptr)
755
756#if !HAVE_SETRLIMIT || !defined(RLIMIT_NOFILE)
757 if (Config.max_filedescriptors > 0) {
758 debugs(0, DBG_IMPORTANT, "WARNING: max_filedescriptors disabled. Operating System setrlimit(RLIMIT_NOFILE) is missing.");
759 }
760#elif USE_SELECT
761 if (Config.max_filedescriptors > FD_SETSIZE) {
762 debugs(0, DBG_IMPORTANT, "WARNING: max_filedescriptors limited to " << FD_SETSIZE << " by select() algorithm.");
763 }
764#endif
765
767
768 snprintf(ThisCache, sizeof(ThisCache), "%s (%s)",
771
772 /*
773 * the extra space is for loop detection in client_side.c -- we search
774 * for substrings in the Via header.
775 */
776 snprintf(ThisCache2, sizeof(ThisCache2), " %s (%s)",
779
780 /* Use visible_hostname as default surrogate_id */
782 const char *t = getMyHostname();
783 Config.Accel.surrogate_id = xstrdup( (t?t:"unset-id") );
784 }
785
788
791 else
793
794 if (Config.connect_retries > 10) {
795 debugs(0,DBG_CRITICAL, "WARNING: connect_retries cannot be larger than 10. Resetting to 10.");
797 }
798
799 requirePathnameExists("MIME Config Table", Config.mimeTablePathname);
800#if USE_UNLINKD
801
802 requirePathnameExists("unlinkd_program", Config.Program.unlinkd);
803#endif
804 bool logDaemonUsed = false;
805 for (const auto *log = Config.Log.accesslogs; !logDaemonUsed && log; log = log->next)
806 logDaemonUsed = log->usesDaemon();
807#if ICAP_CLIENT
808 for (const auto *log = Config.Log.icaplogs; !logDaemonUsed && log; log = log->next)
809 logDaemonUsed = log->usesDaemon();
810#endif
811 if (logDaemonUsed)
812 requirePathnameExists("logfile_daemon", Log::TheConfig.logfile_daemon);
813
815 requirePathnameExists("redirect_program", Config.Program.redirect->key);
816
818 requirePathnameExists("store_id_program", Config.Program.store_id->key);
819
820 requirePathnameExists("Icon Directory", Config.icons.directory);
821
823 requirePathnameExists("Error Directory", Config.errorDirectory);
824
825#if USE_HTTP_VIOLATIONS
826
827 {
828 const RefreshPattern *R;
829
830 for (R = Config.Refresh; R; R = R->next) {
831 if (!R->flags.override_expire)
832 continue;
833
834 debugs(22, DBG_IMPORTANT, "WARNING: use of 'override-expire' in 'refresh_pattern' violates HTTP");
835
836 break;
837 }
838
839 for (R = Config.Refresh; R; R = R->next) {
840 if (!R->flags.override_lastmod)
841 continue;
842
843 debugs(22, DBG_IMPORTANT, "WARNING: use of 'override-lastmod' in 'refresh_pattern' violates HTTP");
844
845 break;
846 }
847
848 for (R = Config.Refresh; R; R = R->next) {
849 if (!R->flags.reload_into_ims)
850 continue;
851
852 debugs(22, DBG_IMPORTANT, "WARNING: use of 'reload-into-ims' in 'refresh_pattern' violates HTTP");
853
854 break;
855 }
856
857 for (R = Config.Refresh; R; R = R->next) {
858 if (!R->flags.ignore_reload)
859 continue;
860
861 debugs(22, DBG_IMPORTANT, "WARNING: use of 'ignore-reload' in 'refresh_pattern' violates HTTP");
862
863 break;
864 }
865
866 for (R = Config.Refresh; R; R = R->next) {
867 if (!R->flags.ignore_no_store)
868 continue;
869
870 debugs(22, DBG_IMPORTANT, "WARNING: use of 'ignore-no-store' in 'refresh_pattern' violates HTTP");
871
872 break;
873 }
874
875 for (R = Config.Refresh; R; R = R->next) {
876 if (!R->flags.ignore_private)
877 continue;
878
879 debugs(22, DBG_IMPORTANT, "WARNING: use of 'ignore-private' in 'refresh_pattern' violates HTTP");
880
881 break;
882 }
883 }
884#endif
885#if !USE_HTTP_VIOLATIONS
886 Config.onoff.via = 1;
887#else
888
889 if (!Config.onoff.via)
890 debugs(22, DBG_IMPORTANT, "WARNING: HTTP requires the use of Via");
891
892#endif
893
894 // we enable runtime PURGE checks if there is at least one PURGE method ACL
895 // TODO: replace with a dedicated "purge" ACL option?
897
898 if (geteuid() == 0) {
899 if (nullptr != Config.effectiveUser) {
900
901 struct passwd *pwd = getpwnam(Config.effectiveUser);
902
903 if (nullptr == pwd) {
904 /*
905 * Andres Kroonmaa <andre@online.ee>:
906 * Some getpwnam() implementations (Solaris?) require
907 * an available FD < 256 for opening a FILE* to the
908 * passwd file.
909 * DW:
910 * This should be safe at startup, but might still fail
911 * during reconfigure.
912 */
913 fatalf("getpwnam failed to find userid for effective user '%s'",
915 return;
916 }
917
918 Config2.effectiveUserID = pwd->pw_uid;
919
920 Config2.effectiveGroupID = pwd->pw_gid;
921
922 if (pwd->pw_dir && *pwd->pw_dir)
923 (void)setenv("HOME", pwd->pw_dir, 1);
924 }
925 } else {
926 Config2.effectiveUserID = geteuid();
927 Config2.effectiveGroupID = getegid();
928 }
929
930 if (nullptr != Config.effectiveGroup) {
931
932 struct group *grp = getgrnam(Config.effectiveGroup);
933
934 if (nullptr == grp) {
935 fatalf("getgrnam failed to find groupid for effective group '%s'",
937 return;
938 }
939
940 Config2.effectiveGroupID = grp->gr_gid;
941 }
942
943#if USE_OPENSSL
946#endif
947
948 if (Security::ProxyOutgoingConfig().encryptTransport) {
949 debugs(3, 2, "initializing https:// proxy context");
950
951 const auto rawSslContext = Security::ProxyOutgoingConfig().createClientContext(false);
952 Config.ssl_client.sslContext_ = rawSslContext ? new Security::ContextPointer(rawSslContext) : nullptr;
954#if USE_OPENSSL
955 fatal("ERROR: Could not initialize https:// proxy context");
956#else
957 debugs(3, DBG_IMPORTANT, "ERROR: proxying https:// currently still requires --with-openssl");
958#endif
959 }
960#if USE_OPENSSL
962#endif
964 }
965
966 for (const auto &p: CurrentCachePeers()) {
967
968 // default value for ssldomain= is the peer host/IP
969 if (p->secure.sslDomain.isEmpty())
970 p->secure.sslDomain = p->host;
971
972 if (p->secure.encryptTransport) {
973 debugs(3, 2, "initializing TLS context for cache_peer " << *p);
974 p->sslContext = p->secure.createClientContext(true);
975 if (!p->sslContext) {
976 debugs(3, DBG_CRITICAL, "ERROR: Could not initialize TLS context for cache_peer " << *p);
978 return;
979 }
980 }
981 }
982
983 for (AnyP::PortCfgPointer s = HttpPortList; s != nullptr; s = s->next) {
984 if (!s->secure.encryptTransport)
985 continue;
986 debugs(3, 2, "initializing " << AnyP::UriScheme(s->transport.protocol) << "_port " << s->s << " TLS contexts");
987 s->secure.initServerContexts(*s);
988 }
989
990 // prevent infinite fetch loops in the request parser
991 // due to buffer full but not enough data received to finish parse
993 fatalf("Client request buffer of %u bytes cannot hold a request with %u bytes of headers." \
994 " Change client_request_buffer_max or request_header_max_size limits.",
996 }
997
998 // Warn about the dangers of exceeding String limits when manipulating HTTP
999 // headers. Technically, we do not concatenate _requests_, so we could relax
1000 // their check, but we keep the two checks the same for simplicity sake.
1001 const auto safeRawHeaderValueSizeMax = (String::SizeMaxXXX()+1)/3;
1002 // TODO: static_assert(safeRawHeaderValueSizeMax >= 64*1024); // no WARNINGs for default settings
1003 if (Config.maxRequestHeaderSize > safeRawHeaderValueSizeMax)
1004 debugs(3, DBG_CRITICAL, "WARNING: Increasing request_header_max_size beyond " << safeRawHeaderValueSizeMax <<
1005 " bytes makes Squid more vulnerable to denial-of-service attacks; configured value: " << Config.maxRequestHeaderSize << " bytes");
1006 if (Config.maxReplyHeaderSize > safeRawHeaderValueSizeMax)
1007 debugs(3, DBG_CRITICAL, "WARNING: Increasing reply_header_max_size beyond " << safeRawHeaderValueSizeMax <<
1008 " bytes makes Squid more vulnerable to denial-of-service attacks; configured value: " << Config.maxReplyHeaderSize << " bytes");
1009
1010 /*
1011 * Disable client side request pipelining if client_persistent_connections OFF.
1012 * Waste of resources queueing any pipelined requests when the first will close the connection.
1013 */
1015 debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: pipeline_prefetch " << Config.pipeline_max_prefetch <<
1016 " requires client_persistent_connections ON. Forced pipeline_prefetch 0.");
1018 }
1019
1020#if USE_AUTH
1021 /*
1022 * disable client side request pipelining. There is a race with
1023 * Negotiate and NTLM when the client sends a second request on an
1024 * connection before the authenticate challenge is sent. With
1025 * pipelining OFF, the client may fail to authenticate, but squid's
1026 * state will be preserved.
1027 */
1028 if (Config.pipeline_max_prefetch > 0) {
1029 Auth::SchemeConfig *nego = Auth::SchemeConfig::Find("Negotiate");
1031 if ((nego && nego->active()) || (ntlm && ntlm->active())) {
1032 debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: pipeline_prefetch breaks NTLM and Negotiate authentication. Forced pipeline_prefetch 0.");
1034 }
1035 }
1036
1037 for (auto &authSchemes : Auth::TheConfig.schemeLists) {
1038 authSchemes.expand();
1039 if (authSchemes.authConfigs.empty()) {
1040 debugs(3, DBG_CRITICAL, "auth_schemes: at least one scheme name is required; got: " << authSchemes.rawSchemes);
1041 self_destruct();
1042 }
1043 }
1044#endif
1045}
1046
1053void
1054parse_obsolete(const char *name)
1055{
1056 // Directives which have been radically changed rather than removed
1057 if (!strcmp(name, "url_rewrite_concurrency")) {
1058 int cval;
1059 parse_int(&cval);
1060 debugs(3, DBG_CRITICAL, "WARNING: url_rewrite_concurrency upgrade overriding url_rewrite_children settings.");
1062 }
1063
1064 if (!strcmp(name, "ignore_ims_on_miss")) {
1065 // the replacement directive cache_revalidate_on_miss has opposite meanings for ON/OFF value
1066 // than the 2.7 directive. We need to parse and invert the configured value.
1067 int temp = 0;
1068 parse_onoff(&temp);
1070 }
1071
1072 if (!strncmp(name, "sslproxy_", 9)) {
1073 // the replacement directive tls_outgoing_options uses options instead of whole-line input
1074 SBuf tmp;
1075 if (!strcmp(name, "sslproxy_cafile"))
1076 tmp.append("cafile=");
1077 else if (!strcmp(name, "sslproxy_capath"))
1078 tmp.append("capath=");
1079 else if (!strcmp(name, "sslproxy_cipher"))
1080 tmp.append("cipher=");
1081 else if (!strcmp(name, "sslproxy_client_certificate"))
1082 tmp.append("cert=");
1083 else if (!strcmp(name, "sslproxy_client_key"))
1084 tmp.append("key=");
1085 else if (!strcmp(name, "sslproxy_flags"))
1086 tmp.append("flags=");
1087 else if (!strcmp(name, "sslproxy_options"))
1088 tmp.append("options=");
1089 else if (!strcmp(name, "sslproxy_version"))
1090 tmp.append("version=");
1091 else {
1092 debugs(3, DBG_CRITICAL, "ERROR: unknown directive: " << name);
1093 self_destruct();
1094 return;
1095 }
1096
1097 // add the value as unquoted-string because the old values did not support whitespace
1098 const char *token = ConfigParser::NextQuotedOrToEol();
1099 if (!token)
1100 throw TextException(ToSBuf("missing required parameter for obsolete directive: ", name), Here());
1101
1102 tmp.append(token, strlen(token));
1104 }
1105}
1106
1107template <class MinimalUnit>
1108static const char *
1110{
1111 const auto minUnit = MinimalUnit(1);
1112 if(minUnit == std::chrono::nanoseconds(1))
1113 return T_NANOSECOND_STR;
1114 else if (minUnit == std::chrono::microseconds(1))
1115 return T_MICROSECOND_STR;
1116 else if (minUnit == std::chrono::milliseconds(1))
1117 return T_MILLISECOND_STR;
1118 else {
1119 assert(minUnit >= std::chrono::seconds(1));
1120 return T_SECOND_STR;
1121 }
1122}
1123
1129template <class MinimalUnit>
1130static bool
1131parseTimeUnit(const char *unitName, std::chrono::nanoseconds &ns)
1132{
1133 if (!unitName)
1134 throw TexcHere("missing time unit");
1135
1136 if (!strncasecmp(unitName, T_NANOSECOND_STR, strlen(T_NANOSECOND_STR)))
1137 ns = std::chrono::nanoseconds(1);
1138 else if (!strncasecmp(unitName, T_MICROSECOND_STR, strlen(T_MICROSECOND_STR)))
1139 ns = std::chrono::microseconds(1);
1140 else if (!strncasecmp(unitName, T_MILLISECOND_STR, strlen(T_MILLISECOND_STR)))
1141 ns = std::chrono::milliseconds(1);
1142 else if (!strncasecmp(unitName, T_SECOND_STR, strlen(T_SECOND_STR)))
1143 ns = std::chrono::seconds(1);
1144 else if (!strncasecmp(unitName, T_MINUTE_STR, strlen(T_MINUTE_STR)))
1145 ns = std::chrono::minutes(1);
1146 else if (!strncasecmp(unitName, T_HOUR_STR, strlen(T_HOUR_STR)))
1147 ns = std::chrono::hours(1);
1148 else if (!strncasecmp(unitName, T_DAY_STR, strlen(T_DAY_STR)))
1149 ns = std::chrono::hours(24);
1150 else if (!strncasecmp(unitName, T_WEEK_STR, strlen(T_WEEK_STR)))
1151 ns = std::chrono::hours(24 * 7);
1152 else if (!strncasecmp(unitName, T_FORTNIGHT_STR, strlen(T_FORTNIGHT_STR)))
1153 ns = std::chrono::hours(24 * 14);
1154 else if (!strncasecmp(unitName, T_MONTH_STR, strlen(T_MONTH_STR)))
1155 ns = std::chrono::hours(24 * 30);
1156 else if (!strncasecmp(unitName, T_YEAR_STR, strlen(T_YEAR_STR)))
1157 ns = std::chrono::hours(static_cast<std::chrono::hours::rep>(HoursPerYear));
1158 else if (!strncasecmp(unitName, T_DECADE_STR, strlen(T_DECADE_STR)))
1159 ns = std::chrono::hours(static_cast<std::chrono::hours::rep>(HoursPerYear * 10));
1160 else
1161 return false;
1162
1163 if (ns < MinimalUnit(1)) {
1164 throw TexcHere(ToSBuf("time unit '", unitName, "' is too small to be used in this context, the minimal unit is ",
1165 TimeUnitToString<MinimalUnit>()));
1166 }
1167
1168 return true;
1169}
1170
1171static std::chrono::nanoseconds
1172ToNanoSeconds(const double value, const std::chrono::nanoseconds &unit)
1173{
1174 if (value < 0.0)
1175 throw TexcHere("time must have a positive value");
1176
1177 if (value > (static_cast<double>(std::chrono::nanoseconds::max().count()) / unit.count())) {
1178 const auto maxYears = std::chrono::duration_cast<std::chrono::hours>(std::chrono::nanoseconds::max()).count()/HoursPerYear;
1179 throw TexcHere(ToSBuf("time values cannot exceed ", maxYears, " years"));
1180 }
1181
1182 return std::chrono::duration_cast<std::chrono::nanoseconds>(unit * value);
1183}
1184
1185template <class TimeUnit>
1186static TimeUnit
1187FromNanoseconds(const std::chrono::nanoseconds &ns, const double parsedValue)
1188{
1189 const auto result = std::chrono::duration_cast<TimeUnit>(ns);
1190 if (!result.count()) {
1191 throw TexcHere(ToSBuf("time value '", parsedValue,
1192 "' is too small to be used in this context, the minimal value is 1 ",
1193 TimeUnitToString<TimeUnit>()));
1194 }
1195 return result;
1196}
1197
1200template <class TimeUnit>
1201static TimeUnit
1203{
1204 const auto valueToken = ConfigParser::NextToken();
1205 if (!valueToken)
1206 throw TexcHere("cannot read a time value");
1207
1208 const auto parsedValue = xatof(valueToken);
1209
1210 if (parsedValue == 0)
1211 return TimeUnit::zero();
1212
1213 std::chrono::nanoseconds parsedUnitDuration;
1214
1215 const auto token = ConfigParser::PeekAtToken();
1216
1217 if (!parseTimeUnit<TimeUnit>(token, parsedUnitDuration))
1218 throw TexcHere(ToSBuf("unknown time unit '", token, "'"));
1219
1221
1222 const auto nanoseconds = ToNanoSeconds(parsedValue, parsedUnitDuration);
1223
1224 // validate precisions (time-units-small only)
1225 if (TimeUnit(1) <= std::chrono::microseconds(1)) {
1226 if (0 < nanoseconds.count() && nanoseconds.count() < 3) {
1228 "Squid time measurement precision is likely to be far worse than " <<
1229 "the nanosecond-level precision implied by the configured value: " << parsedValue << ' ' << token);
1230 }
1231 }
1232
1233 return FromNanoseconds<TimeUnit>(nanoseconds, parsedValue);
1234}
1235
1236static void
1237parseBytesLine64(int64_t * bptr, const char *units)
1238{
1239 char *token;
1240 double d;
1241 int64_t m;
1242 int64_t u;
1243
1244 if ((u = parseBytesUnits(units)) == 0) {
1245 self_destruct();
1246 return;
1247 }
1248
1249 if ((token = ConfigParser::NextToken()) == nullptr) {
1250 self_destruct();
1251 return;
1252 }
1253
1254 if (strcmp(token, "none") == 0 || strcmp(token, "-1") == 0) {
1255 *bptr = -1;
1256 return;
1257 }
1258
1259 d = xatof(token);
1260
1261 m = u; /* default to 'units' if none specified */
1262
1263 if (0.0 == d)
1264 (void) 0;
1265 else if ((token = ConfigParser::NextToken()) == nullptr)
1266 debugs(3, DBG_CRITICAL, "WARNING: No units on '" <<
1267 config_input_line << "', assuming " <<
1268 d << " " << units );
1269 else if ((m = parseBytesUnits(token)) == 0) {
1270 self_destruct();
1271 return;
1272 }
1273
1274 *bptr = static_cast<int64_t>(m * d / u);
1275
1276 if (static_cast<double>(*bptr) * 2 != (m * d / u) * 2) {
1277 debugs(3, DBG_CRITICAL, "ERROR: Invalid value '" <<
1278 d << " " << token << ": integer overflow (int64_t).");
1279 self_destruct();
1280 }
1281}
1282
1283static void
1284parseBytesLine(size_t * bptr, const char *units)
1285{
1286 char *token;
1287 double d;
1288 int m;
1289 int u;
1290
1291 if ((u = parseBytesUnits(units)) == 0) {
1292 self_destruct();
1293 return;
1294 }
1295
1296 if ((token = ConfigParser::NextToken()) == nullptr) {
1297 self_destruct();
1298 return;
1299 }
1300
1301 if (strcmp(token, "none") == 0 || strcmp(token, "-1") == 0) {
1302 *bptr = static_cast<size_t>(-1);
1303 return;
1304 }
1305
1306 d = xatof(token);
1307
1308 m = u; /* default to 'units' if none specified */
1309
1310 if (0.0 == d)
1311 (void) 0;
1312 else if ((token = ConfigParser::NextToken()) == nullptr)
1313 debugs(3, DBG_CRITICAL, "WARNING: No units on '" <<
1314 config_input_line << "', assuming " <<
1315 d << " " << units );
1316 else if ((m = parseBytesUnits(token)) == 0) {
1317 self_destruct();
1318 return;
1319 }
1320
1321 *bptr = static_cast<size_t>(m * d / u);
1322
1323 if (static_cast<double>(*bptr) * 2 != (m * d / u) * 2) {
1324 debugs(3, DBG_CRITICAL, "ERROR: Invalid value '" <<
1325 d << " " << token << ": integer overflow (size_t).");
1326 self_destruct();
1327 }
1328}
1329
1330static void
1331parseBytesLineSigned(ssize_t * bptr, const char *units)
1332{
1333 char *token;
1334 double d;
1335 int m;
1336 int u;
1337
1338 if ((u = parseBytesUnits(units)) == 0) {
1339 self_destruct();
1340 return;
1341 }
1342
1343 if ((token = ConfigParser::NextToken()) == nullptr) {
1344 self_destruct();
1345 return;
1346 }
1347
1348 if (strcmp(token, "none") == 0 || token[0] == '-' /* -N */) {
1349 *bptr = -1;
1350 return;
1351 }
1352
1353 d = xatof(token);
1354
1355 m = u; /* default to 'units' if none specified */
1356
1357 if (0.0 == d)
1358 (void) 0;
1359 else if ((token = ConfigParser::NextToken()) == nullptr)
1360 debugs(3, DBG_CRITICAL, "WARNING: No units on '" <<
1361 config_input_line << "', assuming " <<
1362 d << " " << units );
1363 else if ((m = parseBytesUnits(token)) == 0) {
1364 self_destruct();
1365 return;
1366 }
1367
1368 *bptr = static_cast<ssize_t>(m * d / u);
1369
1370 if (static_cast<double>(*bptr) * 2 != (m * d / u) * 2) {
1371 debugs(3, DBG_CRITICAL, "ERROR: Invalid value '" <<
1372 d << " " << token << ": integer overflow (ssize_t).");
1373 self_destruct();
1374 }
1375}
1376
1382void
1383parseBytesOptionValue(size_t * bptr, const char *units, char const * value)
1384{
1385 int u;
1386 if ((u = parseBytesUnits(units)) == 0) {
1387 self_destruct();
1388 return;
1389 }
1390
1391 // Find number from string beginning.
1392 char const * number_begin = value;
1393 char const * number_end = value;
1394
1395 while ((*number_end >= '0' && *number_end <= '9')) {
1396 ++number_end;
1397 }
1398
1399 String number;
1400 number.assign(number_begin, number_end - number_begin);
1401
1402 int d = xatoi(number.termedBuf());
1403 int m;
1404 if ((m = parseBytesUnits(number_end)) == 0) {
1405 self_destruct();
1406 return;
1407 }
1408
1409 *bptr = static_cast<size_t>(m * d / u);
1410 if (static_cast<double>(*bptr) * 2 != (m * d / u) * 2)
1411 self_destruct();
1412}
1413
1414static size_t
1415parseBytesUnits(const char *unit)
1416{
1417 if (!strncasecmp(unit, B_BYTES_STR, strlen(B_BYTES_STR)))
1418 return 1;
1419
1420 if (!strncasecmp(unit, B_KBYTES_STR, strlen(B_KBYTES_STR)))
1421 return 1 << 10;
1422
1423 if (!strncasecmp(unit, B_MBYTES_STR, strlen(B_MBYTES_STR)))
1424 return 1 << 20;
1425
1426 if (!strncasecmp(unit, B_GBYTES_STR, strlen(B_GBYTES_STR)))
1427 return 1 << 30;
1428
1429 debugs(3, DBG_CRITICAL, "WARNING: Unknown bytes unit '" << unit << "'");
1430
1431 return 0;
1432}
1433
1434static void
1436{
1437 while (char *token = ConfigParser::NextQuotedToken())
1438 list->push_back(SBuf(token));
1439}
1440
1441// just dump a list, no directive name
1442static void
1443dump_SBufList(StoreEntry * entry, const SBufList &words)
1444{
1445 for (const auto &i : words) {
1446 entry->append(i.rawContent(), i.length());
1447 entry->append(" ",1);
1448 }
1449 entry->append("\n",1);
1450}
1451
1452// dump a SBufList type directive with name
1453static void
1454dump_SBufList(StoreEntry * entry, const char *name, SBufList &list)
1455{
1456 if (!list.empty()) {
1457 entry->append(name, strlen(name));
1458 entry->append(" ", 1);
1459 dump_SBufList(entry, list);
1460 }
1461}
1462
1463static void
1465{
1466 if (list)
1467 list->clear();
1468}
1469
1470static void
1471dump_acl(StoreEntry *entry, const char *directiveName, Acl::NamedAcls *config)
1472{
1473 PackableStream os(*entry);
1474 Acl::DumpNamedAcls(os, directiveName, config);
1475}
1476
1477static void
1479{
1480 assert(config);
1482}
1483
1484static void
1486{
1487 Acl::FreeNamedAcls(config);
1488}
1489
1490void
1492{
1493 // XXX: Should dump ACL names like "foo !bar" but dumps parsing context like
1494 // "(clientside_tos 0x11 line)".
1495 dump_SBufList(entry, ToTree(head).dump());
1496}
1497
1498void
1499dump_acl_access(StoreEntry * entry, const char *name, acl_access * head)
1500{
1501 if (head)
1502 dump_SBufList(entry, ToTree(head).treeDump(name, &Acl::AllowOrDeny));
1503}
1504
1505static void
1510
1511static void
1516
1517static void
1518dump_address(StoreEntry * entry, const char *name, Ip::Address &addr)
1519{
1520 char buf[MAX_IPSTRLEN];
1521 storeAppendPrintf(entry, "%s %s\n", name, addr.toStr(buf,MAX_IPSTRLEN) );
1522}
1523
1524static void
1526{
1527 char *token = ConfigParser::NextToken();
1528
1529 if (!token) {
1530 self_destruct();
1531 return;
1532 }
1533
1534 if (!strcmp(token,"any_addr"))
1535 addr->setAnyAddr();
1536 else if ( (!strcmp(token,"no_addr")) || (!strcmp(token,"full_mask")) )
1537 addr->setNoAddr();
1538 else if ( (*addr = token) ) // try parse numeric/IPA
1539 (void) 0;
1540 else if (addr->GetHostByName(token)) // do not use ipcache
1541 (void) 0;
1542 else { // not an IP and not a hostname
1543 debugs(3, DBG_CRITICAL, "FATAL: invalid IP address or domain name '" << token << "'");
1544 self_destruct();
1545 }
1546}
1547
1548static void
1550{
1551 addr->setEmpty();
1552}
1553
1554static void
1555dump_acl_address(StoreEntry * entry, const char *name, Acl::Address * head)
1556{
1557 char buf[MAX_IPSTRLEN];
1558
1559 for (Acl::Address *l = head; l; l = l->next) {
1560 if (!l->addr.isAnyAddr())
1561 storeAppendPrintf(entry, "%s %s", name, l->addr.toStr(buf,MAX_IPSTRLEN));
1562 else
1563 storeAppendPrintf(entry, "%s autoselect", name);
1564
1565 dump_acl_list(entry, l->aclList);
1566
1567 storeAppendPrintf(entry, "\n");
1568 }
1569}
1570
1571static void
1573{
1574 Acl::Address *l = new Acl::Address;
1575 parse_address(&l->addr);
1577
1578 Acl::Address **tail = head;
1579 while (*tail)
1580 tail = &(*tail)->next;
1581
1582 *tail = l;
1583}
1584
1585static void
1587{
1588 delete *head;
1589 *head = nullptr;
1590}
1591
1592static void
1593dump_acl_tos(StoreEntry * entry, const char *name, acl_tos * head)
1594{
1595 acl_tos *l;
1596
1597 for (l = head; l; l = l->next) {
1598 if (l->tos > 0)
1599 storeAppendPrintf(entry, "%s 0x%02X", name, l->tos);
1600 else
1601 storeAppendPrintf(entry, "%s none", name);
1602
1603 dump_acl_list(entry, l->aclList);
1604
1605 storeAppendPrintf(entry, "\n");
1606 }
1607}
1608
1609static void
1611{
1612 unsigned int tos; /* Initially uint for strtoui. Casted to tos_t before return */
1613 char *token = ConfigParser::NextToken();
1614
1615 if (!token) {
1616 self_destruct();
1617 return;
1618 }
1619
1620 if (!xstrtoui(token, nullptr, &tos, 0, std::numeric_limits<tos_t>::max())) {
1621 self_destruct();
1622 return;
1623 }
1624
1625 const unsigned int chTos = tos & 0xFC;
1626 if (chTos != tos) {
1627 debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: Tos value '" << tos << "' adjusted to '" << chTos << "'");
1628 tos = chTos;
1629 }
1630
1631 acl_tos *l = new acl_tos;
1632
1633 l->tos = (tos_t)tos;
1634
1636
1637 acl_tos **tail = head; /* sane name below */
1638 while (*tail)
1639 tail = &(*tail)->next;
1640
1641 *tail = l;
1642}
1643
1644static void
1646{
1647 delete *head;
1648 *head = nullptr;
1649}
1650
1651#if HAVE_LIBCAP && SO_MARK
1652
1653static void
1654dump_acl_nfmark(StoreEntry * entry, const char *name, acl_nfmark * head)
1655{
1656 for (acl_nfmark *l = head; l; l = l->next) {
1657 storeAppendPrintf(entry, "%s %s", name, ToSBuf(l->markConfig).c_str());
1658
1659 dump_acl_list(entry, l->aclList);
1660
1661 storeAppendPrintf(entry, "\n");
1662 }
1663}
1664
1665static void
1666parse_acl_nfmark(acl_nfmark ** head)
1667{
1669 const auto mc = Ip::NfMarkConfig::Parse(token);
1670
1671 // Packet marking directives should not allow to use masks.
1672 const auto pkt_dirs = {"mark_client_packet", "clientside_mark", "tcp_outgoing_mark"};
1673 if (mc.hasMask() && std::find(pkt_dirs.begin(), pkt_dirs.end(), cfg_directive) != pkt_dirs.end())
1674 throw TexcHere(ToSBuf("'", cfg_directive, "' does not support masked marks"));
1675
1676 acl_nfmark *l = new acl_nfmark;
1677 l->markConfig = mc;
1678
1679 aclParseAclList(LegacyParser, &l->aclList, token.c_str());
1680
1681 acl_nfmark **tail = head; /* sane name below */
1682 while (*tail)
1683 tail = &(*tail)->next;
1684
1685 *tail = l;
1686}
1687
1688static void
1689free_acl_nfmark(acl_nfmark ** head)
1690{
1691 delete *head;
1692 *head = nullptr;
1693}
1694#endif /* HAVE_LIBCAP && SO_MARK */
1695
1696static void
1697dump_acl_b_size_t(StoreEntry * entry, const char *name, AclSizeLimit * head)
1698{
1699 for (AclSizeLimit *l = head; l; l = l->next) {
1700 if (l->size != -1)
1701 storeAppendPrintf(entry, "%s %d %s\n", name, (int) l->size, B_BYTES_STR);
1702 else
1703 storeAppendPrintf(entry, "%s none", name);
1704
1705 dump_acl_list(entry, l->aclList);
1706
1707 storeAppendPrintf(entry, "\n");
1708 }
1709}
1710
1711static void
1713{
1714 AclSizeLimit *l = new AclSizeLimit;
1715
1716 parse_b_int64_t(&l->size);
1717
1719
1720 AclSizeLimit **tail = head; /* sane name below */
1721 while (*tail)
1722 tail = &(*tail)->next;
1723
1724 *tail = l;
1725}
1726
1727static void
1729{
1730 delete *head;
1731 *head = nullptr;
1732}
1733
1734#if USE_DELAY_POOLS
1735
1736#include "DelayConfig.h"
1737#include "DelayPools.h"
1738/* do nothing - free_delay_pool_count is the magic free function.
1739 * this is why delay_pool_count isn't just marked TYPE: u_short
1740 */
1741#define free_delay_pool_class(X)
1742#define free_delay_pool_access(X)
1743#define free_delay_pool_rates(X)
1744#define dump_delay_pool_class(X, Y, Z)
1745#define dump_delay_pool_access(X, Y, Z)
1746#define dump_delay_pool_rates(X, Y, Z)
1747
1748static void
1750{
1751 cfg->freePoolCount();
1752}
1753
1754static void
1755dump_delay_pool_count(StoreEntry * entry, const char *name, DelayConfig &cfg)
1756{
1757 cfg.dumpPoolCount (entry, name);
1758}
1759
1760static void
1762{
1763 cfg->parsePoolCount();
1764}
1765
1766static void
1768{
1769 cfg->parsePoolClass();
1770}
1771
1772static void
1774{
1775 cfg->parsePoolRates();
1776}
1777
1778static void
1783
1784#endif
1785
1786#if USE_DELAY_POOLS
1787#include "ClientDelayConfig.h"
1788/* do nothing - free_client_delay_pool_count is the magic free function.
1789 * this is why client_delay_pool_count isn't just marked TYPE: u_short
1790 */
1791
1792#define free_client_delay_pool_access(X)
1793#define free_client_delay_pool_rates(X)
1794#define dump_client_delay_pool_access(X, Y, Z)
1795#define dump_client_delay_pool_rates(X, Y, Z)
1796
1797static void
1802
1803static void
1805{
1806 cfg.dumpPoolCount (entry, name);
1807}
1808
1809static void
1814
1815static void
1820
1821static void
1826#endif
1827
1828#if USE_HTTP_VIOLATIONS
1829static void
1830dump_http_header_access(StoreEntry * entry, const char *name, const HeaderManglers *manglers)
1831{
1832 if (manglers)
1833 manglers->dumpAccess(entry, name);
1834}
1835
1836static void
1838{
1839 char *t = nullptr;
1840
1841 if ((t = ConfigParser::NextToken()) == nullptr) {
1842 debugs(3, DBG_CRITICAL, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
1843 debugs(3, DBG_CRITICAL, "ERROR: parse_http_header_access: missing header name.");
1844 return;
1845 }
1846
1847 if (!*pm)
1848 *pm = new HeaderManglers;
1849 HeaderManglers *manglers = *pm;
1850 headerMangler *mangler = manglers->track(t);
1851 assert(mangler);
1852
1853 std::string directive = "http_header_access ";
1854 directive += t;
1855 aclParseAccessLine(directive.c_str(), LegacyParser, &mangler->access_list);
1856}
1857
1858static void
1860{
1861 // we delete the entire http_header_* mangler configuration at once
1862 if (const HeaderManglers *manglers = *pm) {
1863 delete manglers;
1864 *pm = nullptr;
1865 }
1866}
1867
1868static void
1869dump_http_header_replace(StoreEntry * entry, const char *name, const HeaderManglers *manglers)
1870{
1871 if (manglers)
1872 manglers->dumpReplacement(entry, name);
1873}
1874
1875static void
1877{
1878 char *t = nullptr;
1879
1880 if ((t = ConfigParser::NextToken()) == nullptr) {
1881 debugs(3, DBG_CRITICAL, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
1882 debugs(3, DBG_CRITICAL, "ERROR: parse_http_header_replace: missing header name.");
1883 return;
1884 }
1885
1886 const char *value = ConfigParser::NextQuotedOrToEol();
1887
1888 if (!*pm)
1889 *pm = new HeaderManglers;
1890 HeaderManglers *manglers = *pm;
1891 manglers->setReplacement(t, value);
1892}
1893
1894#endif
1895
1896static void
1897dump_cachedir(StoreEntry * entry, const char *name, const Store::DiskConfig &swap)
1898{
1899 Store::Disks::Dump(swap, *entry, name);
1900}
1901
1902static int
1904{
1905 return s == nullptr;
1906}
1907
1908#if USE_AUTH
1909static void
1911{
1912 char *type_str = ConfigParser::NextToken();
1913 if (!type_str) {
1914 self_destruct();
1915 return;
1916 }
1917
1918 char *param_str = ConfigParser::NextToken();
1919 if (!param_str) {
1920 self_destruct();
1921 return;
1922 }
1923
1924 /* find a configuration for the scheme in the currently parsed configs... */
1925 Auth::SchemeConfig *schemeCfg = Auth::SchemeConfig::Find(type_str);
1926
1927 if (schemeCfg == nullptr) {
1928 /* Create a configuration based on the scheme info */
1929 Auth::Scheme::Pointer theScheme = Auth::Scheme::Find(type_str);
1930
1931 if (theScheme == nullptr) {
1932 debugs(3, DBG_CRITICAL, "ERROR: Failure while parsing Config File: Unknown authentication scheme '" << type_str << "'.");
1933 self_destruct();
1934 return;
1935 }
1936
1937 config->push_back(theScheme->createConfig());
1938 schemeCfg = Auth::SchemeConfig::Find(type_str);
1939 if (schemeCfg == nullptr) {
1940 debugs(3, DBG_CRITICAL, "Parsing Config File: Corruption configuring authentication scheme '" << type_str << "'.");
1941 self_destruct();
1942 return;
1943 }
1944 }
1945
1946 schemeCfg->parse(schemeCfg, config->size(), param_str);
1947}
1948
1949static void
1951{
1952 /* Wipe the Auth globals and Detach/Destruct component config + state. */
1953 cfg->clear();
1954
1955 /* on reconfigure initialize new auth schemes for the new config. */
1956 if (reconfiguring) {
1957 Auth::Init();
1958 }
1959}
1960
1961static void
1962dump_authparam(StoreEntry * entry, const char *name, Auth::ConfigVector cfg)
1963{
1964 for (auto *scheme : cfg)
1965 scheme->dump(entry, name, scheme);
1966}
1967
1968static void
1970{
1971 const char *tok = ConfigParser::NextQuotedToken();
1972 if (!tok) {
1973 debugs(29, DBG_CRITICAL, "FATAL: auth_schemes missing the parameter");
1974 self_destruct();
1975 return;
1976 }
1978 const auto action = Acl::Answer(ACCESS_ALLOWED, Auth::TheConfig.schemeLists.size() - 1);
1979 ParseAclWithAction(authSchemes, action, "auth_schemes");
1980}
1981
1982static void
1984{
1986 free_acl_access(authSchemes);
1987}
1988
1989static void
1990dump_AuthSchemes(StoreEntry *entry, const char *name, acl_access *authSchemes)
1991{
1992 if (authSchemes)
1993 dump_SBufList(entry, ToTree(authSchemes).treeDump(name, [](const Acl::Answer &action) {
1994 return Auth::TheConfig.schemeLists.at(action.kind).rawSchemes;
1995 }));
1996}
1997
1998#endif /* USE_AUTH */
1999
2000static void
2001ParseAclWithAction(acl_access **config, const Acl::Answer &action, const char *desc, Acl::Node *acl)
2002{
2003 assert(config);
2004 auto &access = *config;
2005 if (!access) {
2006 const auto tree = new Acl::Tree;
2007 tree->context(ToSBuf('(', desc, " rules)"), config_input_line);
2008 access = new acl_access(tree);
2009 }
2010 assert(access);
2011
2012 Acl::AndNode *rule = new Acl::AndNode;
2013 rule->context(ToSBuf('(', desc, " rule)"), config_input_line);
2014 if (acl)
2015 rule->add(acl);
2016 else
2017 rule->lineParse();
2018 (*access)->add(rule, action);
2019}
2020
2021static void
2023{
2024 assert(swap);
2025 Store::Disks::Parse(*swap);
2026}
2027
2028static const char *
2030{
2031 const char * result;
2032
2033 switch (type) {
2034
2035 case PEER_PARENT:
2036 result = "parent";
2037 break;
2038
2039 case PEER_SIBLING:
2040 result = "sibling";
2041 break;
2042
2043 case PEER_MULTICAST:
2044 result = "multicast";
2045 break;
2046
2047 default:
2048 result = "unknown";
2049 break;
2050 }
2051
2052 return result;
2053}
2054
2055static void
2056dump_peer(StoreEntry * entry, const char *name, const CachePeers *peers)
2057{
2058 if (!peers)
2059 return;
2060
2062 LOCAL_ARRAY(char, xname, 128);
2063
2064 for (const auto &peer: *peers) {
2065 const auto p = peer.get();
2066 storeAppendPrintf(entry, "%s %s %s %d %d name=%s",
2067 name,
2068 p->host,
2069 neighborTypeStr(p),
2070 p->http_port,
2071 p->icp.port,
2072 p->name);
2073 dump_peer_options(entry, p);
2074
2075 if (p->access) {
2076 snprintf(xname, 128, "cache_peer_access %s", p->name);
2077 dump_acl_access(entry, xname, p->access);
2078 }
2079
2080 for (t = p->typelist; t; t = t->next) {
2081 storeAppendPrintf(entry, "neighbor_type_domain %s %s %s\n",
2082 p->host,
2083 peer_type_str(t->type),
2084 t->domain);
2085 }
2086 }
2087}
2088
2093static bool
2094isUnsignedNumeric(const char *str, size_t len)
2095{
2096 if (len < 1) return false;
2097
2098 for (; len >0 && *str; ++str, --len) {
2099 if (! isdigit(*str))
2100 return false;
2101 }
2102 return true;
2103}
2104
2109static unsigned short
2110GetService(const char *proto)
2111{
2112 struct servent *port = nullptr;
2114 char *token = ConfigParser::NextToken();
2115 if (token == nullptr) {
2116 self_destruct();
2117 return 0; /* NEVER REACHED */
2118 }
2120 if ( !isUnsignedNumeric(token, strlen(token)) )
2121 port = xgetservbyname(token, proto);
2122 if (port != nullptr) {
2123 return ntohs((unsigned short)port->s_port);
2124 }
2126 return xatos(token);
2127}
2128
2133inline unsigned short
2135{
2136 return GetService("tcp");
2137}
2138
2143inline unsigned short
2145{
2146 return GetService("udp");
2147}
2148
2149static void
2151{
2152 char *host_str = ConfigParser::NextToken();
2153 if (!host_str) {
2154 self_destruct();
2155 return;
2156 }
2157
2158 char *token = ConfigParser::NextToken();
2159 if (!token) {
2160 self_destruct();
2161 return;
2162 }
2163
2164 const auto p = new CachePeer(host_str);
2165
2166 p->type = parseNeighborType(token);
2167
2168 if (p->type == PEER_MULTICAST) {
2169 p->options.no_digest = true;
2170 p->options.no_netdb_exchange = true;
2171 }
2172
2173 p->http_port = GetTcpService();
2174
2175 if (!p->http_port) {
2176 delete p;
2177 self_destruct();
2178 return;
2179 }
2180
2181 p->icp.port = GetUdpService();
2182
2183 while ((token = ConfigParser::NextToken())) {
2184 if (!strcmp(token, "proxy-only")) {
2185 p->options.proxy_only = true;
2186 } else if (!strcmp(token, "no-query")) {
2187 p->options.no_query = true;
2188 } else if (!strcmp(token, "background-ping")) {
2189 p->options.background_ping = true;
2190 } else if (!strcmp(token, "no-digest")) {
2191 p->options.no_digest = true;
2192 } else if (!strcmp(token, "no-tproxy")) {
2193 p->options.no_tproxy = true;
2194 } else if (!strcmp(token, "multicast-responder")) {
2195 p->options.mcast_responder = true;
2196 } else if (!strcmp(token, "multicast-siblings")) {
2197 p->options.mcast_siblings = true;
2198 } else if (!strncmp(token, "weight=", 7)) {
2199 p->weight = xatoi(token + 7);
2200 } else if (!strncmp(token, "basetime=", 9)) {
2201 p->basetime = xatoi(token + 9);
2202 } else if (!strcmp(token, "closest-only")) {
2203 p->options.closest_only = true;
2204 } else if (!strncmp(token, "ttl=", 4)) {
2205 p->mcast.ttl = xatoi(token + 4);
2206
2207 if (p->mcast.ttl < 0)
2208 p->mcast.ttl = 0;
2209
2210 if (p->mcast.ttl > 128)
2211 p->mcast.ttl = 128;
2212 } else if (!strcmp(token, "default")) {
2213 p->options.default_parent = true;
2214 } else if (!strcmp(token, "round-robin")) {
2215 p->options.roundrobin = true;
2216 } else if (!strcmp(token, "weighted-round-robin")) {
2217 p->options.weighted_roundrobin = true;
2218#if USE_HTCP
2219 } else if (!strcmp(token, "htcp")) {
2220 p->options.htcp = true;
2221 } else if (!strncmp(token, "htcp=", 5) || !strncmp(token, "htcp-", 5)) {
2222 /* Note: The htcp- form is deprecated, replaced by htcp= */
2223 p->options.htcp = true;
2224 char *tmp = xstrdup(token+5);
2225 char *mode, *nextmode;
2226 for (mode = nextmode = tmp; mode; mode = nextmode) {
2227 nextmode = strchr(mode, ',');
2228 if (nextmode) {
2229 *nextmode = '\0';
2230 ++nextmode;
2231 }
2232 if (!strcmp(mode, "no-clr")) {
2233 if (p->options.htcp_only_clr)
2234 fatalf("parse_peer: can't set htcp-no-clr and htcp-only-clr simultaneously");
2235 p->options.htcp_no_clr = true;
2236 } else if (!strcmp(mode, "no-purge-clr")) {
2237 p->options.htcp_no_purge_clr = true;
2238 } else if (!strcmp(mode, "only-clr")) {
2239 if (p->options.htcp_no_clr)
2240 fatalf("parse_peer: can't set htcp no-clr and only-clr simultaneously");
2241 p->options.htcp_only_clr = true;
2242 } else if (!strcmp(mode, "forward-clr")) {
2243 p->options.htcp_forward_clr = true;
2244 } else if (!strcmp(mode, "oldsquid")) {
2245 p->options.htcp_oldsquid = true;
2246 } else {
2247 fatalf("invalid HTCP mode '%s'", mode);
2248 }
2249 }
2250 safe_free(tmp);
2251#endif
2252 } else if (!strcmp(token, "no-netdb-exchange")) {
2253 p->options.no_netdb_exchange = true;
2254
2255 } else if (!strcmp(token, "carp")) {
2256 if (p->type != PEER_PARENT)
2257 throw TextException(ToSBuf("non-parent carp cache_peer ", *p), Here());
2258
2259 p->options.carp = true;
2260 } else if (!strncmp(token, "carp-key=", 9)) {
2261 if (p->options.carp != true)
2262 throw TextException(ToSBuf("carp-key specified on non-carp cache_peer ", *p), Here());
2263 p->options.carp_key.set = true;
2264 char *nextkey=token+strlen("carp-key="), *key=nextkey;
2265 for (; key; key = nextkey) {
2266 nextkey=strchr(key,',');
2267 if (nextkey) ++nextkey; // skip the comma, any
2268 if (0==strncmp(key,"scheme",6)) {
2269 p->options.carp_key.scheme = true;
2270 } else if (0==strncmp(key,"host",4)) {
2271 p->options.carp_key.host = true;
2272 } else if (0==strncmp(key,"port",4)) {
2273 p->options.carp_key.port = true;
2274 } else if (0==strncmp(key,"path",4)) {
2275 p->options.carp_key.path = true;
2276 } else if (0==strncmp(key,"params",6)) {
2277 p->options.carp_key.params = true;
2278 } else {
2279 fatalf("invalid carp-key '%s'",key);
2280 }
2281 }
2282 } else if (!strcmp(token, "userhash")) {
2283#if USE_AUTH
2284 if (p->type != PEER_PARENT)
2285 throw TextException(ToSBuf("non-parent userhash cache_peer ", *p), Here());
2286
2287 p->options.userhash = true;
2288#else
2289 throw TextException(ToSBuf("missing authentication support; required for userhash cache_peer ", *p), Here());
2290#endif
2291 } else if (!strcmp(token, "sourcehash")) {
2292 if (p->type != PEER_PARENT)
2293 throw TextException(ToSBuf("non-parent sourcehash cache_peer ", *p), Here());
2294
2295 p->options.sourcehash = true;
2296
2297 } else if (!strcmp(token, "no-delay")) {
2298#if USE_DELAY_POOLS
2299 p->options.no_delay = true;
2300#else
2301 debugs(0, DBG_CRITICAL, "WARNING: cache_peer option 'no-delay' requires --enable-delay-pools");
2302#endif
2303 } else if (!strncmp(token, "login=", 6)) {
2304 p->login = xstrdup(token + 6);
2305 rfc1738_unescape(p->login);
2306 } else if (!strcmp(token, "auth-no-keytab")) {
2307 p->options.auth_no_keytab = 1;
2308 } else if (!strncmp(token, "connect-timeout=", 16)) {
2309 p->connect_timeout_raw = xatoi(token + 16);
2310 } else if (!strncmp(token, "connect-fail-limit=", 19)) {
2311 p->connect_fail_limit = xatoi(token + 19);
2312#if USE_CACHE_DIGESTS
2313 } else if (!strncmp(token, "digest-url=", 11)) {
2314 p->digest_url = xstrdup(token + 11);
2315#endif
2316
2317 } else if (!strcmp(token, "allow-miss")) {
2318 p->options.allow_miss = true;
2319 } else if (!strncmp(token, "max-conn=", 9)) {
2320 p->max_conn = xatoi(token + 9);
2321 } else if (!strncmp(token, "standby=", 8)) {
2322 p->standby.limit = xatoi(token + 8);
2323 } else if (!strcmp(token, "originserver")) {
2324 p->options.originserver = true;
2325 } else if (!strncmp(token, "name=", 5)) {
2326 p->rename(token + 5);
2327 } else if (!strncmp(token, "forceddomain=", 13)) {
2328 safe_free(p->domain);
2329 if (token[13])
2330 p->domain = xstrdup(token + 13);
2331
2332 } else if (strncmp(token, "ssl", 3) == 0) {
2333#if !USE_OPENSSL
2334 debugs(0, DBG_CRITICAL, "WARNING: cache_peer option '" << token << "' requires --with-openssl");
2335#else
2336 p->secure.parse(token+3);
2337#endif
2338 } else if (strncmp(token, "tls-", 4) == 0) {
2339 p->secure.parse(token+4);
2340 } else if (strncmp(token, "tls", 3) == 0) {
2341 p->secure.parse(token+3);
2342 } else if (strcmp(token, "front-end-https") == 0) {
2343 p->front_end_https = 1;
2344 } else if (strcmp(token, "front-end-https=on") == 0) {
2345 p->front_end_https = 1;
2346 } else if (strcmp(token, "front-end-https=auto") == 0) {
2347 p->front_end_https = 2;
2348 } else if (strcmp(token, "connection-auth=off") == 0) {
2349 p->connection_auth = 0;
2350 } else if (strcmp(token, "connection-auth") == 0) {
2351 p->connection_auth = 1;
2352 } else if (strcmp(token, "connection-auth=on") == 0) {
2353 p->connection_auth = 1;
2354 } else if (strcmp(token, "connection-auth=auto") == 0) {
2355 p->connection_auth = 2;
2356 } else if (token[0] == '#') {
2357 // start of a text comment. stop reading this line.
2358 break;
2359 } else {
2360 debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: Ignoring unknown cache_peer option '" << token << "'");
2361 }
2362 }
2363
2364 if (findCachePeerByName(p->name))
2365 throw TextException(ToSBuf("cache_peer ", *p, " specified twice"), Here());
2366
2367 if (p->max_conn > 0 && p->max_conn < p->standby.limit)
2368 throw TextException(ToSBuf("cache_peer ", *p, " max-conn=", p->max_conn,
2369 " is lower than its standby=", p->standby.limit), Here());
2370
2371 if (p->weight < 1)
2372 p->weight = 1;
2373
2374 if (p->connect_fail_limit < 1)
2375 p->connect_fail_limit = 10;
2376
2377#if USE_CACHE_DIGESTS
2378 if (!p->options.no_digest)
2379 p->digest = new PeerDigest(p);
2380#endif
2381
2382 if (p->secure.encryptTransport)
2383 p->secure.parseOptions();
2384
2385 if (!*peers)
2386 *peers = new CachePeers;
2387
2388 (*peers)->add(p);
2389
2390 p->index = (*peers)->size();
2391
2393}
2394
2395static void
2396free_peer(CachePeers ** const peers)
2397{
2398 delete *peers;
2399 *peers = nullptr;
2400}
2401
2402static void
2404{
2405 while (list) {
2406 if (strcmp(list->passwd, "none") && strcmp(list->passwd, "disable"))
2407 storeAppendPrintf(entry, "%s XXXXXXXXXX", name);
2408 else
2409 storeAppendPrintf(entry, "%s %s", name, list->passwd);
2410
2411 for (auto w : list->actions)
2412 entry->appendf(" " SQUIDSBUFPH, SQUIDSBUFPRINT(w));
2413
2414 storeAppendPrintf(entry, "\n");
2415 list = list->next;
2416 }
2417}
2418
2419static void
2421{
2422 char *passwd = nullptr;
2423 parse_string(&passwd);
2424
2426 p->passwd = passwd;
2427
2428 while (char *token = ConfigParser::NextQuotedToken())
2429 p->actions.push_back(SBuf(token));
2430
2432 for (P = head; *P; P = &(*P)->next) {
2433 /*
2434 * See if any of the actions from this line already have a
2435 * password from previous lines. The password checking
2436 * routines in cache_manager.c take the the password from
2437 * the first Mgr::ActionPasswordList that contains the
2438 * requested action. Thus, we should warn users who might
2439 * think they can have two passwords for the same action.
2440 */
2441 for (const auto &w : (*P)->actions) {
2442 for (const auto &u : p->actions) {
2443 if (w != u)
2444 continue;
2445
2446 debugs(0, DBG_PARSE_NOTE(1), "ERROR: action '" << u << "' (line " << config_lineno << ") already has a password");
2447 }
2448 }
2449 }
2450
2451 *P = p;
2452}
2453
2454static void
2456{
2457 delete *head;
2458 *head = nullptr;
2459}
2460
2461static void
2462dump_denyinfo(StoreEntry * entry, const char *name, AclDenyInfoList * var)
2463{
2464 while (var != nullptr) {
2465 storeAppendPrintf(entry, "%s %s", name, var->err_page_name);
2466
2467 for (const auto &aclName: var->acl_list)
2468 storeAppendPrintf(entry, " " SQUIDSBUFPH, SQUIDSBUFPRINT(aclName));
2469
2470 storeAppendPrintf(entry, "\n");
2471
2472 var = var->next;
2473 }
2474}
2475
2476static void
2481
2482void
2484{
2485 delete *list;
2486 *list = nullptr;
2487}
2488
2489static void
2491{
2492 auto &p = LegacyParser.cachePeer("cache_peer_access peer-name");
2493 std::string directive = "peer_access ";
2494 directive += p.name;
2495 aclParseAccessLine(directive.c_str(), LegacyParser, &p.access);
2496}
2497
2498static void
2500{
2501 auto &p = LegacyParser.cachePeer("neighbor_type_domain peer-name");
2502
2503 char *type = ConfigParser::NextToken();
2504 if (!type) {
2505 self_destruct();
2506 return;
2507 }
2508
2509 char *domain = nullptr;
2510 while ((domain = ConfigParser::NextToken())) {
2511 auto *l = static_cast<NeighborTypeDomainList *>(xcalloc(1, sizeof(NeighborTypeDomainList)));
2512 l->type = parseNeighborType(type);
2513 l->domain = xstrdup(domain);
2514
2515 NeighborTypeDomainList **L = nullptr;
2516 for (L = &p.typelist; *L; L = &((*L)->next));
2517 *L = l;
2518 }
2519}
2520
2521static void
2522dump_int(StoreEntry * entry, const char *name, int var)
2523{
2524 storeAppendPrintf(entry, "%s %d\n", name, var);
2525}
2526
2527void
2528parse_int(int *var)
2529{
2530 int i;
2531 i = GetInteger();
2532 *var = i;
2533}
2534
2535static void
2536free_int(int *var)
2537{
2538 *var = 0;
2539}
2540
2541static void
2542dump_int64_t(StoreEntry * entry, const char *name, int64_t var)
2543{
2544 storeAppendPrintf(entry, "%s %" PRId64 "\n", name, var);
2545}
2546
2547static void
2548parse_int64_t(int64_t *var)
2549{
2550 int64_t i;
2551 i = GetInteger64();
2552 *var = i;
2553}
2554
2555static void
2556free_int64_t(int64_t *var)
2557{
2558 *var = 0;
2559}
2560
2561static void
2562dump_onoff(StoreEntry * entry, const char *name, int var)
2563{
2564 storeAppendPrintf(entry, "%s %s\n", name, var ? "on" : "off");
2565}
2566
2567void
2569{
2570 char *token = ConfigParser::NextToken();
2571 if (!token) {
2572 self_destruct();
2573 return;
2574 }
2575
2576 if (!strcmp(token, "on")) {
2577 *var = 1;
2578 } else if (!strcmp(token, "enable")) {
2579 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: 'enable' is deprecated. Please update to use 'on'.");
2580 *var = 1;
2581 } else if (!strcmp(token, "off")) {
2582 *var = 0;
2583 } else if (!strcmp(token, "disable")) {
2584 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: 'disable' is deprecated. Please update to use 'off'.");
2585 *var = 0;
2586 } else {
2587 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: Invalid option: Boolean options can only be 'on' or 'off'.");
2588 self_destruct();
2589 }
2590}
2591
2592#define free_onoff free_int
2593
2594static void
2595dump_tristate(StoreEntry * entry, const char *name, int var)
2596{
2597 const char *state;
2598
2599 if (var > 0)
2600 state = "on";
2601 else if (var < 0)
2602 state = "warn";
2603 else
2604 state = "off";
2605
2606 storeAppendPrintf(entry, "%s %s\n", name, state);
2607}
2608
2609static void
2611{
2612 char *token = ConfigParser::NextToken();
2613 if (!token) {
2614 self_destruct();
2615 return;
2616 }
2617
2618 if (!strcmp(token, "on")) {
2619 *var = 1;
2620 } else if (!strcmp(token, "enable")) {
2621 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: 'enable' is deprecated. Please update to use value 'on'.");
2622 *var = 1;
2623 } else if (!strcmp(token, "warn")) {
2624 *var = -1;
2625 } else if (!strcmp(token, "off")) {
2626 *var = 0;
2627 } else if (!strcmp(token, "disable")) {
2628 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: 'disable' is deprecated. Please update to use value 'off'.");
2629 *var = 0;
2630 } else {
2631 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: Invalid option: Tristate options can only be 'on', 'off', or 'warn'.");
2632 self_destruct();
2633 }
2634}
2635
2636#define free_tristate free_int
2637
2638static void
2640{
2641 char *token = ConfigParser::PeekAtToken();
2642 if (!token) {
2643 self_destruct();
2644 return;
2645 }
2646
2647 if (!strcmp(token, "on")) {
2648 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: 'pipeline_prefetch on' is deprecated. Please update to use 1 (or a higher number).");
2649 *var = 1;
2650 //pop the token
2652 } else if (!strcmp(token, "off")) {
2653 debugs(0, DBG_PARSE_NOTE(2), "WARNING: 'pipeline_prefetch off' is deprecated. Please update to use '0'.");
2654 *var = 0;
2655 //pop the token
2657 } else
2658 parse_int(var);
2659}
2660
2661#define free_pipelinePrefetch free_int
2662#define dump_pipelinePrefetch dump_int
2663
2664static void
2666{
2667 while (head != nullptr) {
2668 PackableStream os(*entry);
2669 os << name << ' ';
2670 head->printHead(os);
2671
2672 if (head->max_stale >= 0)
2673 storeAppendPrintf(entry, " max-stale=%d", head->max_stale);
2674
2675 if (head->flags.refresh_ims)
2676 storeAppendPrintf(entry, " refresh-ims");
2677
2678 if (head->flags.store_stale)
2679 storeAppendPrintf(entry, " store-stale");
2680
2681#if USE_HTTP_VIOLATIONS
2682
2683 if (head->flags.override_expire)
2684 storeAppendPrintf(entry, " override-expire");
2685
2686 if (head->flags.override_lastmod)
2687 storeAppendPrintf(entry, " override-lastmod");
2688
2689 if (head->flags.reload_into_ims)
2690 storeAppendPrintf(entry, " reload-into-ims");
2691
2692 if (head->flags.ignore_reload)
2693 storeAppendPrintf(entry, " ignore-reload");
2694
2695 if (head->flags.ignore_no_store)
2696 storeAppendPrintf(entry, " ignore-no-store");
2697
2698 if (head->flags.ignore_private)
2699 storeAppendPrintf(entry, " ignore-private");
2700#endif
2701
2702 storeAppendPrintf(entry, "\n");
2703
2704 head = head->next;
2705 }
2706}
2707
2708static void
2710{
2711 char *token;
2712 time_t min = 0;
2713 double pct = 0.0;
2714 time_t max = 0;
2715 int refresh_ims = 0;
2716 int store_stale = 0;
2717 int max_stale = -1;
2718
2719#if USE_HTTP_VIOLATIONS
2720
2721 int override_expire = 0;
2722 int override_lastmod = 0;
2723 int reload_into_ims = 0;
2724 int ignore_reload = 0;
2725 int ignore_no_store = 0;
2726 int ignore_private = 0;
2727#endif
2728
2729 int i;
2730 RefreshPattern *t;
2731
2732 auto regex = LegacyParser.regex("refresh_pattern regex");
2733
2734 i = GetInteger(); /* token: min */
2735
2736 /* catch negative and insanely huge values close to 32-bit wrap */
2737 if (i < 0) {
2738 debugs(3, DBG_IMPORTANT, "WARNING: refresh_pattern minimum age negative. Cropped back to zero.");
2739 i = 0;
2740 }
2741 if (i > 60*24*365) {
2742 debugs(3, DBG_IMPORTANT, "WARNING: refresh_pattern minimum age too high. Cropped back to 1 year.");
2743 i = 60*24*365;
2744 }
2745
2746 min = (time_t) (i * 60); /* convert minutes to seconds */
2747
2748 pct = GetPercentage(false); /* token: pct . with no limit on size */
2749
2750 i = GetInteger(); /* token: max */
2751
2752 /* catch negative and insanely huge values close to 32-bit wrap */
2753 if (i < 0) {
2754 debugs(3, DBG_IMPORTANT, "WARNING: refresh_pattern maximum age negative. Cropped back to zero.");
2755 i = 0;
2756 }
2757 if (i > 60*24*365) {
2758 debugs(3, DBG_IMPORTANT, "WARNING: refresh_pattern maximum age too high. Cropped back to 1 year.");
2759 i = 60*24*365;
2760 }
2761
2762 max = (time_t) (i * 60); /* convert minutes to seconds */
2763
2764 /* Options */
2765 while ((token = ConfigParser::NextToken()) != nullptr) {
2766 if (!strcmp(token, "refresh-ims")) {
2767 refresh_ims = 1;
2768 } else if (!strcmp(token, "store-stale")) {
2769 store_stale = 1;
2770 } else if (!strncmp(token, "max-stale=", 10)) {
2771 max_stale = xatoi(token + 10);
2772
2773#if USE_HTTP_VIOLATIONS
2774
2775 } else if (!strcmp(token, "override-expire"))
2776 override_expire = 1;
2777 else if (!strcmp(token, "override-lastmod"))
2778 override_lastmod = 1;
2779 else if (!strcmp(token, "ignore-no-store"))
2780 ignore_no_store = 1;
2781 else if (!strcmp(token, "ignore-private"))
2782 ignore_private = 1;
2783 else if (!strcmp(token, "reload-into-ims")) {
2784 reload_into_ims = 1;
2786 /* tell client_side.c that this is used */
2787 } else if (!strcmp(token, "ignore-reload")) {
2788 ignore_reload = 1;
2790 /* tell client_side.c that this is used */
2791#endif
2792
2793 } else if (!strcmp(token, "ignore-no-cache") ||
2794 !strcmp(token, "ignore-must-revalidate") ||
2795 !strcmp(token, "ignore-auth")
2796 ) {
2797 debugs(22, DBG_PARSE_NOTE(2), "UPGRADE: refresh_pattern option '" << token << "' is obsolete. Remove it.");
2798 } else
2799 debugs(22, DBG_CRITICAL, "ERROR: Unknown refresh_pattern option: " << token);
2800 }
2801
2802 pct = pct < 0.0 ? 0.0 : pct;
2803 max = max < 0 ? 0 : max;
2804 t = new RefreshPattern(std::move(regex));
2805 t->min = min;
2806 t->pct = pct;
2807 t->max = max;
2808
2809 if (refresh_ims)
2810 t->flags.refresh_ims = true;
2811
2812 if (store_stale)
2813 t->flags.store_stale = true;
2814
2815 t->max_stale = max_stale;
2816
2817#if USE_HTTP_VIOLATIONS
2818
2819 if (override_expire)
2820 t->flags.override_expire = true;
2821
2822 if (override_lastmod)
2823 t->flags.override_lastmod = true;
2824
2825 if (reload_into_ims)
2826 t->flags.reload_into_ims = true;
2827
2828 if (ignore_reload)
2829 t->flags.ignore_reload = true;
2830
2831 if (ignore_no_store)
2832 t->flags.ignore_no_store = true;
2833
2834 if (ignore_private)
2835 t->flags.ignore_private = true;
2836#endif
2837
2838 t->next = nullptr;
2839
2840 while (*head)
2841 head = &(*head)->next;
2842
2843 *head = t;
2844}
2845
2846static void
2848{
2849 delete *head;
2850 *head = nullptr;
2851
2852#if USE_HTTP_VIOLATIONS
2854
2855#endif
2856}
2857
2858static void
2859dump_string(StoreEntry * entry, const char *name, char *var)
2860{
2861 if (var != nullptr)
2862 storeAppendPrintf(entry, "%s %s\n", name, var);
2863}
2864
2865static void
2866parse_string(char **var)
2867{
2868 safe_free(*var);
2869
2870 char *token = ConfigParser::NextToken();
2871 if (!token) {
2872 self_destruct();
2873 return;
2874 }
2875
2876 *var = xstrdup(token);
2877}
2878
2879static void
2880free_string(char **var)
2881{
2882 safe_free(*var);
2883}
2884
2885void
2886parse_eol(char *volatile *var)
2887{
2888 if (!var) {
2889 self_destruct();
2890 return;
2891 }
2892
2893 unsigned char *token = (unsigned char *) ConfigParser::NextQuotedOrToEol();
2894 safe_free(*var);
2895
2896 if (!token) {
2897 self_destruct();
2898 return;
2899 }
2900
2901 while (*token && xisspace(*token))
2902 ++token;
2903
2904 if (!*token) {
2905 self_destruct();
2906 return;
2907 }
2908
2909 *var = xstrdup((char *) token);
2910}
2911
2912#define dump_eol dump_string
2913#define free_eol free_string
2914
2915static void
2917{
2918 safe_free(*var);
2919
2920 char *token = ConfigParser::NextQuotedToken();
2921 if (!token) {
2922 self_destruct();
2923 return;
2924 }
2925
2926 *var = xstrdup(token);
2927}
2928
2929#define dump_TokenOrQuotedString dump_string
2930#define free_TokenOrQuotedString free_string
2931
2932static void
2933dump_time_t(StoreEntry * entry, const char *name, time_t var)
2934{
2935 PackableStream os(*entry);
2936 os << name << ' ' << var << " seconds\n";
2937}
2938
2939void
2940parse_time_t(time_t * var)
2941{
2942 const auto maxTime = std::numeric_limits<time_t>::max();
2943 const auto seconds = parseTimeLine<std::chrono::seconds>();
2944 if (maxTime < seconds.count())
2945 throw TexcHere(ToSBuf("directive supports time values up to ", maxTime, " but is given ", seconds.count(), " seconds"));
2946 *var = static_cast<time_t>(seconds.count());
2947}
2948
2949static void
2950free_time_t(time_t * var)
2951{
2952 *var = 0;
2953}
2954
2955static void
2956dump_time_msec(StoreEntry * entry, const char *name, time_msec_t var)
2957{
2958 PackableStream os(*entry);
2959 if (var % 1000)
2960 os << name << ' ' << var << " milliseconds\n";
2961 else
2962 os << name << ' ' << (var/1000) << " seconds\n";
2963}
2964
2965static void
2967{
2968 *var = parseTimeLine<std::chrono::milliseconds>().count();
2969}
2970
2971static void
2973{
2974 *var = 0;
2975}
2976
2977static void
2978dump_time_nanoseconds(StoreEntry *entry, const char *name, const std::chrono::nanoseconds &var)
2979{
2980 // std::chrono::nanoseconds::rep is unknown a priori so we cast to (and print) the largest supported integer
2981 storeAppendPrintf(entry, "%s %jd nanoseconds\n", name, static_cast<intmax_t>(var.count()));
2982}
2983
2984static void
2985parse_time_nanoseconds(std::chrono::nanoseconds *var)
2986{
2987 *var = parseTimeLine<std::chrono::nanoseconds>();
2988}
2989
2990static void
2991free_time_nanoseconds(std::chrono::nanoseconds *var)
2992{
2993 *var = std::chrono::nanoseconds::zero();
2994}
2995
2996static void
2997dump_b_size_t(StoreEntry * entry, const char *name, size_t var)
2998{
2999 storeAppendPrintf(entry, "%s %d %s\n", name, (int) var, B_BYTES_STR);
3000}
3001
3002static void
3003dump_b_ssize_t(StoreEntry * entry, const char *name, ssize_t var)
3004{
3005 storeAppendPrintf(entry, "%s %d %s\n", name, (int) var, B_BYTES_STR);
3006}
3007
3008static void
3009dump_b_int64_t(StoreEntry * entry, const char *name, int64_t var)
3010{
3011 storeAppendPrintf(entry, "%s %" PRId64 " %s\n", name, var, B_BYTES_STR);
3012}
3013
3014static void
3015dump_kb_int64_t(StoreEntry * entry, const char *name, int64_t var)
3016{
3017 storeAppendPrintf(entry, "%s %" PRId64 " %s\n", name, var, B_KBYTES_STR);
3018}
3019
3020static void
3021parse_b_size_t(size_t * var)
3022{
3024}
3025
3026static void
3027parse_b_ssize_t(ssize_t * var)
3028{
3030}
3031
3032static void
3033parse_b_int64_t(int64_t * var)
3034{
3036}
3037
3038static void
3039parse_kb_int64_t(int64_t * var)
3040{
3042}
3043
3044static void
3045free_size_t(size_t * var)
3046{
3047 *var = 0;
3048}
3049
3050static void
3051free_ssize_t(ssize_t * var)
3052{
3053 *var = 0;
3054}
3055
3056static void
3057free_b_int64_t(int64_t * var)
3058{
3059 *var = 0;
3060}
3061
3062#define free_b_size_t free_size_t
3063#define free_b_ssize_t free_ssize_t
3064#define free_kb_size_t free_size_t
3065#define free_mb_size_t free_size_t
3066#define free_gb_size_t free_size_t
3067#define free_kb_int64_t free_b_int64_t
3068
3069static void
3070dump_u_short(StoreEntry * entry, const char *name, unsigned short var)
3071{
3072 storeAppendPrintf(entry, "%s %d\n", name, var);
3073}
3074
3075static void
3076free_u_short(unsigned short * u)
3077{
3078 *u = 0;
3079}
3080
3081static void
3082parse_u_short(unsigned short * var)
3083{
3085}
3086
3087void
3088ConfigParser::ParseUShort(unsigned short *var)
3089{
3090 *var = GetShort();
3091}
3092
3093void
3095{
3096 int i = GetInteger();
3097
3098 if (0 == i)
3099 *var = false;
3100 else if (1 == i)
3101 *var = true;
3102 else
3103 self_destruct();
3104}
3105
3106static void
3107dump_wordlist(StoreEntry * entry, const char *name, wordlist * list)
3108{
3109 while (list != nullptr) {
3110 storeAppendPrintf(entry, "%s %s\n", name, list->key);
3111 list = list->next;
3112 }
3113}
3114
3115void
3117{
3118 parse_wordlist(list);
3119}
3120
3121void
3123{
3124 char *token;
3125 while ((token = ConfigParser::NextQuotedToken()))
3126 wordlistAdd(list, token);
3127}
3128
3129static int
3131{
3132 return a == nullptr;
3133}
3134
3135#define free_wordlist wordlistDestroy
3136
3137#define free_uri_whitespace free_int
3138
3139static void
3141{
3142 char *token = ConfigParser::NextToken();
3143 if (!token) {
3144 self_destruct();
3145 return;
3146 }
3147
3148 if (!strcmp(token, "strip"))
3149 *var = URI_WHITESPACE_STRIP;
3150 else if (!strcmp(token, "deny"))
3151 *var = URI_WHITESPACE_DENY;
3152 else if (!strcmp(token, "allow"))
3153 *var = URI_WHITESPACE_ALLOW;
3154 else if (!strcmp(token, "encode"))
3155 *var = URI_WHITESPACE_ENCODE;
3156 else if (!strcmp(token, "chop"))
3157 *var = URI_WHITESPACE_CHOP;
3158 else {
3159 debugs(0, DBG_PARSE_NOTE(2), "ERROR: Invalid option '" << token << "': 'uri_whitespace' accepts 'strip', 'deny', 'allow', 'encode', and 'chop'.");
3160 self_destruct();
3161 }
3162}
3163
3164static void
3165dump_uri_whitespace(StoreEntry * entry, const char *name, int var)
3166{
3167 const char *s;
3168
3169 if (var == URI_WHITESPACE_ALLOW)
3170 s = "allow";
3171 else if (var == URI_WHITESPACE_ENCODE)
3172 s = "encode";
3173 else if (var == URI_WHITESPACE_CHOP)
3174 s = "chop";
3175 else if (var == URI_WHITESPACE_DENY)
3176 s = "deny";
3177 else
3178 s = "strip";
3179
3180 storeAppendPrintf(entry, "%s %s\n", name, s);
3181}
3182
3183static void
3185{
3186 if (!*settings)
3187 return;
3188
3189 free_string(&(*settings)->type);
3190
3191 free_wordlist(&(*settings)->args);
3192
3193 delete *settings;
3194
3195 *settings = nullptr;
3196}
3197
3198static void
3200{
3201 if (*settings)
3202 free_removalpolicy(settings);
3203
3204 *settings = new RemovalPolicySettings;
3205
3206 parse_string(&(*settings)->type);
3207
3208 parse_wordlist(&(*settings)->args);
3209}
3210
3211static void
3212dump_removalpolicy(StoreEntry * entry, const char *name, RemovalPolicySettings * settings)
3213{
3214 wordlist *args;
3215 storeAppendPrintf(entry, "%s %s", name, settings->type);
3216 args = settings->args;
3217
3218 while (args) {
3219 storeAppendPrintf(entry, " %s", args->key);
3220 args = args->next;
3221 }
3222
3223 storeAppendPrintf(entry, "\n");
3224}
3225
3226inline void
3229
3230static void
3232{
3233 int value = 0;
3234 parse_onoff(&value);
3235 option->configure(value > 0);
3236}
3237
3238static void
3239dump_YesNoNone(StoreEntry * entry, const char *name, YesNoNone &option)
3240{
3241 if (option.configured())
3242 dump_onoff(entry, name, option ? 1 : 0);
3243}
3244
3245static void
3248
3249static void
3251{
3252 char *token = ConfigParser::NextToken();
3253 if (!token) {
3254 self_destruct();
3255 return;
3256 }
3257
3258 if (strcmp(token, "always") == 0) {
3261 } else if (strcmp(token, "disk") == 0) {
3264 } else if (strncmp(token, "net", 3) == 0) {
3267 } else if (strcmp(token, "never") == 0) {
3270 } else {
3271 debugs(0, DBG_PARSE_NOTE(2), "ERROR: Invalid option '" << token << "': 'memory_cache_mode' accepts 'always', 'disk', 'network', and 'never'.");
3272 self_destruct();
3273 }
3274}
3275
3276static void
3277dump_memcachemode(StoreEntry * entry, const char *name, SquidConfig &)
3278{
3279 storeAppendPrintf(entry, "%s ", name);
3281 storeAppendPrintf(entry, "always");
3283 storeAppendPrintf(entry, "disk");
3285 storeAppendPrintf(entry, "network");
3287 storeAppendPrintf(entry, "none");
3288 storeAppendPrintf(entry, "\n");
3289}
3290
3291#include "cf_parser.cci"
3292
3293peer_t
3294parseNeighborType(const char *s)
3295{
3296 if (!strcmp(s, "parent"))
3297 return PEER_PARENT;
3298
3299 if (!strcmp(s, "neighbor"))
3300 return PEER_SIBLING;
3301
3302 if (!strcmp(s, "neighbour"))
3303 return PEER_SIBLING;
3304
3305 if (!strcmp(s, "sibling"))
3306 return PEER_SIBLING;
3307
3308 if (!strcmp(s, "multicast"))
3309 return PEER_MULTICAST;
3310
3311 debugs(15, DBG_CRITICAL, "WARNING: Unknown neighbor type: " << s);
3312
3313 return PEER_SIBLING;
3314}
3315
3316#if USE_WCCPv2
3317static void
3319{
3320 char *token;
3322 Ip::Address ipa;
3323
3324 while ((token = ConfigParser::NextToken())) {
3325 if (GetHostWithPort(token, &ipa)) {
3326
3327 while (*head)
3328 head = &(*head)->next;
3329
3330 s = static_cast<Ip::Address_list *>(xcalloc(1, sizeof(*s)));
3331 s->s = ipa;
3332
3333 *head = s;
3334 } else {
3335 self_destruct();
3336 return;
3337 }
3338 }
3339}
3340
3341static void
3343{
3344 char ntoabuf[MAX_IPSTRLEN];
3345
3346 while (s) {
3347 storeAppendPrintf(e, "%s %s\n",
3348 n,
3349 s->s.toStr(ntoabuf,MAX_IPSTRLEN));
3350 s = s->next;
3351 }
3352}
3353
3354static void
3356{
3357 if (*head) delete *head;
3358 *head = nullptr;
3359}
3360
3361#if CURRENTLY_UNUSED
3362/* This code was previously used by http_port. Left as it really should
3363 * be used by icp_port and htcp_port
3364 */
3365static int
3366check_null_IpAddress_list(const Ip::Address_list * s)
3367{
3368 return NULL == s;
3369}
3370
3371#endif /* CURRENTLY_UNUSED */
3372#endif /* USE_WCCPv2 */
3373
3374static void
3376{
3377 char *host = nullptr;
3378 unsigned short port = 0;
3379 char *t = nullptr;
3380 char *junk = nullptr;
3381
3382 s->disable_pmtu_discovery = DISABLE_PMTU_OFF;
3383 s->name = xstrdup(token);
3384 s->connection_auth_disabled = false;
3385
3386 const SBuf &portType = AnyP::UriScheme(s->transport.protocol).image();
3387
3388 if (*token == '[') {
3389 /* [ipv6]:port */
3390 host = token + 1;
3391 t = strchr(host, ']');
3392 if (!t) {
3393 debugs(3, DBG_CRITICAL, "FATAL: " << portType << "_port: missing ']' on IPv6 address: " << token);
3394 self_destruct();
3395 return;
3396 }
3397 *t = '\0';
3398 ++t;
3399 if (*t != ':') {
3400 debugs(3, DBG_CRITICAL, "FATAL: " << portType << "_port: missing Port in: " << token);
3401 self_destruct();
3402 return;
3403 }
3404 if (!Ip::EnableIpv6) {
3405 debugs(3, DBG_CRITICAL, "FATAL: " << portType << "_port: IPv6 is not available.");
3406 self_destruct();
3407 return;
3408 }
3409 port = xatos(t + 1);
3410 } else if ((t = strchr(token, ':'))) {
3411 /* host:port */
3412 /* ipv4:port */
3413 host = token;
3414 *t = '\0';
3415 port = xatos(t + 1);
3416
3417 } else if (strtol(token, &junk, 10) && !*junk) {
3418 port = xatos(token);
3419 debugs(3, 3, portType << "_port: found Listen on Port: " << port);
3420 } else {
3421 debugs(3, DBG_CRITICAL, "FATAL: " << portType << "_port: missing Port: " << token);
3422 self_destruct();
3423 return;
3424 }
3425
3426 if (port == 0 && host != nullptr) {
3427 debugs(3, DBG_CRITICAL, "FATAL: " << portType << "_port: Port cannot be 0: " << token);
3428 self_destruct();
3429 return;
3430 }
3431
3432 if (nullptr == host) {
3433 s->s.setAnyAddr();
3434 s->s.port(port);
3435 if (!Ip::EnableIpv6)
3436 s->s.setIPv4();
3437 debugs(3, 3, portType << "_port: found Listen on wildcard address: *:" << s->s.port());
3438 } else if ( (s->s = host) ) { /* check/parse numeric IPA */
3439 s->s.port(port);
3440 if (!Ip::EnableIpv6)
3441 s->s.setIPv4();
3442 debugs(3, 3, portType << "_port: Listen on Host/IP: " << host << " --> " << s->s);
3443 } else if ( s->s.GetHostByName(host) ) { /* check/parse for FQDN */
3444 /* do not use ipcache */
3445 s->defaultsite = xstrdup(host);
3446 s->s.port(port);
3447 if (!Ip::EnableIpv6)
3448 s->s.setIPv4();
3449 debugs(3, 3, portType << "_port: found Listen as Host " << s->defaultsite << " on IP: " << s->s);
3450 } else {
3451 debugs(3, DBG_CRITICAL, "FATAL: " << portType << "_port: failed to resolve Host/IP: " << host);
3452 self_destruct();
3453 }
3454}
3455
3461{
3462 // HTTP/1.0 not supported because we are version 1.1 which contains a superset of 1.0
3463 // and RFC 2616 requires us to upgrade 1.0 to 1.1
3464 if (value.cmp("HTTP") == 0 || value.cmp("HTTP/1.1") == 0)
3465 return Http::ProtocolVersion(1,1);
3466
3467 if (value.cmp("HTTPS") == 0 || value.cmp("HTTPS/1.1") == 0)
3469
3470 if (value.cmp("FTP") == 0)
3471 return Ftp::ProtocolVersion();
3472
3473 fatalf("%s directive does not support protocol=" SQUIDSBUFPH "\n", cfg_directive, SQUIDSBUFPRINT(value));
3474 return AnyP::ProtocolVersion(); // not reached
3475}
3476
3477static void
3479{
3480 /* modes first */
3481
3482 if (strcmp(token, "accel") == 0) {
3483 if (s->flags.isIntercepted()) {
3484 debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": Accelerator mode requires its own port. It cannot be shared with other modes.");
3485 self_destruct();
3486 return;
3487 }
3488 s->flags.accelSurrogate = true;
3489 s->vhost = true;
3490 } else if (strcmp(token, "transparent") == 0 || strcmp(token, "intercept") == 0) {
3491 if (s->flags.accelSurrogate || s->flags.tproxyIntercept) {
3492 debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": Intercept mode requires its own interception port. It cannot be shared with other modes.");
3493 self_destruct();
3494 return;
3495 }
3496 s->flags.natIntercept = true;
3497 Ip::Interceptor.StartInterception();
3498 /* Log information regarding the port modes under interception. */
3499 debugs(3, DBG_IMPORTANT, "Starting Authentication on port " << s->s);
3500 debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (interception enabled)");
3501 } else if (strcmp(token, "tproxy") == 0) {
3502 if (s->flags.natIntercept || s->flags.accelSurrogate) {
3503 debugs(3,DBG_CRITICAL, "FATAL: " << cfg_directive << ": TPROXY option requires its own interception port. It cannot be shared with other modes.");
3504 self_destruct();
3505 return;
3506 }
3507 s->flags.tproxyIntercept = true;
3508 Ip::Interceptor.StartTransparency();
3509 /* Log information regarding the port modes under transparency. */
3510 debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (TPROXY enabled)");
3511
3512 if (s->flags.proxySurrogate) {
3513 debugs(3, DBG_IMPORTANT, "Disabling TPROXY Spoofing on port " << s->s << " (require-proxy-header enabled)");
3514 }
3515
3516 if (!Ip::Interceptor.ProbeForTproxy(s->s)) {
3517 debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": TPROXY support in the system does not work.");
3518 self_destruct();
3519 return;
3520 }
3521
3522 } else if (strcmp(token, "require-proxy-header") == 0) {
3523 s->flags.proxySurrogate = true;
3524 if (s->flags.tproxyIntercept) {
3525 // receiving is still permitted, so we do not unset the TPROXY flag
3526 // spoofing access control override takes care of the spoof disable later
3527 debugs(3, DBG_IMPORTANT, "Disabling TPROXY Spoofing on port " << s->s << " (require-proxy-header enabled)");
3528 }
3529
3530 } else if (strncmp(token, "defaultsite=", 12) == 0) {
3531 if (!s->flags.accelSurrogate) {
3532 debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": defaultsite option requires Acceleration mode flag.");
3533 self_destruct();
3534 return;
3535 }
3536 safe_free(s->defaultsite);
3537 s->defaultsite = xstrdup(token + 12);
3538 } else if (strcmp(token, "vhost") == 0) {
3539 if (!s->flags.accelSurrogate) {
3540 debugs(3, DBG_CRITICAL, "WARNING: " << cfg_directive << ": vhost option is deprecated. Use 'accel' mode flag instead.");
3541 }
3542 s->flags.accelSurrogate = true;
3543 s->vhost = true;
3544 } else if (strcmp(token, "no-vhost") == 0) {
3545 if (!s->flags.accelSurrogate) {
3546 debugs(3, DBG_IMPORTANT, "ERROR: " << cfg_directive << ": no-vhost option requires Acceleration mode flag.");
3547 }
3548 s->vhost = false;
3549 } else if (strcmp(token, "vport") == 0) {
3550 if (!s->flags.accelSurrogate) {
3551 debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": vport option requires Acceleration mode flag.");
3552 self_destruct();
3553 return;
3554 }
3555 s->vport = -1;
3556 } else if (strncmp(token, "vport=", 6) == 0) {
3557 if (!s->flags.accelSurrogate) {
3558 debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": vport option requires Acceleration mode flag.");
3559 self_destruct();
3560 return;
3561 }
3562 s->vport = xatos(token + 6);
3563 } else if (strncmp(token, "protocol=", 9) == 0) {
3564 if (!s->flags.accelSurrogate) {
3565 debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": protocol option requires Acceleration mode flag.");
3566 self_destruct();
3567 return;
3568 }
3569 s->transport = parsePortProtocol(ToUpper(SBuf(token + 9)));
3570 } else if (strcmp(token, "allow-direct") == 0) {
3571 if (!s->flags.accelSurrogate) {
3572 debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": allow-direct option requires Acceleration mode flag.");
3573 self_destruct();
3574 return;
3575 }
3576 s->allow_direct = true;
3577 } else if (strcmp(token, "act-as-origin") == 0) {
3578 if (!s->flags.accelSurrogate) {
3579 debugs(3, DBG_IMPORTANT, "ERROR: " << cfg_directive << ": act-as-origin option requires Acceleration mode flag.");
3580 } else
3581 s->actAsOrigin = true;
3582 } else if (strcmp(token, "ignore-cc") == 0) {
3583#if !USE_HTTP_VIOLATIONS
3584 if (!s->flags.accelSurrogate) {
3585 debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": ignore-cc option requires Acceleration mode flag.");
3586 self_destruct();
3587 return;
3588 }
3589#endif
3590 s->ignore_cc = true;
3591 } else if (strncmp(token, "name=", 5) == 0) {
3592 safe_free(s->name);
3593 s->name = xstrdup(token + 5);
3594 } else if (strcmp(token, "no-connection-auth") == 0) {
3595 s->connection_auth_disabled = true;
3596 } else if (strcmp(token, "connection-auth=off") == 0) {
3597 s->connection_auth_disabled = true;
3598 } else if (strcmp(token, "connection-auth") == 0) {
3599 s->connection_auth_disabled = false;
3600 } else if (strcmp(token, "connection-auth=on") == 0) {
3601 s->connection_auth_disabled = false;
3602 } else if (strncmp(token, "disable-pmtu-discovery=", 23) == 0) {
3603 if (!strcmp(token + 23, "off"))
3604 s->disable_pmtu_discovery = DISABLE_PMTU_OFF;
3605 else if (!strcmp(token + 23, "transparent"))
3606 s->disable_pmtu_discovery = DISABLE_PMTU_TRANSPARENT;
3607 else if (!strcmp(token + 23, "always"))
3608 s->disable_pmtu_discovery = DISABLE_PMTU_ALWAYS;
3609 else {
3610 self_destruct();
3611 return;
3612 }
3613 } else if (strcmp(token, "ipv4") == 0) {
3614 if ( !s->s.setIPv4() ) {
3615 debugs(3, DBG_CRITICAL, "FATAL: " << cfg_directive << ": IPv6 addresses cannot be used as IPv4-Only. " << s->s );
3616 self_destruct();
3617 return;
3618 }
3619 } else if (strcmp(token, "tcpkeepalive") == 0) {
3620 s->tcp_keepalive.enabled = true;
3621 } else if (strncmp(token, "tcpkeepalive=", 13) == 0) {
3622 char *t = token + 13;
3623 s->tcp_keepalive.enabled = true;
3624 s->tcp_keepalive.idle = xatoui(t,',');
3625 t = strchr(t, ',');
3626 if (t) {
3627 ++t;
3628 s->tcp_keepalive.interval = xatoui(t,',');
3629 t = strchr(t, ',');
3630 }
3631 if (t) {
3632 ++t;
3633 s->tcp_keepalive.timeout = xatoui(t);
3634 }
3635#if USE_OPENSSL
3636 } else if (strcmp(token, "sslBump") == 0) {
3637 debugs(3, DBG_PARSE_NOTE(1), "WARNING: '" << token << "' is deprecated " <<
3638 "in " << cfg_directive << ". Use 'ssl-bump' instead.");
3639 s->flags.tunnelSslBumping = true;
3640 } else if (strcmp(token, "ssl-bump") == 0) {
3641 s->flags.tunnelSslBumping = true;
3642 } else if (strncmp(token, "cert=", 5) == 0) {
3643 s->secure.parse(token);
3644 } else if (strncmp(token, "key=", 4) == 0) {
3645 s->secure.parse(token);
3646 } else if (strncmp(token, "version=", 8) == 0) {
3647 debugs(3, DBG_PARSE_NOTE(1), "WARNING: UPGRADE: '" << token << "' is deprecated " <<
3648 "in " << cfg_directive << ". Use 'options=' instead.");
3649 s->secure.parse(token);
3650 } else if (strncmp(token, "options=", 8) == 0) {
3651 s->secure.parse(token);
3652 } else if (strncmp(token, "cipher=", 7) == 0) {
3653 s->secure.parse(token);
3654 } else if (strncmp(token, "clientca=", 9) == 0) {
3655 s->secure.parse(token);
3656 } else if (strncmp(token, "cafile=", 7) == 0) {
3657 debugs(3, DBG_PARSE_NOTE(1), "WARNING: UPGRADE: '" << token << "' is deprecated " <<
3658 "in " << cfg_directive << ". Use 'tls-cafile=' instead.");
3659 s->secure.parse(token);
3660 } else if (strncmp(token, "capath=", 7) == 0) {
3661 s->secure.parse(token);
3662 } else if (strncmp(token, "crlfile=", 8) == 0) {
3663 s->secure.parse(token);
3664 } else if (strncmp(token, "dhparams=", 9) == 0) {
3665 debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: '" << token << "' is deprecated " <<
3666 "in " << cfg_directive << ". Use 'tls-dh=' instead.");
3667 s->secure.parse(token);
3668 } else if (strncmp(token, "sslflags=", 9) == 0) {
3669 // NP: deprecation warnings output by secure.parse() when relevant
3670 s->secure.parse(token+3);
3671 } else if (strncmp(token, "sslcontext=", 11) == 0) {
3672 // NP: deprecation warnings output by secure.parse() when relevant
3673 s->secure.parse(token+3);
3674 } else if (strncmp(token, "generate-host-certificates", 26) == 0) {
3675 s->secure.parse(token);
3676#endif
3677 } else if (strncmp(token, "dynamic_cert_mem_cache_size=", 28) == 0) {
3678 s->secure.parse(token);
3679 } else if (strncmp(token, "tls-", 4) == 0) {
3680 s->secure.parse(token+4);
3681 } else if (strcmp(token, "ftp-track-dirs") == 0) {
3682 s->ftp_track_dirs = true;
3683 } else if (strcmp(token, "worker-queues") == 0) {
3684#if !defined(SO_REUSEADDR)
3685#error missing system #include that #defines SO_* constants
3686#endif
3687#if !defined(SO_REUSEPORT)
3688 throw TexcHere(ToSBuf(cfg_directive, ' ', token, " option requires building Squid where SO_REUSEPORT is supported by the TCP stack"));
3689#endif
3690 s->workerQueues = true;
3691 } else {
3692 debugs(3, DBG_CRITICAL, "FATAL: Unknown " << cfg_directive << " option '" << token << "'.");
3693 self_destruct();
3694 }
3695}
3696
3697void
3698add_http_port(char *portspec)
3699{
3701 s->transport = parsePortProtocol(SBuf("HTTP"));
3702 parsePortSpecification(s, portspec);
3703 // we may need to merge better if the above returns a list with clones
3704 assert(s->next == nullptr);
3705 s->next = HttpPortList;
3706 HttpPortList = s;
3707}
3708
3709static void
3710parsePortCfg(AnyP::PortCfgPointer *head, const char *optionName)
3711{
3712 SBuf protoName;
3713 if (strcmp(optionName, "http_port") == 0 ||
3714 strcmp(optionName, "ascii_port") == 0)
3715 protoName = "HTTP";
3716 else if (strcmp(optionName, "https_port") == 0)
3717 protoName = "HTTPS";
3718 else if (strcmp(optionName, "ftp_port") == 0)
3719 protoName = "FTP";
3720 if (protoName.isEmpty()) {
3721 self_destruct();
3722 return;
3723 }
3724
3725 char *token = ConfigParser::NextToken();
3726
3727 if (!token) {
3728 self_destruct();
3729 return;
3730 }
3731
3733 s->transport = parsePortProtocol(protoName); // default; protocol=... overwrites
3734 parsePortSpecification(s, token);
3735
3736 /* parse options ... */
3737 while ((token = ConfigParser::NextToken())) {
3738 parse_port_option(s, token);
3739 }
3740
3741 s->secure.syncCaFiles();
3742
3743 if (s->transport.protocol == AnyP::PROTO_HTTPS) {
3744 s->secure.encryptTransport = true;
3745#if USE_OPENSSL
3746 /* ssl-bump on https_port configuration requires either tproxy or intercept, and vice versa */
3747 const bool hijacked = s->flags.isIntercepted();
3748 if (s->flags.tunnelSslBumping && !hijacked) {
3749 debugs(3, DBG_CRITICAL, "FATAL: ssl-bump on https_port requires tproxy/intercept which is missing.");
3750 self_destruct();
3751 return;
3752 }
3753 if (hijacked && !s->flags.tunnelSslBumping) {
3754 debugs(3, DBG_CRITICAL, "FATAL: tproxy/intercept on https_port requires ssl-bump which is missing.");
3755 self_destruct();
3756 return;
3757 }
3758#endif
3759 if (s->flags.proxySurrogate) {
3760 debugs(3,DBG_CRITICAL, "FATAL: https_port: require-proxy-header option is not supported on HTTPS ports.");
3761 self_destruct();
3762 return;
3763 }
3764 } else if (protoName.cmp("FTP") == 0) {
3765 /* ftp_port does not support ssl-bump */
3766 if (s->flags.tunnelSslBumping) {
3767 debugs(3, DBG_CRITICAL, "FATAL: ssl-bump is not supported for ftp_port.");
3768 self_destruct();
3769 return;
3770 }
3771 if (s->flags.proxySurrogate) {
3772 // Passive FTP data channel does not work without deep protocol inspection in the frontend.
3773 debugs(3,DBG_CRITICAL, "FATAL: require-proxy-header option is not supported on ftp_port.");
3774 self_destruct();
3775 return;
3776 }
3777 }
3778
3779 if (s->secure.encryptTransport) {
3780 if (s->secure.certs.empty()) {
3781 debugs(3, DBG_CRITICAL, "FATAL: " << AnyP::UriScheme(s->transport.protocol) << "_port requires a cert= parameter");
3782 self_destruct();
3783 return;
3784 }
3785 s->secure.parseOptions();
3786 }
3787
3788 // *_port line should now be fully valid so we can clone it if necessary
3789 if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && s->s.isAnyAddr()) {
3790 s->next = s->ipV4clone();
3791 }
3792
3793 while (*head != nullptr)
3794 head = &((*head)->next);
3795
3796 *head = s;
3797}
3798
3799static void
3801{
3802 char buf[MAX_IPSTRLEN];
3803
3804 storeAppendPrintf(e, "%s %s",
3805 n,
3806 s->s.toUrl(buf,MAX_IPSTRLEN));
3807
3808 // MODES and specific sub-options.
3809 if (s->flags.natIntercept)
3810 storeAppendPrintf(e, " intercept");
3811
3812 else if (s->flags.tproxyIntercept)
3813 storeAppendPrintf(e, " tproxy");
3814
3815 else if (s->flags.proxySurrogate)
3816 storeAppendPrintf(e, " require-proxy-header");
3817
3818 else if (s->flags.accelSurrogate) {
3819 storeAppendPrintf(e, " accel");
3820
3821 if (s->vhost)
3822 storeAppendPrintf(e, " vhost");
3823
3824 if (s->vport < 0)
3825 storeAppendPrintf(e, " vport");
3826 else if (s->vport > 0)
3827 storeAppendPrintf(e, " vport=%d", s->vport);
3828
3829 if (s->defaultsite)
3830 storeAppendPrintf(e, " defaultsite=%s", s->defaultsite);
3831
3832 // TODO: compare against prefix of 'n' instead of assuming http_port
3833 if (s->transport.protocol != AnyP::PROTO_HTTP)
3834 storeAppendPrintf(e, " protocol=%s", AnyP::ProtocolType_str[s->transport.protocol]);
3835
3836 if (s->allow_direct)
3837 storeAppendPrintf(e, " allow-direct");
3838
3839 if (s->ignore_cc)
3840 storeAppendPrintf(e, " ignore-cc");
3841
3842 }
3843
3844 // Generic independent options
3845
3846 if (s->name)
3847 storeAppendPrintf(e, " name=%s", s->name);
3848
3849#if USE_HTTP_VIOLATIONS
3850 if (!s->flags.accelSurrogate && s->ignore_cc)
3851 storeAppendPrintf(e, " ignore-cc");
3852#endif
3853
3854 if (s->connection_auth_disabled)
3855 storeAppendPrintf(e, " connection-auth=off");
3856 else
3857 storeAppendPrintf(e, " connection-auth=on");
3858
3859 if (s->disable_pmtu_discovery != DISABLE_PMTU_OFF) {
3860 const char *pmtu;
3861
3862 if (s->disable_pmtu_discovery == DISABLE_PMTU_ALWAYS)
3863 pmtu = "always";
3864 else
3865 pmtu = "transparent";
3866
3867 storeAppendPrintf(e, " disable-pmtu-discovery=%s", pmtu);
3868 }
3869
3870 if (s->s.isAnyAddr() && !s->s.isIPv6())
3871 storeAppendPrintf(e, " ipv4");
3872
3873 if (s->tcp_keepalive.enabled) {
3874 if (s->tcp_keepalive.idle || s->tcp_keepalive.interval || s->tcp_keepalive.timeout) {
3875 storeAppendPrintf(e, " tcpkeepalive=%d,%d,%d", s->tcp_keepalive.idle, s->tcp_keepalive.interval, s->tcp_keepalive.timeout);
3876 } else {
3877 storeAppendPrintf(e, " tcpkeepalive");
3878 }
3879 }
3880
3881#if USE_OPENSSL
3882 if (s->flags.tunnelSslBumping)
3883 storeAppendPrintf(e, " ssl-bump");
3884#endif
3885
3886 PackableStream os(*e);
3887 s->secure.dumpCfg(os, "tls-");
3888}
3889
3890static void
3891dump_PortCfg(StoreEntry * e, const char *n, const AnyP::PortCfgPointer &s)
3892{
3893 for (AnyP::PortCfgPointer p = s; p != nullptr; p = p->next) {
3894 dump_generic_port(e, n, p);
3895 storeAppendPrintf(e, "\n");
3896 }
3897}
3898
3899void
3901{
3902 free_all();
3907 Config.ssl_client.sslContext_ = nullptr;
3908#if USE_OPENSSL
3910#endif
3911}
3912
3913void
3914requirePathnameExists(const char *name, const char *path)
3915{
3916
3917 struct stat sb;
3918 char pathbuf[BUFSIZ];
3919 assert(path != nullptr);
3920
3921 if (Config.chroot_dir && (geteuid() == 0)) {
3922 snprintf(pathbuf, BUFSIZ, "%s/%s", Config.chroot_dir, path);
3923 path = pathbuf;
3924 }
3925
3926 if (stat(path, &sb) < 0) {
3927 int xerrno = errno;
3928 debugs(0, DBG_CRITICAL, (opt_parse_cfg_only?"FATAL: ":"ERROR: ") << name << " " << path << ": " << xstrerr(xerrno));
3929 // keep going to find more issues if we are only checking the config file with "-k parse"
3931 return;
3932 // this is fatal if it is found during startup or reconfigure
3933 if (opt_send_signal == -1 || opt_send_signal == SIGHUP)
3934 fatalf("%s %s: %s", name, path, xstrerr(xerrno));
3935 }
3936}
3937
3938#include "AccessLogEntry.h"
3939
3962static void
3964{
3965 const char *filename = ConfigParser::NextToken();
3966 if (!filename) {
3967 self_destruct();
3968 return;
3969 }
3970
3971 const auto cl = new CustomLog();
3972
3973 cl->filename = xstrdup(filename);
3974
3975 if (strcmp(filename, "none") == 0) {
3976 cl->type = Log::Format::CLF_NONE;
3977 aclParseAclList(LegacyParser, &cl->aclList, filename);
3978 while (*logs)
3979 logs = &(*logs)->next;
3980 *logs = cl;
3981 return;
3982 }
3983
3984 const char *token = ConfigParser::PeekAtToken();
3985 if (token && !strchr(token, '=')) { // style #3
3986 // TODO: Deprecate this style to avoid this dangerous guessing.
3987 if (Log::TheConfig.knownFormat(token)) {
3988 cl->setLogformat(token);
3989 (void)ConfigParser::NextToken(); // consume the token used above
3990 } else {
3991 // assume there is no explicit logformat name and use the default
3992 cl->setLogformat("squid");
3993 }
3994 } else { // style #1 or style #4
3995 // TODO: Drop deprecated style #1 support. We already warn about it, and
3996 // its exceptional treatment makes detecting "module" typos impractical!
3997 cl->parseOptions(LegacyParser, "squid");
3998 }
3999 assert(cl->type); // setLogformat() was called
4000
4001 aclParseAclList(LegacyParser, &cl->aclList, cl->filename);
4002
4003 while (*logs)
4004 logs = &(*logs)->next;
4005
4006 *logs = cl;
4007}
4008
4009static int
4010check_null_access_log(CustomLog *customlog_definitions)
4011{
4012 return customlog_definitions == nullptr;
4013}
4014
4015static void
4016dump_access_log(StoreEntry * entry, const char *name, CustomLog * logs)
4017{
4018 assert(entry);
4019 for (auto log = logs; log; log = log->next) {
4020 {
4021 PackableStream os(*entry);
4022 os << name; // directive name
4023 os << ' ' << log->filename; // including "none"
4024 log->dumpOptions(os);
4025 }
4026
4027 if (log->aclList)
4028 dump_acl_list(entry, log->aclList);
4029
4030 storeAppendPrintf(entry, "\n");
4031 }
4032}
4033
4034static void
4036{
4037 while (*definitions) {
4038 CustomLog *log = *definitions;
4039 *definitions = log->next;
4040 delete log;
4041 }
4042}
4043
4044#if HAVE_CPU_AFFINITY /* until somebody else needs this general code */
4046static bool
4047parseNamedIntList(const char *data, const String &name, std::vector<int> &list)
4048{
4049 if (data && (strncmp(data, name.rawBuf(), name.size()) == 0)) {
4050 data += name.size();
4051 if (*data == '=') {
4052 while (true) {
4053 ++data;
4054 int value = 0;
4055 if (!StringToInt(data, value, &data, 10))
4056 break;
4057 list.push_back(value);
4058 if (*data == '\0' || *data != ',')
4059 break;
4060 }
4061 }
4062 }
4063 return data && *data == '\0';
4064}
4065#endif
4066
4067static void
4069{
4070#if !HAVE_CPU_AFFINITY
4071 (void)cpuAffinityMap;
4072 debugs(3, DBG_CRITICAL, "FATAL: Squid built with no CPU affinity " <<
4073 "support, do not set 'cpu_affinity_map'");
4074 self_destruct();
4075
4076#else /* HAVE_CPU_AFFINITY */
4077 if (!*cpuAffinityMap)
4078 *cpuAffinityMap = new CpuAffinityMap;
4079
4080 const char *const pToken = ConfigParser::NextToken();
4081 const char *const cToken = ConfigParser::NextToken();
4082 std::vector<int> processes, cores;
4083 if (!parseNamedIntList(pToken, "process_numbers", processes)) {
4084 debugs(3, DBG_CRITICAL, "FATAL: bad 'process_numbers' parameter " <<
4085 "in 'cpu_affinity_map'");
4086 self_destruct();
4087 } else if (!parseNamedIntList(cToken, "cores", cores)) {
4088 debugs(3, DBG_CRITICAL, "FATAL: bad 'cores' parameter in " <<
4089 "'cpu_affinity_map'");
4090 self_destruct();
4091 } else if (!(*cpuAffinityMap)->add(processes, cores)) {
4092 debugs(3, DBG_CRITICAL, "FATAL: bad 'cpu_affinity_map'; " <<
4093 "process_numbers and cores lists differ in length or " <<
4094 "contain numbers <= 0");
4095 self_destruct();
4096 }
4097#endif
4098}
4099
4100static void
4101dump_CpuAffinityMap(StoreEntry *const entry, const char *const name, const CpuAffinityMap *const cpuAffinityMap)
4102{
4103 if (cpuAffinityMap) {
4104 storeAppendPrintf(entry, "%s process_numbers=", name);
4105 for (size_t i = 0; i < cpuAffinityMap->processes().size(); ++i) {
4106 storeAppendPrintf(entry, "%s%i", (i ? "," : ""),
4107 cpuAffinityMap->processes()[i]);
4108 }
4109 storeAppendPrintf(entry, " cores=");
4110 for (size_t i = 0; i < cpuAffinityMap->cores().size(); ++i) {
4111 storeAppendPrintf(entry, "%s%i", (i ? "," : ""),
4112 cpuAffinityMap->cores()[i]);
4113 }
4114 storeAppendPrintf(entry, "\n");
4115 }
4116}
4117
4118static void
4120{
4121 delete *cpuAffinityMap;
4122 *cpuAffinityMap = nullptr;
4123}
4124
4125#if USE_ADAPTATION
4126
4127static void
4132
4133static void
4138
4139static void
4144#endif /* USE_ADAPTATION */
4145
4146#if ICAP_CLIENT
4147
4148static void
4153
4154static void
4159
4160static void
4161dump_icap_service_type(StoreEntry * entry, const char *name, const Adaptation::Icap::Config &cfg)
4162{
4163 cfg.dumpService(entry, name);
4164}
4165
4166static void
4168{
4169 debugs(93, DBG_CRITICAL, "WARNING: 'icap_class' is deprecated. " <<
4170 "Use 'adaptation_service_set' instead");
4172}
4173
4174static void
4176{
4177 debugs(93, DBG_CRITICAL, "WARNING: 'icap_access' is deprecated. " <<
4178 "Use 'adaptation_access' instead");
4180}
4181
4182#endif
4183
4184#if USE_ECAP
4185
4186static void
4191
4192static void
4197
4198static void
4199dump_ecap_service_type(StoreEntry * entry, const char *name, const Adaptation::Ecap::Config &cfg)
4200{
4201 cfg.dumpService(entry, name);
4202}
4203
4204#endif /* USE_ECAP */
4205
4206#if ICAP_CLIENT
4208{
4209 char *token;
4211
4212 if ((token = ConfigParser::NextToken()) == nullptr)
4213 return;
4214
4215 if (strcmp(token,"in") != 0) {
4216 debugs(3, DBG_CRITICAL, "expecting 'in' on'" << config_input_line << "'");
4217 self_destruct();
4218 return;
4219 }
4220
4222}
4223
4224static void dump_icap_service_failure_limit(StoreEntry *entry, const char *name, const Adaptation::Icap::Config &cfg)
4225{
4226 storeAppendPrintf(entry, "%s %d", name, cfg.service_failure_limit);
4227 if (cfg.oldest_service_failure > 0) {
4228 storeAppendPrintf(entry, " in %d seconds", (int)cfg.oldest_service_failure);
4229 }
4230 storeAppendPrintf(entry, "\n");
4231}
4232
4238#endif
4239
4240#if USE_OPENSSL
4242{
4243 auto *al = ConfigParser::NextToken();
4244 if (!al) {
4245 self_destruct();
4246 return;
4247 }
4248
4249 const char *param;
4250 if ( char *s = strchr(al, '{')) {
4251 *s = '\0'; // terminate the al string
4252 ++s;
4253 param = s;
4254 s = strchr(s, '}');
4255 if (!s) {
4256 self_destruct();
4257 return;
4258 }
4259 *s = '\0';
4260 } else
4261 param = nullptr;
4262
4263 std::unique_ptr<sslproxy_cert_adapt> ca(new sslproxy_cert_adapt);
4264 if (strcmp(al, Ssl::CertAdaptAlgorithmStr[Ssl::algSetValidAfter]) == 0) {
4265 ca->alg = Ssl::algSetValidAfter;
4266 ca->param = xstrdup("on");
4267 } else if (strcmp(al, Ssl::CertAdaptAlgorithmStr[Ssl::algSetValidBefore]) == 0) {
4268 ca->alg = Ssl::algSetValidBefore;
4269 ca->param = xstrdup("on");
4270 } else if (strcmp(al, Ssl::CertAdaptAlgorithmStr[Ssl::algSetCommonName]) == 0) {
4271 ca->alg = Ssl::algSetCommonName;
4272 if (param) {
4273 if (strlen(param) > 64) {
4274 debugs(3, DBG_CRITICAL, "FATAL: sslproxy_cert_adapt: setCommonName{" <<param << "} : using common name longer than 64 bytes is not supported");
4275 self_destruct();
4276 return;
4277 }
4278 ca->param = xstrdup(param);
4279 }
4280 } else {
4281 debugs(3, DBG_CRITICAL, "FATAL: sslproxy_cert_adapt: unknown cert adaptation algorithm: " << al);
4282 self_destruct();
4283 return;
4284 }
4285
4286 aclParseAclList(LegacyParser, &ca->aclList, al);
4287
4288 while (*cert_adapt)
4289 cert_adapt = &(*cert_adapt)->next;
4290
4291 *cert_adapt = ca.release();
4292}
4293
4294static void dump_sslproxy_cert_adapt(StoreEntry *entry, const char *name, sslproxy_cert_adapt *cert_adapt)
4295{
4296 for (const auto *ca = cert_adapt; ca; ca = ca->next) {
4297 storeAppendPrintf(entry, "%s ", name);
4298 storeAppendPrintf(entry, "%s{%s} ", Ssl::sslCertAdaptAlgoritm(ca->alg), ca->param);
4299 if (ca->aclList)
4300 dump_acl_list(entry, ca->aclList);
4301 storeAppendPrintf(entry, "\n");
4302 }
4303}
4304
4306{
4307 delete *cert_adapt;
4308 *cert_adapt = nullptr;
4309}
4310
4312{
4313 const auto al = ConfigParser::NextToken();
4314 if (!al) {
4315 self_destruct();
4316 return;
4317 }
4318
4319 std::unique_ptr<sslproxy_cert_sign> cs(new sslproxy_cert_sign);
4320 if (strcmp(al, Ssl::CertSignAlgorithmStr[Ssl::algSignTrusted]) == 0)
4321 cs->alg = Ssl::algSignTrusted;
4322 else if (strcmp(al, Ssl::CertSignAlgorithmStr[Ssl::algSignUntrusted]) == 0)
4323 cs->alg = Ssl::algSignUntrusted;
4324 else if (strcmp(al, Ssl::CertSignAlgorithmStr[Ssl::algSignSelf]) == 0)
4325 cs->alg = Ssl::algSignSelf;
4326 else {
4327 debugs(3, DBG_CRITICAL, "FATAL: sslproxy_cert_sign: unknown cert signing algorithm: " << al);
4328 self_destruct();
4329 return;
4330 }
4331
4332 aclParseAclList(LegacyParser, &cs->aclList, al);
4333
4334 while (*cert_sign)
4335 cert_sign = &(*cert_sign)->next;
4336
4337 *cert_sign = cs.release();
4338}
4339
4340static void dump_sslproxy_cert_sign(StoreEntry *entry, const char *name, sslproxy_cert_sign *cert_sign)
4341{
4342 for (const auto *cs = cert_sign; cs; cs = cs->next) {
4343 storeAppendPrintf(entry, "%s ", name);
4344 storeAppendPrintf(entry, "%s ", Ssl::certSignAlgorithm(cs->alg));
4345 if (cs->aclList)
4346 dump_acl_list(entry, cs->aclList);
4347 storeAppendPrintf(entry, "\n");
4348 }
4349}
4350
4352{
4353 delete *cert_sign;
4354 *cert_sign = nullptr;
4355}
4356
4358{
4359public:
4361 /* RegisteredRunner API */
4362 void finalizeConfig() override;
4363};
4364
4366
4368
4369void
4371{
4374 static char buf[1024];
4376 strcpy(buf, "ssl_bump deny all");
4377 debugs(3, DBG_CRITICAL, "WARNING: auto-converting deprecated implicit "
4378 "\"ssl_bump deny all\" to \"ssl_bump none all\". New ssl_bump configurations "
4379 "must not use implicit rules. Update your ssl_bump rules.");
4380 } else {
4381 strcpy(buf, "ssl_bump allow all");
4382 debugs(3, DBG_CRITICAL, "SECURITY NOTICE: auto-converting deprecated implicit "
4383 "\"ssl_bump allow all\" to \"ssl_bump client-first all\" which is usually "
4384 "inferior to the newer server-first bumping mode. New ssl_bump"
4385 " configurations must not use implicit rules. Update your ssl_bump rules.");
4386 }
4387 parse_line(buf);
4388 }
4389}
4390
4392{
4393 typedef const char *BumpCfgStyle;
4394 BumpCfgStyle bcsNone = nullptr;
4395 BumpCfgStyle bcsNew = "new client/server-first/none";
4396 BumpCfgStyle bcsOld = "deprecated allow/deny";
4397 static BumpCfgStyle bumpCfgStyleLast = bcsNone;
4398 BumpCfgStyle bumpCfgStyleNow = bcsNone;
4399 char *bm;
4400 if ((bm = ConfigParser::NextToken()) == nullptr) {
4401 self_destruct();
4402 return;
4403 }
4404
4405 // if this is the first rule processed
4406 if (*ssl_bump == nullptr) {
4407 bumpCfgStyleLast = bcsNone;
4409 }
4410
4411 auto action = Acl::Answer(ACCESS_ALLOWED);
4412
4413 if (strcmp(bm, Ssl::BumpModeStr[Ssl::bumpClientFirst]) == 0) {
4414 action.kind = Ssl::bumpClientFirst;
4415 bumpCfgStyleNow = bcsNew;
4416 } else if (strcmp(bm, Ssl::BumpModeStr[Ssl::bumpServerFirst]) == 0) {
4417 action.kind = Ssl::bumpServerFirst;
4418 bumpCfgStyleNow = bcsNew;
4419 } else if (strcmp(bm, Ssl::BumpModeStr[Ssl::bumpPeek]) == 0) {
4420 action.kind = Ssl::bumpPeek;
4421 bumpCfgStyleNow = bcsNew;
4422 } else if (strcmp(bm, Ssl::BumpModeStr[Ssl::bumpStare]) == 0) {
4423 action.kind = Ssl::bumpStare;
4424 bumpCfgStyleNow = bcsNew;
4425 } else if (strcmp(bm, Ssl::BumpModeStr[Ssl::bumpSplice]) == 0) {
4426 action.kind = Ssl::bumpSplice;
4427 bumpCfgStyleNow = bcsNew;
4428 } else if (strcmp(bm, Ssl::BumpModeStr[Ssl::bumpBump]) == 0) {
4429 action.kind = Ssl::bumpBump;
4430 bumpCfgStyleNow = bcsNew;
4431 } else if (strcmp(bm, Ssl::BumpModeStr[Ssl::bumpTerminate]) == 0) {
4432 action.kind = Ssl::bumpTerminate;
4433 bumpCfgStyleNow = bcsNew;
4434 } else if (strcmp(bm, Ssl::BumpModeStr[Ssl::bumpNone]) == 0) {
4435 action.kind = Ssl::bumpNone;
4436 bumpCfgStyleNow = bcsNew;
4437 } else if (strcmp(bm, "allow") == 0) {
4438 debugs(3, DBG_CRITICAL, "SECURITY NOTICE: auto-converting deprecated "
4439 "\"ssl_bump allow <acl>\" to \"ssl_bump client-first <acl>\" which "
4440 "is usually inferior to the newer server-first "
4441 "bumping mode. Update your ssl_bump rules.");
4442 action.kind = Ssl::bumpClientFirst;
4443 bumpCfgStyleNow = bcsOld;
4445 } else if (strcmp(bm, "deny") == 0) {
4446 debugs(3, DBG_CRITICAL, "WARNING: auto-converting deprecated "
4447 "\"ssl_bump deny <acl>\" to \"ssl_bump none <acl>\". Update "
4448 "your ssl_bump rules.");
4449 action.kind = Ssl::bumpNone;
4450 bumpCfgStyleNow = bcsOld;
4452 } else {
4453 debugs(3, DBG_CRITICAL, "FATAL: unknown ssl_bump mode: " << bm);
4454 self_destruct();
4455 return;
4456 }
4457
4458 if (bumpCfgStyleLast != bcsNone && bumpCfgStyleNow != bumpCfgStyleLast) {
4459 debugs(3, DBG_CRITICAL, "FATAL: do not mix " << bumpCfgStyleNow << " actions with " <<
4460 bumpCfgStyleLast << " actions. Update your ssl_bump rules.");
4461 self_destruct();
4462 return;
4463 }
4464
4465 bumpCfgStyleLast = bumpCfgStyleNow;
4466
4467 // empty rule OK
4468 ParseAclWithAction(ssl_bump, action, "ssl_bump");
4469}
4470
4471static void dump_sslproxy_ssl_bump(StoreEntry *entry, const char *name, acl_access *ssl_bump)
4472{
4473 if (ssl_bump)
4474 dump_SBufList(entry, ToTree(ssl_bump).treeDump(name, [](const Acl::Answer &action) {
4475 return Ssl::BumpModeStr.at(action.kind);
4476 }));
4477}
4478
4479static void free_sslproxy_ssl_bump(acl_access **ssl_bump)
4480{
4481 free_acl_access(ssl_bump);
4482}
4483
4484#endif
4485
4486static void dump_HeaderWithAclList(StoreEntry * entry, const char *name, HeaderWithAclList *headers)
4487{
4488 if (!headers)
4489 return;
4490
4491 for (HeaderWithAclList::iterator hwa = headers->begin(); hwa != headers->end(); ++hwa) {
4492 storeAppendPrintf(entry, "%s %s %s", name, hwa->fieldName.c_str(), hwa->fieldValue.c_str());
4493 if (hwa->aclList)
4494 dump_acl_list(entry, hwa->aclList);
4495 storeAppendPrintf(entry, "\n");
4496 }
4497}
4498
4500{
4501 char *fn;
4502 if (!*headers) {
4503 *headers = new HeaderWithAclList;
4504 }
4505 if ((fn = ConfigParser::NextToken()) == nullptr) {
4506 self_destruct();
4507 return;
4508 }
4509 HeaderWithAcl hwa;
4510 hwa.fieldName = fn;
4514
4515 Format::Format *nlf = new ::Format::Format("hdrWithAcl");
4519 hwa.fieldValue = buf.termedBuf();
4521 if (hwa.quoted) {
4522 if (!nlf->parse(hwa.fieldValue.c_str())) {
4523 self_destruct();
4524 return;
4525 }
4526 hwa.valueFormat = nlf;
4527 } else
4528 delete nlf;
4529 aclParseAclList(LegacyParser, &hwa.aclList, (hwa.fieldName + ':' + hwa.fieldValue).c_str());
4530 (*headers)->push_back(hwa);
4531}
4532
4534{
4535 if (!(*header))
4536 return;
4537
4538 for (HeaderWithAclList::iterator hwa = (*header)->begin(); hwa != (*header)->end(); ++hwa) {
4539 if (hwa->aclList)
4540 aclDestroyAclList(&hwa->aclList);
4541
4542 if (hwa->valueFormat) {
4543 delete hwa->valueFormat;
4544 hwa->valueFormat = nullptr;
4545 }
4546 }
4547 delete *header;
4548 *header = nullptr;
4549}
4550
4551static void parse_note(Notes *notes)
4552{
4553 assert(notes);
4554 notes->parse(LegacyParser);
4555}
4556
4557static void dump_note(StoreEntry *entry, const char *name, Notes &notes)
4558{
4559 notes.printAsNoteDirectives(entry, name);
4560}
4561
4562static void free_note(Notes *notes)
4563{
4564 notes->clean();
4565}
4566
4567static DebugMessageId ParseDebugMessageId(const char *value, const char eov)
4568{
4569 const auto id = xatoui(value, eov);
4570 if (!(0 < id && id < DebugMessageIdUpperBound))
4571 throw TextException(ToSBuf("unknown cache_log_message ID: ", value), Here());
4572 return static_cast<DebugMessageId>(id);
4573}
4574
4575static void parse_cache_log_message(DebugMessages **debugMessages)
4576{
4577 DebugMessage msg;
4578 DebugMessageId minId = 0;
4579 DebugMessageId maxId = 0;
4580
4581 char *key = nullptr;
4582 char *value = nullptr;
4583 while (ConfigParser::NextKvPair(key, value)) {
4584 if (strcmp(key, "id") == 0) {
4585 if (minId > 0)
4586 break;
4587 minId = maxId = ParseDebugMessageId(value, '\0');
4588 } else if (strcmp(key, "ids") == 0) {
4589 if (minId > 0)
4590 break;
4591 const auto dash = strchr(value, '-');
4592 if (!dash)
4593 throw TextException(ToSBuf("malformed cache_log_message ID range: ", key, '=', value), Here());
4594 minId = ParseDebugMessageId(value, '-');
4595 maxId = ParseDebugMessageId(dash+1, '\0');
4596 if (minId > maxId)
4597 throw TextException(ToSBuf("invalid cache_log_message ID range: ", key, '=', value), Here());
4598 } else if (strcmp(key, "level") == 0) {
4599 if (msg.levelled())
4600 break;
4601 const auto level = xatoi(value);
4602 if (level < 0)
4603 throw TextException(ToSBuf("negative cache_log_message level: ", value), Here());
4604 msg.level = level;
4605 } else if (strcmp(key, "limit") == 0) {
4606 if (msg.limited())
4607 break;
4608 msg.limit = xatoull(value, 10);
4609 } else {
4610 throw TextException(ToSBuf("unsupported cache_log_message option: ", key), Here());
4611 }
4612 key = value = nullptr;
4613 }
4614
4615 if (key && value)
4616 throw TextException(ToSBuf("repeated or conflicting cache_log_message option: ", key, '=', value), Here());
4617
4618 if (!minId)
4619 throw TextException("cache_log_message is missing a required id=... or ids=... option", Here());
4620
4621 if (!(msg.levelled() || msg.limited()))
4622 throw TextException("cache_log_message is missing a required level=... or limit=... option", Here());
4623
4624 assert(debugMessages);
4625 if (!*debugMessages)
4626 *debugMessages = new DebugMessages();
4627
4628 for (auto id = minId; id <= maxId; ++id) {
4629 msg.id = id;
4630 (*debugMessages)->messages.at(id) = msg;
4631 }
4632}
4633
4634static void dump_cache_log_message(StoreEntry *entry, const char *name, const DebugMessages *debugMessages)
4635{
4636 if (!debugMessages)
4637 return;
4638
4639 SBufStream out;
4640 for (const auto &msg: debugMessages->messages) {
4641 if (!msg.configured())
4642 continue;
4643 out << name << " id=" << msg.id;
4644 if (msg.levelled())
4645 out << " level=" << msg.level;
4646 if (msg.limited())
4647 out << " limit=" << msg.limit;
4648 out << "\n";
4649 }
4650 const auto buf = out.buf();
4651 entry->append(buf.rawContent(), buf.length()); // may be empty
4652}
4653
4654static void free_cache_log_message(DebugMessages **debugMessages)
4655{
4656 // clear old messages to avoid cumulative effect across (re)configurations
4657 assert(debugMessages);
4658 delete *debugMessages;
4659 *debugMessages = nullptr;
4660}
4661
4662static bool FtpEspvDeprecated = false;
4663static void parse_ftp_epsv(acl_access **ftp_epsv)
4664{
4665 Acl::Answer ftpEpsvDeprecatedAction;
4666 bool ftpEpsvIsDeprecatedRule = false;
4667
4668 char *t = ConfigParser::PeekAtToken();
4669 if (!t) {
4670 self_destruct();
4671 return;
4672 }
4673
4674 if (!strcmp(t, "off")) {
4676 ftpEpsvIsDeprecatedRule = true;
4677 ftpEpsvDeprecatedAction = Acl::Answer(ACCESS_DENIED);
4678 } else if (!strcmp(t, "on")) {
4680 ftpEpsvIsDeprecatedRule = true;
4681 ftpEpsvDeprecatedAction = Acl::Answer(ACCESS_ALLOWED);
4682 }
4683
4684 // Check for mixing "ftp_epsv on|off" and "ftp_epsv allow|deny .." rules:
4685 // 1) if this line is "ftp_epsv allow|deny ..." and already exist rules of "ftp_epsv on|off"
4686 // 2) if this line is "ftp_epsv on|off" and already exist rules of "ftp_epsv allow|deny ..."
4687 // then abort
4688 if ((!ftpEpsvIsDeprecatedRule && FtpEspvDeprecated) ||
4689 (ftpEpsvIsDeprecatedRule && !FtpEspvDeprecated && *ftp_epsv != nullptr)) {
4690 debugs(3, DBG_CRITICAL, "FATAL: do not mix \"ftp_epsv on|off\" cfg lines with \"ftp_epsv allow|deny ...\" cfg lines. Update your ftp_epsv rules.");
4691 self_destruct();
4692 return;
4693 }
4694
4695 if (ftpEpsvIsDeprecatedRule) {
4696 // overwrite previous ftp_epsv lines
4697 delete *ftp_epsv;
4698 *ftp_epsv = nullptr;
4699
4700 if (ftpEpsvDeprecatedAction == Acl::Answer(ACCESS_DENIED)) {
4701 static const auto all = new SBuf("all");
4702 if (const auto a = Acl::Node::FindByName(*all))
4703 ParseAclWithAction(ftp_epsv, ftpEpsvDeprecatedAction, "ftp_epsv", a);
4704 else {
4705 self_destruct();
4706 return;
4707 }
4708 }
4709 FtpEspvDeprecated = true;
4710 } else {
4712 }
4713}
4714
4715static void dump_ftp_epsv(StoreEntry *entry, const char *name, acl_access *ftp_epsv)
4716{
4717 if (ftp_epsv)
4718 dump_SBufList(entry, ToTree(ftp_epsv).treeDump(name, Acl::AllowOrDeny));
4719}
4720
4721static void free_ftp_epsv(acl_access **ftp_epsv)
4722{
4723 free_acl_access(ftp_epsv);
4724 FtpEspvDeprecated = false;
4725}
4726
4729static std::chrono::seconds
4731{
4732 const auto timeValueToken = ConfigParser::NextToken();
4733 if (!timeValueToken)
4734 throw TexcHere("cannot read a time value");
4735
4736 using Seconds = std::chrono::seconds;
4737
4738 const auto parsedTimeValue = xatof(timeValueToken);
4739
4740 if (parsedTimeValue == 0)
4741 return std::chrono::seconds::zero();
4742
4743 std::chrono::nanoseconds parsedUnitDuration;
4744
4745 const auto unitToken = ConfigParser::PeekAtToken();
4746 if (parseTimeUnit<Seconds>(unitToken, parsedUnitDuration))
4748 else {
4749 const auto defaultParsed = parseTimeUnit<Seconds>(T_SECOND_STR, parsedUnitDuration);
4750 assert(defaultParsed);
4752 ": WARNING: missing time unit, using deprecated default '" << T_SECOND_STR << "'");
4753 }
4754
4755 const auto nanoseconds = ToNanoSeconds(parsedTimeValue, parsedUnitDuration);
4756
4757 return FromNanoseconds<Seconds>(nanoseconds, parsedTimeValue);
4758}
4759
4760static void
4762{
4763 // TODO: do not allow optional timeunit (as the documentation prescribes)
4764 // and use parseTimeLine() instead.
4766
4767 char *key, *value;
4768 while(ConfigParser::NextKvPair(key, value)) {
4769 if (strcasecmp(key, "on_timeout") == 0) {
4770 if (strcasecmp(value, "bypass") == 0)
4771 config->action = toutActBypass;
4772 else if (strcasecmp(value, "fail") == 0)
4773 config->action = toutActFail;
4774 else if (strcasecmp(value, "retry") == 0)
4775 config->action = toutActRetry;
4776 else if (strcasecmp(value, "use_configured_response") == 0) {
4778 } else {
4779 debugs(3, DBG_CRITICAL, "FATAL: unsupported \"on_timeout\" action: " << value);
4780 self_destruct();
4781 return;
4782 }
4783 } else if (strcasecmp(key, "response") == 0) {
4784 config->response = xstrdup(value);
4785 } else {
4786 debugs(3, DBG_CRITICAL, "FATAL: unsupported option " << key);
4787 self_destruct();
4788 return;
4789 }
4790 }
4791
4792 if (config->action == toutActUseConfiguredResponse && !config->response) {
4793 debugs(3, DBG_CRITICAL, "FATAL: Expected 'response=' option after 'on_timeout=use_configured_response' option");
4794 self_destruct();
4795 }
4796
4797 if (config->action != toutActUseConfiguredResponse && config->response) {
4798 debugs(3, DBG_CRITICAL, "FATAL: 'response=' option is valid only when used with the 'on_timeout=use_configured_response' option");
4799 self_destruct();
4800 }
4801}
4802
4803static void
4805{
4806 const char *onTimedOutActions[] = {"bypass", "fail", "retry", "use_configured_response"};
4807 assert(config.action >= 0 && config.action <= toutActUseConfiguredResponse);
4808
4809 dump_time_t(entry, name, Config.Timeout.urlRewrite);
4810 storeAppendPrintf(entry, " on_timeout=%s", onTimedOutActions[config.action]);
4811
4812 if (config.response)
4813 storeAppendPrintf(entry, " response=\"%s\"", config.response);
4814
4815 storeAppendPrintf(entry, "\n");
4816}
4817
4818static void
4820{
4822 config->action = 0;
4823 safe_free(config->response);
4824}
4825
4826static void
4828{
4829 int val = 0;
4830 parse_onoff(&val);
4831
4832 // If quoted values is set to on then enable new strict mode parsing
4833 if (val) {
4836 } else {
4839 }
4840}
4841
4842static void
4843dump_configuration_includes_quoted_values(StoreEntry *const entry, const char *const name, bool)
4844{
4845 int val = ConfigParser::RecognizeQuotedValues ? 1 : 0;
4846 dump_onoff(entry, name, val);
4847}
4848
4849static void
4855
4856static void
4858{
4859 char *tm;
4860 if ((tm = ConfigParser::NextToken()) == nullptr) {
4861 self_destruct();
4862 return;
4863 }
4864
4865 auto action = Acl::Answer(ACCESS_ALLOWED);
4866 if (strcmp(tm, "tunnel") == 0)
4867 action.kind = 1;
4868 else if (strcmp(tm, "respond") == 0)
4869 action.kind = 2;
4870 else {
4871 debugs(3, DBG_CRITICAL, "FATAL: unknown on_unsupported_protocol mode: " << tm);
4872 self_destruct();
4873 return;
4874 }
4875
4876 // empty rule OK
4877 ParseAclWithAction(access, action, "on_unsupported_protocol");
4878}
4879
4880static void
4881dump_on_unsupported_protocol(StoreEntry *entry, const char *name, acl_access *access)
4882{
4883 static const std::vector<const char *> onErrorTunnelMode = {
4884 "none",
4885 "tunnel",
4886 "respond"
4887 };
4888 if (access) {
4889 const auto lines = ToTree(access).treeDump(name, [](const Acl::Answer &action) {
4890 return onErrorTunnelMode.at(action.kind);
4891 });
4892 dump_SBufList(entry, lines);
4893 }
4894}
4895
4896static void
4898{
4899 free_acl_access(access);
4900}
4901
4902static void
4904{
4905 assert(protoGuardsPtr);
4906 auto &protoGuards = *protoGuardsPtr;
4907 if (!protoGuards)
4908 protoGuards = new HttpUpgradeProtocolAccess();
4909 protoGuards->configureGuard(LegacyParser);
4910}
4911
4912static void
4914{
4915 if (!protoGuards)
4916 return;
4917
4918 const SBuf name(rawName);
4919 protoGuards->forEach([entry,&name](const SBuf &proto, const acl_access *acls) {
4920 SBufList line;
4921 line.push_back(name);
4922 line.push_back(proto);
4923 const auto acld = ToTree(acls).treeDump("", &Acl::AllowOrDeny);
4924 line.insert(line.end(), acld.begin(), acld.end());
4925 dump_SBufList(entry, line);
4926 });
4927}
4928
4929static void
4931{
4932 assert(protoGuardsPtr);
4933 auto &protoGuards = *protoGuardsPtr;
4934 delete protoGuards;
4935 protoGuards = nullptr;
4936}
4937
const CachePeers & CurrentCachePeers()
Definition CachePeers.cc:43
std::list< HeaderWithAcl > HeaderWithAclList
#define Here()
source code location of the caller
Definition Here.h:15
SBuf TheKidName
current Squid process name (e.g., "squid-coord")
Definition Kids.cc:19
int size
Definition ModDevPoll.cc:70
unsigned int xatoui(const char *token, char eov)
Definition Parsing.cc:58
double GetPercentage(bool limit)
Definition Parsing.cc:178
bool GetHostWithPort(char *token, Ip::Address *ipa)
Definition Parsing.cc:257
uint64_t xatoull(const char *token, int base, char eov)
Definition Parsing.cc:105
double xatof(const char *token)
Definition Parsing.cc:25
unsigned short xatos(const char *token)
Definition Parsing.cc:114
bool StringToInt(const char *s, int &result, const char **p, int base)
Definition Parsing.cc:217
int64_t GetInteger64(void)
Definition Parsing.cc:132
unsigned short GetShort(void)
Definition Parsing.cc:205
int GetInteger(void)
Definition Parsing.cc:148
int xatoi(const char *token)
Definition Parsing.cc:44
AnyP::PortCfgPointer HttpPortList
list of Squid http(s)_port configured
Definition PortCfg.cc:22
#define DefineRunnerRegistrator(ClassName)
SBuf ToUpper(SBuf buf)
Returns a lower-cased copy of its parameter.
Definition SBuf.h:725
#define SQUIDSBUFPH
Definition SBuf.h:31
#define SQUIDSBUFPRINT(s)
Definition SBuf.h:32
class SquidConfig Config
class SquidConfig2 Config2
char * strwordtok(char *buf, char **t)
Definition String.cc:321
std::ostream & CurrentException(std::ostream &os)
prints active (i.e., thrown but not yet handled) exception
#define TexcHere(msg)
legacy convenience macro; it is not difficult to type Here() now
#define Must(condition)
void aclParseAccessLine(const char *directive, ConfigParser &, acl_access **config)
Parses a single line of a "action followed by acls" directive (e.g., http_access).
Definition Gadgets.cc:132
size_t aclParseAclList(ConfigParser &, ACLList **config, const char *label)
Definition Gadgets.cc:184
void log(char *format,...)
Acl::TreePointer acl_access
Definition forward.h:46
squidaio_request_t * head
Definition aiops.cc:129
#define assert(EX)
Definition assert.h:17
static DebugMessageId ParseDebugMessageId(const char *value, const char eov)
Definition cache_cf.cc:4567
static std::chrono::nanoseconds ToNanoSeconds(const double value, const std::chrono::nanoseconds &unit)
Definition cache_cf.cc:1172
static void SetConfigFilename(char const *file_name, bool is_pipe)
Definition cache_cf.cc:281
void parse_time_t(time_t *var)
Definition cache_cf.cc:2940
static void dump_sslproxy_ssl_bump(StoreEntry *entry, const char *name, acl_access *ssl_bump)
Definition cache_cf.cc:4471
static void free_authparam(Auth::ConfigVector *cfg)
Definition cache_cf.cc:1950
static void dump_cachemgrpasswd(StoreEntry *entry, const char *name, Mgr::ActionPasswordList *list)
Definition cache_cf.cc:2403
static void parse_address(Ip::Address *addr)
Definition cache_cf.cc:1525
static void free_icap_service_failure_limit(Adaptation::Icap::Config *)
Definition cache_cf.cc:4233
static const char *const T_SECOND_STR
Definition cache_cf.cc:146
static void ReplaceSubstr(char *&str, int &len, unsigned substrIdx, unsigned substrLen, const char *newSubstr)
Definition cache_cf.cc:341
static void parse_b_size_t(size_t *var)
Definition cache_cf.cc:3021
static int parseOneConfigFile(const char *file_name, unsigned int depth)
Definition cache_cf.cc:446
static void parse_icap_service_failure_limit(Adaptation::Icap::Config *)
Definition cache_cf.cc:4207
static void free_b_int64_t(int64_t *var)
Definition cache_cf.cc:3057
static void free_int64_t(int64_t *var)
Definition cache_cf.cc:2556
static void free_refreshpattern(RefreshPattern **head)
Definition cache_cf.cc:2847
static void parse_authparam(Auth::ConfigVector *config)
Definition cache_cf.cc:1910
static void dump_SBufList(StoreEntry *entry, const SBufList &words)
Definition cache_cf.cc:1443
static void free_time_nanoseconds(std::chrono::nanoseconds *var)
Definition cache_cf.cc:2991
void free_YesNoNone(YesNoNone *)
Definition cache_cf.cc:3227
static void free_HeaderManglers(HeaderManglers **pm)
Definition cache_cf.cc:1859
static void dump_note(StoreEntry *, const char *, Notes &)
Definition cache_cf.cc:4557
static void free_delay_pool_count(DelayConfig *cfg)
Definition cache_cf.cc:1749
void configFreeMemory(void)
Definition cache_cf.cc:3900
static void free_memcachemode(SquidConfig *)
Definition cache_cf.cc:3246
static void free_time_msec(time_msec_t *var)
Definition cache_cf.cc:2972
static void parse_b_ssize_t(ssize_t *var)
Definition cache_cf.cc:3027
static void dump_cache_log_message(StoreEntry *entry, const char *name, const DebugMessages *messages)
Definition cache_cf.cc:4634
static void free_time_t(time_t *var)
Definition cache_cf.cc:2950
static void dump_configuration_includes_quoted_values(StoreEntry *const entry, const char *const name, bool recognizeQuotedValues)
Definition cache_cf.cc:4843
static void parse_client_delay_pool_count(ClientDelayConfig *cfg)
Definition cache_cf.cc:1810
static void parse_adaptation_service_set_type()
Definition cache_cf.cc:4128
static void parse_ftp_epsv(acl_access **ftp_epsv)
Definition cache_cf.cc:4663
static void parse_string(char **)
Definition cache_cf.cc:2866
static const char *const T_MONTH_STR
Definition cache_cf.cc:152
static void parse_port_option(AnyP::PortCfgPointer &s, char *token)
Definition cache_cf.cc:3478
static void dump_removalpolicy(StoreEntry *entry, const char *name, RemovalPolicySettings *settings)
Definition cache_cf.cc:3212
static const char *const B_MBYTES_STR
Definition cache_cf.cc:158
static void parse_acl_access(acl_access **head)
Definition cache_cf.cc:1506
static void free_http_upgrade_request_protocols(HttpUpgradeProtocolAccess **protoGuards)
Definition cache_cf.cc:4930
static void free_AuthSchemes(acl_access **authSchemes)
Definition cache_cf.cc:1983
static void free_ecap_service_type(Adaptation::Ecap::Config *)
Definition cache_cf.cc:4193
static void ParseAclWithAction(acl_access **access, const Acl::Answer &action, const char *desc, Acl::Node *acl=nullptr)
Definition cache_cf.cc:2001
static void dump_AuthSchemes(StoreEntry *entry, const char *name, acl_access *authSchemes)
Definition cache_cf.cc:1990
static void free_client_delay_pool_count(ClientDelayConfig *cfg)
Definition cache_cf.cc:1798
static void parse_adaptation_access_type()
Definition cache_cf.cc:4140
static void dump_PortCfg(StoreEntry *, const char *, const AnyP::PortCfgPointer &)
Definition cache_cf.cc:3891
static void dump_ecap_service_type(StoreEntry *, const char *, const Adaptation::Ecap::Config &)
Definition cache_cf.cc:4199
static const char *const T_WEEK_STR
Definition cache_cf.cc:150
static void dump_delay_pool_count(StoreEntry *entry, const char *name, DelayConfig &cfg)
Definition cache_cf.cc:1755
static void dump_b_ssize_t(StoreEntry *entry, const char *name, ssize_t var)
Definition cache_cf.cc:3003
static int parse_line(char *)
static void defaults_postscriptum(void)
static void parse_configuration_includes_quoted_values(bool *recognizeQuotedValues)
Definition cache_cf.cc:4827
static void free_SBufList(SBufList *list)
Definition cache_cf.cc:1464
static void parse_adaptation_service_chain_type()
Definition cache_cf.cc:4134
static void SubstituteMacro(char *&line, int &len, const char *macroName, const char *substStr)
Definition cache_cf.cc:359
static void dump_refreshpattern(StoreEntry *entry, const char *name, RefreshPattern *head)
Definition cache_cf.cc:2665
static void parse_icap_service_type(Adaptation::Icap::Config *)
Definition cache_cf.cc:4149
static void parse_time_msec(time_msec_t *var)
Definition cache_cf.cc:2966
static void free_removalpolicy(RemovalPolicySettings **settings)
Definition cache_cf.cc:3184
void parse_onoff(int *var)
Definition cache_cf.cc:2568
static void parse_obsolete(const char *)
Definition cache_cf.cc:1054
static void dump_b_size_t(StoreEntry *entry, const char *name, size_t var)
Definition cache_cf.cc:2997
static void dump_client_delay_pool_count(StoreEntry *entry, const char *name, ClientDelayConfig &cfg)
Definition cache_cf.cc:1804
static void ProcessMacros(char *&line, int &len)
Definition cache_cf.cc:370
static AnyP::ProtocolVersion parsePortProtocol(const SBuf &value)
Definition cache_cf.cc:3460
static void dump_time_t(StoreEntry *entry, const char *name, time_t var)
Definition cache_cf.cc:2933
static void free_size_t(size_t *var)
Definition cache_cf.cc:3045
static void free_note(Notes *)
Definition cache_cf.cc:4562
static void dump_tristate(StoreEntry *entry, const char *name, int var)
Definition cache_cf.cc:2595
static bool StrToInt(const char *str, long &number)
Definition cache_cf.cc:407
static void parse_kb_int64_t(int64_t *var)
Definition cache_cf.cc:3039
static void free_acl(Acl::NamedAcls **config)
Definition cache_cf.cc:1485
static void default_all(void)
static const char *const T_DECADE_STR
Definition cache_cf.cc:154
static int parseManyConfigFiles(char *files, int depth)
Definition cache_cf.cc:311
static void dump_http_header_replace(StoreEntry *entry, const char *name, const HeaderManglers *manglers)
Definition cache_cf.cc:1869
static int check_null_acl_access(acl_access *a)
Definition cache_cf.cc:3130
void add_http_port(char *portspec)
Definition cache_cf.cc:3698
static void dump_sslproxy_cert_sign(StoreEntry *entry, const char *name, sslproxy_cert_sign *cert_sign)
Definition cache_cf.cc:4340
static void free_acl_access(acl_access **head)
Definition cache_cf.cc:1512
static void dump_memcachemode(StoreEntry *entry, const char *name, SquidConfig &)
Definition cache_cf.cc:3277
static void free_CpuAffinityMap(CpuAffinityMap **const cpuAffinityMap)
Definition cache_cf.cc:4119
static const char *const T_HOUR_STR
Definition cache_cf.cc:148
static void parse_removalpolicy(RemovalPolicySettings **settings)
Definition cache_cf.cc:3199
static void free_all(void)
static void parse_TokenOrQuotedString(char **var)
Definition cache_cf.cc:2916
static void parse_http_upgrade_request_protocols(HttpUpgradeProtocolAccess **protoGuards)
Definition cache_cf.cc:4903
static void dump_int(StoreEntry *entry, const char *name, int var)
Definition cache_cf.cc:2522
static bool EvalBoolExpr(const char *expr)
Definition cache_cf.cc:418
static void dump_u_short(StoreEntry *entry, const char *name, unsigned short var)
Definition cache_cf.cc:3070
static void parse_on_unsupported_protocol(acl_access **access)
Definition cache_cf.cc:4857
static void DumpDirective(const T &raw, StoreEntry *entry, const char *name)
Definition cache_cf.cc:679
static const char *const B_GBYTES_STR
Definition cache_cf.cc:159
static void parse_peer(CachePeers **peers)
Definition cache_cf.cc:2150
static void parse_AuthSchemes(acl_access **authSchemes)
Definition cache_cf.cc:1969
static void dump_sslproxy_cert_adapt(StoreEntry *entry, const char *name, sslproxy_cert_adapt *cert_adapt)
Definition cache_cf.cc:4294
static void parse_delay_pool_access(DelayConfig *cfg)
Definition cache_cf.cc:1779
static void free_acl_address(Acl::Address **head)
Definition cache_cf.cc:1586
static void free_on_unsupported_protocol(acl_access **access)
Definition cache_cf.cc:4897
void parse_wordlist(wordlist **list)
Definition cache_cf.cc:3122
static void parse_cachemgrpasswd(Mgr::ActionPasswordList **head)
Definition cache_cf.cc:2420
static void free_ssize_t(ssize_t *var)
Definition cache_cf.cc:3051
static void parse_icap_class_type()
Definition cache_cf.cc:4167
static void parseBytesLine64(int64_t *bptr, const char *units)
Definition cache_cf.cc:1237
void parse_int(int *var)
Definition cache_cf.cc:2528
static void parse_access_log(CustomLog **customlog_definitions)
Definition cache_cf.cc:3963
void requirePathnameExists(const char *name, const char *path)
Definition cache_cf.cc:3914
static void free_acl_b_size_t(AclSizeLimit **head)
Definition cache_cf.cc:1728
static void parse_refreshpattern(RefreshPattern **)
Definition cache_cf.cc:2709
static void free_u_short(unsigned short *u)
Definition cache_cf.cc:3076
static void parse_http_header_replace(HeaderManglers **manglers)
Definition cache_cf.cc:1876
static void parse_sslproxy_ssl_bump(acl_access **ssl_bump)
Definition cache_cf.cc:4391
static void free_IpAddress_list(Ip::Address_list **)
Definition cache_cf.cc:3355
static void dump_icap_service_type(StoreEntry *, const char *, const Adaptation::Icap::Config &)
Definition cache_cf.cc:4161
static void parse_time_nanoseconds(std::chrono::nanoseconds *var)
Definition cache_cf.cc:2985
static const char *const T_MILLISECOND_STR
Definition cache_cf.cc:145
void parse_eol(char *volatile *var)
Definition cache_cf.cc:2886
static void free_icap_service_type(Adaptation::Icap::Config *)
Definition cache_cf.cc:4155
static void parse_pipelinePrefetch(int *var)
Definition cache_cf.cc:2639
const char * cfg_directive
During parsing, the name of the current squid.conf directive being parsed.
Definition cache_cf.cc:269
static void dump_authparam(StoreEntry *entry, const char *name, Auth::ConfigVector cfg)
Definition cache_cf.cc:1962
static bool IsSpace(const char ch)
Definition cache_cf.cc:296
static void dump_string(StoreEntry *entry, const char *name, char *var)
Definition cache_cf.cc:2859
static void trim_trailing_ws(char *str)
Definition cache_cf.cc:378
static void FreeDirective(T &raw)
frees any resources associated with the given raw SquidConfig data member
Definition cache_cf.cc:698
static void dump_UrlHelperTimeout(StoreEntry *, const char *, SquidConfig::UrlHelperTimeout &)
Definition cache_cf.cc:4804
static void parse_ecap_service_type(Adaptation::Ecap::Config *)
Definition cache_cf.cc:4187
static void free_cachemgrpasswd(Mgr::ActionPasswordList **head)
Definition cache_cf.cc:2455
static void dump_denyinfo(StoreEntry *entry, const char *name, AclDenyInfoList *var)
Definition cache_cf.cc:2462
static const char *const B_KBYTES_STR
Definition cache_cf.cc:157
static void dump_http_header_access(StoreEntry *entry, const char *name, const HeaderManglers *manglers)
Definition cache_cf.cc:1830
static void dump_wordlist(StoreEntry *entry, const char *name, wordlist *list)
Definition cache_cf.cc:3107
static void free_int(int *var)
Definition cache_cf.cc:2536
static const char *const T_YEAR_STR
Definition cache_cf.cc:153
#define free_wordlist
Definition cache_cf.cc:3135
static const char *const T_MINUTE_STR
Definition cache_cf.cc:147
char config_input_line[BUFSIZ]
Definition cache_cf.cc:272
static void free_acl_tos(acl_tos **head)
Definition cache_cf.cc:1645
const char * cfg_filename
Definition cache_cf.cc:270
static void parse_memcachemode(SquidConfig *)
Definition cache_cf.cc:3250
static bool FtpEspvDeprecated
Definition cache_cf.cc:4662
static void parse_hostdomaintype(void)
Definition cache_cf.cc:2499
static int check_null_string(char *s)
Definition cache_cf.cc:1903
static void free_address(Ip::Address *addr)
Definition cache_cf.cc:1549
static void dump_on_unsupported_protocol(StoreEntry *entry, const char *name, acl_access *access)
Definition cache_cf.cc:4881
static const char *const T_FORTNIGHT_STR
Definition cache_cf.cc:151
static OBJH dump_config
Definition cache_cf.cc:187
static void dump_cachedir(StoreEntry *entry, const char *name, const Store::DiskConfig &swap)
Definition cache_cf.cc:1897
static int check_null_access_log(CustomLog *customlog_definitions)
Definition cache_cf.cc:4010
static const char * FindStatement(const char *line, const char *statement)
Definition cache_cf.cc:388
static bool SawDirective(const T &raw)
whether we have seen (and, hence, configured) the given directive
Definition cache_cf.cc:654
static void parseBytesLine(size_t *bptr, const char *units)
Definition cache_cf.cc:1284
static void dump_IpAddress_list(StoreEntry *, const char *, const Ip::Address_list *)
Definition cache_cf.cc:3342
static void dump_access_log(StoreEntry *entry, const char *name, CustomLog *definitions)
Definition cache_cf.cc:4016
static void dump_http_upgrade_request_protocols(StoreEntry *entry, const char *name, HttpUpgradeProtocolAccess *protoGuards)
Definition cache_cf.cc:4913
static void parse_client_delay_pool_rates(ClientDelayConfig *cfg)
Definition cache_cf.cc:1816
static void free_access_log(CustomLog **definitions)
Definition cache_cf.cc:4035
static void parse_sslproxy_cert_sign(sslproxy_cert_sign **cert_sign)
Definition cache_cf.cc:4311
static void parse_peer_access(void)
Definition cache_cf.cc:2490
static ConfigParser LegacyParser
Definition cache_cf.cc:267
static void parseBytesLineSigned(ssize_t *bptr, const char *units)
Definition cache_cf.cc:1331
static void dump_HeaderWithAclList(StoreEntry *entry, const char *name, HeaderWithAclList *headers)
Definition cache_cf.cc:4486
static void parse_cache_log_message(DebugMessages **messages)
Definition cache_cf.cc:4575
static void dump_acl(StoreEntry *entry, const char *directiveName, Acl::NamedAcls *config)
Definition cache_cf.cc:1471
static void parse_acl_address(Acl::Address **head)
Definition cache_cf.cc:1572
static const char *const T_MICROSECOND_STR
Definition cache_cf.cc:144
static void dump_int64_t(StoreEntry *entry, const char *name, int64_t var)
Definition cache_cf.cc:2542
static void dump_address(StoreEntry *entry, const char *name, Ip::Address &addr)
Definition cache_cf.cc:1518
static void free_cache_log_message(DebugMessages **messages)
Definition cache_cf.cc:4654
static void parse_UrlHelperTimeout(SquidConfig::UrlHelperTimeout *)
Definition cache_cf.cc:4761
static void parse_http_header_access(HeaderManglers **manglers)
Definition cache_cf.cc:1837
static void parse_b_int64_t(int64_t *var)
Definition cache_cf.cc:3033
static const char *const B_BYTES_STR
Definition cache_cf.cc:156
static void dump_peer(StoreEntry *entry, const char *name, const CachePeers *peers)
Definition cache_cf.cc:2056
static void dump_acl_address(StoreEntry *entry, const char *name, Acl::Address *head)
Definition cache_cf.cc:1555
static void free_peer(CachePeers **const peers)
Definition cache_cf.cc:2396
static size_t parseBytesUnits(const char *unit)
Definition cache_cf.cc:1415
static void parse_delay_pool_class(DelayConfig *cfg)
Definition cache_cf.cc:1767
static void free_sslproxy_cert_adapt(sslproxy_cert_adapt **cert_adapt)
Definition cache_cf.cc:4305
static void free_ftp_epsv(acl_access **ftp_epsv)
Definition cache_cf.cc:4721
static bool parseTimeUnit(const char *unitName, std::chrono::nanoseconds &ns)
Definition cache_cf.cc:1131
static void parse_u_short(unsigned short *var)
Definition cache_cf.cc:3082
static const char *const T_NANOSECOND_STR
Definition cache_cf.cc:143
static void free_sslproxy_ssl_bump(acl_access **ssl_bump)
Definition cache_cf.cc:4479
static void dump_time_msec(StoreEntry *entry, const char *name, time_msec_t var)
Definition cache_cf.cc:2956
static const double HoursPerYear
Definition cache_cf.cc:162
static void free_denyinfo(AclDenyInfoList **var)
Definition cache_cf.cc:2483
static void free_UrlHelperTimeout(SquidConfig::UrlHelperTimeout *)
Definition cache_cf.cc:4819
void parseBytesOptionValue(size_t *bptr, const char *units, char const *value)
Parse bytes number from a string.
Definition cache_cf.cc:1383
static const char * peer_type_str(const peer_t type)
Definition cache_cf.cc:2029
static const char *const T_DAY_STR
Definition cache_cf.cc:149
static void dump_uri_whitespace(StoreEntry *entry, const char *name, int var)
Definition cache_cf.cc:3165
static void dump_icap_service_failure_limit(StoreEntry *, const char *, const Adaptation::Icap::Config &)
Definition cache_cf.cc:4224
static void parse_denyinfo(AclDenyInfoList **var)
Definition cache_cf.cc:2477
static void free_string(char **var)
Definition cache_cf.cc:2880
static unsigned short GetService(const char *proto)
Definition cache_cf.cc:2110
static TimeUnit parseTimeLine()
Definition cache_cf.cc:1202
static void parse_CpuAffinityMap(CpuAffinityMap **const cpuAffinityMap)
Definition cache_cf.cc:4068
static void parse_SBufList(SBufList *list)
Definition cache_cf.cc:1435
static void parse_tristate(int *var)
Definition cache_cf.cc:2610
static void parsePortCfg(AnyP::PortCfgPointer *, const char *protocol)
Definition cache_cf.cc:3710
static void dump_kb_int64_t(StoreEntry *entry, const char *name, int64_t var)
Definition cache_cf.cc:3015
static void parse_YesNoNone(YesNoNone *option)
Definition cache_cf.cc:3231
static void dump_time_nanoseconds(StoreEntry *entry, const char *name, const std::chrono::nanoseconds &var)
Definition cache_cf.cc:2978
int config_lineno
Definition cache_cf.cc:271
static void free_sslproxy_cert_sign(sslproxy_cert_sign **cert_sign)
Definition cache_cf.cc:4351
static void parse_delay_pool_count(DelayConfig *cfg)
Definition cache_cf.cc:1761
static void dump_b_int64_t(StoreEntry *entry, const char *name, int64_t var)
Definition cache_cf.cc:3009
static void parse_delay_pool_rates(DelayConfig *cfg)
Definition cache_cf.cc:1773
static void dump_acl_tos(StoreEntry *entry, const char *name, acl_tos *head)
Definition cache_cf.cc:1593
static void parse_acl_b_size_t(AclSizeLimit **head)
Definition cache_cf.cc:1712
static void dump_onoff(StoreEntry *entry, const char *name, int var)
Definition cache_cf.cc:2562
static void parse_uri_whitespace(int *var)
Definition cache_cf.cc:3140
void self_destruct(void)
Definition cache_cf.cc:275
static bool isUnsignedNumeric(const char *str, size_t len)
Definition cache_cf.cc:2094
static void ParseDirective(T &raw, ConfigParser &parser)
Definition cache_cf.cc:663
static peer_t parseNeighborType(const char *s)
Definition cache_cf.cc:3294
static void parse_IpAddress_list(Ip::Address_list **)
Definition cache_cf.cc:3318
static void parse_icap_access_type()
Definition cache_cf.cc:4175
static TimeUnit FromNanoseconds(const std::chrono::nanoseconds &ns, const double parsedValue)
Definition cache_cf.cc:1187
static void parse_acl(Acl::NamedAcls **config)
Definition cache_cf.cc:1478
static void dump_generic_port(StoreEntry *e, const char *n, const AnyP::PortCfgPointer &s)
Definition cache_cf.cc:3800
static void parse_HeaderWithAclList(HeaderWithAclList **header)
Definition cache_cf.cc:4499
static void parsePortSpecification(const AnyP::PortCfgPointer &s, char *token)
Definition cache_cf.cc:3375
static const char * skip_ws(const char *s)
Definition cache_cf.cc:302
static const char * TimeUnitToString()
Definition cache_cf.cc:1109
static std::chrono::seconds ParseUrlRewriteTimeout()
Definition cache_cf.cc:4730
static void parse_client_delay_pool_access(ClientDelayConfig *cfg)
Definition cache_cf.cc:1822
static void free_configuration_includes_quoted_values(bool *recognizeQuotedValues)
Definition cache_cf.cc:4850
static void parse_int64_t(int64_t *var)
Definition cache_cf.cc:2548
static void parse_cachedir(Store::DiskConfig *swap)
Definition cache_cf.cc:2022
static void parse_note(Notes *)
Definition cache_cf.cc:4551
static void dump_ftp_epsv(StoreEntry *entry, const char *name, acl_access *ftp_epsv)
Definition cache_cf.cc:4715
unsigned short GetUdpService(void)
Definition cache_cf.cc:2144
static void parse_sslproxy_cert_adapt(sslproxy_cert_adapt **cert_adapt)
Definition cache_cf.cc:4241
static void free_HeaderWithAclList(HeaderWithAclList **header)
Definition cache_cf.cc:4533
static void dump_acl_b_size_t(StoreEntry *entry, const char *name, AclSizeLimit *head)
Definition cache_cf.cc:1697
static void defaults_if_none(void)
static void parse_acl_tos(acl_tos **head)
Definition cache_cf.cc:1610
static void dump_CpuAffinityMap(StoreEntry *const entry, const char *const name, const CpuAffinityMap *const cpuAffinityMap)
Definition cache_cf.cc:4101
static void configDoConfigure(void)
Definition cache_cf.cc:712
static void dump_YesNoNone(StoreEntry *entry, const char *name, YesNoNone &option)
Definition cache_cf.cc:3239
unsigned short GetTcpService(void)
Definition cache_cf.cc:2134
static int ThePurgeCount
PURGE methods seen by parse()
Definition MethodData.h:32
deny_info representation. Currently a POD.
SBufList acl_list
ACL names in configured order.
AclDenyInfoList * next
representation of a class of Size-limit ACLs
AclSizeLimit * next
ACLList * aclList
list of address-based ACLs.
Definition Address.h:21
Ip::Address addr
Definition Address.h:31
Acl::Address * next
Definition Address.h:28
ACLList * aclList
Definition Address.h:29
int kind
the matched custom access list verb (or zero)
Definition Acl.h:99
void add(Acl::Node *node)
appends the node to the collection and takes control over it
Definition InnerNode.cc:36
size_t lineParse()
Definition InnerNode.cc:44
parsed "acl aclname ..." directives indexed by aclname
Definition Acl.cc:38
void context(const SBuf &aName, const char *configuration)
sets user-specified ACL name and squid.conf context
Definition Acl.cc:220
static void ParseNamedAcl(ConfigParser &, NamedAcls *&)
parses acl directive parts that follow directive name (i.e. "acl")
Definition Acl.cc:229
static Acl::Node * FindByName(const SBuf &)
A configured ACL with a given name or nil.
Definition Acl.cc:159
SBufList treeDump(const char *name, ActionToStringConverter converter) const
Definition Tree.h:60
time_t oldest_service_failure
Definition Config.h:55
void parseService(void)
Definition Config.cc:141
static void ParseServiceSet(void)
Definition Config.cc:247
static void ParseAccess(ConfigParser &parser)
Definition Config.cc:284
void dumpService(StoreEntry *, const char *) const
Definition Config.cc:163
int service_failure_limit
Definition Config.h:54
void freeService(void)
Definition Config.cc:152
static void ParseServiceChain(void)
Definition Config.cc:253
General eCAP configuration.
Definition Config.h:39
SBuf image() const
Definition UriScheme.h:57
std::vector< Auth::SchemesConfig > schemeLists
set of auth_schemes directives
Definition Config.h:32
virtual bool active() const =0
virtual void parse(SchemeConfig *, size_t, char *)
static SchemeConfig * Find(const char *proxy_auth)
static Scheme::Pointer Find(const char *)
Definition Scheme.cc:31
char * name
Definition CachePeer.h:61
cache_peer configuration storage
Definition CachePeers.h:21
void add(CachePeer *p)
stores a being-configured cache_peer
Definition CachePeers.h:27
static const CharacterSet WSP
void parsePoolAccess(ConfigParser &parser)
void dumpPoolCount(StoreEntry *entry, const char *name) const
static void DisableMacros()
Do not allow macros inside quoted strings.
static SBuf CurrentLocation()
void rejectDuplicateDirective()
rejects configuration due to a repeated directive
static char * NextQuotedToken()
static char * NextQuotedOrToEol()
static bool StrictMode
std::unique_ptr< RegexPattern > regex(const char *expectedRegexDescription)
extracts and returns a regex (including any optional flags)
static bool RecognizeQuotedValues
configuration_includes_quoted_values in squid.conf
static char * PeekAtToken()
void closeDirective()
stops parsing the current configuration directive
static bool NextKvPair(char *&key, char *&value)
static bool LastTokenWasQuoted()
static void ParseUShort(unsigned short *var)
Definition cache_cf.cc:3088
CachePeer & cachePeer(const char *peerNameTokenDescription)
extracts a cache_peer name token and returns the corresponding CachePeer
static void ParseBool(bool *var)
Definition cache_cf.cc:3094
static char * NextToken()
static void EnableMacros()
Allow macros inside quoted strings.
static void ParseWordList(wordlist **list)
Definition cache_cf.cc:3116
static void Free(T)
destroys Parse() result
static T Parse(ConfigParser &)
creates a new T instance using the given parser; never returns nil
static void Print(std::ostream &, const T &)
reports the current T instance configuration in squid.conf format
stores cpu_affinity_map configuration
const std::vector< int > & processes() const
returns list of process numbers
const std::vector< int > & cores() const
returns list of cores
CustomLog * next
next _log line (if any); maintained by cache_cf.cc
Definition CustomLog.h:21
manages configurable aspects of a debugs() message
Definition Messages.h:26
uint64_t limit
logging attempts beyond this limit are logged at the DBG_DATA level
Definition Messages.h:56
DebugMessageId id
message identifier or, if the message has not been configured, zero
Definition Messages.h:48
bool limited() const
whether the number of logging attempts have been limited
Definition Messages.h:35
bool levelled() const
whether the default logging level of this message has been altered
Definition Messages.h:32
int level
debugging level (i.e., the second debugs() parameter) or -1
Definition Messages.h:53
a collection of DebugMessage objects (with fast access by message IDs)
Definition Messages.h:68
Storage messages
Definition Messages.h:72
static std::ostream & Extra(std::ostream &)
Definition debug.cc:1316
static int rotateNumber
Definition Stream.h:82
void parsePoolRates()
void parsePoolClass()
void dumpPoolCount(StoreEntry *entry, const char *name) const
void parsePoolAccess(ConfigParser &parser)
void freePoolCount()
void parsePoolCount()
bool parse(const char *def)
Definition Format.cc:66
A collection of headerMangler objects for a given message kind.
void dumpAccess(StoreEntry *entry, const char *optionName) const
report the *_header_access part of the configuration
void setReplacement(const char *name, const char *replacementValue)
updates mangler for the named header with a replacement value
headerMangler * track(const char *name)
returns a mangler for the named header (known or custom)
void dumpReplacement(StoreEntry *entry, const char *optionName) const
report the *_header_replace part of the configuration
ACLList * aclList
when the header field should be added (always if nil)
Http::HdrType fieldId
internal ID for "known" headers or HDR_OTHER
bool quoted
whether fieldValue may contain macros
std::string fieldName
HTTP header field name.
Format::Format * valueFormat
compiled HTTP header field value (no macros)
std::string fieldValue
HTTP header field value, possibly with macros.
unsigned int n_max
Definition ChildConfig.h:48
unsigned int concurrency
Definition ChildConfig.h:72
Allows or blocks HTTP Upgrade protocols (see http_upgrade_request_protocols)
void forEach(const Visitor &) const
iterates over all configured rules, calling the given visitor
const HeaderTableRecord & lookup(const char *buf, const std::size_t len) const
look record type up by name (C-string and length)
Address_list * next
Definition Address.h:389
char * toStr(char *buf, const unsigned int blen, int force=AF_UNSPEC) const
Definition Address.cc:804
void setEmpty()
Fast reset of the stored content to what would be after default constructor.
Definition Address.cc:204
bool GetHostByName(const char *s)
Definition Address.cc:392
void setNoAddr()
Definition Address.cc:312
void setAnyAddr()
NOTE: Does NOT clear the Port stored. Only the Address and Type.
Definition Address.cc:197
static NfMarkConfig Parse(const SBuf &token)
parses a token and returns an object, expects a "mark[/mask]" format
list of cachemgr password authorization definitions. Currently a POD.
ActionPasswordList * next
representation of a neighbor_type_domain configuration directive. A POD
NeighborTypeDomainList * next
Definition Notes.h:114
Note::Pointer parse(ConfigParser &parser)
Parses a notes line and returns a pointer to the parsed Note object.
Definition Notes.cc:210
void clean()
clean the notes list
Definition Notes.h:138
void printAsNoteDirectives(StoreEntry *, const char *directiveName) const
Prints notes using "note" squid.conf directive format, one directive per stored note.
Definition Notes.cc:263
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition Packable.h:61
a representation of a refresh pattern.
struct RefreshPattern::@72 flags
RefreshPattern * next
SBuf buf()
bytes written so far
Definition Stream.h:41
Definition SBuf.h:94
const char * c_str()
Definition SBuf.cc:516
int cmp(const SBuf &S, const size_type n) const
shorthand version for compare()
Definition SBuf.h:279
bool isEmpty() const
Definition SBuf.h:435
SBuf & append(const SBuf &S)
Definition SBuf.cc:185
A combination of PeerOptions and the corresponding Context.
Security::ContextPointer createClientContext(bool setOptions)
generate a security client-context from these configured options
virtual void parse(const char *)
parse a TLS squid.conf option
gid_t effectiveGroupID
struct SquidConfig2::@102 onoff
uid_t effectiveUserID
the representation of the configuration. POD.
Definition SquidConfig.h:79
int cache_miss_revalidate
Helper::ChildConfig redirectChildren
char * errHtmlText
size_t maxRequestBufferSize
char * mimeTablePathname
struct SquidConfig::@99 ssl_client
size_t appendDomainLen
int max_filedescriptors
struct SquidConfig::@82 Log
char * effectiveGroup
int connect_retries
wordlist * store_id
char * foreignIntermediateCertsPath
Helper::ChildConfig storeIdChildren
CustomLog * accesslogs
char * errorDirectory
int memory_cache_first
size_t maxReplyHeaderSize
struct SquidConfig::@83 Program
char * unlinkd
CustomLog * icaplogs
wordlist * redirect
RefreshPattern * Refresh
struct SquidConfig::@77 Timeout
char * appendDomain
Security::ContextPointer * sslContext_
int memory_cache_disk
time_t urlRewrite
char * surrogate_id
Security::FuturePeerContext * defaultPeerContext
struct SquidConfig::@90 onoff
size_t maxRequestHeaderSize
char * chroot_dir
size_t udpMaxHitObjsz
struct SquidConfig::@93 icons
struct SquidConfig::@84 Accel
int64_t maxObjectSize
char * directory
int pipeline_max_prefetch
char * effectiveUser
struct SquidConfig::@88 Store
int httpd_suppress_version_string
void append(char const *, int) override
Appends a c-string to existing packed data.
Definition store.cc:803
static void Dump(const DiskConfig &, StoreEntry &, const char *name)
prints the configuration into the provided StoreEntry
Definition Disks.cc:467
static void Parse(DiskConfig &)
parses a single cache_dir configuration line
Definition Disks.cc:414
static size_type SizeMaxXXX()
Definition SquidString.h:72
void assign(const char *str, int len)
Definition String.cc:79
char const * rawBuf() const
Definition SquidString.h:87
char const * termedBuf() const
Definition SquidString.h:93
size_type size() const
Definition SquidString.h:74
an std::runtime_error with thrower location info
void configure(bool beSet)
enables or disables the option; updating to 'configured' state
Definition YesNoNone.h:53
bool configured() const
Definition YesNoNone.h:67
acl_nfmark * next
Definition QosConfig.h:54
Ip::NfMarkConfig markConfig
Definition QosConfig.h:56
ACLList * aclList
Definition QosConfig.h:55
tos_t tos
Definition QosConfig.h:42
acl_tos * next
Definition QosConfig.h:40
ACLList * aclList
Definition QosConfig.h:41
acl_access * access_list
void finalizeConfig() override
Definition cache_cf.cc:4370
static Ssl::BumpMode lastDeprecatedRule
Definition cache_cf.cc:4360
sslproxy_cert_adapt * next
Definition ProxyCerts.h:58
sslproxy_cert_sign * next
Definition ProxyCerts.h:35
char * key
Definition wordlist.h:59
wordlist * next
Definition wordlist.h:60
A const & max(A const &lhs, A const &rhs)
A const & min(A const &lhs, A const &rhs)
constexpr DebugMessageId DebugMessageIdUpperBound
The maximum used DebugMessage::id plus 1. Increase as you add new IDs.
Definition Messages.h:64
#define Important(id)
Definition Messages.h:93
size_t DebugMessageId
an identifier for messages supporting configuration via cache_log_message
Definition Messages.h:22
#define DBG_PARSE_NOTE(x)
Definition Stream.h:42
#define MYNAME
Definition Stream.h:219
#define DBG_IMPORTANT
Definition Stream.h:38
#define debugs(SECTION, LEVEL, CONTENT)
Definition Stream.h:192
#define DBG_CRITICAL
Definition Stream.h:37
#define URI_WHITESPACE_CHOP
Definition defines.h:127
#define URI_WHITESPACE_STRIP
Definition defines.h:124
#define URI_WHITESPACE_DENY
Definition defines.h:128
#define URI_WHITESPACE_ALLOW
Definition defines.h:125
#define URI_WHITESPACE_ENCODE
Definition defines.h:126
#define BUFSIZ
Definition defines.h:20
#define O_TEXT
Definition defines.h:131
static int port
@ DISABLE_PMTU_ALWAYS
Definition enums.h:226
@ DISABLE_PMTU_OFF
Definition enums.h:225
@ DISABLE_PMTU_TRANSPARENT
Definition enums.h:227
peer_t
Definition enums.h:22
@ PEER_SIBLING
Definition enums.h:24
@ PEER_PARENT
Definition enums.h:25
@ PEER_MULTICAST
Definition enums.h:26
void fatal(const char *message)
Definition fatal.cc:28
void fatalf(const char *fmt,...)
Definition fatal.cc:68
char * ConfigFile
int refresh_nocache_hack
int opt_send_signal
char ThisCache2[RFC2181_MAXHOSTNAMELEN<< 1]
char const * visible_appname_string
const char * null_string
int opt_parse_cfg_only
char ThisCache[RFC2181_MAXHOSTNAMELEN<< 1]
const char * appname_string
int reconfiguring
int KidIdentifier
void aclDestroyAccessList(acl_access **list)
Definition Gadgets.cc:223
void dump_acl_list(StoreEntry *entry, ACLList *head)
Definition cache_cf.cc:1491
void aclDestroyAclList(ACLList **list)
Definition Gadgets.cc:214
void aclParseDenyInfoLine(AclDenyInfoList **head)
Definition Gadgets.cc:88
void dump_acl_access(StoreEntry *entry, const char *name, acl_access *head)
Definition cache_cf.cc:1499
@ ACCESS_DENIED
Definition Acl.h:41
@ ACCESS_ALLOWED
Definition Acl.h:42
void useSquidUntrusted(SSL_CTX *sslContext)
Definition support.cc:1441
std::vector< const char * > BumpModeStr
Definition support.cc:46
bool loadSquidUntrusted(const char *path)
Definition support.cc:1447
BumpMode
Definition support.h:132
void unloadSquidUntrusted()
Definition support.cc:1453
@ bumpTerminate
Definition support.h:132
@ bumpEnd
Definition support.h:132
@ bumpPeek
Definition support.h:132
@ bumpClientFirst
Definition support.h:132
@ bumpNone
Definition support.h:132
@ bumpStare
Definition support.h:132
@ bumpSplice
Definition support.h:132
@ bumpBump
Definition support.h:132
@ bumpServerFirst
Definition support.h:132
const char * sslCertAdaptAlgoritm(int alg)
Definition gadgets.h:219
const char * CertAdaptAlgorithmStr[]
Definition gadgets.cc:285
const char * certSignAlgorithm(int sg)
Definition gadgets.h:182
const char * CertSignAlgorithmStr[]
Definition gadgets.cc:278
@ algSetValidAfter
Definition gadgets.h:207
@ algSetCommonName
Definition gadgets.h:207
@ algSetValidBefore
Definition gadgets.h:207
@ algSignTrusted
Definition gadgets.h:169
@ algSignUntrusted
Definition gadgets.h:169
@ algSignSelf
Definition gadgets.h:169
#define MAX_IPSTRLEN
Length of buffer that needs to be allocated to old a null-terminated IP-string.
Definition forward.h:25
unsigned char tos_t
Definition forward.h:27
#define IPV6_SPECIAL_SPLITSTACK
Definition tools.h:22
void memConfigure(void)
Definition old_api.cc:254
void OBJH(StoreEntry *)
Definition forward.h:44
const char * AllowOrDeny(const Answer &action)
Definition Tree.h:53
void DumpNamedAcls(std::ostream &, const char *directiveName, NamedAcls *)
report the given list of "acl" directives (using squid.conf syntax)
Definition Acl.cc:335
void FreeNamedAcls(NamedAcls **)
delete the given list of "acl" directives
Definition Acl.cc:346
const char * ProtocolType_str[]
@ PROTO_HTTPS
@ PROTO_HTTP
void Init(void)
Initialize Auth subsystem.
Definition AuthReg.cc:31
std::vector< Auth::SchemeConfig * > ConfigVector
Definition forward.h:24
Auth::Config TheConfig
Definition Config.cc:15
void Parse()
interprets (and partially applies) squid.conf or equivalent configuration
Definition cache_cf.cc:609
bool ResolveClientAddressesAsap
whether to do reverse DNS lookups for source IPs of accepted connections
Definition fqdncache.cc:30
AnyP::ProtocolVersion ProtocolVersion()
Protocol version to use in Http::Message structures wrapping FTP messages.
Definition Elements.cc:24
AnyP::ProtocolVersion ProtocolVersion()
const HeaderLookupTable_t HeaderLookupTable
LogConfig TheConfig
Definition Config.cc:15
void RegisterAction(char const *action, char const *desc, OBJH *handler, Protected, Atomic, Format)
std::shared_ptr< SSL_CTX > ContextPointer
Definition Context.h:29
PeerOptions & ProxyOutgoingConfig()
configuration options for DIRECT server access
#define xfree
#define xstrdup
#define xmalloc
CachePeer * findCachePeerByName(const char *const name)
cache_peer with a given name (or nil)
void dump_peer_options(StoreEntry *sentry, CachePeer *p)
const char * neighborTypeStr(const CachePeer *p)
Definition neighbors.cc:84
void peerClearRRStart(void)
Definition neighbors.cc:426
struct servent * xgetservbyname(const char *name, const char *proto)
POSIX getservbyname(3) equivalent.
Definition netdb.h:31
@ toutActFail
Definition redirect.h:16
@ toutActUseConfiguredResponse
Definition redirect.h:16
@ toutActBypass
Definition redirect.h:16
@ toutActRetry
Definition redirect.h:16
void rfc1738_unescape(char *url)
Definition rfc1738.c:146
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf
Definition Stream.h:63
std::list< SBuf > SBufList
Definition forward.h:23
#define LOCAL_ARRAY(type, name, size)
Definition squid.h:62
#define SQUID_UDP_SO_SNDBUF
Definition squid.h:43
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition store.cc:855
void storeConfigure(void)
Definition store.cc:1270
struct squidaio_request_t * next
Definition aiops.cc:53
Definition parse.c:160
int unsigned int
Definition stub_fd.cc:19
SBuf service_name(APP_SHORTNAME)
number
uint64_t time_msec_t
Definition gadgets.h:16
const char * getMyHostname(void)
Definition tools.cc:468
const char * uniqueHostname(void)
Definition tools.cc:548
#define NULL
Definition types.h:145
#define PRId64
Definition types.h:104
const char * xitoa(int num)
Definition util.cc:60
#define APP_FULLNAME
Definition version.h:25
const char * wordlistAdd(wordlist **list, const char *key)
Definition wordlist.cc:25
void wordlistDestroy(wordlist **list)
destroy a wordlist
Definition wordlist.cc:16
void * xrealloc(void *s, size_t sz)
Definition xalloc.cc:126
void * xcalloc(size_t n, size_t sz)
Definition xalloc.cc:71
#define safe_free(x)
Definition xalloc.h:73
#define xisspace(x)
Definition xis.h:15
const char * xstrerr(int error)
Definition xstrerror.cc:83
char * xstrncpy(char *dst, const char *src, size_t n)
Definition xstring.cc:37
bool xstrtoui(const char *s, char **end, unsigned int *value, unsigned int min, unsigned int max)
Definition xstrto.cc:86